diff --git a/src/main/scala/leon/SubtypingPhase.scala b/src/main/scala/leon/SubtypingPhase.scala index 8a63663b4080bde72176297814a27ec44ab4bce8..350c7ddac18d333505d2654275a98f962720e318 100644 --- a/src/main/scala/leon/SubtypingPhase.scala +++ b/src/main/scala/leon/SubtypingPhase.scala @@ -2,6 +2,7 @@ package leon +import purescala.Common._ import purescala.TypeTrees._ import purescala.Trees._ import purescala.Definitions._ @@ -32,10 +33,15 @@ object SubtypingPhase extends LeonPhase[Program, Program] { fd.postcondition = fd.returnType match { case cct@CaseClassType(cd) => { - val subtypingConstraint = CaseClassInstanceOf(cd, ResultVariable()) + fd.postcondition match { - case Some(p) => Some(And(subtypingConstraint, p)) - case None => Some(subtypingConstraint) + case Some((id, p)) => + Some((id, And(CaseClassInstanceOf(cd, Variable(id)), p))) + + case None => + val resId = FreshIdentifier("res").setType(cct) + + Some((resId, CaseClassInstanceOf(cd, Variable(resId)))) } } case _ => fd.postcondition diff --git a/src/main/scala/leon/TypeChecking.scala b/src/main/scala/leon/TypeChecking.scala deleted file mode 100644 index 2733b8781ecbd3abc66fdb6496ee77b55994deb8..0000000000000000000000000000000000000000 --- a/src/main/scala/leon/TypeChecking.scala +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright 2009-2013 EPFL, Lausanne */ - -package leon - -import purescala.Common._ -import purescala.Definitions._ -import purescala.Trees._ -import purescala.TypeTrees._ - -object TypeChecking extends UnitPhase[Program] { - - val name = "Type Checking" - val description = "Type check the AST" - - def apply(ctx: LeonContext, pgm: Program): Unit = { - val allFuns = pgm.definedFunctions - - allFuns.foreach(fd => { - fd.precondition.foreach(typeCheck) - fd.postcondition.foreach(typeCheck) - fd.body.foreach(typeCheck) - }) - } - - private def typeCheck(expr: Expr): Unit = { //expr match { - //quick hack - //searchAndReplaceDFS(e => { - // if(e.getType == Untyped) { - // println("Expression is untyped: " + e) - // } - // None - //})(expr) - - //case l@Let(i, v, b) => { - // if(l.getType == Untyp - // val vr = transform(v) - // v.getType match { - // case ArrayType(_) => { - // val freshIdentifier = FreshIdentifier("t").setType(vr.getType) - // id2id += (i -> freshIdentifier) - // val br = transform(b) - // LetVar(freshIdentifier, vr, br) - // } - // case _ => { - // val br = transform(b) - // Let(i, vr, br) - // } - // } - //} - //case LetVar(id, e, b) => { - // val er = transform(e) - // val br = transform(b) - // LetVar(id, er, br) - //} - //case wh@While(c, e) => { - // val newWh = While(transform(c), transform(e)) - // newWh.invariant = wh.invariant.map(i => transform(i)) - // newWh.setPosInfo(wh) - //} - - //case ite@IfExpr(c, t, e) => { - // val rc = transform(c) - // val rt = transform(t) - // val re = transform(e) - // IfExpr(rc, rt, re).setType(rt.getType) - //} - - //case m @ MatchExpr(scrut, cses) => { - // val scrutRec = transform(scrut) - // val csesRec = cses.map{ - // case SimpleCase(pat, rhs) => SimpleCase(pat, transform(rhs)) - // case GuardedCase(pat, guard, rhs) => GuardedCase(pat, transform(guard), transform(rhs)) - // } - // val tpe = csesRec.head.rhs.getType - // MatchExpr(scrutRec, csesRec).setType(tpe).setPosInfo(m) - //} - //case LetDef(fd, b) => { - // val newFd = if(fd.hasImplementation) { - // val body = fd.body.get - // val args = fd.args - // val newFd = - // if(args.exists(vd => containsArrayType(vd.tpe)) || containsArrayType(fd.returnType)) { - // val newArgs = args.map(vd => { - // val freshId = FreshIdentifier(vd.id.name).setType(transform(vd.tpe)) - // id2id += (vd.id -> freshId) - // val newTpe = transform(vd.tpe) - // VarDecl(freshId, newTpe) - // }) - // val freshFunName = FreshIdentifier(fd.id.name) - // val freshFunDef = new FunDef(freshFunName, transform(fd.returnType), newArgs) - // fd2fd += (fd -> freshFunDef) - // freshFunDef.precondition = fd.precondition.map(transform) - // freshFunDef.postcondition = fd.postcondition.map(transform) - // freshFunDef.addAnnotation(fd.annotations.toSeq:_*) - // freshFunDef - // } else fd - // val newBody = transform(body) - // newFd.body = Some(newBody) - // newFd - // } else fd - // val rb = transform(b) - // LetDef(newFd, rb) - //} - //case FunctionInvocation(fd, args) => { - // val rargs = args.map(transform) - // val rfd = fd2fd.get(fd).getOrElse(fd) - // FunctionInvocation(rfd, rargs) - //} - - //case n @ NAryOperator(args, recons) => recons(args.map(transform)).setType(n.getType) - //case b @ BinaryOperator(a1, a2, recons) => recons(transform(a1), transform(a2)).setType(b.getType) - //case u @ UnaryOperator(a, recons) => recons(transform(a)).setType(u.getType) - - //case v @ Variable(id) => if(id2id.isDefinedAt(id)) Variable(id2id(id)) else v - //case (t: Terminal) => t - //case unhandled => scala.sys.error("Non-terminal case should be handled in ArrayTransformation: " + unhandled) - } - -} diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala index b98224402ed252b9801b11d846f4aa4dea039fd6..727c6ab2b5a311a6b2b9d614c45fb207cc45f587 100644 --- a/src/main/scala/leon/codegen/CodeGeneration.scala +++ b/src/main/scala/leon/codegen/CodeGeneration.scala @@ -68,9 +68,8 @@ object CodeGeneration { } val bodyWithPost = if(funDef.hasPostcondition && env.compileContracts) { - val freshResID = FreshIdentifier("result").setType(funDef.returnType) - val post = purescala.TreeOps.replace(Map(ResultVariable() -> Variable(freshResID)), funDef.postcondition.get) - Let(freshResID, bodyWithPre, IfExpr(post, Variable(freshResID), Error("Postcondition failed")) ) + val Some((id, post)) = funDef.postcondition + Let(id, bodyWithPre, IfExpr(post, Variable(id), Error("Postcondition failed")) ) } else { bodyWithPre } diff --git a/src/main/scala/leon/evaluators/DefaultEvaluator.scala b/src/main/scala/leon/evaluators/DefaultEvaluator.scala index b10f23bef57e1904185c429c35c1092fd1dc22fd..dd55f2b5d65c333b575a54605d685ba0eda596f4 100644 --- a/src/main/scala/leon/evaluators/DefaultEvaluator.scala +++ b/src/main/scala/leon/evaluators/DefaultEvaluator.scala @@ -87,8 +87,10 @@ class DefaultEvaluator(ctx : LeonContext, prog : Program) extends Evaluator(ctx, val callResult = rec(frame, matchToIfThenElse(body)) if(fd.hasPostcondition) { + val (id, post) = fd.postcondition.get + val freshResID = FreshIdentifier("result").setType(fd.returnType) - val postBody = replace(Map(ResultVariable() -> Variable(freshResID)), matchToIfThenElse(fd.postcondition.get)) + val postBody = replace(Map(Variable(id) -> Variable(freshResID)), matchToIfThenElse(post)) rec(frame + ((freshResID -> callResult)), postBody) match { case BooleanLiteral(true) => ; case BooleanLiteral(false) => throw RuntimeError("Postcondition violation for " + fd.id.name + " reached in evaluation.") diff --git a/src/main/scala/leon/plugin/CodeExtraction.scala b/src/main/scala/leon/plugin/CodeExtraction.scala index bd07bf48b594a144b27ab9d48b16e5ba451eacc5..6f9c3101defff497d48fe92493544501f35928f5 100644 --- a/src/main/scala/leon/plugin/CodeExtraction.scala +++ b/src/main/scala/leon/plugin/CodeExtraction.scala @@ -239,11 +239,13 @@ trait CodeExtraction extends Extractors { val (body2, ensuring) = body match { case ExEnsuredExpression(body2, resSym, contract) => - varSubsts(resSym) = (() => ResultVariable().setType(funDef.returnType)) - (body2, toPureScala(contract)) + val resId = FreshIdentifier(resSym.name.toString).setType(funDef.returnType) + varSubsts(resSym) = (() => Variable(resId)) + (body2, toPureScala(contract).map(r => (resId, r))) case ExHoldsExpression(body2) => - (body2, Some(ResultVariable().setType(BooleanType))) + val resId = FreshIdentifier("res").setType(BooleanType) + (body2, Some((resId, Variable(resId)))) case _ => (body, None) @@ -288,7 +290,7 @@ trait CodeExtraction extends Extractors { } } - val finalEnsuring = ensuring.filter{ e => + val finalEnsuring = ensuring.filter{ case (id, e) => if(containsLetDef(e)) { reporter.error(body3.pos, "Function postcondition should not contain nested function definition") false diff --git a/src/main/scala/leon/purescala/Definitions.scala b/src/main/scala/leon/purescala/Definitions.scala index f1f3311becb8249fa2b5180569f3d9c22e9e3099..b62992618575b17cbd0cc6f923d1e44a6939b1d0 100644 --- a/src/main/scala/leon/purescala/Definitions.scala +++ b/src/main/scala/leon/purescala/Definitions.scala @@ -18,7 +18,6 @@ object Definitions { case t : Definition => t.id == this.id case _ => false } - def allIdentifiers : Set[Identifier] } /** A VarDecl declares a new identifier to be of a certain type. */ @@ -58,8 +57,6 @@ object Definitions { def isRecursive(f1: FunDef) = mainObject.isRecursive(f1) def isCatamorphism(f1: FunDef) = mainObject.isCatamorphism(f1) def caseClassDef(name: String) = mainObject.caseClassDef(name) - def allIdentifiers : Set[Identifier] = mainObject.allIdentifiers + id - //def isPure: Boolean = definedFunctions.forall(fd => fd.body.forall(TreeOps.isPure) && fd.precondition.forall(TreeOps.isPure) && fd.postcondition.forall(TreeOps.isPure)) def writeScalaFile(filename: String) { import java.io.FileWriter @@ -92,11 +89,6 @@ object Definitions { def caseClassDef(caseClassName : String) : CaseClassDef = definedClasses.find(ctd => ctd.id.name == caseClassName).getOrElse(scala.sys.error("Asking for non-existent case class def: " + caseClassName)).asInstanceOf[CaseClassDef] - def allIdentifiers : Set[Identifier] = { - (defs map (_.allIdentifiers)).foldLeft(Set[Identifier]())((a, b) => a ++ b) ++ - (invariants map (TreeOps.allIdentifiers(_))).foldLeft(Set[Identifier]())((a, b) => a ++ b) + id - } - lazy val classHierarchyRoots : Seq[ClassTypeDef] = defs.filter(_.isInstanceOf[ClassTypeDef]).map(_.asInstanceOf[ClassTypeDef]).filter(!_.hasParent) lazy val algebraicDataTypes : Map[AbstractClassDef,Seq[CaseClassDef]] = (defs.collect { @@ -120,7 +112,7 @@ object Definitions { val resSet: CallGraph = (for(funDef <- definedFunctions) yield { funDef.precondition.map(treeCatamorphism[CallGraph](convert, combine, compute(funDef)_, _)).getOrElse(Set.empty) ++ funDef.body.map(treeCatamorphism[CallGraph](convert, combine, compute(funDef)_, _)).getOrElse(Set.empty) ++ - funDef.postcondition.map(treeCatamorphism[CallGraph](convert, combine, compute(funDef)_, _)).getOrElse(Set.empty) + funDef.postcondition.map( pc => treeCatamorphism[CallGraph](convert, combine, compute(funDef)_, pc._2)).getOrElse(Set.empty) }).reduceLeft(_ ++ _) var callers: Map[FunDef,Set[FunDef]] = @@ -215,10 +207,6 @@ object Definitions { children = child :: children } - def allIdentifiers : Set[Identifier] = { - fields.map(f => f.id).toSet + id - } - def knownChildren : Seq[ClassTypeDef] = { children } @@ -264,10 +252,6 @@ object Definitions { } def parent = parent_ - def allIdentifiers : Set[Identifier] = { - fields.map(f => f.id).toSet - } - def fieldsIds = fields.map(_.id) def selectorID2Index(id: Identifier) : Int = { @@ -289,50 +273,27 @@ object Definitions { } } - /** "Regular" classes */ - //class ClassDef(val id: Identifier, var parent: Option[AbstractClassDef]) extends ClassTypeDef { - // var fields: VarDecls = Nil - // val isAbstract = false - //} - /** Values */ case class ValDef(varDecl: VarDecl, value: Expr) extends Definition { val id: Identifier = varDecl.id - def allIdentifiers : Set[Identifier] = TreeOps.allIdentifiers(value) + id } /** Functions (= 'methods' of objects) */ - object FunDef { - def unapply(fd: FunDef): Option[(Identifier,TypeTree,VarDecls,Option[Expr],Option[Expr],Option[Expr])] = { - if(fd != null) { - Some((fd.id, fd.returnType, fd.args, fd.body, fd.precondition, fd.postcondition)) - } else { - None - } - } - } class FunDef(val id: Identifier, val returnType: TypeTree, val args: VarDecls) extends Definition with ScalacPositional { var body: Option[Expr] = None def implementation : Option[Expr] = body var precondition: Option[Expr] = None - var postcondition: Option[Expr] = None + var postcondition: Option[(Identifier, Expr)] = None // Metadata kept here after transformations var parent: Option[FunDef] = None var orig: Option[FunDef] = None def hasImplementation : Boolean = body.isDefined - def hasBody = hasImplementation - def hasPrecondition : Boolean = precondition.isDefined - def hasPostcondition : Boolean = postcondition.isDefined - - def allIdentifiers : Set[Identifier] = { - args.map(_.id).toSet ++ - body.map(TreeOps.allIdentifiers(_)).getOrElse(Set[Identifier]()) ++ - precondition.map(TreeOps.allIdentifiers(_)).getOrElse(Set[Identifier]()) ++ - postcondition.map(TreeOps.allIdentifiers(_)).getOrElse(Set[Identifier]()) + id - } - + def hasBody = hasImplementation + def hasPrecondition : Boolean = precondition.isDefined + def hasPostcondition : Boolean = postcondition.isDefined + private var annots: Set[String] = Set.empty[String] def addAnnotation(as: String*) : FunDef = { annots = annots ++ as @@ -342,68 +303,4 @@ object Definitions { def isPrivate : Boolean = annots.contains("private") } - - object Catamorphism { - // If a function is a catamorphism, this deconstructs it into the cases. Eg: - // def size(l : List) : Int = ... - // should return: - // List, - // Seq( - // (Nil(), 0) - // (Cons(x, xs), 1 + size(xs))) - // ...where x and xs are fresh (and could be unused in the expr) - import scala.collection.mutable.{Map=>MutableMap} - type CataRepr = (AbstractClassDef,Seq[(CaseClass,Expr)]) - private val unapplyCache : MutableMap[FunDef,CataRepr] = MutableMap.empty - - def unapply(funDef : FunDef) : Option[CataRepr] = if( - funDef == null || - funDef.args.size != 1 || - funDef.hasPrecondition || - !funDef.hasImplementation || - (funDef.hasPostcondition && functionCallsOf(funDef.postcondition.get) != Set.empty) - ) { - None - } else if(unapplyCache.isDefinedAt(funDef)) { - Some(unapplyCache(funDef)) - } else { - var moreConditions = true - val argVar = funDef.args(0).toVariable - val argVarType = argVar.getType - val body = funDef.body.get - val iteized = matchToIfThenElse(body) - val invocations = functionCallsOf(iteized) - moreConditions = moreConditions && invocations.forall(_ match { - case FunctionInvocation(fd, Seq(CaseClassSelector(_, e, _))) if fd == funDef && e == argVar => true - case _ => false - }) - moreConditions = moreConditions && argVarType.isInstanceOf[AbstractClassType] - var spmList : Seq[(CaseClassDef,Identifier,Seq[Identifier],Expr)] = Seq.empty - moreConditions = moreConditions && (body match { - case SimplePatternMatching(scrut, _, s) if scrut == argVar => spmList = s; true - case _ => false - }) - - val patternSeq : Seq[(CaseClass,Expr)] = if(moreConditions) { - spmList.map(tuple => { - val (ccd, id, ids, ex) = tuple - val ex2 = matchToIfThenElse(ex) - if(!(variablesOf(ex2) -- ids).isEmpty) { - moreConditions = false - } - (CaseClass(ccd, ids.map(Variable(_))), ex2) - }) - } else { - Seq.empty - } - - if(moreConditions) { - val finalResult = (argVarType.asInstanceOf[AbstractClassType].classDef, patternSeq) - unapplyCache(funDef) = finalResult - Some(finalResult) - } else { - None - } - } - } } diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala index 02e0e7c2978d8462a8983fd3091ae73471f9a1ba..2047e175597ef4b8791ece32281441378023c39a 100644 --- a/src/main/scala/leon/purescala/Extractors.scala +++ b/src/main/scala/leon/purescala/Extractors.scala @@ -143,17 +143,17 @@ object Extractors { fd.precondition = Some(as(2)) LetDef(fd, as(1)) })) - case (None, Some(post)) => + case (None, Some((pid, post))) => Some((Seq(b, body, post), (as: Seq[Expr]) => { fd.body = Some(as(0)) - fd.postcondition = Some(as(2)) + fd.postcondition = Some((pid, as(2))) LetDef(fd, as(1)) })) - case (Some(pre), Some(post)) => + case (Some(pre), Some((pid, post))) => Some((Seq(b, body, pre, post), (as: Seq[Expr]) => { fd.body = Some(as(0)) fd.precondition = Some(as(2)) - fd.postcondition = Some(as(3)) + fd.postcondition = Some((pid, as(3))) LetDef(fd, as(1)) })) } @@ -169,15 +169,15 @@ object Extractors { fd.precondition = Some(as(1)) LetDef(fd, as(0)) })) - case (None, Some(post)) => + case (None, Some((pid, post))) => Some((Seq(body, post), (as: Seq[Expr]) => { - fd.postcondition = Some(as(1)) + fd.postcondition = Some((pid, as(1))) LetDef(fd, as(0)) })) - case (Some(pre), Some(post)) => + case (Some(pre), Some((pid, post))) => Some((Seq(body, pre, post), (as: Seq[Expr]) => { fd.precondition = Some(as(1)) - fd.postcondition = Some(as(2)) + fd.postcondition = Some((pid, as(2))) LetDef(fd, as(0)) })) } diff --git a/src/main/scala/leon/purescala/FunctionClosure.scala b/src/main/scala/leon/purescala/FunctionClosure.scala index e4d006e2ec25d07b7b0af8c47af345506772d7f4..5b0b7aaaf6b694eef91648f425f099d75000ef6e 100644 --- a/src/main/scala/leon/purescala/FunctionClosure.scala +++ b/src/main/scala/leon/purescala/FunctionClosure.scala @@ -77,7 +77,7 @@ object FunctionClosure extends TransformationPhase { val newPrecondition = simplifyLets(introduceLets(And((capturedConstraints ++ fd.precondition).toSeq), fd2FreshFd)) newFunDef.precondition = if(newPrecondition == BooleanLiteral(true)) None else Some(newPrecondition) - val freshPostcondition = fd.postcondition.map(post => introduceLets(post, fd2FreshFd)) + val freshPostcondition = fd.postcondition.map{ case (id, post) => (id, introduceLets(post, fd2FreshFd)) } newFunDef.postcondition = freshPostcondition pathConstraints = fd.precondition.getOrElse(BooleanLiteral(true)) :: pathConstraints diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index 147c4635b3e277439c24d1539023bafbf3fc796c..551ea44c0d05e18f1dc004b1df93e4987e0f8746 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -276,7 +276,6 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { sb.append("}") } - case ResultVariable() => sb.append("#res") case Not(expr) => ppUnary(expr, "\u00AC(", ")", lvl) // \neg case e @ Error(desc) => @@ -380,35 +379,36 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { parent.foreach(p => sb.append(" extends " + idToString(p.id))) } - case fd @ FunDef(id, rt, args, body, pre, post) => { + case fd: FunDef => for(a <- fd.annotations) { ind(lvl) sb.append("@" + a + "\n") } - pre.foreach(prec => { + fd.precondition.foreach(prec => { ind(lvl) sb.append("@pre : ") pp(prec, lvl) sb.append("\n") }) - post.foreach(postc => { + fd.postcondition.foreach{ case (id, postc) => { ind(lvl) sb.append("@post: ") + sb.append(idToString(id)+" => ") pp(postc, lvl) sb.append("\n") - }) + }} ind(lvl) sb.append("def ") - sb.append(idToString(id)) + sb.append(idToString(fd.id)) sb.append("(") - val sz = args.size + val sz = fd.args.size var c = 0 - args.foreach(arg => { + fd.args.foreach(arg => { sb.append(arg.id) sb.append(" : ") pp(arg.tpe, lvl) @@ -420,13 +420,15 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { }) sb.append(") : ") - pp(rt, lvl) + pp(fd.returnType, lvl) sb.append(" = ") - if(body.isDefined) - pp(body.get, lvl) - else - sb.append("[unknown function implementation]") - } + fd.body match { + case Some(body) => + pp(body, lvl) + + case None => + sb.append("[unknown function implementation]") + } case _ => sb.append("Defn?") } diff --git a/src/main/scala/leon/purescala/ScalaPrinter.scala b/src/main/scala/leon/purescala/ScalaPrinter.scala index b1d82854d7594bc8c24d8f938bc2f4da4b86d0d2..0c338c4259bbb121ad4b70a6c833fe418767dacc 100644 --- a/src/main/scala/leon/purescala/ScalaPrinter.scala +++ b/src/main/scala/leon/purescala/ScalaPrinter.scala @@ -285,7 +285,6 @@ class ScalaPrinter(sb: StringBuffer = new StringBuffer) extends PrettyPrinter(sb sb.append(")") } - case ResultVariable() => sb.append("res") case Not(expr) => ppUnary(expr, "!(", ")", lvl) // \neg case e @ Error(desc) => { @@ -388,22 +387,17 @@ class ScalaPrinter(sb: StringBuffer = new StringBuffer) extends PrettyPrinter(sb sb.append(")") parent.foreach(p => sb.append(" extends " + p.id)) - case fd @ FunDef(id, rt, args, body, pre, post) => - - //for(a <- fd.annotations) { - // ind(lvl) - // sb.append("@" + a + "\n") - //} + case fd: FunDef => ind(lvl) sb.append("def ") - sb.append(id) + sb.append(fd.id) sb.append("(") - val sz = args.size + val sz = fd.args.size var c = 0 - args.foreach(arg => { + fd.args.foreach(arg => { sb.append(arg.id) sb.append(" : ") pp(arg.tpe, lvl) @@ -415,41 +409,35 @@ class ScalaPrinter(sb: StringBuffer = new StringBuffer) extends PrettyPrinter(sb }) sb.append(") : ") - pp(rt, lvl) - sb.append(" = (") - if(body.isDefined) { - pre match { - case None => pp(body.get, lvl) - case Some(prec) => { - sb.append("{\n") - ind(lvl+1) - sb.append("require(") - pp(prec, lvl+1) - sb.append(")\n") - pp(body.get, lvl) - sb.append("\n") - ind(lvl) - sb.append("}") - } - } - } else - sb.append("[unknown function implementation]") + pp(fd.returnType, lvl) + sb.append(" = {") + + fd.precondition match { + case None => + case Some(prec) => + ind(lvl+1) + sb.append("require(") + pp(prec, lvl+1) + sb.append(");\n") + } - post match { - case None => { - sb.append(")") - } - case Some(postc) => { - val res = Variable(FreshIdentifier("res", true).setType(fd.returnType)) + fd.body match { + case Some(body) => + pp(body, lvl) + case None => + sb.append("???") + } - val newPost = TreeOps.replace(Map(ResultVariable() -> res), postc) + fd.postcondition match { + case None => + sb.append("}") - sb.append(" ensuring(") - pp(res, lvl) - sb.append(" => ") //TODO, not very general solution... - pp(newPost, lvl) - sb.append("))") - } + case Some((id, postc)) => + sb.append("} ensuring(") + pp(Variable(id), lvl) + sb.append(" => ") + pp(postc, lvl) + sb.append(")") } case _ => sb.append("Defn?") diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala index 45a5ba008d66feb18f4f3db797db3080242ca12f..32e377b4ab08d2ef9590fb2b99295d2d29a409c7 100644 --- a/src/main/scala/leon/purescala/TreeOps.scala +++ b/src/main/scala/leon/purescala/TreeOps.scala @@ -433,22 +433,6 @@ object TreeOps { expr) } - def allIdentifiers(expr: Expr) : Set[Identifier] = expr match { - case l @ Let(binder, e, b) => allIdentifiers(e) ++ allIdentifiers(b) + binder - //TODO: Cannot have LetVar nor LetDef here, should not be visible at this point - //case l @ LetVar(binder, e, b) => allIdentifiers(e) ++ allIdentifiers(b) + binder - //case l @ LetDef(fd, b) => allIdentifiers(fd.getBody) ++ allIdentifiers(b) + fd.id - case n @ NAryOperator(args, _) => - (args map (TreeOps.allIdentifiers(_))).foldLeft(Set[Identifier]())((a, b) => a ++ b) - case b @ BinaryOperator(a1,a2,_) => allIdentifiers(a1) ++ allIdentifiers(a2) - case u @ UnaryOperator(a,_) => allIdentifiers(a) - case i @ IfExpr(a1,a2,a3) => allIdentifiers(a1) ++ allIdentifiers(a2) ++ allIdentifiers(a3) - case m @ MatchExpr(scrut, cses) => - (cses map (_.allIdentifiers)).foldLeft(Set[Identifier]())((a, b) => a ++ b) ++ allIdentifiers(scrut) - case Variable(id) => Set(id) - case t: Terminal => Set.empty - } - def allDeBruijnIndices(expr: Expr) : Set[DeBruijnIndex] = { def convert(t: Expr) : Set[DeBruijnIndex] = t match { case i @ DeBruijnIndex(idx) => Set(i) @@ -1456,8 +1440,13 @@ object TreeOps { newFd.body = fd.body.map(b => rec(b, newScope)) newFd.precondition = fd.precondition.map(pre => rec(pre, newScope)) - newFd.postcondition = fd.postcondition.map(post => rec(post, newScope)) + newFd.postcondition = fd.postcondition.map { + case (id, post) => + val nid = genId(id, newScope) + val postScope = newScope.register(id -> nid) + (id, rec(post, postScope)) + } LetDef(newFd, rec(body, newScope)) @@ -1628,13 +1617,6 @@ object TreeOps { case l @ LetDef(fd, bdy) => LetDef(fd2fd(fd), bdy) - case r @ ResultVariable() => - mapType(r.getType).map { newType => - ResultVariable().setType(newType) - } getOrElse { - r - } - case FunctionInvocation(fd, args) => FunctionInvocation(fd2fd(fd), args) diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala index f4f18b1b7f3a6f8b6d55cfffbd5f2f244c3986ca..ad833062293a509ded51159a00af7268aea1aba3 100644 --- a/src/main/scala/leon/purescala/Trees.scala +++ b/src/main/scala/leon/purescala/Trees.scala @@ -145,13 +145,6 @@ object Trees { val theGuard: Option[Expr] def hasGuard = theGuard.isDefined def expressions: Seq[Expr] - - def allIdentifiers : Set[Identifier] = { - pattern.allIdentifiers ++ - TreeOps.allIdentifiers(rhs) ++ - theGuard.map(TreeOps.allIdentifiers(_)).getOrElse(Set[Identifier]()) ++ - (expressions map (TreeOps.allIdentifiers(_))).foldLeft(Set[Identifier]())((a, b) => a ++ b) - } } case class SimpleCase(pattern: Pattern, rhs: Expr) extends MatchCase { @@ -169,11 +162,8 @@ object Trees { private def subBinders = subPatterns.map(_.binders).foldLeft[Set[Identifier]](Set.empty)(_ ++ _) def binders: Set[Identifier] = subBinders ++ (if(binder.isDefined) Set(binder.get) else Set.empty) - - def allIdentifiers : Set[Identifier] = { - ((subPatterns map (_.allIdentifiers)).foldLeft(Set[Identifier]())((a, b) => a ++ b)) ++ binders - } } + case class InstanceOfPattern(binder: Option[Identifier], classTypeDef: ClassTypeDef) extends Pattern { // c: Class val subPatterns = Seq.empty } @@ -389,9 +379,6 @@ object Trees { case class DeBruijnIndex(index: Int) extends Expr with Terminal - // represents the result in post-conditions - case class ResultVariable() extends Expr with Terminal - /* Literals */ sealed abstract class Literal[T] extends Expr with Terminal { val value: T diff --git a/src/main/scala/leon/solvers/z3/FunctionTemplate.scala b/src/main/scala/leon/solvers/z3/FunctionTemplate.scala index 6c5e64b19eeb9df3a063698df21716ce0ab4436e..5a3f2e2f4700dd0f118184377c63fdfa0c3313f0 100644 --- a/src/main/scala/leon/solvers/z3/FunctionTemplate.scala +++ b/src/main/scala/leon/solvers/z3/FunctionTemplate.scala @@ -344,8 +344,8 @@ object FunctionTemplate { // Now the postcondition. funDef.postcondition match { - case Some(post) => - val newPost : Expr = replace(Map(ResultVariable() -> invocation), matchToIfThenElse(post)) + case Some((id, post)) => + val newPost : Expr = replace(Map(Variable(id) -> invocation), matchToIfThenElse(post)) val postHolds : Expr = if(funDef.hasPrecondition) { diff --git a/src/main/scala/leon/synthesis/SimpleSearch.scala b/src/main/scala/leon/synthesis/SimpleSearch.scala index 42546b01abc6328fa3ffb824cfddb1b59f17f741..9c47c9e38ab4eb479e9349551ec555010cca035d 100644 --- a/src/main/scala/leon/synthesis/SimpleSearch.scala +++ b/src/main/scala/leon/synthesis/SimpleSearch.scala @@ -155,19 +155,19 @@ class SimpleSearch(synth: Synthesizer, val map = (p.as.map(Variable(_): Expr) zip freshAs.map(Variable(_): Expr)).toMap - val res = ResultVariable().setType(ret) + val res = Variable(FreshIdentifier("res").setType(ret)) val mapPost: Map[Expr, Expr] = if (p.xs.size > 1) { p.xs.zipWithIndex.map{ case (id, i) => Variable(id) -> TupleSelect(res, i+1) }.toMap } else { - Map(Variable(p.xs.head) -> ResultVariable().setType(ret)) + Map(Variable(p.xs.head) -> res) } val fd = new FunDef(FreshIdentifier("chimp", true), ret, freshAs.map(id => VarDecl(id, id.getType))) fd.precondition = Some(replace(map, p.pc)) - fd.postcondition = Some(replace(map++mapPost, p.phi)) + fd.postcondition = Some((res.id, replace(map++mapPost, p.phi))) fd } diff --git a/src/main/scala/leon/synthesis/Synthesizer.scala b/src/main/scala/leon/synthesis/Synthesizer.scala index 42032b3e61ca2064a0acc2b3250d8fbaf56ca546..3f53f26abb4beffe434dcdd842c74a621f6f7d5d 100644 --- a/src/main/scala/leon/synthesis/Synthesizer.scala +++ b/src/main/scala/leon/synthesis/Synthesizer.scala @@ -122,7 +122,7 @@ class Synthesizer(val context : LeonContext, // Create new fundef for the body val ret = TupleType(problem.xs.map(_.getType)) - val res = ResultVariable().setType(ret) + val res = Variable(FreshIdentifier("res").setType(ret)) val mapPost: Map[Expr, Expr] = problem.xs.zipWithIndex.map{ case (id, i) => @@ -131,7 +131,7 @@ class Synthesizer(val context : LeonContext, val fd = new FunDef(FreshIdentifier("finalTerm", true), ret, problem.as.map(id => VarDecl(id, id.getType))) fd.precondition = Some(And(problem.pc, sol.pre)) - fd.postcondition = Some(replace(mapPost, problem.phi)) + fd.postcondition = Some((res.id, replace(mapPost, problem.phi))) fd.body = Some(sol.term) val newDefs = sol.defs + fd diff --git a/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala b/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala index 2a7b60bd5a4d1e9cf21d60f3fa664337a6e5d101..4b8786987bee1e69f4f3a58f012c66861c2ba6ce 100644 --- a/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala +++ b/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala @@ -103,10 +103,11 @@ case object ADTInduction extends Rule("ADT Induction") with Heuristic { } else { val funPre = substAll(substMap, And(p.pc, Or(globalPre))) val funPost = substAll(substMap, p.phi) + val idPost = FreshIdentifier("res").setType(resType) val outerPre = Or(globalPre) newFun.precondition = Some(funPre) - newFun.postcondition = Some(LetTuple(p.xs.toSeq, ResultVariable().setType(resType), funPost)) + newFun.postcondition = Some((idPost, LetTuple(p.xs.toSeq, Variable(idPost), funPost))) newFun.body = Some(MatchExpr(Variable(inductOn), cases)) diff --git a/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala b/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala index 0437e52e331160bb91e5fa6a371c9062aea8a7f6..db5af8c78876881ce48db86c77312e08c0248b59 100644 --- a/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala +++ b/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala @@ -155,10 +155,11 @@ case object ADTLongInduction extends Rule("ADT Long Induction") with Heuristic { } else { val funPre = substAll(substMap, And(p.pc, Or(globalPre))) val funPost = substAll(substMap, p.phi) + val idPost = FreshIdentifier("res").setType(resType) val outerPre = Or(globalPre) newFun.precondition = Some(funPre) - newFun.postcondition = Some(LetTuple(p.xs.toSeq, ResultVariable().setType(resType), funPost)) + newFun.postcondition = Some((idPost, LetTuple(p.xs.toSeq, Variable(idPost), funPost))) newFun.body = Some(MatchExpr(Variable(inductOn), cases)) diff --git a/src/main/scala/leon/synthesis/heuristics/IntInduction.scala b/src/main/scala/leon/synthesis/heuristics/IntInduction.scala index 7799a01dee767adf61c1d33848ec00b49bd458bc..1be8dd8eee16e74063a10ef2bbcc3e4c02d68cf0 100644 --- a/src/main/scala/leon/synthesis/heuristics/IntInduction.scala +++ b/src/main/scala/leon/synthesis/heuristics/IntInduction.scala @@ -44,8 +44,10 @@ case object IntInduction extends Rule("Int Induction") with Heuristic { val preOut = subst(inductOn -> Variable(origId), preIn) val newFun = new FunDef(FreshIdentifier("rec", true), tpe, Seq(VarDecl(inductOn, inductOn.getType))) + val idPost = FreshIdentifier("res").setType(tpe) + newFun.precondition = Some(preIn) - newFun.postcondition = Some(LetTuple(p.xs.toSeq, ResultVariable().setType(tpe), p.phi)) + newFun.postcondition = Some((idPost, LetTuple(p.xs.toSeq, Variable(idPost), p.phi))) newFun.body = Some( IfExpr(Equals(Variable(inductOn), IntLiteral(0)), diff --git a/src/main/scala/leon/termination/SimpleTerminationChecker.scala b/src/main/scala/leon/termination/SimpleTerminationChecker.scala index 98303cd74948897246a79157ca0f078350544a9a..058474b2635512a73ff43acb9adfc2b93885dea0 100644 --- a/src/main/scala/leon/termination/SimpleTerminationChecker.scala +++ b/src/main/scala/leon/termination/SimpleTerminationChecker.scala @@ -87,7 +87,7 @@ class SimpleTerminationChecker(context : LeonContext, program : Program) extends } getOrElse Set.empty[FunctionInvocation] } - val callsToAnalyze = callsOfInterest(funDef.body) ++ callsOfInterest(funDef.precondition) ++ callsOfInterest(funDef.postcondition) + val callsToAnalyze = callsOfInterest(funDef.body) ++ callsOfInterest(funDef.precondition) ++ callsOfInterest(funDef.postcondition.map(_._2)) assert(!callsToAnalyze.isEmpty) diff --git a/src/main/scala/leon/verification/DefaultTactic.scala b/src/main/scala/leon/verification/DefaultTactic.scala index 94f4526f3ce7ea7b4f0af707f3cb774efc41a5a5..44463f11d8755c7219d5c1b1613e3f797688911b 100644 --- a/src/main/scala/leon/verification/DefaultTactic.scala +++ b/src/main/scala/leon/verification/DefaultTactic.scala @@ -28,25 +28,27 @@ class DefaultTactic(reporter: Reporter) extends Tactic(reporter) { def generatePostconditions(functionDefinition: FunDef) : Seq[VerificationCondition] = { assert(functionDefinition.body.isDefined) val prec = functionDefinition.precondition - val post = functionDefinition.postcondition + val optPost = functionDefinition.postcondition val body = matchToIfThenElse(functionDefinition.body.get) - if(post.isEmpty) { - Seq.empty - } else { - val theExpr = { - val resFresh = FreshIdentifier("result", true).setType(body.getType) - val bodyAndPost = Let(resFresh, body, replace(Map(ResultVariable() -> Variable(resFresh)), matchToIfThenElse(post.get))) - - val withPrec = if(prec.isEmpty) { - bodyAndPost - } else { - Implies(matchToIfThenElse(prec.get), bodyAndPost) - } + optPost match { + case None => + Seq() - withPrec - } - Seq(new VerificationCondition(theExpr, functionDefinition, VCKind.Postcondition, this.asInstanceOf[DefaultTactic])) + case Some((id, post)) => + val theExpr = { + val resFresh = FreshIdentifier("result", true).setType(body.getType) + val bodyAndPost = Let(resFresh, body, replace(Map(Variable(id) -> Variable(resFresh)), matchToIfThenElse(post))) + + val withPrec = if(prec.isEmpty) { + bodyAndPost + } else { + Implies(matchToIfThenElse(prec.get), bodyAndPost) + } + + withPrec + } + Seq(new VerificationCondition(theExpr, functionDefinition, VCKind.Postcondition, this.asInstanceOf[DefaultTactic])) } } diff --git a/src/main/scala/leon/verification/InductionTactic.scala b/src/main/scala/leon/verification/InductionTactic.scala index 26d9de252f9eed3826a8d4db34f7cbe4e0ac1f4d..2138a02cee212522f8e259057e2b1fea3df2c5e2 100644 --- a/src/main/scala/leon/verification/InductionTactic.scala +++ b/src/main/scala/leon/verification/InductionTactic.scala @@ -38,39 +38,41 @@ class InductionTactic(reporter: Reporter) extends DefaultTactic(reporter) { firstAbsClassDef(funDef.args) match { case Some((classDef, arg)) => val prec = funDef.precondition - val post = funDef.postcondition + val optPost = funDef.postcondition val body = matchToIfThenElse(funDef.body.get) val argAsVar = arg.toVariable - if (post.isEmpty) { - Seq.empty - } else { - val children = classDef.knownChildren - val conditionsForEachChild = (for (child <- classDef.knownChildren) yield (child match { - case ccd @ CaseClassDef(id, prnt, vds) => - val selectors = selectorsOfParentType(classDefToClassType(classDef), ccd, argAsVar) - // if no subtrees of parent type, assert property for base case - val resFresh = FreshIdentifier("result", true).setType(body.getType) - val bodyAndPostForArg = Let(resFresh, body, replace(Map(ResultVariable() -> Variable(resFresh)), matchToIfThenElse(post.get))) - val withPrec = if (prec.isEmpty) bodyAndPostForArg else Implies(matchToIfThenElse(prec.get), bodyAndPostForArg) - - val conditionForChild = - if (selectors.size == 0) - withPrec - else { - val inductiveHypothesis = (for (sel <- selectors) yield { - val resFresh = FreshIdentifier("result", true).setType(body.getType) - val bodyAndPost = Let(resFresh, replace(Map(argAsVar -> sel), body), replace(Map(ResultVariable() -> Variable(resFresh), argAsVar -> sel), matchToIfThenElse(post.get))) - val withPrec = if (prec.isEmpty) bodyAndPost else Implies(replace(Map(argAsVar -> sel), matchToIfThenElse(prec.get)), bodyAndPost) + optPost match { + case None => + Seq.empty + case Some((pid, post)) => + val children = classDef.knownChildren + val conditionsForEachChild = (for (child <- classDef.knownChildren) yield (child match { + case ccd @ CaseClassDef(id, prnt, vds) => + val selectors = selectorsOfParentType(classDefToClassType(classDef), ccd, argAsVar) + // if no subtrees of parent type, assert property for base case + val resFresh = FreshIdentifier("result", true).setType(body.getType) + val bodyAndPostForArg = Let(resFresh, body, replace(Map(Variable(pid) -> Variable(resFresh)), matchToIfThenElse(post))) + val withPrec = if (prec.isEmpty) bodyAndPostForArg else Implies(matchToIfThenElse(prec.get), bodyAndPostForArg) + + val conditionForChild = + if (selectors.size == 0) withPrec - }) - Implies(And(inductiveHypothesis), withPrec) - } - new VerificationCondition(Implies(CaseClassInstanceOf(ccd, argAsVar), conditionForChild), funDef, VCKind.Postcondition, this) - case _ => scala.sys.error("Abstract class has non-case class subtype.") - })) - conditionsForEachChild + else { + val inductiveHypothesis = (for (sel <- selectors) yield { + val resFresh = FreshIdentifier("result", true).setType(body.getType) + val bodyAndPost = Let(resFresh, replace(Map(argAsVar -> sel), body), replace(Map(Variable(pid) -> Variable(resFresh), argAsVar -> sel), matchToIfThenElse(post))) + val withPrec = if (prec.isEmpty) bodyAndPost else Implies(replace(Map(argAsVar -> sel), matchToIfThenElse(prec.get)), bodyAndPost) + withPrec + }) + Implies(And(inductiveHypothesis), withPrec) + } + new VerificationCondition(Implies(CaseClassInstanceOf(ccd, argAsVar), conditionForChild), funDef, VCKind.Postcondition, this) + case _ => scala.sys.error("Abstract class has non-case class subtype.") + })) + conditionsForEachChild } + case None => reporter.warning("Induction tactic currently supports exactly one argument of abstract class type") defaultPost diff --git a/src/main/scala/leon/xlang/ArrayTransformation.scala b/src/main/scala/leon/xlang/ArrayTransformation.scala index fb930993103cb6f70cf92b50a10db3999b9eca43..04a75d1037d5aec418d5bbfa7f3b4f184bc50b20 100644 --- a/src/main/scala/leon/xlang/ArrayTransformation.scala +++ b/src/main/scala/leon/xlang/ArrayTransformation.scala @@ -26,7 +26,7 @@ object ArrayTransformation extends TransformationPhase { id2FreshId = Map() fd.precondition = fd.precondition.map(transform) fd.body = fd.body.map(transform) - fd.postcondition = fd.postcondition.map(transform) + fd.postcondition = fd.postcondition.map { case (id, post) => (id, transform(post)) } }) pgm } @@ -119,7 +119,7 @@ object ArrayTransformation extends TransformationPhase { case LetDef(fd, b) => { fd.precondition = fd.precondition.map(transform) fd.body = fd.body.map(transform) - fd.postcondition = fd.postcondition.map(transform) + fd.postcondition = fd.postcondition.map { case (id, post) => (id, transform(post)) } val rb = transform(b) LetDef(fd, rb) } @@ -131,173 +131,4 @@ object ArrayTransformation extends TransformationPhase { case unhandled => scala.sys.error("Non-terminal case should be handled in ArrayTransformation: " + unhandled) } - //val newFuns: Seq[FunDef] = allFuns.map(fd => { - // if(fd.hasImplementation) { - // val args = fd.args - // if(args.exists(vd => containsArrayType(vd.tpe)) || containsArrayType(fd.returnType)) { - // val newArgs = args.map(vd => { - // val freshId = FreshIdentifier(vd.id.name).setType(transform(vd.tpe)) - // id2id += (vd.id -> freshId) - // val newTpe = transform(vd.tpe) - // VarDecl(freshId, newTpe) - // }) - // val freshFunName = FreshIdentifier(fd.id.name) - // val freshFunDef = new FunDef(freshFunName, transform(fd.returnType), newArgs) - // fd2fd += (fd -> freshFunDef) - // freshFunDef.addAnnotation(fd.annotations.toSeq:_*) - // freshFunDef - // } else fd - // } else fd - //}) - - //allFuns.zip(newFuns).foreach{ case (ofd, nfd) => ofd.body.map(body => { - // nfd.precondition = ofd.precondition.map(transform) - // nfd.postcondition = ofd.postcondition.map(transform) - // val newBody = transform(body) - // nfd.body = Some(newBody) - //})} - - //val Program(id, ObjectDef(objId, _, invariants)) = pgm - //val allClasses: Seq[Definition] = pgm.definedClasses - //Program(id, ObjectDef(objId, allClasses ++ newFuns, invariants)) - - - //private def transform(tpe: TypeTree): TypeTree = tpe match { - // case ArrayType(base) => TupleType(Seq(ArrayType(transform(base)), Int32Type)) - // case TupleType(tpes) => TupleType(tpes.map(transform)) - // case t => t - //} - //private def containsArrayType(tpe: TypeTree): Boolean = tpe match { - // case ArrayType(base) => true - // case TupleType(tpes) => tpes.exists(containsArrayType) - // case t => false - //} - - //private var id2id: Map[Identifier, Identifier] = Map() - //private var fd2fd: Map[FunDef, FunDef] = Map() - - //private def transform(expr: Expr): Expr = expr match { - // case fill@ArrayFill(length, default) => { - // var rLength = transform(length) - // val rDefault = transform(default) - // val rFill = ArrayMake(rDefault).setType(fill.getType) - // Tuple(Seq(rFill, rLength)).setType(TupleType(Seq(fill.getType, Int32Type))) - // } - // case sel@ArraySelect(a, i) => { - // val ar = transform(a) - // val ir = transform(i) - // val length = TupleSelect(ar, 2).setType(Int32Type) - // IfExpr( - // And(GreaterEquals(ir, IntLiteral(0)), LessThan(ir, length)), - // ArraySelect(TupleSelect(ar, 1).setType(ArrayType(sel.getType)), ir).setType(sel.getType).setPosInfo(sel), - // Error("Index out of bound").setType(sel.getType).setPosInfo(sel) - // ).setType(sel.getType) - // } - // case up@ArrayUpdate(a, i, v) => { - // val ar = transform(a) - // val ir = transform(i) - // val vr = transform(v) - // val Variable(id) = ar - // val length = TupleSelect(ar, 2).setType(Int32Type) - // val array = TupleSelect(ar, 1).setType(ArrayType(v.getType)) - // IfExpr( - // And(GreaterEquals(i, IntLiteral(0)), LessThan(i, length)), - // Assignment( - // id, - // Tuple(Seq( - // ArrayUpdated(array, ir, vr).setType(array.getType).setPosInfo(up), - // length) - // ).setType(TupleType(Seq(array.getType, Int32Type)))), - // Error("Index out of bound").setType(UnitType).setPosInfo(up) - // ).setType(UnitType) - // } - // case ArrayLength(a) => { - // val ar = transform(a) - // TupleSelect(ar, 2).setType(Int32Type) - // } - // case Let(i, v, b) => { - // val vr = transform(v) - // v.getType match { - // case ArrayType(_) => { - // val freshIdentifier = FreshIdentifier("t").setType(vr.getType) - // id2id += (i -> freshIdentifier) - // val br = transform(b) - // LetVar(freshIdentifier, vr, br) - // } - // case _ => { - // val br = transform(b) - // Let(i, vr, br) - // } - // } - // } - // case LetVar(id, e, b) => { - // val er = transform(e) - // val br = transform(b) - // LetVar(id, er, br) - // } - // case wh@While(c, e) => { - // val newWh = While(transform(c), transform(e)) - // newWh.invariant = wh.invariant.map(i => transform(i)) - // newWh.setPosInfo(wh) - // } - - // case ite@IfExpr(c, t, e) => { - // val rc = transform(c) - // val rt = transform(t) - // val re = transform(e) - // IfExpr(rc, rt, re).setType(rt.getType) - // } - - // case m @ MatchExpr(scrut, cses) => { - // val scrutRec = transform(scrut) - // val csesRec = cses.map{ - // case SimpleCase(pat, rhs) => SimpleCase(pat, transform(rhs)) - // case GuardedCase(pat, guard, rhs) => GuardedCase(pat, transform(guard), transform(rhs)) - // } - // val tpe = csesRec.head.rhs.getType - // MatchExpr(scrutRec, csesRec).setType(tpe).setPosInfo(m) - // } - // case LetDef(fd, b) => { - // val newFd = if(fd.hasImplementation) { - // val body = fd.body.get - // val args = fd.args - // val newFd = - // if(args.exists(vd => containsArrayType(vd.tpe)) || containsArrayType(fd.returnType)) { - // val newArgs = args.map(vd => { - // val freshId = FreshIdentifier(vd.id.name).setType(transform(vd.tpe)) - // id2id += (vd.id -> freshId) - // val newTpe = transform(vd.tpe) - // VarDecl(freshId, newTpe) - // }) - // val freshFunName = FreshIdentifier(fd.id.name) - // val freshFunDef = new FunDef(freshFunName, transform(fd.returnType), newArgs) - // fd2fd += (fd -> freshFunDef) - // freshFunDef.precondition = fd.precondition.map(transform) - // freshFunDef.postcondition = fd.postcondition.map(transform) - // freshFunDef.addAnnotation(fd.annotations.toSeq:_*) - // freshFunDef - // } else fd - // val newBody = transform(body) - // newFd.body = Some(newBody) - // newFd - // } else fd - // val rb = transform(b) - // LetDef(newFd, rb) - // } - // case FunctionInvocation(fd, args) => { - // val rargs = args.map(transform) - // val rfd = fd2fd.get(fd).getOrElse(fd) - // FunctionInvocation(rfd, rargs) - // } - - // case n @ NAryOperator(args, recons) => recons(args.map(transform)).setType(n.getType) - // case b @ BinaryOperator(a1, a2, recons) => recons(transform(a1), transform(a2)).setType(b.getType) - // case u @ UnaryOperator(a, recons) => recons(transform(a)).setType(u.getType) - - // case v @ Variable(id) => if(id2id.isDefinedAt(id)) Variable(id2id(id)) else v - // case (t: Terminal) => t - // case unhandled => scala.sys.error("Non-terminal case should be handled in ArrayTransformation: " + unhandled) - - //} - } diff --git a/src/main/scala/leon/xlang/EpsilonElimination.scala b/src/main/scala/leon/xlang/EpsilonElimination.scala index 7a9d3245f59650d53e8b42fe75146e66f2b11198..5e543505ceabcb52fe13b0e4e9efcc44f47d61f2 100644 --- a/src/main/scala/leon/xlang/EpsilonElimination.scala +++ b/src/main/scala/leon/xlang/EpsilonElimination.scala @@ -25,9 +25,9 @@ object EpsilonElimination extends TransformationPhase { val freshName = FreshIdentifier("epsilon") val newFunDef = new FunDef(freshName, eps.getType, Seq()) val epsilonVar = EpsilonVariable(eps.posIntInfo) - val resultVar = ResultVariable().setType(eps.getType) - val postcondition = replace(Map(epsilonVar -> resultVar), pred) - newFunDef.postcondition = Some(postcondition) + val resId = FreshIdentifier("res").setType(eps.getType) + val postcondition = replace(Map(epsilonVar -> Variable(resId)), pred) + newFunDef.postcondition = Some((resId, postcondition)) Some(LetDef(newFunDef, FunctionInvocation(newFunDef, Seq()))) } case _ => None diff --git a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala index a9054aea47ada170e721a268c6b0e7bc5ae0aacd..89a830056f830ac317c088a910c214f32ab29b9a 100644 --- a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala +++ b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala @@ -171,7 +171,7 @@ object ImperativeCodeElimination extends LeonPhase[Program, (Program, Set[FunDef condScope(IfExpr(whileFunCond, whileFunRecursiveCall, whileFunBaseCase).setType(whileFunReturnType))) whileFunDef.body = Some(whileFunBody) - val resVar = ResultVariable().setType(whileFunReturnType) + val resVar = Variable(FreshIdentifier("res").setType(whileFunReturnType)) val whileFunVars2ResultVars: Map[Expr, Expr] = if(whileFunVars.size == 1) Map(whileFunVars.head.toVariable -> resVar) @@ -188,10 +188,10 @@ object ImperativeCodeElimination extends LeonPhase[Program, (Program, Set[FunDef val invariantPostcondition: Option[Expr] = wh.invariant.map(expr => replace(modifiedVars2ResultVars, expr)) whileFunDef.precondition = invariantPrecondition whileFunDef.postcondition = trivialPostcondition.map(expr => - And(expr, invariantPostcondition match { + (resVar.id, And(expr, invariantPostcondition match { case Some(e) => e case None => BooleanLiteral(true) - })) + }))) val finalVars = modifiedVars.map(id => FreshIdentifier(id.name).setType(id.getType)) val finalScope = ((body: Expr) => {