From 45f42fc33a2e4deb3081d9ad3de974e7112edad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Blanc?= <regwblanc@gmail.com> Date: Fri, 4 May 2012 04:34:31 +0000 Subject: [PATCH] cleaner (and more correct) separation of array operation --- src/main/scala/leon/ArrayTransformation.scala | 2 +- src/main/scala/leon/Evaluator.scala | 10 +++--- src/main/scala/leon/FairZ3Solver.scala | 32 ++++++++++++------- .../scala/leon/purescala/PrettyPrinter.scala | 5 +++ src/main/scala/leon/purescala/Trees.scala | 2 ++ testcases/regression/valid/Array3.scala | 12 ++++--- 6 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/main/scala/leon/ArrayTransformation.scala b/src/main/scala/leon/ArrayTransformation.scala index 95e8719b1..dd1fee89e 100644 --- a/src/main/scala/leon/ArrayTransformation.scala +++ b/src/main/scala/leon/ArrayTransformation.scala @@ -25,7 +25,7 @@ object ArrayTransformation extends Pass { case fill@ArrayFill(length, default) => { var rLength = transform(length) val rDefault = transform(default) - val rFill = ArrayFill(length, default).setType(fill.getType) + val rFill = ArrayMake(rDefault).setType(fill.getType) Tuple(Seq(rFill, length)).setType(TupleType(Seq(fill.getType, Int32Type))) } case sel@ArraySelect(a, i) => { diff --git a/src/main/scala/leon/Evaluator.scala b/src/main/scala/leon/Evaluator.scala index 6f72611ce..47337af61 100644 --- a/src/main/scala/leon/Evaluator.scala +++ b/src/main/scala/leon/Evaluator.scala @@ -248,11 +248,9 @@ object Evaluator { case i @ IntLiteral(_) => i case b @ BooleanLiteral(_) => b - case f @ ArrayFill(length, default) => { - val rLength = rec(ctx, length) + case f @ ArrayMake(default) => { val rDefault = rec(ctx, default) - assert(rLength.isInstanceOf[IntLiteral]) - ArrayFill(rLength, rDefault) + ArrayMake(rDefault) } case ArrayUpdated(a, i, v) => { val ra = rec(ctx, a) @@ -266,7 +264,7 @@ object Evaluator { var ra = rec(ctx, a) var found = false var result: Option[Expr] = None - while(!ra.isInstanceOf[ArrayFill] && !found) { + while(!ra.isInstanceOf[ArrayMake] && !found) { val ArrayUpdated(ra2, IntLiteral(i), v) = ra if(index == i) { result = Some(v) @@ -277,7 +275,7 @@ object Evaluator { } result match { case Some(r) => r - case None => ra.asInstanceOf[ArrayFill].defaultValue + case None => ra.asInstanceOf[ArrayMake].defaultValue } } diff --git a/src/main/scala/leon/FairZ3Solver.scala b/src/main/scala/leon/FairZ3Solver.scala index 7a21e9ab2..3ab173b7d 100644 --- a/src/main/scala/leon/FairZ3Solver.scala +++ b/src/main/scala/leon/FairZ3Solver.scala @@ -525,14 +525,11 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S reporter.info(" - Initial unrolling...") val (clauses, guards) = unrollingBank.initialUnrolling(expandedVC) - //for(clause <- clauses) { - //println("we're getting a new clause " + clause) - // z3.assertCnstr(toZ3Formula(z3, clause).get) - //} + for(clause <- clauses) { + Logger.debug("we're getting a new clause " + clause, 4, "z3solver") + } - //println("The blocking guards: " + guards) val cc = toZ3Formula(z3, And(clauses)).get - // println("CC : " + cc) z3.assertCnstr(cc) // these are the optional sequence of assumption literals @@ -573,6 +570,7 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S (a, m, Seq.empty[Z3AST]) } reporter.info(" - Finished search with blocked literals") + Logger.debug("The blocking guards are: " + blockingSet.mkString(", "), 4, "z3solver") // if (Settings.useCores) // reporter.info(" - Core is : " + core) @@ -747,16 +745,13 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S reporter.info(" - more unrollings") for((id,polarity) <- toReleaseAsPairs) { val (newClauses,newBlockers) = unrollingBank.unlock(id, !polarity) - //println("Unlocked : " + (id, !polarity)) for(clause <- newClauses) { - //println("we're getting a new clause " + clause) - // z3.assertCnstr(toZ3Formula(z3, clause).get) + Logger.debug("we're getting a new clause " + clause, 4, "z3solver") } for(ncl <- newClauses) { z3.assertCnstr(toZ3Formula(z3, ncl).get) } - //z3.assertCnstr(toZ3Formula(z3, And(newClauses)).get) blockingSet = blockingSet ++ Set(newBlockers.map(p => if(p._2) Not(Variable(p._1)) else Variable(p._1)) : _*) } reporter.info(" - finished unrolling") @@ -1055,8 +1050,8 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S case MapType(ft, tt) => z3.mkDistinct(z3.mkSelect(rec(m), rec(k)), mapRangeNoneConstructors(tt)()) case errorType => scala.sys.error("Unexpected type for map: " + (ex, errorType)) } - case fill@ArrayFill(length, default) => { - val ArrayType(base) = fill.getType + case a@ArrayMake(default) => { + val ArrayType(base) = a.getType z3.mkConstArray(typeToSort(base), rec(default)) } case ArraySelect(ar, index) => { @@ -1122,6 +1117,19 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S (if (elems.isEmpty) EmptySet(dt) else FiniteSet(elems.toSeq)).setType(expType.get) } } + case Some(ArrayType(dt)) => + model.getArrayValue(t) match { + case None => throw new CantTranslateException(t) + case Some((map, elseValue)) => + map.foldLeft(ArrayMake(rec(elseValue, Some(dt))): Expr) { + case (acc, (key, value)) => ArrayUpdated(acc, rec(key, Some(Int32Type)), rec(value, Some(dt))) + } + } + case Some(TupleType(tpes)) => { + val Z3AppAST(decl, args) = z3.getASTKind(t) + val rargs = args.zip(tpes).map(p => rec(p._1, Some(p._2))) + Tuple(rargs) + } case other => z3.getASTKind(t) match { case Z3AppAST(decl, args) => { diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index 848c1dad3..b0b0bba08 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -260,6 +260,11 @@ object PrettyPrinter { pp(v, sb, lvl) sb.append(")#" + fill.getType) } + case am@ArrayMake(v) => { + sb.append("Array.make(") + pp(v, sb, lvl) + sb.append(")") + } case sel@ArraySelect(ar, i) => { pp(ar, sb, lvl) sb.append("(") diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala index b308dbf53..030845358 100644 --- a/src/main/scala/leon/purescala/Trees.scala +++ b/src/main/scala/leon/purescala/Trees.scala @@ -381,6 +381,7 @@ object Trees { /* Array operations */ case class ArrayFill(length: Expr, defaultValue: Expr) extends Expr + case class ArrayMake(defaultValue: Expr) extends Expr case class ArraySelect(array: Expr, index: Expr) extends Expr //the difference between ArrayUpdate and ArrayUpdated is that the former has a side effect while the latter is the function variant //ArrayUpdate should be eliminated soon in the analysis while ArrayUpdated is keep all the way to the backend @@ -423,6 +424,7 @@ object Trees { case Assignment(id, e) => Some((e, Assignment(id, _))) case TupleSelect(t, i) => Some((t, TupleSelect(_, i))) case ArrayLength(a) => Some((a, ArrayLength)) + case ArrayMake(t) => Some((t, ArrayMake)) case e@Epsilon(t) => Some((t, (expr: Expr) => Epsilon(expr).setType(e.getType).setPosInfo(e))) case _ => None } diff --git a/testcases/regression/valid/Array3.scala b/testcases/regression/valid/Array3.scala index d51894c36..bbb1845b8 100644 --- a/testcases/regression/valid/Array3.scala +++ b/testcases/regression/valid/Array3.scala @@ -1,14 +1,16 @@ -object Array1 { +import leon.Utils._ + +object Array3 { def foo(): Int = { - val a = Array.fill(5)(0) + val a = Array.fill(5)(3) var i = 0 var sum = 0 - while(i < a.length) { + (while(i < a.length) { sum = sum + a(i) i = i + 1 - } + }) invariant(i >= 0) sum - } ensuring(_ == 0) + } ensuring(_ == 15) } -- GitLab