From a541166ce051c16ce3a208166218179894cd5b29 Mon Sep 17 00:00:00 2001 From: Etienne Kneuss <colder@php.net> Date: Mon, 3 Mar 2014 12:36:55 +0100 Subject: [PATCH] Stabilize datagen, fix interrupts & parallel, fix array boxing --- build.sbt | 4 + .../java/leon/codegen/runtime/ArrayBox.java | 85 +++++++++++++++++++ .../scala/leon/codegen/CodeGeneration.scala | 17 +++- .../scala/leon/codegen/CompilationUnit.scala | 2 +- .../scala/leon/datagen/NaiveDataGen.scala | 5 ++ .../scala/leon/datagen/VanuatooDataGen.scala | 68 +++++++++++---- .../leon/evaluators/RecursiveEvaluator.scala | 2 +- .../frontends/scalac/CodeExtraction.scala | 8 +- .../scala/leon/purescala/PrettyPrinter.scala | 2 +- .../scala/leon/purescala/ScalaPrinter.scala | 2 +- src/main/scala/leon/purescala/TreeOps.scala | 8 +- src/main/scala/leon/purescala/Trees.scala | 2 +- .../scala/leon/purescala/TypeTreeOps.scala | 16 ++-- src/main/scala/leon/purescala/TypeTrees.scala | 28 +----- .../leon/solvers/EnumerationSolver.scala | 42 +++++---- .../solvers/combinators/PortfolioSolver.scala | 4 + .../leon/solvers/z3/AbstractZ3Solver.scala | 46 +++++----- .../condabd/SynthesizerExamples.scala | 2 +- .../insynth/leon/loader/PreLoader.scala | 4 +- .../leon/verification/AnalysisPhase.scala | 2 +- .../xlang/ImperativeCodeElimination.scala | 6 +- src/main/scala/leon/xlang/TreeOps.scala | 4 +- .../insynth/testutil/CommonDeclarations.scala | 2 +- .../test/condabd/refinement/FilterTest.scala | 10 +-- .../PureScalaVerificationRegression.scala | 1 + 25 files changed, 260 insertions(+), 112 deletions(-) create mode 100644 src/main/java/leon/codegen/runtime/ArrayBox.java diff --git a/build.sbt b/build.sbt index 3e3014e82..ba228dd81 100644 --- a/build.sbt +++ b/build.sbt @@ -37,6 +37,10 @@ logBuffered in Test := false testOptions in Test += Tests.Argument("-oD") +javaOptions in test += "-Xss32M" + +parallelExecution in Test := false + sourcesInBase in Compile := false // do not skip parent Eclipse project definition diff --git a/src/main/java/leon/codegen/runtime/ArrayBox.java b/src/main/java/leon/codegen/runtime/ArrayBox.java new file mode 100644 index 000000000..07f4bec8e --- /dev/null +++ b/src/main/java/leon/codegen/runtime/ArrayBox.java @@ -0,0 +1,85 @@ +/* Copyright 2009-2013 EPFL, Lausanne */ + +package leon.codegen.runtime; + +import java.util.Arrays; + +/** If someone wants to make it an efficient implementation of immutable + * sets, go ahead. */ +public final class ArrayBox { + private final Object[] obj1; + private final int[] obj2; + private final boolean[] obj3; + private final int mode; + + protected final Object[] arrayValue() { + return obj1; + } + + protected final int[] arrayValueI() { + return obj2; + } + + protected final boolean[] arrayValueZ() { + return obj3; + } + + public ArrayBox(Object[] array) { + obj1 = array; + obj2 = null; + obj3 = null; + mode = 1; + } + + public ArrayBox(int[] array) { + obj1 = null; + obj2 = array; + obj3 = null; + mode = 2; + } + + public ArrayBox(boolean[] array) { + obj1 = null; + obj2 = null; + obj3 = array; + mode = 3; + } + + @Override + public boolean equals(Object that) { + if(that == this) return true; + if(!(that instanceof ArrayBox)) return false; + + ArrayBox other = (ArrayBox)that; + + if (mode == 1) { + return (other.mode == 1) && Arrays.equals(this.obj1, other.obj1); + } else if (mode == 2) { + return (other.mode == 2) && Arrays.equals(this.obj2, other.obj2); + } else { + return (other.mode == 3) && Arrays.equals(this.obj3, other.obj3); + } + } + + @Override + public String toString() { + if (mode == 1) { + return Arrays.toString(obj1); + } else if (mode == 2) { + return Arrays.toString(obj2); + } else { + return Arrays.toString(obj3); + } + } + + @Override + public int hashCode() { + if (mode == 1) { + return Arrays.hashCode(obj1); + } else if (mode == 2) { + return Arrays.hashCode(obj2); + } else { + return Arrays.hashCode(obj3); + } + } +} diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala index d815a0549..0702fb7da 100644 --- a/src/main/scala/leon/codegen/CodeGeneration.scala +++ b/src/main/scala/leon/codegen/CodeGeneration.scala @@ -34,6 +34,8 @@ trait CodeGeneration { private[codegen] val BoxedIntClass = "java/lang/Integer" private[codegen] val BoxedBoolClass = "java/lang/Boolean" + private[codegen] val BoxedArrayClass = "leon/codegen/runtime/ArrayBox" + private[codegen] val TupleClass = "leon/codegen/runtime/Tuple" private[codegen] val SetClass = "leon/codegen/runtime/Set" private[codegen] val MapClass = "leon/codegen/runtime/Map" @@ -166,7 +168,7 @@ trait CodeGeneration { case BooleanLiteral(v) => ch << Ldc(if(v) 1 else 0) - case UnitLiteral => + case UnitLiteral() => ch << Ldc(1) // Case classes @@ -458,6 +460,11 @@ trait CodeGeneration { mkExpr(e, ch) ch << InvokeSpecial(BoxedBoolClass, constructorName, "(Z)V") + case at @ ArrayType(et) => + ch << New(BoxedArrayClass) << DUP + mkExpr(e, ch) + ch << InvokeSpecial(BoxedArrayClass, constructorName, "(%s)V".format(typeToJVM(at))) + case _ => mkExpr(e, ch) } @@ -473,7 +480,9 @@ trait CodeGeneration { case BooleanType | UnitType => ch << New(BoxedBoolClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedBoolClass, constructorName, "(Z)V") - case _ => + case at @ ArrayType(et) => + ch << New(BoxedArrayClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedArrayClass, constructorName, "(%s)V".format(typeToJVM(at))) + case _ => } } @@ -503,6 +512,10 @@ trait CodeGeneration { case tp : TypeParameter => + case tp : ArrayType => + ch << CheckCast(BoxedArrayClass) << InvokeVirtual(BoxedArrayClass, "arrayValue", "()%s".format(typeToJVM(tp))) + ch << CheckCast(typeToJVM(tp)) + case _ => throw new CompilationException("Unsupported type in unboxing : " + tpe) } diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala index 8993fdc48..0af4052a6 100644 --- a/src/main/scala/leon/codegen/CompilationUnit.scala +++ b/src/main/scala/leon/codegen/CompilationUnit.scala @@ -348,7 +348,7 @@ class CompilationUnit(val ctx: LeonContext, object CompilationUnit { private var _nextExprId = 0 - private def nextExprId = { + private def nextExprId = synchronized { _nextExprId += 1 _nextExprId } diff --git a/src/main/scala/leon/datagen/NaiveDataGen.scala b/src/main/scala/leon/datagen/NaiveDataGen.scala index 5bd33cb85..7be5b1075 100644 --- a/src/main/scala/leon/datagen/NaiveDataGen.scala +++ b/src/main/scala/leon/datagen/NaiveDataGen.scala @@ -55,6 +55,8 @@ class NaiveDataGen(ctx: LeonContext, p: Program, evaluator: Evaluator, _bounds : private def intStream : Stream[Expr] = Stream.cons(IntLiteral(0), intStream0(1)) private def intStream0(n : Int) : Stream[Expr] = Stream.cons(IntLiteral(n), intStream0(if(n > 0) -n else -(n-1))) + private def tpStream(tp: TypeParameter, i: Int = 1): Stream[Expr] = Stream.cons(GenericValue(tp, i), tpStream(tp, i+1)) + def natStream : Stream[Expr] = natStream0(0) private def natStream0(n : Int) : Stream[Expr] = Stream.cons(IntLiteral(n), natStream0(n+1)) @@ -77,6 +79,9 @@ class NaiveDataGen(ctx: LeonContext, p: Program, evaluator: Evaluator, _bounds : case Int32Type => intStream + case tp: TypeParameter => + tpStream(tp) + case TupleType(bses) => naryProduct(bses.map(generate(_, bounds))).map(Tuple) diff --git a/src/main/scala/leon/datagen/VanuatooDataGen.scala b/src/main/scala/leon/datagen/VanuatooDataGen.scala index e94415131..12f76a2a8 100644 --- a/src/main/scala/leon/datagen/VanuatooDataGen.scala +++ b/src/main/scala/leon/datagen/VanuatooDataGen.scala @@ -34,9 +34,7 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { ConstructorPattern[Expr, TypeTree](c, args) } - private var ccConstructors = Map[CaseClassType, Constructor[Expr, TypeTree]]() - private var acConstructors = Map[AbstractClassType, List[Constructor[Expr, TypeTree]]]() - private var tConstructors = Map[TupleType, Constructor[Expr, TypeTree]]() + private var constructors = Map[TypeTree, List[Constructor[Expr, TypeTree]]]() private def getConstructorFor(t: CaseClassType, act: AbstractClassType): Constructor[Expr, TypeTree] = { // We "up-cast" the returnType of the specific caseclass generator to match its superclass @@ -45,30 +43,66 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { private def getConstructors(t: TypeTree): List[Constructor[Expr, TypeTree]] = t match { + case UnitType => + constructors.getOrElse(t, { + val cs = List(Constructor[Expr, TypeTree](List(), t, s => UnitLiteral(), "()")) + constructors += t -> cs + cs + }) + + case at @ ArrayType(sub) => + constructors.getOrElse(at, { + val cs = for (size <- List(0, 1, 2, 5)) yield { + Constructor[Expr, TypeTree]((1 to size).map(i => sub).toList, at, s => FiniteArray(s).setType(at), at.toString+"@"+size) + } + constructors += at -> cs + cs + }) + case tt @ TupleType(parts) => - List(tConstructors.getOrElse(tt, { - val c = Constructor[Expr, TypeTree](parts, tt, s => Tuple(s).setType(tt), tt.toString) - tConstructors += tt -> c - c - })) + constructors.getOrElse(tt, { + val cs = List(Constructor[Expr, TypeTree](parts, tt, s => Tuple(s).setType(tt), tt.toString)) + constructors += tt -> cs + cs + }) + + case mt @ MapType(from, to) => + constructors.getOrElse(mt, { + val cs = for (size <- List(0, 1, 2, 5)) yield { + val subs = (1 to size).flatMap(i => List(from, to)).toList + + Constructor[Expr, TypeTree](subs, mt, s => FiniteMap(s.grouped(2).map(t => (t(0), t(1))).toSeq).setType(mt), mt.toString+"@"+size) + } + constructors += mt -> cs + cs + }) + + case tp: TypeParameter => + constructors.getOrElse(tp, { + val cs = for (i <- List(1, 2)) yield { + Constructor[Expr, TypeTree](List(), tp, s => GenericValue(tp, i), tp.id+"#"+i) + } + constructors += tp -> cs + cs + }) case act: AbstractClassType => - acConstructors.getOrElse(act, { + constructors.getOrElse(act, { val cs = act.knownCCDescendents.map { cct => getConstructorFor(cct, act) }.toList - acConstructors += act -> cs + constructors += act -> cs cs }) case cct: CaseClassType => - List(ccConstructors.getOrElse(cct, { - val c = Constructor[Expr, TypeTree](cct.fieldsTypes, cct, s => CaseClass(cct, s), cct.id.name) - ccConstructors += cct -> c + constructors.getOrElse(cct, { + val c = List(Constructor[Expr, TypeTree](cct.fieldsTypes, cct, s => CaseClass(cct, s), cct.id.name)) + constructors += cct -> c c - })) + }) case _ => ctx.reporter.error("Unknown type to generate constructor for: "+t) @@ -128,8 +162,10 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { (ConstructorPattern(c, elems.map(_._1)), elems.forall(_._2)) - case _ => - sys.error("Unsupported value, can't paternify : "+v+" : "+expType) + case (gv: GenericValue, t: TypeParameter) => + (cPattern(getConstructors(t)(gv.id-1), List()), true) + case (v, t) => + sys.error("Unsupported value, can't paternify : "+v+" ("+v.getClass+") : "+t) } type InstrumentedResult = (EvaluationResults.Result, Option[vanuatoo.Pattern[Expr, TypeTree]]) diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala index 748056d58..7432e33b3 100644 --- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala +++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala @@ -299,7 +299,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program) extends Evalu case f @ FiniteSet(els) => FiniteSet(els.map(se(_)).distinct).setType(f.getType) case i @ IntLiteral(_) => i case b @ BooleanLiteral(_) => b - case u @ UnitLiteral => u + case u @ UnitLiteral() => u case f @ ArrayFill(length, default) => { val rDefault = se(default) diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala index 523a487f3..7dad7128b 100644 --- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala +++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala @@ -740,7 +740,7 @@ trait CodeExtraction extends ASTExtractors { val nctx = dctx.withNewVar(vs -> (() => Variable(newID))) extractTree(rst)(nctx) } - case None => UnitLiteral + case None => UnitLiteral() } rest = None @@ -764,7 +764,7 @@ trait CodeExtraction extends ASTExtractors { val restTree = rest match { case Some(rst) => extractTree(rst) - case None => UnitLiteral + case None => UnitLiteral() } rest = None LetDef(funDefWithBody, restTree) @@ -793,7 +793,7 @@ trait CodeExtraction extends ASTExtractors { val nctx = dctx.withNewVar(nv).withNewMutableVar(nv) extractTree(rst)(nctx) } - case None => UnitLiteral + case None => UnitLiteral() } rest = None @@ -873,7 +873,7 @@ trait CodeExtraction extends ASTExtractors { BooleanLiteral(v) case ExUnitLiteral() => - UnitLiteral + UnitLiteral() case ExLocally(body) => extractTree(body) diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index d57b1c58a..9e07420a2 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -116,7 +116,7 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe case IntLiteral(v) => sb.append(v) case BooleanLiteral(v) => sb.append(v) case StringLiteral(s) => sb.append("\"" + s + "\"") - case UnitLiteral => sb.append("()") + case UnitLiteral() => sb.append("()") case GenericValue(tp, id) => pp(tp, p) sb.append("#"+id) diff --git a/src/main/scala/leon/purescala/ScalaPrinter.scala b/src/main/scala/leon/purescala/ScalaPrinter.scala index bbab14678..660c60c12 100644 --- a/src/main/scala/leon/purescala/ScalaPrinter.scala +++ b/src/main/scala/leon/purescala/ScalaPrinter.scala @@ -100,7 +100,7 @@ class ScalaPrinter(opts: PrinterOptions, sb: StringBuffer = new StringBuffer) ex case IntLiteral(v) => sb.append(v) case BooleanLiteral(v) => sb.append(v) case StringLiteral(s) => sb.append("\"" + s + "\"") - case UnitLiteral => sb.append("()") + case UnitLiteral() => sb.append("()") /* These two aren't really supported in Scala, but we know how to encode them. */ case Implies(l,r) => pp(Or(Not(l), r), p) diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala index 54a634bb1..86f33d7b2 100644 --- a/src/main/scala/leon/purescala/TreeOps.scala +++ b/src/main/scala/leon/purescala/TreeOps.scala @@ -628,7 +628,7 @@ object TreeOps { (realCond, newRhs) } - val bigIte = condsAndRhs.foldRight[Expr](Error("non-exhaustive match").setType(bestRealType(m.getType)).setPos(m))((p1, ex) => { + val bigIte = condsAndRhs.foldRight[Expr](Error("non-exhaustive match").copiedFrom(m))((p1, ex) => { if(p1._1 == BooleanLiteral(true)) { p1._2 } else { @@ -1153,6 +1153,8 @@ object TreeOps { } else { None } + case ft : FunctionType => None // FIXME + case a : AbstractClassType => None case c : CaseClassType => // This is really just one big assertion. We don't rewrite class defs. @@ -1166,7 +1168,7 @@ object TreeOps { } else { None } - case Untyped | AnyType | BottomType | BooleanType | Int32Type | UnitType => None + case Untyped | AnyType | BottomType | BooleanType | Int32Type | UnitType | TypeParameter(_) => None } var idMap = Map[Identifier, Identifier]() @@ -1200,7 +1202,7 @@ object TreeOps { } def pre(e : Expr) : Expr = e match { - case Tuple(Seq()) => UnitLiteral + case Tuple(Seq()) => UnitLiteral() case Variable(id) if idMap contains id => Variable(idMap(id)) case Tuple(Seq(s)) => pre(s) diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala index 76f573553..6cdb61b81 100644 --- a/src/main/scala/leon/purescala/Trees.scala +++ b/src/main/scala/leon/purescala/Trees.scala @@ -416,7 +416,7 @@ object Trees { } case class StringLiteral(value: String) extends Literal[String] - case object UnitLiteral extends Literal[Unit] with FixedType { + case class UnitLiteral() extends Literal[Unit] with FixedType { val fixedType = UnitType val value = () } diff --git a/src/main/scala/leon/purescala/TypeTreeOps.scala b/src/main/scala/leon/purescala/TypeTreeOps.scala index 75d9e9d8f..cb0dd2044 100644 --- a/src/main/scala/leon/purescala/TypeTreeOps.scala +++ b/src/main/scala/leon/purescala/TypeTreeOps.scala @@ -23,13 +23,16 @@ object TypeTreeOps { } def bestRealType(t: TypeTree) : TypeTree = t match { - case c: ClassType if c.classDef.isInstanceOf[CaseClassDef] => { + case c: CaseClassType => c.classDef.parent match { - case None => CaseClassType(c.classDef.asInstanceOf[CaseClassDef], c.tps) - case Some(p) => instantiateType(p, (c.classDef.tparams zip c.tps).toMap) + case None => + c + + case Some(p) => + instantiateType(p, (c.classDef.tparams zip c.tps).toMap) } - } - case other => other + + case NAryType(tps, builder) => builder(tps.map(bestRealType)) } def leastUpperBound(t1: TypeTree, t2: TypeTree): Option[TypeTree] = (t1,t2) match { @@ -181,6 +184,9 @@ object TypeTreeOps { val newOb = ob.map(id => freshId(id, expTpe)) (WildcardPattern(newOb), (ob zip newOb).toMap) + + case _ => + sys.error("woot!?") } MatchExpr(srec(e), cases.map(trCase)).copiedFrom(m) diff --git a/src/main/scala/leon/purescala/TypeTrees.scala b/src/main/scala/leon/purescala/TypeTrees.scala index 58c90f882..fbf266b0c 100644 --- a/src/main/scala/leon/purescala/TypeTrees.scala +++ b/src/main/scala/leon/purescala/TypeTrees.scala @@ -65,6 +65,7 @@ object TypeTrees { case Int32Type => InfiniteSize case ListType(_) => InfiniteSize case ArrayType(_) => InfiniteSize + case TypeParameter(_) => InfiniteSize case TupleType(bases) => { val baseSizes = bases.map(domainSize(_)) baseSizes.find(_ == InfiniteSize) match { @@ -104,32 +105,10 @@ object TypeTrees { case class TypeParameter(id: Identifier) extends TypeTree - class TupleType private (val bases: Seq[TypeTree]) extends TypeTree { + case class TupleType(val bases: Seq[TypeTree]) extends TypeTree { lazy val dimension: Int = bases.length - - override def equals(other: Any): Boolean = { - other match { - case (t: TupleType) => t.bases == bases - case _ => false - } - } - - override def hashCode: Int = { - bases.foldLeft(42)((acc, t) => acc + t.hashCode) - } - - } - object TupleType { - def apply(bases: Seq[TypeTree]): TupleType = { - new TupleType(bases.map(bestRealType(_))) - } - //TODO: figure out which of the two unapply is better - //def unapply(t: TypeTree): Option[Seq[TypeTree]] = t match { - // case (tt: TupleType) => Some(tt.bases) - // case _ => None - //} - def unapply(tt: TupleType): Option[Seq[TypeTree]] = if(tt == null) None else Some(tt.bases) } + object TupleOneType { def unapply(tt : TupleType) : Option[TypeTree] = if(tt == null) None else { if(tt.bases.size == 1) { @@ -204,7 +183,6 @@ object TypeTrees { case TupleType(ts) => Some((ts, TupleType(_))) case ListType(t) => Some((Seq(t), ts => ListType(ts.head))) case ArrayType(t) => Some((Seq(t), ts => ArrayType(ts.head))) - case TupleType(ts) => Some((ts, TupleType(_))) case SetType(t) => Some((Seq(t), ts => SetType(ts.head))) case MultisetType(t) => Some((Seq(t), ts => MultisetType(ts.head))) case MapType(from,to) => Some((Seq(from, to), t => MapType(t(0), t(1)))) diff --git a/src/main/scala/leon/solvers/EnumerationSolver.scala b/src/main/scala/leon/solvers/EnumerationSolver.scala index 4f5d71659..3730fb45a 100644 --- a/src/main/scala/leon/solvers/EnumerationSolver.scala +++ b/src/main/scala/leon/solvers/EnumerationSolver.scala @@ -19,13 +19,15 @@ class EnumerationSolver(val context: LeonContext, val program: Program) extends val maxTried = 10000; - var datagen: DataGenerator = _ + var datagen: Option[DataGenerator] = None + + private var interrupted = false; var freeVars = List[Identifier]() var constraints = List[Expr]() def assertCnstr(expression: Expr): Unit = { - constraints ::= expression + constraints = constraints :+ expression val newFreeVars = (variablesOf(expression) -- freeVars).toList freeVars = freeVars ::: newFreeVars @@ -34,25 +36,29 @@ class EnumerationSolver(val context: LeonContext, val program: Program) extends private var modelMap = Map[Identifier, Expr]() def check: Option[Boolean] = { - try { - val muteContext = context.copy(reporter = new DefaultReporter(context.settings)) - datagen = new VanuatooDataGen(muteContext, program) - - modelMap = Map() + val res = try { + datagen = Some(new VanuatooDataGen(context, program)) + if (interrupted) { + None + } else { + modelMap = Map() - val it = datagen.generateFor(freeVars, And(constraints.reverse), 1, maxTried) + val it = datagen.get.generateFor(freeVars, And(constraints), 1, maxTried) - if (it.hasNext) { - val model = it.next - modelMap = (freeVars zip model).toMap - Some(true) - } else { - None + if (it.hasNext) { + val model = it.next + modelMap = (freeVars zip model).toMap + Some(true) + } else { + None + } } } catch { case e: codegen.CompilationException => None } + datagen = None + res } def getModel: Map[Identifier, Expr] = { @@ -64,10 +70,14 @@ class EnumerationSolver(val context: LeonContext, val program: Program) extends } def interrupt(): Unit = { - Option(datagen).foreach(_.interrupt) + interrupted = true; + + datagen.foreach{ s => + s.interrupt + } } def recoverInterrupt(): Unit = { - Option(datagen).foreach(_.recoverInterrupt) + datagen.foreach(_.recoverInterrupt) } } diff --git a/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala b/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala index 1c75bf3b8..246ea430c 100644 --- a/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala +++ b/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala @@ -55,12 +55,16 @@ class PortfolioSolver(val context: LeonContext, solvers: Seq[SolverFactory[Solve val res = Await.result(result, 10.days) match { case Some((s, r, m)) => modelMap = m + context.reporter.debug("Solved with "+s.name) solversInsts.foreach(_.interrupt) r case None => None } + // Block until all solvers finished + Await.result(Future.fold(fs)(0){ (i, r) => i+1 }, 10.days); + solversInsts.foreach(_.free) res diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala index 20d447ed5..d0b52e283 100644 --- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala +++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala @@ -381,22 +381,26 @@ trait AbstractZ3Solver reverseADTFieldSelectors = Map.empty } + def normalizeType(t: TypeTree): TypeTree = { + bestRealType(t) + } + // assumes prepareSorts has been called.... - protected[leon] def typeToSort(tt: TypeTree): Z3Sort = tt match { + protected[leon] def typeToSort(oldtt: TypeTree): Z3Sort = normalizeType(oldtt) match { case Int32Type | BooleanType | UnitType => - sorts.toZ3(tt) + sorts.toZ3(oldtt) case act: AbstractClassType => - sorts.toZ3OrCompute(rootType(act)) { - declareADTSort(rootType(act)) + sorts.toZ3OrCompute(act) { + declareADTSort(act) } case cct: CaseClassType => - sorts.toZ3OrCompute(rootType(cct)) { - declareADTSort(rootType(cct)) + sorts.toZ3OrCompute(cct) { + declareADTSort(cct) } - case SetType(base) => + case tt @ SetType(base) => sorts.toZ3OrCompute(tt) { val newSetSort = z3.mkSetSort(typeToSort(base)) @@ -406,7 +410,7 @@ trait AbstractZ3Solver newSetSort } - case MapType(fromType, toType) => + case tt @ MapType(fromType, toType) => sorts.toZ3OrCompute(tt) { val fromSort = typeToSort(fromType) val toSort = mapRangeSort(toType) @@ -414,7 +418,7 @@ trait AbstractZ3Solver z3.mkArraySort(fromSort, toSort) } - case ArrayType(base) => + case tt @ ArrayType(base) => sorts.toZ3OrCompute(tt) { val intSort = typeToSort(Int32Type) val toSort = typeToSort(base) @@ -426,7 +430,7 @@ trait AbstractZ3Solver ats } - case TupleType(tpes) => + case tt @ TupleType(tpes) => sorts.toZ3OrCompute(tt) { val tpesSorts = tpes.map(typeToSort) val sortSymbol = z3.mkFreshStringSymbol("Tuple") @@ -437,7 +441,7 @@ trait AbstractZ3Solver tupleSort } - case TypeParameter(id) => + case tt @ TypeParameter(id) => sorts.toZ3OrCompute(tt) { val symbol = z3.mkFreshStringSymbol(id.name) val newTPSort = z3.mkUninterpretedSort(symbol) @@ -470,13 +474,13 @@ trait AbstractZ3Solver def rec(ex: Expr): Z3AST = ex match { case tu @ Tuple(args) => typeToSort(tu.getType) // Make sure we generate sort & meta info - val meta = tupleMetaDecls(tu.getType) + val meta = tupleMetaDecls(normalizeType(tu.getType)) meta.cons(args.map(rec(_)): _*) case ts @ TupleSelect(tu, i) => typeToSort(tu.getType) // Make sure we generate sort & meta info - val meta = tupleMetaDecls(tu.getType) + val meta = tupleMetaDecls(normalizeType(tu.getType)) meta.selects(i-1)(rec(tu)) @@ -519,7 +523,7 @@ trait AbstractZ3Solver case Not(e) => z3.mkNot(rec(e)) case IntLiteral(v) => z3.mkInt(v, typeToSort(Int32Type)) case BooleanLiteral(v) => if (v) z3.mkTrue() else z3.mkFalse() - case UnitLiteral => unitValue + case UnitLiteral() => unitValue case Equals(l, r) => z3.mkEq(rec( l ), rec( r ) ) case Plus(l, r) => z3.mkAdd(rec(l), rec(r)) case Minus(l, r) => z3.mkSub(rec(l), rec(r)) @@ -593,7 +597,7 @@ trait AbstractZ3Solver case fill @ ArrayFill(length, default) => val at @ ArrayType(base) = fill.getType typeToSort(at) - val meta = arrayMetaDecls(at) + val meta = arrayMetaDecls(normalizeType(at)) val ar = z3.mkConstArray(typeToSort(base), rec(default)) val res = meta.cons(ar, rec(length)) @@ -602,14 +606,14 @@ trait AbstractZ3Solver case ArraySelect(a, index) => typeToSort(a.getType) val ar = rec(a) - val getArray = arrayMetaDecls(a.getType).select + val getArray = arrayMetaDecls(normalizeType(a.getType)).select val res = z3.mkSelect(getArray(ar), rec(index)) res case ArrayUpdated(a, index, newVal) => typeToSort(a.getType) val ar = rec(a) - val meta = arrayMetaDecls(a.getType) + val meta = arrayMetaDecls(normalizeType(a.getType)) val store = z3.mkStore(meta.select(ar), rec(index), rec(newVal)) val res = meta.cons(store, meta.length(ar)) @@ -618,7 +622,7 @@ trait AbstractZ3Solver case ArrayLength(a) => typeToSort(a.getType) val ar = rec(a) - val meta = arrayMetaDecls(a.getType) + val meta = arrayMetaDecls(normalizeType(a.getType)) val res = meta.length(ar) res @@ -685,7 +689,7 @@ trait AbstractZ3Solver val rargs = args.map(rec) Tuple(rargs) - case LeonType(ArrayType(dt)) => + case LeonType(at @ ArrayType(dt)) => assert(args.size == 2) val IntLiteral(length) = rec(args(1)) model.getArrayValue(args(0)) match { @@ -699,7 +703,7 @@ trait AbstractZ3Solver FiniteArray(for (i <- 1 to length) yield { valuesMap.getOrElse(i, elseValue) - }) + }).setType(at) } case LeonType(tpe @ MapType(kt, vt)) => @@ -723,7 +727,7 @@ trait AbstractZ3Solver } case LeonType(UnitType) => - UnitLiteral + UnitLiteral() case _ => import Z3DeclKind._ diff --git a/src/main/scala/leon/synthesis/condabd/SynthesizerExamples.scala b/src/main/scala/leon/synthesis/condabd/SynthesizerExamples.scala index 7b8ecc0b8..0aec55e20 100755 --- a/src/main/scala/leon/synthesis/condabd/SynthesizerExamples.scala +++ b/src/main/scala/leon/synthesis/condabd/SynthesizerExamples.scala @@ -167,7 +167,7 @@ class SynthesizerForRuleExamples( info("####################################") info("# precondition is: " + tfd.precondition.getOrElse(BooleanLiteral(true))) info("# accumulatingCondition is: " + accumulatingCondition) - info("# accumulatingExpression(Unit) is: " + accumulatingExpression(UnitLiteral)) + info("# accumulatingExpression(Unit) is: " + accumulatingExpression(UnitLiteral())) info("####################################") interactivePause diff --git a/src/main/scala/leon/synthesis/condabd/insynth/leon/loader/PreLoader.scala b/src/main/scala/leon/synthesis/condabd/insynth/leon/loader/PreLoader.scala index 47223b5a9..7b92e5f7b 100644 --- a/src/main/scala/leon/synthesis/condabd/insynth/leon/loader/PreLoader.scala +++ b/src/main/scala/leon/synthesis/condabd/insynth/leon/loader/PreLoader.scala @@ -250,7 +250,7 @@ object PreLoader extends ( (Boolean) => List[Declaration] ) { ) // case u @ UnitLiteral => u list += makeLiteral( - IE( "UnitLit", UnitLiteral ), + IE( "UnitLit", UnitLiteral() ), UnitType ) @@ -269,4 +269,4 @@ object PreLoader extends ( (Boolean) => List[Declaration] ) { def makeNAE( name: String, fun: List[Expr]=>Expr ): NAE = NAE( name, fun ) -} \ No newline at end of file +} diff --git a/src/main/scala/leon/verification/AnalysisPhase.scala b/src/main/scala/leon/verification/AnalysisPhase.scala index 25ec22efc..aa24c61b0 100644 --- a/src/main/scala/leon/verification/AnalysisPhase.scala +++ b/src/main/scala/leon/verification/AnalysisPhase.scala @@ -103,7 +103,7 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] { val s = solverFactory.getNewSolver try { - reporter.debug("Trying with solver: " + s.name) + reporter.debug("Solving with: " + s.name) val t1 = System.nanoTime s.assertCnstr(Not(vc)) diff --git a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala index 397744e10..96b66dbe6 100644 --- a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala +++ b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala @@ -57,7 +57,7 @@ object ImperativeCodeElimination extends LeonPhase[Program, (Program, Set[FunDef val newId = FreshIdentifier(id.name).copiedFrom(id) val (rhsVal, rhsScope, rhsFun) = toFunction(e) val scope = (body: Expr) => rhsScope(Let(newId, rhsVal, body).copiedFrom(expr)) - (UnitLiteral, scope, rhsFun + (id -> newId)) + (UnitLiteral(), scope, rhsFun + (id -> newId)) } case ite@IfExpr(cond, tExpr, eExpr) => { @@ -150,7 +150,7 @@ object ImperativeCodeElimination extends LeonPhase[Program, (Program, Set[FunDef val modifiedVars: Seq[Identifier] = condBodyFun.keys.toSet.intersect(varInScope).toSeq if(modifiedVars.isEmpty) - (UnitLiteral, (b: Expr) => b, Map()) + (UnitLiteral(), (b: Expr) => b, Map()) else { val whileFunVars = modifiedVars.map(id => FreshIdentifier(id.name).setType(id.getType)) val modifiedVars2WhileFunVars = modifiedVars.zip(whileFunVars).toMap @@ -210,7 +210,7 @@ object ImperativeCodeElimination extends LeonPhase[Program, (Program, Set[FunDef b)))) }) - (UnitLiteral, finalScope, modifiedVars.zip(finalVars).toMap) + (UnitLiteral(), finalScope, modifiedVars.zip(finalVars).toMap) } } diff --git a/src/main/scala/leon/xlang/TreeOps.scala b/src/main/scala/leon/xlang/TreeOps.scala index 8da89fc6d..fef1d95e3 100644 --- a/src/main/scala/leon/xlang/TreeOps.scala +++ b/src/main/scala/leon/xlang/TreeOps.scala @@ -40,11 +40,11 @@ object TreeOps { case Block(exprs, last) => val nexprs = (exprs :+ last).flatMap{ case Block(es2, el) => es2 :+ el - case UnitLiteral => Seq() + case UnitLiteral() => Seq() case e2 => Seq(e2) } Some(nexprs match { - case Seq() => UnitLiteral + case Seq() => UnitLiteral() case Seq(e) => e case es => Block(es.init, es.last).setType(es.last.getType) }) diff --git a/src/test/scala/leon/test/condabd/insynth/testutil/CommonDeclarations.scala b/src/test/scala/leon/test/condabd/insynth/testutil/CommonDeclarations.scala index befa9a141..2d721e38b 100644 --- a/src/test/scala/leon/test/condabd/insynth/testutil/CommonDeclarations.scala +++ b/src/test/scala/leon/test/condabd/insynth/testutil/CommonDeclarations.scala @@ -30,7 +30,7 @@ object CommonDeclarations { Int32Type ) - val unit = UnitLiteral + val unit = UnitLiteral() val unitDeclaration = makeDeclaration( ImmediateExpression("unit", unit), diff --git a/src/test/scala/leon/test/condabd/refinement/FilterTest.scala b/src/test/scala/leon/test/condabd/refinement/FilterTest.scala index baf08e6c6..2c1467ec5 100644 --- a/src/test/scala/leon/test/condabd/refinement/FilterTest.scala +++ b/src/test/scala/leon/test/condabd/refinement/FilterTest.scala @@ -60,7 +60,7 @@ class FilterTest extends JUnitSuite { tail = loader.extractFields.find { _.expression match { - case ure: UnaryReconstructionExpression => ure(UnitLiteral).toString.contains(".tail") + case ure: UnaryReconstructionExpression => ure(UnitLiteral()).toString.contains(".tail") case _ => false } } match { @@ -71,7 +71,7 @@ class FilterTest extends JUnitSuite { head = loader.extractFields.find { _.expression match { - case ure: UnaryReconstructionExpression => ure(UnitLiteral).toString.contains(".head") + case ure: UnaryReconstructionExpression => ure(UnitLiteral()).toString.contains(".head") case _ => false } } match { @@ -82,7 +82,7 @@ class FilterTest extends JUnitSuite { cons = loader.extractCaseClasses.find { _.expression match { - case nre: NaryReconstructionExpression => nre(List(UnitLiteral, UnitLiteral)).toString.contains("Cons") + case nre: NaryReconstructionExpression => nre(List(UnitLiteral(), UnitLiteral())).toString.contains("Cons") case _ => false } } match { @@ -114,8 +114,8 @@ class FilterTest extends JUnitSuite { val variable1 = tfunDef.params.head val variable2 = tfunDef.params(1) - assertEquals(+1, isLess(cons(List(UnitLiteral, variable1.toVariable)), variable1.id)) - assertEquals(+1, isLess(cons(List(UnitLiteral, variable1.toVariable)), variable2.id)) + assertEquals(+1, isLess(cons(List(UnitLiteral(), variable1.toVariable)), variable1.id)) + assertEquals(+1, isLess(cons(List(UnitLiteral(), variable1.toVariable)), variable2.id)) assertEquals(-1, isLess(tail(variable1.toVariable), variable1.id)) assertEquals(+1, isLess(head(variable1.toVariable), variable1.id)) assertEquals(0, isLess(variable1.toVariable, variable1.id)) diff --git a/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala b/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala index de6acd0f1..d65e875fb 100644 --- a/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala +++ b/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala @@ -61,6 +61,7 @@ class PureScalaVerificationRegression extends LeonTestSuite { for(f <- fs) { mkTest(f, List(LeonFlagOption("feelinglucky", true)), forError)(block) mkTest(f, List(LeonFlagOption("codegen", true), LeonFlagOption("evalground", true), LeonFlagOption("feelinglucky", true)), forError)(block) + mkTest(f, List(LeonValueOption("solvers", "fairz3,enum"), LeonFlagOption("codegen", true), LeonFlagOption("evalground", true), LeonFlagOption("feelinglucky", true)), forError)(block) } } -- GitLab