From d1592f3253551cc8e2e139b3186445cc476c6ab1 Mon Sep 17 00:00:00 2001 From: Philippe Suter <philippe.suter@gmail.com> Date: Wed, 12 Dec 2012 00:34:54 +0100 Subject: [PATCH] Generalization of Evaluators, and CodeGenEvaluator. Evaluators now have a common interface, and need to be instantiated before they can be used. This makes them more like solvers, and allows us to switch between them completely transparently. Evaluators should support `eval` and `compile`. The default implementation for `compile` returns a closure that invokes `eval` each time. `eval` returns one of three results: - EvaluationSuccessful: evaluation terminated with a value - EvaluationFailure: evaluation resulted in a runtime error - EvaluationError: evaluation resulted in an internal error CodeGenEvaluator is a drop-in substitute for DefaultEvaluator. It works by compiling Leon methods to Java bytecode which is loaded dynamically. The `compile` method should be used as much as possible, as `eval` will recompile the expression each time (the functions from the Leon program are always compiled only once, though). CodeGenEvaluator intercepts most runtime errors and rewrites them into `EvaluationFailure` results. Use --codegen to use code generation as the evaluator of choice within FairZ3Solver. (Has no effect if neither --feelinglucky nor --checkmodels is used.) Improvements of EvaluatorsTests testing suite, and verification regression suite is now run twice (with different options). As a result, the original tests for codegen are obsolete. --- .../java/leon/codegen/runtime/CaseClass.java | 4 +- src/main/java/leon/codegen/runtime/Map.java | 62 +++- src/main/java/leon/codegen/runtime/Set.java | 31 +- src/main/scala/leon/LeonOption.scala | 7 +- .../scala/leon/codegen/CodeGeneration.scala | 118 +++++- .../scala/leon/codegen/CompilationUnit.scala | 48 ++- .../leon/codegen/CompiledExpression.scala | 21 +- .../leon/evaluators/CodeGenEvaluator.scala | 51 +++ .../DefaultEvaluator.scala} | 157 ++++---- .../scala/leon/evaluators/Evaluator.scala | 40 ++ .../scala/leon/purescala/Definitions.scala | 11 + .../scala/leon/solvers/ParallelSolver.scala | 2 - .../scala/leon/solvers/RandomSolver.scala | 34 +- .../scala/leon/solvers/z3/FairZ3Solver.scala | 91 +++-- .../leon/synthesis/LinearEquations.scala | 22 +- .../regression/codegen/Prog001.scala | 18 - .../regression/codegen/Prog002.scala | 14 - .../regression/codegen/Prog003.scala | 14 - .../regression/codegen/Prog004.scala | 17 - src/test/resources/regression/codegen/README | 2 - .../leon/test/codegen/CodeGenEvaluation.scala | 191 ---------- .../leon/test/codegen/CodeGenRegression.scala | 71 ---- .../test/evaluators/EvaluatorsTests.scala | 347 ++++++++++++++++++ .../scala/leon/test/purescala/LikelyEq.scala | 31 +- .../leon/test/purescala/LikelyEqSuite.scala | 4 +- .../leon/test/purescala/TreeOpsTests.scala | 7 +- .../test/solvers/TimeoutSolverTests.scala | 7 +- .../test/synthesis/LinearEquationsSuite.scala | 1 - .../PureScalaVerificationRegression.scala | 9 +- unmanaged/common/cafebabe_2.9.2-1.2.jar | Bin 499960 -> 502331 bytes 30 files changed, 875 insertions(+), 557 deletions(-) create mode 100644 src/main/scala/leon/evaluators/CodeGenEvaluator.scala rename src/main/scala/leon/{Evaluator.scala => evaluators/DefaultEvaluator.scala} (63%) create mode 100644 src/main/scala/leon/evaluators/Evaluator.scala delete mode 100644 src/test/resources/regression/codegen/Prog001.scala delete mode 100644 src/test/resources/regression/codegen/Prog002.scala delete mode 100644 src/test/resources/regression/codegen/Prog003.scala delete mode 100644 src/test/resources/regression/codegen/Prog004.scala delete mode 100644 src/test/resources/regression/codegen/README delete mode 100644 src/test/scala/leon/test/codegen/CodeGenEvaluation.scala delete mode 100644 src/test/scala/leon/test/codegen/CodeGenRegression.scala create mode 100644 src/test/scala/leon/test/evaluators/EvaluatorsTests.scala diff --git a/src/main/java/leon/codegen/runtime/CaseClass.java b/src/main/java/leon/codegen/runtime/CaseClass.java index ea27c7853..bbbdb92f8 100644 --- a/src/main/java/leon/codegen/runtime/CaseClass.java +++ b/src/main/java/leon/codegen/runtime/CaseClass.java @@ -1,5 +1,7 @@ package leon.codegen.runtime; public interface CaseClass { - public abstract Object[] productElements(); + public abstract Object[] productElements(); + + public abstract String productName(); } diff --git a/src/main/java/leon/codegen/runtime/Map.java b/src/main/java/leon/codegen/runtime/Map.java index b82ba05c9..0bdb221c1 100644 --- a/src/main/java/leon/codegen/runtime/Map.java +++ b/src/main/java/leon/codegen/runtime/Map.java @@ -1,10 +1,11 @@ package leon.codegen.runtime; import java.util.Arrays; +import java.util.Iterator; import java.util.TreeMap; /** If someone wants to make it an efficient implementation of immutable - * sets, go ahead. */ + * maps, go ahead. */ public final class Map { private final TreeMap<Object,Object> _underlying; @@ -16,22 +17,25 @@ public final class Map { _underlying = new TreeMap<Object,Object>(); } - // For Maps, it's simpler to build them by starting with empty and putting - // the elements in. + private Map(TreeMap<Object,Object> u) { + _underlying = u; + } + + // Uses mutation! Useful at building time. public void add(Object key, Object value) { _underlying.put(key, value); } - private Map(TreeMap<Object,Object> u) { - _underlying = u; + public Iterator<java.util.Map.Entry<Object,Object>> getElements() { + return _underlying.entrySet().iterator(); } public boolean isDefinedAt(Object element) { - return underlying().containsKey(element); + return _underlying.containsKey(element); } public Object get(Object k) throws LeonCodeGenRuntimeException { - Object result = underlying().get(k); + Object result = _underlying.get(k); if(result == null) { throw new LeonCodeGenRuntimeException("Get of undefined key."); } @@ -39,12 +43,52 @@ public final class Map { } public int size() { - return underlying().size(); + return _underlying.size(); } public Map union(Map s) { - TreeMap<Object,Object> n = new TreeMap<Object,Object>(underlying()); + TreeMap<Object,Object> n = new TreeMap<Object,Object>(_underlying); n.putAll(s.underlying()); return new Map(n); } + + @Override + public boolean equals(Object that) { + if(that == this) return true; + if(!(that instanceof Map)) return false; + + Map other = (Map)that; + + if(this.size() != other.size()) return false; + + for(java.util.Map.Entry<Object,Object> entry : _underlying.entrySet()) { + Object there = other.underlying().get(entry.getKey()); + if(there == null || !entry.getValue().equals(there)) return false; + } + + return true; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Map("); + boolean first = true; + for(java.util.Map.Entry<Object,Object> entry : _underlying.entrySet()) { + if(!first) { + sb.append(", "); + first = false; + } + sb.append(entry.getKey().toString()); + sb.append(" -> "); + sb.append(entry.getValue().toString()); + } + sb.append(")"); + return sb.toString(); + } + + @Override + public int hashCode() { + return _underlying.hashCode(); + } } diff --git a/src/main/java/leon/codegen/runtime/Set.java b/src/main/java/leon/codegen/runtime/Set.java index f882fdf3b..b38ba9070 100644 --- a/src/main/java/leon/codegen/runtime/Set.java +++ b/src/main/java/leon/codegen/runtime/Set.java @@ -21,7 +21,7 @@ public final class Set { _underlying = new TreeSet<Object>(Arrays.asList(elements)); } - // Uses mutation! + // Uses mutation! Useful at building time. public void add(Object e) { _underlying.add(e); } @@ -52,7 +52,7 @@ public final class Set { } public Set union(Set s) { - TreeSet<Object> n = new TreeSet<Object>(underlying()); + TreeSet<Object> n = new TreeSet<Object>(_underlying); n.addAll(s.underlying()); return new Set(n); } @@ -79,7 +79,32 @@ public final class Set { public boolean equals(Object that) { if(that == this) return true; if(!(that instanceof Set)) return false; + Set other = (Set)that; - return this.subsetOf(other) && other.subsetOf(this); + + if(this.size() != other.size()) return false; + + return this.subsetOf(other); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Set("); + boolean first = true; + for(Object o : _underlying) { + if(!first) { + sb.append(", "); + first = false; + } + sb.append(o.toString()); + } + sb.append(")"); + return sb.toString(); + } + + @Override + public int hashCode() { + return _underlying.hashCode(); } } diff --git a/src/main/scala/leon/LeonOption.scala b/src/main/scala/leon/LeonOption.scala index 1ad3cb99b..40cd6c23f 100644 --- a/src/main/scala/leon/LeonOption.scala +++ b/src/main/scala/leon/LeonOption.scala @@ -6,7 +6,10 @@ sealed abstract class LeonOption { } /** Boolean (on/off) options. Present means "on". */ -case class LeonFlagOption(name: String) extends LeonOption +case class LeonFlagOption(name: String) extends LeonOption { + override def toString() : String = "--" + name +} + /** Options of the form --option=value. */ case class LeonValueOption(name: String, value: String) extends LeonOption { def splitList : Seq[String] = value.split(':').map(_.trim).filter(!_.isEmpty) @@ -18,6 +21,8 @@ case class LeonValueOption(name: String, value: String) extends LeonOption { ctx.reporter.error("Option --%s takes an integer as value.".format(name)) None } + + override def toString() : String = "--%s=%s".format(name, value) } sealed abstract class LeonOptionDef { diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala index 6ccb05f24..03f4222cd 100644 --- a/src/main/scala/leon/codegen/CodeGeneration.scala +++ b/src/main/scala/leon/codegen/CodeGeneration.scala @@ -14,12 +14,14 @@ import cafebabe.Defaults.constructorName import cafebabe.Flags._ object CodeGeneration { - private val BoxedIntClass = "java/lang/Integer" + private val BoxedIntClass = "java/lang/Integer" private val BoxedBoolClass = "java/lang/Boolean" private val TupleClass = "leon/codegen/runtime/Tuple" private val SetClass = "leon/codegen/runtime/Set" + private val MapClass = "leon/codegen/runtime/Map" private val CaseClassClass = "leon/codegen/runtime/CaseClass" + private val ErrorClass = "leon/codegen/runtime/LeonCodeGenRuntimeException" def defToJVMName(p : Program, d : Definition) : String = "Leon$CodeGen$" + d.id.uniqueName @@ -28,6 +30,8 @@ object CodeGeneration { case BooleanType => "Z" + case UnitType => "Z" + case c : ClassType => env.classDefToClass(c.classDef).map(n => "L" + n + ";").getOrElse("Unsupported class " + c.id) @@ -37,6 +41,9 @@ object CodeGeneration { case _ : SetType => "L" + SetClass + ";" + case _ : MapType => + "L" + MapClass + ";" + case _ => throw CompilationException("Unsupported type : " + tpe) } @@ -50,10 +57,10 @@ object CodeGeneration { mkExpr(exprToCompile, ch)(env.withVars(newMapping)) funDef.returnType match { - case Int32Type | BooleanType => + case Int32Type | BooleanType | UnitType => ch << IRETURN - case _ : ClassType | _ : TupleType | _ : SetType => + case _ : ClassType | _ : TupleType | _ : SetType | _ : MapType => ch << ARETURN case other => @@ -68,7 +75,7 @@ object CodeGeneration { case Variable(id) => val slot = slotFor(id) val instr = id.getType match { - case Int32Type | BooleanType => ILoad(slot) + case Int32Type | BooleanType | UnitType => ILoad(slot) case _ => ALoad(slot) } ch << instr @@ -77,7 +84,7 @@ object CodeGeneration { mkExpr(d, ch) val slot = ch.getFreshVar val instr = i.getType match { - case Int32Type | BooleanType => IStore(slot) + case Int32Type | BooleanType | UnitType => IStore(slot) case _ => AStore(slot) } ch << instr @@ -93,7 +100,7 @@ object CodeGeneration { ch << InvokeVirtual(TupleClass, "get", "(I)Ljava/lang/Object;") mkUnbox(i.getType, ch) val instr = i.getType match { - case Int32Type | BooleanType => IStore(s) + case Int32Type | BooleanType | UnitType => IStore(s) case _ => AStore(s) } ch << instr @@ -107,11 +114,15 @@ object CodeGeneration { case BooleanLiteral(v) => ch << Ldc(if(v) 1 else 0) + case UnitLiteral => + ch << Ldc(1) + + // Case classes case CaseClass(ccd, as) => val ccName = env.classDefToClass(ccd).getOrElse { throw CompilationException("Unknown class : " + ccd.id) } - // It's a little ugly that we do it each time. Could be in env. + // TODO FIXME It's a little ugly that we do it each time. Could be in env. val consSig = "(" + ccd.fields.map(f => typeToJVM(f.tpe)).mkString("") + ")V" ch << New(ccName) << DUP for(a <- as) { @@ -134,6 +145,7 @@ object CodeGeneration { ch << CheckCast(ccName) ch << GetField(ccName, sid.name, typeToJVM(sid.getType)) + // Tuples (note that instanceOf checks are in mkBranch) case Tuple(es) => ch << New(TupleClass) << DUP ch << Ldc(es.size) @@ -153,6 +165,7 @@ object CodeGeneration { ch << InvokeVirtual(TupleClass, "get", "(I)Ljava/lang/Object;") mkUnbox(bs(i - 1), ch) + // Sets case FiniteSet(es) => ch << DefaultNew(SetClass) for(e <- es) { @@ -190,6 +203,34 @@ object CodeGeneration { mkExpr(s2, ch) ch << InvokeVirtual(SetClass, "minus", "(L%s;)L%s;".format(SetClass,SetClass)) + // Maps + case FiniteMap(ss) => + ch << DefaultNew(MapClass) + for((f,t) <- ss) { + ch << DUP + mkBoxedExpr(f, ch) + mkBoxedExpr(t, ch) + ch << InvokeVirtual(MapClass, "add", "(Ljava/lang/Object;Ljava/lang/Object;)V") + } + + case MapGet(m, k) => + val MapType(_, tt) = m.getType + mkExpr(m, ch) + mkBoxedExpr(k, ch) + ch << InvokeVirtual(MapClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;") + mkUnbox(tt, ch) + + case MapIsDefinedAt(m, k) => + mkExpr(m, ch) + mkBoxedExpr(k, ch) + ch << InvokeVirtual(MapClass, "isDefinedAt", "(Ljava/lang/Object;)Z") + + case MapUnion(m1, m2) => + mkExpr(m1, ch) + mkExpr(m2, ch) + ch << InvokeVirtual(MapClass, "union", "(L%s;)L%s;".format(MapClass,MapClass)) + + // Branching case IfExpr(c, t, e) => val tl = ch.getFreshLabel("then") val el = ch.getFreshLabel("else") @@ -210,6 +251,7 @@ object CodeGeneration { } ch << InvokeStatic(cn, mn, ms) + // Arithmetic case Plus(l, r) => mkExpr(l, ch) mkExpr(r, ch) @@ -225,13 +267,31 @@ object CodeGeneration { mkExpr(r, ch) ch << IMUL + case Division(l, r) => + mkExpr(l, ch) + mkExpr(r, ch) + ch << IDIV + + case Modulo(l, r) => + mkExpr(l, ch) + mkExpr(r, ch) + ch << IREM + case UMinus(e) => mkExpr(e, ch) ch << INEG + // Misc and boolean tests + case Error(desc) => + ch << New(ErrorClass) << DUP + ch << Ldc(desc) + ch << InvokeSpecial(ErrorClass, constructorName, "(Ljava/lang/String;)V") + ch << ATHROW + // WARNING !!! See remark at the end of mkBranch ! The two functions are // mutually recursive and will loop if none supports some Boolean construct ! case b if b.getType == BooleanType => + // println("Don't know how to mkExpr for " + b) val fl = ch.getFreshLabel("boolfalse") val al = ch.getFreshLabel("boolafter") ch << Ldc(1) @@ -250,7 +310,7 @@ object CodeGeneration { mkExpr(e, ch) ch << InvokeSpecial(BoxedIntClass, constructorName, "(I)V") - case BooleanType => + case BooleanType | UnitType => ch << New(BoxedBoolClass) << DUP mkExpr(e, ch) ch << InvokeSpecial(BoxedBoolClass, constructorName, "(Z)V") @@ -267,7 +327,7 @@ object CodeGeneration { case Int32Type => ch << New(BoxedIntClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedIntClass, constructorName, "(I)V") - case BooleanType => + case BooleanType | UnitType => ch << New(BoxedBoolClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedBoolClass, constructorName, "(Z)V") case _ => @@ -280,7 +340,7 @@ object CodeGeneration { case Int32Type => ch << CheckCast(BoxedIntClass) << InvokeVirtual(BoxedIntClass, "intValue", "()I") - case BooleanType => + case BooleanType | UnitType => ch << CheckCast(BoxedBoolClass) << InvokeVirtual(BoxedBoolClass, "booleanValue", "()Z") case ct : ClassType => @@ -289,6 +349,15 @@ object CodeGeneration { } ch << CheckCast(cn) + case tt : TupleType => + ch << CheckCast(TupleClass) + + case st : SetType => + ch << CheckCast(SetClass) + + case mt : MapType => + ch << CheckCast(MapClass) + case _ => throw new CompilationException("Unsupported type in unboxing : " + tpe) } @@ -314,6 +383,9 @@ object CodeGeneration { ch << Label(fl) mkBranch(Or(es.tail), then, elze, ch) + case Implies(l, r) => + mkBranch(Or(Not(l), r), then, elze, ch) + case Not(c) => mkBranch(c, elze, then, ch) @@ -324,10 +396,17 @@ object CodeGeneration { mkExpr(l, ch) mkExpr(r, ch) l.getType match { - case Int32Type | BooleanType => ch << If_ICmpEq(then) << Goto(elze) - case _ => ch << If_ACmpEq(then) << Goto(elze) + case Int32Type | BooleanType | UnitType => + ch << If_ICmpEq(then) << Goto(elze) + + case _ => + ch << InvokeVirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z") + ch << IfEq(elze) << Goto(then) } + case Iff(l,r) => + mkBranch(Equals(l, r), then, elze, ch) + case LessThan(l,r) => mkExpr(l, ch) mkExpr(r, ch) @@ -351,6 +430,7 @@ object CodeGeneration { // WARNING !!! mkBranch delegates to mkExpr, and mkExpr delegates to mkBranch ! // That means, between the two of them, they'd better know what to generate ! case other => + // println("Don't know how to mkBranch for " + other) mkExpr(other, ch) ch << IfEq(elze) << Goto(then) } @@ -424,6 +504,20 @@ object CodeGeneration { cch.freeze } + locally { + val pnm = cf.addMethod("Ljava/lang/String;", "productName") + pnm.setFlags(( + METHOD_ACC_PUBLIC | + METHOD_ACC_FINAL + ).asInstanceOf[U2]) + + val pnch = pnm.codeHandler + + pnch << Ldc(cName) << ARETURN + + pnch.freeze + } + locally { val pem = cf.addMethod("[Ljava/lang/Object;", "productElements") pem.setFlags(( diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala index 1a56b8cfa..4cad603f7 100644 --- a/src/main/scala/leon/codegen/CompilationUnit.scala +++ b/src/main/scala/leon/codegen/CompilationUnit.scala @@ -14,29 +14,47 @@ import cafebabe.Flags._ import scala.collection.JavaConverters._ +import java.lang.reflect.Constructor + import CodeGeneration._ class CompilationUnit(val program: Program, val classes: Map[Definition, ClassFile], implicit val env: CompilationEnvironment) { - val jvmClassToDef = classes.map{ case (d, cf) => cf.className -> d }.toMap + private val jvmClassToDef = classes.map { + case (d, cf) => cf.className -> d + }.toMap + + protected[codegen] val loader = { + val l = new CafebabeClassLoader + classes.values.foreach(l.register(_)) + l + } - val loader = new CafebabeClassLoader - classes.values.foreach(loader.register(_)) + private val caseClassConstructors : Map[CaseClassDef,Constructor[_]] = { + (classes collect { + case (ccd : CaseClassDef, cf) => + val klass = loader.loadClass(cf.className) + // This is a hack: we pick the constructor with the most arguments. + val conss = klass.getConstructors().sortBy(_.getParameterTypes().length) + assert(!conss.isEmpty) + (ccd -> conss.last) + }).toMap + } - def writeClassFiles() { + private def writeClassFiles() { for ((d, cl) <- classes) { cl.writeToFile(cl.className + ".class") } } private var _nextExprId = 0 - def nextExprId = { + private def nextExprId = { _nextExprId += 1 _nextExprId } // Currently, this method is only used to prepare arguments to reflective calls. - // This means it is safe to return AnyRef (and never native values), because + // This means it is safe to return AnyRef (as opposed to primitive types), because // reflection needs this anyway. private[codegen] def valueToJVM(e: Expr): AnyRef = e match { case IntLiteral(v) => @@ -45,6 +63,10 @@ class CompilationUnit(val program: Program, val classes: Map[Definition, ClassFi case BooleanLiteral(v) => new java.lang.Boolean(v) + case CaseClass(ccd, args) => + val cons = caseClassConstructors(ccd) + cons.newInstance(args.map(valueToJVM).toArray : _*).asInstanceOf[AnyRef] + // just slightly overkill... case _ => compileExpression(e, Seq()).evalToJVM(Seq()) @@ -76,8 +98,16 @@ class CompilationUnit(val program: Program, val classes: Map[Definition, ClassFi case set : runtime.Set => FiniteSet(set.getElements().asScala.map(jvmToValue).toSeq) + case map : runtime.Map => + val pairs = map.getElements().asScala.map { entry => + val k = jvmToValue(entry.getKey()) + val v = jvmToValue(entry.getValue()) + (k, v) + } + FiniteMap(pairs.toSeq) + case _ => - throw CompilationException("MEH Unsupported return value : " + e.getClass) + throw CompilationException("Unsupported return value : " + e.getClass) } def compileExpression(e: Expr, args: Seq[Identifier]): CompiledExpression = { @@ -129,8 +159,10 @@ class CompilationUnit(val program: Program, val classes: Map[Definition, ClassFi loader.register(cf) - new CompiledExpression(this, cf, args) + new CompiledExpression(this, cf, e, args) } + + // writeClassFiles } object CompilationUnit { diff --git a/src/main/scala/leon/codegen/CompiledExpression.scala b/src/main/scala/leon/codegen/CompiledExpression.scala index 0c10fe02a..0ae8f949f 100644 --- a/src/main/scala/leon/codegen/CompiledExpression.scala +++ b/src/main/scala/leon/codegen/CompiledExpression.scala @@ -12,23 +12,28 @@ import cafebabe.ByteCodes._ import cafebabe.ClassFileTypes._ import cafebabe.Flags._ -class CompiledExpression(unit: CompilationUnit, cf: ClassFile, argsDecl: Seq[Identifier]) { +import java.lang.reflect.InvocationTargetException - def evalToJVM(args: Seq[Expr]): AnyRef = { - val cl = unit.loader.loadClass(cf.className) - val meth = cl.getMethods()(0) +class CompiledExpression(unit: CompilationUnit, cf: ClassFile, expression : Expr, argsDecl: Seq[Identifier]) { + private lazy val cl = unit.loader.loadClass(cf.className) + private lazy val meth = cl.getMethods()(0) + protected[codegen] def evalToJVM(args: Seq[Expr]): AnyRef = { assert(args.size == argsDecl.size) if (args.isEmpty) { meth.invoke(null) } else { - meth.invoke(null, args.map(unit.valueToJVM).toArray) + meth.invoke(null, args.map(unit.valueToJVM).toArray : _*) } } - def eval(args: Seq[Expr]): Expr = { - unit.jvmToValue(evalToJVM(args)) + // This may throw an exception. We unwrap it if needed. + def eval(args: Seq[Expr]) : Expr = { + try { + unit.jvmToValue(evalToJVM(args)) + } catch { + case ite : InvocationTargetException => throw ite.getCause() + } } - } diff --git a/src/main/scala/leon/evaluators/CodeGenEvaluator.scala b/src/main/scala/leon/evaluators/CodeGenEvaluator.scala new file mode 100644 index 000000000..9b9702f31 --- /dev/null +++ b/src/main/scala/leon/evaluators/CodeGenEvaluator.scala @@ -0,0 +1,51 @@ +package leon +package evaluators + +import purescala.Common._ +import purescala.Definitions._ +import purescala.TreeOps._ +import purescala.Trees._ +import purescala.TypeTrees._ + +import codegen.CompilationUnit + +class CodeGenEvaluator(ctx : LeonContext, val unit : CompilationUnit) extends Evaluator(ctx, unit.program) { + val name = "codegen-eval" + val description = "Evaluator for PureScala expressions based on compilation to JVM" + + /** Another constructor to make it look more like other `Evaluator`s. */ + def this(ctx : LeonContext, prog : Program) { + this(ctx, CompilationUnit.compileProgram(prog).get) // this .get is dubious... + } + + + def eval(expression : Expr, mapping : Map[Identifier,Expr]) : EvaluationResult = { + // ctx.reporter.warning("Using `eval` in CodeGenEvaluator is discouraged. Use `compile` whenever applicable.") + + val toPairs = mapping.toSeq + compile(expression, toPairs.map(_._1)).map(e => e(toPairs.map(_._2))).getOrElse(EvaluationError("Couldn't compile expression.")) + } + + override def compile(expression : Expr, argorder : Seq[Identifier]) : Option[Seq[Expr]=>EvaluationResult] = { + import leon.codegen.runtime.LeonCodeGenRuntimeException + + val ce = unit.compileExpression(expression, argorder) + + Some((args : Seq[Expr]) => { + try { + EvaluationSuccessful(ce.eval(args)) + } catch { + case e : ArithmeticException => + EvaluationFailure(e.getMessage) + + case e : LeonCodeGenRuntimeException => + EvaluationFailure(e.getMessage) + + // Required, because the class may be loaded from a different classloader, + // and the check above would fail. + case t : Throwable if t.getClass.toString.endsWith("LeonCodeGenRuntimeException") => + EvaluationFailure(t.getMessage) + } + }) + } +} diff --git a/src/main/scala/leon/Evaluator.scala b/src/main/scala/leon/evaluators/DefaultEvaluator.scala similarity index 63% rename from src/main/scala/leon/Evaluator.scala rename to src/main/scala/leon/evaluators/DefaultEvaluator.scala index 24d0fd06e..a6998f10b 100644 --- a/src/main/scala/leon/Evaluator.scala +++ b/src/main/scala/leon/evaluators/DefaultEvaluator.scala @@ -1,46 +1,29 @@ package leon +package evaluators import purescala.Common._ -import purescala.Trees._ -import xlang.Trees._ +import purescala.Definitions._ import purescala.TreeOps._ +import purescala.Trees._ import purescala.TypeTrees._ -object Evaluator { -// Expr should be some ground term. We have call-by-value semantics. - type EvaluationContext = Map[Identifier,Expr] - - sealed abstract class EvaluationResult { - val finalResult: Option[Expr] - } - case class OK(result: Expr) extends EvaluationResult { - val finalResult = Some(result) - } - case class RuntimeError(msg: String) extends EvaluationResult { - val finalResult = None - } - case class TypeError(expression: Expr, expected: TypeTree) extends EvaluationResult { - lazy val msg = "When typing:\n" + expression + "\nexpected: " + expected + ", found: " + expression.getType - val finalResult = None - } - case class InfiniteComputation() extends EvaluationResult { - val finalResult = None - } - case class ImpossibleComputation() extends EvaluationResult { - val finalResult = None - } - +import xlang.Trees._ - def eval(context: EvaluationContext, expression: Expr, evaluator: Option[(EvaluationContext)=>Boolean], maxSteps: Int=500000) : EvaluationResult = { - case class RuntimeErrorEx(msg: String) extends Exception - case class InfiniteComputationEx() extends Exception - case class TypeErrorEx(typeError: TypeError) extends Exception - case class ImpossibleComputationEx() extends Exception +class DefaultEvaluator(ctx : LeonContext, prog : Program) extends Evaluator(ctx, prog) { + val name = "evaluator" + val description = "Recursive interpreter for PureScala expressions" + private def typeErrorMsg(tree : Expr, expected : TypeTree) : String = "Type error : expected %s, found %s.".format(expected, tree) + private case class EvalError(msg : String) extends Exception + private case class RuntimeError(msg : String) extends Exception + + private val maxSteps = 50000 + + def eval(expression: Expr, mapping : Map[Identifier,Expr]) : EvaluationResult = { var left: Int = maxSteps - def rec(ctx: EvaluationContext, expr: Expr) : Expr = if(left <= 0) { - throw InfiniteComputationEx() + def rec(ctx: Map[Identifier,Expr], expr: Expr) : Expr = if(left <= 0) { + throw RuntimeError("Diverging computation.") } else { // println("Step on : " + expr) // println(ctx) @@ -50,12 +33,12 @@ object Evaluator { if(ctx.isDefinedAt(id)) { val res = ctx(id) if(!isGround(res)) { - throw RuntimeErrorEx("Substitution for identifier " + id.name + " is not ground.") + throw EvalError("Substitution for identifier " + id.name + " is not ground.") } else { res } } else { - throw RuntimeErrorEx("No value for identifier " + id.name + " in context.") + throw EvalError("No value for identifier " + id.name + " in mapping.") } } case Tuple(ts) => { @@ -70,35 +53,35 @@ object Evaluator { val first = rec(ctx, e) rec(ctx + ((i -> first)), b) } - case Error(desc) => throw RuntimeErrorEx("Error reached in evaluation: " + desc) + case Error(desc) => throw RuntimeError("Error reached in evaluation: " + desc) case IfExpr(cond, then, elze) => { val first = rec(ctx, cond) first match { case BooleanLiteral(true) => rec(ctx, then) case BooleanLiteral(false) => rec(ctx, elze) - case _ => throw TypeErrorEx(TypeError(first, BooleanType)) + case _ => throw EvalError(typeErrorMsg(first, BooleanType)) } } case Waypoint(_, arg) => rec(ctx, arg) case FunctionInvocation(fd, args) => { val evArgs = args.map(a => rec(ctx, a)) - // build a context for the function... + // build a mapping for the function... val frame = Map[Identifier,Expr]((fd.args.map(_.id) zip evArgs) : _*) if(fd.hasPrecondition) { rec(frame, matchToIfThenElse(fd.precondition.get)) match { case BooleanLiteral(true) => ; case BooleanLiteral(false) => { - throw RuntimeErrorEx("Precondition violation for " + fd.id.name + " reached in evaluation.: " + fd.precondition.get) + throw RuntimeError("Precondition violation for " + fd.id.name + " reached in evaluation.: " + fd.precondition.get) } - case other => throw TypeErrorEx(TypeError(other, BooleanType)) + case other => throw RuntimeError(typeErrorMsg(other, BooleanType)) } } - if(!fd.hasBody && !context.isDefinedAt(fd.id)) { - throw RuntimeErrorEx("Evaluation of function with unknown implementation.") + if(!fd.hasBody && !mapping.isDefinedAt(fd.id)) { + throw EvalError("Evaluation of function with unknown implementation.") } - val body = fd.body.getOrElse(context(fd.id)) + val body = fd.body.getOrElse(mapping(fd.id)) val callResult = rec(frame, matchToIfThenElse(body)) if(fd.hasPostcondition) { @@ -106,9 +89,8 @@ object Evaluator { val postBody = replace(Map(ResultVariable() -> Variable(freshResID)), matchToIfThenElse(fd.postcondition.get)) rec(frame + ((freshResID -> callResult)), postBody) match { case BooleanLiteral(true) => ; - case BooleanLiteral(false) if !fd.hasImplementation => throw ImpossibleComputationEx() - case BooleanLiteral(false) => throw RuntimeErrorEx("Postcondition violation for " + fd.id.name + " reached in evaluation.") - case other => throw TypeErrorEx(TypeError(other, BooleanType)) + case BooleanLiteral(false) => throw RuntimeError("Postcondition violation for " + fd.id.name + " reached in evaluation.") + case other => throw EvalError(typeErrorMsg(other, BooleanType)) } } @@ -119,7 +101,7 @@ object Evaluator { rec(ctx, args.head) match { case BooleanLiteral(false) => BooleanLiteral(false) case BooleanLiteral(true) => rec(ctx, And(args.tail)) - case other => throw TypeErrorEx(TypeError(other, BooleanType)) + case other => throw EvalError(typeErrorMsg(other, BooleanType)) } } case Or(args) if args.isEmpty => BooleanLiteral(false) @@ -127,20 +109,20 @@ object Evaluator { rec(ctx, args.head) match { case BooleanLiteral(true) => BooleanLiteral(true) case BooleanLiteral(false) => rec(ctx, Or(args.tail)) - case other => throw TypeErrorEx(TypeError(other, BooleanType)) + case other => throw EvalError(typeErrorMsg(other, BooleanType)) } } case Not(arg) => rec(ctx, arg) match { case BooleanLiteral(v) => BooleanLiteral(!v) - case other => throw TypeErrorEx(TypeError(other, BooleanType)) + case other => throw EvalError(typeErrorMsg(other, BooleanType)) } case Implies(l,r) => (rec(ctx,l), rec(ctx,r)) match { case (BooleanLiteral(b1),BooleanLiteral(b2)) => BooleanLiteral(!b1 || b2) - case (le,re) => throw TypeErrorEx(TypeError(le, BooleanType)) + case (le,re) => throw EvalError(typeErrorMsg(le, BooleanType)) } case Iff(le,re) => (rec(ctx,le),rec(ctx,re)) match { case (BooleanLiteral(b1),BooleanLiteral(b2)) => BooleanLiteral(b1 == b2) - case _ => throw TypeErrorEx(TypeError(le, BooleanType)) + case _ => throw EvalError(typeErrorMsg(le, BooleanType)) } case Equals(le,re) => { val lv = rec(ctx,le) @@ -164,53 +146,55 @@ object Evaluator { val le = rec(ctx, expr) le match { case CaseClass(cd2, args) if cd == cd2 => args(cd.selectorID2Index(sel)) - case _ => throw TypeErrorEx(TypeError(le, CaseClassType(cd))) + case _ => throw EvalError(typeErrorMsg(le, CaseClassType(cd))) } } case Plus(l,r) => (rec(ctx,l), rec(ctx,r)) match { case (IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 + i2) - case (le,re) => throw TypeErrorEx(TypeError(le, Int32Type)) + case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case Minus(l,r) => (rec(ctx,l), rec(ctx,r)) match { case (IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 - i2) - case (le,re) => throw TypeErrorEx(TypeError(le, Int32Type)) + case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case UMinus(e) => rec(ctx,e) match { case IntLiteral(i) => IntLiteral(-i) - case re => throw TypeErrorEx(TypeError(re, Int32Type)) + case re => throw EvalError(typeErrorMsg(re, Int32Type)) } case Times(l,r) => (rec(ctx,l), rec(ctx,r)) match { case (IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 * i2) - case (le,re) => throw TypeErrorEx(TypeError(le, Int32Type)) + case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case Division(l,r) => (rec(ctx,l), rec(ctx,r)) match { - case (IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 / i2) - case (le,re) => throw TypeErrorEx(TypeError(le, Int32Type)) + case (IntLiteral(i1), IntLiteral(i2)) => + if(i2 != 0) IntLiteral(i1 / i2) else throw RuntimeError("Division by 0.") + case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case Modulo(l,r) => (rec(ctx,l), rec(ctx,r)) match { - case (IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 % i2) - case (le,re) => throw TypeErrorEx(TypeError(le, Int32Type)) + case (IntLiteral(i1), IntLiteral(i2)) => + if(i2 != 0) IntLiteral(i1 % i2) else throw RuntimeError("Modulo by 0.") + case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case LessThan(l,r) => (rec(ctx,l), rec(ctx,r)) match { case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 < i2) - case (le,re) => throw TypeErrorEx(TypeError(le, Int32Type)) + case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case GreaterThan(l,r) => (rec(ctx,l), rec(ctx,r)) match { case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 > i2) - case (le,re) => throw TypeErrorEx(TypeError(le, Int32Type)) + case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case LessEquals(l,r) => (rec(ctx,l), rec(ctx,r)) match { case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 <= i2) - case (le,re) => throw TypeErrorEx(TypeError(le, Int32Type)) + case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case GreaterEquals(l,r) => (rec(ctx,l), rec(ctx,r)) match { case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 >= i2) - case (le,re) => throw TypeErrorEx(TypeError(le, Int32Type)) + case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case SetUnion(s1,s2) => (rec(ctx,s1), rec(ctx,s2)) match { case (f@FiniteSet(els1),FiniteSet(els2)) => FiniteSet((els1 ++ els2).distinct).setType(f.getType) - case (le,re) => throw TypeErrorEx(TypeError(le, s1.getType)) + case (le,re) => throw EvalError(typeErrorMsg(le, s1.getType)) } case SetIntersection(s1,s2) => (rec(ctx,s1), rec(ctx,s2)) match { case (f@FiniteSet(els1),FiniteSet(els2)) => { @@ -218,7 +202,7 @@ object Evaluator { val baseType = f.getType.asInstanceOf[SetType].base FiniteSet(newElems).setType(f.getType) } - case (le,re) => throw TypeErrorEx(TypeError(le, s1.getType)) + case (le,re) => throw EvalError(typeErrorMsg(le, s1.getType)) } case SetDifference(s1,s2) => (rec(ctx,s1), rec(ctx,s2)) match { case (f@FiniteSet(els1),FiniteSet(els2)) => { @@ -226,17 +210,17 @@ object Evaluator { val baseType = f.getType.asInstanceOf[SetType].base FiniteSet(newElems).setType(f.getType) } - case (le,re) => throw TypeErrorEx(TypeError(le, s1.getType)) + case (le,re) => throw EvalError(typeErrorMsg(le, s1.getType)) } case ElementOfSet(el,s) => (rec(ctx,el), rec(ctx,s)) match { case (e, f @ FiniteSet(els)) => BooleanLiteral(els.contains(e)) - case (l,r) => throw TypeErrorEx(TypeError(r, SetType(l.getType))) + case (l,r) => throw EvalError(typeErrorMsg(r, SetType(l.getType))) } case SetCardinality(s) => { val sr = rec(ctx, s) sr match { case FiniteSet(els) => IntLiteral(els.size) - case _ => throw TypeErrorEx(TypeError(sr, SetType(AnyType))) + case _ => throw EvalError(typeErrorMsg(sr, SetType(AnyType))) } } @@ -279,9 +263,9 @@ object Evaluator { case g @ MapGet(m,k) => (rec(ctx,m), rec(ctx,k)) match { case (FiniteMap(ss), e) => ss.find(_._1 == e) match { case Some((_, v0)) => v0 - case None => throw RuntimeErrorEx("key not found: " + e) + case None => throw RuntimeError("Key not found: " + e) } - case (l,r) => throw TypeErrorEx(TypeError(l, MapType(r.getType, g.getType))) + case (l,r) => throw EvalError(typeErrorMsg(l, MapType(r.getType, g.getType))) } case u @ MapUnion(m1,m2) => (rec(ctx,m1), rec(ctx,m2)) match { case (f1@FiniteMap(ss1), FiniteMap(ss2)) => { @@ -289,11 +273,11 @@ object Evaluator { val newSs = filtered1 ++ ss2 FiniteMap(newSs).setType(f1.getType) } - case (l, r) => throw TypeErrorEx(TypeError(l, m1.getType)) + case (l, r) => throw EvalError(typeErrorMsg(l, m1.getType)) } case i @ MapIsDefinedAt(m,k) => (rec(ctx,m), rec(ctx,k)) match { case (FiniteMap(ss), e) => BooleanLiteral(ss.exists(_._1 == e)) - case (l, r) => throw TypeErrorEx(TypeError(l, m.getType)) + case (l, r) => throw EvalError(typeErrorMsg(l, m.getType)) } case Distinct(args) => { val newArgs = args.map(rec(ctx, _)) @@ -301,33 +285,22 @@ object Evaluator { } case other => { - Settings.reporter.error("Error: don't know how to handle " + other + " in Evaluator.") - throw RuntimeErrorEx("unhandled case in Evaluator") + context.reporter.error("Error: don't know how to handle " + other + " in Evaluator.") + throw EvalError("Unhandled case in Evaluator : " + other) } } } - evaluator match { - case Some(evalFun) => - try { - OK(BooleanLiteral(evalFun(context))) - } catch { - case e: Exception => RuntimeError(e.getMessage) - } - case None => - try { - OK(rec(context, expression)) - } catch { - case RuntimeErrorEx(msg) => RuntimeError(msg) - case InfiniteComputationEx() => InfiniteComputation() - case TypeErrorEx(te) => te - case ImpossibleComputationEx() => ImpossibleComputation() - } + try { + EvaluationSuccessful(rec(mapping, expression)) + } catch { + case EvalError(msg) => EvaluationError(msg) + case RuntimeError(msg) => EvaluationFailure(msg) } } // quick and dirty.. don't overuse. - def isGround(expr: Expr) : Boolean = { + private def isGround(expr: Expr) : Boolean = { variablesOf(expr) == Set.empty } } diff --git a/src/main/scala/leon/evaluators/Evaluator.scala b/src/main/scala/leon/evaluators/Evaluator.scala new file mode 100644 index 000000000..7beda070f --- /dev/null +++ b/src/main/scala/leon/evaluators/Evaluator.scala @@ -0,0 +1,40 @@ +package leon +package evaluators + +import purescala.Common._ +import purescala.Definitions._ +import purescala.Trees._ + +abstract class Evaluator(val context : LeonContext, val program : Program) extends LeonComponent { + + /** Evaluates an expression, using `mapping` as a valuation function for the free variables. */ + def eval(expr : Expr, mapping : Map[Identifier,Expr]) : EvaluationResult + + /** Evaluates a ground expression. */ + final def eval(expr : Expr) : EvaluationResult = eval(expr, Map.empty) + + /** Compiles an expression into a function, where the arguments are the free variables in the expression. + * `argorder` specifies in which order the arguments should be passed. + * The default implementation uses the evaluation function each time, but evaluators are free + * to (and encouraged to) apply any specialization. */ + def compile(expr : Expr, argorder : Seq[Identifier]) : Option[Seq[Expr]=>EvaluationResult] = Some( + (args : Seq[Expr]) => if(args.size != argorder.size) { + EvaluationError("Wrong number of arguments for evaluation.") + } else { + val mapping = argorder.zip(args).toMap + eval(expr, mapping) + } + ) +} + +/** Possible results of expression evaluation. */ +sealed abstract class EvaluationResult(val result : Option[Expr]) + +/** Represents an evaluation that successfully derived the result `value`. */ +case class EvaluationSuccessful(value : Expr) extends EvaluationResult(Some(value)) + +/** Represents an evaluation that led to an error (in the program). */ +case class EvaluationFailure(message : String) extends EvaluationResult(None) + +/** Represents an evaluation that failed (in the evaluator). */ +case class EvaluationError(message : String) extends EvaluationResult(None) diff --git a/src/main/scala/leon/purescala/Definitions.scala b/src/main/scala/leon/purescala/Definitions.scala index e212c1baa..6eee2247c 100644 --- a/src/main/scala/leon/purescala/Definitions.scala +++ b/src/main/scala/leon/purescala/Definitions.scala @@ -68,6 +68,17 @@ object Definitions { } } + object Program { + lazy val empty : Program = Program( + FreshIdentifier("empty"), + ObjectDef( + FreshIdentifier("empty"), + Seq.empty, + Seq.empty + ) + ) + } + /** Objects work as containers for class definitions, functions (def's) and * val's. */ case class ObjectDef(id: Identifier, defs : Seq[Definition], invariants: Seq[Expr]) extends Definition { diff --git a/src/main/scala/leon/solvers/ParallelSolver.scala b/src/main/scala/leon/solvers/ParallelSolver.scala index b6e66ff07..e2a334df1 100644 --- a/src/main/scala/leon/solvers/ParallelSolver.scala +++ b/src/main/scala/leon/solvers/ParallelSolver.scala @@ -6,8 +6,6 @@ import purescala.Definitions._ import purescala.Trees._ import purescala.TypeTrees._ -import Evaluator._ - import scala.actors.Actor import scala.actors.DaemonActor import scala.actors.Actor._ diff --git a/src/main/scala/leon/solvers/RandomSolver.scala b/src/main/scala/leon/solvers/RandomSolver.scala index 3c7265635..c793d37f8 100644 --- a/src/main/scala/leon/solvers/RandomSolver.scala +++ b/src/main/scala/leon/solvers/RandomSolver.scala @@ -7,7 +7,7 @@ import purescala.Trees._ import purescala.TreeOps._ import purescala.TypeTrees._ -import Evaluator._ +import evaluators._ import scala.util.Random @@ -16,6 +16,11 @@ class RandomSolver(context: LeonContext, val nbTrial: Option[Int] = None) extend require(nbTrial.forall(i => i >= 0)) private val reporter = context.reporter + private var evaluator : Evaluator = null + + override def setProgram(program : Program) : Unit = { + evaluator = new DefaultEvaluator(context, program) + } val name = "QC" val description = "Solver applying random testing (QuickCheck-like)" @@ -110,29 +115,26 @@ class RandomSolver(context: LeonContext, val nbTrial: Option[Int] = None) extend val var2val: Map[Identifier, Expr] = Map(vars.map(v => (v, randomValue(v.getType, bound))).toList: _*) //reporter.info("Trying with: " + var2val) - val evalResult = eval(var2val, expression, None) + val evalResult = evaluator.eval(expression, var2val) evalResult match { - case OK(BooleanLiteral(true)) => { + case EvaluationSuccessful(BooleanLiteral(true)) => { //continue trying } - case OK(BooleanLiteral(false)) => { + + case EvaluationSuccessful(BooleanLiteral(false)) => { reporter.info("Found counter example to formula: " + var2val) result = Some(false) stop = true } - /* in any of the following case, simply continue with another assignement */ - case InfiniteComputation() => { - //reporter.info("Model seems to lead to divergent computation.") - } - case RuntimeError(msg) => { - //reporter.info("Model leads to runtime error: " + msg) - } - case t @ TypeError(_,_) => { - //reporter.info("Type error in model evaluation.\n" + t.msg) - } - case _ => { - //reporter.info(" -> candidate model discarded.") + + case EvaluationFailure(_) => { + reporter.info("Input leads to runtime error: " + var2val) + result = Some(false) + stop = true } + + // otherwise, simply continue with another assignement + case EvaluationError(_) => ; } iteration += 1 diff --git a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala index 676f77e61..49a7c5399 100644 --- a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala +++ b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala @@ -12,6 +12,8 @@ import purescala.Extractors._ import purescala.TreeOps._ import purescala.TypeTrees._ +import evaluators._ + import scala.collection.mutable.{Map => MutableMap} import scala.collection.mutable.{Set => MutableSet} @@ -27,24 +29,42 @@ class FairZ3Solver(context : LeonContext) val description = "Fair Z3 Solver" override val definedOptions : Set[LeonOptionDef] = Set( - LeonFlagOptionDef("checkmodels", "--checkmodels", "Double-check counter-examples"), - LeonFlagOptionDef("feelinglucky", "--feelinglucky", "Use evaluator to find counter-examples early") + LeonFlagOptionDef("checkmodels", "--checkmodels", "Double-check counter-examples with evaluator"), + LeonFlagOptionDef("feelinglucky", "--feelinglucky", "Use evaluator to find counter-examples early"), + LeonFlagOptionDef("codegen", "--codegen", "Use compiled evaluator instead of interpreter") ) - val (feelingLucky, checkModels) = locally { - var lucky = false - var check = false + // What wouldn't we do to avoid defining vars? + val (feelingLucky, checkModels, useCodeGen) = locally { + var lucky = false + var check = false + var codegen = false for(opt <- context.options) opt match { - case LeonFlagOption("checkmodels") => check = true - case LeonFlagOption("feelinglucky") => lucky = true + case LeonFlagOption("checkmodels") => check = true + case LeonFlagOption("feelinglucky") => lucky = true + case LeonFlagOption("codegen") => codegen = true case _ => } - (lucky,check) + (lucky,check,codegen) } - // this is fixed + private var evaluator : Evaluator = null + + override def setProgram(prog : Program) { + super.setProgram(prog) + + evaluator = if(useCodeGen) { + // TODO If somehow we could not recompile each time we create a solver, + // that would be good? + new CodeGenEvaluator(context, prog) + } else { + new DefaultEvaluator(context, prog) + } + } + + // This is fixed. protected[leon] val z3cfg = new Z3Config( "MODEL" -> true, "MBQI" -> false, @@ -67,7 +87,7 @@ class FairZ3Solver(context : LeonContext) private var reverseFunctionMap: Map[Z3FuncDecl, FunDef] = Map.empty private var axiomatizedFunctions : Set[FunDef] = Set.empty - def prepareFunctions: Unit = { + protected[leon] def prepareFunctions: Unit = { functionMap = Map.empty reverseFunctionMap = Map.empty for (funDef <- program.definedFunctions) { @@ -105,9 +125,7 @@ class FairZ3Solver(context : LeonContext) (solver.checkAssumptions(assumptions), solver.getModel, solver.getUnsatCore) } - private def validateAndDeleteModel(model: Z3Model, formula: Expr, variables: Set[Identifier], evaluator: Option[(Map[Identifier,Expr])=>Boolean] = None) : (Boolean, Map[Identifier,Expr]) = { - import Evaluator._ - + private def validateModel(model: Z3Model, formula: Expr, variables: Set[Identifier]) : (Boolean, Map[Identifier,Expr]) = { if(!forceStop) { val functionsModel: Map[Z3FuncDecl, (Seq[(Seq[Z3AST], Z3AST)], Z3AST)] = model.getModelFuncInterpretations.map(i => (i._1, (i._2, i._3))).toMap @@ -137,31 +155,26 @@ class FairZ3Solver(context : LeonContext) val asMap = modelToMap(model, variables) ++ functionsAsMap ++ constantFunctionsAsMap lazy val modelAsString = asMap.toList.map(p => p._1 + " -> " + p._2).mkString("\n") - val evalResult = eval(asMap, formula, evaluator) + val evalResult = evaluator.eval(formula, asMap) evalResult match { - case OK(BooleanLiteral(true)) => { + case EvaluationSuccessful(BooleanLiteral(true)) => reporter.info("- Model validated:") reporter.info(modelAsString) (true, asMap) - } - case RuntimeError(msg) => { - reporter.info("- Invalid model") - //reporter.error(modelAsString) - (false, asMap) - } - case OK(BooleanLiteral(false)) => { + + case EvaluationSuccessful(BooleanLiteral(false)) => reporter.info("- Invalid model.") (false, asMap) - } - case ImpossibleComputation() => { - reporter.info("- Invalid Model: the model could not be verified because of insufficient information.") + + case EvaluationFailure(msg) => + reporter.info("- Model leads to runtime error.") (false, asMap) - } - case other => { - reporter.error("Something went wrong. While evaluating the model, we got this: " + other) + + case EvaluationError(msg) => + reporter.error("Something went wrong. While evaluating the model, we got this : " + msg) (false, asMap) - } + } } else { (false, Map.empty) @@ -233,8 +246,10 @@ class FairZ3Solver(context : LeonContext) } def getNewSolver = new solvers.IncrementalSolver { + private val evaluator = enclosing.evaluator private val feelingLucky = enclosing.feelingLucky private val checkModels = enclosing.checkModels + private val useCodeGen = enclosing.useCodeGen initZ3 @@ -246,15 +261,16 @@ class FairZ3Solver(context : LeonContext) } } + private var varsInVC = Set[Identifier]() + private var frameGuards = List[Z3AST](z3.mkFreshConst("frame", z3.mkBoolSort)) private var frameExpressions = List[List[Expr]](Nil) - private var varsInVC = Set[Identifier]() def entireFormula = And(frameExpressions.flatten) def push() { - frameGuards = z3.mkFreshConst("frame", z3.mkBoolSort) :: frameGuards - frameExpressions = Nil :: frameExpressions + frameGuards = z3.mkFreshConst("frame", z3.mkBoolSort) :: frameGuards + frameExpressions = Nil :: frameExpressions } def halt() { @@ -262,12 +278,15 @@ class FairZ3Solver(context : LeonContext) } def pop(lvl: Int = 1) { + // TODO FIXME : this is wrong if lvl != 1. + // We could fix it, or change the interface to remove the optional arg. + // We make sure we discard the expressions guarded by this frame solver.assertCnstr(z3.mkNot(frameGuards.head)) // Pop the frames - frameGuards = frameGuards.tail - frameExpressions = frameExpressions.tail + frameGuards = frameGuards.tail + frameExpressions = frameExpressions.tail } def check: Option[Boolean] = { @@ -364,7 +383,7 @@ class FairZ3Solver(context : LeonContext) val z3model = solver.getModel if (this.checkModels) { - val (isValid, model) = validateAndDeleteModel(z3model, entireFormula, varsInVC) + val (isValid, model) = validateModel(z3model, entireFormula, varsInVC) if (isValid) { foundAnswer(Some(true), model) @@ -417,7 +436,7 @@ class FairZ3Solver(context : LeonContext) if (this.feelingLucky && !forceStop) { // we might have been lucky :D luckyTime.start - val (wereWeLucky, cleanModel) = validateAndDeleteModel(solver.getModel, entireFormula, varsInVC) + val (wereWeLucky, cleanModel) = validateModel(solver.getModel, entireFormula, varsInVC) luckyTime.stop if(wereWeLucky) { diff --git a/src/main/scala/leon/synthesis/LinearEquations.scala b/src/main/scala/leon/synthesis/LinearEquations.scala index 9debb3a8d..1465ea919 100644 --- a/src/main/scala/leon/synthesis/LinearEquations.scala +++ b/src/main/scala/leon/synthesis/LinearEquations.scala @@ -1,13 +1,18 @@ -package leon.synthesis +package leon +package synthesis -import leon.purescala.Trees._ -import leon.purescala.TreeNormalizations.linearArithmeticForm -import leon.purescala.TypeTrees._ -import leon.purescala.Common._ -import leon.Evaluator -import leon.synthesis.Algebra._ +import purescala.Definitions._ +import purescala.Trees._ +import purescala.TreeNormalizations.linearArithmeticForm +import purescala.TypeTrees._ +import purescala.Common._ + +import synthesis.Algebra._ object LinearEquations { + // This is a hack, but the use of an evaluator in this file is itself beyond that. + import evaluators._ + private lazy val evaluator = new DefaultEvaluator(LeonContext(), Program.empty) //eliminate one variable from normalizedEquation t + a1*x1 + ... + an*xn = 0 //return a mapping for each of the n variables in (pre, map, freshVars) @@ -70,7 +75,8 @@ object LinearEquations { val (_, sols) = particularSolution(as, IntLiteral(coef(j)*K(j)(j)) :: coef.drop(j+1).map(IntLiteral(_)).toList) var i = 0 while(i < sols.size) { - K(i+j+1)(j) = Evaluator.eval(Map(), sols(i), None).asInstanceOf[Evaluator.OK].result.asInstanceOf[IntLiteral].value + // seriously ??? + K(i+j+1)(j) = evaluator.eval(sols(i)).asInstanceOf[EvaluationSuccessful].value.asInstanceOf[IntLiteral].value i += 1 } } diff --git a/src/test/resources/regression/codegen/Prog001.scala b/src/test/resources/regression/codegen/Prog001.scala deleted file mode 100644 index 91f9a253f..000000000 --- a/src/test/resources/regression/codegen/Prog001.scala +++ /dev/null @@ -1,18 +0,0 @@ -object Prog001 { - def fortyTwo() = 42 - - def plus(x : Int, y : Int) = x + y - - def double(x : Int) : Int = { - val a = x - a + a - } - - def implies(a : Boolean, b : Boolean) : Boolean = !a || b - - def abs(x : Int) : Int = { - if(x < 0) -x else x - } - - def factorial(i : Int) : Int = if(i <= 1) 1 else (i * factorial(i - 1)) -} diff --git a/src/test/resources/regression/codegen/Prog002.scala b/src/test/resources/regression/codegen/Prog002.scala deleted file mode 100644 index 1da0f03c0..000000000 --- a/src/test/resources/regression/codegen/Prog002.scala +++ /dev/null @@ -1,14 +0,0 @@ -object Prog002 { - sealed abstract class List - case class Nil() extends List - case class Cons(head : Int, tail : List) extends List - - def isNil(l : List) : Boolean = { - l == Nil() - } - - def size(l : List) : Int = l match { - case Nil() => 0 - case Cons(_, xs) => 1 + size(xs) - } -} diff --git a/src/test/resources/regression/codegen/Prog003.scala b/src/test/resources/regression/codegen/Prog003.scala deleted file mode 100644 index 829583057..000000000 --- a/src/test/resources/regression/codegen/Prog003.scala +++ /dev/null @@ -1,14 +0,0 @@ -object Prog003 { - // Some tests for tuples - def wrap(x : Int, b : Boolean) : (Int,Boolean) = (x,b) - - def fst(t : (Int,Boolean)) : Int = t._1 - - def snd(t : (Int,Boolean)) : Boolean = t._2 - - def swap(t : (Int,Boolean)) : (Boolean,Int) = { - val (i,b) = t - - (b,i) - } -} diff --git a/src/test/resources/regression/codegen/Prog004.scala b/src/test/resources/regression/codegen/Prog004.scala deleted file mode 100644 index cf5ece1a1..000000000 --- a/src/test/resources/regression/codegen/Prog004.scala +++ /dev/null @@ -1,17 +0,0 @@ -object Prog004 { - def set1() : Set[Int] = { - Set(6, 7) - } - - def set2() : Set[Int] = { - set1() ++ Set(4) - } - - def set3() : Set[Int] = { - set2() ** set1() - } - - def set4() : Set[Int] = { - set2() -- set1() - } -} diff --git a/src/test/resources/regression/codegen/README b/src/test/resources/regression/codegen/README deleted file mode 100644 index 2edec5407..000000000 --- a/src/test/resources/regression/codegen/README +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains PureScala programs for which compilation (codegen) -should always succeed entirely. diff --git a/src/test/scala/leon/test/codegen/CodeGenEvaluation.scala b/src/test/scala/leon/test/codegen/CodeGenEvaluation.scala deleted file mode 100644 index 13d4a4948..000000000 --- a/src/test/scala/leon/test/codegen/CodeGenEvaluation.scala +++ /dev/null @@ -1,191 +0,0 @@ -package leon.test -package codegen - -import leon._ -import leon.plugin.{TemporaryInputPhase, ExtractionPhase} -import leon.codegen.CompilationUnit -import leon.purescala.Definitions._ -import leon.purescala.TypeTrees.TypeErrorException - -import org.scalatest.FunSuite - -import TestUtils._ - -class CodeGenEvaluation extends FunSuite { - private var counter : Int = 0 - private def nextInt() : Int = { - counter += 1 - counter - } - - object CodeTestPhase extends LeonPhase[Program,Option[CompilationUnit]] { - val name = "CodeGen" - val description = "Compiles a Leon program into Java methods" - - def run(ctx : LeonContext)(p : Program) : Option[CompilationUnit] = { - CompilationUnit.compileProgram(p) - } - } - - private case class Output(result : Option[CompilationUnit], reporter : Reporter) - - private def mkPipeline : Pipeline[List[String], Option[CompilationUnit]] = - ExtractionPhase andThen CodeTestPhase - - private def forProgram(name: String)(content: String)(block: Output => Unit) = { - test("PureScala program %3d: [%s]".format(nextInt(), name)) { - - val ctx = LeonContext( - settings = Settings( - synthesis = false, - xlang = false, - verify = false - ), - files = List(), - reporter = new SilentReporter - ) - - val pipeline = TemporaryInputPhase andThen ExtractionPhase andThen CodeTestPhase - - val result = pipeline.run(ctx)((content, Nil)) - - block(Output(result, ctx.reporter)) - } - } - - import purescala.Trees._ - - def javaEval(unit: CompilationUnit)(ex: Expr): Expr = { - val cp = unit.compileExpression(ex, Seq()) - cp.eval(Seq()) - } - - def getFunction(unit: CompilationUnit, name: String): FunDef = { - unit.program.definedFunctions.find(_.id.toString == name) match { - case Some(fd) => - fd - case _ => - throw new AssertionError("Could not find any function named '"+name+"'") - } - } - - def getCaseClass(unit: CompilationUnit, name: String): CaseClassDef = { - unit.program.mainObject.caseClassDef(name) - } - - forProgram("Simple Evaluation")( - """ -object Prog001 { - def fortyTwo() = 42 - - def plus(x : Int, y : Int) = x + y - - def double(x : Int) : Int = { - val a = x - a + a - } - - def implies(a : Boolean, b : Boolean) : Boolean = !a || b - - def abs(x : Int) : Int = { - if(x < 0) -x else x - } - - def factorial(i : Int) : Int = if(i <= 1) 1 else (i * factorial(i - 1)) -} - """ - ){ out => - assert(out.result.isDefined === true) - val unit = out.result.get - - val fact = getFunction(unit, "factorial") - - val expr1 = Plus(IntLiteral(5), IntLiteral(42)) - assert(javaEval(unit)(expr1) === IntLiteral(47)) - - - val expr2 = Plus(FunctionInvocation(fact, Seq(IntLiteral(5))), IntLiteral(42)) - assert(javaEval(unit)(expr2) === IntLiteral(162)) - - //Type error - intercept[TypeErrorException] { - val expr3 = FunctionInvocation(fact, Seq(BooleanLiteral(false))) - assert(javaEval(unit)(expr3) != IntLiteral(1), "This should be a type error") - } - } - - forProgram("Case Classes Evaluation")( - """ -object Prog002 { - sealed abstract class List - case class Nil() extends List - case class Cons(head : Int, tail : List) extends List - - def isNil(l : List) : Boolean = { - l == Nil() - } - - def size(l : List) : Int = l match { - case Nil() => 0 - case Cons(_, xs) => 1 + size(xs) - } - - def conscons(l: List): List = Cons(0, Cons(1, l)) -} - """ - ){ out => - assert(out.result.isDefined === true) - val unit = out.result.get - - val ccNil = getCaseClass(unit, "Nil") - val ccCons = getCaseClass(unit, "Cons") - val cons = getFunction(unit, "conscons") - - val expr1 = FunctionInvocation(cons, Seq(CaseClass(ccNil, Seq()))) - assert(javaEval(unit)(expr1) === CaseClass(ccCons, Seq(IntLiteral(0), CaseClass(ccCons, Seq(IntLiteral(1), CaseClass(ccNil, Seq())))))) - } - - forProgram("Set Evaluation")( - """ -object Sets { - def s0() : Set[Int] = Set() - def s1() : Set[Int] = Set(1, 2, 3) - def s2() : Set[Int] = Set(2, 4, 6) - def s3() : Set[Int] = s1() ++ s2() - def s4() : Set[Int] = s2() ++ s1() - def s5() : Set[Int] = s1() ** s2() - def s6() : Set[Int] = s2() ** s1() - def s7() : Set[Int] = s1() -- s2() - def s8() : Set[Int] = s2() -- s1() -} - """ - ){ out => - assert(out.result.isDefined === true) - val unit = out.result.get - - def asIntSet(e : Expr) : Option[Set[Int]] = e match { - case FiniteSet(es) => - val ois = es.map(_ match { - case IntLiteral(v) => Some(v) - case _ => None - }) - if(ois.forall(_.isDefined)) - Some(ois.map(_.get).toSet) - else - None - case _ => None - } - - def eval(f : String) : Option[Set[Int]] = asIntSet(javaEval(unit)(FunctionInvocation(getFunction(unit, f), Seq()))) - - assert(eval("s0") === Some(Set.empty[Int])) - assert(eval("s1") === Some(Set(1, 2, 3))) - assert(eval("s2") === Some(Set(2, 4, 6))) - assert(eval("s3") === Some(Set(1, 2, 3, 4, 6))) - assert(eval("s4") === Some(Set(2, 4, 6, 1, 3))) - assert(eval("s5") === Some(Set(2))) - assert(eval("s6") === Some(Set(2))) - assert(eval("s7") === Some(Set(1, 3))) - assert(eval("s8") === Some(Set(4, 6))) - } -} diff --git a/src/test/scala/leon/test/codegen/CodeGenRegression.scala b/src/test/scala/leon/test/codegen/CodeGenRegression.scala deleted file mode 100644 index 75b58e933..000000000 --- a/src/test/scala/leon/test/codegen/CodeGenRegression.scala +++ /dev/null @@ -1,71 +0,0 @@ -package leon.test -package codegen - -import leon._ -import leon.plugin.ExtractionPhase -import leon.codegen.CodeGenPhase -import leon.codegen.CompilationResult - -import org.scalatest.FunSuite - -import java.io.File - -import TestUtils._ - -class CodeGenRegression extends FunSuite { - private var counter : Int = 0 - private def nextInt() : Int = { - counter += 1 - counter - } - - private case class Output(result : CompilationResult, reporter : Reporter) - - private def mkPipeline : Pipeline[List[String],CompilationResult] = - ExtractionPhase andThen CodeGenPhase - - private def mkTest(file : File)(block: Output=>Unit) = { - val fullName = file.getPath() - val start = fullName.indexOf("regression") - val displayName = if(start != -1) { - fullName.substring(start, fullName.length) - } else { - fullName - } - - test("%3d: %s".format(nextInt(), displayName)) { - assert(file.exists && file.isFile && file.canRead, - "Benchmark [%s] is not a readable file".format(displayName)) - val ctx = LeonContext( - settings = Settings( - synthesis = false, - xlang = false, - verify = false - ), - files = List(file), - reporter = new SilentReporter - ) - - val pipeline = mkPipeline - - val result = pipeline.run(ctx)(file.getPath :: Nil) - - block(Output(result, ctx.reporter)) - } - } - - private def forEachFileIn(cat : String)(block : Output=>Unit) { - val fs = filesInResourceDir(cat, _.endsWith(".scala")) - - for(f <- fs) { - mkTest(f)(block) - } - } - - forEachFileIn("regression/codegen/") { output => - val Output(result, reporter) = output - assert(result.successful, "Compilation should be successful.") - assert(reporter.errorCount === 0) - assert(reporter.warningCount === 0) - } -} diff --git a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala new file mode 100644 index 000000000..1d2d690bc --- /dev/null +++ b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala @@ -0,0 +1,347 @@ +package leon.test +package evaluators + +import leon._ + +import leon.evaluators._ + +import leon.plugin.{TemporaryInputPhase, ExtractionPhase} + +import leon.purescala.Common._ +import leon.purescala.Definitions._ +import leon.purescala.Trees._ +import leon.purescala.TypeTrees._ + +import org.scalatest.FunSuite + +class EvaluatorsTests extends FunSuite { + private implicit lazy val leonContext = LeonContext( + settings = Settings( + synthesis = false, + xlang = false, + verify = false + ), + files = List(), + reporter = new SilentReporter + ) + + private val evaluatorConstructors : List[(LeonContext,Program)=>Evaluator] = List( + new DefaultEvaluator(_,_), + new CodeGenEvaluator(_,_) + ) + + private def prepareEvaluators(implicit ctx : LeonContext, prog : Program) : List[Evaluator] = evaluatorConstructors.map(c => c(leonContext, prog)) + + private def parseString(str : String) : Program = { + val pipeline = TemporaryInputPhase andThen ExtractionPhase + + val errorsBefore = leonContext.reporter.errorCount + val warningsBefore = leonContext.reporter.warningCount + + val program = pipeline.run(leonContext)((str, Nil)) + + assert(leonContext.reporter.errorCount === errorsBefore) + assert(leonContext.reporter.warningCount === warningsBefore) + + program + } + + private def mkCall(name : String, args : Expr*)(implicit p : Program) = { + val fDef = p.definedFunctions.find(_.id.name == name) getOrElse { + throw new AssertionError("No function named '%s' defined in program.".format(name)) + } + + FunctionInvocation(fDef, args.toSeq) + } + + private def mkCaseClass(name : String, args : Expr*)(implicit p : Program) = { + val ccDef = p.mainObject.caseClassDef(name) + CaseClass(ccDef, args.toSeq) + } + + private def checkCompSuccess(evaluator : Evaluator, in : Expr) : Expr = { + evaluator.eval(in) match { + case EvaluationFailure(msg) => + throw new AssertionError("Evaluation of '%s' with evaluator '%s' should have succeeded, but it failed (%s).".format(in, evaluator.name, msg)) + + case EvaluationError(msg) => + throw new AssertionError("Evaluation of '%s' with evaluator '%s' should have succeeded, but the evaluator had an internal error (%s).".format(in, evaluator.name, msg)) + + case EvaluationSuccessful(result) => + result + } + } + + private def checkComp(evaluator : Evaluator, in : Expr, out : Expr) { + val result = checkCompSuccess(evaluator, in) + if(result != out) + throw new AssertionError("Evaluation of '%s' with evaluator '%s' should have produced '%s' but produced '%s' instead.".format(in, evaluator.name, out, result)) + } + + private def checkSetComp(evaluator : Evaluator, in : Expr, out : Set[Int]) { + val result = checkCompSuccess(evaluator, in) + + def asIntSet(e : Expr) : Option[Set[Int]] = e match { + case FiniteSet(es) => + val ois = es.map(_ match { + case IntLiteral(v) => Some(v) + case _ => None + }) + if(ois.forall(_.isDefined)) + Some(ois.map(_.get).toSet) + else + None + case _ => None + } + + asIntSet(result) match { + case Some(s) if s == out => + ; + + case _ => + throw new AssertionError("Evaluation of '%s' with evaluator '%s' should have produced a set '%s', but it produced '%s' instead.".format(in, evaluator.name, out, result)) + } + } + + private def checkMapComp(evaluator : Evaluator, in : Expr, out : Map[Int,Int]) { + val result = checkCompSuccess(evaluator, in) + + def asIntMap(e : Expr) : Option[Map[Int,Int]] = e match { + case FiniteMap(ss) => + val oips : Seq[Option[(Int,Int)]] = ss.map(_ match { + case (IntLiteral(f),IntLiteral(t)) => Some(f -> t) + case _ => None + }) + if(oips.forall(_.isDefined)) + Some(oips.map(_.get).toMap) + else + None + case _ => None + } + + asIntMap(result) match { + case Some(s) if s == out => + ; + + case _ => + throw new AssertionError("Evaluation of '%s' with evaluator '%s' should produced a map '%s', but it produced '%s' instead.".format(in, evaluator.name, out, result)) + } + } + + private def checkError(evaluator : Evaluator, in : Expr) { + evaluator.eval(in) match { + case EvaluationError(msg) => + throw new AssertionError("Evaluation of '%s' with evaluator '%s' should have failed, but it produced an internal error (%s).".format(in, evaluator.name, msg)) + + case EvaluationSuccessful(result) => + throw new AssertionError("Evaluation of '%s' with evaluator '%s' should have failed, but it produced the result '%s' instead.".format(in, evaluator.name, result)) + + case EvaluationFailure(_) => + // that's the desired outcome + } + } + + private def T = BooleanLiteral(true) + private def F = BooleanLiteral(false) + private def IL(i : Int) = IntLiteral(i) + + test("Arithmetic") { + val p = """|object Program { + | def plus(x : Int, y : Int) : Int = x + y + | def max(x : Int, y : Int) : Int = if(x >= y) x else y + | def square(i : Int) : Int = { val j = i; j * i } + | def abs(i : Int) : Int = if(i < 0) -i else i + | def intSqrt(n : Int) : Int = intSqrt0(abs(n), 0) + | def intSqrt0(n : Int, c : Int) : Int = { + | val s = square(c+1) + | if(s > n) c else intSqrt0(n, c+1) + | } + | def div(x : Int, y : Int) : Int = (x / y) + | def mod(x : Int, y : Int) : Int = (x % y) + |} + |""".stripMargin + + implicit val prog = parseString(p) + + val evaluators = prepareEvaluators + + for(e <- evaluators) { + // Some simple math. + checkComp(e, mkCall("plus", IL(60), UMinus(IL(18))), IL(42)) + checkComp(e, mkCall("max", IL(4), IL(42)), IL(42)) + checkComp(e, mkCall("max", IL(42), UMinus(IL(42))), IL(42)) + checkComp(e, mkCall("intSqrt", UMinus(IL(1800))), IL(42)) + checkComp(e, mkCall("div", IL(7), IL(5)), IL(1)) + checkComp(e, mkCall("div", IL(7), IL(-5)), IL(-1)) + checkComp(e, mkCall("div", IL(-7), IL(5)), IL(-1)) + checkComp(e, mkCall("div", IL(-7), IL(-5)), IL(1)) + checkComp(e, mkCall("mod", IL(7), IL(5)), IL(2)) + checkComp(e, mkCall("mod", IL(7), IL(-5)), IL(2)) + checkComp(e, mkCall("mod", IL(-7), IL(5)), IL(-2)) + checkComp(e, mkCall("mod", IL(-7), IL(-5)), IL(-2)) + + // Things that should crash. + checkError(e, mkCall("div", IL(42), IL(0))) + checkError(e, mkCall("mod", IL(42), IL(0))) + } + } + + test("Booleans") { + val p = """|object Program { + |def and1(x : Boolean, y : Boolean) : Boolean = x && y + |def or1(x : Boolean, y : Boolean) : Boolean = x || y + |def and2(x : Boolean, y : Boolean) : Boolean = !(!x || !y) + |def or2(x : Boolean, y : Boolean) : Boolean = !(!x && !y) + |def safe(n : Int) : Boolean = (n != 0 && (1/n == n)) + |}""".stripMargin + + implicit val prog = parseString(p) + + val evaluators = prepareEvaluators + + for(e <- evaluators) { + checkComp(e, mkCall("and1", F, F), F) + checkComp(e, mkCall("and1", F, T), F) + checkComp(e, mkCall("and1", T, F), F) + checkComp(e, mkCall("and1", T, T), T) + checkComp(e, mkCall("and2", F, F), F) + checkComp(e, mkCall("and2", F, T), F) + checkComp(e, mkCall("and2", T, F), F) + checkComp(e, mkCall("and2", T, T), T) + checkComp(e, mkCall("or1", F, F), F) + checkComp(e, mkCall("or1", F, T), T) + checkComp(e, mkCall("or1", T, F), T) + checkComp(e, mkCall("or1", T, T), T) + checkComp(e, mkCall("or2", F, F), F) + checkComp(e, mkCall("or2", F, T), T) + checkComp(e, mkCall("or2", T, F), T) + checkComp(e, mkCall("or2", T, T), T) + + checkComp(e, mkCall("safe", IL(1)), T) + checkComp(e, mkCall("safe", IL(2)), F) + + // This one needs short-circuit. + checkComp(e, mkCall("safe", IL(0)), F) + } + } + + test("Case classes") { + val p = """|object Program { + | sealed abstract class List + | case class Nil() extends List + | case class Cons(head : Int, tail : List) extends List + | + | def size(l : List) : Int = l match { + | case Nil() => 0 + | case Cons(_, xs) => 1 + size(xs) + | } + | + | def compare(l1 : List, l2 : List) : Boolean = (l1 == l2) + | + | def head(l : List) : Int = l match { + | case Cons(h, _) => h + | } + |}""".stripMargin + + implicit val prog = parseString(p) + + val evaluators = prepareEvaluators + + val nil = mkCaseClass("Nil") + val cons12a = mkCaseClass("Cons", IL(1), mkCaseClass("Cons", IL(2), mkCaseClass("Nil"))) + val cons12b = mkCaseClass("Cons", IL(1), mkCaseClass("Cons", IL(2), mkCaseClass("Nil"))) + + for(e <- evaluators) { + checkComp(e, mkCall("size", nil), IL(0)) + checkComp(e, mkCall("size", cons12a), IL(2)) + checkComp(e, mkCall("compare", nil, cons12a), F) + checkComp(e, mkCall("compare", cons12a, cons12b), T) + checkComp(e, mkCall("head", cons12a), IL(1)) + + // Match error + checkError(e, mkCall("head", nil)) + } + } + + test("Sets") { + val p = """|object Program { + | sealed abstract class List + | case class Nil() extends List + | case class Cons(head : Int, tail : List) extends List + | + | def content(l : List) : Set[Int] = l match { + | case Nil() => Set.empty[Int] + | case Cons(x, xs) => Set(x) ++ content(xs) + | } + | + | 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 diff(s1 : Set[Int], s2 : Set[Int]) : Set[Int] = s1 -- s2 + |}""".stripMargin + + implicit val prog = parseString(p) + + val evaluators = prepareEvaluators + + val nil = mkCaseClass("Nil") + val cons12 = mkCaseClass("Cons", IL(1), mkCaseClass("Cons", IL(2), mkCaseClass("Nil"))) + + val semp = FiniteSet(Seq.empty).setType(SetType(Int32Type)) + val s123 = FiniteSet(Seq(IL(1), IL(2), IL(3))).setType(SetType(Int32Type)) + val s246 = FiniteSet(Seq(IL(2), IL(4), IL(6))).setType(SetType(Int32Type)) + + for(e <- evaluators) { + checkSetComp(e, mkCall("finite"), Set(1, 2, 3)) + checkSetComp(e, mkCall("content", nil), Set.empty) + checkSetComp(e, mkCall("content", cons12), Set(1,2)) + checkSetComp(e, mkCall("build", IL(1), IL(2), IL(3)), Set(1,2,3)) + checkSetComp(e, mkCall("build", IL(1), IL(2), IL(2)), Set(1,2)) + checkSetComp(e, mkCall("union", s123, s246), Set(1,2,3,4,6)) + checkSetComp(e, mkCall("union", s246, s123), Set(1,2,3,4,6)) + checkComp(e, Equals(mkCall("union", s123, s246), mkCall("union", s246, s123)), T) + checkSetComp(e, mkCall("inter", s123, s246), Set(2)) + checkSetComp(e, mkCall("inter", s246, s123), Set(2)) + checkComp(e, Equals(mkCall("inter", s123, s246), mkCall("inter", s246, s123)), T) + checkSetComp(e, mkCall("diff", s123, s246), Set(1,3)) + checkSetComp(e, mkCall("diff", s246, s123), Set(4,6)) + checkComp(e, Equals(mkCall("diff", s123, s246), mkCall("diff", s246, s123)), F) + } + } + + test("Maps") { + val p = """|object Program { + |sealed abstract class PList + |case class PNil() extends PList + |case class PCons(headfst : Int, headsnd : Int, tail : PList) extends PList + | + |def toMap(pl : PList) : Map[Int,Int] = pl match { + | case PNil() => Map.empty[Int,Int] + | case PCons(f,s,xs) => toMap(xs).updated(f, s) + |} + | + |def finite0() : Map[Int,Int] = Map() + |def finite1() : Map[Int,Int] = Map(1 -> 2) + |def finite2() : Map[Int,Int] = Map(2 -> 3, 1 -> 2) + |def finite3() : Map[Int,Int] = finite1().updated(2, 3) + |}""".stripMargin + + implicit val prog = parseString(p) + + val evaluators = prepareEvaluators + + val cons1223 = mkCaseClass("PCons", IL(1), IL(2), mkCaseClass("PCons", IL(2), IL(3), mkCaseClass("PNil"))) + + for(e <- evaluators) { + checkMapComp(e, mkCall("finite0"), Map.empty) + checkMapComp(e, mkCall("finite1"), Map(1 -> 2)) + checkMapComp(e, mkCall("finite2"), Map(1 -> 2, 2 -> 3)) + checkComp(e, Equals(mkCall("finite1"), mkCall("finite2")), F) + checkComp(e, Equals(mkCall("finite2"), mkCall("finite3")), T) + checkMapComp(e, mkCall("toMap", cons1223), Map(1 -> 2, 2 -> 3)) + checkComp(e, MapIsDefinedAt(mkCall("finite2"), IL(2)), T) + checkComp(e, MapIsDefinedAt(mkCall("finite2"), IL(3)), F) + } + } +} diff --git a/src/test/scala/leon/test/purescala/LikelyEq.scala b/src/test/scala/leon/test/purescala/LikelyEq.scala index 5de9e10ea..f1a6e971b 100644 --- a/src/test/scala/leon/test/purescala/LikelyEq.scala +++ b/src/test/scala/leon/test/purescala/LikelyEq.scala @@ -1,17 +1,20 @@ package leon.test.purescala -import leon.Evaluator._ -import leon.purescala.Trees._ -import leon.purescala.TreeOps.replace +import leon._ +import leon.evaluators._ import leon.purescala.Common._ +import leon.purescala.Definitions._ +import leon.purescala.TreeOps.replace +import leon.purescala.Trees._ /* - * Determine if two expressions over arithmetic variables are likely to be the same + * Determine if two expressions over arithmetic variables are likely to be equal. * * This is a probabilistic based approach, it does not rely on any external solver and can * only prove the non equality of two expressions. */ object LikelyEq { + private lazy val evaluator : Evaluator = new DefaultEvaluator(LeonContext(reporter = new SilentReporter), Program.empty) private val min = -5 private val max = 5 @@ -29,9 +32,9 @@ object LikelyEq { compare: (Expr, Expr) => Boolean = (e1, e2) => e1 == e2, defaultMap: Map[Identifier, Expr] = Map()): Boolean = { if(vs.isEmpty) { - val ndm = defaultMap.map{ case (id, expr) => (id, eval(Map(), expr, None).asInstanceOf[OK].result) } //TODO: not quite sure why I need to do this... - (eval(ndm, e1, None), eval(defaultMap, e2, None)) match { - case (OK(v1), OK(v2)) => compare(v1, v2) + val ndm = defaultMap.map { case (id, expr) => (id, evaluator.eval(expr).asInstanceOf[EvaluationSuccessful].value) } //TODO: not quite sure why I need to do this... + (evaluator.eval(e1, ndm), evaluator.eval(e2, defaultMap)) match { + case (EvaluationSuccessful(v1), EvaluationSuccessful(v2)) => compare(v1, v2) case (err1, err2) => sys.error("evaluation could not complete, got: (" + err1 + ", " + err2 + ")") } } else { @@ -46,14 +49,14 @@ object LikelyEq { val ne1 = replace(m, e1) val ne2 = replace(m, e2) val npre = replace(m, pre) - val ndm = defaultMap.map{ case (id, expr) => (id, eval(m.map{case (Variable(id), t) => (id, t)}, expr, None).asInstanceOf[OK].result) } - eval(ndm, npre, None) match { - case OK(BooleanLiteral(false)) => - case OK(BooleanLiteral(true)) => - val ev1 = eval(ndm, ne1, None) - val ev2 = eval(ndm, ne2, None) + val ndm = defaultMap.map{ case (id, expr) => (id, evaluator.eval(expr, m.map{case (Variable(id), t) => (id, t)}).asInstanceOf[EvaluationSuccessful].value) } + evaluator.eval(npre, ndm) match { + case EvaluationSuccessful(BooleanLiteral(false)) => + case EvaluationSuccessful(BooleanLiteral(true)) => + val ev1 = evaluator.eval(ne1, ndm) + val ev2 = evaluator.eval(ne2, ndm) (ev1, ev2) match { - case (OK(v1), OK(v2)) => if(!compare(v1, v2)) isEq = false + case (EvaluationSuccessful(v1), EvaluationSuccessful(v2)) => if(!compare(v1, v2)) isEq = false case (err1, err2) => sys.error("evaluation could not complete, got: (" + err1 + ", " + err2 + ")") } case err => sys.error("evaluation of precondition could not complete, got: " + err) diff --git a/src/test/scala/leon/test/purescala/LikelyEqSuite.scala b/src/test/scala/leon/test/purescala/LikelyEqSuite.scala index dcc0788b0..4ba6a5845 100644 --- a/src/test/scala/leon/test/purescala/LikelyEqSuite.scala +++ b/src/test/scala/leon/test/purescala/LikelyEqSuite.scala @@ -2,13 +2,11 @@ package leon.test.purescala import org.scalatest.FunSuite -import leon.Evaluator -import leon.purescala.Trees._ import leon.purescala.Common._ +import leon.purescala.Trees._ class LikelyEqSuite extends FunSuite { - def i(x: Int) = IntLiteral(x) val xId = FreshIdentifier("x") diff --git a/src/test/scala/leon/test/purescala/TreeOpsTests.scala b/src/test/scala/leon/test/purescala/TreeOpsTests.scala index a7ca3dac3..b19018e59 100644 --- a/src/test/scala/leon/test/purescala/TreeOpsTests.scala +++ b/src/test/scala/leon/test/purescala/TreeOpsTests.scala @@ -14,15 +14,10 @@ import org.scalatest.FunSuite class TreeOpsTests extends FunSuite { private val silentContext = LeonContext(reporter = new SilentReporter) - private val emptyProgram = Program( - FreshIdentifier("Empty"), - ObjectDef(FreshIdentifier("Empty"), Seq.empty, Seq.empty) - ) - test("Path-aware simplifications") { import leon.solvers.z3.UninterpretedZ3Solver val solver = new UninterpretedZ3Solver(silentContext) - solver.setProgram(emptyProgram) + solver.setProgram(Program.empty) // TODO actually testing something here would be better, sorry // PS diff --git a/src/test/scala/leon/test/solvers/TimeoutSolverTests.scala b/src/test/scala/leon/test/solvers/TimeoutSolverTests.scala index 0372f4706..e94e071bc 100644 --- a/src/test/scala/leon/test/solvers/TimeoutSolverTests.scala +++ b/src/test/scala/leon/test/solvers/TimeoutSolverTests.scala @@ -26,14 +26,9 @@ class TimeoutSolverTests extends FunSuite { } } - private val emptyProgram = Program( - FreshIdentifier("empty"), - ObjectDef(FreshIdentifier("empty"), Seq.empty, Seq.empty) - ) - private def getTOSolver : Solver = { val s = new TimeoutSolver(new IdioticSolver(LeonContext()), 1) - s.setProgram(emptyProgram) + s.setProgram(Program.empty) s } diff --git a/src/test/scala/leon/test/synthesis/LinearEquationsSuite.scala b/src/test/scala/leon/test/synthesis/LinearEquationsSuite.scala index 1f49ae517..95d8706be 100644 --- a/src/test/scala/leon/test/synthesis/LinearEquationsSuite.scala +++ b/src/test/scala/leon/test/synthesis/LinearEquationsSuite.scala @@ -2,7 +2,6 @@ package leon.test.synthesis import org.scalatest.FunSuite -import leon.Evaluator import leon.purescala.Trees._ import leon.purescala.TypeTrees._ import leon.purescala.TreeOps._ diff --git a/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala b/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala index 77a64fef4..74ce1ddc9 100644 --- a/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala +++ b/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala @@ -21,7 +21,7 @@ class PureScalaVerificationRegression extends FunSuite { private def mkPipeline : Pipeline[List[String],VerificationReport] = leon.plugin.ExtractionPhase andThen leon.verification.AnalysisPhase - private def mkTest(file : File, forError: Boolean = false)(block: Output=>Unit) = { + private def mkTest(file : File, leonOptions : Seq[LeonOption], forError: Boolean)(block: Output=>Unit) = { val fullName = file.getPath() val start = fullName.indexOf("regression") @@ -31,7 +31,7 @@ class PureScalaVerificationRegression extends FunSuite { fullName } - test("%3d: %s".format(nextInt(), displayName)) { + test("%3d: %s %s".format(nextInt(), displayName, leonOptions.mkString(" "))) { assert(file.exists && file.isFile && file.canRead, "Benchmark %s is not a readable file".format(displayName)) @@ -41,7 +41,7 @@ class PureScalaVerificationRegression extends FunSuite { xlang = false, verify = true ), - options = List(LeonFlagOption("feelinglucky")), + options = leonOptions.toList, files = List(file), reporter = new SilentReporter ) @@ -67,7 +67,8 @@ class PureScalaVerificationRegression extends FunSuite { _.endsWith(".scala")) for(f <- fs) { - mkTest(f, forError)(block) + mkTest(f, List(LeonFlagOption("feelinglucky")), forError)(block) + mkTest(f, List(LeonFlagOption("codegen"), LeonFlagOption("feelinglucky")), forError)(block) } } diff --git a/unmanaged/common/cafebabe_2.9.2-1.2.jar b/unmanaged/common/cafebabe_2.9.2-1.2.jar index 47ba4d4848e69cb70792570da656c576701949b6..bd36c4eee8b7548a6bb0e4fba9003597fc5bf2f6 100644 GIT binary patch delta 45543 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 delta 42876 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 Z1$eWvfs#%)V>hE$Jp;oGMRo=T1^@}8WWoRd -- GitLab