diff --git a/build.sbt b/build.sbt index 4de988e5dc18eb4aa5c9dbf6a9c8e7f6178f1ef9..359c39a0bcd372b0d337eb80c11760c95a792b6f 100644 --- a/build.sbt +++ b/build.sbt @@ -4,17 +4,15 @@ version := "2.0" organization := "ch.epfl.lara" -scalaVersion := "2.9.2" +scalaVersion := "2.10.2" scalacOptions += "-deprecation" scalacOptions += "-unchecked" -javacOptions += "-Xlint:unchecked" - -libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.9.2" +scalacOptions += "-feature" -libraryDependencies += "org.scalatest" %% "scalatest" % "1.8" % "test" +javacOptions += "-Xlint:unchecked" if(System.getProperty("sun.arch.data.model") == "64") { unmanagedBase <<= baseDirectory { base => base / "unmanaged" / "64" } @@ -24,7 +22,11 @@ if(System.getProperty("sun.arch.data.model") == "64") { resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/" -libraryDependencies += "com.typesafe.akka" % "akka-actor" % "2.0.4" +libraryDependencies ++= Seq( + "org.scala-lang" % "scala-compiler" % "2.10.2", + "org.scalatest" %% "scalatest" % "1.9.1" excludeAll(ExclusionRule(organization="org.scala-lang")), + "com.typesafe.akka" %% "akka-actor" % "2.1.4" +) fork in run := true diff --git a/library/build.sbt b/library/build.sbt index 6d2b7989698b6b07736a2a0ba5c2189e5b73e36c..0c4c88e13c3096c5e4b9976ab021083f8569aa38 100644 --- a/library/build.sbt +++ b/library/build.sbt @@ -4,10 +4,12 @@ version := "2.0" organization := "ch.epfl.lara" -scalaVersion := "2.9.2" +scalaVersion := "2.10.2" scalacOptions += "-deprecation" scalacOptions += "-unchecked" -libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.9.2" +scalacOptions += "-feature" + +libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.10.2" diff --git a/library/src/main/scala/leon/Annotations.scala b/library/src/main/scala/leon/Annotations.scala index a441066401489312eefcb1261da1722a9184f561..aac4cf423a28fd79d9df4a95ef094c83d765b136 100644 --- a/library/src/main/scala/leon/Annotations.scala +++ b/library/src/main/scala/leon/Annotations.scala @@ -2,6 +2,8 @@ package leon +import scala.annotation.StaticAnnotation + object Annotations { class induct extends StaticAnnotation class axiomatize extends StaticAnnotation diff --git a/library/src/main/scala/leon/Utils.scala b/library/src/main/scala/leon/Utils.scala index ab3e84eb52acb45abc724f9935f0268142f1fc8f..d34bcd0e9c36c572fa9b4948e71a7b7b09185b7e 100644 --- a/library/src/main/scala/leon/Utils.scala +++ b/library/src/main/scala/leon/Utils.scala @@ -2,6 +2,8 @@ package leon +import scala.language.implicitConversions + object Utils { sealed class IsValid(val property : Boolean) { def holds : Boolean = { diff --git a/project/Build.scala b/project/Build.scala index eff96902f72a6c297c0760677bd9832dffdd78d7..02a430d7676d6eefb5da891ef602f213b77de7b2 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -43,7 +43,7 @@ object Leon extends Build { val ldLibPath = if (is64) ldLibraryDir64.absolutePath else ldLibraryDir32.absolutePath - val leonLibPath = depsPaths.find(_.endsWith("/library/target/scala-2.9.2/classes")) match { + val leonLibPath = depsPaths.find(_.endsWith("/library/target/scala-2.10/classes")) match { case None => throw new Exception("Couldn't find leon-library in the classpath.") case Some(p) => p } diff --git a/src/main/scala/leon/Main.scala b/src/main/scala/leon/Main.scala index 9055d9bee9ce9d42bc81efe872b427db445991e2..88c072dcf52c8c7a024b84bac6bf064374c4e6fd 100644 --- a/src/main/scala/leon/Main.scala +++ b/src/main/scala/leon/Main.scala @@ -78,7 +78,7 @@ object Main { val leonOpt: LeonOption = opt.substring(2, opt.length).split("=", 2).toList match { case List(name, value) => LeonValueOption(name, value) - case List(name) => name + case List(name) => LeonFlagOption(name) case _ => reporter.fatalError("Woot?") diff --git a/src/main/scala/leon/Pipeline.scala b/src/main/scala/leon/Pipeline.scala index 80c834506198d3e673a6f5ad8f42f625d4fa0cdc..6438bb8d19538d50a663c87b9299fc79aa2d0e7c 100644 --- a/src/main/scala/leon/Pipeline.scala +++ b/src/main/scala/leon/Pipeline.scala @@ -5,8 +5,8 @@ package leon abstract class Pipeline[-F, +T] { self => - def andThen[G](then: Pipeline[T, G]): Pipeline[F, G] = new Pipeline[F,G] { - def run(ctx : LeonContext)(v : F) : G = then.run(ctx)(self.run(ctx)(v)) + def andThen[G](thenn: Pipeline[T, G]): Pipeline[F, G] = new Pipeline[F,G] { + def run(ctx : LeonContext)(v : F) : G = thenn.run(ctx)(self.run(ctx)(v)) } def run(ctx: LeonContext)(v: F): T diff --git a/src/main/scala/leon/Reporter.scala b/src/main/scala/leon/Reporter.scala index 83b9aec06b0c5fd8199127553cc170b1730c90d1..8db2e5acf8b5db8e6829232e0b25c56f6bce54d9 100644 --- a/src/main/scala/leon/Reporter.scala +++ b/src/main/scala/leon/Reporter.scala @@ -49,7 +49,7 @@ class DefaultReporter extends Reporter { Console.BLUE } "[" + color + pfx.substring(1, pfx.length-2) + Console.RESET + "] " + - msg.trim.replaceAll("\n", "\n" + (" " * (pfx.size))) + msg.replaceAll("\n", "\n" + (" " * (pfx.size))) } def errorFunction(msg: Any) = output(reline(errorPfx, msg.toString)) @@ -65,5 +65,5 @@ class QuietReporter extends DefaultReporter { class SilentReporter extends QuietReporter { override def errorFunction(msg : Any) = {} - override def fatalErrorFunction(msg : Any) = throw new Exception("Fatal error: " + msg.toString) + override def fatalErrorFunction(msg: Any) = throw LeonFatalError() } diff --git a/src/main/scala/leon/Settings.scala b/src/main/scala/leon/Settings.scala index 4271bf85d31b619698752928cacc3c420f0d2202..a9605e6203fe948439fb2f8a84d29387b0b6f1c0 100644 --- a/src/main/scala/leon/Settings.scala +++ b/src/main/scala/leon/Settings.scala @@ -8,7 +8,6 @@ object Settings { lazy val reporter: Reporter = new DefaultReporter var showIDs: Boolean = false - var silentlyTolerateNonPureBodies: Boolean = false def defaultClassPath() = { val leonLib = System.getenv("LEON_LIBRARY_PATH") @@ -35,12 +34,13 @@ object Settings { } case class Settings( - val termination: Boolean = false, - val synthesis: Boolean = false, - val xlang: Boolean = false, - val verify: Boolean = true, + val strictCompilation: Boolean = true, // Terminates Leon in case an error occured during extraction + val termination: Boolean = false, + val synthesis: Boolean = false, + val xlang: Boolean = false, + val verify: Boolean = true, // This is a list of directories that is passed as class-path of the inner-compiler. // It needs to contain at least a directory containing scala-library.jar, and // one for the leon runtime library. - val classPath: List[String] = Settings.defaultClassPath() + val classPath: List[String] = Settings.defaultClassPath() ) diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala index 9e23300c03f0affd2d51d25862ec88b62f8508ee..80d55ab9eef90931627ac82d1fd8ff3dd775899d 100644 --- a/src/main/scala/leon/codegen/CodeGeneration.scala +++ b/src/main/scala/leon/codegen/CodeGeneration.scala @@ -414,10 +414,10 @@ object CodeGeneration { } } - private[codegen] def mkBranch(cond : Expr, then : String, elze : String, ch : CodeHandler, canDelegateToMkExpr : Boolean = true)(implicit env : CompilationEnvironment) { + private[codegen] def mkBranch(cond : Expr, thenn : String, elze : String, ch : CodeHandler, canDelegateToMkExpr : Boolean = true)(implicit env : CompilationEnvironment) { cond match { case BooleanLiteral(true) => - ch << Goto(then) + ch << Goto(thenn) case BooleanLiteral(false) => ch << Goto(elze) @@ -426,63 +426,63 @@ object CodeGeneration { val fl = ch.getFreshLabel("andnext") mkBranch(es.head, fl, elze, ch) ch << Label(fl) - mkBranch(And(es.tail), then, elze, ch) + mkBranch(And(es.tail), thenn, elze, ch) case Or(es) => val fl = ch.getFreshLabel("ornext") - mkBranch(es.head, then, fl, ch) + mkBranch(es.head, thenn, fl, ch) ch << Label(fl) - mkBranch(Or(es.tail), then, elze, ch) + mkBranch(Or(es.tail), thenn, elze, ch) case Implies(l, r) => - mkBranch(Or(Not(l), r), then, elze, ch) + mkBranch(Or(Not(l), r), thenn, elze, ch) case Not(c) => - mkBranch(c, elze, then, ch) + mkBranch(c, elze, thenn, ch) case Variable(b) => - ch << ILoad(slotFor(b)) << IfEq(elze) << Goto(then) + ch << ILoad(slotFor(b)) << IfEq(elze) << Goto(thenn) case Equals(l,r) => mkExpr(l, ch) mkExpr(r, ch) l.getType match { case Int32Type | BooleanType | UnitType => - ch << If_ICmpEq(then) << Goto(elze) + ch << If_ICmpEq(thenn) << Goto(elze) case _ => ch << InvokeVirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z") - ch << IfEq(elze) << Goto(then) + ch << IfEq(elze) << Goto(thenn) } case Iff(l,r) => mkExpr(l, ch) mkExpr(r, ch) - ch << If_ICmpEq(then) << Goto(elze) + ch << If_ICmpEq(thenn) << Goto(elze) case LessThan(l,r) => mkExpr(l, ch) mkExpr(r, ch) - ch << If_ICmpLt(then) << Goto(elze) + ch << If_ICmpLt(thenn) << Goto(elze) case GreaterThan(l,r) => mkExpr(l, ch) mkExpr(r, ch) - ch << If_ICmpGt(then) << Goto(elze) + ch << If_ICmpGt(thenn) << Goto(elze) case LessEquals(l,r) => mkExpr(l, ch) mkExpr(r, ch) - ch << If_ICmpLe(then) << Goto(elze) + ch << If_ICmpLe(thenn) << Goto(elze) case GreaterEquals(l,r) => mkExpr(l, ch) mkExpr(r, ch) - ch << If_ICmpGe(then) << Goto(elze) + ch << If_ICmpGe(thenn) << Goto(elze) case other if canDelegateToMkExpr => mkExpr(other, ch, canDelegateToMkBranch = false) - ch << IfEq(elze) << Goto(then) + ch << IfEq(elze) << Goto(thenn) case other => throw CompilationException("Unsupported branching expr. : " + other) } diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala index 1c5b5eac369b435e2a9970a399dfff74482ac347..d62fb9fbc3a621b0037b881914fbfb8f046cc943 100644 --- a/src/main/scala/leon/codegen/CompilationUnit.scala +++ b/src/main/scala/leon/codegen/CompilationUnit.scala @@ -43,6 +43,8 @@ class CompilationUnit(val program: Program, val classes: Map[Definition, ClassFi }).toMap } + val a = 42 + private def writeClassFiles() { for ((d, cl) <- classes) { cl.writeToFile(cl.className + ".class") diff --git a/src/main/scala/leon/evaluators/DefaultEvaluator.scala b/src/main/scala/leon/evaluators/DefaultEvaluator.scala index d29f91c508d968e370543d2f276e807d41a50dd3..024665d055e99e93ab594ebbb7ba201074c6b200 100644 --- a/src/main/scala/leon/evaluators/DefaultEvaluator.scala +++ b/src/main/scala/leon/evaluators/DefaultEvaluator.scala @@ -56,10 +56,10 @@ class DefaultEvaluator(ctx : LeonContext, prog : Program) extends Evaluator(ctx, rec(ctx + ((i -> first)), b) } case Error(desc) => throw RuntimeError("Error reached in evaluation: " + desc) - case IfExpr(cond, then, elze) => { + case IfExpr(cond, thenn, elze) => { val first = rec(ctx, cond) first match { - case BooleanLiteral(true) => rec(ctx, then) + case BooleanLiteral(true) => rec(ctx, thenn) case BooleanLiteral(false) => rec(ctx, elze) case _ => throw EvalError(typeErrorMsg(first, BooleanType)) } diff --git a/src/main/scala/leon/plugin/AnalysisComponent.scala b/src/main/scala/leon/plugin/AnalysisComponent.scala deleted file mode 100644 index 49a62fcb4b521e308b42a33477feef70f9557287..0000000000000000000000000000000000000000 --- a/src/main/scala/leon/plugin/AnalysisComponent.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2009-2013 EPFL, Lausanne */ - -package leon -package plugin - -import scala.tools.nsc._ -import scala.tools.nsc.plugins._ - -import purescala.Definitions.Program -import synthesis.SynthesisPhase - -class AnalysisComponent(val global: Global, val pluginInstance: LeonPlugin) - extends PluginComponent - with CodeExtraction -{ - import global._ - - // This is how it works from 2.8 on.. - override val runsRightAfter: Option[String] = None - override val runsAfter: List[String] = List("refchecks") - - val phaseName = pluginInstance.name - - /** this is initialized when the Leon phase starts*/ - var fresh: scala.tools.nsc.util.FreshNameCreator = null - - protected def stopIfErrors: Unit = { - if(reporter.hasErrors) { - throw LeonFatalError() - } - } - - def newPhase(prev: Phase) = new AnalysisPhase(prev) - - class AnalysisPhase(prev: Phase) extends StdPhase(prev) { - def apply(unit: CompilationUnit): Unit = { - //global ref to freshName creator - fresh = unit.fresh - - - pluginInstance.global.program = Some(extractCode(unit)) - } - } -} diff --git a/src/main/scala/leon/plugin/CodeExtraction.scala b/src/main/scala/leon/plugin/CodeExtraction.scala index b03a8438f9dd661caec6d034f5fdf5f51e4162ab..bd07bf48b594a144b27ab9d48b16e5ba451eacc5 100644 --- a/src/main/scala/leon/plugin/CodeExtraction.scala +++ b/src/main/scala/leon/plugin/CodeExtraction.scala @@ -6,16 +6,18 @@ package plugin import scala.tools.nsc._ import scala.tools.nsc.plugins._ +import scala.language.implicitConversions + import purescala.Definitions._ -import purescala.Trees._ -import xlang.Trees.{Block => PBlock, _} +import purescala.Trees.{Expr => LeonExpr, _} +import xlang.Trees.{Block => LeonBlock, _} import xlang.TreeOps._ -import purescala.TypeTrees._ +import purescala.TypeTrees.{TypeTree => LeonType, _} import purescala.Common._ import purescala.TreeOps._ trait CodeExtraction extends Extractors { - self: AnalysisComponent => + self: LeonExtraction => import global._ import global.definitions._ @@ -23,1114 +25,1009 @@ trait CodeExtraction extends Extractors { import ExpressionExtractors._ import ExtractorHelpers._ - - private lazy val setTraitSym = definitions.getClass("scala.collection.immutable.Set") - private lazy val mapTraitSym = definitions.getClass("scala.collection.immutable.Map") - private lazy val multisetTraitSym = try { - definitions.getClass("scala.collection.immutable.Multiset") - } catch { - case _ => null - } - private lazy val optionClassSym = definitions.getClass("scala.Option") - private lazy val someClassSym = definitions.getClass("scala.Some") - private lazy val function1TraitSym = definitions.getClass("scala.Function1") - - private lazy val arraySym = definitions.getClass("scala.Array") - - def isArrayClassSym(sym: Symbol): Boolean = sym == arraySym - - def isTuple2(sym : Symbol) : Boolean = sym == tuple2Sym - def isTuple3(sym : Symbol) : Boolean = sym == tuple3Sym - def isTuple4(sym : Symbol) : Boolean = sym == tuple4Sym - def isTuple5(sym : Symbol) : Boolean = sym == tuple5Sym - - def isSetTraitSym(sym : Symbol) : Boolean = { - sym == setTraitSym || sym.tpe.toString.startsWith("scala.Predef.Set") - } - - def isMapTraitSym(sym : Symbol) : Boolean = { - sym == mapTraitSym || sym.tpe.toString.startsWith("scala.Predef.Map") + class ScalaPos(p: global.Position) extends ScalacPositional { + setPosInfo(p.line, p.column) } - def isMultisetTraitSym(sym : Symbol) : Boolean = { - sym == multisetTraitSym + implicit def scalaPosToLeonPos(p: global.Position): ScalacPositional = { + new ScalaPos(p) } - def isOptionClassSym(sym : Symbol) : Boolean = { - sym == optionClassSym || sym == someClassSym - } - - def isFunction1TraitSym(sym : Symbol) : Boolean = { - sym == function1TraitSym - } - - private val mutableVarSubsts: scala.collection.mutable.Map[Symbol,Function0[Expr]] = - scala.collection.mutable.Map.empty[Symbol,Function0[Expr]] - private val varSubsts: scala.collection.mutable.Map[Symbol,Function0[Expr]] = - scala.collection.mutable.Map.empty[Symbol,Function0[Expr]] + private val mutableVarSubsts: scala.collection.mutable.Map[Symbol,Function0[LeonExpr]] = + scala.collection.mutable.Map.empty[Symbol,Function0[LeonExpr]] + private val varSubsts: scala.collection.mutable.Map[Symbol,Function0[LeonExpr]] = + scala.collection.mutable.Map.empty[Symbol,Function0[LeonExpr]] private val classesToClasses: scala.collection.mutable.Map[Symbol,ClassTypeDef] = scala.collection.mutable.Map.empty[Symbol,ClassTypeDef] private val defsToDefs: scala.collection.mutable.Map[Symbol,FunDef] = scala.collection.mutable.Map.empty[Symbol,FunDef] - def extractCode(unit: CompilationUnit): Program = { - import scala.collection.mutable.HashMap + /** An exception thrown when non-purescala compatible code is encountered. */ + sealed case class ImpureCodeEncounteredException(tree: Tree) extends Exception - def s2ps(tree: Tree): Expr = toPureScala(unit)(tree) match { - case Some(ex) => ex - case None => stopIfErrors; scala.sys.error("unreachable error.") - } + /** Attempts to convert a scalac AST to a pure scala AST. */ + private var currentFunDef: FunDef = null - def st2ps(tree: Type): purescala.TypeTrees.TypeTree = toPureScalaType(unit)(tree) match { - case Some(tt) => tt - case None => stopIfErrors; scala.sys.error("unreachable error.") - } + //This is a bit missleading, if an expr is not mapped then it has no owner, if it is mapped to None it means + //that it can have any owner + private var owners: Map[LeonExpr, Option[FunDef]] = Map() - def extractTopLevelDef: ObjectDef = { - val top = unit.body match { - case p @ PackageDef(name, lst) if lst.size == 0 => { - unit.error(p.pos, "No top-level definition found.") + + class Extraction(unit: CompilationUnit) { + def toPureScala(tree: Tree): Option[LeonExpr] = { + try { + Some(extractTree(tree)) + } catch { + case e: ImpureCodeEncounteredException => None - } + } + } - case PackageDef(name, lst) if lst.size > 1 => { - unit.error(lst(1).pos, "Too many top-level definitions.") + // This one never fails, on error, it returns Untyped + def toPureScalaType(tpt: Type): LeonType = { + try { + extractType(tpt) + } catch { + case e: ImpureCodeEncounteredException => + Untyped + } + } + + private def extractTopLevelDef: Option[ObjectDef] = { + unit.body match { + case p @ PackageDef(name, lst) if lst.size == 0 => + reporter.error(p.pos, "No top-level definition found.") None - } - case PackageDef(name, lst) => { - assert(lst.size == 1) + case PackageDef(name, lst) => + if (lst.size > 1) { + reporter.error(lst(1).pos, "More than one top-level object. Rest will be ignored.") + } lst(0) match { - case ExObjectDef(n, templ) => Some(extractObjectDef(n.toString, templ)) - case other @ _ => unit.error(other.pos, "Expected: top-level single object.") - None + case ExObjectDef(n, templ) => + Some(extractObjectDef(n.toString, templ)) + + case other @ _ => + reporter.error(other.pos, "Expected: top-level single object.") + None } } - } - - stopIfErrors - top.get } - def extractObjectDef(nameStr: String, tmpl: Template): ObjectDef = { + private def extractObjectDef(nameStr: String, tmpl: Template): ObjectDef = { // we assume that the template actually corresponds to an object // definition. Typically it should have been obtained from the proper // extractor (ExObjectDef) - var classDefs: List[ClassTypeDef] = Nil - var objectDefs: List[ObjectDef] = Nil - var funDefs: List[FunDef] = Nil - - val scalaClassSyms: scala.collection.mutable.Map[Symbol,Identifier] = - scala.collection.mutable.Map.empty[Symbol,Identifier] - val scalaClassArgs: scala.collection.mutable.Map[Symbol,Seq[(String,Tree)]] = - scala.collection.mutable.Map.empty[Symbol,Seq[(String,Tree)]] - val scalaClassNames: scala.collection.mutable.Set[String] = - scala.collection.mutable.Set.empty[String] + var scalaClassSyms = Map[Symbol,Identifier]() + var scalaClassArgs = Map[Symbol,Seq[(String,Tree)]]() + var scalaClassNames = Set[String]() // we need the new type definitions before we can do anything... - tmpl.body.foreach(t => - t match { - case ExAbstractClass(o2, sym) => { - if(scalaClassNames.contains(o2)) { - unit.error(t.pos, "A class with the same name already exists.") - } else { - scalaClassSyms += (sym -> FreshIdentifier(o2)) - scalaClassNames += o2 - } + for (t <- tmpl.body) t match { + case ExAbstractClass(o2, sym) => + if(scalaClassNames.contains(o2)) { + reporter.error(t.pos, "A class with the same name already exists.") + } else { + scalaClassSyms += sym -> FreshIdentifier(o2) + scalaClassNames += o2 } - case ExCaseClass(o2, sym, args) => { - if(scalaClassNames.contains(o2)) { - unit.error(t.pos, "A class with the same name already exists.") - } else { - scalaClassSyms += (sym -> FreshIdentifier(o2)) - scalaClassNames += o2 - scalaClassArgs += (sym -> args) - } + + case ExCaseClass(o2, sym, args) => + if(scalaClassNames.contains(o2)) { + reporter.error(t.pos, "A class with the same name already exists.") + } else { + scalaClassSyms += sym -> FreshIdentifier(o2) + scalaClassNames += o2 + scalaClassArgs += sym -> args } - case _ => ; - } - ) - stopIfErrors + case _ => + } - scalaClassSyms.foreach(p => { - if(p._1.isAbstractClass) { - classesToClasses += (p._1 -> new AbstractClassDef(p._2)) - } else if(p._1.isCase) { - val ccd = new CaseClassDef(p._2) - ccd.isCaseObject = p._1.isModuleClass - classesToClasses += (p._1 -> ccd) - } - }) + for ((sym, id) <- scalaClassSyms) { + if (sym.isAbstractClass) { + classesToClasses += sym -> new AbstractClassDef(id) + } else { + val ccd = new CaseClassDef(id) + ccd.isCaseObject = sym.isModuleClass + classesToClasses += sym -> ccd + } + } - classesToClasses.foreach(p => { - val superC: List[ClassTypeDef] = p._1.tpe.baseClasses.filter(bcs => scalaClassSyms.exists(pp => pp._1 == bcs) && bcs != p._1).map(s => classesToClasses(s)).toList + for ((sym, ctd) <- classesToClasses) { + val superClasses: List[ClassTypeDef] = sym.tpe.baseClasses + .filter(bcs => scalaClassSyms.contains(bcs) && bcs != sym) + .map(s => classesToClasses(s)).toList - val superAC: List[AbstractClassDef] = superC.map(c => { - if(!c.isInstanceOf[AbstractClassDef]) { - unit.error(p._1.pos, "Class is inheriting from non-abstract class.") - null - } else { - c.asInstanceOf[AbstractClassDef] - } - }).filter(_ != null) - if(superAC.length > 1) { - unit.error(p._1.pos, "Multiple inheritance.") + val superAClasses: List[AbstractClassDef] = superClasses.flatMap { + case acd: AbstractClassDef => + Some(acd) + case c => + reporter.error(sym.pos, "Class "+ctd.id+" is inheriting from non-abstract class "+c.id+".") + None } - if(superAC.length == 1) { - p._2.setParent(superAC.head) + if (superAClasses.size > 2) { + reporter.error(sym.pos, "Multiple inheritance is not permitted, ignoring extra parents.") } - if(p._2.isInstanceOf[CaseClassDef]) { - // this should never fail - val ccargs = scalaClassArgs(p._1) - p._2.asInstanceOf[CaseClassDef].fields = ccargs.map(cca => { - val cctpe = st2ps(cca._2.tpe) - VarDecl(FreshIdentifier(cca._1).setType(cctpe), cctpe) - }) - } - }) + superAClasses.headOption.foreach{ parent => ctd.setParent(parent) } - classDefs = classesToClasses.valuesIterator.toList - - // end of class (type) extraction - - // we now extract the function signatures. - tmpl.body.foreach( - _ match { - case ExMainFunctionDef() => ; - case dd @ ExFunctionDef(n,p,t,b) => { - val mods = dd.mods - val funDef = extractFunSig(n, p, t).setPosInfo(dd.pos.line, dd.pos.column) - if(mods.isPrivate) funDef.addAnnotation("private") - for(a <- dd.symbol.annotations) { - a.atp.safeToString match { - case "leon.Annotations.induct" => funDef.addAnnotation("induct") - case "leon.Annotations.axiomatize" => funDef.addAnnotation("axiomatize") - case "leon.Annotations.main" => funDef.addAnnotation("main") - case _ => ; - } + ctd match { + case ccd: CaseClassDef => + assert(scalaClassArgs contains sym) + + ccd.fields = scalaClassArgs(sym).map{ case (name, asym) => + val tpe = toPureScalaType(asym.tpe) + VarDecl(FreshIdentifier(name).setType(tpe), tpe) } - defsToDefs += (dd.symbol -> funDef) - } - case _ => ; + case _ => + // no fields to set } - ) - - // then their bodies. - tmpl.body.foreach( - _ match { - case ExMainFunctionDef() => ; - case dd @ ExFunctionDef(n,p,t,b) => { - val fd = defsToDefs(dd.symbol) - defsToDefs(dd.symbol) = extractFunDef(fd, b) + } + + var classDefs: List[ClassTypeDef] = classesToClasses.values.toList + + // First pass to instanciate all FunDefs + for (d <- tmpl.body) d match { + case ExMainFunctionDef() => + // we ignore the main function + + case dd @ ExFunctionDef(name, params, tpe, body) => + val funDef = extractFunSig(name, params, tpe).setPosInfo(dd.pos) + + if (dd.mods.isPrivate) { + funDef.addAnnotation("private") } - case _ => ; - } - ) - - funDefs = defsToDefs.valuesIterator.toList - - // we check nothing else is polluting the object. - tmpl.body.foreach( - _ match { - case ExCaseClassSyntheticJunk() => ; - // case ExObjectDef(o2, t2) => { objectDefs = extractObjectDef(o2, t2) :: objectDefs } - case ExAbstractClass(_,_) => ; - case ExCaseClass(_,_,_) => ; - case ExConstructorDef() => ; - case ExMainFunctionDef() => ; - case ExFunctionDef(_,_,_,_) => ; - case tree => { unit.error(tree.pos, "Don't know what to do with this. Not purescala?"); println(tree) } - } - ) - val name: Identifier = FreshIdentifier(nameStr) - val theDef = new ObjectDef(name, objectDefs.reverse ::: classDefs ::: funDefs, Nil) - - theDef + for(a <- dd.symbol.annotations) { + a.atp.safeToString match { + case "leon.Annotations.induct" => funDef.addAnnotation("induct") + case "leon.Annotations.axiomatize" => funDef.addAnnotation("axiomatize") + case "leon.Annotations.main" => funDef.addAnnotation("main") + case _ => ; + } + } + + defsToDefs += dd.symbol -> funDef + + case _ => + } + + // Second pass to convert function bodies + for (d <- tmpl.body) d match { + case dd @ ExFunctionDef(_, _, _, body) if defsToDefs contains dd.symbol => + val fd = defsToDefs(dd.symbol) + + extractFunDef(fd, body) + case _ => + } + + var funDefs: List[FunDef] = defsToDefs.values.toList + + // FIXME: we check nothing else is polluting the object + for (t <- tmpl.body) t match { + case ExCaseClassSyntheticJunk() => + case ExAbstractClass(_,_) => + case ExCaseClass(_,_,_) => + case ExConstructorDef() => + case ExMainFunctionDef() => + case ExFunctionDef(_,_,_,_) => + case tree => + unsupported(tree, "Don't know what to do with this. Not purescala?"); + } + + new ObjectDef(FreshIdentifier(nameStr), classDefs ::: funDefs, Nil) } - def extractFunSig(nameStr: String, params: Seq[ValDef], tpt: Tree): FunDef = { + private def extractFunSig(nameStr: String, params: Seq[ValDef], tpt: Tree): FunDef = { val newParams = params.map(p => { - val ptpe = st2ps(p.tpt.tpe) + val ptpe = toPureScalaType(p.tpt.tpe) val newID = FreshIdentifier(p.name.toString).setType(ptpe) owners += (Variable(newID) -> None) varSubsts(p.symbol) = (() => Variable(newID)) VarDecl(newID, ptpe) }) - new FunDef(FreshIdentifier(nameStr), st2ps(tpt.tpe), newParams) + new FunDef(FreshIdentifier(nameStr), toPureScalaType(tpt.tpe), newParams) } - def extractFunDef(funDef: FunDef, body: Tree): FunDef = { - var realBody = body - var reqCont: Option[Expr] = None - var ensCont: Option[Expr] = None - + private def extractFunDef(funDef: FunDef, body: Tree): FunDef = { currentFunDef = funDef - realBody match { - case ExEnsuredExpression(body2, resSym, contract) => { + val (body2, ensuring) = body match { + case ExEnsuredExpression(body2, resSym, contract) => varSubsts(resSym) = (() => ResultVariable().setType(funDef.returnType)) - val c1 = s2ps(contract) - // varSubsts.remove(resSym) - realBody = body2 - ensCont = Some(c1) - } - case ExHoldsExpression(body2) => { - realBody = body2 - ensCont = Some(ResultVariable().setType(BooleanType)) - } - case _ => ; + (body2, toPureScala(contract)) + + case ExHoldsExpression(body2) => + (body2, Some(ResultVariable().setType(BooleanType))) + + case _ => + (body, None) } - realBody match { - case ExRequiredExpression(body3, contract) => { - realBody = body3 - reqCont = Some(s2ps(contract)) - } - case _ => ; + val (body3, require) = body2 match { + case ExRequiredExpression(body3, contract) => + (body3, toPureScala(contract)) + + case _ => + (body2, None) } - - val bodyAttempt = try { - Some(flattenBlocks(scala2PureScala(unit, Settings.silentlyTolerateNonPureBodies)(realBody))) + + val finalBody = try { + toPureScala(body3).map(flattenBlocks) match { + case Some(e) if e.getType.isInstanceOf[ArrayType] => + getOwner(e) match { + case Some(Some(fd)) if fd == funDef => + Some(e) + + case None => + Some(e) + + case _ => + reporter.error(body3.pos, "Function cannot return an array that is not locally defined") + None + } + case e => + e + } } catch { - case e: ImpureCodeEncounteredException => None + case e: ImpureCodeEncounteredException => + None } - bodyAttempt.foreach(e => - if(e.getType.isInstanceOf[ArrayType]) { - //println(owners) - //println(getOwner(e)) - getOwner(e) match { - case Some(Some(fd)) if fd == funDef => - case None => - case _ => unit.error(realBody.pos, "Function cannot return an array that is not locally defined") - } - }) - reqCont.map(e => + val finalRequire = require.filter{ e => if(containsLetDef(e)) { - unit.error(realBody.pos, "Function precondtion should not contain nested function definition") - }) - ensCont.map(e => + reporter.error(body3.pos, "Function precondtion should not contain nested function definition") + false + } else { + true + } + } + + val finalEnsuring = ensuring.filter{ e => if(containsLetDef(e)) { - unit.error(realBody.pos, "Function postcondition should not contain nested function definition") - }) - funDef.body = bodyAttempt - funDef.precondition = reqCont - funDef.postcondition = ensCont + reporter.error(body3.pos, "Function postcondition should not contain nested function definition") + false + } else { + true + } + } + + funDef.body = finalBody + funDef.precondition = finalRequire + funDef.postcondition = finalEnsuring funDef } - // THE EXTRACTION CODE STARTS HERE - val topLevelObjDef: ObjectDef = extractTopLevelDef - - stopIfErrors - - val programName: Identifier = unit.body match { - case PackageDef(name, _) => FreshIdentifier(name.toString) - case _ => FreshIdentifier("<program>") + def unsupported(msg: String): Nothing = { + reporter.error(NoPosition, msg) + throw new ImpureCodeEncounteredException(null) } - - //Program(programName, ObjectDef("Object", Nil, Nil)) - Program(programName, topLevelObjDef) - } - - /** An exception thrown when non-purescala compatible code is encountered. */ - sealed case class ImpureCodeEncounteredException(tree: Tree) extends Exception - - /** Attempts to convert a scalac AST to a pure scala AST. */ - def toPureScala(unit: CompilationUnit)(tree: Tree): Option[Expr] = { - try { - Some(scala2PureScala(unit, false)(tree)) - } catch { - case ImpureCodeEncounteredException(_) => None + def unsupported(tr: Tree, msg: String): Nothing = { + reporter.error(tr.pos, tr.toString) + reporter.error(tr.pos, msg) + throw new ImpureCodeEncounteredException(tr) } - } - - def toPureScalaType(unit: CompilationUnit)(typeTree: Type): Option[purescala.TypeTrees.TypeTree] = { - try { - Some(scalaType2PureScala(unit, false)(typeTree)) - } catch { - case ImpureCodeEncounteredException(_) => None - } - } - private var currentFunDef: FunDef = null + private def extractPattern(p: Tree, binder: Option[Identifier] = None): Pattern = p match { + case b @ Bind(name, Typed(pat, tpe)) => + val newID = FreshIdentifier(name.toString).setType(extractType(tpe.tpe)) + varSubsts(b.symbol) = (() => Variable(newID)) + extractPattern(pat, Some(newID)) + + case b @ Bind(name, pat) => + val newID = FreshIdentifier(name.toString).setType(extractType(b.symbol.tpe)) + varSubsts(b.symbol) = (() => Variable(newID)) + extractPattern(pat, Some(newID)) + + case Ident(nme.WILDCARD) => + WildcardPattern(binder) + + case s @ Select(This(_), b) if s.tpe.typeSymbol.isCase && + classesToClasses.contains(s.tpe.typeSymbol) => + // case Obj => + val cd = classesToClasses(s.tpe.typeSymbol).asInstanceOf[CaseClassDef] + assert(cd.fields.size == 0) + CaseClassPattern(binder, cd, Seq()) + + case a @ Apply(fn, args) if fn.isType && + a.tpe.typeSymbol.isCase && + classesToClasses.contains(a.tpe.typeSymbol) => + + val cd = classesToClasses(a.tpe.typeSymbol).asInstanceOf[CaseClassDef] + assert(args.size == cd.fields.size) + CaseClassPattern(binder, cd, args.map(extractPattern(_))) + + case a @ Apply(fn, args) => + extractType(a.tpe) match { + case TupleType(argsTpes) => + TuplePattern(binder, args.map(extractPattern(_))) + case _ => + unsupported(p, "Unsupported pattern") + } - //This is a bit missleading, if an expr is not mapped then it has no owner, if it is mapped to None it means - //that it can have any owner - private var owners: Map[Expr, Option[FunDef]] = Map() - - /** Forces conversion from scalac AST to purescala AST, throws an Exception - * if impossible. If not in 'silent mode', non-pure AST nodes are reported as - * errors. */ - private def scala2PureScala(unit: CompilationUnit, silent: Boolean)(tree: Tree): Expr = { - def rewriteCaseDef(cd: CaseDef): MatchCase = { - - def pat2pat(p: Tree, binder: Option[Identifier] = None): Pattern = p match { - case b @ Bind(name, Typed(pat, tpe)) => - val newID = FreshIdentifier(name.toString).setType(scalaType2PureScala(unit,silent)(tpe.tpe)) - varSubsts(b.symbol) = (() => Variable(newID)) - pat2pat(pat, Some(newID)) - - case b @ Bind(name, pat) => - val newID = FreshIdentifier(name.toString).setType(scalaType2PureScala(unit,silent)(b.symbol.tpe)) - varSubsts(b.symbol) = (() => Variable(newID)) - pat2pat(pat, Some(newID)) - - case Ident(nme.WILDCARD) => - WildcardPattern(binder) - - case s @ Select(This(_), b) if s.tpe.typeSymbol.isCase && - classesToClasses.keySet.contains(s.tpe.typeSymbol) => - // case Obj => - val cd = classesToClasses(s.tpe.typeSymbol).asInstanceOf[CaseClassDef] - assert(cd.fields.size == 0) - CaseClassPattern(binder, cd, Seq()) - - case a @ Apply(fn, args) if fn.isType && - a.tpe.typeSymbol.isCase && - classesToClasses.keySet.contains(a.tpe.typeSymbol) => - - val cd = classesToClasses(a.tpe.typeSymbol).asInstanceOf[CaseClassDef] - assert(args.size == cd.fields.size) - CaseClassPattern(binder, cd, args.map(pat2pat(_))) - - case a @ Apply(fn, args) => - val pst = scalaType2PureScala(unit, silent)(a.tpe) - pst match { - case TupleType(argsTpes) => TuplePattern(binder, args.map(pat2pat(_))) - case _ => throw ImpureCodeEncounteredException(p) - } + case _ => + unsupported(p, "Unsupported pattern") + } - case _ => - if (!silent) { - unit.error(p.pos, "Unsupported pattern.") - } - throw ImpureCodeEncounteredException(p) - } + private def extractMatchCase(cd: CaseDef): MatchCase = { + val recPattern = extractPattern(cd.pat) + val recBody = extractTree(cd.body) if(cd.guard == EmptyTree) { - SimpleCase(pat2pat(cd.pat), rec(cd.body)) + SimpleCase(recPattern, recBody) } else { - val recPattern = pat2pat(cd.pat) - val recGuard = rec(cd.guard) - val recBody = rec(cd.body) + val recGuard = extractTree(cd.guard) + if(!isPure(recGuard)) { - unit.error(cd.guard.pos, "Guard expression must be pure") + reporter.error(cd.guard.pos, "Guard expression must be pure") throw ImpureCodeEncounteredException(cd) } + GuardedCase(recPattern, recGuard, recBody) } } - def extractFunSig(nameStr: String, params: Seq[ValDef], tpt: Tree): FunDef = { - val newParams = params.map(p => { - val ptpe = scalaType2PureScala(unit, silent) (p.tpt.tpe) - val newID = FreshIdentifier(p.name.toString).setType(ptpe) - owners += (Variable(newID) -> None) - varSubsts(p.symbol) = (() => Variable(newID)) - VarDecl(newID, ptpe) - }) - new FunDef(FreshIdentifier(nameStr), scalaType2PureScala(unit, silent)(tpt.tpe), newParams) - } - - def extractFunDef(funDef: FunDef, body: Tree): FunDef = { - var realBody = body - var reqCont: Option[Expr] = None - var ensCont: Option[Expr] = None - - currentFunDef = funDef - - realBody match { - case ExEnsuredExpression(body2, resSym, contract) => { - varSubsts(resSym) = (() => ResultVariable().setType(funDef.returnType)) - val c1 = scala2PureScala(unit, Settings.silentlyTolerateNonPureBodies) (contract) - // varSubsts.remove(resSym) - realBody = body2 - ensCont = Some(c1) - } - case ExHoldsExpression(body2) => { - realBody = body2 - ensCont = Some(ResultVariable().setType(BooleanType)) - } - case _ => ; + private def extractTree(tr: Tree): LeonExpr = { + val (current, tmpRest) = tr match { + case Block(Block(e :: es1, l1) :: es2, l2) => + (e, Some(Block(es1 ++ Seq(l1) ++ es2, l2))) + case Block(e :: Nil, last) => + (e, Some(last)) + case Block(e :: es, last) => + (e, Some(Block(es, last))) + case e => + (e, None) } - realBody match { - case ExRequiredExpression(body3, contract) => { - realBody = body3 - reqCont = Some(scala2PureScala(unit, Settings.silentlyTolerateNonPureBodies) (contract)) - } - case _ => ; - } - - val bodyAttempt = try { - Some(flattenBlocks(scala2PureScala(unit, Settings.silentlyTolerateNonPureBodies)(realBody))) - } catch { - case e: ImpureCodeEncounteredException => None - } - - bodyAttempt.foreach(e => - if(e.getType.isInstanceOf[ArrayType]) { - getOwner(e) match { - case Some(Some(fd)) if fd == funDef => - case None => - case _ => unit.error(realBody.pos, "Function cannot return an array that is not locally defined") - } - }) - - reqCont.foreach(e => - if(containsLetDef(e)) { - unit.error(realBody.pos, "Function precondtion should not contain nested function definition") - }) - ensCont.foreach(e => - if(containsLetDef(e)) { - unit.error(realBody.pos, "Function postcondition should not contain nested function definition") - }) - funDef.body = bodyAttempt - funDef.precondition = reqCont - funDef.postcondition = ensCont - funDef - } + var rest = tmpRest - def rec(tr: Tree): Expr = { - - val (nextExpr, rest) = tr match { - case Block(Block(e :: es1, l1) :: es2, l2) => (e, Some(Block(es1 ++ Seq(l1) ++ es2, l2))) - case Block(e :: Nil, last) => (e, Some(last)) - case Block(e :: es, last) => (e, Some(Block(es, last))) - case _ => (tr, None) - } - - val e2: Option[Expr] = nextExpr match { + val res = current match { case ExCaseObject(sym) => classesToClasses.get(sym) match { case Some(ccd: CaseClassDef) => - Some(CaseClass(ccd, Seq())) + CaseClass(ccd, Seq()) + case _ => - None + unsupported(tr, "Unknown case class "+sym.name) } - case ExParameterlessMethodCall(t,n) => { - val selector = rec(t) + case ExParameterlessMethodCall(t,n) if extractTree(t).getType.isInstanceOf[CaseClassType] => + val selector = extractTree(t) val selType = selector.getType - if(!selType.isInstanceOf[CaseClassType]) - None - else { - - val selDef: CaseClassDef = selType.asInstanceOf[CaseClassType].classDef + val selDef: CaseClassDef = selType.asInstanceOf[CaseClassType].classDef - val fieldID = selDef.fields.find(_.id.name == n.toString) match { - case None => { - if(!silent) - unit.error(tr.pos, "Invalid method or field invocation (not a case class arg?)") - throw ImpureCodeEncounteredException(tr) - } - case Some(vd) => vd.id - } + val fieldID = selDef.fields.find(_.id.name == n.toString) match { + case None => + unsupported(tr, "Invalid method or field invocation (not a case class arg?)") - Some(CaseClassSelector(selDef, selector, fieldID).setType(fieldID.getType)) - } - } - case _ => None - } - var handleRest = true - val psExpr = e2 match { - case Some(e3) => e3 - case None => nextExpr match { - case ExTuple(tpes, exprs) => { - val tupleExprs = exprs.map(e => rec(e)) - val tupleType = TupleType(tupleExprs.map(expr => expr.getType)) - Tuple(tupleExprs).setType(tupleType) - } - case ExErrorExpression(str, tpe) => - Error(str).setType(scalaType2PureScala(unit, silent)(tpe)) - - case ExTupleExtract(tuple, index) => { - val tupleExpr = rec(tuple) - val TupleType(tpes) = tupleExpr.getType - if(tpes.size < index) - throw ImpureCodeEncounteredException(tree) - else - TupleSelect(tupleExpr, index).setType(tpes(index-1)) + case Some(vd) => + vd.id } - case ExValDef(vs, tpt, bdy) => { - val binderTpe = scalaType2PureScala(unit, silent)(tpt.tpe) - val newID = FreshIdentifier(vs.name.toString).setType(binderTpe) - val valTree = rec(bdy) - handleRest = false - if(valTree.getType.isInstanceOf[ArrayType]) { - getOwner(valTree) match { - case None => - owners += (Variable(newID) -> Some(currentFunDef)) - case Some(_) => - unit.error(nextExpr.pos, "Cannot alias array") - throw ImpureCodeEncounteredException(nextExpr) - } - } - val restTree = rest match { - case Some(rst) => { - varSubsts(vs) = (() => Variable(newID)) - val res = rec(rst) - varSubsts.remove(vs) - res - } - case None => UnitLiteral - } - val res = Let(newID, valTree, restTree) - res - } - case dd@ExFunctionDef(n, p, t, b) => { - val funDef = extractFunSig(n, p, t).setPosInfo(dd.pos.line, dd.pos.column) - defsToDefs += (dd.symbol -> funDef) - 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) - mutableVarSubsts ++= oldMutableVarSubst - currentFunDef = oldCurrentFunDef - val restTree = rest match { - case Some(rst) => rec(rst) - case None => UnitLiteral - } - defsToDefs.remove(dd.symbol) - handleRest = false - LetDef(funDefWithBody, restTree) + + CaseClassSelector(selDef, selector, fieldID).setType(fieldID.getType) + + case ExTuple(tpes, exprs) => + val tupleExprs = exprs.map(e => extractTree(e)) + val tupleType = TupleType(tupleExprs.map(expr => expr.getType)) + Tuple(tupleExprs) + + case ExErrorExpression(str, tpe) => + Error(str).setType(extractType(tpe)) + + case ExTupleExtract(tuple, index) => + val tupleExpr = extractTree(tuple) + + tupleExpr.getType match { + case TupleType(tpes) if tpes.size >= index => + TupleSelect(tupleExpr, index) + + case _ => + unsupported(tr, "Invalid tupple access") } - case ExVarDef(vs, tpt, bdy) => { - val binderTpe = scalaType2PureScala(unit, silent)(tpt.tpe) - //binderTpe match { - // case ArrayType(_) => - // unit.error(tree.pos, "Cannot declare array variables, only val are alllowed") - // throw ImpureCodeEncounteredException(tree) - // case _ => - //} - val newID = FreshIdentifier(vs.name.toString).setType(binderTpe) - val valTree = rec(bdy) - mutableVarSubsts += (vs -> (() => Variable(newID))) - handleRest = false - if(valTree.getType.isInstanceOf[ArrayType]) { - getOwner(valTree) match { - case None => - owners += (Variable(newID) -> Some(currentFunDef)) - case Some(_) => - unit.error(nextExpr.pos, "Cannot alias array") - throw ImpureCodeEncounteredException(nextExpr) - } - } - val restTree = rest match { - case Some(rst) => { - varSubsts(vs) = (() => Variable(newID)) - val res = rec(rst) - varSubsts.remove(vs) - res - } - case None => UnitLiteral + + case ExValDef(vs, tpt, bdy) => + val binderTpe = extractType(tpt.tpe) + val newID = FreshIdentifier(vs.name.toString).setType(binderTpe) + val valTree = extractTree(bdy) + + if(valTree.getType.isInstanceOf[ArrayType]) { + getOwner(valTree) match { + case None => + owners += (Variable(newID) -> Some(currentFunDef)) + case _ => + unsupported(tr, "Cannot alias array") } - val res = LetVar(newID, valTree, restTree) - res } - case ExAssign(sym, rhs) => mutableVarSubsts.get(sym) match { - case Some(fun) => { - val Variable(id) = fun() - val rhsTree = rec(rhs) - if(rhsTree.getType.isInstanceOf[ArrayType]) { - getOwner(rhsTree) match { - case None => - case Some(_) => - unit.error(nextExpr.pos, "Cannot alias array") - throw ImpureCodeEncounteredException(nextExpr) - } - } - Assignment(id, rhsTree) - } - case None => { - unit.error(tr.pos, "Undeclared variable.") - throw ImpureCodeEncounteredException(tr) + val restTree = rest match { + case Some(rst) => { + varSubsts(vs) = (() => Variable(newID)) + val res = extractTree(rst) + varSubsts.remove(vs) + res } - } - case wh@ExWhile(cond, body) => { - val condTree = rec(cond) - val bodyTree = rec(body) - While(condTree, bodyTree).setPosInfo(wh.pos.line,wh.pos.column) - } - case wh@ExWhileWithInvariant(cond, body, inv) => { - val condTree = rec(cond) - val bodyTree = rec(body) - val invTree = rec(inv) - val w = While(condTree, bodyTree).setPosInfo(wh.pos.line,wh.pos.column) - w.invariant = Some(invTree) - w + case None => UnitLiteral } - case ExInt32Literal(v) => IntLiteral(v).setType(Int32Type) - case ExBooleanLiteral(v) => BooleanLiteral(v).setType(BooleanType) - case ExUnitLiteral() => UnitLiteral - case ExLocally(body) => rec(body) - case ExTyped(e,tpt) => rec(e) - case ExIdentifier(sym,tpt) => varSubsts.get(sym) match { - case Some(fun) => fun() - case None => mutableVarSubsts.get(sym) match { - case Some(fun) => fun() - case None => { - unit.error(tr.pos, "Unidentified variable.") - throw ImpureCodeEncounteredException(tr) - } - } + rest = None + Let(newID, valTree, restTree) + + /** + * XLang Extractors + */ + + case dd @ ExFunctionDef(n, p, t, b) => + val funDef = extractFunSig(n, p, t).setPosInfo(dd.pos.line, dd.pos.column) + defsToDefs += (dd.symbol -> funDef) + 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) + mutableVarSubsts ++= oldMutableVarSubst + currentFunDef = oldCurrentFunDef + val restTree = rest match { + case Some(rst) => extractTree(rst) + case None => UnitLiteral } - case epsi@ExEpsilonExpression(tpe, varSym, predBody) => { - val pstpe = scalaType2PureScala(unit, silent)(tpe) - val previousVarSubst: Option[Function0[Expr]] = varSubsts.get(varSym) //save the previous in case of nested epsilon - varSubsts(varSym) = (() => EpsilonVariable((epsi.pos.line, epsi.pos.column)).setType(pstpe)) - val c1 = rec(predBody) - previousVarSubst match { - case Some(f) => varSubsts(varSym) = f - case None => varSubsts.remove(varSym) + defsToDefs.remove(dd.symbol) + rest = None + LetDef(funDefWithBody, restTree) + + case ExVarDef(vs, tpt, bdy) => { + val binderTpe = extractType(tpt.tpe) + val newID = FreshIdentifier(vs.name.toString).setType(binderTpe) + val valTree = extractTree(bdy) + mutableVarSubsts += (vs -> (() => Variable(newID))) + + if(valTree.getType.isInstanceOf[ArrayType]) { + getOwner(valTree) match { + case None => + owners += (Variable(newID) -> Some(currentFunDef)) + case Some(_) => + unsupported(tr, "Cannot alias array") } - if(containsEpsilon(c1)) { - unit.error(epsi.pos, "Usage of nested epsilon is not allowed.") - throw ImpureCodeEncounteredException(epsi) + } + val restTree = rest match { + case Some(rst) => { + varSubsts(vs) = (() => Variable(newID)) + val res = extractTree(rst) + varSubsts.remove(vs) + res } - Epsilon(c1).setType(pstpe).setPosInfo(epsi.pos.line, epsi.pos.column) + case None => UnitLiteral } - case chs @ ExChooseExpression(args, tpe, body, select) => { - val cTpe = scalaType2PureScala(unit, silent)(tpe) + rest = None + + LetVar(newID, valTree, restTree) + } - val vars = args map { case (tpe, sym) => - val aTpe = scalaType2PureScala(unit, silent)(tpe) - val newID = FreshIdentifier(sym.name.toString).setType(aTpe) - owners += (Variable(newID) -> None) - varSubsts(sym) = (() => Variable(newID)) - newID + case ExAssign(sym, rhs) => mutableVarSubsts.get(sym) match { + case Some(fun) => + val Variable(id) = fun() + val rhsTree = extractTree(rhs) + if(rhsTree.getType.isInstanceOf[ArrayType] && getOwner(rhsTree).isDefined) { + unsupported(tr, "Cannot alias array") } + Assignment(id, rhsTree) - val cBody = rec(body) + case None => + unsupported(tr, "Undeclared variable.") + } - Choose(vars, cBody).setType(cTpe).setPosInfo(select.pos.line, select.pos.column) + case wh @ ExWhile(cond, body) => + val condTree = extractTree(cond) + val bodyTree = extractTree(body) + While(condTree, bodyTree).setPosInfo(wh.pos) + + case wh @ ExWhileWithInvariant(cond, body, inv) => + val condTree = extractTree(cond) + val bodyTree = extractTree(body) + val invTree = extractTree(inv) + + val w = While(condTree, bodyTree).setPosInfo(wh.pos) + w.invariant = Some(invTree) + w + + case epsi @ ExEpsilonExpression(tpe, varSym, predBody) => + val pstpe = extractType(tpe) + val previousVarSubst: Option[Function0[LeonExpr]] = varSubsts.get(varSym) //save the previous in case of nested epsilon + varSubsts(varSym) = (() => EpsilonVariable((epsi.pos.line, epsi.pos.column)).setType(pstpe)) + val c1 = extractTree(predBody) + previousVarSubst match { + case Some(f) => varSubsts(varSym) = f + case None => varSubsts.remove(varSym) } - - case ExWaypointExpression(tpe, i, tree) => { - val pstpe = scalaType2PureScala(unit, silent)(tpe) - val IntLiteral(ri) = rec(i) - Waypoint(ri, rec(tree)).setType(pstpe) - } - case ExCaseClassConstruction(tpt, args) => { - val cctype = scalaType2PureScala(unit, silent)(tpt.tpe) - if(!cctype.isInstanceOf[CaseClassType]) { - if(!silent) { - unit.error(tr.pos, "Construction of a non-case class.") - } - throw ImpureCodeEncounteredException(tree) - } - val nargs = args.map(rec(_)) - val cct = cctype.asInstanceOf[CaseClassType] - CaseClass(cct.classDef, nargs).setType(cct) + if(containsEpsilon(c1)) { + unsupported(epsi, "Usage of nested epsilon is not allowed") } + Epsilon(c1).setType(pstpe).setPosInfo(epsi.pos.line, epsi.pos.column) - case ExAnd(l, r) => And(rec(l), rec(r)).setType(BooleanType) - case ExOr(l, r) => Or(rec(l), rec(r)).setType(BooleanType) - case ExNot(e) => Not(rec(e)).setType(BooleanType) - case ExUMinus(e) => UMinus(rec(e)).setType(Int32Type) - case ExPlus(l, r) => Plus(rec(l), rec(r)).setType(Int32Type) - case ExMinus(l, r) => Minus(rec(l), rec(r)).setType(Int32Type) - case ExTimes(l, r) => Times(rec(l), rec(r)).setType(Int32Type) - case ExDiv(l, r) => Division(rec(l), rec(r)).setType(Int32Type) - case ExMod(l, r) => Modulo(rec(l), rec(r)).setType(Int32Type) - case ExEquals(l, r) => { - val rl = rec(l) - val rr = rec(r) - ((rl.getType,rr.getType) match { - case (SetType(_), SetType(_)) => SetEquals(rl, rr) - case (BooleanType, BooleanType) => Iff(rl, rr) - case (_, _) => Equals(rl, rr) - }).setType(BooleanType) - } - case ExNotEquals(l, r) => Not(Equals(rec(l), rec(r)).setType(BooleanType)).setType(BooleanType) - case ExGreaterThan(l, r) => GreaterThan(rec(l), rec(r)).setType(BooleanType) - case ExGreaterEqThan(l, r) => GreaterEquals(rec(l), rec(r)).setType(BooleanType) - case ExLessThan(l, r) => LessThan(rec(l), rec(r)).setType(BooleanType) - case ExLessEqThan(l, r) => LessEquals(rec(l), rec(r)).setType(BooleanType) - case ExFiniteSet(tt, args) => { - val underlying = scalaType2PureScala(unit, silent)(tt.tpe) - FiniteSet(args.map(rec(_))).setType(SetType(underlying)) - } - case ExFiniteMultiset(tt, args) => { - val underlying = scalaType2PureScala(unit, silent)(tt.tpe) - FiniteMultiset(args.map(rec(_))).setType(MultisetType(underlying)) + case ExWaypointExpression(tpe, i, tree) => + val pstpe = extractType(tpe) + val IntLiteral(ri) = extractTree(i) + Waypoint(ri, extractTree(tree)).setType(pstpe) + + case update @ ExUpdate(lhs, index, newValue) => + val lhsRec = extractTree(lhs) + lhsRec match { + case Variable(_) => + case _ => + unsupported(tr, "Array update only works on variables") } - case ExEmptySet(tt) => { - val underlying = scalaType2PureScala(unit, silent)(tt.tpe) - FiniteSet(Seq()).setType(SetType(underlying)) + + getOwner(lhsRec) match { + case Some(Some(fd)) if fd != currentFunDef => + unsupported(tr, "cannot update an array that is not defined locally") + + case Some(None) => + unsupported(tr, "cannot update an array that is not defined locally") + + case Some(_) => + + case None => sys.error("This array: " + lhsRec + " should have had an owner") } - case ExEmptyMultiset(tt) => { - val underlying = scalaType2PureScala(unit, silent)(tt.tpe) - EmptyMultiset(underlying).setType(MultisetType(underlying)) + + val indexRec = extractTree(index) + val newValueRec = extractTree(newValue) + ArrayUpdate(lhsRec, indexRec, newValueRec).setPosInfo(update.pos) + + case ExInt32Literal(v) => + IntLiteral(v) + + case ExBooleanLiteral(v) => + BooleanLiteral(v) + + case ExUnitLiteral() => + UnitLiteral + + case ExLocally(body) => + extractTree(body) + + case ExTyped(e,tpt) => + // TODO: refine type here? + extractTree(e) + + case ExIdentifier(sym,tpt) => varSubsts.get(sym) match { + case Some(fun) => fun() + case None => mutableVarSubsts.get(sym) match { + case Some(fun) => fun() + case None => + unsupported(tr, "Unidentified variable.") } - case ExEmptyMap(ft, tt) => { - val fromUnderlying = scalaType2PureScala(unit, silent)(ft.tpe) - val toUnderlying = scalaType2PureScala(unit, silent)(tt.tpe) - val tpe = MapType(fromUnderlying, toUnderlying) + } + + case chs @ ExChooseExpression(args, tpe, body, select) => + val cTpe = extractType(tpe) - FiniteMap(Seq()).setType(tpe) + val vars = args map { case (tpe, sym) => + val aTpe = extractType(tpe) + val newID = FreshIdentifier(sym.name.toString).setType(aTpe) + owners += (Variable(newID) -> None) + varSubsts(sym) = (() => Variable(newID)) + newID } - case ExLiteralMap(ft, tt, elems) => { - val fromUnderlying = scalaType2PureScala(unit, silent)(ft.tpe) - val toUnderlying = scalaType2PureScala(unit, silent)(tt.tpe) - val tpe = MapType(fromUnderlying, toUnderlying) - val singletons: Seq[(Expr, Expr)] = elems.collect { case ExTuple(tpes, trees) if (trees.size == 2) => - (rec(trees(0)), rec(trees(1))) - } + val cBody = extractTree(body) - if (singletons.size != elems.size) { - unit.error(nextExpr.pos, "Some map elements could not be extracted as Tuple2") - throw ImpureCodeEncounteredException(nextExpr) - } + Choose(vars, cBody).setPosInfo(select.pos) - FiniteMap(singletons).setType(tpe) - } + case ExCaseClassConstruction(tpt, args) => + extractType(tpt.tpe) match { + case cct: CaseClassType => + val nargs = args.map(extractTree(_)) + CaseClass(cct.classDef, nargs) + + case _ => + unsupported(tr, "Construction of a non-case class.") - case ExSetMin(t) => { - val set = rec(t) - if(!set.getType.isInstanceOf[SetType]) { - if(!silent) unit.error(t.pos, "Min should be computed on a set.") - throw ImpureCodeEncounteredException(tree) - } - SetMin(set).setType(set.getType.asInstanceOf[SetType].base) } - case ExSetMax(t) => { - val set = rec(t) - if(!set.getType.isInstanceOf[SetType]) { - if(!silent) unit.error(t.pos, "Max should be computed on a set.") - throw ImpureCodeEncounteredException(tree) - } - SetMax(set).setType(set.getType.asInstanceOf[SetType].base) + + case ExAnd(l, r) => And(extractTree(l), extractTree(r)) + case ExOr(l, r) => Or(extractTree(l), extractTree(r)) + case ExNot(e) => Not(extractTree(e)) + case ExUMinus(e) => UMinus(extractTree(e)) + case ExPlus(l, r) => Plus(extractTree(l), extractTree(r)) + case ExMinus(l, r) => Minus(extractTree(l), extractTree(r)) + case ExTimes(l, r) => Times(extractTree(l), extractTree(r)) + case ExDiv(l, r) => Division(extractTree(l), extractTree(r)) + case ExMod(l, r) => Modulo(extractTree(l), extractTree(r)) + case ExNotEquals(l, r) => Not(Equals(extractTree(l), extractTree(r))) + case ExGreaterThan(l, r) => GreaterThan(extractTree(l), extractTree(r)) + case ExGreaterEqThan(l, r) => GreaterEquals(extractTree(l), extractTree(r)) + case ExLessThan(l, r) => LessThan(extractTree(l), extractTree(r)) + case ExLessEqThan(l, r) => LessEquals(extractTree(l), extractTree(r)) + case ExEquals(l, r) => + val rl = extractTree(l) + val rr = extractTree(r) + + (rl.getType, rr.getType) match { + case (SetType(_), SetType(_)) => + SetEquals(rl, rr) + + case (BooleanType, BooleanType) => + Iff(rl, rr) + + case (rt, lt) if isSubtypeOf(rt, lt) || isSubtypeOf(lt, rt) => + Equals(rl, rr) + + case (rt, lt) => + unsupported(tr, "Invalid comparison: (_: "+rt+") == (_: "+lt+")") } - case ExUnion(t1,t2) => { - val rl = rec(t1) - val rr = rec(t2) - rl.getType match { - case s @ SetType(_) => SetUnion(rl, rr).setType(s) - case m @ MultisetType(_) => MultisetUnion(rl, rr).setType(m) - case _ => { - if(!silent) unit.error(tree.pos, "Union of non set/multiset expressions.") - throw ImpureCodeEncounteredException(tree) - } - } + + case ExFiniteSet(tt, args) => + val underlying = extractType(tt.tpe) + FiniteSet(args.map(extractTree(_))).setType(SetType(underlying)) + + case ExFiniteMultiset(tt, args) => + val underlying = extractType(tt.tpe) + FiniteMultiset(args.map(extractTree(_))).setType(MultisetType(underlying)) + + case ExEmptySet(tt) => + val underlying = extractType(tt.tpe) + FiniteSet(Seq()).setType(SetType(underlying)) + + case ExEmptyMultiset(tt) => + val underlying = extractType(tt.tpe) + EmptyMultiset(underlying).setType(MultisetType(underlying)) + + case ExEmptyMap(ft, tt) => + val fromUnderlying = extractType(ft.tpe) + val toUnderlying = extractType(tt.tpe) + val tpe = MapType(fromUnderlying, toUnderlying) + + FiniteMap(Seq()).setType(tpe) + + case ExLiteralMap(ft, tt, elems) => + val fromUnderlying = extractType(ft.tpe) + val toUnderlying = extractType(tt.tpe) + val tpe = MapType(fromUnderlying, toUnderlying) + + val singletons: Seq[(LeonExpr, LeonExpr)] = elems.collect { + case ExTuple(tpes, trees) if (trees.size == 2) => + (extractTree(trees(0)), extractTree(trees(1))) } - case ExIntersection(t1,t2) => { - val rl = rec(t1) - val rr = rec(t2) - rl.getType match { - case s @ SetType(_) => SetIntersection(rl, rr).setType(s) - case m @ MultisetType(_) => MultisetIntersection(rl, rr).setType(m) - case _ => { - if(!silent) unit.error(tree.pos, "Intersection of non set/multiset expressions.") - throw ImpureCodeEncounteredException(tree) - } - } + + if (singletons.size != elems.size) { + unsupported(tr, "Some map elements could not be extracted as Tuple2") } - case ExSetContains(t1,t2) => { - val rl = rec(t1) - val rr = rec(t2) - rl.getType match { - case s @ SetType(_) => ElementOfSet(rr, rl) - case _ => { - if(!silent) unit.error(tree.pos, ".contains on non set expression.") - throw ImpureCodeEncounteredException(tree) - } - } + + FiniteMap(singletons).setType(tpe) + + case ExSetMin(t) => + val set = extractTree(t) + set.getType match { + case SetType(base) => + SetMin(set).setType(base) + + case _ => + unsupported(t, "Min should be computer on a set.") } - case ExSetSubset(t1,t2) => { - val rl = rec(t1) - val rr = rec(t2) - rl.getType match { - case s @ SetType(_) => SubsetOf(rl, rr) - case _ => { - if(!silent) unit.error(tree.pos, "Subset on non set expression.") - throw ImpureCodeEncounteredException(tree) - } - } + + case ExSetMax(t) => + val set = extractTree(t) + set.getType match { + case SetType(base) => + SetMax(set).setType(base) + + case _ => + unsupported(t, "Max should be computer on a set.") } - case ExSetMinus(t1,t2) => { - val rl = rec(t1) - val rr = rec(t2) - rl.getType match { - case s @ SetType(_) => SetDifference(rl, rr).setType(s) - case m @ MultisetType(_) => MultisetDifference(rl, rr).setType(m) - case _ => { - if(!silent) unit.error(tree.pos, "Difference of non set/multiset expressions.") - throw ImpureCodeEncounteredException(tree) - } - } - } - case ExSetCard(t) => { - val rt = rec(t) - rt.getType match { - case s @ SetType(_) => SetCardinality(rt) - case m @ MultisetType(_) => MultisetCardinality(rt) - case _ => { - if(!silent) unit.error(tree.pos, "Cardinality of non set/multiset expressions.") - throw ImpureCodeEncounteredException(tree) - } - } + + case ExUnion(t1,t2) => + val rl = extractTree(t1) + val rr = extractTree(t2) + + (rl.getType, rr.getType) match { + case (SetType(b1), SetType(b2)) if b1 == b2 => + SetUnion(rl, rr).setType(SetType(b1)) + + case (MultisetType(b1), MultisetType(b2)) if b1 == b2 => + MultisetUnion(rl, rr).setType(SetType(b1)) + + case (lt, rt) => + unsupported(tr, "Unsupported union between "+lt+" and "+rt) } - case ExMultisetToSet(t) => { - val rt = rec(t) - rt.getType match { - case m @ MultisetType(u) => MultisetToSet(rt).setType(SetType(u)) - case _ => { - if(!silent) unit.error(tree.pos, "toSet can only be applied to multisets.") - throw ImpureCodeEncounteredException(tree) - } - } + + case ExIntersection(t1,t2) => + val rl = extractTree(t1) + val rr = extractTree(t2) + + (rl.getType, rr.getType) match { + case (SetType(b1), SetType(b2)) if b1 == b2 => + SetIntersection(rl, rr).setType(SetType(b1)) + + case (MultisetType(b1), MultisetType(b2)) if b1 == b2 => + MultisetIntersection(rl, rr).setType(SetType(b1)) + + case (lt, rt) => + unsupported(tr, "Unsupported intersection between "+lt+" and "+rt) } - case up@ExUpdated(m,f,t) => { - val rm = rec(m) - val rf = rec(f) - val rt = rec(t) - rm.getType match { - case MapType(ft, tt) => { - MapUnion(rm, FiniteMap(Seq((rf, rt))).setType(rm.getType)).setType(rm.getType) - } - case ArrayType(bt) => { - ArrayUpdated(rm, rf, rt).setType(rm.getType).setPosInfo(up.pos.line, up.pos.column) - } - case _ => { - if (!silent) unit.error(tree.pos, "updated can only be applied to maps.") - throw ImpureCodeEncounteredException(tree) - } - } + + case ExSetContains(t1,t2) => + val rl = extractTree(t1) + val rr = extractTree(t2) + + (rl.getType, rr.getType) match { + case (SetType(base), elem) if isSubtypeOf(elem, base) => + ElementOfSet(rr, rl) + + case (lt, rt) => + unsupported(tr, "Invalid "+lt+".contains("+rt+")") } - case ExMapIsDefinedAt(m,k) => { - val rm = rec(m) - val rk = rec(k) - MapIsDefinedAt(rm, rk) + + case ExSetSubset(t1,t2) => + val rl = extractTree(t1) + val rr = extractTree(t2) + + (rl.getType, rr.getType) match { + case (SetType(base1), SetType(base2)) if base2 == base1 => + SubsetOf(rl, rr) + + case (lt, rt) => + unsupported(tr, "Invalid "+lt+" isSubsetOf "+rt+"") } - case ExPlusPlusPlus(t1,t2) => { - val rl = rec(t1) - val rr = rec(t2) - MultisetPlus(rl, rr).setType(rl.getType) + case ExSetMinus(t1,t2) => + val rl = extractTree(t1) + val rr = extractTree(t2) + + (rl.getType, rr.getType) match { + case (SetType(base1), SetType(base2)) if base2 == base1 => + SetDifference(rl, rr).setType(SetType(base1)) + + case (MultisetType(base1), MultisetType(base2)) if base2 == base1 => + MultisetDifference(rl, rr).setType(MultisetType(base1)) + + case (lt, rt) => + unsupported(tr, "Invalid "+lt+" -- "+rt+"") } - case app@ExApply(lhs,args) => { - val rlhs = rec(lhs) - val rargs = args map rec - rlhs.getType match { - case MapType(_,tt) => - assert(rargs.size == 1) - MapGet(rlhs, rargs.head).setType(tt).setPosInfo(app.pos.line, app.pos.column) - case ArrayType(bt) => { - assert(rargs.size == 1) - ArraySelect(rlhs, rargs.head).setType(bt).setPosInfo(app.pos.line, app.pos.column) - } - case _ => { - if (!silent) unit.error(tree.pos, "apply on unexpected type") - throw ImpureCodeEncounteredException(tree) - } - } + + case ExSetCard(t) => + val rt = extractTree(t) + rt.getType match { + case SetType(_) => + SetCardinality(rt) + + case MultisetType(_) => + MultisetCardinality(rt) + + case _ => + unsupported(tr, "Cardinality of non set/multiset expressions.") } - // for now update only occurs on Array. later we might have to distinguished depending on the type of the lhs - case update@ExUpdate(lhs, index, newValue) => { - val lhsRec = rec(lhs) - lhsRec match { - case Variable(_) => - case _ => { - unit.error(tree.pos, "array update only works on variables") - throw ImpureCodeEncounteredException(tree) - } - } - getOwner(lhsRec) match { - case Some(Some(fd)) if fd != currentFunDef => - unit.error(nextExpr.pos, "cannot update an array that is not defined locally") - throw ImpureCodeEncounteredException(nextExpr) - case Some(None) => - unit.error(nextExpr.pos, "cannot update an array that is not defined locally") - throw ImpureCodeEncounteredException(nextExpr) - case Some(_) => - case None => sys.error("This array: " + lhsRec + " should have had an owner") - } - val indexRec = rec(index) - val newValueRec = rec(newValue) - ArrayUpdate(lhsRec, indexRec, newValueRec).setPosInfo(update.pos.line, update.pos.column) + + case ExMultisetToSet(t) => + val rt = extractTree(t) + + rt.getType match { + case MultisetType(u) => + MultisetToSet(rt).setType(SetType(u)) + + case _ => + unsupported(tr, "toSet can only be applied to multisets.") } - case ExArrayLength(t) => { - val rt = rec(t) - ArrayLength(rt) + + case up @ ExUpdated(m, f, t) => + val rm = extractTree(m) + val rf = extractTree(f) + val rt = extractTree(t) + + rm.getType match { + case t @ MapType(ft, tt) => + MapUnion(rm, FiniteMap(Seq((rf, rt))).setType(t)).setType(t) + + case t @ ArrayType(bt) => + ArrayUpdated(rm, rf, rt).setType(t).setPosInfo(up.pos) + + case _ => + unsupported(tr, "updated can only be applied to maps.") } - case ExArrayClone(t) => { - val rt = rec(t) - ArrayClone(rt) + + case ExMapIsDefinedAt(m,k) => + val rm = extractTree(m) + val rk = extractTree(k) + MapIsDefinedAt(rm, rk) + + case ExPlusPlusPlus(t1,t2) => + val rl = extractTree(t1) + val rr = extractTree(t2) + MultisetPlus(rl, rr).setType(rl.getType) + + case app @ ExApply(lhs,args) => + val rlhs = extractTree(lhs) + val rargs = args map extractTree + + rlhs.getType match { + case MapType(_,tt) => + assert(rargs.size == 1) + MapGet(rlhs, rargs.head).setType(tt).setPosInfo(app.pos.line, app.pos.column) + + case ArrayType(bt) => + assert(rargs.size == 1) + ArraySelect(rlhs, rargs.head).setType(bt).setPosInfo(app.pos.line, app.pos.column) + + case _ => + unsupported(tr, "apply on unexpected type") } - case ExArrayFill(baseType, length, defaultValue) => { - val underlying = scalaType2PureScala(unit, silent)(baseType.tpe) - val lengthRec = rec(length) - val defaultValueRec = rec(defaultValue) - ArrayFill(lengthRec, defaultValueRec).setType(ArrayType(underlying)) + + case ExArrayLength(t) => + val rt = extractTree(t) + ArrayLength(rt) + + case ExArrayClone(t) => + val rt = extractTree(t) + ArrayClone(rt) + + case ExArrayFill(baseType, length, defaultValue) => + val underlying = extractType(baseType.tpe) + val lengthRec = extractTree(length) + val defaultValueRec = extractTree(defaultValue) + ArrayFill(lengthRec, defaultValueRec).setType(ArrayType(underlying)) + + case ExIfThenElse(t1,t2,t3) => + val r1 = extractTree(t1) + if(containsLetDef(r1)) { + unsupported(t1, "Condition of if-then-else expression should not contain nested function definition") } - case ExIfThenElse(t1,t2,t3) => { - val r1 = rec(t1) - if(containsLetDef(r1)) { - unit.error(t1.pos, "Condition of if-then-else expression should not contain nested function definition") - throw ImpureCodeEncounteredException(t1) - } - val r2 = rec(t2) - val r3 = rec(t3) - val lub = leastUpperBound(r2.getType, r3.getType) - lub match { - case Some(lub) => IfExpr(r1, r2, r3).setType(lub) - case None => - unit.error(nextExpr.pos, "Both branches of ifthenelse have incompatible types") - throw ImpureCodeEncounteredException(t1) - } + val r2 = extractTree(t2) + val r3 = extractTree(t3) + val lub = leastUpperBound(r2.getType, r3.getType) + lub match { + case Some(lub) => + IfExpr(r1, r2, r3).setType(lub) + + case None => + unsupported(tr, "Both branches of ifthenelse have incompatible types") } - case ExIsInstanceOf(tt, cc) => { - val ccRec = rec(cc) - val checkType = scalaType2PureScala(unit, silent)(tt.tpe) - checkType match { - case CaseClassType(ccd) => { - val rootType: ClassTypeDef = if(ccd.parent != None) ccd.parent.get else ccd - if(!ccRec.getType.isInstanceOf[ClassType]) { - unit.error(tr.pos, "isInstanceOf can only be used with a case class") + case ExIsInstanceOf(tt, cc) => { + val ccRec = extractTree(cc) + val checkType = extractType(tt.tpe) + checkType match { + case CaseClassType(ccd) => { + val rootType: ClassTypeDef = if(ccd.parent != None) ccd.parent.get else ccd + if(!ccRec.getType.isInstanceOf[ClassType]) { + reporter.error(tr.pos, "isInstanceOf can only be used with a case class") + throw ImpureCodeEncounteredException(tr) + } else { + val testedExprType = ccRec.getType.asInstanceOf[ClassType].classDef + val testedExprRootType: ClassTypeDef = if(testedExprType.parent != None) testedExprType.parent.get else testedExprType + + if(rootType != testedExprRootType) { + reporter.error(tr.pos, "isInstanceOf can only be used with compatible case classes") throw ImpureCodeEncounteredException(tr) } else { - val testedExprType = ccRec.getType.asInstanceOf[ClassType].classDef - val testedExprRootType: ClassTypeDef = if(testedExprType.parent != None) testedExprType.parent.get else testedExprType - - if(rootType != testedExprRootType) { - unit.error(tr.pos, "isInstanceOf can only be used with compatible case classes") - throw ImpureCodeEncounteredException(tr) - } else { - CaseClassInstanceOf(ccd, ccRec) - } + CaseClassInstanceOf(ccd, ccRec) } } - case _ => { - unit.error(tr.pos, "isInstanceOf can only be used with a case class") - throw ImpureCodeEncounteredException(tr) - } } - } - - case lc @ ExLocalCall(sy,nm,ar) => { - if(defsToDefs.keysIterator.find(_ == sy).isEmpty) { - if(!silent) - unit.error(tr.pos, "Invoking an invalid function.") + case _ => { + reporter.error(tr.pos, "isInstanceOf can only be used with a case class") throw ImpureCodeEncounteredException(tr) } - val fd = defsToDefs(sy) - FunctionInvocation(fd, ar.map(rec(_))).setType(fd.returnType).setPosInfo(lc.pos.line,lc.pos.column) } + } - case pm @ ExPatternMatching(sel, cses) => { - val rs = rec(sel) - val rc = cses.map(rewriteCaseDef(_)) - val rt: purescala.TypeTrees.TypeTree = rc.map(_.rhs.getType).reduceLeft(leastUpperBound(_,_).get) - MatchExpr(rs, rc).setType(rt).setPosInfo(pm.pos.line,pm.pos.column) - } - - - // default behaviour is to complain :) - case _ => { - if(!silent) { - reporter.info(tr.pos, "Could not extract as PureScala.", true) - } - throw ImpureCodeEncounteredException(tree) + case lc @ ExLocalCall(sy,nm,ar) => { + if(defsToDefs.keysIterator.find(_ == sy).isEmpty) { + reporter.error(tr.pos, "Invoking an invalid function.") + throw ImpureCodeEncounteredException(tr) } + val fd = defsToDefs(sy) + FunctionInvocation(fd, ar.map(extractTree(_))).setType(fd.returnType).setPosInfo(lc.pos.line,lc.pos.column) } + + case pm @ ExPatternMatching(sel, cses) => + val rs = extractTree(sel) + val rc = cses.map(extractMatchCase(_)) + val rt: LeonType = rc.map(_.rhs.getType).reduceLeft(leastUpperBound(_,_).get) + MatchExpr(rs, rc).setType(rt).setPosInfo(pm.pos.line,pm.pos.column) + + + // default behaviour is to complain :) + case _ => + unsupported(tr, "Could not extract as PureScala") } - val res = if(handleRest) { - rest match { - case Some(rst) => { - val recRst = rec(rst) - val block = PBlock(Seq(psExpr), recRst).setType(recRst.getType) - block - } - case None => psExpr - } - } else { - psExpr + rest match { + case Some(r) => + LeonBlock(Seq(res), extractTree(r)) + case None => + res } + } + + private def extractType(tpt: Type): LeonType = tpt match { + case tpe if tpe == IntClass.tpe => + Int32Type + + case tpe if tpe == BooleanClass.tpe => + BooleanType + + case tpe if tpe == UnitClass.tpe => + UnitType + + case tpe if tpe == NothingClass.tpe => + BottomType - res + case TypeRef(_, sym, btt :: Nil) if isSetTraitSym(sym) => + SetType(extractType(btt)) + + case TypeRef(_, sym, btt :: Nil) if isMultisetTraitSym(sym) => + MultisetType(extractType(btt)) + + case TypeRef(_, sym, List(ftt,ttt)) if isMapTraitSym(sym) => + MapType(extractType(ftt), extractType(ttt)) + + case TypeRef(_, sym, List(t1,t2)) if isTuple2(sym) => + TupleType(Seq(extractType(t1),extractType(t2))) + + case TypeRef(_, sym, List(t1,t2,t3)) if isTuple3(sym) => + TupleType(Seq(extractType(t1),extractType(t2),extractType(t3))) + + case TypeRef(_, sym, List(t1,t2,t3,t4)) if isTuple4(sym) => + TupleType(Seq(extractType(t1),extractType(t2),extractType(t3),extractType(t4))) + + case TypeRef(_, sym, List(t1,t2,t3,t4,t5)) if isTuple5(sym) => + TupleType(Seq(extractType(t1),extractType(t2),extractType(t3),extractType(t4),extractType(t5))) + + case TypeRef(_, sym, btt :: Nil) if isArrayClassSym(sym) => + ArrayType(extractType(btt)) + + case TypeRef(_, sym, Nil) if classesToClasses contains sym => + classDefToClassType(classesToClasses(sym)) + + case SingleType(_, sym) if classesToClasses contains sym.moduleClass=> + classDefToClassType(classesToClasses(sym.moduleClass)) + + case _ => + unsupported("Could not extract type as PureScala: "+tpt+" ("+tpt.getClass+")") } - rec(tree) - } - private def scalaType2PureScala(unit: CompilationUnit, silent: Boolean)(tree: Type): purescala.TypeTrees.TypeTree = { - - def rec(tr: Type): purescala.TypeTrees.TypeTree = tr match { - case tpe if tpe == IntClass.tpe => Int32Type - case tpe if tpe == BooleanClass.tpe => BooleanType - case tpe if tpe == UnitClass.tpe => UnitType - case tpe if tpe == NothingClass.tpe => BottomType - case TypeRef(_, sym, btt :: Nil) if isSetTraitSym(sym) => SetType(rec(btt)) - case TypeRef(_, sym, btt :: Nil) if isMultisetTraitSym(sym) => MultisetType(rec(btt)) - case TypeRef(_, sym, List(ftt,ttt)) if isMapTraitSym(sym) => MapType(rec(ftt),rec(ttt)) - case TypeRef(_, sym, List(t1,t2)) if isTuple2(sym) => TupleType(Seq(rec(t1),rec(t2))) - case TypeRef(_, sym, List(t1,t2,t3)) if isTuple3(sym) => TupleType(Seq(rec(t1),rec(t2),rec(t3))) - case TypeRef(_, sym, List(t1,t2,t3,t4)) if isTuple4(sym) => TupleType(Seq(rec(t1),rec(t2),rec(t3),rec(t4))) - case TypeRef(_, sym, List(t1,t2,t3,t4,t5)) if isTuple5(sym) => TupleType(Seq(rec(t1),rec(t2),rec(t3),rec(t4),rec(t5))) - case TypeRef(_, sym, btt :: Nil) if isArrayClassSym(sym) => ArrayType(rec(btt)) - case TypeRef(_, sym, Nil) if classesToClasses.keySet.contains(sym) => classDefToClassType(classesToClasses(sym)) - case _ => { - if(!silent) { - unit.error(NoPosition, "Could not extract type as PureScala. [" + tr + "]") - throw new Exception("aouch") - } - throw ImpureCodeEncounteredException(null) + private def getReturnedExpr(expr: LeonExpr): Seq[LeonExpr] = expr match { + case Let(_, _, rest) => getReturnedExpr(rest) + case LetVar(_, _, rest) => getReturnedExpr(rest) + case LeonBlock(_, rest) => getReturnedExpr(rest) + case IfExpr(_, thenn, elze) => getReturnedExpr(thenn) ++ getReturnedExpr(elze) + case MatchExpr(_, cses) => cses.flatMap{ + case SimpleCase(_, rhs) => getReturnedExpr(rhs) + case GuardedCase(_, _, rhs) => getReturnedExpr(rhs) } - // case tt => { - // if(!silent) { - // unit.error(tree.pos, "This does not appear to be a type tree: [" + tt + "]") - // } - // throw ImpureCodeEncounteredException(tree) - // } + case _ => Seq(expr) } - rec(tree) - } + def getOwner(exprs: Seq[LeonExpr]): Option[Option[FunDef]] = { + val exprOwners: Seq[Option[Option[FunDef]]] = exprs.map(owners.get(_)) + if(exprOwners.exists(_ == None)) + None + else if(exprOwners.exists(_ == Some(None))) + Some(None) + else if(exprOwners.exists(o1 => exprOwners.exists(o2 => o1 != o2))) + Some(None) + else + exprOwners(0) + } - def mkPosString(pos: scala.tools.nsc.util.Position) : String = { - pos.line + "," + pos.column - } + def getOwner(expr: LeonExpr): Option[Option[FunDef]] = getOwner(getReturnedExpr(expr)) - def getReturnedExpr(expr: Expr): Seq[Expr] = expr match { - case Let(_, _, rest) => getReturnedExpr(rest) - case LetVar(_, _, rest) => getReturnedExpr(rest) - case PBlock(_, rest) => getReturnedExpr(rest) - case IfExpr(_, then, elze) => getReturnedExpr(then) ++ getReturnedExpr(elze) - case MatchExpr(_, cses) => cses.flatMap{ - case SimpleCase(_, rhs) => getReturnedExpr(rhs) - case GuardedCase(_, _, rhs) => getReturnedExpr(rhs) - } - case _ => Seq(expr) - } + def extractProgram: Option[Program] = { + val topLevelObjDef = extractTopLevelDef - def getOwner(exprs: Seq[Expr]): Option[Option[FunDef]] = { - val exprOwners: Seq[Option[Option[FunDef]]] = exprs.map(owners.get(_)) - if(exprOwners.exists(_ == None)) - None - else if(exprOwners.exists(_ == Some(None))) - Some(None) - else if(exprOwners.exists(o1 => exprOwners.exists(o2 => o1 != o2))) - Some(None) - else - exprOwners(0) - } + val programName: Identifier = unit.body match { + case PackageDef(name, _) => FreshIdentifier(name.toString) + case _ => FreshIdentifier("<program>") + } + + topLevelObjDef.map(obj => Program(programName, obj)) + } + } - def getOwner(expr: Expr): Option[Option[FunDef]] = getOwner(getReturnedExpr(expr)) } diff --git a/src/main/scala/leon/plugin/ExtractionPhase.scala b/src/main/scala/leon/plugin/ExtractionPhase.scala index 07f9f113fdc980599c28c24638682bd977fc0de0..b81c951303aadd4ae8be6ef0fdbe72a85cc6f8d6 100644 --- a/src/main/scala/leon/plugin/ExtractionPhase.scala +++ b/src/main/scala/leon/plugin/ExtractionPhase.scala @@ -4,7 +4,8 @@ package leon package plugin import purescala.Definitions.Program -import scala.tools.nsc.{Global,Settings=>NSCSettings,SubComponent,CompilerCommand} + +import scala.tools.nsc.{Settings=>NSCSettings,CompilerCommand} object ExtractionPhase extends LeonPhase[List[String], Program] { @@ -16,6 +17,7 @@ object ExtractionPhase extends LeonPhase[List[String], Program] { val settings = new NSCSettings settings.classpath.value = ctx.settings.classPath.mkString(":") + settings.skip.value = List("patmat") val compilerOpts = args.filterNot(_.startsWith("--")) @@ -31,13 +33,17 @@ object ExtractionPhase extends LeonPhase[List[String], Program] { // ) // } - val runner = new PluginRunner(settings, ctx, None) - val run = new runner.Run + val compiler = new ScalaCompiler(settings, ctx) + val run = new compiler.Run run.compile(command.files) - runner.program match { + compiler.leonExtraction.program match { case Some(p) => - p + if (ctx.reporter.errorCount > 0 && ctx.settings.strictCompilation) { + ctx.reporter.fatalError("Error while compiling.") + } else { + p + } case None => ctx.reporter.fatalError("Error while compiling.") } @@ -46,30 +52,3 @@ object ExtractionPhase extends LeonPhase[List[String], Program] { } } } - -/** This class is a compiler that will be used for running the plugin in - * standalone mode. Original version courtesy of D. Zufferey. */ -class PluginRunner(settings : NSCSettings, ctx: LeonContext, var program: Option[Program]) extends Global(settings, new SimpleReporter(settings, ctx.reporter)) { - val leonPlugin = new LeonPlugin(this) - - protected def myAddToPhasesSet(sub : SubComponent, descr : String) : Unit = { - phasesSet += sub - } - - /** The phases to be run. */ - override protected def computeInternalPhases() : Unit = { - val phs = List( - syntaxAnalyzer -> "parse source into ASTs, perform simple desugaring", - analyzer.namerFactory -> "resolve names, attach symbols to named trees", - analyzer.packageObjects -> "load package objects", - analyzer.typerFactory -> "the meat and potatoes: type the trees", - superAccessors -> "add super accessors in traits and nested classes", - pickler -> "serialize symbol tables", - refchecks -> "reference and override checking, translate nested objects" - ) ::: { - val zipped = leonPlugin.components zip leonPlugin.descriptions - zipped - } - phs foreach (myAddToPhasesSet _).tupled - } -} diff --git a/src/main/scala/leon/plugin/Extractors.scala b/src/main/scala/leon/plugin/Extractors.scala index e407a35086e62215869bcbfdeefd520b60f44d63..00da888f67181eecb21e62118b263e8ec326c6f3 100644 --- a/src/main/scala/leon/plugin/Extractors.scala +++ b/src/main/scala/leon/plugin/Extractors.scala @@ -8,24 +8,82 @@ import scala.tools.nsc._ /** Contains extractors to pull-out interesting parts of the Scala ASTs. */ trait Extractors { val global: Global - val pluginInstance: LeonPlugin import global._ import global.definitions._ - protected lazy val tuple2Sym: Symbol = definitions.getClass("scala.Tuple2") - protected lazy val tuple3Sym: Symbol = definitions.getClass("scala.Tuple3") - protected lazy val tuple4Sym: Symbol = definitions.getClass("scala.Tuple4") - protected lazy val tuple5Sym: Symbol = definitions.getClass("scala.Tuple5") - private lazy val setTraitSym = definitions.getClass("scala.collection.immutable.Set") - private lazy val mapTraitSym = definitions.getClass("scala.collection.immutable.Map") - private lazy val multisetTraitSym = definitions.getClass("scala.collection.immutable.Multiset") - private lazy val optionClassSym = definitions.getClass("scala.Option") + def classFromName(str: String) = { + rootMirror.getClassByName(newTypeName(str)) + } + def objectFromName(str: String) = { + rootMirror.getClassByName(newTermName(str)) + } + + protected lazy val tuple2Sym = classFromName("scala.Tuple2") + protected lazy val tuple3Sym = classFromName("scala.Tuple3") + protected lazy val tuple4Sym = classFromName("scala.Tuple4") + protected lazy val tuple5Sym = classFromName("scala.Tuple5") + protected lazy val mapSym = classFromName("scala.collection.immutable.Map") + protected lazy val setSym = classFromName("scala.collection.immutable.Set") + protected lazy val optionClassSym = classFromName("scala.Option") + protected lazy val arraySym = classFromName("scala.Array") + protected lazy val someClassSym = classFromName("scala.Some") + protected lazy val function1TraitSym = classFromName("scala.Function1") + + def isTuple2(sym : Symbol) : Boolean = sym == tuple2Sym + def isTuple3(sym : Symbol) : Boolean = sym == tuple3Sym + def isTuple4(sym : Symbol) : Boolean = sym == tuple4Sym + def isTuple5(sym : Symbol) : Boolean = sym == tuple5Sym + + + // Resolve type aliases + def getResolvedTypeSym(sym: Symbol): Symbol = { + if (sym.isAliasType) { + getResolvedTypeSym(sym.tpe.resultType.typeSymbol) + } else { + sym + } + } + + def isSetTraitSym(sym : Symbol) : Boolean = { + getResolvedTypeSym(sym) == setSym + } + + def isMapTraitSym(sym : Symbol) : Boolean = { + getResolvedTypeSym(sym) == mapSym + } + + def isMultisetTraitSym(sym : Symbol) : Boolean = { + sym == multisetTraitSym + } + + def isOptionClassSym(sym : Symbol) : Boolean = { + sym == optionClassSym || sym == someClassSym + } + + def isFunction1TraitSym(sym : Symbol) : Boolean = { + sym == function1TraitSym + } + + + protected lazy val multisetTraitSym = try { + classFromName("scala.collection.immutable.Multiset") + } catch { + case e: Throwable => + null + } + + def isArrayClassSym(sym: Symbol): Boolean = sym == arraySym object ExtractorHelpers { object ExIdNamed { def unapply(id: Ident): Option[String] = Some(id.toString) } + + object ExHasType { + def unapply(tr: Tree): Option[(Tree, Symbol)] = Some((tr, tr.tpe.typeSymbol)) + } + object ExNamed { def unapply(name: Name): Option[String] = Some(name.toString) } @@ -63,12 +121,10 @@ trait Extractors { object ExHoldsExpression { def unapply(tree: Select) : Option[Tree] = tree match { - case Select(Apply(Select(Select(leonIdent, utilsName), any2IsValidName), realExpr :: Nil), holdsName) if ( - utilsName.toString == "Utils" && - any2IsValidName.toString == "any2IsValid" && - holdsName.toString == "holds") => Some(realExpr) + case Select(Apply(ExSelected("leon", "Utils", "any2IsValid"), realExpr :: Nil), ExNamed("holds")) => + Some(realExpr) case _ => None - } + } } object ExRequiredExpression { @@ -137,7 +193,7 @@ trait Extractors { object ExCaseClassSyntheticJunk { def unapply(cd: ClassDef): Boolean = cd match { - case ClassDef(_, _, _, _) if (cd.symbol.isSynthetic && cd.symbol.isFinal) => true + case ClassDef(_, _, _, _) if (cd.symbol.isSynthetic) => true case _ => false } } @@ -172,29 +228,12 @@ trait Extractors { object ExpressionExtractors { import ExtractorHelpers._ - //object ExLocalFunctionDef { - // def unapply(tree: Block): Option[(DefDef,String,Seq[ValDef],Tree,Tree,Tree)] = tree match { - // case Block((dd @ DefDef(_, name, tparams, vparamss, tpt, rhs)) :: rest, expr) if(tparams.isEmpty && vparamss.size == 1 && name != nme.CONSTRUCTOR) => { - // if(rest.isEmpty) - // Some((dd,name.toString, vparamss(0), tpt, rhs, expr)) - // else - // Some((dd,name.toString, vparamss(0), tpt, rhs, Block(rest, expr))) - // } - // case _ => None - // } - //} - - object ExEpsilonExpression { def unapply(tree: Apply) : Option[(Type, Symbol, Tree)] = tree match { case Apply( - TypeApply(Select(Select(funcheckIdent, utilsName), epsilonName), typeTree :: Nil), - Function((vd @ ValDef(_, _, _, EmptyTree)) :: Nil, predicateBody) :: Nil) => { - if (utilsName.toString == "Utils" && epsilonName.toString == "epsilon") + TypeApply(ExSelected("leon", "Utils", "epsilon"), typeTree :: Nil), + Function((vd @ ValDef(_, _, _, EmptyTree)) :: Nil, predicateBody) :: Nil) => Some((typeTree.tpe, vd.symbol, predicateBody)) - else - None - } case _ => None } } @@ -211,13 +250,9 @@ trait Extractors { object ExChooseExpression { def unapply(tree: Apply) : Option[(List[(Type, Symbol)], Type, Tree, Tree)] = tree match { case a @ Apply( - TypeApply(Select(s @ Select(funcheckIdent, utilsName), chooseName), types), - Function(vds, predicateBody) :: Nil) => { - if (utilsName.toString == "Utils" && chooseName.toString == "choose") + TypeApply(s @ ExSelected("leon", "Utils", "choose"), types), + Function(vds, predicateBody) :: Nil) => Some(((types.map(_.tpe) zip vds.map(_.symbol)).toList, a.tpe, predicateBody, s)) - else - None - } case _ => None } } @@ -225,13 +260,9 @@ trait Extractors { object ExWaypointExpression { def unapply(tree: Apply) : Option[(Type, Tree, Tree)] = tree match { case Apply( - TypeApply(Select(Select(funcheckIdent, utilsName), waypoint), typeTree :: Nil), - List(i, expr)) => { - if (utilsName.toString == "Utils" && waypoint.toString == "waypoint") + TypeApply(ExSelected("leon", "Utils", "waypoint"), typeTree :: Nil), + List(i, expr)) => Some((typeTree.tpe, i, expr)) - else - None - } case _ => None } } @@ -267,6 +298,7 @@ trait Extractors { case _ => None } } + object ExWhileWithInvariant { def unapply(tree: Apply): Option[(Tree, Tree, Tree)] = tree match { case Apply( @@ -277,6 +309,7 @@ trait Extractors { case _ => None } } + object ExTuple { def unapply(tree: Apply): Option[(Seq[Type], Seq[Tree])] = tree match { case Apply( @@ -335,10 +368,11 @@ trait Extractors { try { val index = indexString.toInt if(index > 0) { - Some((lhs, index)) + Some((lhs, index)) } else None } catch { - case _ => None + case t: Throwable => + None } } else None } @@ -645,28 +679,20 @@ trait Extractors { } } - // object ExFiniteMap { - // def unapply(tree: Apply): Option[(Tree,Tree,List[Tree])] = tree match { - // case Apply(TypeApply(Select(Select(Select(Select(Ident(s), collectionName), immutableName), mapName), applyName), List(fromTypeTree, toTypeTree)), args) if (collectionName.toString == "collection" && immutableName.toString == "immutable" && mapName.toString == "Map" && applyName.toString == "apply") => Some((fromTypeTree, toTypeTree, args)) - // case Apply(TypeApply(Select(Select(Select(This(scalaName), predefName), mapName), applyName), List(fromTypeTree, toTypeTree)), args) if (scalaName.toString == "scala" && predefName.toString == "Predef" && mapName.toString == "Map" && applyName.toString == "apply") => Some((fromTypeTree, toTypeTree, args)) - // case _ => None - // } - // } - object ExUnion { def unapply(tree: Apply): Option[(Tree,Tree)] = tree match { - case Apply(Select(lhs, n), List(rhs)) if (n == encode("++")/*nme.PLUSPLUS*/) => Some((lhs,rhs)) + case Apply(Select(lhs, n), List(rhs)) if n == encode("++") => Some((lhs,rhs)) case _ => None } } object ExPlusPlusPlus { def unapply(tree: Apply): Option[(Tree,Tree)] = tree match { - case Apply(Select(lhs, n), List(rhs)) if (n.toString == "$plus$plus$plus") => Some((lhs,rhs)) + case Apply(Select(lhs, n), List(rhs)) if n.toString == encode("+++") => Some((lhs,rhs)) case _ => None } } - + object ExIntersection { def unapply(tree: Apply): Option[(Tree,Tree)] = tree match { case Apply(Select(lhs, n), List(rhs)) if (n == encode("**") || n == encode("&")) => Some((lhs,rhs)) @@ -744,14 +770,14 @@ trait Extractors { object ExArrayLength { def unapply(tree: Select): Option[Tree] = tree match { - case Select(t, n) if (n.toString == "length") => Some(t) + case Select(ExHasType(t, `arraySym`), n) if n.toString == "length" => Some(t) case _ => None } } object ExArrayClone { def unapply(tree: Apply): Option[Tree] = tree match { - case Apply(Select(t, n), List()) if (n.toString == "clone") => Some(t) + case Apply(Select(ExHasType(t, `arraySym`), n), List()) if n.toString == "clone" => Some(t) case _ => None } } @@ -762,18 +788,14 @@ trait Extractors { case Apply( Apply( Apply( - TypeApply( - Select(Select(Ident(scala), arrayObject), fillMethod), - baseType :: Nil - ), + TypeApply(ExSelected("scala", "Array", "fill"), baseType :: Nil), length :: Nil ), defaultValue :: Nil ), manifest - ) if(scala.toString == "scala" && - arrayObject.toString == "Array" && - fillMethod.toString == "fill") => Some((baseType, length, defaultValue)) + ) => + Some((baseType, length, defaultValue)) case _ => None } } diff --git a/src/main/scala/leon/plugin/LeonExtraction.scala b/src/main/scala/leon/plugin/LeonExtraction.scala new file mode 100644 index 0000000000000000000000000000000000000000..a2f00340e9026225e35b9e6d9f800ecd2563e735 --- /dev/null +++ b/src/main/scala/leon/plugin/LeonExtraction.scala @@ -0,0 +1,27 @@ +/* Copyright 2009-2013 EPFL, Lausanne */ + +package leon +package plugin + +import scala.tools.nsc._ +import scala.tools.nsc.plugins._ + +import purescala.Definitions.Program + +trait LeonExtraction extends SubComponent with CodeExtraction { + import global._ + + val phaseName = "leon" + + var program: Option[Program] = None + + val ctx: LeonContext + + def newPhase(prev: scala.tools.nsc.Phase): StdPhase = new Phase(prev) + + class Phase(prev: scala.tools.nsc.Phase) extends StdPhase(prev) { + def apply(unit: CompilationUnit): Unit = { + program = new Extraction(unit).extractProgram + } + } +} diff --git a/src/main/scala/leon/plugin/LeonPlugin.scala b/src/main/scala/leon/plugin/LeonPlugin.scala deleted file mode 100644 index badf32e8ef5d3333f937a6291d4fade2f8603aec..0000000000000000000000000000000000000000 --- a/src/main/scala/leon/plugin/LeonPlugin.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright 2009-2013 EPFL, Lausanne */ - -package leon -package plugin - -import scala.tools.nsc -import scala.tools.nsc.{Global,Phase} -import scala.tools.nsc.plugins.{Plugin,PluginComponent} -import purescala.Definitions.Program - -/** This class is the entry point for the plugin. */ -class LeonPlugin(val global: PluginRunner) extends Plugin { - import global._ - - val name = "leon" - val description = "The Leon static analyzer" - - /** The help message displaying the options for that plugin. */ - override val optionsHelp: Option[String] = Some( - " --uniqid When pretty-printing purescala trees, show identifiers IDs" + "\n" + - " --tolerant Silently extracts non-pure function bodies as ''unknown''" + "\n" - ) - - /** Processes the command-line options. */ - private def splitList(lst: String) : Seq[String] = lst.split(':').map(_.trim).filter(!_.isEmpty) - override def processOptions(options: List[String], error: String => Unit) { - for(option <- options) { - option match { - case "uniqid" => leon.Settings.showIDs = true - case "tolerant" => leon.Settings.silentlyTolerateNonPureBodies = true - - case _ => error("Invalid option: " + option + "\nValid options are:\n" + optionsHelp.get) - } - } - } - - val components = List(new AnalysisComponent(global, this)) - val descriptions = List[String]("leon analyses") -} diff --git a/src/main/scala/leon/plugin/ScalaCompiler.scala b/src/main/scala/leon/plugin/ScalaCompiler.scala new file mode 100644 index 0000000000000000000000000000000000000000..f6052d60ac68b241a01235c5ff622927434cebe1 --- /dev/null +++ b/src/main/scala/leon/plugin/ScalaCompiler.scala @@ -0,0 +1,30 @@ +package leon +package plugin + +import scala.tools.nsc.{Global,Settings=>NSCSettings} + +class ScalaCompiler(settings : NSCSettings, ctx: LeonContext) extends Global(settings, new SimpleReporter(settings, ctx.reporter)) { + + object leonExtraction extends { + val global: ScalaCompiler.this.type = ScalaCompiler.this + val runsAfter = List[String]("refchecks") + val runsRightAfter = None + val ctx = ScalaCompiler.this.ctx + } with LeonExtraction + + override protected def computeInternalPhases() : Unit = { + val phs = List( + syntaxAnalyzer -> "parse source into ASTs, perform simple desugaring", + analyzer.namerFactory -> "resolve names, attach symbols to named trees", + analyzer.packageObjects -> "load package objects", + analyzer.typerFactory -> "the meat and potatoes: type the trees", + patmat -> "translate match expressions", + superAccessors -> "add super accessors in traits and nested classes", + extensionMethods -> "add extension methods for inline classes", + pickler -> "serialize symbol tables", + refChecks -> "reference/override checking, translate nested objects", + leonExtraction -> "extracts leon trees out of scala trees" + ) + phs foreach { phasesSet += _._1 } + } +} diff --git a/src/main/scala/leon/plugin/SimpleReporter.scala b/src/main/scala/leon/plugin/SimpleReporter.scala index 549fb2589d47e5557b5ba1ebf415f7c37099f614..9057afeaf1ffa317b72c25292c58c9f56bf32260 100644 --- a/src/main/scala/leon/plugin/SimpleReporter.scala +++ b/src/main/scala/leon/plugin/SimpleReporter.scala @@ -5,8 +5,8 @@ package plugin import scala.tools.nsc.Settings import scala.tools.nsc.reporters.AbstractReporter -import scala.tools.nsc.util._ -import scala.tools.util.StringOps + +import scala.reflect.internal.util.{Position, NoPosition, FakePos, StringOps} /** This implements a reporter that calls the callback with every line that a regular ConsoleReporter would display. */ @@ -28,40 +28,50 @@ class SimpleReporter(val settings: Settings, reporter: leon.Reporter) extends Ab StringOps.countElementsAsString((severity).count, label(severity)) /** Prints the message. */ - def printMessage(msg: String) { reporter.info(msg) } + def printMessage(msg: String, severity: Severity) { + severity match { + case ERROR => + reporter.error(msg) + case WARNING => + reporter.warning(msg) + case INFO => + reporter.info(msg) + } + } /** Prints the message with the given position indication. */ - def printMessage(posIn: Position, msg: String) { + def printMessage(posIn: Position, msg: String, severity: Severity) { val pos = if (posIn eq null) NoPosition else if (posIn.isDefined) posIn.inUltimateSource(posIn.source) else posIn pos match { case FakePos(fmsg) => - printMessage(fmsg+" "+msg) + printMessage(fmsg+" "+msg, severity) case NoPosition => - printMessage(msg) + printMessage(msg, severity) case _ => val buf = new StringBuilder(msg) val file = pos.source.file - printMessage(pos.line + ": " + msg) - printSourceLine(pos) + printMessage(pos.line + ": " + msg+"\n"+getSourceLine(pos), severity) } } def print(pos: Position, msg: String, severity: Severity) { - printMessage(pos, clabel(severity) + msg) + printMessage(pos, clabel(severity) + msg, severity) } - def printSourceLine(pos: Position) { - printMessage(pos.lineContent.stripLineEnd) - printColumnMarker(pos) + def getSourceLine(pos: Position) = { + pos.lineContent.stripLineEnd+getColumnMarker(pos) } - def printColumnMarker(pos: Position) = - if (pos.isDefined) { printMessage(" " * (pos.column - 1) + "^") } + def getColumnMarker(pos: Position) = if (pos.isDefined) { + "\n"+(" " * (pos.column - 1) + "^") + } else { + "" + } def printSummary() { - if (WARNING.count > 0) printMessage(getCountString(WARNING) + " found") - if ( ERROR.count > 0) printMessage(getCountString(ERROR ) + " found") + if (WARNING.count > 0) printMessage(getCountString(WARNING) + " found", INFO) + if ( ERROR.count > 0) printMessage(getCountString(ERROR ) + " found", INFO) } def display(pos: Position, msg: String, severity: Severity) { diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala index 704d6a7ae3d6f89a67af8b889ce1818d5ef83bf5..8837ee937c89adb0593d5a2ec0e208162dbcb2e3 100644 --- a/src/main/scala/leon/purescala/Extractors.scala +++ b/src/main/scala/leon/purescala/Extractors.scala @@ -105,7 +105,7 @@ object Extractors { case FiniteArray(args) => Some((args, FiniteArray)) case Distinct(args) => Some((args, Distinct)) case Tuple(args) => Some((args, Tuple)) - case IfExpr(cond, then, elze) => Some((Seq(cond, then, elze), (as: Seq[Expr]) => IfExpr(as(0), as(1), as(2)))) + case IfExpr(cond, thenn, elze) => Some((Seq(cond, thenn, elze), (as: Seq[Expr]) => IfExpr(as(0), as(1), as(2)))) case MatchExpr(scrut, cases) => Some((scrut +: cases.flatMap{ case SimpleCase(_, e) => Seq(e) case GuardedCase(_, e1, e2) => Seq(e1, e2) } @@ -207,7 +207,7 @@ object Extractors { object TopLevelOrs { // expr1 AND (expr2 AND (expr3 AND ..)) => List(expr1, expr2, expr3) def unapply(e: Expr): Option[Seq[Expr]] = e match { case Or(exprs) => - Some(exprs.flatMap(unapply(_).flatten)) + Some(exprs.flatMap(unapply(_)).flatten) case e => Some(Seq(e)) } @@ -215,7 +215,7 @@ object Extractors { object TopLevelAnds { // expr1 AND (expr2 AND (expr3 AND ..)) => List(expr1, expr2, expr3) def unapply(e: Expr): Option[Seq[Expr]] = e match { case And(exprs) => - Some(exprs.flatMap(unapply(_).flatten)) + Some(exprs.flatMap(unapply(_)).flatten) case e => Some(Seq(e)) } diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index 964d4d90559041c95086922d4c09fa9ae41fc9da..ebe8260c80372708a220ed55d8daa46c98ac39e5 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -56,7 +56,7 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { def pp(tree: Expr, lvl: Int): Unit = tree match { case Variable(id) => sb.append(idToString(id)) case DeBruijnIndex(idx) => sb.append("_" + idx) - case LetTuple(bs,d,e) => { + case LetTuple(bs,d,e) => //pp(e, pp(d, sb.append("(let (" + b + " := "), lvl).append(") in "), lvl).append(")") sb.append("(let (" + bs.map(idToString _).mkString(",") + " := "); pp(d, lvl) @@ -64,9 +64,8 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { ind(lvl+1) pp(e, lvl+1) sb.append(")") - sb - } - case Let(b,d,e) => { + + case Let(b,d,e) => //pp(e, pp(d, sb.append("(let (" + b + " := "), lvl).append(") in "), lvl).append(")") sb.append("(let (" + idToString(b) + " := "); pp(d, lvl) @@ -74,8 +73,7 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { ind(lvl+1) pp(e, lvl+1) sb.append(")") - sb - } + case And(exprs) => ppNary(exprs, "(", " \u2227 ", ")", lvl) // \land case Or(exprs) => ppNary(exprs, "(", " \u2228 ", ")", lvl) // \lor case Not(Equals(l, r)) => ppBinary(l, r, " \u2260 ", lvl) // \neq @@ -88,41 +86,35 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { case StringLiteral(s) => sb.append("\"" + s + "\"") case UnitLiteral => sb.append("()") case t@Tuple(exprs) => ppNary(exprs, "(", ", ", ")", lvl) - case s@TupleSelect(t, i) => { + case s@TupleSelect(t, i) => pp(t, lvl) sb.append("._" + i) - sb - } - case c@Choose(vars, pred) => { + case c@Choose(vars, pred) => sb.append("choose("+vars.map(idToString _).mkString(", ")+" => ") pp(pred, lvl) sb.append(")") - } - case CaseClass(cd, args) => { + case CaseClass(cd, args) => sb.append(idToString(cd.id)) if (cd.isCaseObject) { ppNary(args, "", "", "", lvl) } else { ppNary(args, "(", ", ", ")", lvl) } - sb - } - case CaseClassInstanceOf(cd, e) => { + + case CaseClassInstanceOf(cd, e) => pp(e, lvl) sb.append(".isInstanceOf[" + idToString(cd.id) + "]") - sb - } + case CaseClassSelector(_, cc, id) => pp(cc, lvl) sb.append("." + idToString(id)) - case FunctionInvocation(fd, args) => { + case FunctionInvocation(fd, args) => sb.append(idToString(fd.id)) ppNary(args, "(", ", ", ")", lvl) - sb - } + case Plus(l,r) => ppBinary(l, r, " + ", lvl) case Minus(l,r) => ppBinary(l, r, " - ", lvl) case Times(l,r) => ppBinary(l, r, " * ", lvl) @@ -152,7 +144,7 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { case MultisetCardinality(t) => ppUnary(t, "|", "|", lvl) case MultisetPlus(l,r) => ppBinary(l, r, " \u228E ", lvl) // U+ case MultisetToSet(e) => pp(e, lvl); sb.append(".toSet") - case FiniteMap(rs) => { + case FiniteMap(rs) => sb.append("{") val sz = rs.size var c = 0 @@ -160,62 +152,58 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { pp(k, lvl); sb.append(" -> "); pp(v, lvl); c += 1 ; if(c < sz) sb.append(", ") }} sb.append("}") - } - case MapGet(m,k) => { + + case MapGet(m,k) => pp(m, lvl) ppNary(Seq(k), "(", ",", ")", lvl) - sb - } - case MapIsDefinedAt(m,k) => { + + case MapIsDefinedAt(m,k) => pp(m, lvl) sb.append(".isDefinedAt") ppNary(Seq(k), "(", ",", ")", lvl) - sb - } - case ArrayLength(a) => { + + case ArrayLength(a) => pp(a, lvl) sb.append(".length") - } - case ArrayClone(a) => { + + case ArrayClone(a) => pp(a, lvl) sb.append(".clone") - } - case fill@ArrayFill(size, v) => { + + case fill@ArrayFill(size, v) => sb.append("Array.fill(") pp(size, lvl) sb.append(")(") pp(v, lvl) sb.append(")") - } - case am@ArrayMake(v) => { + + case am@ArrayMake(v) => sb.append("Array.make(") pp(v, lvl) sb.append(")") - } - case sel@ArraySelect(ar, i) => { + + case sel@ArraySelect(ar, i) => pp(ar, lvl) sb.append("(") pp(i, lvl) sb.append(")") - } - case up@ArrayUpdated(ar, i, v) => { + + case up@ArrayUpdated(ar, i, v) => pp(ar, lvl) sb.append(".updated(") pp(i, lvl) sb.append(", ") pp(v, lvl) sb.append(")") - } - case FiniteArray(exprs) => { + + case FiniteArray(exprs) => ppNary(exprs, "Array(", ", ", ")", lvl) - } - case Distinct(exprs) => { + case Distinct(exprs) => sb.append("distinct") ppNary(exprs, "(", ", ", ")", lvl) - } - case IfExpr(c, t, e) => { + case IfExpr(c, t, e) => sb.append("if (") pp(c, lvl) sb.append(")\n") @@ -226,7 +214,6 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { sb.append("else\n") ind(lvl+1) pp(e, lvl+1) - } case mex @ MatchExpr(s, csc) => { def ppc(p: Pattern): Unit = p match { @@ -286,11 +273,10 @@ class PrettyPrinter(sb: StringBuffer = new StringBuffer) { case ResultVariable() => sb.append("#res") case Not(expr) => ppUnary(expr, "\u00AC(", ")", lvl) // \neg - case e @ Error(desc) => { + case e @ Error(desc) => sb.append("error(\"" + desc + "\")[") pp(e.getType, lvl) sb.append("]") - } case (expr: PrettyPrintable) => expr.printWith(lvl, this) diff --git a/src/main/scala/leon/purescala/ScalaPrinter.scala b/src/main/scala/leon/purescala/ScalaPrinter.scala index d7ab7e3a48dd140853f548bf38251fb92435d937..e2350d5037d430fe6e7ba48423a2e8f1c05ea791 100644 --- a/src/main/scala/leon/purescala/ScalaPrinter.scala +++ b/src/main/scala/leon/purescala/ScalaPrinter.scala @@ -415,15 +415,13 @@ object ScalaPrinter { sb.append("}\n") } - case AbstractClassDef(id, parent) => { + case AbstractClassDef(id, parent) => ind(sb, lvl) sb.append("sealed abstract class ") sb.append(id) parent.foreach(p => sb.append(" extends " + p.id)) - sb - } - case CaseClassDef(id, parent, varDecls) => { + case CaseClassDef(id, parent, varDecls) => ind(sb, lvl) sb.append("case class ") sb.append(id) @@ -442,10 +440,8 @@ object ScalaPrinter { }) sb.append(")") parent.foreach(p => sb.append(" extends " + p.id)) - sb - } - case fd @ FunDef(id, rt, args, body, pre, post) => { + case fd @ FunDef(id, rt, args, body, pre, post) => //for(a <- fd.annotations) { // ind(sb, lvl) @@ -509,9 +505,6 @@ object ScalaPrinter { } } - sb - } - case _ => sb.append("Defn?") } } diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala index 818d125e4e2041add92b4888437608f0b5072229..d59e67b40aeb9e1944a18bd07d4031deb41ed1dc 100644 --- a/src/main/scala/leon/purescala/TreeOps.scala +++ b/src/main/scala/leon/purescala/TreeOps.scala @@ -1015,12 +1015,12 @@ object TreeOps { */ def decomposeIfs(e: Expr): Expr = { def pre(e: Expr): Expr = e match { - case IfExpr(cond, then, elze) => + case IfExpr(cond, thenn, elze) => val TopLevelOrs(orcases) = cond if (orcases.exists{ case TopLevelAnds(ands) => ands.exists(_.isInstanceOf[CaseClassInstanceOf]) } ) { if (!orcases.tail.isEmpty) { - pre(IfExpr(orcases.head, then, IfExpr(Or(orcases.tail), then, elze))) + pre(IfExpr(orcases.head, thenn, IfExpr(Or(orcases.tail), thenn, elze))) } else { val TopLevelAnds(andcases) = orcases.head @@ -1029,7 +1029,7 @@ object TreeOps { if (andis.isEmpty || andnotis.isEmpty) { e } else { - IfExpr(And(andis), IfExpr(And(andnotis), then, elze), elze) + IfExpr(And(andis), IfExpr(And(andnotis), thenn, elze), elze) } } } else { @@ -1045,7 +1045,7 @@ object TreeOps { // This transformation assumes IfExpr of the form generated by decomposeIfs def patternMatchReconstruction(e: Expr): Expr = { def pre(e: Expr): Expr = e match { - case IfExpr(cond, then, elze) => + case IfExpr(cond, thenn, elze) => val TopLevelAnds(cases) = cond if (cases.forall(_.isInstanceOf[CaseClassInstanceOf])) { @@ -1107,7 +1107,7 @@ object TreeOps { CaseClassPattern(Some(binder), cd, subconds) } - val (scrutinees, patterns) = scrutSet.toSeq.map(s => (s, computePatternFor(conditions(s), s))) unzip + val (scrutinees, patterns) = scrutSet.toSeq.map(s => (s, computePatternFor(conditions(s), s))).unzip val (scrutinee, pattern) = if (scrutinees.size > 1) { (Tuple(scrutinees), TuplePattern(None, patterns)) @@ -1119,7 +1119,7 @@ object TreeOps { // (topdown). // So replaceing using Map(a => b, CC(a) => d) will replace // "CC(a)" by "d" and not by "CC(b)" - val newThen = searchAndReplace(substMap.get)(then) + val newThen = searchAndReplace(substMap.get)(thenn) // Remove unused binders val vars = variablesOf(newThen) @@ -1168,10 +1168,10 @@ object TreeOps { e - case IfExpr(cond, then, elze) => + case IfExpr(cond, thenn, elze) => try { solver.solve(cond) match { - case Some(true) => then + case Some(true) => thenn case Some(false) => solver.solve(Not(cond)) match { case Some(true) => elze case _ => e @@ -1238,10 +1238,10 @@ object TreeOps { val sb = rec(b, register(Equals(Tuple(is.map(Variable(_))), se), path)) LetTuple(is, se, sb) - case IfExpr(cond, then, elze) => + case IfExpr(cond, thenn, elze) => val rc = rec(cond, path) - IfExpr(rc, rec(then, register(rc, path)), rec(elze, register(Not(rc), path))) + IfExpr(rc, rec(thenn, register(rc, path)), rec(elze, register(Not(rc), path))) case And(es) => { var soFar = path @@ -1308,7 +1308,7 @@ object TreeOps { } protected override def rec(e: Expr, path: C) = e match { - case IfExpr(cond, then, elze) => + case IfExpr(cond, thenn, elze) => super.rec(e, path) match { case IfExpr(BooleanLiteral(true) , t, _) => t case IfExpr(BooleanLiteral(false), _, e) => e @@ -1742,7 +1742,8 @@ object TreeOps { if(t._1 == IntLiteral(0)) acc else Plus(acc, Times(t._1, t._2)) }) } catch { - case _ => expr + case _: Throwable => + expr } simplifyArithmetic(expr0) } diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala index 21a23be82a8a50c20720404913f2a6c1d0cfb045..b0a7d3220196212b7b42f118b373fb73a489af7e 100644 --- a/src/main/scala/leon/purescala/Trees.scala +++ b/src/main/scala/leon/purescala/Trees.scala @@ -57,8 +57,8 @@ object Trees { funDef.args.zip(args).foreach { case (a, c) => typeCheck(c, a.tpe) } } - case class IfExpr(cond: Expr, then: Expr, elze: Expr) extends Expr with FixedType { - val fixedType = leastUpperBound(then.getType, elze.getType).getOrElse(AnyType) + case class IfExpr(cond: Expr, thenn: Expr, elze: Expr) extends Expr with FixedType { + val fixedType = leastUpperBound(thenn.getType, elze.getType).getOrElse(AnyType) } case class Tuple(exprs: Seq[Expr]) extends Expr with FixedType { diff --git a/src/main/scala/leon/solvers/ParallelSolver.scala b/src/main/scala/leon/solvers/ParallelSolver.scala deleted file mode 100644 index b812f3b7e58b64ab38de723765ee2eb258f24870..0000000000000000000000000000000000000000 --- a/src/main/scala/leon/solvers/ParallelSolver.scala +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright 2009-2013 EPFL, Lausanne */ - -package leon -package solvers - -import purescala.Common._ -import purescala.Definitions._ -import purescala.Trees._ -import purescala.TypeTrees._ - -import scala.actors.Actor -import scala.actors.DaemonActor -import scala.actors.Actor._ - -import scala.concurrent.Lock - -@deprecated("Unused, Untested, Unmaintained", "") -class ParallelSolver(solvers : Solver*) extends Solver(solvers(0).context) with NaiveIncrementalSolver { - private val nbSolvers = solvers.size - require(nbSolvers >= 2) - - private val reporter = context.reporter - - val description = "Solver running subsolvers in parallel " + solvers.map(_.description).mkString("(", ", ", ")") - override val name = solvers.map(_.name).mkString("//") - override val superseeds : Seq[String] = solvers.map(_.name).toSeq - - case class Solve(expr: Expr) - case object Init - case object Ready - case class Result(res: Option[Boolean]) - - private class SolverRunner(s: Solver) extends DaemonActor { - - /* - val that = this - val worker = new Actor { - def act(): Unit = { - while(true) { - receive { - case Solve(expr) => { - reporter.info("Starting solver " + s.name) - val res = s.solve(expr) - that ! Result(res) - reporter.info("Ending solver " + s.name) - } - } - } - } - } - */ - - def act(): Unit = { - while(true) { - receive { - case Init => { - reporter.info("Init solver " + s.name) - s.init - coordinator ! Ready - } - case Solve(expr) => { - reporter.info("Starting solver " + s.name) - val res = s.solve(expr) - coordinator ! Result(res) - reporter.info("Ending solver " + s.name) - } - } - } - } - } - - private class Coordinator extends DaemonActor { - - def act(): Unit = { - while(true) { - receive { - case s@Solve(expr) => { - var nbResponses = 0 - - solverRunners.foreach(_ ! Init) - while(nbResponses < nbSolvers) { - receive { - case Ready => nbResponses += 1 - } - } - - nbResponses = 0 - solverRunners.foreach(_ ! s) - var result: Option[Boolean] = None - - while(nbResponses < nbSolvers) { - receive { - case Result(Some(b)) => { - solvers.foreach(_.halt) - result = Some(b) - nbResponses += 1 - } - case Result(None) => { - nbResponses += 1 - } - } - } - reply(result) - } - } - } - } - } - - private val solverRunners = solvers.map(s => new SolverRunner(s).start()) - solverRunners.foreach(_.start()) - private val coordinator = new Coordinator - coordinator.start() - - def solve(expression: Expr) : Option[Boolean] = { - val result = (coordinator !? Solve(expression)).asInstanceOf[Option[Boolean]] - result - } - - override def halt() { - solvers.foreach(_.halt) - } - - override def setProgram(prog: Program): Unit = { - solvers.foreach(_.setProgram(prog)) - } - -} - - - - -/* - private val lock = new Lock - private var nbResponses: Int = 0 - private var result: Option[Boolean] = None - private var resultNotReady: Boolean = true - private var foundSolution: Boolean = false - - - class SolverRunner(s: Solver, expr: Expr) extends Actor { - def act() { - reporter.info("Starting solver " + s.name) - s.solve(expr) match { - case Some(b) => { - lock.acquire - nbResponses += 1 - if(!foundSolution) { - solvers.foreach(_.halt) - result = Some(b) - foundSolution = true - } - lock.release - } - case None => { - lock.acquire - nbResponses += 1 - lock.release - } - } - lock.acquire - if(nbResponses >= nbSolvers) - resultNotReady = false - lock.release - reporter.info("Ending solver " + s.name) - } - } - */ - diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala index e024b55460ed35db573a500ba517e92e9bcd1e98..f55c4956712b9ffbf976aefdc47378c90d41595e 100644 --- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala +++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala @@ -623,7 +623,7 @@ trait AbstractZ3Solver extends solvers.IncrementalSolverBuilder { case OpTrue => BooleanLiteral(true) case OpFalse => BooleanLiteral(false) case OpEq => Equals(rargs(0), rargs(1)) - case OpITE => { + case OpITE => assert(argsSize == 3) val r0 = rargs(0) val r1 = rargs(1) @@ -631,15 +631,14 @@ trait AbstractZ3Solver extends solvers.IncrementalSolverBuilder { try { IfExpr(r0, r1, r2).setType(leastUpperBound(r1.getType, r2.getType).get) } catch { - case e => { + case e: Throwable => println("I was asking for lub because of this.") println(t) println("which was translated as") println(IfExpr(r0,r1,r2)) throw e - } } - } + case OpAnd => And(rargs) case OpOr => Or(rargs) case OpIff => Iff(rargs(0), rargs(1)) diff --git a/src/main/scala/leon/solvers/z3/FunctionTemplate.scala b/src/main/scala/leon/solvers/z3/FunctionTemplate.scala index aacc633764dd0df4dbee24b72d5aa3cb1f531b7d..32e919992f42c6978d843d8a5990ad27a79c0f87 100644 --- a/src/main/scala/leon/solvers/z3/FunctionTemplate.scala +++ b/src/main/scala/leon/solvers/z3/FunctionTemplate.scala @@ -263,8 +263,8 @@ object FunctionTemplate { Or(parts.map(rec(pathVar, _))) } - case i @ IfExpr(cond, then, elze) => { - if(!containsFunctionCalls(cond) && !containsFunctionCalls(then) && !containsFunctionCalls(elze)) { + case i @ IfExpr(cond, thenn, elze) => { + if(!containsFunctionCalls(cond) && !containsFunctionCalls(thenn) && !containsFunctionCalls(elze)) { i } else { val newBool1 : Identifier = FreshIdentifier("b", true).setType(BooleanType) @@ -277,7 +277,7 @@ object FunctionTemplate { exprVars += newExpr val crec = rec(pathVar, cond) - val trec = rec(newBool1, then) + val trec = rec(newBool1, thenn) val erec = rec(newBool2, elze) storeGuarded(pathVar, Or(Variable(newBool1), Variable(newBool2))) diff --git a/src/main/scala/leon/synthesis/ManualSearch.scala b/src/main/scala/leon/synthesis/ManualSearch.scala index 4e075254f217c5e5303b448a51d55acfa205e154..b64a8340326ce1d11454b05c859a7407c9325f82 100644 --- a/src/main/scala/leon/synthesis/ManualSearch.scala +++ b/src/main/scala/leon/synthesis/ManualSearch.scala @@ -157,7 +157,7 @@ class ManualSearch(synth: Synthesizer, } } } catch { - case e => + case e: Throwable => error("Woops: "+e.getMessage()) e.printStackTrace() } diff --git a/src/main/scala/leon/synthesis/rules/Cegis.scala b/src/main/scala/leon/synthesis/rules/Cegis.scala index 5b6442206faf4dc71628fb30f25dd4bed9571f76..294a54f8f4e8caad453149410651fc3d36b492a2 100644 --- a/src/main/scala/leon/synthesis/rules/Cegis.scala +++ b/src/main/scala/leon/synthesis/rules/Cegis.scala @@ -233,12 +233,12 @@ case object CEGIS extends Rule("CEGIS") { Error("No valid clause available").setType(c.getType) } else { cases.tail.foldLeft(cases.head._2) { - case (elze, (b, then)) => IfExpr(Variable(b), then, elze) + case (elze, (b, thenn)) => IfExpr(Variable(b), thenn, elze) } } c -> ifExpr - } toMap + }.toMap // Map each x generated by the program to fresh xs passed as argument val newXs = p.xs.map(x => x -> FreshIdentifier(x.name, true).setType(x.getType)) diff --git a/src/main/scala/leon/synthesis/search/AndOrGraphParallelSearch.scala b/src/main/scala/leon/synthesis/search/AndOrGraphParallelSearch.scala index 786d1970dd137eef4bd33e6971a5bcee1ff438e9..c2f08f1286f51489ecbeb974d4111aed85cc9f97 100644 --- a/src/main/scala/leon/synthesis/search/AndOrGraphParallelSearch.scala +++ b/src/main/scala/leon/synthesis/search/AndOrGraphParallelSearch.scala @@ -3,11 +3,11 @@ package leon.synthesis.search import akka.actor._ -import akka.util.duration._ +import scala.concurrent.duration._ +import scala.concurrent.Await import akka.util.Timeout import akka.pattern.ask import akka.pattern.AskTimeoutException -import akka.dispatch.Await abstract class AndOrGraphParallelSearch[WC, AT <: AOAndTask[S], diff --git a/src/main/scala/leon/testgen/CallGraph.scala b/src/main/scala/leon/testgen/CallGraph.scala index a81a56ee213223187769fda525fd8d1aeb23fc69..62de1f42b6ef68b345d9b90641e8ca74889eaa8f 100644 --- a/src/main/scala/leon/testgen/CallGraph.scala +++ b/src/main/scala/leon/testgen/CallGraph.scala @@ -111,9 +111,9 @@ class CallGraph(val program: Program) { // callGraph += (startingPoint -> (transitions + ((newPoint, newTransition)))) // rec(e, List(), newPoint) //} - case IfExpr(cond, then, elze) => { + case IfExpr(cond, thenn, elze) => { rec(cond, path, startingPoint) - rec(then, cond :: path, startingPoint) + rec(thenn, cond :: path, startingPoint) rec(elze, Not(cond) :: path, startingPoint) } case n@NAryOperator(args, _) => { diff --git a/src/main/scala/leon/testgen/TestGeneration.scala b/src/main/scala/leon/testgen/TestGeneration.scala index 7073f68f74a67e211b2061e9cf3f29d0bc10d4d8..d8a716ba59bf1af731acab5418bd86937fa0316f 100644 --- a/src/main/scala/leon/testgen/TestGeneration.scala +++ b/src/main/scala/leon/testgen/TestGeneration.scala @@ -139,7 +139,7 @@ class TestGeneration(context : LeonContext) { // var allPaths: Seq[Expr] = Seq() // def rec(expr: Expr, path: List[Expr]): Seq[Expr] = expr match { - // case IfExpr(cond, then, elze) => rec(then, cond :: path) ++ rec(elze, Not(cond) :: path) + // case IfExpr(cond, thenn, elze) => rec(thenn, cond :: path) ++ rec(elze, Not(cond) :: path) // case _ => Seq(And(path.toSeq)) // } diff --git a/src/main/scala/leon/verification/DefaultTactic.scala b/src/main/scala/leon/verification/DefaultTactic.scala index d866afdb4ac00650b4783dc519353d79a12fa3e9..94f4526f3ce7ea7b4f0af707f3cb774efc41a5a5 100644 --- a/src/main/scala/leon/verification/DefaultTactic.scala +++ b/src/main/scala/leon/verification/DefaultTactic.scala @@ -206,9 +206,9 @@ class DefaultTactic(reporter: Reporter) extends Tactic(reporter) { rec(e, path) rec(b, Equals(Variable(i), e) :: path) } - case IfExpr(cond, then, elze) => { + case IfExpr(cond, thenn, elze) => { rec(cond, path) - rec(then, cond :: path) + rec(thenn, cond :: path) rec(elze, Not(cond) :: path) } case NAryOperator(args, _) => args.foreach(rec(_, path)) diff --git a/src/main/scala/leon/xlang/FunctionClosure.scala b/src/main/scala/leon/xlang/FunctionClosure.scala index 0feb5476c83f3b6858c0b11d60837038eca2198d..8ade819e42e3bbe1eb1ba8f6e9f40cafd67b8039 100644 --- a/src/main/scala/leon/xlang/FunctionClosure.scala +++ b/src/main/scala/leon/xlang/FunctionClosure.scala @@ -109,14 +109,14 @@ object FunctionClosure extends LeonPhase[Program, (Program, Map[FunDef, FunDef], //pathConstraints = pathConstraints.tail Let(i, re, rb).setType(l.getType) } - case i @ IfExpr(cond,then,elze) => { + case i @ IfExpr(cond,thenn,elze) => { /* when acumulating path constraints, take the condition without closing it first, so this might not work well with nested fundef in if then else condition */ val rCond = functionClosure(cond, bindedVars, id2freshId, fd2FreshFd) pathConstraints ::= cond//rCond - val rThen = functionClosure(then, bindedVars, id2freshId, fd2FreshFd) + val rThen = functionClosure(thenn, bindedVars, id2freshId, fd2FreshFd) pathConstraints = pathConstraints.tail pathConstraints ::= Not(cond)//Not(rCond) val rElze = functionClosure(elze, bindedVars, id2freshId, fd2FreshFd) diff --git a/src/main/scala/leon/xlang/Trees.scala b/src/main/scala/leon/xlang/Trees.scala index 97313acf18bcc977a8aa06481b732c1195b87446..5560f97f093609aafdd4d831963b176ce295d1df 100644 --- a/src/main/scala/leon/xlang/Trees.scala +++ b/src/main/scala/leon/xlang/Trees.scala @@ -18,11 +18,7 @@ object Trees { sb } - case class Block(exprs: Seq[Expr], last: Expr) extends Expr with NAryExtractable with PrettyPrintable with ScalaPrintable { - //val t = last.getType - //if(t != Untyped) - // setType(t) - + case class Block(exprs: Seq[Expr], last: Expr) extends Expr with NAryExtractable with PrettyPrintable with ScalaPrintable with FixedType { def extract: Option[(Seq[Expr], (Seq[Expr])=>Expr)] = { val Block(args, rest) = this Some((args :+ rest, exprs => Block(exprs.init, exprs.last))) @@ -54,6 +50,8 @@ object Trees { sb.append("}\n") sb } + + val fixedType = last.getType } case class Assignment(varId: Identifier, expr: Expr) extends Expr with FixedType with UnaryExtractable with PrettyPrintable with ScalaPrintable { diff --git a/src/main/scala/leon/z3plugins/bapa/AST.scala b/src/main/scala/leon/z3plugins/bapa/AST.scala index 6169a9f741617c3b546d63e3c9c3855cbb98b16f..499550f199338016de19764cb20d9537eea99357 100644 --- a/src/main/scala/leon/z3plugins/bapa/AST.scala +++ b/src/main/scala/leon/z3plugins/bapa/AST.scala @@ -2,6 +2,8 @@ package purescala.z3plugins.bapa +import scala.language.implicitConversions + import z3.scala._ object AST { @@ -24,7 +26,7 @@ object AST { def seteq(tree: Tree) = Op(SETEQ, Seq(this, tree)) def subseteq(tree: Tree) = Op(SUBSETEQ, Seq(this, tree)) def +(tree: Tree) = Op(ADD, Seq(this, tree)) -// def ifThenElse(then: Tree, elze: Tree) = Op(ITE, Seq(this, then, elze)) +// def ifThenElse(thenn: Tree, elze: Tree) = Op(ITE, Seq(this, thenn, elze)) def card = Op(CARD, Seq(this)) def ++(tree: Tree) = Op(UNION, Seq(this, tree)) def **(tree: Tree) = Op(INTER, Seq(this, tree)) diff --git a/src/main/scala/leon/z3plugins/bapa/Bubbles.scala b/src/main/scala/leon/z3plugins/bapa/Bubbles.scala index a60c99016a1a7f9cc35cd19177e321cee049d12e..34d17040a3b56a75bf8e0f5b12dbd1c8f4bbd0a2 100644 --- a/src/main/scala/leon/z3plugins/bapa/Bubbles.scala +++ b/src/main/scala/leon/z3plugins/bapa/Bubbles.scala @@ -421,11 +421,11 @@ trait Bubbles { def showState { println("------------") println("Bubbles :") - allBubbles.values foreach {x => println(x toLongString)} + allBubbles.values foreach {x => println(x.toLongString)} println println("Edges :") - allEdges.values foreach {x => println(x toLongString)} + allEdges.values foreach {x => println(x.toLongString)} println } // */ @@ -705,7 +705,7 @@ trait Bubbles { // nodeOrder foreach println toModel(singletons(reconstruct)) } catch { - case ex => + case ex: Throwable => var err = ex.toString if (errorVennRegion != null) err += "\nPossible cause :\n " + errorVennRegion BAPAModel(z3model, Map.empty[Z3AST,Set[Int]], Set.empty[Z3AST], err) @@ -741,7 +741,7 @@ case class BAPAModel(z3model: Z3Model, setModel: Map[Z3AST,Set[Int]], blacklist: } */ // TODO: HACK ! (scalaZ3 interface has no model navigation yet) - val badstart = blacklist map {_ toString} + val badstart = blacklist map {_.toString} val lines = (z3model.toString split '\n').toList filterNot {line => badstart exists {line startsWith _} } diff --git a/src/main/scala/leon/z3plugins/bapa/PrettyPrinter.scala b/src/main/scala/leon/z3plugins/bapa/PrettyPrinter.scala index 9330832d8d24d2c4fb2d090acad843a8b33fb9c1..3c825a2fcece0db4f0bdda068e762a0714af5f60 100644 --- a/src/main/scala/leon/z3plugins/bapa/PrettyPrinter.scala +++ b/src/main/scala/leon/z3plugins/bapa/PrettyPrinter.scala @@ -3,6 +3,8 @@ package purescala.z3plugins.bapa import scala.text.{Document, DocBreak} +import scala.language.implicitConversions + import Document._ import AST._ diff --git a/src/test/resources/regression/verification/purescala/invalid/ListOperations.scala b/src/test/resources/regression/verification/purescala/invalid/ListOperations.scala index b3b8a2f90ebbf941b9ef9b73ebb839e3df1cbf99..edf0e170e145458c3d606232be1242e096fa641f 100644 --- a/src/test/resources/regression/verification/purescala/invalid/ListOperations.scala +++ b/src/test/resources/regression/verification/purescala/invalid/ListOperations.scala @@ -50,7 +50,7 @@ object ListOperations { def sizesAreEquiv(l: List) : Boolean = { size(l) == sizeTailRec(l) - } holds + }.holds def content(l: List) : Set[Int] = l match { case Nil() => Set.empty[Int] @@ -59,7 +59,7 @@ object ListOperations { def sizeAndContent(l: List) : Boolean = { size(l) == 0 || content(l) != Set.empty[Int] - } holds + }.holds def drunk(l : List) : List = (l match { case Nil() => Nil() @@ -78,19 +78,19 @@ object ListOperations { }) ensuring(content(_) == content(l1) ++ content(l2)) @induct - def nilAppend(l : List) : Boolean = (append(l, Nil()) == l) holds + def nilAppend(l : List) : Boolean = (append(l, Nil()) == l).holds @induct def appendAssoc(xs : List, ys : List, zs : List) : Boolean = - (append(append(xs, ys), zs) == append(xs, append(ys, zs))) holds + (append(append(xs, ys), zs) == append(xs, append(ys, zs))).holds def revAuxBroken(l1 : List, e : Int, l2 : List) : Boolean = { (append(reverse(l1), Cons(e,l2)) == reverse0(l1, l2)) - } holds + }.holds @induct def sizeAppend(l1 : List, l2 : List) : Boolean = - (size(append(l1, l2)) == size(l1) + size(l2)) holds + (size(append(l1, l2)) == size(l1) + size(l2)).holds @induct def concat(l1: List, l2: List) : List = diff --git a/src/test/resources/regression/verification/purescala/invalid/PropositionalLogic.scala b/src/test/resources/regression/verification/purescala/invalid/PropositionalLogic.scala index 3018379ccd3bbc179305459524689fdb06996dc8..ec14ad7bb900e9cfa63212832d4de4b18207c926 100644 --- a/src/test/resources/regression/verification/purescala/invalid/PropositionalLogic.scala +++ b/src/test/resources/regression/verification/purescala/invalid/PropositionalLogic.scala @@ -66,23 +66,23 @@ object PropositionalLogic { // @induct // def wrongCommutative(f: Formula) : Boolean = { // nnf(simplify(f)) == simplify(nnf(f)) - // } holds + // }.holds @induct def simplifyBreaksNNF(f: Formula) : Boolean = { require(isNNF(f)) isNNF(simplify(f)) - } holds + }.holds @induct def nnfIsStable(f: Formula) : Boolean = { require(isNNF(f)) nnf(f) == f - } holds + }.holds @induct def simplifyIsStable(f: Formula) : Boolean = { require(isSimplified(f)) simplify(f) == f - } holds + }.holds } diff --git a/src/test/resources/regression/verification/purescala/invalid/Unit1.scala b/src/test/resources/regression/verification/purescala/invalid/Unit1.scala index ed3d6fcd394be796169577860de048e2395d6bfa..21ba0863c1199116a1d5f5226292b381c0db8e6f 100644 --- a/src/test/resources/regression/verification/purescala/invalid/Unit1.scala +++ b/src/test/resources/regression/verification/purescala/invalid/Unit1.scala @@ -4,6 +4,6 @@ object Unit1 { def foo(u: Unit): Unit = ({ u - }) ensuring(_ != ()) + }) ensuring(res => false) } diff --git a/src/test/resources/regression/verification/purescala/valid/AmortizedQueue.scala b/src/test/resources/regression/verification/purescala/valid/AmortizedQueue.scala index 81979fa4d18b20f0c957fad851bdce15971ee820..1b264b2e5ac7be4d0fba2b75695b2956665a3ece 100644 --- a/src/test/resources/regression/verification/purescala/valid/AmortizedQueue.scala +++ b/src/test/resources/regression/verification/purescala/valid/AmortizedQueue.scala @@ -78,7 +78,7 @@ object AmortizedQueue { // asList(enqueue(queue, elem)) == concat(list, Cons(elem, Nil())) // } else // true - // } holds + // }.holds @induct def propFront(queue : AbsQueue, list : List, elem : Int) : Boolean = { @@ -89,7 +89,7 @@ object AmortizedQueue { } } else true - } holds + }.holds @induct def propTail(rear : List, front : List, list : List, elem : Int) : Boolean = { @@ -100,14 +100,14 @@ object AmortizedQueue { } } else true - } // holds + } //.holds def enqueueAndFront(queue : AbsQueue, elem : Int) : Boolean = { if (isEmpty(queue)) front(enqueue(queue, elem)) == elem else true - } holds + }.holds def enqueueDequeueThrice(queue : AbsQueue, e1 : Int, e2 : Int, e3 : Int) : Boolean = { if (isEmpty(queue)) { @@ -122,5 +122,5 @@ object AmortizedQueue { e1 == e1prime && e2 == e2prime && e3 == e3prime } else true - } holds + }.holds } diff --git a/src/test/resources/regression/verification/purescala/valid/AssociativeList.scala b/src/test/resources/regression/verification/purescala/valid/AssociativeList.scala index ad450a93c81a006986ebd20b7f2a47cb761c0450..dd7516b20f9f11435bf047d7d58b4c4f9d0e692e 100644 --- a/src/test/resources/regression/verification/purescala/valid/AssociativeList.scala +++ b/src/test/resources/regression/verification/purescala/valid/AssociativeList.scala @@ -48,5 +48,5 @@ object AssociativeList { @induct def readOverWrite(l: List, k1: Int, k2: Int, e: Int) : Boolean = { find(updateElem(l, KeyValuePair(k2,e)), k1) == (if (k1 == k2) Some(e) else find(l, k1)) - } holds + }.holds } diff --git a/src/test/resources/regression/verification/purescala/valid/BestRealTypes.scala b/src/test/resources/regression/verification/purescala/valid/BestRealTypes.scala index c68eb99b23affb0a41537f38fd50460cb2ccdba6..449bba2f192833807566fe54784110aa71548868 100644 --- a/src/test/resources/regression/verification/purescala/valid/BestRealTypes.scala +++ b/src/test/resources/regression/verification/purescala/valid/BestRealTypes.scala @@ -23,5 +23,5 @@ object BestRealTypes { def somethingToProve(b : Boolean) : Boolean = { val (z1,z2) = zipWrap(Wrapper(boolToNum(b)), Wrapper(boolToNum(!b))) z1.num == Zero() || z2.num == Zero() - } holds + }.holds } diff --git a/src/test/resources/regression/verification/purescala/valid/ListOperations.scala b/src/test/resources/regression/verification/purescala/valid/ListOperations.scala index 9f0b8da37fdab144679b9cce226a4a55b2784afd..178d9a523d71484b0e667e8c66f4ba06ab1152b2 100644 --- a/src/test/resources/regression/verification/purescala/valid/ListOperations.scala +++ b/src/test/resources/regression/verification/purescala/valid/ListOperations.scala @@ -50,7 +50,7 @@ object ListOperations { def sizesAreEquiv(l: List) : Boolean = { size(l) == sizeTailRec(l) - } holds + }.holds def content(l: List) : Set[Int] = l match { case Nil() => Set.empty[Int] @@ -59,7 +59,7 @@ object ListOperations { def sizeAndContent(l: List) : Boolean = { size(l) == 0 || content(l) != Set.empty[Int] - } holds + }.holds def drunk(l : List) : List = (l match { case Nil() => Nil() @@ -78,15 +78,15 @@ object ListOperations { }) ensuring(content(_) == content(l1) ++ content(l2)) @induct - def nilAppend(l : List) : Boolean = (append(l, Nil()) == l) holds + def nilAppend(l : List) : Boolean = (append(l, Nil()) == l).holds @induct def appendAssoc(xs : List, ys : List, zs : List) : Boolean = - (append(append(xs, ys), zs) == append(xs, append(ys, zs))) holds + (append(append(xs, ys), zs) == append(xs, append(ys, zs))).holds @induct def sizeAppend(l1 : List, l2 : List) : Boolean = - (size(append(l1, l2)) == size(l1) + size(l2)) holds + (size(append(l1, l2)) == size(l1) + size(l2)).holds @induct def concat(l1: List, l2: List) : List = diff --git a/src/test/resources/regression/verification/purescala/valid/MyMap.scala b/src/test/resources/regression/verification/purescala/valid/MyMap.scala index 5d039ff9463c7e01c107366820551098a7203ad3..7b75661126d4452b26387a009ba71236990ec378 100644 --- a/src/test/resources/regression/verification/purescala/valid/MyMap.scala +++ b/src/test/resources/regression/verification/purescala/valid/MyMap.scala @@ -13,6 +13,6 @@ object MyMap { val m1 = Map[Int, Int]() val m2 = Map.empty[Int, Int] m1 == m2 - } holds + }.holds } diff --git a/src/test/resources/regression/verification/purescala/valid/MySet.scala b/src/test/resources/regression/verification/purescala/valid/MySet.scala index 5be8bb6e76cdda433eae19d9bfca52969c62b17c..8f1b482ffbf28c0076f5265c016773140e73dbf8 100644 --- a/src/test/resources/regression/verification/purescala/valid/MySet.scala +++ b/src/test/resources/regression/verification/purescala/valid/MySet.scala @@ -7,12 +7,12 @@ object MySet { def set1(): Boolean = { val s = Set(1, 2, 3, 4) s.contains(3) - } holds + }.holds def set2(): Boolean = { val s1 = Set[Int]() val s2 = Set.empty[Int] s1 == s2 - } holds + }.holds } diff --git a/src/test/resources/regression/verification/purescala/valid/PropositionalLogic.scala b/src/test/resources/regression/verification/purescala/valid/PropositionalLogic.scala index 60c1ef7a2fd62dd7e24c9c5c63a26e12820f813c..25b842f6c7ea194bfe8201d43384ca2690010917 100644 --- a/src/test/resources/regression/verification/purescala/valid/PropositionalLogic.scala +++ b/src/test/resources/regression/verification/purescala/valid/PropositionalLogic.scala @@ -67,11 +67,11 @@ object PropositionalLogic { def nnfIsStable(f: Formula) : Boolean = { require(isNNF(f)) nnf(f) == f - } holds + }.holds @induct def simplifyIsStable(f: Formula) : Boolean = { require(isSimplified(f)) simplify(f) == f - } holds + }.holds } diff --git a/src/test/resources/regression/verification/purescala/valid/SearchLinkedList.scala b/src/test/resources/regression/verification/purescala/valid/SearchLinkedList.scala index 64230dbd7ca744bff5cf55c554c7f5ce698aaff1..44d5550c1a0286c63c0f7a5f38f597f985285166 100644 --- a/src/test/resources/regression/verification/purescala/valid/SearchLinkedList.scala +++ b/src/test/resources/regression/verification/purescala/valid/SearchLinkedList.scala @@ -46,5 +46,5 @@ object SearchLinkedList { } else { true } - } holds + }.holds } diff --git a/src/test/resources/regression/verification/purescala/valid/SumAndMax.scala b/src/test/resources/regression/verification/purescala/valid/SumAndMax.scala index 629dc6dba22584f8413b7b32ab0457713008f54d..555f80f0a7bf9814a65a3c6ce3f5d1f1433cfaea 100644 --- a/src/test/resources/regression/verification/purescala/valid/SumAndMax.scala +++ b/src/test/resources/regression/verification/purescala/valid/SumAndMax.scala @@ -37,12 +37,12 @@ object SumAndMax { def prop0(list : List) : Boolean = { require(list != Nil()) !allPos(list) || max(list) >= 0 - } holds + }.holds @induct def property(list : List) : Boolean = { // This precondition was given in the problem but isn't actually useful :D // require(allPos(list)) sum(list) <= size(list) * (if(list == Nil()) 0 else max(list)) - } holds + }.holds } diff --git a/src/test/resources/regression/verification/purescala/valid/Unit1.scala b/src/test/resources/regression/verification/purescala/valid/Unit1.scala index 0f4d78ae9d2d0e84ac5a3aa5f88089f921ded61a..cfcbba76ff8a6372a8bb6b839d3c8f6df76223f9 100644 --- a/src/test/resources/regression/verification/purescala/valid/Unit1.scala +++ b/src/test/resources/regression/verification/purescala/valid/Unit1.scala @@ -4,6 +4,6 @@ object Unit1 { def foo(): Unit = ({ () - }) ensuring(_ == ()) + }) ensuring(r => true) } diff --git a/src/test/resources/regression/verification/purescala/valid/Unit2.scala b/src/test/resources/regression/verification/purescala/valid/Unit2.scala index 08c96fc22ef7b3c6bb731930d4cae179ed3db3cc..1f09609d04b65b3a38e32a673ff91c8cfb2d06cc 100644 --- a/src/test/resources/regression/verification/purescala/valid/Unit2.scala +++ b/src/test/resources/regression/verification/purescala/valid/Unit2.scala @@ -4,6 +4,6 @@ object Unit2 { def foo(u: Unit): Unit = { u - } ensuring(_ == ()) + } ensuring(res => true) } diff --git a/src/test/resources/regression/verification/xlang/invalid/Epsilon1.scala b/src/test/resources/regression/verification/xlang/invalid/Epsilon1.scala index 51d72f9614baeea05681632fe43e57a214d0f594..48cc02793a635154563ba1546b2623f14b4f1ed2 100644 --- a/src/test/resources/regression/verification/xlang/invalid/Epsilon1.scala +++ b/src/test/resources/regression/verification/xlang/invalid/Epsilon1.scala @@ -9,6 +9,6 @@ object Epsilon1 { //this should not hold def property2(x: Int): Boolean = { rand2(x) == rand2(x+1) - } holds + }.holds } diff --git a/src/test/resources/regression/verification/xlang/invalid/Epsilon2.scala b/src/test/resources/regression/verification/xlang/invalid/Epsilon2.scala index 7ed458cefb9dbdc7f5909a9fe6e703c6556da9a4..f5f0d6be05a34af38f2d558489b34dc8b8b9ab71 100644 --- a/src/test/resources/regression/verification/xlang/invalid/Epsilon2.scala +++ b/src/test/resources/regression/verification/xlang/invalid/Epsilon2.scala @@ -9,5 +9,5 @@ object Epsilon1 { //this should not hold def property3(x: Int): Boolean = { rand3(x) == rand3(x+1) - } holds + }.holds } diff --git a/src/test/resources/regression/verification/xlang/invalid/Epsilon4.scala b/src/test/resources/regression/verification/xlang/invalid/Epsilon4.scala index 72cb25fc16f65bbe2aa7c2f485588e2a28b71f83..92cd1d75843217a1c026c0ca191ccf588fcb38ad 100644 --- a/src/test/resources/regression/verification/xlang/invalid/Epsilon4.scala +++ b/src/test/resources/regression/verification/xlang/invalid/Epsilon4.scala @@ -24,6 +24,6 @@ object Epsilon4 { } - def wrongProperty0(lst: MyList): Boolean = (size(toList(toSet(lst))) == size(lst)) holds - //def wrongProperty1(lst: MyList): Boolean = (toList(toSet(lst)) == lst) holds + def wrongProperty0(lst: MyList): Boolean = (size(toList(toSet(lst))) == size(lst)).holds + //def wrongProperty1(lst: MyList): Boolean = (toList(toSet(lst)) == lst).holds } diff --git a/src/test/resources/regression/verification/xlang/valid/Epsilon2.scala b/src/test/resources/regression/verification/xlang/valid/Epsilon2.scala index 77315ca2f0ea326082a5b01feefb3cebce824f67..794c4f0708052adef0ffed9e34f1b5f0561dad15 100644 --- a/src/test/resources/regression/verification/xlang/valid/Epsilon2.scala +++ b/src/test/resources/regression/verification/xlang/valid/Epsilon2.scala @@ -9,7 +9,7 @@ object Epsilon1 { //this should hold, that is the expected semantic of our epsilon def property1(): Boolean = { rand() == rand() - } holds + }.holds } diff --git a/src/test/resources/regression/verification/xlang/valid/Epsilon4.scala b/src/test/resources/regression/verification/xlang/valid/Epsilon4.scala index 14fabbeb2c81c6f9ff816649a2876944ea20fc91..cbe5498b4e89dc90c80bd7e716e0cd32abe621c6 100644 --- a/src/test/resources/regression/verification/xlang/valid/Epsilon4.scala +++ b/src/test/resources/regression/verification/xlang/valid/Epsilon4.scala @@ -24,11 +24,11 @@ object Epsilon4 { } //timeout, but this probably means that it is valid as expected - //def property(lst: MyList): Boolean = (size(toList(toSet(lst))) <= size(lst)) holds + //def property(lst: MyList): Boolean = (size(toList(toSet(lst))) <= size(lst)).holds def propertyBase(lst: MyList): Boolean = ({ require(lst match { case MyNil() => true case _ => false}) size(toList(toSet(lst))) <= size(lst) - }) holds + }).holds } diff --git a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala index 27ba891159ebf47e3b0aacbdeddcd354fc9facc9..6cd6d9a88c96915eb1c2c7e90d1ef34209e5dd01 100644 --- a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala +++ b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala @@ -41,7 +41,7 @@ class EvaluatorsTests extends FunSuite { val warningsBefore = leonContext.reporter.warningCount val program = pipeline.run(leonContext)((str, Nil)) - + assert(leonContext.reporter.errorCount === errorsBefore) assert(leonContext.reporter.warningCount === warningsBefore) @@ -316,7 +316,7 @@ class EvaluatorsTests extends FunSuite { | def finite() : Set[Int] = Set(1, 2, 3) | def build(x : Int, y : Int, z : Int) : Set[Int] = Set(x, y, z) | def union(s1 : Set[Int], s2 : Set[Int]) : Set[Int] = s1 ++ s2 - | def inter(s1 : Set[Int], s2 : Set[Int]) : Set[Int] = s1 ** s2 + | def inter(s1 : Set[Int], s2 : Set[Int]) : Set[Int] = s1 & s2 | def diff(s1 : Set[Int], s2 : Set[Int]) : Set[Int] = s1 -- s2 |}""".stripMargin diff --git a/unmanaged/32/cafebabe_2.10-1.2.jar b/unmanaged/32/cafebabe_2.10-1.2.jar new file mode 120000 index 0000000000000000000000000000000000000000..37f428a8b2941987bdc522bac7e2fa90c0f37467 --- /dev/null +++ b/unmanaged/32/cafebabe_2.10-1.2.jar @@ -0,0 +1 @@ +../common/cafebabe_2.10-1.2.jar \ No newline at end of file diff --git a/unmanaged/32/cafebabe_2.9.2-1.2.jar b/unmanaged/32/cafebabe_2.9.2-1.2.jar deleted file mode 120000 index 2ccd5ee86a0781d0ad57ccc10ccafc9ef3b022bd..0000000000000000000000000000000000000000 --- a/unmanaged/32/cafebabe_2.9.2-1.2.jar +++ /dev/null @@ -1 +0,0 @@ -../common/cafebabe_2.9.2-1.2.jar \ No newline at end of file diff --git a/unmanaged/64/cafebabe_2.10-1.2.jar b/unmanaged/64/cafebabe_2.10-1.2.jar new file mode 120000 index 0000000000000000000000000000000000000000..37f428a8b2941987bdc522bac7e2fa90c0f37467 --- /dev/null +++ b/unmanaged/64/cafebabe_2.10-1.2.jar @@ -0,0 +1 @@ +../common/cafebabe_2.10-1.2.jar \ No newline at end of file diff --git a/unmanaged/64/cafebabe_2.9.2-1.2.jar b/unmanaged/64/cafebabe_2.9.2-1.2.jar deleted file mode 120000 index 2ccd5ee86a0781d0ad57ccc10ccafc9ef3b022bd..0000000000000000000000000000000000000000 --- a/unmanaged/64/cafebabe_2.9.2-1.2.jar +++ /dev/null @@ -1 +0,0 @@ -../common/cafebabe_2.9.2-1.2.jar \ No newline at end of file diff --git a/unmanaged/64/scalaz3.jar b/unmanaged/64/scalaz3.jar deleted file mode 100644 index 1584e21c3ba8bc285dc862f63dafa6bee148642a..0000000000000000000000000000000000000000 Binary files a/unmanaged/64/scalaz3.jar and /dev/null differ diff --git a/unmanaged/64/scalaz3_2.10-2.0.jar b/unmanaged/64/scalaz3_2.10-2.0.jar new file mode 120000 index 0000000000000000000000000000000000000000..304102e51a192b3df47da9f705429736afc3c474 --- /dev/null +++ b/unmanaged/64/scalaz3_2.10-2.0.jar @@ -0,0 +1 @@ +/home/ekneuss/git/ScalaZ3/target/scala-2.10/scalaz3_2.10-2.0.jar \ No newline at end of file diff --git a/unmanaged/common/cafebabe_2.10-1.2.jar b/unmanaged/common/cafebabe_2.10-1.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..4dc1806689a5932ddc8097afe769df62f2d5ffbb Binary files /dev/null and b/unmanaged/common/cafebabe_2.10-1.2.jar differ diff --git a/unmanaged/common/cafebabe_2.9.2-1.2.jar b/unmanaged/common/cafebabe_2.9.2-1.2.jar deleted file mode 100644 index 7fdd2eae06df631006abc992f29847c84198f9a4..0000000000000000000000000000000000000000 Binary files a/unmanaged/common/cafebabe_2.9.2-1.2.jar and /dev/null differ