diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala index 71920325e88979042fd7add19cd4f7b45edcca21..8f79149b9eb3290209ede19c6b7afb11410af3f0 100644 --- a/src/main/scala/leon/codegen/CompilationUnit.scala +++ b/src/main/scala/leon/codegen/CompilationUnit.scala @@ -231,7 +231,7 @@ class CompilationUnit(val ctx: LeonContext, else GenericValue(tp, id).copiedFrom(gv) case (set: runtime.Set, SetType(b)) => - finiteSet(set.getElements.asScala.map(jvmToExpr(_, b)).toSet, b) + FiniteSet(set.getElements.asScala.map(jvmToExpr(_, b)).toSet, b) case (map: runtime.Map, MapType(from, to)) => val pairs = map.getElements.asScala.map { entry => @@ -239,7 +239,7 @@ class CompilationUnit(val ctx: LeonContext, val v = jvmToExpr(entry.getValue, to) (k, v) } - finiteMap(pairs.toSeq, from, to) + FiniteMap(pairs.toSeq, from, to) case (lambda: runtime.Lambda, _: FunctionType) => val cls = lambda.getClass diff --git a/src/main/scala/leon/datagen/VanuatooDataGen.scala b/src/main/scala/leon/datagen/VanuatooDataGen.scala index 4b48a2ac576c7ce3aed6280bb9c8a8e74d58721f..c4100ceef464368de733a11ca9b67f2a5c3226b4 100644 --- a/src/main/scala/leon/datagen/VanuatooDataGen.scala +++ b/src/main/scala/leon/datagen/VanuatooDataGen.scala @@ -79,7 +79,7 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { Constructor[Expr, TypeTree]( (1 to size).map(i => sub).toList, st, - s => finiteSet(s.toSet, sub), + s => FiniteSet(s.toSet, sub), st.toString+"@"+size ) } @@ -99,7 +99,7 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { 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, from, to), mt.toString+"@"+size) + Constructor[Expr, TypeTree](subs, mt, s => FiniteMap(s.grouped(2).map(t => (t(0), t(1))).toSeq, from, to), mt.toString+"@"+size) } constructors += mt -> cs cs diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala index 77e74b5303816b6b0a6a56c3e4e646762a0cc335..ff2e8309103d117aa8738c20803e485547186561 100644 --- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala +++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala @@ -399,7 +399,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int (e(s1), e(s2)) match { case (f@FiniteSet(els1, _),FiniteSet(els2, _)) => val SetType(tpe) = f.getType - finiteSet(els1 ++ els2, tpe) + FiniteSet(els1 ++ els2, tpe) case (le,re) => throw EvalError(typeErrorMsg(le, s1.getType)) } @@ -408,7 +408,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int case (f @ FiniteSet(els1, _), FiniteSet(els2, _)) => { val newElems = els1 intersect els2 val SetType(tpe) = f.getType - finiteSet(newElems, tpe) + FiniteSet(newElems, tpe) } case (le,re) => throw EvalError(typeErrorMsg(le, s1.getType)) } @@ -418,7 +418,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int case (f @ FiniteSet(els1, _),FiniteSet(els2, _)) => { val SetType(tpe) = f.getType val newElems = els1 -- els2 - finiteSet(newElems, tpe) + FiniteSet(newElems, tpe) } case (le,re) => throw EvalError(typeErrorMsg(le, s1.getType)) } @@ -439,7 +439,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int } case f @ FiniteSet(els, base) => - finiteSet(els.map(e), base) + FiniteSet(els.map(e), base) case l @ Lambda(_, _) => val mapping = variablesOf(l).map(id => id -> e(Variable(id))).toMap @@ -477,7 +477,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int ) case f @ FiniteMap(ss, kT, vT) => - finiteMap(ss.map{ case (k, v) => (e(k), e(v)) }.distinct, kT, vT) + FiniteMap(ss.map{ case (k, v) => (e(k), e(v)) }.distinct, kT, vT) case g @ MapGet(m,k) => (e(m), e(k)) match { case (FiniteMap(ss, _, _), e) => ss.find(_._1 == e) match { @@ -491,7 +491,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int val filtered1 = ss1.filterNot(s1 => ss2.exists(s2 => s2._1 == s1._1)) val newSs = filtered1 ++ ss2 val MapType(kT, vT) = u.getType - finiteMap(newSs, kT, vT) + FiniteMap(newSs, kT, vT) } case (l, r) => throw EvalError(typeErrorMsg(l, m1.getType)) } diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala index 362b225ce37d041255d867407f9eab159fbeca60..0c81ec1d4f9a387355958f8700fabb8c4c55e43c 100644 --- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala +++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala @@ -1410,10 +1410,10 @@ trait CodeExtraction extends ASTExtractors { outOfSubsetError(tr, "Some map elements could not be extracted as Tuple2") } - finiteMap(singletons, extractType(tptFrom), extractType(tptTo)) + FiniteMap(singletons, extractType(tptFrom), extractType(tptTo)) case ExFiniteSet(tpt, args) => - finiteSet(args.map(extractTree).toSet, extractType(tpt)) + FiniteSet(args.map(extractTree).toSet, extractType(tpt)) case ExCaseClassConstruction(tpt, args) => extractType(tpt) match { @@ -1695,7 +1695,7 @@ trait CodeExtraction extends ASTExtractors { ElementOfSet(a2, a1) case (IsTyped(a1, SetType(b1)), "isEmpty", List()) => - Equals(a1, finiteSet(Set(), b1)) + Equals(a1, FiniteSet(Set(), b1)) // Multiset methods case (IsTyped(a1, MultisetType(b1)), "++", List(IsTyped(a2, MultisetType(b2)))) if b1 == b2 => diff --git a/src/main/scala/leon/purescala/Constructors.scala b/src/main/scala/leon/purescala/Constructors.scala index 2c15bdaf386c427365faac434fe64aacd5c6c949..ce97e591284b460008bcd882fa17283b5b890828 100644 --- a/src/main/scala/leon/purescala/Constructors.scala +++ b/src/main/scala/leon/purescala/Constructors.scala @@ -187,19 +187,11 @@ object Constructors { case _ => Implies(lhs, rhs) } - def finiteSet(els: Set[Expr], tpe: TypeTree) = { - FiniteSet(els, tpe) - } - def finiteMultiset(els: Seq[Expr], tpe: TypeTree) = { if (els.isEmpty) EmptyMultiset(tpe) else NonemptyMultiset(els) } - def finiteMap(els: Seq[(Expr, Expr)], keyType: TypeTree, valueType: TypeTree) = { - FiniteMap(els, keyType, valueType) - } - def finiteArray(els: Seq[Expr]): Expr = { require(els.nonEmpty) finiteArray(els, None, Untyped) // Untyped is not correct, but will not be used anyway diff --git a/src/main/scala/leon/purescala/ExprOps.scala b/src/main/scala/leon/purescala/ExprOps.scala index a80cdb41c4e144ef847e06f935125568602450cc..b3bd13f5d380c8955d7068d02ee761aac6b30ed9 100644 --- a/src/main/scala/leon/purescala/ExprOps.scala +++ b/src/main/scala/leon/purescala/ExprOps.scala @@ -1948,18 +1948,25 @@ object ExprOps { } def isListLiteral(e: Expr): Option[(TypeTree, List[Expr])] = e match { - case CaseClass(cct, args) => - programOf(cct.classDef) flatMap { p => - val lib = p.library - if (Some(cct.classDef) == lib.Nil) { - Some((cct.tps.head, Nil)) - } else if (Some(cct.classDef) == lib.Cons) { - isListLiteral(args(1)).map { case (_, t) => - (cct.tps.head, args.head :: t) - } - } else None - } - case _ => None + case CaseClass(CaseClassType(classDef, Seq(tp)), Nil) => + for { + p <- programOf(classDef) + leonNil <- p.library.Nil + if classDef == leonNil + } yield { + (tp, Nil) + } + case CaseClass(CaseClassType(classDef, Seq(tp)), Seq(hd, tl)) => + for { + p <- programOf(classDef) + leonCons <- p.library.Cons + if classDef == leonCons + (_, tlElems) <- isListLiteral(tl) + } yield { + (tp, hd :: tlElems) + } + case _ => + None } diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala index 9fb28e66d21877d0ab88441d6fa586c684ea85ab..c363c60ba1568a8129f755eca985b9f02f5a2fa0 100644 --- a/src/main/scala/leon/purescala/Extractors.scala +++ b/src/main/scala/leon/purescala/Extractors.scala @@ -13,7 +13,7 @@ object Extractors { object UnaryOperator { def unapply(expr: Expr) : Option[(Expr,(Expr)=>Expr)] = expr match { - case Not(t) => Some((t,Not(_))) + case Not(t) => Some((t,not)) case UMinus(t) => Some((t,UMinus)) case BVUMinus(t) => Some((t,BVUMinus)) case BVNot(t) => Some((t,BVNot)) @@ -45,7 +45,7 @@ object Extractors { LetDef(fd, body) } )) - case Equals(t1,t2) => Some((t1,t2,Equals.apply)) + case Equals(t1,t2) => Some((t1,t2,Equals)) case Implies(t1,t2) => Some((t1,t2, implies)) case Plus(t1,t2) => Some((t1,t2,Plus)) case Minus(t1,t2) => Some((t1,t2,Minus)) @@ -78,15 +78,15 @@ object Extractors { case MultisetUnion(t1,t2) => Some((t1,t2,MultisetUnion)) case MultisetPlus(t1,t2) => Some((t1,t2,MultisetPlus)) case MultisetDifference(t1,t2) => Some((t1,t2,MultisetDifference)) - case mg@MapGet(t1,t2) => Some((t1,t2, (t1, t2) => MapGet(t1, t2).setPos(mg))) + case mg@MapGet(t1,t2) => Some((t1,t2, MapGet)) case MapUnion(t1,t2) => Some((t1,t2,MapUnion)) case MapDifference(t1,t2) => Some((t1,t2,MapDifference)) case MapIsDefinedAt(t1,t2) => Some((t1,t2, MapIsDefinedAt)) case ArraySelect(t1, t2) => Some((t1, t2, ArraySelect)) - case Let(binders, e, body) => Some((e, body, (e: Expr, b: Expr) => Let(binders, e, b))) + case Let(binder, e, body) => Some((e, body, let(binder, _, _))) case Require(pre, body) => Some((pre, body, Require)) - case Ensuring(body, post) => Some((body, post, (b: Expr, p: Expr) => Ensuring(b, p))) - case Assert(const, oerr, body) => Some((const, body, (c: Expr, b: Expr) => Assert(c, oerr, b))) + case Ensuring(body, post) => Some((body, post, Ensuring)) + case Assert(const, oerr, body) => Some((const, body, Assert(_, oerr, _))) case (ex: BinaryExtractable) => ex.extract case _ => None } @@ -102,9 +102,9 @@ object Extractors { case Seq(pred) => Choose(pred, None) case Seq(pred, impl) => Choose(pred, Some(impl)) })) - case fi @ FunctionInvocation(fd, args) => Some((args, as => FunctionInvocation(fd, as).setPos(fi))) - case mi @ MethodInvocation(rec, cd, tfd, args) => Some((rec +: args, as => MethodInvocation(as.head, cd, tfd, as.tail).setPos(mi))) - case fa @ Application(caller, args) => Some(caller +: args, as => application(as.head, as.tail).setPos(fa)) + case fi @ FunctionInvocation(fd, args) => Some((args, FunctionInvocation(fd, _))) + case mi @ MethodInvocation(rec, cd, tfd, args) => Some((rec +: args, as => MethodInvocation(as.head, cd, tfd, as.tail))) + case fa @ Application(caller, args) => Some(caller +: args, as => application(as.head, as.tail)) case CaseClass(cd, args) => Some((args, CaseClass(cd, _))) case And(args) => Some((args, and)) case Or(args) => Some((args, or)) @@ -136,11 +136,11 @@ object Extractors { } case NonemptyArray(elems, None) => val all = elems.map(_._2).toSeq - Some(( all, finiteArray _ )) - case Tuple(args) => Some((args, Tuple)) + Some(( all, finiteArray)) + case Tuple(args) => Some((args, tupleWrap)) case IfExpr(cond, thenn, elze) => Some(( - Seq(cond, thenn, elze), - (as: Seq[Expr]) => IfExpr(as(0), as(1), as(2)) + Seq(cond, thenn, elze), + { case Seq(c,t,e) => IfExpr(c,t,e) } )) case MatchExpr(scrut, cases) => Some(( scrut +: cases.flatMap { @@ -166,7 +166,7 @@ object Extractors { case GuardedCase(b, _, _) => i+=2; GuardedCase(b, es(i-1), es(i-2)) } - Passes(in, out, newcases) + passes(in, out, newcases) }} )) case (ex: NAryExtractable) => ex.extract @@ -181,35 +181,19 @@ object Extractors { object StringLiteral { def unapply(e: Expr): Option[String] = e match { case CaseClass(cct, args) => - DefOps.programOf(cct.classDef) flatMap { p => - val lib = p.library - - if (Some(cct.classDef) == lib.String) { - isListLiteral(args.head) match { - case Some((_, chars)) => - val str = chars.map { - case CharLiteral(c) => Some(c) - case _ => None - } - - if (str.forall(_.isDefined)) { - Some(str.flatten.mkString) - } else { - None - } - case _ => - None - - } - } else { - None - } + for { + p <- DefOps.programOf(cct.classDef) + libS <- p.library.String + if cct.classDef == libS + (_, chars) <- isListLiteral(args.head) + if chars.forall(_.isInstanceOf[CharLiteral]) + } yield { + chars.collect{ case CharLiteral(c) => c }.mkString } case _ => None } } - object TopLevelOrs { // expr1 AND (expr2 AND (expr3 AND ..)) => List(expr1, expr2, expr3) def unapply(e: Expr): Option[Seq[Expr]] = e match { diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Solver.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Solver.scala index f43e4bd831c16cb87a1eb671261e438ee5b5e33c..dfe6df71419ff6b9fc817fe3525b72335a3cad5f 100644 --- a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Solver.scala +++ b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Solver.scala @@ -88,15 +88,15 @@ class SMTLIBCVC4Solver(context: LeonContext, program: Program) extends SMTLIBSol finiteLambda(dflt, mapping :+ (fromSMT(key, tupleTypeWrap(from)) -> fromSMT(elem, to)), from) case (FunctionApplication(SimpleSymbol(SSymbol("singleton")), elems), SetType(base)) => - finiteSet(elems.map(fromSMT(_, base)).toSet, base) + FiniteSet(elems.map(fromSMT(_, base)).toSet, base) case (FunctionApplication(SimpleSymbol(SSymbol("insert")), elems), SetType(base)) => val selems = elems.init.map(fromSMT(_, base)) val FiniteSet(se, _) = fromSMT(elems.last, tpe) - finiteSet(se ++ selems, base) + FiniteSet(se ++ selems, base) case (FunctionApplication(SimpleSymbol(SSymbol("union")), elems), SetType(base)) => - finiteSet(elems.map(fromSMT(_, tpe) match { + FiniteSet(elems.map(fromSMT(_, tpe) match { case FiniteSet(elems, _) => elems }).flatten.toSet, base) diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala index b5560fb0b4d5861ed226d63c74407c3a4392eaa0..722e2566afadeb49e980c77b73747c24a9683414 100644 --- a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala +++ b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala @@ -159,7 +159,7 @@ abstract class SMTLIBSolver(val context: LeonContext, } require(r.keyTpe == base, s"Type error in solver model, expected $base, found ${r.keyTpe}") - finiteSet(r.elems.keySet, base) + FiniteSet(r.elems.keySet, base) case RawArrayType(from, to) => r @@ -180,7 +180,7 @@ abstract class SMTLIBSolver(val context: LeonContext, case (k, CaseClass(leonSome, Seq(x))) => Some(k -> x) case (k, _) => None }.toSeq - finiteMap(elems, from, to) + FiniteMap(elems, from, to) case _ => unsupported("Unable to extract from raw array for "+tpe) diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala index fe7b0fec729419f29fbbe346c38fe3e7a14dca40..3959e2265f67ac446faf4e2d4ea81fd8f617b562 100644 --- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala +++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala @@ -714,7 +714,7 @@ trait AbstractZ3Solver case (k, _) => None }.toSeq - finiteMap(elems, from, to) + FiniteMap(elems, from, to) } @@ -732,7 +732,7 @@ trait AbstractZ3Solver case None => throw new IllegalArgumentException case Some(set) => val elems = set.map(e => rec(e, dt)) - finiteSet(elems, dt) + FiniteSet(elems, dt) } case _ => diff --git a/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala b/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala index 3752b228c2bf2c6b84c7445f2c22b6628e2c9380..ebb4bb8faf22ddd1bf25a5b0ab26cbaea41d2add 100644 --- a/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala +++ b/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala @@ -124,7 +124,7 @@ object ExpressionGrammars { case st @ SetType(base) => List( - Generator(List(base), { case elems => finiteSet(elems.toSet, base) }), + Generator(List(base), { case elems => FiniteSet(elems.toSet, base) }), Generator(List(st, st), { case Seq(a, b) => SetUnion(a, b) }), Generator(List(st, st), { case Seq(a, b) => SetIntersection(a, b) }), Generator(List(st, st), { case Seq(a, b) => SetDifference(a, b) }) @@ -177,8 +177,8 @@ object ExpressionGrammars { case st @ SetType(base) => List( - Generator(List(base), { case elems => finiteSet(elems.toSet, base) }), - Generator(List(base, base), { case elems => finiteSet(elems.toSet, base) }) + Generator(List(base), { case elems => FiniteSet(elems.toSet, base) }), + Generator(List(base, base), { case elems => FiniteSet(elems.toSet, base) }) ) case UnitType => diff --git a/src/test/resources/regression/verification/purescala/invalid/Array4.scala b/src/test/resources/regression/verification/purescala/invalid/Array4.scala index 4e630cd428758454bc00f9e5355e502939839ad3..d7875d9b3ea09be869429c801fe59716213aac3a 100644 --- a/src/test/resources/regression/verification/purescala/invalid/Array4.scala +++ b/src/test/resources/regression/verification/purescala/invalid/Array4.scala @@ -6,7 +6,7 @@ object Array4 { def foo(a: Array[Int]): Int = { val tmp = a.updated(0, 0) - 42 + tmp(0) } }