diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala index 8b72eb86c5706c7870acfb44a643ee74b86a1500..9e4939dd47ee7498a605c6f746f9862568197cb9 100644 --- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala +++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala @@ -296,10 +296,10 @@ trait CodeExtraction extends ASTExtractors { val tparams = extractTypeParams(tps.map(_.tpe)) - val dctx = DefContext(tparams.toMap) + val newDctx = DefContext(dctx.tparams ++ tparams.toMap) val newParams = params.map{ vd => - val ptpe = toPureScalaType(vd.tpt.tpe)(dctx) + val ptpe = toPureScalaType(vd.tpt.tpe)(newDctx) val newID = FreshIdentifier(vd.symbol.name.toString).setType(ptpe).setPos(vd.pos) owners += (newID -> None) varSubsts += vd.symbol -> (() => Variable(newID)) @@ -308,7 +308,7 @@ trait CodeExtraction extends ASTExtractors { val tparamsDef = tparams.map(t => TypeParameterDef(t._2)) - new FunDef(FreshIdentifier(sym.name.toString), tparamsDef, toPureScalaType(ret)(dctx), newParams) + new FunDef(FreshIdentifier(sym.name.toString), tparamsDef, toPureScalaType(ret)(newDctx), newParams) } private def extractFunDef(funDef: FunDef, body: Tree)(implicit dctx: DefContext): FunDef = { @@ -556,9 +556,6 @@ trait CodeExtraction extends ASTExtractors { rest = None Let(newID, valTree, restTree) - /** - * XLang Extractors - */ case ExFunctionDef(symbol, tparams, params, ret, b) => val funDef = extractFunSig(symbol, tparams, params, ret) @@ -566,7 +563,11 @@ trait CodeExtraction extends ASTExtractors { val oldMutableVarSubst = mutableVarSubsts.toMap //take an immutable snapshot of the map val oldCurrentFunDef = currentFunDef mutableVarSubsts.clear //reseting the visible mutable vars, we do not handle mutable variable closure in nested functions - val funDefWithBody = extractFunDef(funDef, b) + + val tparamsMap = (tparams zip funDef.tparams.map(_.tp)).toMap + val newDctx = DefContext(dctx.tparams ++ tparamsMap) + + val funDefWithBody = extractFunDef(funDef, b)(newDctx) mutableVarSubsts ++= oldMutableVarSubst currentFunDef = oldCurrentFunDef val restTree = rest match { @@ -577,6 +578,10 @@ trait CodeExtraction extends ASTExtractors { rest = None LetDef(funDefWithBody, restTree) + /** + * XLang Extractors + */ + case ExVarDef(vs, tpt, bdy) => { val binderTpe = extractType(tpt.tpe) val newID = FreshIdentifier(vs.name.toString).setType(binderTpe) diff --git a/src/main/scala/leon/purescala/Common.scala b/src/main/scala/leon/purescala/Common.scala index e8838bee75a1ef7f0474cdc3c83221f8f5483b43..89fc30674d9155d5949e0c3714edce32e52c2c50 100644 --- a/src/main/scala/leon/purescala/Common.scala +++ b/src/main/scala/leon/purescala/Common.scala @@ -50,7 +50,7 @@ object Common { def markAsLetBinder : Identifier = { _islb = true; this } def isLetBinder : Boolean = _islb - def freshen: Identifier = FreshIdentifier(name, alwaysShowUniqueID).setType(getType) + def freshen: Identifier = FreshIdentifier(name, alwaysShowUniqueID).copiedFrom(this) } private object UniqueCounter { diff --git a/src/main/scala/leon/purescala/Definitions.scala b/src/main/scala/leon/purescala/Definitions.scala index a02055b7457556ccab7afd560481e9156cb0e910..832c514ab423726968479a9ec0cf774f264dc9d3 100644 --- a/src/main/scala/leon/purescala/Definitions.scala +++ b/src/main/scala/leon/purescala/Definitions.scala @@ -22,11 +22,10 @@ object Definitions { } /** A VarDecl declares a new identifier to be of a certain type. */ - case class VarDecl(id: Identifier, tpe: TypeTree) extends Definition with Typed { + case class VarDecl(id: Identifier, tpe: TypeTree) extends Definition with FixedType { self: Serializable => - override def getType = tpe - override def setType(tt: TypeTree) = scala.sys.error("Can't set type of VarDecl.") + val fixedType = tpe override def hashCode : Int = id.hashCode override def equals(that : Any) : Boolean = that match { @@ -316,7 +315,7 @@ object Definitions { } private lazy val typesMap = { - (fd.tparams zip tps).toMap + (fd.tparams zip tps).toMap.filter(tt => tt._1 != tt._2) } def translated(t: TypeTree): TypeTree = instantiateType(t, typesMap) @@ -324,7 +323,7 @@ object Definitions { def translated(e: Expr): Expr = instantiateType(e, typesMap, argsMap) lazy val (args: Seq[VarDecl], argsMap: Map[Identifier, Identifier]) = { - if (tps.isEmpty) { + if (typesMap.isEmpty) { (fd.args, Map()) } else { val newArgs = fd.args.map { @@ -365,7 +364,7 @@ object Definitions { } def postcondition = fd.postcondition.map { - case (id, post) if tps.nonEmpty => + case (id, post) if typesMap.nonEmpty => postCache.getOrElse((id, post), { val nId = FreshIdentifier(id.name).setType(translated(id.getType)).copiedFrom(id) val res = nId -> instantiateType(post, typesMap, argsMap + (id -> nId)) diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index 63d302ad2dad607089fceaf2ae106aa9d099e404..a5962a428b3497730f6c475d12e83d9b0efaf474 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -14,7 +14,7 @@ import java.lang.StringBuffer /** This pretty-printer uses Unicode for some operators, to make sure we * distinguish PureScala from "real" Scala (and also because it's cute). */ -class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { +class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffer) { override def toString = sb.toString def append(str: String) { @@ -57,20 +57,16 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { sb.append(post) } - def idToString(id: Identifier): String = { - if (opts.printUniqueIds) { - id.uniqueName - } else { - id.toString - } - } - def pp(tree: Tree, parent: Option[Tree])(implicit lvl: Int): Unit = { implicit val p = Some(tree) tree match { case id: Identifier => - sb.append(idToString(id)) + if (opts.printUniqueIds) { + sb.append(id.uniqueName) + } else { + sb.append(id.toString) + } case Variable(id) => //sb.append("(") @@ -80,7 +76,8 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { //sb.append(")") case LetTuple(bs,d,e) => - sb.append("(let (" + bs.map(idToString _).mkString(",") + " := "); + sb.append("(let ") + ppNary(bs, "(", ",", " :="); pp(d, p) sb.append(") in") nl(lvl+1) @@ -88,7 +85,9 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { sb.append(")") case Let(b,d,e) => - sb.append("(let (" + idToString(b) + " := "); + sb.append("(let (") + pp(b, p) + sb.append(" := "); pp(d, p) sb.append(") in") nl(lvl+1) @@ -124,7 +123,9 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { sb.append("._" + i) case c@Choose(vars, pred) => - sb.append("choose("+vars.map(idToString _).mkString(", ")+" => ") + sb.append("choose(") + ppNary(vars, "", ", ", "") + sb.append(" => ") pp(pred, p) sb.append(")") @@ -144,10 +145,11 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { case CaseClassSelector(_, cc, id) => pp(cc, p) - sb.append("." + idToString(id)) + sb.append(".") + pp(id, p) case FunctionInvocation(tfd, args) => - sb.append(idToString(tfd.id)) + pp(tfd.id, p) if (tfd.tps.nonEmpty) { ppNary(tfd.tps, "[", ",", "]") @@ -307,7 +309,7 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { sb.append(")") case WildcardPattern(None) => sb.append("_") - case WildcardPattern(Some(id)) => sb.append(idToString(id)) + case WildcardPattern(Some(id)) => pp(id, p) case InstanceOfPattern(bndr, cct) => bndr.foreach(b => sb.append(b + " : ")) pp(cct, p) @@ -325,6 +327,7 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { // Types case Untyped => sb.append("???") + case BottomType => sb.append("Nothing") case UnitType => sb.append("Unit") case Int32Type => sb.append("Int") case BooleanType => sb.append("Boolean") @@ -357,7 +360,7 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { pp(tt, p) case c: ClassType => - sb.append(idToString(c.classDef.id)) + pp(c.classDef.id, p) if (c.tps.nonEmpty) { ppNary(c.tps, "[", ",", "]") } @@ -367,7 +370,7 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { case Program(id, mainObj) => assert(lvl == 0) sb.append("package ") - sb.append(idToString(id)) + pp(id, p) sb.append(" {\n") pp(mainObj, p)(lvl+1) sb.append("}\n") @@ -375,7 +378,7 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { case ModuleDef(id, defs, invs) => nl sb.append("object ") - sb.append(idToString(id)) + pp(id, p) sb.append(" {") var c = 0 @@ -395,8 +398,11 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { case AbstractClassDef(id, tparams, parent) => nl sb.append("sealed abstract class ") - sb.append(idToString(id)) - parent.foreach(p => sb.append(" extends " + idToString(p.id))) + pp(id, p) + parent.foreach{ par => + sb.append(" extends ") + pp(par.id, p) + } case ccd @ CaseClassDef(id, tparams, parent, isObj) => nl @@ -406,7 +412,7 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { sb.append("case class ") } - sb.append(idToString(id)) + pp(id, p) if (tparams.nonEmpty) { ppNary(tparams, "[", ", ", "]") @@ -416,7 +422,10 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { ppNary(ccd.fields, "(", ", ", ")") } - parent.foreach(p => sb.append(" extends " + idToString(p.id))) + parent.foreach{ par => + sb.append(" extends ") + pp(par.id, p) + } case fd: FunDef => for(a <- fd.annotations) { @@ -434,14 +443,15 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { fd.postcondition.foreach{ case (id, postc) => { ind sb.append("@post: ") - sb.append(idToString(id)+" => ") + pp(id, p) + sb.append(" => ") pp(postc, p)(lvl) sb.append("\n") }} ind sb.append("def ") - sb.append(idToString(fd.id)) + pp(fd.id, p) sb.append("(") val sz = fd.args.size @@ -473,7 +483,7 @@ class PrettyPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) { pp(tp, p) case TypeParameter(id) => - pp(id, p) + sb.append(id.uniqueName) case _ => sb.append("Tree? (" + tree.getClass + ")") } @@ -498,7 +508,15 @@ trait PrettyPrintable { } class EquivalencePrettyPrinter(opts: PrinterOptions) extends PrettyPrinter(opts) { - override def idToString(id: Identifier) = id.name + override def pp(tree: Tree, parent: Option[Tree])(implicit lvl: Int): Unit = { + tree match { + case id: Identifier => + sb.append(id.name) + + case _ => + super.pp(tree, parent) + } + } } abstract class PrettyPrinterFactory { diff --git a/src/main/scala/leon/purescala/ScalaPrinter.scala b/src/main/scala/leon/purescala/ScalaPrinter.scala index 3bbfc02603a94dd60e4cd6d8ae1faef17dbc5e47..843e0905bb99472eaca61192cf281d4986cdf890 100644 --- a/src/main/scala/leon/purescala/ScalaPrinter.scala +++ b/src/main/scala/leon/purescala/ScalaPrinter.scala @@ -53,12 +53,15 @@ class ScalaPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) ex var printPos = opts.printPositions tree match { - case Variable(id) => sb.append(idToString(id)) + case Variable(id) => + pp(id, p) + case LetTuple(ids,d,e) => optBraces { implicit lvl => sb.append("val (" ) for (((id, tpe), i) <- ids.map(id => (id, id.getType)).zipWithIndex) { - sb.append(idToString(id)+": ") + pp(id, p) + sb.append(": ") pp(tpe, p) if (i != ids.size-1) { sb.append(", ") @@ -111,8 +114,13 @@ class ScalaPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) ex pp(t, p) sb.append("._" + i) - case FunctionInvocation(fd, args) => - sb.append(idToString(fd.id)) + case FunctionInvocation(tfd, args) => + pp(tfd.id, p) + + if (tfd.tps.nonEmpty) { + ppNary(tfd.tps, "[", ", ", "]") + } + ppNary(args, "(", ", ", ")") case Plus(l,r) => optParentheses { ppBinary(l, r, " + ") } @@ -226,7 +234,8 @@ class ScalaPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) ex optParentheses { sb.append("choose { (") for (((id, tpe), i) <- ids.map(id => (id, id.getType)).zipWithIndex) { - sb.append(idToString(id)+": ") + pp(id, p) + sb.append(": ") pp(tpe, p) if (i != ids.size-1) { sb.append(", ") @@ -273,7 +282,7 @@ class ScalaPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) ex case ModuleDef(id, defs, invs) => sb.append("object ") - sb.append(idToString(id)) + pp(id, p) sb.append(" {\n") var c = 0 @@ -294,13 +303,16 @@ class ScalaPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) ex case AbstractClassDef(id, tparams, parent) => sb.append("sealed abstract class ") - sb.append(idToString(id)) + pp(id, p) if (tparams.nonEmpty) { ppNary(tparams, "[", ",", "]") } - parent.foreach(p => sb.append(" extends " + idToString(p.id))) + parent.foreach{ par => + sb.append(" extends ") + pp(par.id, p) + } case ccd @ CaseClassDef(id, tparams, parent, isObj) => if (isObj) { @@ -309,7 +321,7 @@ class ScalaPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) ex sb.append("case class ") } - sb.append(idToString(id)) + pp(id, p) if (tparams.nonEmpty) { ppNary(tparams, "[", ", ", "]") @@ -319,7 +331,10 @@ class ScalaPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) ex ppNary(ccd.fields, "(", ", ", ")") } - parent.foreach(p => sb.append(" extends " + idToString(p.id))) + parent.foreach{ par => + sb.append(" extends ") + pp(par.id, p) + } case vd: VarDecl => pp(vd.id, p) diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala index 59d0ba02c27e326c5993f2e9ad8de7105cf548da..0bd6546bda2ff4f2e47be0f1285aa37c0cb32c9c 100644 --- a/src/main/scala/leon/purescala/TreeOps.scala +++ b/src/main/scala/leon/purescala/TreeOps.scala @@ -292,6 +292,7 @@ object TreeOps { e match { case Variable(i) => subvs + i + case LetDef(fd,_) => subvs -- fd.args.map(_.id) -- fd.postcondition.map(_._1) case Let(i,_,_) => subvs - i case Choose(is,_) => subvs -- is case MatchExpr(_, cses) => subvs -- (cses.map(_.pattern.binders).foldLeft(Set[Identifier]())((a, b) => a ++ b)) diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala index 9344224129106a0b849a5b0834e60182ec07b2d2..a9e7904f3591e60a287b63d54a149f3af65665c4 100644 --- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala +++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala @@ -454,6 +454,7 @@ trait AbstractZ3Solver } protected[leon] def toZ3Formula(expr: Expr, initialMap: Map[Identifier,Z3AST] = Map.empty) : Option[Z3AST] = { + class CantTranslateException extends Exception val varsInformula: Set[Identifier] = variablesOf(expr)