From 949856a9662952dff35ce9ab606f9126c9402d97 Mon Sep 17 00:00:00 2001 From: Utkarsh Upadhyay <musically.ut@gmail.com> Date: Fri, 9 Jul 2010 17:59:43 +0000 Subject: [PATCH] Partial evaluation of catamorphisms (will be inducted in elsewhere in the code). --- src/orderedsets/getAlpha.scala | 141 +++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 src/orderedsets/getAlpha.scala diff --git a/src/orderedsets/getAlpha.scala b/src/orderedsets/getAlpha.scala new file mode 100644 index 000000000..91f81970c --- /dev/null +++ b/src/orderedsets/getAlpha.scala @@ -0,0 +1,141 @@ +package orderedsets + +import purescala._ +import Trees._ +import Common._ +import TypeTrees._ +import Definitions._ +import scala.collection.mutable.{Set => MutableSet} + +object getAlpha { + + var program: Program = null + def setProgram(p: Program) = program = p + + def searchAndApply(subst: Expr => Option[Expr], recursive: Boolean = true)(expr: Expr) = { + def rec(ex: Expr, skip: Expr = null): Expr = (if(ex == skip) None else subst(ex)) match { + case Some(newExpr) => { + if(newExpr.getType == NoType) { + Settings.reporter.warning("REPLACING IN EXPRESSION WITH AN UNTYPED TREE ! " + ex + " --to--> " + newExpr) + } + if(ex == newExpr) + if(recursive) rec(ex, ex) else ex + else + if(recursive) rec(newExpr) else newExpr + } + case None => ex match { + case l @ Let(i,e,b) => { + val re = rec(e) + val rb = rec(b) + if(re != e || rb != b) + Let(i, re, rb).setType(l.getType) + else + l + } + case f @ FunctionInvocation(fd, args) => { + var change = false + val rargs = args.map(a => { + val ra = rec(a) + if(ra != a) { + change = true + ra + } else { + a + } + }) + if(change) + FunctionInvocation(fd, rargs).setType(f.getType) + else + f + } + case i @ IfExpr(t1,t2,t3) => IfExpr(rec(t1),rec(t2),rec(t3)).setType(i.getType) + case m @ MatchExpr(scrut,cses) => MatchExpr(rec(scrut), cses.map(inCase(_))).setType(m.getType) + case And(exs) => And(exs.map(rec(_))) + case Or(exs) => Or(exs.map(rec(_))) + case Not(e) => Not(rec(e)) + case u @ UnaryOperator(t,recons) => { + val r = rec(t) + if(r != t) + recons(r).setType(u.getType) + else + u + } + case b @ BinaryOperator(t1,t2,recons) => { + val r1 = rec(t1) + val r2 = rec(t2) + if(r1 != t1 || r2 != t2) + recons(r1,r2).setType(b.getType) + else + b + } + case c @ CaseClass(cd, args) => { + CaseClass(cd, args.map(rec(_))).setType(c.getType) + } + case c @ CaseClassSelector(cc, sel) => { + val rc = rec(cc) + if(rc != cc) + CaseClassSelector(rc, sel).setType(c.getType) + else + c + } + case _ => ex + } + } + + def inCase(cse: MatchCase) : MatchCase = cse match { + case SimpleCase(pat, rhs) => SimpleCase(pat, rec(rhs)) + case GuardedCase(pat, guard, rhs) => GuardedCase(pat, rec(guard), rec(rhs)) + } + + rec(expr) + } + + def asCatamorphism(f : FunDef) : Option[Seq[(CaseClassDef,Identifier,Seq[Identifier],Expr)]] = { + def recCallsOnMatchedVars(l: (CaseClassDef,Identifier,Seq[Identifier],Expr)) = { + var varSet = MutableSet.empty[Identifier] + searchAndApply({ case FunctionInvocation(_, Seq(Variable(id))) => varSet += id; None; case _ => None})(l._4) + varSet.subsetOf(l._3.toSet) + } + + val c = this.program.callees(f) + if(f.hasImplementation && f.args.size == 1 && c.size == 1 && c.head == f) f.body.get match { + case SimplePatternMatching(scrut, _, lstMatches) + if (scrut == f.args.head.toVariable) && lstMatches.forall(recCallsOnMatchedVars) => Some(lstMatches) + case _ => None + } else { + None + } + } + + def isAlpha(varMap: Variable => Expr)(t: Expr): Option[Expr] = t match { + case FunctionInvocation(fd, Seq(v@ Variable(_))) => asCatamorphism(fd) match { + case None => None + case Some(lstMatch) => varMap(v) match { + case CaseClass(cd, args) => { + val (_, _, ids, rhs) = lstMatch.find( _._1 == cd).get + val repMap = Map( ids.map(id => Variable(id):Expr).zip(args):_* ) + Some(searchAndApply(repMap.get)(rhs)) + } + case u @ Variable(_) => { + val c = Variable(FreshIdentifier("Coll", true)).setType(t.getType) + // TODO: Keep track of these variables for M1(t, c) + Some(c) + } + case _ => error("Bad substitution") + } + case _ => None + } + case _ => None + } + + def apply(t: Expr, varMap: Variable => Expr): Expr = { + searchAndApply(isAlpha(varMap))(t) + } + +// def solve(e : Expr): Option[Boolean] = { +// searchAndApply(isAlpha(x => x))(e) +// None +// } +} + + -- GitLab