diff --git a/library/collection/List.scala b/library/collection/List.scala index c9ebac9d3590d9b4831097342d556022a9ced95b..f4ab47a45ee75e571242c6b7bf72cbd8ec35e270 100644 --- a/library/collection/List.scala +++ b/library/collection/List.scala @@ -8,8 +8,8 @@ import leon.annotation._ @library sealed abstract class List[T] { - def size: Int = (this match { - case Nil() => 0 + def size: BigInt = (this match { + case Nil() => BigInt(0) case Cons(h, t) => 1 + t.size }) ensuring (_ >= 0) @@ -43,9 +43,9 @@ sealed abstract class List[T] { } } - def apply(index: Int): T = { + def apply(index: BigInt): T = { require(0 <= index && index < size) - if (index == 0) { + if (index == BigInt(0)) { head } else { tail(index-1) @@ -68,27 +68,27 @@ sealed abstract class List[T] { } } ensuring (res => (res.size == size) && (res.content == content)) - def take(i: Int): List[T] = (this, i) match { + def take(i: BigInt): List[T] = (this, i) match { case (Nil(), _) => Nil() case (Cons(h, t), i) => - if (i == 0) { + if (i == BigInt(0)) { Nil() } else { Cons(h, t.take(i-1)) } } - def drop(i: Int): List[T] = (this, i) match { + def drop(i: BigInt): List[T] = (this, i) match { case (Nil(), _) => Nil() case (Cons(h, t), i) => - if (i == 0) { + if (i == BigInt(0)) { Cons(h, t) } else { t.drop(i-1) } } - def slice(from: Int, to: Int): List[T] = { + def slice(from: BigInt, to: BigInt): List[T] = { require(from < to && to < size && from >= 0) drop(from).take(to-from) } @@ -104,7 +104,7 @@ sealed abstract class List[T] { } } - private def chunk0(s: Int, l: List[T], acc: List[T], res: List[List[T]], s0: Int): List[List[T]] = l match { + private def chunk0(s: BigInt, l: List[T], acc: List[T], res: List[List[T]], s0: BigInt): List[List[T]] = l match { case Nil() => if (acc.size > 0) { res :+ acc @@ -112,14 +112,14 @@ sealed abstract class List[T] { res } case Cons(h, t) => - if (s0 == 0) { + if (s0 == BigInt(0)) { chunk0(s, l, Nil(), res :+ acc, s) } else { chunk0(s, t, acc :+ h, res, s0-1) } } - def chunks(s: Int): List[List[T]] = { + def chunks(s: BigInt): List[List[T]] = { require(s > 0) chunk0(s, this, Nil(), Nil(), s) @@ -165,7 +165,7 @@ sealed abstract class List[T] { Nil() } - def pad(s: Int, e: T): List[T] = (this, s) match { + def pad(s: BigInt, e: T): List[T] = (this, s) match { case (_, s) if s <= 0 => this case (Nil(), s) => @@ -174,7 +174,7 @@ sealed abstract class List[T] { Cons(h, t.pad(s-1, e)) } - def find(e: T): Option[Int] = this match { + def find(e: T): Option[BigInt] = this match { case Nil() => None() case Cons(h, t) => if (h == e) { @@ -194,7 +194,7 @@ sealed abstract class List[T] { Cons[T](h, t.init) case Nil() => Nil[T]() - }) ensuring ( (r: List[T]) => ((r.size < this.size) || (this.size == 0)) ) + }) ensuring ( (r: List[T]) => ((r.size < this.size) || (this.size == BigInt(0))) ) def lastOption: Option[T] = this match { case Cons(h, t) => @@ -230,7 +230,7 @@ sealed abstract class List[T] { Cons(Nil(), Nil()) } - def count(e: T): Int = this match { + def count(e: T): BigInt = this match { case Cons(h, t) => if (h == e) { 1 + t.count(e) @@ -238,7 +238,7 @@ sealed abstract class List[T] { t.count(e) } case Nil() => - 0 + BigInt(0) } def evenSplit: (List[T], List[T]) = { @@ -246,10 +246,10 @@ sealed abstract class List[T] { (take(c), drop(c)) } - def insertAt(pos: Int, l: List[T]): List[T] = { + def insertAt(pos: BigInt, l: List[T]): List[T] = { if(pos < 0) { insertAt(size + pos, l) - } else if(pos == 0) { + } else if(pos == BigInt(0)) { l ++ this } else { this match { @@ -261,10 +261,10 @@ sealed abstract class List[T] { } } - def replaceAt(pos: Int, l: List[T]): List[T] = { + def replaceAt(pos: BigInt, l: List[T]): List[T] = { if(pos < 0) { replaceAt(size + pos, l) - } else if(pos == 0) { + } else if(pos == BigInt(0)) { l ++ this.drop(l.size) } else { this match { @@ -276,7 +276,7 @@ sealed abstract class List[T] { } } - def rotate(s: Int): List[T] = { + def rotate(s: BigInt): List[T] = { if (s < 0) { rotate(size+s) } else { @@ -304,19 +304,19 @@ object ListOps { case Nil() => Nil() } - def isSorted(ls: List[Int]): Boolean = ls match { + def isSorted(ls: List[BigInt]): Boolean = ls match { case Nil() => true case Cons(_, Nil()) => true case Cons(h1, Cons(h2, _)) if(h1 > h2) => false case Cons(_, t) => isSorted(t) } - def sorted(ls: List[Int]): List[Int] = ls match { + def sorted(ls: List[BigInt]): List[BigInt] = ls match { case Cons(h, t) => insSort(sorted(t), h) case Nil() => Nil() } - def insSort(ls: List[Int], v: Int): List[Int] = ls match { + def insSort(ls: List[BigInt], v: BigInt): List[BigInt] = ls match { case Nil() => Cons(v, Nil()) case Cons(h, t) => if (v <= h) { @@ -333,7 +333,7 @@ case class Nil[T]() extends List[T] @library object ListSpecs { - def snocIndex[T](l : List[T], t : T, i : Int) : Boolean = { + def snocIndex[T](l : List[T], t : T, i : BigInt) : Boolean = { require(0 <= i && i < l.size + 1) // proof: (l match { @@ -344,7 +344,7 @@ object ListSpecs { ((l :+ t).apply(i) == (if (i < l.size) l(i) else t)) }.holds - def reverseIndex[T](l : List[T], i : Int) : Boolean = { + def reverseIndex[T](l : List[T], i : BigInt) : Boolean = { require(0 <= i && i < l.size) (l match { case Nil() => true @@ -353,11 +353,11 @@ object ListSpecs { (l.reverse.apply(i) == l.apply(l.size - 1 - i)) }.holds - def appendIndex[T](l1 : List[T], l2 : List[T], i : Int) : Boolean = { + def appendIndex[T](l1 : List[T], l2 : List[T], i : BigInt) : Boolean = { require(0 <= i && i < l1.size + l2.size) (l1 match { case Nil() => true - case Cons(x,xs) => if (i==0) true else appendIndex[T](xs,l2,i-1) + case Cons(x,xs) => if (i==BigInt(0)) true else appendIndex[T](xs,l2,i-1) }) && ((l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size))) }.holds diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala index 8a548ecdb009a6bb4c89cbca5b66dc85353b91dd..dbca0c5de0d920cf2b2528fe23c8b52d1123bb11 100644 --- a/src/main/scala/leon/codegen/CodeGeneration.scala +++ b/src/main/scala/leon/codegen/CodeGeneration.scala @@ -84,6 +84,7 @@ trait CodeGeneration { /** Return the respective JVM type from a Leon type */ def typeToJVM(tpe : TypeTree) : String = tpe match { case Int32Type => "I" + case IntegerType => "I" case BooleanType => "Z" @@ -118,6 +119,7 @@ trait CodeGeneration { /** Return the respective boxed JVM type from a Leon type */ def typeToJVMBoxed(tpe : TypeTree) : String = tpe match { case Int32Type => s"L$BoxedIntClass;" + case IntegerType => s"L$BoxedIntClass;" case BooleanType | UnitType => s"L$BoxedBoolClass;" case CharType => s"L$BoxedCharClass;" case other => typeToJVM(other) @@ -190,7 +192,7 @@ trait CodeGeneration { mkExpr(bodyWithPost, ch)(Locals(newMapping, Map.empty, Map.empty, isStatic)) funDef.returnType match { - case Int32Type | BooleanType | UnitType => + case IntegerType | Int32Type | BooleanType | UnitType => ch << IRETURN case _ : ClassType | _ : TupleType | _ : SetType | _ : MapType | _ : ArrayType | _ : FunctionType | _ : TypeParameter => @@ -218,7 +220,7 @@ trait CodeGeneration { mkExpr(d, ch) val slot = ch.getFreshVar val instr = i.getType match { - case Int32Type | CharType | BooleanType | UnitType => IStore(slot) + case IntegerType | Int32Type | CharType | BooleanType | UnitType => IStore(slot) case _ => AStore(slot) } ch << instr @@ -226,6 +228,8 @@ trait CodeGeneration { case IntLiteral(v) => ch << Ldc(v) + case InfiniteIntegerLiteral(v) => + ch << Ldc(v.toInt) case CharLiteral(v) => ch << Ldc(v) @@ -562,6 +566,9 @@ trait CodeGeneration { ch << InvokeSpecial(afName, constructorName, consSig) // Arithmetic + /* + * TODO: Correct code generation for infinite precision operations + */ case Plus(l, r) => mkExpr(l, ch) mkExpr(r, ch) @@ -591,6 +598,37 @@ trait CodeGeneration { mkExpr(e, ch) ch << INEG + //BV arithmetic + case BVPlus(l, r) => + mkExpr(l, ch) + mkExpr(r, ch) + ch << IADD + + case BVMinus(l, r) => + mkExpr(l, ch) + mkExpr(r, ch) + ch << ISUB + + case BVTimes(l, r) => + mkExpr(l, ch) + mkExpr(r, ch) + ch << IMUL + + case BVDivision(l, r) => + mkExpr(l, ch) + mkExpr(r, ch) + ch << IDIV + + case BVModulo(l, r) => + mkExpr(l, ch) + mkExpr(r, ch) + ch << IREM + + case BVUMinus(e) => + mkExpr(e, ch) + ch << INEG + + case ArrayLength(a) => mkExpr(a, ch) ch << ARRAYLENGTH @@ -602,6 +640,7 @@ trait CodeGeneration { case Untyped => throw CompilationException("Cannot compile untyped array access.") case CharType => CALOAD case Int32Type => IALOAD + case IntegerType => IALOAD case BooleanType => BALOAD case _ => AALOAD }) @@ -613,6 +652,7 @@ trait CodeGeneration { val storeInstr = a.getType match { case ArrayType(CharType) => ch << NewArray.primitive("T_CHAR"); CASTORE case ArrayType(Int32Type) => ch << NewArray.primitive("T_INT"); IASTORE + case ArrayType(IntegerType) => ch << NewArray.primitive("T_INT"); IASTORE case ArrayType(BooleanType) => ch << NewArray.primitive("T_BOOLEAN"); BASTORE case ArrayType(other) => ch << NewArray(typeToJVM(other)); AASTORE case other => throw CompilationException("Cannot compile finite array expression whose type is %s.".format(other)) @@ -637,6 +677,7 @@ trait CodeGeneration { val storeInstr = a.getType match { case ArrayType(CharType) => ch << NewArray.primitive("T_CHAR"); CASTORE case ArrayType(Int32Type) => ch << NewArray.primitive("T_INT"); IASTORE + case ArrayType(IntegerType) => ch << NewArray.primitive("T_INT"); IASTORE case ArrayType(BooleanType) => ch << NewArray.primitive("T_BOOLEAN"); BASTORE case ArrayType(other) => ch << NewArray(typeToJVM(other)); AASTORE case other => throw CompilationException("Cannot compile finite array expression whose type is %s.".format(other)) @@ -719,6 +760,10 @@ trait CodeGeneration { ch << New(BoxedIntClass) << DUP mkExpr(e, ch) ch << InvokeSpecial(BoxedIntClass, constructorName, "(I)V") + case IntegerType => + ch << New(BoxedIntClass) << DUP + mkExpr(e, ch) + ch << InvokeSpecial(BoxedIntClass, constructorName, "(I)V") case BooleanType | UnitType => ch << New(BoxedBoolClass) << DUP @@ -746,6 +791,8 @@ trait CodeGeneration { tpe match { case Int32Type => ch << New(BoxedIntClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedIntClass, constructorName, "(I)V") + case IntegerType => + ch << New(BoxedIntClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedIntClass, constructorName, "(I)V") case BooleanType | UnitType => ch << New(BoxedBoolClass) << DUP_X1 << SWAP << InvokeSpecial(BoxedBoolClass, constructorName, "(Z)V") @@ -764,6 +811,8 @@ trait CodeGeneration { tpe match { case Int32Type => ch << CheckCast(BoxedIntClass) << InvokeVirtual(BoxedIntClass, "intValue", "()I") + case IntegerType => + ch << CheckCast(BoxedIntClass) << InvokeVirtual(BoxedIntClass, "intValue", "()I") case BooleanType | UnitType => ch << CheckCast(BoxedBoolClass) << InvokeVirtual(BoxedBoolClass, "booleanValue", "()Z") @@ -834,7 +883,7 @@ trait CodeGeneration { mkExpr(l, ch) mkExpr(r, ch) l.getType match { - case Int32Type | BooleanType | UnitType | CharType => + case Int32Type | IntegerType | BooleanType | UnitType | CharType => ch << If_ICmpEq(thenn) << Goto(elze) case _ => @@ -894,7 +943,7 @@ trait CodeGeneration { case None => locals.varToLocal(id) match { case Some(slot) => val instr = id.getType match { - case Int32Type | CharType | BooleanType | UnitType => ILoad(slot) + case IntegerType | Int32Type | CharType | BooleanType | UnitType => ILoad(slot) case _ => ALoad(slot) } ch << instr @@ -985,7 +1034,7 @@ trait CodeGeneration { ch << Label(initLabel) // return lzy //newValue lzy.returnType match { - case Int32Type | BooleanType | UnitType | CharType => + case Int32Type | IntegerType | BooleanType | UnitType | CharType => // Since the underlying field only has boxed types, we have to unbox them to return them mkUnbox(lzy.returnType, ch)(NoLocals(isStatic)) ch << IRETURN diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala index 5bf34b1f70f3bd0b3ec4e52b3eb9713a17fc7685..b24a5f0f91406a732c99f30cdb3ba86fb9f2606c 100644 --- a/src/main/scala/leon/codegen/CompilationUnit.scala +++ b/src/main/scala/leon/codegen/CompilationUnit.scala @@ -125,6 +125,8 @@ class CompilationUnit(val ctx: LeonContext, def exprToJVM(e: Expr)(implicit monitor : LeonCodeGenRuntimeMonitor): AnyRef = e match { case IntLiteral(v) => new java.lang.Integer(v) + case InfiniteIntegerLiteral(v) => + new java.lang.Integer(v.toInt) case BooleanLiteral(v) => new java.lang.Boolean(v) @@ -184,6 +186,8 @@ class CompilationUnit(val ctx: LeonContext, def jvmToExpr(e: AnyRef, tpe: TypeTree): Expr = (e, tpe) match { case (i: Integer, Int32Type) => IntLiteral(i.toInt) + case (i: Integer, IntegerType) => + InfiniteIntegerLiteral(i.toInt) case (b: java.lang.Boolean, BooleanType) => BooleanLiteral(b.booleanValue) @@ -284,7 +288,7 @@ class CompilationUnit(val ctx: LeonContext, mkExpr(e, ch)(Locals(newMapping, Map.empty, Map.empty, true)) e.getType match { - case Int32Type | BooleanType => + case IntegerType | Int32Type | BooleanType => ch << IRETURN case UnitType | _: TupleType | _: SetType | _: MapType | _: AbstractClassType | _: CaseClassType | _: ArrayType | _: FunctionType | _: TypeParameter => diff --git a/src/main/scala/leon/datagen/VanuatooDataGen.scala b/src/main/scala/leon/datagen/VanuatooDataGen.scala index 6adab6929b9bac530248f97f769fb53c8e53e4a4..e40af01e948f6fc0f6c15bd182fc6f6e091e7b87 100644 --- a/src/main/scala/leon/datagen/VanuatooDataGen.scala +++ b/src/main/scala/leon/datagen/VanuatooDataGen.scala @@ -23,11 +23,17 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { i -> Constructor[Expr, TypeTree](List(), Int32Type, s => IntLiteral(i), ""+i) }).toMap + val bigInts = (for (i <- Set(0, 1, 2, 3)) yield { + i -> Constructor[Expr, TypeTree](List(), IntegerType, s => InfiniteIntegerLiteral(i), ""+i) + }).toMap + val booleans = (for (b <- Set(true, false)) yield { b -> Constructor[Expr, TypeTree](List(), BooleanType, s => BooleanLiteral(b), ""+b) }).toMap def intConstructor(i: Int) = ints(i) + + def bigIntConstructor(i: Int) = bigInts(i) def boolConstructor(b: Boolean) = booleans(b) @@ -133,6 +139,9 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { case (i: Integer, Int32Type) => (cPattern(intConstructor(i), List()), true) + case (i: Integer, IntegerType) => + (cPattern(bigIntConstructor(i), List()), true) + case (b: java.lang.Boolean, BooleanType) => (cPattern(boolConstructor(b), List()), true) @@ -256,7 +265,7 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { }).flatten - val gen = new StubGenerator[Expr, TypeTree]((ints.values ++ booleans.values).toSeq, + val gen = new StubGenerator[Expr, TypeTree]((ints.values ++ bigInts.values ++ booleans.values).toSeq, Some(getConstructors _), treatEmptyStubsAsChildless = true) @@ -274,7 +283,7 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { return new Iterator[Seq[Expr]] { var total = 0 - var found = 0; + var found = 0 var theNext: Option[Seq[Expr]] = None @@ -294,6 +303,7 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator { def computeNext(): Option[Seq[Expr]] = { + //return None while(total < maxEnumerated && found < maxValid && it.hasNext && !interrupted.get) { val model = it.next.asInstanceOf[Tuple] diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala index fa0148b5df985576caa41bddb661d5c26477e0bb..1d060afb63c140889ac5e3dfeb69e83261ad2fd7 100644 --- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala +++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala @@ -229,63 +229,106 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int } case Plus(l,r) => + (e(l), e(r)) match { + case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => InfiniteIntegerLiteral(i1 + i2) + case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType)) + } + + case Minus(l,r) => + (e(l), e(r)) match { + case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => InfiniteIntegerLiteral(i1 - i2) + case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType)) + } + + case BVPlus(l,r) => (e(l), e(r)) match { case (IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 + i2) case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } - case Minus(l,r) => + case BVMinus(l,r) => (e(l), e(r)) match { case (IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 - i2) case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case UMinus(ex) => + e(ex) match { + case InfiniteIntegerLiteral(i) => InfiniteIntegerLiteral(-i) + case re => throw EvalError(typeErrorMsg(re, IntegerType)) + } + + case BVUMinus(ex) => e(ex) match { case IntLiteral(i) => IntLiteral(-i) case re => throw EvalError(typeErrorMsg(re, Int32Type)) } case Times(l,r) => + (e(l), e(r)) match { + case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => InfiniteIntegerLiteral(i1 * i2) + case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType)) + } + + case Division(l,r) => + (e(l), e(r)) match { + case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => + if(i2 != 0) InfiniteIntegerLiteral(i1 / i2) else throw RuntimeError("Division by 0.") + case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType)) + } + + case Modulo(l,r) => + (e(l), e(r)) match { + case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => + if(i2 != 0) InfiniteIntegerLiteral(i1 % i2) else throw RuntimeError("Modulo by 0.") + case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType)) + } + + case BVTimes(l,r) => (e(l), e(r)) match { case (IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 * i2) case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } - case Division(l,r) => + case BVDivision(l,r) => (e(l), e(r)) match { 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) => + case BVModulo(l,r) => (e(l), e(r)) match { 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) => (e(l), e(r)) match { case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 < i2) + case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 < i2) case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case GreaterThan(l,r) => (e(l), e(r)) match { case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 > i2) + case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 > i2) case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case LessEquals(l,r) => (e(l), e(r)) match { case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 <= i2) + case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 <= i2) case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } case GreaterEquals(l,r) => (e(l), e(r)) match { case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 >= i2) + case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 >= i2) case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type)) } @@ -332,6 +375,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int case f @ FiniteSet(els) => FiniteSet(els.map(e(_))).setType(f.getType) case i @ IntLiteral(_) => i + case i @ InfiniteIntegerLiteral(_) => i case b @ BooleanLiteral(_) => b case u @ UnitLiteral() => u case l @ Lambda(_, _) => l diff --git a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala index 0424350cf2ae76a1f4e1a9b08d3c95faa156e484..8f9f8b0b7c0e8eec1ac28b6a5b48d3be9bb6735f 100644 --- a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala +++ b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala @@ -36,12 +36,15 @@ trait ASTExtractors { protected lazy val function4TraitSym = classFromName("scala.Function4") protected lazy val function5TraitSym = classFromName("scala.Function5") protected lazy val byNameSym = classFromName("scala.<byname>") + protected lazy val bigIntSym = classFromName("scala.math.BigInt") def isTuple2(sym : Symbol) : Boolean = sym == tuple2Sym def isTuple3(sym : Symbol) : Boolean = sym == tuple3Sym def isTuple4(sym : Symbol) : Boolean = sym == tuple4Sym def isTuple5(sym : Symbol) : Boolean = sym == tuple5Sym + def isBigIntSym(sym : Symbol) : Boolean = getResolvedTypeSym(sym) == bigIntSym + def isByNameSym(sym : Symbol) : Boolean = getResolvedTypeSym(sym) == byNameSym // Resolve type aliases @@ -88,6 +91,8 @@ trait ASTExtractors { val tpe = t.tpe.widen tpe =:= IntClass.tpe } + + def hasBigIntType(t : Tree) = isBigIntSym(t.tpe.typeSymbol) object ExtractorHelpers { @@ -214,6 +219,24 @@ trait ASTExtractors { } } + object ExBigIntLiteral { + def unapply(tree: Tree): Option[Int] = tree match { + case Apply(ExSelected("scala", "package", "BigInt", "apply"), (n: Literal) :: Nil) => + Some(n.value.intValue) + case _ => + None + } + } + + + object ExIntToBigInt { + def unapply(tree: Tree): Option[Tree] = tree match { + case Apply(ExSelected("math", "BigInt", "int2bigInt"), tree :: Nil) => Some(tree) + case _ => None + } + } + + object ExListLiteral { def unapply(tree: Apply): Option[(Tree, List[Tree])] = tree match { case Apply( @@ -714,6 +737,13 @@ trait ASTExtractors { } object ExUMinus { + def unapply(tree: Select): Option[Tree] = tree match { + case Select(t, n) if (n == nme.UNARY_- && hasBigIntType(t)) => Some(t) + case _ => None + } + } + + object ExBVUMinus { def unapply(tree: Select): Option[Tree] = tree match { case Select(t, n) if (n == nme.UNARY_- && hasIntType(t)) => Some(t) case _ => None diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala index 369be0adfbba6ba4dfba7e7229c41785c8ccb4dc..8b63ff7318f6b414715e851bcf8c661021f966a0 100644 --- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala +++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala @@ -1204,6 +1204,20 @@ trait CodeExtraction extends ASTExtractors { val newValueRec = extractTree(newValue) ArrayUpdate(lhsRec, indexRec, newValueRec) + case ExBigIntLiteral(n) => { + InfiniteIntegerLiteral(BigInt(n)) + } + + case ExIntToBigInt(tree) => { + val rec = extractTree(tree) + rec match { + case IntLiteral(n) => + InfiniteIntegerLiteral(BigInt(n)) + case _ => + IntToBigInt(rec) + } + } + case ExInt32Literal(v) => IntLiteral(v) @@ -1314,6 +1328,7 @@ trait CodeExtraction extends ASTExtractors { case ExNot(e) => Not(extractTree(e)) case ExUMinus(e) => UMinus(extractTree(e)) + case ExBVUMinus(e) => BVUMinus(extractTree(e)) case ExEquals(l, r) => val rl = extractTree(l) @@ -1457,6 +1472,8 @@ trait CodeExtraction extends ASTExtractors { CaseClass(CaseClassType(libraryCaseClass(str.pos, "leon.lang.string.String"), Seq()), Seq(charList)) + + case c @ ExCall(rec, sym, tps, args) => val rrec = rec match { case t if (defsToDefs contains sym) && !isMethod(sym) => @@ -1499,21 +1516,43 @@ trait CodeExtraction extends ASTExtractors { case (a1, "!=", List(a2)) => Not(Equals(a1, a2)) + //BigInt methods + case (IsTyped(a1, IntegerType), "+", List(IsTyped(a2, IntegerType))) => + Plus(a1, a2) + case (IsTyped(a1, IntegerType), "-", List(IsTyped(a2, IntegerType))) => + Minus(a1, a2) + case (IsTyped(a1, IntegerType), "*", List(IsTyped(a2, IntegerType))) => + Times(a1, a2) + case (IsTyped(a1, IntegerType), "%", List(IsTyped(a2, IntegerType))) => + Modulo(a1, a2) + case (IsTyped(a1, IntegerType), "/", List(IsTyped(a2, IntegerType))) => + Division(a1, a2) + case (IsTyped(a1, IntegerType), ">", List(IsTyped(a2, IntegerType))) => + GreaterThan(a1, a2) + case (IsTyped(a1, IntegerType), ">=", List(IsTyped(a2, IntegerType))) => + GreaterEquals(a1, a2) + case (IsTyped(a1, IntegerType), "<", List(IsTyped(a2, IntegerType))) => + LessThan(a1, a2) + case (IsTyped(a1, IntegerType), "<=", List(IsTyped(a2, IntegerType))) => + LessEquals(a1, a2) + case (IsTyped(a1, IntegerType), "<=", List(IsTyped(a2, IntegerType))) => + LessEquals(a1, a2) + // Int methods case (IsTyped(a1, Int32Type), "+", List(IsTyped(a2, Int32Type))) => - Plus(a1, a2) + BVPlus(a1, a2) case (IsTyped(a1, Int32Type), "-", List(IsTyped(a2, Int32Type))) => - Minus(a1, a2) + BVMinus(a1, a2) case (IsTyped(a1, Int32Type), "*", List(IsTyped(a2, Int32Type))) => - Times(a1, a2) + BVTimes(a1, a2) case (IsTyped(a1, Int32Type), "%", List(IsTyped(a2, Int32Type))) => - Modulo(a1, a2) + BVModulo(a1, a2) case (IsTyped(a1, Int32Type), "/", List(IsTyped(a2, Int32Type))) => - Division(a1, a2) + BVDivision(a1, a2) case (IsTyped(a1, Int32Type), ">", List(IsTyped(a2, Int32Type))) => GreaterThan(a1, a2) @@ -1642,6 +1681,9 @@ trait CodeExtraction extends ASTExtractors { case tpe if tpe == NothingClass.tpe => Untyped + case TypeRef(_, sym, _) if isBigIntSym(sym) => + IntegerType + case TypeRef(_, sym, btt :: Nil) if isSetTraitSym(sym) => SetType(extractType(btt)) diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala index f2cd6bc079b83e5eb8f4dc24ddaf0bf98c89ad87..a62521d84f17c91e62039514a3bb2a200080c79f 100644 --- a/src/main/scala/leon/purescala/Extractors.scala +++ b/src/main/scala/leon/purescala/Extractors.scala @@ -18,6 +18,7 @@ object Extractors { def unapply(expr: Expr) : Option[(Expr,(Expr)=>Expr)] = expr match { case Not(t) => Some((t,Not(_))) case UMinus(t) => Some((t,UMinus)) + case BVUMinus(t) => Some((t,BVUMinus)) case SetCardinality(t) => Some((t,SetCardinality)) case MultisetCardinality(t) => Some((t,MultisetCardinality)) case MultisetToSet(t) => Some((t,MultisetToSet)) @@ -51,6 +52,11 @@ object Extractors { case GreaterThan(t1,t2) => Some((t1,t2,GreaterThan)) case LessEquals(t1,t2) => Some((t1,t2,LessEquals)) case GreaterEquals(t1,t2) => Some((t1,t2,GreaterEquals)) + case BVPlus(t1,t2) => Some((t1,t2,BVPlus)) + case BVMinus(t1,t2) => Some((t1,t2,BVMinus)) + case BVTimes(t1,t2) => Some((t1,t2,BVTimes)) + case BVDivision(t1,t2) => Some((t1,t2,BVDivision)) + case BVModulo(t1,t2) => Some((t1,t2,BVModulo)) case ElementOfSet(t1,t2) => Some((t1,t2,ElementOfSet)) case SubsetOf(t1,t2) => Some((t1,t2,SubsetOf)) case SetIntersection(t1,t2) => Some((t1,t2,SetIntersection)) diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index 8127e0af690531b2f1dd8af443661b9411ad24ed..baa1a2c203f941d782213b136b33a8fb24969c55 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -269,8 +269,10 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe case Not(Equals(l, r)) => optP { p"$l \u2260 $r" } case Implies(l,r) => optP { p"$l ==> $r" } case UMinus(expr) => p"-$expr" + case BVUMinus(expr) => p"-$expr" case Equals(l,r) => optP { p"$l == $r" } case IntLiteral(v) => p"$v" + case InfiniteIntegerLiteral(v) => p"BigInt($v)" case CharLiteral(v) => p"$v" case BooleanLiteral(v) => p"$v" case StringLiteral(s) => p""""$s"""" @@ -341,6 +343,11 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe case GreaterThan(l,r) => optP { p"$l > $r" } case LessEquals(l,r) => optP { p"$l <= $r" } case GreaterEquals(l,r) => optP { p"$l >= $r" } + case BVPlus(l,r) => optP { p"$l + $r" } + case BVMinus(l,r) => optP { p"$l - $r" } + case BVTimes(l,r) => optP { p"$l * $r" } + case BVDivision(l,r) => optP { p"$l / $r" } + case BVModulo(l,r) => optP { p"$l % $r" } case FiniteSet(rs) => p"{${rs.toSeq}}" case FiniteMultiset(rs) => p"{|$rs|)" case EmptyMultiset(_) => p"\u2205" @@ -379,7 +386,7 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe s match { case IntLiteral(length) => { if(es.size == length) { - val orderedElements = es.toSeq.sortWith((e1, e2) => e1._1 < e2._1) + val orderedElements = es.toSeq.sortWith((e1, e2) => e1._1 < e2._1).map(el => el._2) p"Array($orderedElements)" } else if(length < 10) { val elems = (0 until length).map(i => @@ -487,6 +494,7 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe case Untyped => p"<untyped>" case UnitType => p"Unit" case Int32Type => p"Int" + case IntegerType => p"BigInt" case CharType => p"Char" case BooleanType => p"Boolean" case ArrayType(bt) => p"Array[$bt]" @@ -697,8 +705,8 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe case (_: And | BinaryMethodCall(_, "&&", _)) => 3 case (_: GreaterThan | _: GreaterEquals | _: LessEquals | _: LessThan) => 4 case (_: Equals | _: Not) => 5 - case (_: Plus | _: Minus | _: SetUnion| _: SetDifference | BinaryMethodCall(_, "+" | "-", _)) => 6 - case (_: Times | _: Division | _: Modulo | BinaryMethodCall(_, "*" | "/", _)) => 7 + case (_: Plus | _: BVPlus | _: Minus | _: BVMinus | _: SetUnion| _: SetDifference | BinaryMethodCall(_, "+" | "-", _)) => 6 + case (_: Times | _: BVTimes | _: Division | _: BVDivision | _: Modulo | _: BVModulo | BinaryMethodCall(_, "*" | "/", _)) => 7 case _ => 7 } diff --git a/src/main/scala/leon/purescala/TreeNormalizations.scala b/src/main/scala/leon/purescala/TreeNormalizations.scala index 2f080d93e6f617d6dce1258e6407a1d129d95cc3..3558ad5984eae73f95a7b00ab6d8ea870ac73fc1 100644 --- a/src/main/scala/leon/purescala/TreeNormalizations.scala +++ b/src/main/scala/leon/purescala/TreeNormalizations.scala @@ -24,34 +24,34 @@ object TreeNormalizations { //assume the expr is a literal (mult of constants and variables) with degree one def extractCoef(e: Expr): (Expr, Identifier) = { var id: Option[Identifier] = None - var coef = 1 + var coef: BigInt = 1 def rec(e: Expr): Unit = e match { - case IntLiteral(i) => coef = coef*i + case InfiniteIntegerLiteral(i) => coef = coef*i case Variable(id2) => if(id.isEmpty) id = Some(id2) else throw NonLinearExpressionException("multiple variable") case Times(e1, e2) => rec(e1); rec(e2) } rec(e) assert(!id.isEmpty) - (IntLiteral(coef), id.get) + (InfiniteIntegerLiteral(coef), id.get) } def containsId(e: Expr, id: Identifier): Boolean = e match { case Times(e1, e2) => containsId(e1, id) || containsId(e2, id) - case IntLiteral(_) => false + case InfiniteIntegerLiteral(_) => false case Variable(id2) => id == id2 case err => throw NonLinearExpressionException("unexpected in containsId: " + err) } def group(es: Seq[Expr], id: Identifier): Expr = { - val totalCoef = es.foldLeft(0)((acc, e) => { - val (IntLiteral(i), id2) = extractCoef(e) + val totalCoef = es.foldLeft(BigInt(0))((acc, e) => { + val (InfiniteIntegerLiteral(i), id2) = extractCoef(e) assert(id2 == id) acc + i }) - Times(IntLiteral(totalCoef), Variable(id)) + Times(InfiniteIntegerLiteral(totalCoef), Variable(id)) } var exprs: Seq[Expr] = expandedForm(expr) @@ -64,7 +64,7 @@ object TreeNormalizations { res(index+1) = coef }} - res(0) = simplifyArithmetic(exprs.foldLeft[Expr](IntLiteral(0))(Plus(_, _))) + res(0) = simplifyArithmetic(exprs.foldLeft[Expr](InfiniteIntegerLiteral(0))(Plus(_, _))) res } @@ -78,11 +78,11 @@ object TreeNormalizations { //do not keep the evaluation order def expandedForm(expr: Expr): Seq[Expr] = expr match { case Plus(es1, es2) => expandedForm(es1) ++ expandedForm(es2) - case Minus(e1, e2) => expandedForm(e1) ++ expandedForm(e2).map(Times(IntLiteral(-1), _): Expr) - case UMinus(e) => expandedForm(e).map(Times(IntLiteral(-1), _): Expr) + case Minus(e1, e2) => expandedForm(e1) ++ expandedForm(e2).map(Times(InfiniteIntegerLiteral(-1), _): Expr) + case UMinus(e) => expandedForm(e).map(Times(InfiniteIntegerLiteral(-1), _): Expr) case Times(es1, es2) => multiply(expandedForm(es1), expandedForm(es2)) - case v@Variable(_) if v.getType == Int32Type => Seq(v) - case n@IntLiteral(_) => Seq(n) + case v@Variable(_) if v.getType == IntegerType => Seq(v) + case n@InfiniteIntegerLiteral(_) => Seq(n) case err => throw NonLinearExpressionException("unexpected in expandedForm: " + err) } diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala index a0313c5dc878fa0f46a9348ccfbbdb02cc45b755..1a256bc82cc197514403703bdd52173aed42e30a 100644 --- a/src/main/scala/leon/purescala/TreeOps.scala +++ b/src/main/scala/leon/purescala/TreeOps.scala @@ -998,6 +998,7 @@ object TreeOps { */ def simplestValue(tpe: TypeTree) : Expr = tpe match { case Int32Type => IntLiteral(0) + case IntegerType => InfiniteIntegerLiteral(0) case CharType => CharLiteral('a') case BooleanType => BooleanLiteral(false) case UnitType => UnitLiteral() @@ -1295,7 +1296,7 @@ object TreeOps { } else { None } - case Untyped | BooleanType | Int32Type | UnitType | TypeParameter(_) => None + case Untyped | BooleanType | Int32Type | IntegerType | UnitType | TypeParameter(_) => None } var idMap = Map[Identifier, Identifier]() @@ -1430,45 +1431,45 @@ object TreeOps { */ def simplifyArithmetic(expr: Expr): Expr = { def simplify0(expr: Expr): Expr = (expr match { - case Plus(IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 + i2) - case Plus(IntLiteral(0), e) => e - case Plus(e, IntLiteral(0)) => e + case Plus(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => InfiniteIntegerLiteral(i1 + i2) + case Plus(InfiniteIntegerLiteral(zero), e) if zero == BigInt(0) => e + case Plus(e, InfiniteIntegerLiteral(zero)) if zero == BigInt(0) => e case Plus(e1, UMinus(e2)) => Minus(e1, e2) - case Plus(Plus(e, IntLiteral(i1)), IntLiteral(i2)) => Plus(e, IntLiteral(i1+i2)) - case Plus(Plus(IntLiteral(i1), e), IntLiteral(i2)) => Plus(IntLiteral(i1+i2), e) + case Plus(Plus(e, InfiniteIntegerLiteral(i1)), InfiniteIntegerLiteral(i2)) => Plus(e, InfiniteIntegerLiteral(i1+i2)) + case Plus(Plus(InfiniteIntegerLiteral(i1), e), InfiniteIntegerLiteral(i2)) => Plus(InfiniteIntegerLiteral(i1+i2), e) - case Minus(e, IntLiteral(0)) => e - case Minus(IntLiteral(0), e) => UMinus(e) - case Minus(IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 - i2) + case Minus(e, InfiniteIntegerLiteral(zero)) if zero == BigInt(0) => e + case Minus(InfiniteIntegerLiteral(zero), e) if zero == BigInt(0) => UMinus(e) + case Minus(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => InfiniteIntegerLiteral(i1 - i2) case Minus(e1, UMinus(e2)) => Plus(e1, e2) case Minus(e1, Minus(UMinus(e2), e3)) => Plus(e1, Plus(e2, e3)) - case UMinus(IntLiteral(x)) => IntLiteral(-x) + case UMinus(InfiniteIntegerLiteral(x)) => InfiniteIntegerLiteral(-x) case UMinus(UMinus(x)) => x case UMinus(Plus(UMinus(e1), e2)) => Plus(e1, UMinus(e2)) case UMinus(Minus(e1, e2)) => Minus(e2, e1) - case Times(IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 * i2) - case Times(IntLiteral(1), e) => e - case Times(IntLiteral(-1), e) => UMinus(e) - case Times(e, IntLiteral(1)) => e - case Times(IntLiteral(0), _) => IntLiteral(0) - case Times(_, IntLiteral(0)) => IntLiteral(0) - case Times(IntLiteral(i1), Times(IntLiteral(i2), t)) => Times(IntLiteral(i1*i2), t) - case Times(IntLiteral(i1), Times(t, IntLiteral(i2))) => Times(IntLiteral(i1*i2), t) - case Times(IntLiteral(i), UMinus(e)) => Times(IntLiteral(-i), e) - case Times(UMinus(e), IntLiteral(i)) => Times(e, IntLiteral(-i)) - case Times(IntLiteral(i1), Division(e, IntLiteral(i2))) if i2 != 0 && i1 % i2 == 0 => Times(IntLiteral(i1/i2), e) - - case Division(IntLiteral(i1), IntLiteral(i2)) if i2 != 0 => IntLiteral(i1 / i2) - case Division(e, IntLiteral(1)) => e + case Times(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => InfiniteIntegerLiteral(i1 * i2) + case Times(InfiniteIntegerLiteral(one), e) if one == BigInt(1) => e + case Times(InfiniteIntegerLiteral(mone), e) if mone == BigInt(-1) => UMinus(e) + case Times(e, InfiniteIntegerLiteral(one)) if one == BigInt(1) => e + case Times(InfiniteIntegerLiteral(zero), _) if zero == BigInt(0) => InfiniteIntegerLiteral(0) + case Times(_, InfiniteIntegerLiteral(zero)) if zero == BigInt(0) => InfiniteIntegerLiteral(0) + case Times(InfiniteIntegerLiteral(i1), Times(InfiniteIntegerLiteral(i2), t)) => Times(InfiniteIntegerLiteral(i1*i2), t) + case Times(InfiniteIntegerLiteral(i1), Times(t, InfiniteIntegerLiteral(i2))) => Times(InfiniteIntegerLiteral(i1*i2), t) + case Times(InfiniteIntegerLiteral(i), UMinus(e)) => Times(InfiniteIntegerLiteral(-i), e) + case Times(UMinus(e), InfiniteIntegerLiteral(i)) => Times(e, InfiniteIntegerLiteral(-i)) + case Times(InfiniteIntegerLiteral(i1), Division(e, InfiniteIntegerLiteral(i2))) if i2 != BigInt(0) && i1 % i2 == BigInt(0) => Times(InfiniteIntegerLiteral(i1/i2), e) + + case Division(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) if i2 != BigInt(0) => InfiniteIntegerLiteral(i1 / i2) + case Division(e, InfiniteIntegerLiteral(one)) if one == BigInt(1) => e //here we put more expensive rules //btw, I know those are not the most general rules, but they lead to good optimizations :) case Plus(UMinus(Plus(e1, e2)), e3) if e1 == e3 => UMinus(e2) case Plus(UMinus(Plus(e1, e2)), e3) if e2 == e3 => UMinus(e1) - case Minus(e1, e2) if e1 == e2 => IntLiteral(0) - case Minus(Plus(e1, e2), Plus(e3, e4)) if e1 == e4 && e2 == e3 => IntLiteral(0) + case Minus(e1, e2) if e1 == e2 => InfiniteIntegerLiteral(0) + case Minus(Plus(e1, e2), Plus(e3, e4)) if e1 == e4 && e2 == e3 => InfiniteIntegerLiteral(0) case Minus(Plus(e1, e2), Plus(Plus(e3, e4), e5)) if e1 == e4 && e2 == e3 => UMinus(e5) //default @@ -1899,8 +1900,8 @@ object TreeOps { val expr0 = try { val freeVars: Array[Identifier] = variablesOf(expr).toArray val coefs: Array[Expr] = TreeNormalizations.linearArithmeticForm(expr, freeVars) - coefs.toList.zip(IntLiteral(1) :: freeVars.toList.map(Variable(_))).foldLeft[Expr](IntLiteral(0))((acc, t) => { - if(t._1 == IntLiteral(0)) acc else Plus(acc, Times(t._1, t._2)) + coefs.toList.zip(InfiniteIntegerLiteral(1) :: freeVars.toList.map(Variable(_))).foldLeft[Expr](InfiniteIntegerLiteral(0))((acc, t) => { + if(t._1 == InfiniteIntegerLiteral(0)) acc else Plus(acc, Times(t._1, t._2)) }) } catch { case _: Throwable => diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala index 5879c42da0a7d30fde9fcb669c0766d4edc6db28..eeb15220ff7a5ed27d7579bf8f0a9c8cb5ab4e01 100644 --- a/src/main/scala/leon/purescala/Trees.scala +++ b/src/main/scala/leon/purescala/Trees.scala @@ -255,6 +255,9 @@ object Trees { case class IntLiteral(value: Int) extends Literal[Int] { val getType = Int32Type } + case class InfiniteIntegerLiteral(value: BigInt) extends Literal[BigInt] { + val getType = IntegerType + } case class BooleanLiteral(value: Boolean) extends Literal[Boolean] { val getType = BooleanType @@ -307,22 +310,28 @@ object Trees { /* Arithmetic */ case class Plus(lhs: Expr, rhs: Expr) extends Expr { - val getType = Int32Type + require(lhs.getType == IntegerType && rhs.getType == IntegerType) + val getType = IntegerType } case class Minus(lhs: Expr, rhs: Expr) extends Expr { - val getType = Int32Type + require(lhs.getType == IntegerType && rhs.getType == IntegerType) + val getType = IntegerType } case class UMinus(expr: Expr) extends Expr { - val getType = Int32Type + require(expr.getType == IntegerType) + val getType = IntegerType } case class Times(lhs: Expr, rhs: Expr) extends Expr { - val getType = Int32Type + require(lhs.getType == IntegerType && rhs.getType == IntegerType) + val getType = IntegerType } case class Division(lhs: Expr, rhs: Expr) extends Expr { - val getType = Int32Type + require(lhs.getType == IntegerType && rhs.getType == IntegerType) + val getType = IntegerType } case class Modulo(lhs: Expr, rhs: Expr) extends Expr { - val getType = Int32Type + require(lhs.getType == IntegerType && rhs.getType == IntegerType) + val getType = IntegerType } case class LessThan(lhs: Expr, rhs: Expr) extends Expr { val getType = BooleanType @@ -337,6 +346,36 @@ object Trees { val getType = BooleanType } + /* Bit-vector arithmetic */ + case class BVPlus(lhs: Expr, rhs: Expr) extends Expr { + require(lhs.getType == Int32Type && rhs.getType == Int32Type) + val getType = Int32Type + } + case class BVMinus(lhs: Expr, rhs: Expr) extends Expr { + require(lhs.getType == Int32Type && rhs.getType == Int32Type) + val getType = Int32Type + } + case class BVUMinus(expr: Expr) extends Expr { + require(expr.getType == Int32Type) + val getType = Int32Type + } + case class BVTimes(lhs: Expr, rhs: Expr) extends Expr { + require(lhs.getType == Int32Type && rhs.getType == Int32Type) + val getType = Int32Type + } + case class BVDivision(lhs: Expr, rhs: Expr) extends Expr { + require(lhs.getType == Int32Type && rhs.getType == Int32Type) + val getType = Int32Type + } + case class BVModulo(lhs: Expr, rhs: Expr) extends Expr { + require(lhs.getType == Int32Type && rhs.getType == Int32Type) + val getType = Int32Type + } + + case class IntToBigInt(expr: Expr) extends Expr { + val getType = Int32Type + } + /* Set expressions */ case class FiniteSet(elements: Set[Expr]) extends Expr with MutableTyped { val tpe = if (elements.isEmpty) None else leastUpperBound(elements.toSeq.map(_.getType)) diff --git a/src/main/scala/leon/purescala/TypeTrees.scala b/src/main/scala/leon/purescala/TypeTrees.scala index 2cc6591ca6d4ad1dd0cd2b37eceb675d264b69d5..05c90501e95f62dc5c7020b22ffd0260223a8df0 100644 --- a/src/main/scala/leon/purescala/TypeTrees.scala +++ b/src/main/scala/leon/purescala/TypeTrees.scala @@ -56,9 +56,12 @@ object TypeTrees { case object Untyped extends TypeTree case object BooleanType extends TypeTree - case object Int32Type extends TypeTree case object UnitType extends TypeTree case object CharType extends TypeTree + case object IntegerType extends TypeTree + + case class BitVectorType(size: Int) extends TypeTree + case object Int32Type extends TypeTree case class TypeParameter(id: Identifier) extends TypeTree { def freshen = TypeParameter(id.freshen) diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala index f754744b271f96e8c125bc0d955477c70a97d5a0..0c69b047b7190194f32bfd74b962c8b2583728df 100644 --- a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala +++ b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala @@ -95,7 +95,8 @@ trait SMTLIBTarget { sorts.cachedB(tpe) { tpe match { case BooleanType => Core.BoolSort() - case Int32Type => Ints.IntSort() + case IntegerType => Ints.IntSort() + case Int32Type => FixedSizeBitVectors.BitVectorSort(32) case CharType => FixedSizeBitVectors.BitVectorSort(32) case RawArrayType(from, to) => @@ -331,7 +332,8 @@ trait SMTLIBTarget { declareVariable(FreshIdentifier("Unit").setType(UnitType)) - case IntLiteral(i) => if (i > 0) Ints.NumeralLit(i) else Ints.Neg(Ints.NumeralLit(-i)) + case InfiniteIntegerLiteral(i) => if (i > 0) Ints.NumeralLit(i) else Ints.Neg(Ints.NumeralLit(-i)) + case IntLiteral(i) => FixedSizeBitVectors.BitVectorLit(Hexadecimal.fromInt(i)) case CharLiteral(c) => FixedSizeBitVectors.BitVectorLit(Hexadecimal.fromInt(c.toInt)) case BooleanLiteral(v) => Core.BoolConst(v) case StringLiteral(s) => SString(s) @@ -452,10 +454,27 @@ trait SMTLIBTarget { case (_: Times) => Ints.Mul(toSMT(a), toSMT(b)) case (_: Division) => Ints.Div(toSMT(a), toSMT(b)) case (_: Modulo) => Ints.Mod(toSMT(a), toSMT(b)) - case (_: LessThan) => Ints.LessThan(toSMT(a), toSMT(b)) - case (_: LessEquals) => Ints.LessEquals(toSMT(a), toSMT(b)) - case (_: GreaterThan) => Ints.GreaterThan(toSMT(a), toSMT(b)) - case (_: GreaterEquals) => Ints.GreaterEquals(toSMT(a), toSMT(b)) + case (_: LessThan) => a.getType match { + case Int32Type => FixedSizeBitVectors.SLessThan(toSMT(a), toSMT(b)) + case IntegerType => Ints.LessThan(toSMT(a), toSMT(b)) + } + case (_: LessEquals) => a.getType match { + case Int32Type => FixedSizeBitVectors.SLessEquals(toSMT(a), toSMT(b)) + case IntegerType => Ints.LessEquals(toSMT(a), toSMT(b)) + } + case (_: GreaterThan) => a.getType match { + case Int32Type => FixedSizeBitVectors.SGreaterThan(toSMT(a), toSMT(b)) + case IntegerType => Ints.GreaterThan(toSMT(a), toSMT(b)) + } + case (_: GreaterEquals) => a.getType match { + case Int32Type => FixedSizeBitVectors.SGreaterEquals(toSMT(a), toSMT(b)) + case IntegerType => Ints.GreaterEquals(toSMT(a), toSMT(b)) + } + case (_: BVPlus) => FixedSizeBitVectors.Add(toSMT(a), toSMT(b)) + case (_: BVMinus) => FixedSizeBitVectors.Sub(toSMT(a), toSMT(b)) + case (_: BVTimes) => FixedSizeBitVectors.Mul(toSMT(a), toSMT(b)) + case (_: BVDivision) => FixedSizeBitVectors.SDiv(toSMT(a), toSMT(b)) + case (_: BVModulo) => FixedSizeBitVectors.SRem(toSMT(a), toSMT(b)) case _ => reporter.fatalError("Unhandled binary "+e) } @@ -490,8 +509,8 @@ trait SMTLIBTarget { case (SHexadecimal(h), CharType) => CharLiteral(h.toInt.toChar) - case (SNumeral(n), Int32Type) => - IntLiteral(n.toInt) + case (SNumeral(n), IntegerType) => + InfiniteIntegerLiteral(n) case (Core.True(), BooleanType) => BooleanLiteral(true) case (Core.False(), BooleanType) => BooleanLiteral(false) @@ -556,8 +575,8 @@ trait SMTLIBTarget { app match { case "-" => args match { - case List(a) => UMinus(fromSMT(a, Int32Type)) - case List(a, b) => Minus(fromSMT(a, Int32Type), fromSMT(b, Int32Type)) + case List(a) => UMinus(fromSMT(a, IntegerType)) + case List(a, b) => Minus(fromSMT(a, IntegerType), fromSMT(b, IntegerType)) } case _ => diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala index dfe0784197c0763915aa58529e686dd66e3a2f21..f73c0ae11e506e664e52204cf4f7e5b68b191eac 100644 --- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala +++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala @@ -377,14 +377,16 @@ trait AbstractZ3Solver ) ) - sorts += Int32Type -> z3.mkIntSort + //TODO: mkBitVectorType + sorts += Int32Type -> z3.mkBVSort(32) + sorts += IntegerType -> z3.mkIntSort sorts += BooleanType -> z3.mkBoolSort sorts += UnitType -> us unitValue = unitCons() - val intSetSort = typeToSort(SetType(Int32Type)) - val intSort = typeToSort(Int32Type) + val intSetSort = typeToSort(SetType(IntegerType)) + val intSort = typeToSort(IntegerType) intSetMinFun = z3.mkFreshFuncDecl("setMin", Seq(intSetSort), intSort) intSetMaxFun = z3.mkFreshFuncDecl("setMax", Seq(intSetSort), intSort) @@ -404,7 +406,7 @@ trait AbstractZ3Solver // assumes prepareSorts has been called.... protected[leon] def typeToSort(oldtt: TypeTree): Z3Sort = normalizeType(oldtt) match { - case Int32Type | BooleanType | UnitType => + case Int32Type | BooleanType | UnitType | IntegerType => sorts.toZ3(oldtt) case act: AbstractClassType => @@ -563,6 +565,7 @@ trait AbstractZ3Solver case Not(Equals(l, r)) => z3.mkDistinct(rec(l), rec(r)) case Not(e) => z3.mkNot(rec(e)) case IntLiteral(v) => z3.mkInt(v, typeToSort(Int32Type)) + case InfiniteIntegerLiteral(v) => z3.mkNumeral(v.toString, typeToSort(IntegerType)) case BooleanLiteral(v) => if (v) z3.mkTrue() else z3.mkFalse() case UnitLiteral() => unitValue case Equals(l, r) => z3.mkEq(rec( l ), rec( r ) ) @@ -572,10 +575,29 @@ trait AbstractZ3Solver case Division(l, r) => z3.mkDiv(rec(l), rec(r)) case Modulo(l, r) => z3.mkMod(rec(l), rec(r)) case UMinus(e) => z3.mkUnaryMinus(rec(e)) - case LessThan(l, r) => z3.mkLT(rec(l), rec(r)) - case LessEquals(l, r) => z3.mkLE(rec(l), rec(r)) - case GreaterThan(l, r) => z3.mkGT(rec(l), rec(r)) - case GreaterEquals(l, r) => z3.mkGE(rec(l), rec(r)) + case BVPlus(l, r) => z3.mkBVAdd(rec(l), rec(r)) + case BVMinus(l, r) => z3.mkBVSub(rec(l), rec(r)) + case BVTimes(l, r) => z3.mkBVMul(rec(l), rec(r)) + case BVDivision(l, r) => z3.mkBVSdiv(rec(l), rec(r)) + case BVModulo(l, r) => z3.mkBVSrem(rec(l), rec(r)) + case BVUMinus(e) => z3.mkBVNeg(rec(e)) + case LessThan(l, r) => l.getType match { + case IntegerType => z3.mkLT(rec(l), rec(r)) + case Int32Type => z3.mkBVSlt(rec(l), rec(r)) + } + case LessEquals(l, r) => l.getType match { + case IntegerType => z3.mkLE(rec(l), rec(r)) + case Int32Type => z3.mkBVSle(rec(l), rec(r)) + } + case GreaterThan(l, r) => l.getType match { + case IntegerType => z3.mkGT(rec(l), rec(r)) + case Int32Type => z3.mkBVSgt(rec(l), rec(r)) + } + case GreaterEquals(l, r) => l.getType match { + case IntegerType => z3.mkGE(rec(l), rec(r)) + case Int32Type => z3.mkBVSge(rec(l), rec(r)) + } + case c @ CaseClass(ct, args) => typeToSort(ct) // Making sure the sort is defined val constructor = adtConstructors(ct) @@ -668,9 +690,10 @@ trait AbstractZ3Solver val default = oDefault.getOrElse(simplestValue(base)) - val ar = z3.mkConstArray(typeToSort(base), rec(default)) - val u = elems.foldLeft(ar)((array, el) => - z3.mkStore(array, rec(IntLiteral(el._1)), rec(el._2))) + val ar = z3.mkConstArray(typeToSort(Int32Type), rec(default)) + val u = elems.foldLeft(ar)((array, el) => { + z3.mkStore(array, rec(IntLiteral(el._1)), rec(el._2)) + }) meta.cons(u, rec(length)) case gv @ GenericValue(tp, id) => @@ -696,7 +719,29 @@ trait AbstractZ3Solver val sort = z3.getSort(t) kind match { - case Z3NumeralIntAST(Some(v)) => IntLiteral(v) + case Z3NumeralIntAST(Some(v)) => { + val leading = t.toString.substring(0, 2 min t.toString.size) + if(leading == "#x") { + _root_.smtlib.common.Hexadecimal.fromString(t.toString.substring(2)) match { + case Some(hexa) => IntLiteral(hexa.toInt) + case None => { + println("Z3NumeralIntAST with None: " + t) + throw new CantTranslateException(t) + } + } + } else { + InfiniteIntegerLiteral(v) + } + } + case Z3NumeralIntAST(None) => { + _root_.smtlib.common.Hexadecimal.fromString(t.toString.substring(2)) match { + case Some(hexa) => IntLiteral(hexa.toInt) + case None => { + println("Z3NumeralIntAST with None: " + t) + throw new CantTranslateException(t) + } + } + } case Z3AppAST(decl, args) => val argsSize = args.size if(argsSize == 0 && (variables containsZ3 t)) { @@ -729,13 +774,21 @@ trait AbstractZ3Solver case LeonType(at @ ArrayType(dt)) => assert(args.size == 2) - val IntLiteral(length) = rec(args(1)) + val length = rec(args(1)) match { + case InfiniteIntegerLiteral(length) => length.toInt + case IntLiteral(length) => length + case _ => throw new CantTranslateException(t) + } model.getArrayValue(args(0)) match { case None => throw new CantTranslateException(t) case Some((map, elseZ3Value)) => val elseValue = rec(elseZ3Value) var valuesMap = map.map { case (k,v) => - val IntLiteral(index) = rec(k) + val index = rec(k) match { + case InfiniteIntegerLiteral(index) => index.toInt + case IntLiteral(index) => index + case _ => throw new CantTranslateException(t) + } (index -> rec(v)) } @@ -850,7 +903,7 @@ trait AbstractZ3Solver } } } - case Z3NumeralIntAST(Some(v)) => IntLiteral(v) + case Z3NumeralIntAST(Some(v)) => InfiniteIntegerLiteral(v) case _ => throw e } diff --git a/src/main/scala/leon/solvers/z3/Z3ModelReconstruction.scala b/src/main/scala/leon/solvers/z3/Z3ModelReconstruction.scala index 5953fc422598d19de8fb774a3064a607d78cea93..1bdb9fe6ad22b91357e9c3cfa46cf0a29515f079 100644 --- a/src/main/scala/leon/solvers/z3/Z3ModelReconstruction.scala +++ b/src/main/scala/leon/solvers/z3/Z3ModelReconstruction.scala @@ -24,6 +24,7 @@ trait Z3ModelReconstruction { expectedType match { case BooleanType => model.evalAs[Boolean](z3ID).map(BooleanLiteral(_)) case Int32Type => model.evalAs[Int](z3ID).map(IntLiteral(_)) + case IntegerType => model.evalAs[Int](z3ID).map(InfiniteIntegerLiteral(_)) case other => model.eval(z3ID) match { case None => None case Some(t) => softFromZ3Formula(model, t) diff --git a/src/main/scala/leon/synthesis/Algebra.scala b/src/main/scala/leon/synthesis/Algebra.scala index 757c4c83c12f32b0e3d4d24e2db32bf06b735310..474d6e90e2bd4b2277cad21ca22ce7cea8705ac9 100644 --- a/src/main/scala/leon/synthesis/Algebra.scala +++ b/src/main/scala/leon/synthesis/Algebra.scala @@ -19,6 +19,12 @@ object Algebra { ((a - r)/b, r) } + def remainder(x: BigInt, y: BigInt) = ((x % y) + y.abs) % y.abs + def divide(a: BigInt, b: BigInt): (BigInt, BigInt) = { + val r = remainder(a, b) + ((a - r)/b, r) + } + def gcd(a: Int, b: Int): Int = { val (na, nb) = (a.abs, b.abs) def gcd0(a: Int, b: Int): Int = { @@ -54,6 +60,41 @@ object Algebra { } } + def gcd(a: BigInt, b: BigInt): BigInt = { + val (na, nb) = (a.abs, b.abs) + def gcd0(a: BigInt, b: BigInt): BigInt = { + require(a >= b) + if(b == 0) a else gcd0(b, a % b) + } + if(na > nb) gcd0(na, nb) else gcd0(nb, na) + } + + def gcd(a1: BigInt, a2: BigInt, a3: BigInt, as: BigInt*): BigInt = { + var tmp = gcd(a1, a2) + tmp = gcd(tmp, a3) + var i = 0 + while(i < as.size) { + tmp = gcd(tmp, as(i)) + i += 1 + } + tmp + } + + def gcd(as: Seq[BigInt]): BigInt = { + require(as.length >= 1) + if(as.length == 1) + as(0).abs + else { + var tmp = gcd(as(0), as(1)) + var i = 2 + while(i < as.size) { + tmp = gcd(tmp, as(i)) + i += 1 + } + tmp + } + } + def lcm(a: Int, b: Int): Int = { val (na, nb) = (a.abs, b.abs) na*nb/gcd(a, b) @@ -85,6 +126,37 @@ object Algebra { } } + def lcm(a: BigInt, b: BigInt): BigInt = { + val (na, nb) = (a.abs, b.abs) + na*nb/gcd(a, b) + } + + def lcm(a1: BigInt, a2: BigInt, a3: BigInt, as: BigInt*): BigInt = { + var tmp = lcm(a1, a2) + tmp = lcm(tmp, a3) + var i = 0 + while(i < as.size) { + tmp = lcm(tmp, as(i)) + i += 1 + } + tmp + } + + def lcm(as: Seq[BigInt]): BigInt = { + require(as.length >= 1) + if(as.length == 1) + as(0).abs + else { + var tmp = lcm(as(0), as(1)) + var i = 2 + while(i < as.size) { + tmp = lcm(tmp, as(i)) + i += 1 + } + tmp + } + } + //return (x, y) such that ax + by = gcd(a, b) def extendedEuclid(a: Int, b: Int): (Int, Int) = { def rec(a: Int, b: Int): (Int, Int) = { @@ -101,6 +173,21 @@ object Algebra { else if(a < 0 && b < 0) {val (x, y) = rec(-a, -b); (-x, -y)} else sys.error("shouldn't have forgot a case here") } + def extendedEuclid(a: BigInt, b: BigInt): (BigInt, BigInt) = { + def rec(a: BigInt, b: BigInt): (BigInt, BigInt) = { + require(a >= 0 && b >= 0) + if(b == 0) (1, 0) else { + val (q, r) = divide(a, b) + val (s, t) = extendedEuclid(b, r) + (t, s - q * t) + } + } + if(a >= 0 && b >= 0) rec(a, b) + else if(a < 0 && b >= 0) {val (x, y) = rec(-a, b); (-x, y)} + else if(a >= 0 && b < 0) {val (x, y) = rec(a, -b); (x, -y)} + else if(a < 0 && b < 0) {val (x, y) = rec(-a, -b); (-x, -y)} + else sys.error("shouldn't have forgot a case here") + } //val that the sol vector with the term in the equation diff --git a/src/main/scala/leon/synthesis/LinearEquations.scala b/src/main/scala/leon/synthesis/LinearEquations.scala index 6c91c40f59e62a60e2b5666725239e9928ad9671..a9dd5ff9a30d42902857b1ae77b12a3c6ac44e26 100644 --- a/src/main/scala/leon/synthesis/LinearEquations.scala +++ b/src/main/scala/leon/synthesis/LinearEquations.scala @@ -17,32 +17,32 @@ object LinearEquations { //return a mapping for each of the n variables in (pre, map, freshVars) def elimVariable(evaluator: Evaluator, as: Set[Identifier], normalizedEquation: List[Expr]): (Expr, List[Expr], List[Identifier]) = { require(normalizedEquation.size > 1) - require(normalizedEquation.tail.forall{case IntLiteral(i) if i != 0 => true case _ => false}) + require(normalizedEquation.tail.forall{case InfiniteIntegerLiteral(i) if i != 0 => true case _ => false}) val t: Expr = normalizedEquation.head - val coefsVars: List[Int] = normalizedEquation.tail.map{case IntLiteral(i) => i} + val coefsVars: List[BigInt] = normalizedEquation.tail.map{case InfiniteIntegerLiteral(i) => i} val orderedParams: Array[Identifier] = as.toArray - val coefsParams: List[Int] = linearArithmeticForm(t, orderedParams).map{case IntLiteral(i) => i}.toList + val coefsParams: List[BigInt] = linearArithmeticForm(t, orderedParams).map{case InfiniteIntegerLiteral(i) => i}.toList //val coefsParams: List[Int] = if(coefsParams0.head == 0) coefsParams0.tail else coefsParams0 - val d: Int = gcd((coefsParams ++ coefsVars).toSeq) + val d: BigInt = gcd((coefsParams ++ coefsVars).toSeq) if(coefsVars.size == 1) { val coef = coefsVars.head - (Equals(Modulo(t, IntLiteral(coef)), IntLiteral(0)), List(UMinus(Division(t, IntLiteral(coef)))), List()) + (Equals(Modulo(t, InfiniteIntegerLiteral(coef)), InfiniteIntegerLiteral(0)), List(UMinus(Division(t, InfiniteIntegerLiteral(coef)))), List()) } else if(d > 1) { - val newCoefsParams: List[Expr] = coefsParams.map(i => IntLiteral(i/d) : Expr) - val newT = newCoefsParams.zip(IntLiteral(1)::orderedParams.map(Variable(_)).toList).foldLeft[Expr](IntLiteral(0))((acc, p) => Plus(acc, Times(p._1, p._2))) - elimVariable(evaluator, as, newT :: normalizedEquation.tail.map{case IntLiteral(i) => IntLiteral(i/d) : Expr}) + val newCoefsParams: List[Expr] = coefsParams.map(i => InfiniteIntegerLiteral(i/d) : Expr) + val newT = newCoefsParams.zip(InfiniteIntegerLiteral(1)::orderedParams.map(Variable(_)).toList).foldLeft[Expr](InfiniteIntegerLiteral(0))((acc, p) => Plus(acc, Times(p._1, p._2))) + elimVariable(evaluator, as, newT :: normalizedEquation.tail.map{case InfiniteIntegerLiteral(i) => InfiniteIntegerLiteral(i/d) : Expr}) } else { - val basis: Array[Array[Int]] = linearSet(evaluator, as, normalizedEquation.tail.map{case IntLiteral(i) => i}.toArray) + val basis: Array[Array[BigInt]] = linearSet(evaluator, as, normalizedEquation.tail.map{case InfiniteIntegerLiteral(i) => i}.toArray) val (pre, sol) = particularSolution(as, normalizedEquation) - val freshVars: Array[Identifier] = basis(0).map(_ => FreshIdentifier("v", true).setType(Int32Type)) + val freshVars: Array[Identifier] = basis(0).map(_ => FreshIdentifier("v", true).setType(IntegerType)) val tbasis = basis.transpose assert(freshVars.size == tbasis.size) val basisWithFreshVars: Array[Array[Expr]] = freshVars.zip(tbasis).map{ - case (lambda, column) => column.map((i: Int) => Times(IntLiteral(i), Variable(lambda)): Expr) + case (lambda, column) => column.map((i: BigInt) => Times(InfiniteIntegerLiteral(i), Variable(lambda)): Expr) }.transpose - val combinationBasis: Array[Expr] = basisWithFreshVars.map((v: Array[Expr]) => v.foldLeft[Expr](IntLiteral(0))((acc, e) => Plus(acc, e))) + val combinationBasis: Array[Expr] = basisWithFreshVars.map((v: Array[Expr]) => v.foldLeft[Expr](InfiniteIntegerLiteral(0))((acc, e) => Plus(acc, e))) assert(combinationBasis.size == sol.size) val subst: List[Expr] = sol.zip(combinationBasis.toList).map(p => Plus(p._1, p._2): Expr) @@ -58,9 +58,9 @@ object LinearEquations { //Intuitively, we are building a "basis" for the "vector space" of solutions (although we are over //integers, so it is not a vector space). //we are returning a matrix where the columns are the vectors - def linearSet(evaluator: Evaluator, as: Set[Identifier], coef: Array[Int]): Array[Array[Int]] = { + def linearSet(evaluator: Evaluator, as: Set[Identifier], coef: Array[BigInt]): Array[Array[BigInt]] = { - val K = Array.ofDim[Int](coef.size, coef.size-1) + val K = Array.ofDim[BigInt](coef.size, coef.size-1) for(i <- 0 until K.size) { for(j <- 0 until K(i).size) { if(i < j) @@ -71,11 +71,11 @@ object LinearEquations { } } for(j <- 0 until K.size - 1) { - val (_, sols) = particularSolution(as, IntLiteral(coef(j)*K(j)(j)) :: coef.drop(j+1).map(IntLiteral(_)).toList) + val (_, sols) = particularSolution(as, InfiniteIntegerLiteral(coef(j)*K(j)(j)) :: coef.drop(j+1).map(InfiniteIntegerLiteral(_)).toList) var i = 0 while(i < sols.size) { // seriously ??? - K(i+j+1)(j) = evaluator.eval(sols(i)).asInstanceOf[EvaluationResults.Successful].value.asInstanceOf[IntLiteral].value + K(i+j+1)(j) = evaluator.eval(sols(i)).asInstanceOf[EvaluationResults.Successful].value.asInstanceOf[InfiniteIntegerLiteral].value i += 1 } } @@ -96,16 +96,16 @@ object LinearEquations { //return a particular solution to t + c1x + c2y = 0, with (pre, (x0, y0)) def particularSolution(as: Set[Identifier], t: Expr, c1: Expr, c2: Expr): (Expr, (Expr, Expr)) = { - val (IntLiteral(i1), IntLiteral(i2)) = (c1, c2) + val (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) = (c1, c2) val (v1, v2) = extendedEuclid(i1, i2) val d = gcd(i1, i2) - val pre = Equals(Modulo(t, IntLiteral(d)), IntLiteral(0)) + val pre = Equals(Modulo(t, InfiniteIntegerLiteral(d)), InfiniteIntegerLiteral(0)) (pre, ( - UMinus(Times(IntLiteral(v1), Division(t, IntLiteral(d)))), - UMinus(Times(IntLiteral(v2), Division(t, IntLiteral(d)))) + UMinus(Times(InfiniteIntegerLiteral(v1), Division(t, InfiniteIntegerLiteral(d)))), + UMinus(Times(InfiniteIntegerLiteral(v2), Division(t, InfiniteIntegerLiteral(d)))) ) ) } @@ -114,9 +114,9 @@ object LinearEquations { def particularSolution(as: Set[Identifier], normalizedEquation: List[Expr]): (Expr, List[Expr]) = { require(normalizedEquation.size >= 2) val t: Expr = normalizedEquation.head - val coefs: List[Int] = normalizedEquation.tail.map{case IntLiteral(i) => i} + val coefs: List[BigInt] = normalizedEquation.tail.map{case InfiniteIntegerLiteral(i) => i} val d = gcd(coefs.toSeq) - val pre = Equals(Modulo(t, IntLiteral(d)), IntLiteral(0)) + val pre = Equals(Modulo(t, InfiniteIntegerLiteral(d)), InfiniteIntegerLiteral(0)) if(normalizedEquation.size == 2) { (pre, List(UMinus(Division(t, normalizedEquation(1))))) @@ -125,8 +125,8 @@ object LinearEquations { (pre, List(w1, w2)) } else { val gamma1: Expr = normalizedEquation(1) - val coefs: List[Int] = normalizedEquation.drop(2).map{case IntLiteral(i) => i} - val gamma2: Expr = IntLiteral(gcd(coefs.toSeq)) + val coefs: List[BigInt] = normalizedEquation.drop(2).map{case InfiniteIntegerLiteral(i) => i} + val gamma2: Expr = InfiniteIntegerLiteral(gcd(coefs.toSeq)) val (_, (w1, w)) = particularSolution(as, t, gamma1, gamma2) val (_, sols) = particularSolution(as, UMinus(Times(w, gamma2)) :: normalizedEquation.drop(2)) (pre, w1 :: sols) diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala index 10b8e6ef51f781a6767c41c4db4d1e0693c4ea24..399e045a537e1522be519773532e8b66555ee7fc 100644 --- a/src/main/scala/leon/synthesis/Rules.scala +++ b/src/main/scala/leon/synthesis/Rules.scala @@ -50,8 +50,8 @@ object Rules { DetupleInput, ADTSplit, InlineHoles, - IntegerEquation, - IntegerInequalities, + //IntegerEquation, + //IntegerInequalities, IntInduction, InnerCaseSplit, //new OptimisticInjection(_), diff --git a/src/main/scala/leon/synthesis/rules/Cegis.scala b/src/main/scala/leon/synthesis/rules/Cegis.scala index 3a744c42c0b04c7a9f899748195c9ee5e84c6843..6d989c4ef4126e8391a47a9fa048fcd7d8efd92b 100644 --- a/src/main/scala/leon/synthesis/rules/Cegis.scala +++ b/src/main/scala/leon/synthesis/rules/Cegis.scala @@ -9,6 +9,18 @@ import purescala.TypeTrees._ import purescala.Common._ import purescala.Definitions._ import utils.Helpers._ +import purescala.TypeTrees._ +import purescala.TreeOps._ +import purescala.DefOps._ +import purescala.TypeTreeOps._ +import purescala.Extractors._ +import purescala.ScalaPrinter + +import scala.collection.mutable.{Map=>MutableMap} + +import evaluators._ +import datagen._ +import codegen.CodeGenParams import utils._ diff --git a/src/main/scala/leon/synthesis/rules/InequalitySplit.scala b/src/main/scala/leon/synthesis/rules/InequalitySplit.scala index 54ce95e5e83d1a7e76cf08b0f9589c3f6aeefa50..a71574fdaf243c388014f0c73c1f49773e512db1 100644 --- a/src/main/scala/leon/synthesis/rules/InequalitySplit.scala +++ b/src/main/scala/leon/synthesis/rules/InequalitySplit.scala @@ -18,7 +18,7 @@ case object InequalitySplit extends Rule("Ineq. Split.") { def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { val solver = SimpleSolverAPI(hctx.sctx.fastSolverFactory) - val candidates = p.as.filter(_.getType == Int32Type).combinations(2).toList.filter { + val candidates = p.as.filter(_.getType == IntegerType).combinations(2).toList.filter { case List(a1, a2) => val toValLT = implies(p.pc, LessThan(Variable(a1), Variable(a2))) diff --git a/src/main/scala/leon/synthesis/rules/IntInduction.scala b/src/main/scala/leon/synthesis/rules/IntInduction.scala index ae0567bd3a2e0ab53bd9208a181674a27b057cd8..15c19915d02269358ea4c98c6910f09389c568e6 100644 --- a/src/main/scala/leon/synthesis/rules/IntInduction.scala +++ b/src/main/scala/leon/synthesis/rules/IntInduction.scala @@ -15,7 +15,7 @@ import purescala.Definitions._ case object IntInduction extends Rule("Int Induction") { def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { p.as match { - case List(IsTyped(origId, Int32Type)) => + case List(IsTyped(origId, IntegerType)) => val tpe = tupleTypeWrap(p.xs.map(_.getType)) val inductOn = FreshIdentifier(origId.name, true).setType(origId.getType) @@ -27,12 +27,12 @@ case object IntInduction extends Rule("Int Induction") { val newPhi = subst(origId -> Variable(inductOn), p.phi) val newPc = subst(origId -> Variable(inductOn), p.pc) val newWs = subst(origId -> Variable(inductOn), p.ws) - val postCondGT = substAll(postXsMap + (origId -> Minus(Variable(inductOn), IntLiteral(1))), p.phi) - val postCondLT = substAll(postXsMap + (origId -> Plus(Variable(inductOn), IntLiteral(1))), p.phi) + val postCondGT = substAll(postXsMap + (origId -> Minus(Variable(inductOn), InfiniteIntegerLiteral(1))), p.phi) + val postCondLT = substAll(postXsMap + (origId -> Plus(Variable(inductOn), InfiniteIntegerLiteral(1))), p.phi) - val subBase = Problem(List(), subst(origId -> IntLiteral(0), p.ws), subst(origId -> IntLiteral(0), p.pc), subst(origId -> IntLiteral(0), p.phi), p.xs) - val subGT = Problem(inductOn :: postXs, newWs, and(GreaterThan(Variable(inductOn), IntLiteral(0)), postCondGT, newPc), newPhi, p.xs) - val subLT = Problem(inductOn :: postXs, newWs, and(LessThan(Variable(inductOn), IntLiteral(0)), postCondLT, newPc), newPhi, p.xs) + val subBase = Problem(List(), subst(origId -> InfiniteIntegerLiteral(0), p.ws), subst(origId -> InfiniteIntegerLiteral(0), p.pc), subst(origId -> InfiniteIntegerLiteral(0), p.phi), p.xs) + val subGT = Problem(inductOn :: postXs, newWs, and(GreaterThan(Variable(inductOn), InfiniteIntegerLiteral(0)), postCondGT, newPc), newPhi, p.xs) + val subLT = Problem(inductOn :: postXs, newWs, and(LessThan(Variable(inductOn), InfiniteIntegerLiteral(0)), postCondLT, newPc), newPhi, p.xs) val onSuccess: List[Solution] => Option[Solution] = { case List(base, gt, lt) => @@ -41,9 +41,9 @@ case object IntInduction extends Rule("Int Induction") { // allow invalid programs. None } else { - val preIn = or(and(Equals(Variable(inductOn), IntLiteral(0)), base.pre), - and(GreaterThan(Variable(inductOn), IntLiteral(0)), gt.pre), - and(LessThan(Variable(inductOn), IntLiteral(0)), lt.pre)) + val preIn = or(and(Equals(Variable(inductOn), InfiniteIntegerLiteral(0)), base.pre), + and(GreaterThan(Variable(inductOn), InfiniteIntegerLiteral(0)), gt.pre), + and(LessThan(Variable(inductOn), InfiniteIntegerLiteral(0)), lt.pre)) val preOut = subst(inductOn -> Variable(origId), preIn) val newFun = new FunDef(FreshIdentifier("rec", true), Nil, tpe, Seq(ValDef(inductOn, inductOn.getType)),DefType.MethodDef) @@ -53,11 +53,11 @@ case object IntInduction extends Rule("Int Induction") { newFun.postcondition = Some((idPost, letTuple(p.xs.toSeq, Variable(idPost), p.phi))) newFun.body = Some( - IfExpr(Equals(Variable(inductOn), IntLiteral(0)), + IfExpr(Equals(Variable(inductOn), InfiniteIntegerLiteral(0)), base.toExpr, - IfExpr(GreaterThan(Variable(inductOn), IntLiteral(0)), - letTuple(postXs, FunctionInvocation(newFun.typed, Seq(Minus(Variable(inductOn), IntLiteral(1)))), gt.toExpr) - , letTuple(postXs, FunctionInvocation(newFun.typed, Seq(Plus(Variable(inductOn), IntLiteral(1)))), lt.toExpr))) + IfExpr(GreaterThan(Variable(inductOn), InfiniteIntegerLiteral(0)), + letTuple(postXs, FunctionInvocation(newFun.typed, Seq(Minus(Variable(inductOn), InfiniteIntegerLiteral(1)))), gt.toExpr) + , letTuple(postXs, FunctionInvocation(newFun.typed, Seq(Plus(Variable(inductOn), InfiniteIntegerLiteral(1)))), lt.toExpr))) ) diff --git a/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala b/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala index 97687c4250153f1424c00cf38fce707f1854e165..ac3f47b1798902582ac6c09ac79fbfd44a755cfd 100644 --- a/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala +++ b/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala @@ -81,18 +81,30 @@ object ExpressionGrammars { Generator(List(BooleanType), { case Seq(a) => Not(a) }), Generator(List(BooleanType, BooleanType), { case Seq(a, b) => And(a, b) }), Generator(List(BooleanType, BooleanType), { case Seq(a, b) => LeonOr(a, b) }), - Generator(List(Int32Type, Int32Type), { case Seq(a, b) => LessThan(a, b) }), - Generator(List(Int32Type, Int32Type), { case Seq(a, b) => LessEquals(a, b) }), + Generator(List(Int32Type, Int32Type), { case Seq(a, b) => LessThan(a, b) }), + Generator(List(Int32Type, Int32Type), { case Seq(a, b) => LessEquals(a, b) }), Generator(List(Int32Type, Int32Type ), { case Seq(a, b) => Equals(a, b) }), + Generator(List(IntegerType, IntegerType), { case Seq(a, b) => LessThan(a, b) }), + Generator(List(IntegerType, IntegerType), { case Seq(a, b) => LessEquals(a, b) }), + Generator(List(IntegerType, IntegerType), { case Seq(a, b) => Equals(a, b) }), Generator(List(BooleanType, BooleanType), { case Seq(a, b) => Equals(a, b) }) ) case Int32Type => List( Generator(Nil, { _ => IntLiteral(0) }), Generator(Nil, { _ => IntLiteral(1) }), - Generator(List(Int32Type, Int32Type), { case Seq(a,b) => Plus(a, b) }), - Generator(List(Int32Type, Int32Type), { case Seq(a,b) => Minus(a, b) }), - Generator(List(Int32Type, Int32Type), { case Seq(a,b) => Times(a, b) }) + Generator(List(Int32Type, Int32Type), { case Seq(a,b) => BVPlus(a, b) }), + Generator(List(Int32Type, Int32Type), { case Seq(a,b) => BVMinus(a, b) }), + Generator(List(Int32Type, Int32Type), { case Seq(a,b) => BVTimes(a, b) }) + ) + + case IntegerType => + List( + Generator(Nil, { _ => InfiniteIntegerLiteral(0) }), + Generator(Nil, { _ => InfiniteIntegerLiteral(1) }), + Generator(List(IntegerType, IntegerType), { case Seq(a,b) => Plus(a, b) }), + Generator(List(IntegerType, IntegerType), { case Seq(a,b) => Minus(a, b) }), + Generator(List(IntegerType, IntegerType), { case Seq(a,b) => Times(a, b) }) ) case TupleType(stps) => @@ -137,6 +149,12 @@ object ExpressionGrammars { Generator(Nil, { _ => IntLiteral(1) }), Generator(Nil, { _ => IntLiteral(-1) }) ) + case IntegerType => + List( + Generator(Nil, { _ => InfiniteIntegerLiteral(0) }), + Generator(Nil, { _ => InfiniteIntegerLiteral(1) }), + Generator(Nil, { _ => InfiniteIntegerLiteral(-1) }) + ) case tp@TypeParameter(_) => for (ind <- (1 to 3).toList) yield @@ -263,8 +281,8 @@ object ExpressionGrammars { def intVariations(gl: L, e : Expr): Seq[(L, Gen)] = { Seq( - gl -> Generator(Nil, { _ => Minus(e, IntLiteral(1))} ), - gl -> Generator(Nil, { _ => Plus (e, IntLiteral(1))} ) + gl -> Generator(Nil, { _ => BVMinus(e, IntLiteral(1))} ), + gl -> Generator(Nil, { _ => BVPlus (e, IntLiteral(1))} ) ) } diff --git a/src/main/scala/leon/termination/ChainComparator.scala b/src/main/scala/leon/termination/ChainComparator.scala index 68f5f97a2908fcb3e3079692ee553a14f3d0cb72..f1d146e7dca987900714948fef9eebc9ab1d649a 100644 --- a/src/main/scala/leon/termination/ChainComparator.scala +++ b/src/main/scala/leon/termination/ChainComparator.scala @@ -194,7 +194,7 @@ trait ChainComparator { self : StructuralSize with TerminationChecker => def numericConverging(e1: Expr, e2s: Seq[(Seq[Expr], Expr)], cluster: Set[Chain]) : Seq[Expr] = flatType(e1.getType).toSeq.flatMap { recons => recons(e1) match { - case e if e.getType == Int32Type => + case e if e.getType == IntegerType => val endpoint = numericEndpoint(e, cluster) val uppers = if (endpoint == UpperBoundEndpoint || endpoint == AnyEndpoint) { diff --git a/src/main/scala/leon/termination/StructuralSize.scala b/src/main/scala/leon/termination/StructuralSize.scala index 25965c4ad6c71a9fa09c41a3ca5df674d0885f69..e1f8f8b3cf423e1d83f2776983d828feb6a5f6d7 100644 --- a/src/main/scala/leon/termination/StructuralSize.scala +++ b/src/main/scala/leon/termination/StructuralSize.scala @@ -34,12 +34,12 @@ trait StructuralSize { case None => val argument = ValDef(FreshIdentifier("x", true).setType(argumentType), argumentType) val formalTParams = typeParams.map(TypeParameterDef(_)) - val fd = new FunDef(FreshIdentifier("size", true), formalTParams, Int32Type, Seq(argument), DefType.MethodDef) + val fd = new FunDef(FreshIdentifier("size", true), formalTParams, IntegerType, Seq(argument), DefType.MethodDef) sizeCache(argumentType) = fd val body = simplifyLets(matchToIfThenElse(matchExpr(argument.toVariable, cases(argumentType)))) - val postId = FreshIdentifier("res", false).setType(Int32Type) - val postcondition = GreaterThan(Variable(postId), IntLiteral(0)) + val postId = FreshIdentifier("res", false).setType(IntegerType) + val postcondition = GreaterThan(Variable(postId), InfiniteIntegerLiteral(0)) fd.body = Some(body) fd.postcondition = Some(postId, postcondition) @@ -52,7 +52,7 @@ trait StructuralSize { val arguments = c.fields.map(vd => FreshIdentifier(vd.id.name).setType(vd.tpe)) val argumentPatterns = arguments.map(id => WildcardPattern(Some(id))) val sizes = arguments.map(id => size(Variable(id))) - val result = sizes.foldLeft[Expr](IntLiteral(1))(Plus(_,_)) + val result = sizes.foldLeft[Expr](InfiniteIntegerLiteral(1))(Plus(_,_)) purescala.Extractors.SimpleCase(CaseClassPattern(None, c, argumentPatterns), result) } @@ -65,8 +65,8 @@ trait StructuralSize { FunctionInvocation(TypedFunDef(fd, ct.tps), Seq(expr)) case TupleType(argTypes) => argTypes.zipWithIndex.map({ case (_, index) => size(tupleSelect(expr, index + 1)) - }).foldLeft[Expr](IntLiteral(0))(Plus(_,_)) - case _ => IntLiteral(0) + }).foldLeft[Expr](InfiniteIntegerLiteral(0))(Plus(_,_)) + case _ => InfiniteIntegerLiteral(0) } } diff --git a/src/test/resources/regression/synthesis/List/Insert.scala b/src/test/resources/regression/synthesis/List/Insert.scala index 13c1294d7000c4b8fce4fbe229a3a5b54ea27790..0a2cb88b0efa17ab1498b71bac764c55504c1f96 100644 --- a/src/test/resources/regression/synthesis/List/Insert.scala +++ b/src/test/resources/regression/synthesis/List/Insert.scala @@ -9,9 +9,9 @@ object Insert { case class Cons(head: Int, tail: List) extends List case object Nil extends List - def size(l: List) : Int = (l match { - case Nil => 0 - case Cons(_, t) => 1 + size(t) + def size(l: List) : BigInt = (l match { + case Nil => BigInt(0) + case Cons(_, t) => size(t) + 1 }) ensuring(res => res >= 0) def content(l: List): Set[Int] = l match { diff --git a/src/test/resources/regression/termination/valid/Fibonacci.scala b/src/test/resources/regression/termination/valid/Fibonacci.scala index feabb8aff313a4cfd91f5a2cf75f2ab764dc0917..e859a2c3d8c80ce169081d49f72938201d2dfa38 100644 --- a/src/test/resources/regression/termination/valid/Fibonacci.scala +++ b/src/test/resources/regression/termination/valid/Fibonacci.scala @@ -1,7 +1,7 @@ /* Copyright 2009-2014 EPFL, Lausanne */ object Fibonacci { - def fib(x: Int) : Int = { + def fib(x: BigInt) : BigInt = { require(x >= 0) if(x < 2) { x @@ -12,6 +12,6 @@ object Fibonacci { // requires that fib is universally quantified to work... def check() : Boolean = { - fib(5) == 5 + fib(5) == BigInt(5) } ensuring(_ == true) } diff --git a/src/test/resources/regression/termination/valid/Numeric1.scala b/src/test/resources/regression/termination/valid/Numeric1.scala index 07218fa520f9373717b9e3eed3d363db7367a505..7015bf71e3297131940b175e4034fdb9715f2aaf 100644 --- a/src/test/resources/regression/termination/valid/Numeric1.scala +++ b/src/test/resources/regression/termination/valid/Numeric1.scala @@ -4,10 +4,7 @@ import leon.lang._ object Numeric { - def f1(x: Int): Int = f2(x - 2) + def f1(x: BigInt): BigInt = f2(x - 2) - def f2(x: Int): Int = if (x < 0) 0 else f1(x + 1) + def f2(x: BigInt): BigInt = if (x < 0) 0 else f1(x + 1) } - - -// vim: set ts=4 sw=4 et: diff --git a/src/test/resources/regression/verification/purescala/invalid/AddingNegativeNumbers.scala b/src/test/resources/regression/verification/purescala/invalid/AddingNegativeNumbers.scala new file mode 100644 index 0000000000000000000000000000000000000000..a8c1433b1b0eb8e86b575453141d910fe4dc39cc --- /dev/null +++ b/src/test/resources/regression/verification/purescala/invalid/AddingNegativeNumbers.scala @@ -0,0 +1,10 @@ +package test.resources.regression.verification.purescala.invalid + +object AddingNegativeNumbers { + + def additionOverflow(x: Int, y: Int): Int = { + require(x <= 0 && y <= 0) + x + y + } ensuring(_ <= 0) + +} diff --git a/src/test/resources/regression/verification/purescala/invalid/AddingPositiveNumbers.scala b/src/test/resources/regression/verification/purescala/invalid/AddingPositiveNumbers.scala new file mode 100644 index 0000000000000000000000000000000000000000..d5f1b2825f17083409b2f5474fc0d3d331e7ff1e --- /dev/null +++ b/src/test/resources/regression/verification/purescala/invalid/AddingPositiveNumbers.scala @@ -0,0 +1,11 @@ +/* Copyright 2009-2014 EPFL, Lausanne */ + +object AddingPositiveNumbers { + + //this should overflow with bit vectors + def additionOverflow(x: Int, y: Int): Int = { + require(x >= 0 && y >= 0) + x + y + } ensuring(_ >= 0) + +} diff --git a/src/test/resources/regression/verification/purescala/invalid/Choose1.scala b/src/test/resources/regression/verification/purescala/invalid/Choose1.scala index 20d5885231c38d0ea858152d112fe43e5e546f23..8ff2e7dcb81701d0113f96a98268426e7c0ba071 100644 --- a/src/test/resources/regression/verification/purescala/invalid/Choose1.scala +++ b/src/test/resources/regression/verification/purescala/invalid/Choose1.scala @@ -9,8 +9,8 @@ object Choose1 { case class Cons(head: Int, tail: List) extends List case class Nil() extends List - def size(l: List) : Int = (l match { - case Nil() => 0 + def size(l: List) : BigInt = (l match { + case Nil() => BigInt(0) case Cons(_, t) => 1 + size(t) }) ensuring(res => res >= 0) @@ -19,10 +19,10 @@ object Choose1 { case Cons(x, xs) => Set(x) ++ content(xs) } - def listOfSize(i: Int): List = { + def listOfSize(i: BigInt): List = { require(i >= 0) - if (i == 0) { + if (i == BigInt(0)) { Nil() } else { choose { (res: List) => size(res) == i-1 } @@ -30,7 +30,7 @@ object Choose1 { } ensuring ( size(_) == i ) - def listOfSize2(i: Int): List = { + def listOfSize2(i: BigInt): List = { require(i >= 0) if (i > 0) { diff --git a/src/test/resources/regression/verification/purescala/invalid/Generics.scala b/src/test/resources/regression/verification/purescala/invalid/Generics.scala index 04421e7549b02d573b86093803879344881c7526..1c8566937e7c3a1c56edaf62aa6bfb4a7db9a099 100644 --- a/src/test/resources/regression/verification/purescala/invalid/Generics.scala +++ b/src/test/resources/regression/verification/purescala/invalid/Generics.scala @@ -7,8 +7,8 @@ object Generics1 { case class Cons[A](head: A, tail: List[A]) extends List[A] case class Nil[B]() extends List[B] - def size[T](l: List[T]): Int = (l match { - case Nil() => 0 + def size[T](l: List[T]): BigInt = (l match { + case Nil() => BigInt(0) case Cons(h, t) => 1+size(t) })ensuring { _ > 0 } diff --git a/src/test/resources/regression/verification/purescala/invalid/Generics2.scala b/src/test/resources/regression/verification/purescala/invalid/Generics2.scala index 0376cfaf21e557ce82e03877bf7decdfde00b0b3..56dc25fd4fd8573039deab177c4e88f536475579 100644 --- a/src/test/resources/regression/verification/purescala/invalid/Generics2.scala +++ b/src/test/resources/regression/verification/purescala/invalid/Generics2.scala @@ -7,8 +7,8 @@ object Generics1 { case class Cons[A](head: A, tail: List[A]) extends List[A] case class Nil[B]() extends List[B] - def size[T](l: List[T]): Int = (l match { - case Nil() => 0 + def size[T](l: List[T]): BigInt = (l match { + case Nil() => BigInt(0) case Cons(h, t) => 1+size(t) })ensuring { _ >= 0 } diff --git a/src/test/resources/regression/verification/purescala/invalid/InsertionSort.scala b/src/test/resources/regression/verification/purescala/invalid/InsertionSort.scala index 5fd06d36a53f3b41ffde13fff37044afc50734ec..8f4d88aa28398d441f5ac9179d8a548fd516646a 100644 --- a/src/test/resources/regression/verification/purescala/invalid/InsertionSort.scala +++ b/src/test/resources/regression/verification/purescala/invalid/InsertionSort.scala @@ -13,8 +13,8 @@ object InsertionSort { case class Some(value: Int) extends OptInt case class None() extends OptInt - def size(l : List) : Int = (l match { - case Nil() => 0 + def size(l : List) : BigInt = (l match { + case Nil() => BigInt(0) case Cons(_, xs) => 1 + size(xs) }) ensuring(_ >= 0) diff --git a/src/test/resources/regression/verification/purescala/invalid/ListOperations.scala b/src/test/resources/regression/verification/purescala/invalid/ListOperations.scala index bca6e6a76bbe862f63d4016a0e6db6073cba6443..afa46acd20e5fdfcab9a6b91a04d46b6cd8b883c 100644 --- a/src/test/resources/regression/verification/purescala/invalid/ListOperations.scala +++ b/src/test/resources/regression/verification/purescala/invalid/ListOperations.scala @@ -16,13 +16,13 @@ object ListOperations { sealed abstract class IntPair case class IP(fst: Int, snd: Int) extends IntPair - def size(l: List) : Int = (l match { - case Nil() => 0 + def size(l: List) : BigInt = (l match { + case Nil() => BigInt(0) case Cons(_, t) => 1 + size(t) }) ensuring(res => res >= 0) - def iplSize(l: IntPairList) : Int = (l match { - case IPNil() => 0 + def iplSize(l: IntPairList) : BigInt = (l match { + case IPNil() => BigInt(0) case IPCons(_, xs) => 1 + iplSize(xs) }) ensuring(_ >= 0) @@ -39,8 +39,8 @@ object ListOperations { } } ensuring(iplSize(_) == size(l1)) - def sizeTailRec(l: List) : Int = sizeTailRecAcc(l, 0) - def sizeTailRecAcc(l: List, acc: Int) : Int = { + def sizeTailRec(l: List) : BigInt = sizeTailRecAcc(l, 0) + def sizeTailRecAcc(l: List, acc: BigInt) : BigInt = { require(acc >= 0) l match { case Nil() => acc @@ -58,7 +58,7 @@ object ListOperations { } def sizeAndContent(l: List) : Boolean = { - size(l) == 0 || content(l) != Set.empty[Int] + size(l) == BigInt(0) || content(l) != Set.empty[Int] }.holds def drunk(l : List) : List = (l match { diff --git a/src/test/resources/regression/verification/purescala/invalid/RedBlackTree.scala b/src/test/resources/regression/verification/purescala/invalid/RedBlackTree.scala index 148512d000bf452ca3c284d9fd57670318eb6b87..1a75c77190cdea1c49aedf0d63491ee08db1e943 100644 --- a/src/test/resources/regression/verification/purescala/invalid/RedBlackTree.scala +++ b/src/test/resources/regression/verification/purescala/invalid/RedBlackTree.scala @@ -22,8 +22,8 @@ object RedBlackTree { case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r) } - def size(t: Tree) : Int = (t match { - case Empty() => 0 + def size(t: Tree) : BigInt = (t match { + case Empty() => BigInt(0) case Node(_, l, v, r) => size(l) + 1 + size(r) }) ensuring(_ >= 0) diff --git a/src/test/resources/regression/verification/purescala/valid/AddingPositiveNumbers.scala b/src/test/resources/regression/verification/purescala/valid/AddingPositiveNumbers.scala new file mode 100644 index 0000000000000000000000000000000000000000..ad5efa8794a974e620fe5c0ea936380a36dd562b --- /dev/null +++ b/src/test/resources/regression/verification/purescala/valid/AddingPositiveNumbers.scala @@ -0,0 +1,11 @@ +/* Copyright 2009-2014 EPFL, Lausanne */ + +object AddingPositiveNumbers { + + //this should not overflow + def additionSound(x: BigInt, y: BigInt): BigInt = { + require(x >= 0 && y >= 0) + x + y + } ensuring(_ >= 0) + +} diff --git a/src/test/resources/regression/verification/purescala/valid/AmortizedQueue.scala b/src/test/resources/regression/verification/purescala/valid/AmortizedQueue.scala index 0c7d2170f77ebb4e338dc3840d3ac750b0f0f9f2..1f74ed4b12933352dedeb22dadff0f1d1121f19d 100644 --- a/src/test/resources/regression/verification/purescala/valid/AmortizedQueue.scala +++ b/src/test/resources/regression/verification/purescala/valid/AmortizedQueue.scala @@ -12,8 +12,8 @@ object AmortizedQueue { sealed abstract class AbsQueue case class Queue(front : List, rear : List) extends AbsQueue - def size(list : List) : Int = (list match { - case Nil() => 0 + def size(list : List) : BigInt = (list match { + case Nil() => BigInt(0) case Cons(_, xs) => 1 + size(xs) }) ensuring(_ >= 0) diff --git a/src/test/resources/regression/verification/purescala/valid/Anonymous.scala b/src/test/resources/regression/verification/purescala/valid/Anonymous.scala index b8d3235ccf5e817d0202b0f8de3145d977e1989f..d69b1f8423c3ae681527e2a49fb75d6c54672b4f 100644 --- a/src/test/resources/regression/verification/purescala/valid/Anonymous.scala +++ b/src/test/resources/regression/verification/purescala/valid/Anonymous.scala @@ -1,9 +1,9 @@ import leon.lang._ object Anonymous { - def test(x: Int) = { + def test(x: BigInt) = { require(x > 0) - val i = (a: Int) => a + 1 + val i = (a: BigInt) => a + 1 i(x) + i(2) } ensuring { res => res > 0 } } diff --git a/src/test/resources/regression/verification/purescala/valid/Asserts1.scala b/src/test/resources/regression/verification/purescala/valid/Asserts1.scala index abbd39d5e8f88244891e20f763f7ccd150fcf839..0851ba5adf9eaa3b80a73fe263b904e93fc474da 100644 --- a/src/test/resources/regression/verification/purescala/valid/Asserts1.scala +++ b/src/test/resources/regression/verification/purescala/valid/Asserts1.scala @@ -4,7 +4,7 @@ import leon._ object Operators { - def foo(a: Int): Int = { + def foo(a: BigInt): BigInt = { require(a > 0) { @@ -17,7 +17,7 @@ object Operators { _ > a } - def bar(a: Int): Int = { + def bar(a: BigInt): BigInt = { require(a > 0) { diff --git a/src/test/resources/regression/verification/purescala/valid/Choose1.scala b/src/test/resources/regression/verification/purescala/valid/Choose1.scala index 2b033c809ca1e5c71ad9c7592aa4482ab13ef083..da4b4e7752a7a4a6fcbd21c72533e0312c18cb73 100644 --- a/src/test/resources/regression/verification/purescala/valid/Choose1.scala +++ b/src/test/resources/regression/verification/purescala/valid/Choose1.scala @@ -9,8 +9,8 @@ object Choose1 { case class Cons(head: Int, tail: List) extends List case class Nil() extends List - def size(l: List) : Int = (l match { - case Nil() => 0 + def size(l: List) : BigInt = (l match { + case Nil() => BigInt(0) case Cons(_, t) => 1 + size(t) }) ensuring(res => res >= 0) @@ -19,10 +19,10 @@ object Choose1 { case Cons(x, xs) => Set(x) ++ content(xs) } - def listOfSize(i: Int): List = { + def listOfSize(i: BigInt): List = { require(i >= 0) - if (i == 0) { + if (i == BigInt(0)) { Nil() } else { choose { (res: List) => size(res) == i } @@ -30,7 +30,7 @@ object Choose1 { } ensuring ( size(_) == i ) - def listOfSize2(i: Int): List = { + def listOfSize2(i: BigInt): List = { require(i >= 0) if (i > 0) { diff --git a/src/test/resources/regression/verification/purescala/valid/Generics.scala b/src/test/resources/regression/verification/purescala/valid/Generics.scala index 2820d5a5cfe8791584a187787e564e84d8a280ba..7e1b2359f35b7b197738397782b20d0a73a32df6 100644 --- a/src/test/resources/regression/verification/purescala/valid/Generics.scala +++ b/src/test/resources/regression/verification/purescala/valid/Generics.scala @@ -7,8 +7,8 @@ object Generics1 { case class Cons[A](head: A, tail: List[A]) extends List[A] case class Nil[B]() extends List[B] - def size[T](l: List[T]): Int = (l match { - case Nil() => 0 + def size[T](l: List[T]): BigInt = (l match { + case Nil() => BigInt(0) case Cons(h, t) => 1+size(t) })ensuring { _ >= 0 } diff --git a/src/test/resources/regression/verification/purescala/valid/Generics2.scala b/src/test/resources/regression/verification/purescala/valid/Generics2.scala index 5bd3627d49d9b1a86dcb604da915bf3237bfaf1f..3ad9b7df9a5090a1abfa268f3bdbcbd7a57f2119 100644 --- a/src/test/resources/regression/verification/purescala/valid/Generics2.scala +++ b/src/test/resources/regression/verification/purescala/valid/Generics2.scala @@ -7,10 +7,10 @@ object Generics1 { case class Cons[A](head: A, tail: List[A]) extends List[A] case class Nil[B]() extends List[B] - def size[T](l: List[T]): Int = (l match { - case Nil() => 0 - case Cons(h, t) => 1+size(t) - })ensuring { _ >= 0 } + def size[T](l: List[T]): BigInt = (l match { + case Nil() => BigInt(0) + case Cons(h, t) => size(t) + BigInt(1) + }) ensuring((res: BigInt) => res >= BigInt(0)) def content[T](l: List[T]): Set[T] = l match { case Nil() => Set() @@ -21,7 +21,7 @@ object Generics1 { Cons(a, l) } ensuring { res => (size(res) == size(l) + 1) && (content(res) == content(l) ++ Set(a))} - def insertInt(a: Int, l: List[Int]): List[Int] = { + def insertInt(a: BigInt, l: List[BigInt]): List[BigInt] = { insert(a,l) } ensuring { res => (size(res) == size(l) + 1) && (content(res) == content(l) ++ Set(a))} } diff --git a/src/test/resources/regression/verification/purescala/valid/Heap.scala b/src/test/resources/regression/verification/purescala/valid/Heap.scala index f70934816ca4b437b4cb08bded8bc6d586499ca0..f1464e8bcfbacf1b4ea2bc721e104d9309a98b44 100644 --- a/src/test/resources/regression/verification/purescala/valid/Heap.scala +++ b/src/test/resources/regression/verification/purescala/valid/Heap.scala @@ -7,25 +7,25 @@ object Heaps { /*~~~~~~~~~~~~~~~~~~~~~~~*/ /* Data type definitions */ /*~~~~~~~~~~~~~~~~~~~~~~~*/ - private case class Node(rank : Int, elem : Int, nodes : Heap) + private case class Node(rank : BigInt, elem : BigInt, nodes : Heap) sealed abstract class Heap private case class Nodes(head : Node, tail : Heap) extends Heap private case object Empty extends Heap sealed abstract class OptInt - case class Some(value : Int) extends OptInt + case class Some(value : BigInt) extends OptInt case object None extends OptInt /*~~~~~~~~~~~~~~~~~~~~~~~*/ /* Abstraction functions */ /*~~~~~~~~~~~~~~~~~~~~~~~*/ - def heapContent(h : Heap) : Set[Int] = h match { - case Empty => Set.empty[Int] + def heapContent(h : Heap) : Set[BigInt] = h match { + case Empty => Set.empty[BigInt] case Nodes(n, ns) => nodeContent(n) ++ heapContent(ns) } - def nodeContent(n : Node) : Set[Int] = n match { + def nodeContent(n : Node) : Set[BigInt] = n match { case Node(_, e, h) => Set(e) ++ heapContent(h) } @@ -78,13 +78,13 @@ object Heaps { /*~~~~~~~~~~~~~~~~*/ def empty() : Heap = { Empty - } ensuring(res => heapContent(res) == Set.empty[Int]) + } ensuring(res => heapContent(res) == Set.empty[BigInt]) def isEmpty(h : Heap) : Boolean = { (h == Empty) - } ensuring(res => res == (heapContent(h) == Set.empty[Int])) + } ensuring(res => res == (heapContent(h) == Set.empty[BigInt])) - def insert(e : Int, h : Heap) : Heap = { + def insert(e : BigInt, h : Heap) : Heap = { insertNode(Node(0, e, Empty), h) } ensuring(res => heapContent(res) == heapContent(h) ++ Set(e)) diff --git a/src/test/resources/regression/verification/purescala/valid/InsertionSort.scala b/src/test/resources/regression/verification/purescala/valid/InsertionSort.scala index 820e9717857ecb98e3d5034d2de90a15b4a9cde9..a3120a9bc9e728ab5a6f352d649b64e9c67e761c 100644 --- a/src/test/resources/regression/verification/purescala/valid/InsertionSort.scala +++ b/src/test/resources/regression/verification/purescala/valid/InsertionSort.scala @@ -13,8 +13,8 @@ object InsertionSort { case class Some(value: Int) extends OptInt case class None() extends OptInt - def size(l : List) : Int = (l match { - case Nil() => 0 + def size(l : List) : BigInt = (l match { + case Nil() => BigInt(0) case Cons(_, xs) => 1 + size(xs) }) ensuring(_ >= 0) diff --git a/src/test/resources/regression/verification/purescala/valid/ListOperations.scala b/src/test/resources/regression/verification/purescala/valid/ListOperations.scala deleted file mode 100644 index fb6b11d94c35c33ab4293712697906f2b91b46d3..0000000000000000000000000000000000000000 --- a/src/test/resources/regression/verification/purescala/valid/ListOperations.scala +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright 2009-2014 EPFL, Lausanne */ - -import scala.collection.immutable.Set -import leon.annotation._ -import leon.lang._ - -object ListOperations { - sealed abstract class List - case class Cons(head: Int, tail: List) extends List - case class Nil() extends List - - sealed abstract class IntPairList - case class IPCons(head: IntPair, tail: IntPairList) extends IntPairList - case class IPNil() extends IntPairList - - sealed abstract class IntPair - case class IP(fst: Int, snd: Int) extends IntPair - - def size(l: List) : Int = (l match { - case Nil() => 0 - case Cons(_, t) => 1 + size(t) - }) ensuring(res => res >= 0) - - def iplSize(l: IntPairList) : Int = (l match { - case IPNil() => 0 - case IPCons(_, xs) => 1 + iplSize(xs) - }) ensuring(_ >= 0) - - def zip(l1: List, l2: List) : IntPairList = { - // try to comment this and see how pattern-matching becomes - // non-exhaustive and post-condition fails - require(size(l1) == size(l2)) - - l1 match { - case Nil() => IPNil() - case Cons(x, xs) => l2 match { - case Cons(y, ys) => IPCons(IP(x, y), zip(xs, ys)) - } - } - } ensuring(iplSize(_) == size(l1)) - - def sizeTailRec(l: List) : Int = sizeTailRecAcc(l, 0) - def sizeTailRecAcc(l: List, acc: Int) : Int = { - require(acc >= 0) - l match { - case Nil() => acc - case Cons(_, xs) => sizeTailRecAcc(xs, acc+1) - } - } ensuring(res => res == size(l) + acc) - - def sizesAreEquiv(l: List) : Boolean = { - size(l) == sizeTailRec(l) - }.holds - - def content(l: List) : Set[Int] = l match { - case Nil() => Set.empty[Int] - case Cons(x, xs) => Set(x) ++ content(xs) - } - - def sizeAndContent(l: List) : Boolean = { - size(l) == 0 || content(l) != Set.empty[Int] - }.holds - - def drunk(l : List) : List = (l match { - case Nil() => Nil() - case Cons(x,l1) => Cons(x,Cons(x,drunk(l1))) - }) ensuring (size(_) == 2 * size(l)) - - def reverse(l: List) : List = reverse0(l, Nil()) ensuring(content(_) == content(l)) - def reverse0(l1: List, l2: List) : List = (l1 match { - case Nil() => l2 - case Cons(x, xs) => reverse0(xs, Cons(x, l2)) - }) ensuring(content(_) == content(l1) ++ content(l2)) - - def append(l1 : List, l2 : List) : List = (l1 match { - case Nil() => l2 - case Cons(x,xs) => Cons(x, append(xs, l2)) - }) ensuring(content(_) == content(l1) ++ content(l2)) - - @induct - def nilAppend(l : List) : Boolean = (append(l, Nil()) == l).holds - - @induct - def appendAssoc(xs : List, ys : List, zs : List) : Boolean = - (append(append(xs, ys), zs) == append(xs, append(ys, zs))).holds - - @induct - def sizeAppend(l1 : List, l2 : List) : Boolean = - (size(append(l1, l2)) == size(l1) + size(l2)).holds - - @induct - def concat(l1: List, l2: List) : List = - concat0(l1, l2, Nil()) ensuring(content(_) == content(l1) ++ content(l2)) - - @induct - def concat0(l1: List, l2: List, l3: List) : List = (l1 match { - case Nil() => l2 match { - case Nil() => reverse(l3) - case Cons(y, ys) => { - concat0(Nil(), ys, Cons(y, l3)) - } - } - case Cons(x, xs) => concat0(xs, l2, Cons(x, l3)) - }) ensuring(content(_) == content(l1) ++ content(l2) ++ content(l3)) -} diff --git a/src/test/resources/regression/verification/purescala/valid/MergeSort.scala b/src/test/resources/regression/verification/purescala/valid/MergeSort.scala index e3714371ba6a331c705d4f71a217ef223afe6209..de8b0c32b21cca1d1cbe869fe89dd3fb70d0cece 100644 --- a/src/test/resources/regression/verification/purescala/valid/MergeSort.scala +++ b/src/test/resources/regression/verification/purescala/valid/MergeSort.scala @@ -23,8 +23,8 @@ object MergeSort { case LCons(x, xs) => content(x) ++ lContent(xs) } - def size(list : List) : Int = (list match { - case Nil() => 0 + def size(list : List) : BigInt = (list match { + case Nil() => BigInt(0) case Cons(_, xs) => 1 + size(xs) }) ensuring(_ >= 0) @@ -40,7 +40,7 @@ object MergeSort { case LCons(x, xs) => isSorted(x) && lIsSorted(xs) } - def abs(i : Int) : Int = { + def abs(i : BigInt) : BigInt = { if(i < 0) -i else i } ensuring(_ >= 0) diff --git a/src/test/resources/regression/verification/purescala/valid/PositiveMap.scala b/src/test/resources/regression/verification/purescala/valid/PositiveMap.scala index 7ee05ec9cffdc9789bfe4372586c20a882a84d37..0441ec26ca74f98dec17e05e91e487f0756b78ad 100644 --- a/src/test/resources/regression/verification/purescala/valid/PositiveMap.scala +++ b/src/test/resources/regression/verification/purescala/valid/PositiveMap.scala @@ -3,7 +3,7 @@ import leon.lang._ object PositiveMap { abstract class List - case class Cons(head: Int, tail: List) extends List + case class Cons(head: BigInt, tail: List) extends List case class Nil() extends List def positive(list: List): Boolean = list match { @@ -11,7 +11,7 @@ object PositiveMap { case Nil() => true } - def positiveMap_passing_1(f: (Int) => Int, list: List): List = { + def positiveMap_passing_1(f: (BigInt) => BigInt, list: List): List = { list match { case Cons(head, tail) => val fh = f(head) @@ -21,7 +21,7 @@ object PositiveMap { } } ensuring { res => positive(res) } - def positiveMap_passing_2(f: (Int) => Int, list: List): List = { + def positiveMap_passing_2(f: (BigInt) => BigInt, list: List): List = { list match { case Cons(head, tail) => val fh = f(head) diff --git a/src/test/resources/regression/verification/purescala/valid/RedBlackTree.scala b/src/test/resources/regression/verification/purescala/valid/RedBlackTree.scala index 15f4ba78d016836e875e3727ed89138eea152a06..841befb415c77e3609b9ad7bf28a1e760d3ce39f 100644 --- a/src/test/resources/regression/verification/purescala/valid/RedBlackTree.scala +++ b/src/test/resources/regression/verification/purescala/valid/RedBlackTree.scala @@ -11,19 +11,19 @@ object RedBlackTree { sealed abstract class Tree case class Empty() extends Tree - case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree + case class Node(color: Color, left: Tree, value: BigInt, right: Tree) extends Tree sealed abstract class OptionInt - case class Some(v : Int) extends OptionInt + case class Some(v : BigInt) extends OptionInt case class None() extends OptionInt - def content(t: Tree) : Set[Int] = t match { + def content(t: Tree) : Set[BigInt] = t match { case Empty() => Set.empty case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r) } - def size(t: Tree) : Int = (t match { - case Empty() => 0 + def size(t: Tree) : BigInt = (t match { + case Empty() => BigInt(0) case Node(_, l, v, r) => size(l) + 1 + size(r) }) ensuring(_ >= 0) @@ -50,14 +50,14 @@ object RedBlackTree { case Empty() => true } - def blackHeight(t : Tree) : Int = t match { + def blackHeight(t : Tree) : BigInt = t match { case Empty() => 1 case Node(Black(), l, _, _) => blackHeight(l) + 1 case Node(Red(), l, _, _) => blackHeight(l) } // <<insert element x into the tree t>> - def ins(x: Int, t: Tree): Tree = { + def ins(x: BigInt, t: Tree): Tree = { require(redNodesHaveBlackChildren(t) && blackBalanced(t)) t match { case Empty() => Node(Red(),Empty(),x,Empty()) @@ -79,12 +79,12 @@ object RedBlackTree { } } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res)) - def add(x: Int, t: Tree): Tree = { + def add(x: BigInt, t: Tree): Tree = { require(redNodesHaveBlackChildren(t) && blackBalanced(t)) makeBlack(ins(x, t)) } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res)) - def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = { + def balance(c: Color, a: Tree, x: BigInt, b: Tree): Tree = { Node(c,a,x,b) match { case Node(Black(),Node(Red(),Node(Red(),a,xV,b),yV,c),zV,d) => Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d)) diff --git a/src/test/resources/regression/verification/purescala/valid/SearchLinkedList.scala b/src/test/resources/regression/verification/purescala/valid/SearchLinkedList.scala index bf259ab0f480ee303c3ee27a878984fe9f488876..bd0596fbaab48f4a64309e71d019db53ed72db2a 100644 --- a/src/test/resources/regression/verification/purescala/valid/SearchLinkedList.scala +++ b/src/test/resources/regression/verification/purescala/valid/SearchLinkedList.scala @@ -9,8 +9,8 @@ object SearchLinkedList { case class Cons(head : Int, tail : List) extends List case class Nil() extends List - def size(list : List) : Int = (list match { - case Nil() => 0 + def size(list : List) : BigInt = (list match { + case Nil() => BigInt(0) case Cons(_, xs) => 1 + size(xs) }) ensuring(_ >= 0) @@ -19,9 +19,9 @@ object SearchLinkedList { case Cons(x, xs) => x == elem || contains(xs, elem) }) - def firstZero(list : List) : Int = (list match { - case Nil() => 0 - case Cons(x, xs) => if (x == 0) 0 else firstZero(xs) + 1 + def firstZero(list : List) : BigInt = (list match { + case Nil() => BigInt(0) + case Cons(x, xs) => if (x == 0) BigInt(0) else firstZero(xs) + 1 }) ensuring (res => res >= 0 && (if (contains(list, 0)) { firstZeroAtPos(list, res) @@ -29,14 +29,14 @@ object SearchLinkedList { res == size(list) })) - def firstZeroAtPos(list : List, pos : Int) : Boolean = { + def firstZeroAtPos(list : List, pos : BigInt) : Boolean = { list match { case Nil() => false - case Cons(x, xs) => if (pos == 0) x == 0 else x != 0 && firstZeroAtPos(xs, pos - 1) + case Cons(x, xs) => if (pos == BigInt(0)) x == 0 else x != 0 && firstZeroAtPos(xs, pos - 1) } } - def goal(list : List, i : Int) : Boolean = { + def goal(list : List, i : BigInt) : Boolean = { if(firstZero(list) == i) { if(contains(list, 0)) { firstZeroAtPos(list, i) diff --git a/src/test/resources/regression/verification/xlang/invalid/Mean.scala b/src/test/resources/regression/verification/xlang/invalid/Mean.scala new file mode 100644 index 0000000000000000000000000000000000000000..f6e8757d5f12e82ac472e764780dce12d17a187a --- /dev/null +++ b/src/test/resources/regression/verification/xlang/invalid/Mean.scala @@ -0,0 +1,12 @@ +import scala.collection.immutable.Set +import leon.annotation._ +import leon.lang._ + +object Mean { + + def meanOverflow(x: Int, y: Int): Int = { + require(x <= y && x >= 0 && y >= 0) + (x + y)/2 + } ensuring(m => m >= x && m <= y) + +} diff --git a/src/test/resources/regression/verification/xlang/valid/Arithmetic.scala b/src/test/resources/regression/verification/xlang/valid/Arithmetic.scala index 56baab22fe29220879459d2927fc9c667412894d..2e080a90c7245efe9490d2cf208612cc0280c271 100644 --- a/src/test/resources/regression/verification/xlang/valid/Arithmetic.scala +++ b/src/test/resources/regression/verification/xlang/valid/Arithmetic.scala @@ -5,17 +5,17 @@ import leon.lang._ object Arithmetic { /* VSTTE 2008 - Dafny paper */ - def mult(x : Int, y : Int): Int = ({ - var r = 0 + def mult(x : BigInt, y : BigInt): BigInt = ({ + var r: BigInt = 0 if(y < 0) { var n = y - (while(n != 0) { + (while(n != BigInt(0)) { r = r - x n = n + 1 }) invariant(r == x * (y - n) && 0 <= -n) } else { var n = y - (while(n != 0) { + (while(n != BigInt(0)) { r = r + x n = n - 1 }) invariant(r == x * (y - n) && 0 <= n) @@ -24,17 +24,17 @@ object Arithmetic { }) ensuring(_ == x*y) /* VSTTE 2008 - Dafny paper */ - def add(x : Int, y : Int): Int = ({ + def add(x : BigInt, y : BigInt): BigInt = ({ var r = x if(y < 0) { var n = y - (while(n != 0) { + (while(n != BigInt(0)) { r = r - 1 n = n + 1 }) invariant(r == x + y - n && 0 <= -n) } else { var n = y - (while(n != 0) { + (while(n != BigInt(0)) { r = r + 1 n = n - 1 }) invariant(r == x + y - n && 0 <= n) @@ -43,10 +43,10 @@ object Arithmetic { }) ensuring(_ == x+y) - def sum(n: Int): Int = { + def sum(n: BigInt): BigInt = { require(n >= 0) - var r = 0 - var i = 0 + var r = BigInt(0) + var i = BigInt(0) (while(i < n) { i = i + 1 r = r + i @@ -54,10 +54,10 @@ object Arithmetic { r } ensuring(_ >= n) - def divide(x: Int, y: Int): (Int, Int) = { + def divide(x: BigInt, y: BigInt): (BigInt, BigInt) = { require(x >= 0 && y > 0) var r = x - var q = 0 + var q = BigInt(0) (while(r >= y) { r = r - y q = q + 1 diff --git a/src/test/resources/regression/verification/xlang/valid/Mean.scala b/src/test/resources/regression/verification/xlang/valid/Mean.scala new file mode 100644 index 0000000000000000000000000000000000000000..447553e95006e3430b9b22bcc88f0d0800391dbf --- /dev/null +++ b/src/test/resources/regression/verification/xlang/valid/Mean.scala @@ -0,0 +1,12 @@ +import scala.collection.immutable.Set +import leon.annotation._ +import leon.lang._ + +object Mean { + + def mean(x: Int, y: Int): Int = { + require(x <= y && x >= 0 && y >= 0) + x + (y - x)/2 + } ensuring(m => m >= x && m <= y) + +} diff --git a/src/test/resources/regression/verification/xlang/valid/Nested2.scala b/src/test/resources/regression/verification/xlang/valid/Nested2.scala index da94f93d6fee5db8ff425a8f10aa8ec23b22d7f1..35cbb861183aaff59932a3e71d4eda97bd461d3a 100644 --- a/src/test/resources/regression/verification/xlang/valid/Nested2.scala +++ b/src/test/resources/regression/verification/xlang/valid/Nested2.scala @@ -2,10 +2,10 @@ object Nested2 { - def foo(a: Int): Int = { + def foo(a: BigInt): BigInt = { require(a >= 0) val b = a + 2 - def rec1(c: Int): Int = { + def rec1(c: BigInt): BigInt = { require(c >= 0) b + c } diff --git a/src/test/resources/regression/verification/xlang/valid/Nested3.scala b/src/test/resources/regression/verification/xlang/valid/Nested3.scala index 81b7483375b9225beab3cb486d40d1bea9a0204a..05449370531b823999b4b40683db662b457abfd2 100644 --- a/src/test/resources/regression/verification/xlang/valid/Nested3.scala +++ b/src/test/resources/regression/verification/xlang/valid/Nested3.scala @@ -2,11 +2,11 @@ object Nested3 { - def foo(a: Int): Int = { + def foo(a: BigInt): BigInt = { require(a >= 0 && a <= 50) val b = a + 2 val c = a + b - def rec1(d: Int): Int = { + def rec1(d: BigInt): BigInt = { require(d >= 0 && d <= 50) val e = d + b + c e diff --git a/src/test/resources/regression/verification/xlang/valid/Nested4.scala b/src/test/resources/regression/verification/xlang/valid/Nested4.scala index cb91848ee813e4c602f73e88b65c555c5f3b8685..7b82532dfed6c5b4ced77eee01840e39a5751d83 100644 --- a/src/test/resources/regression/verification/xlang/valid/Nested4.scala +++ b/src/test/resources/regression/verification/xlang/valid/Nested4.scala @@ -2,20 +2,20 @@ object Nested4 { - def foo(a: Int, a2: Int): Int = { + def foo(a: BigInt, a2: BigInt): BigInt = { require(a >= 0 && a <= 50) val b = a + 2 val c = a + b if(a2 > a) { - def rec1(d: Int): Int = { + def rec1(d: BigInt): BigInt = { require(d >= 0 && d <= 50) val e = d + b + c + a2 e } ensuring(_ > 0) rec1(2) } else { - 5 + BigInt(5) } - } ensuring(_ > 0) + } ensuring(x => x > 0) } diff --git a/src/test/resources/regression/verification/xlang/valid/Nested6.scala b/src/test/resources/regression/verification/xlang/valid/Nested6.scala index 305870f843d9ec22b94bc5e7274d8a8cb2b8b9b5..f7bfa772fa2f31ac30efa8fd3c1be5be6813318b 100644 --- a/src/test/resources/regression/verification/xlang/valid/Nested6.scala +++ b/src/test/resources/regression/verification/xlang/valid/Nested6.scala @@ -2,15 +2,15 @@ object Nested5 { - def foo(a: Int): Int = { + def foo(a: BigInt): BigInt = { require(a >= 0) - def bar(b: Int): Int = { + def bar(b: BigInt): BigInt = { require(b > 0) b + 3 } ensuring(prop(a, b) && a >= 0 && _ == b + 3) bar(2) - } ensuring(a >= 0 && _ == 5) + } ensuring(a >= 0 && _ == BigInt(5)) - def prop(x: Int, y: Int): Boolean = x + y > 0 + def prop(x: BigInt, y: BigInt): Boolean = x + y > 0 } diff --git a/src/test/resources/regression/verification/xlang/valid/Nested7.scala b/src/test/resources/regression/verification/xlang/valid/Nested7.scala index 2f785f083c871923c6021e29bf4f10ae7d82f5e0..4187e7b0fb31affe67314cb072be128ef386ca5b 100644 --- a/src/test/resources/regression/verification/xlang/valid/Nested7.scala +++ b/src/test/resources/regression/verification/xlang/valid/Nested7.scala @@ -2,10 +2,10 @@ object Nested2 { - def foo(a: Int): Int = { + def foo(a: BigInt): BigInt = { require(a >= 0) val b = a + 2 - def rec1(c: Int): Int = { + def rec1(c: BigInt): BigInt = { require(c >= 0) b + c + bar(a) + bar(b) + bar(c) } @@ -13,7 +13,7 @@ object Nested2 { } ensuring(_ > 0) - def bar(x: Int): Int = { + def bar(x: BigInt): BigInt = { require(x >= 0) x } ensuring(_ >= 0) diff --git a/src/test/resources/regression/verification/xlang/valid/Nested8.scala b/src/test/resources/regression/verification/xlang/valid/Nested8.scala index 4024de42cec25892dd26ba08a4af0b83ea921150..6bcb9050ba953d96d7ea7f9f74b9e477d989dcc6 100644 --- a/src/test/resources/regression/verification/xlang/valid/Nested8.scala +++ b/src/test/resources/regression/verification/xlang/valid/Nested8.scala @@ -4,12 +4,12 @@ import leon.lang._ object Nested8 { - def foo(a: Int): Int = { + def foo(a: BigInt): BigInt = { require(a > 0) - def bar(b: Int): Int = { + def bar(b: BigInt): BigInt = { if(a < b) { - def rec(c: Int): Int = { + def rec(c: BigInt): BigInt = { require(c > 0) c + b } ensuring(_ > 0) diff --git a/src/test/resources/regression/verification/xlang/valid/Nested9.scala b/src/test/resources/regression/verification/xlang/valid/Nested9.scala index 14f912137f6a38b7e8057916135f28fee3e1d2d0..148ba3a589cf1d61003bd9f79d4a7d04f994416f 100644 --- a/src/test/resources/regression/verification/xlang/valid/Nested9.scala +++ b/src/test/resources/regression/verification/xlang/valid/Nested9.scala @@ -2,15 +2,15 @@ object Nested4 { - def foo(a: Int, a2: Int): Int = { + def foo(a: BigInt, a2: BigInt): BigInt = { require(a >= 0 && a <= 50) val b = a + 2 val c = a + b if(a2 > a) { - def rec1(d: Int): Int = { + def rec1(d: BigInt): BigInt = { require(d >= 0 && d <= 50) val e = d + b + c + a2 - def rec2(f: Int): Int = { + def rec2(f: BigInt): BigInt = { require(f >= c) f + e } ensuring(_ > 0) @@ -18,7 +18,7 @@ object Nested4 { } ensuring(_ > 0) rec1(2) } else { - 5 + BigInt(5) } } ensuring(_ > 0) diff --git a/src/test/scala/leon/test/codegen/CodeGenTests.scala b/src/test/scala/leon/test/codegen/CodeGenTests.scala index af02b00a9f56e09c9f8a9ebad3247ce3d8d95bf9..1e0ad3a1172c330ea22a15cee2b434535b3358de 100644 --- a/src/test/scala/leon/test/codegen/CodeGenTests.scala +++ b/src/test/scala/leon/test/codegen/CodeGenTests.scala @@ -104,7 +104,20 @@ class CodeGenTests extends test.LeonTestSuite { } }""", IntLiteral(1) - ), + ), + + TestCase("simpleBigInt", """ + object simple { + abstract class Abs + case class Conc(x : BigInt) extends Abs + def test = { + val c = Conc(1) + c.x + + } + }""", + InfiniteIntegerLiteral(1) + ), TestCase("eager", """ object eager { @@ -158,6 +171,19 @@ class CodeGenTests extends test.LeonTestSuite { IntLiteral(10) ), + TestCase("methSimpleBignt", """ + object methSimple { + + sealed abstract class Ab { + def f2(x : BigInt): BigInt = x + 5 + } + case class Con() extends Ab { } + + def test = Con().f2(5) + }""", + InfiniteIntegerLiteral(10) + ), + TestCase("methods", """ object methods { def f1 = 4 diff --git a/src/test/scala/leon/test/evaluators/DefaultEvaluatorTests.scala b/src/test/scala/leon/test/evaluators/DefaultEvaluatorTests.scala index 0dd8fe1d38ab195ddd2b7d6f0d13d86b2af6f7ea..7dd1b474266c3fb7ea6e850174deef78c0b59a93 100644 --- a/src/test/scala/leon/test/evaluators/DefaultEvaluatorTests.scala +++ b/src/test/scala/leon/test/evaluators/DefaultEvaluatorTests.scala @@ -34,19 +34,32 @@ class DefaultEvaluatorTests extends leon.test.LeonTestSuite { expectSuccessful(defaultEvaluator.eval(IntLiteral(0)), IntLiteral(0)) expectSuccessful(defaultEvaluator.eval(IntLiteral(42)), IntLiteral(42)) expectSuccessful(defaultEvaluator.eval(UnitLiteral()), UnitLiteral()) + expectSuccessful(defaultEvaluator.eval(InfiniteIntegerLiteral(0)), InfiniteIntegerLiteral(0)) + expectSuccessful(defaultEvaluator.eval(InfiniteIntegerLiteral(42)), InfiniteIntegerLiteral(42)) + } + + test("eval of simple bit vector arithmetic expressions") { + expectSuccessful(defaultEvaluator.eval(BVPlus(IntLiteral(3), IntLiteral(5))), IntLiteral(8)) + expectSuccessful(defaultEvaluator.eval(BVPlus(IntLiteral(0), IntLiteral(5))), IntLiteral(5)) + expectSuccessful(defaultEvaluator.eval(BVTimes(IntLiteral(3), IntLiteral(3))), IntLiteral(9)) } test("eval of simple arithmetic expressions") { expectSuccessful( - defaultEvaluator.eval(Plus(IntLiteral(3), IntLiteral(5))), IntLiteral(8)) + defaultEvaluator.eval(Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(5))), + InfiniteIntegerLiteral(8)) expectSuccessful( - defaultEvaluator.eval(Minus(IntLiteral(7), IntLiteral(2))), IntLiteral(5)) + defaultEvaluator.eval(Minus(InfiniteIntegerLiteral(7), InfiniteIntegerLiteral(2))), + InfiniteIntegerLiteral(5)) expectSuccessful( - defaultEvaluator.eval(UMinus(IntLiteral(7))), IntLiteral(-7)) + defaultEvaluator.eval(UMinus(InfiniteIntegerLiteral(7))), + InfiniteIntegerLiteral(-7)) expectSuccessful( - defaultEvaluator.eval(Times(IntLiteral(2), IntLiteral(3))), IntLiteral(6)) + defaultEvaluator.eval(Times(InfiniteIntegerLiteral(2), InfiniteIntegerLiteral(3))), + InfiniteIntegerLiteral(6)) expectSuccessful( - defaultEvaluator.eval(Modulo(IntLiteral(10), IntLiteral(3))), IntLiteral(1)) + defaultEvaluator.eval(Modulo(InfiniteIntegerLiteral(10), InfiniteIntegerLiteral(3))), + InfiniteIntegerLiteral(1)) } test("Eval of simple boolean operations") { @@ -146,4 +159,5 @@ class DefaultEvaluatorTests extends leon.test.LeonTestSuite { Map(id -> IntLiteral(27))), FiniteArray(Map(), Some(IntLiteral(27)), IntLiteral(7))) } + } diff --git a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala index 5828635a309ca2b517fc454b13ed252cc7da30b7..5a0599b41c525a2e737540dfddd22768d98432e5 100644 --- a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala +++ b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala @@ -183,10 +183,10 @@ class EvaluatorsTests extends leon.test.LeonTestSuite { for(e <- evaluators) { // Some simple math. - checkComp(e, mkCall("plus", IL(60), UMinus(IL(18))), IL(42)) + checkComp(e, mkCall("plus", IL(60), BVUMinus(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("max", IL(42), BVUMinus(IL(42))), IL(42)) + checkComp(e, mkCall("intSqrt", BVUMinus(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)) diff --git a/src/test/scala/leon/test/purescala/LikelyEq.scala b/src/test/scala/leon/test/purescala/LikelyEq.scala index 3dd28dfc7032b569293e79cefb1feea63858914a..7fd0341232eb79a7f3e5ae91fb069388ec700ea2 100644 --- a/src/test/scala/leon/test/purescala/LikelyEq.scala +++ b/src/test/scala/leon/test/purescala/LikelyEq.scala @@ -50,7 +50,7 @@ trait WithLikelyEq { var cont = true while(i < counters.size && isEq) { - val m: Map[Expr, Expr] = vsOrder.zip(counters).map{case (v, c) => (Variable(v), IntLiteral(c))}.toMap + val m: Map[Expr, Expr] = vsOrder.zip(counters).map{case (v, c) => (Variable(v), InfiniteIntegerLiteral(c))}.toMap val ne1 = replace(m, e1) val ne2 = replace(m, e2) val npre = replace(m, pre) diff --git a/src/test/scala/leon/test/purescala/LikelyEqSuite.scala b/src/test/scala/leon/test/purescala/LikelyEqSuite.scala index 8c367a0cea64c914304b6007c43a0210241af7fe..fced5df182f3888a37c16227c4b1dc03e6a831a8 100644 --- a/src/test/scala/leon/test/purescala/LikelyEqSuite.scala +++ b/src/test/scala/leon/test/purescala/LikelyEqSuite.scala @@ -6,42 +6,43 @@ import leon._ import leon.test._ import leon.purescala.Common._ import leon.purescala.Trees._ +import leon.purescala.TypeTrees._ class LikelyEqSuite extends LeonTestSuite with WithLikelyEq { - def i(x: Int) = IntLiteral(x) + def i(x: Int) = InfiniteIntegerLiteral(x) - val xId = FreshIdentifier("x") + val xId = FreshIdentifier("x").setType(IntegerType) val x = Variable(xId) - val yId = FreshIdentifier("y") + val yId = FreshIdentifier("y").setType(IntegerType) val y = Variable(yId) - val zId = FreshIdentifier("z") + val zId = FreshIdentifier("z").setType(IntegerType) val z = Variable(zId) test("apply") { - assert(LikelyEq(Plus(x, x), Times(IntLiteral(2), x), Set(xId))) - assert(LikelyEq(Plus(x, x), Times(x, IntLiteral(2)), Set(xId))) + assert(LikelyEq(Plus(x, x), Times(i(2), x), Set(xId))) + assert(LikelyEq(Plus(x, x), Times(x, i(2)), Set(xId))) assert(LikelyEq(Plus(x, y), Plus(y, x), Set(xId, yId))) - assert(LikelyEq(Plus(Plus(x, y), y), Plus(x, Times(IntLiteral(2), y)), Set(xId, yId))) + assert(LikelyEq(Plus(Plus(x, y), y), Plus(x, Times(i(2), y)), Set(xId, yId))) def defaultCompare(e1: Expr, e2: Expr) = e1 == e2 assert(LikelyEq( - Plus(IntLiteral(2), Plus(x, y)), - Plus(IntLiteral(3), Plus(x, z)), + Plus(i(2), Plus(x, y)), + Plus(i(3), Plus(x, z)), Set(xId), BooleanLiteral(true), defaultCompare, - Map(yId -> IntLiteral(2), zId -> IntLiteral(1))) + Map(yId -> i(2), zId -> i(1))) ) assert(LikelyEq( - Plus(x, Times(IntLiteral(2), Division(y, IntLiteral(2)))) + Plus(x, Times(i(2), Division(y, i(2)))) , Plus(x, y) , Set(xId, yId) - , Equals(Modulo(y, IntLiteral(2)), IntLiteral(0)) + , Equals(Modulo(y, i(2)), i(0)) )) } diff --git a/src/test/scala/leon/test/purescala/TreeNormalizationsTests.scala b/src/test/scala/leon/test/purescala/TreeNormalizationsTests.scala index f05a5ddef590cce7b5c2145071cc1d4332232ddc..75dd1090343521ca272e21d6a6199df844f4a5ae 100644 --- a/src/test/scala/leon/test/purescala/TreeNormalizationsTests.scala +++ b/src/test/scala/leon/test/purescala/TreeNormalizationsTests.scala @@ -13,17 +13,17 @@ import leon.purescala.TreeOps._ import leon.purescala.TreeNormalizations._ class TreeNormalizationsTests extends LeonTestSuite with WithLikelyEq { - def i(x: Int) = IntLiteral(x) + def i(x: Int) = InfiniteIntegerLiteral(x) - val xId = FreshIdentifier("x").setType(Int32Type) + val xId = FreshIdentifier("x").setType(IntegerType) val x = Variable(xId) - val yId = FreshIdentifier("y").setType(Int32Type) + val yId = FreshIdentifier("y").setType(IntegerType) val y = Variable(yId) val xs = Set(xId, yId) - val aId = FreshIdentifier("a").setType(Int32Type) + val aId = FreshIdentifier("a").setType(IntegerType) val a = Variable(aId) - val bId = FreshIdentifier("b").setType(Int32Type) + val bId = FreshIdentifier("b").setType(IntegerType) val b = Variable(bId) val as = Set(aId, bId) @@ -35,7 +35,7 @@ class TreeNormalizationsTests extends LeonTestSuite with WithLikelyEq { } def toSum(es: Seq[Expr]) = es.reduceLeft(Plus(_, _)) - def coefToSum(es: Array[Expr], vs: Array[Expr]) = (es.zip(Array[Expr](IntLiteral(1)) ++ vs)).foldLeft[Expr](IntLiteral(0))((acc, p) => Plus(acc, Times(p._1, p._2))) + def coefToSum(es: Array[Expr], vs: Array[Expr]) = (es.zip(Array[Expr](InfiniteIntegerLiteral(1)) ++ vs)).foldLeft[Expr](InfiniteIntegerLiteral(0))((acc, p) => Plus(acc, Times(p._1, p._2))) test("checkSameExpr") { checkSameExpr(Plus(x, y), Plus(y, x), xs) @@ -80,5 +80,8 @@ class TreeNormalizationsTests extends LeonTestSuite with WithLikelyEq { val e3 = Minus(Plus(x, i(3)), Plus(y, i(2))) checkSameExpr(coefToSum(linearArithmeticForm(e3, xsOrder), Array(x, y)), e3, xs) + val e4 = Plus(Plus(i(0), i(2)), Times(i(-1), i(3))) + assert(linearArithmeticForm(e4, Array()) === Array(i(-1))) + } } diff --git a/src/test/scala/leon/test/purescala/TreeOpsTests.scala b/src/test/scala/leon/test/purescala/TreeOpsTests.scala index 4bcce108d9927dfd1ee430ede115511e36eb8aee..7137ebd34ad4c0245d68ebc5bc4807221134a3ab 100644 --- a/src/test/scala/leon/test/purescala/TreeOpsTests.scala +++ b/src/test/scala/leon/test/purescala/TreeOpsTests.scala @@ -41,17 +41,17 @@ class TreeOpsTests extends LeonTestSuite with WithLikelyEq { } - def i(x: Int) = IntLiteral(x) + def i(x: Int) = InfiniteIntegerLiteral(x) - val xId = FreshIdentifier("x").setType(Int32Type) + val xId = FreshIdentifier("x").setType(IntegerType) val x = Variable(xId) - val yId = FreshIdentifier("y").setType(Int32Type) + val yId = FreshIdentifier("y").setType(IntegerType) val y = Variable(yId) val xs = Set(xId, yId) - val aId = FreshIdentifier("a").setType(Int32Type) + val aId = FreshIdentifier("a").setType(IntegerType) val a = Variable(aId) - val bId = FreshIdentifier("b").setType(Int32Type) + val bId = FreshIdentifier("b").setType(IntegerType) val b = Variable(bId) val as = Set(aId, bId) @@ -62,36 +62,36 @@ class TreeOpsTests extends LeonTestSuite with WithLikelyEq { } test("simplifyArithmetic") { - val e1 = Plus(IntLiteral(3), IntLiteral(2)) + val e1 = Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2)) checkSameExpr(e1, simplifyArithmetic(e1), Set()) - val e2 = Plus(x, Plus(IntLiteral(3), IntLiteral(2))) + val e2 = Plus(x, Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2))) checkSameExpr(e2, simplifyArithmetic(e2), Set(xId)) - val e3 = Minus(IntLiteral(3), IntLiteral(2)) + val e3 = Minus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2)) checkSameExpr(e3, simplifyArithmetic(e3), Set()) - val e4 = Plus(x, Minus(IntLiteral(3), IntLiteral(2))) + val e4 = Plus(x, Minus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2))) checkSameExpr(e4, simplifyArithmetic(e4), Set(xId)) - val e5 = Plus(x, Minus(x, IntLiteral(2))) + val e5 = Plus(x, Minus(x, InfiniteIntegerLiteral(2))) checkSameExpr(e5, simplifyArithmetic(e5), Set(xId)) - val e6 = Times(IntLiteral(9), Plus(Division(x, IntLiteral(3)), Division(x, IntLiteral(6)))) + val e6 = Times(InfiniteIntegerLiteral(9), Plus(Division(x, InfiniteIntegerLiteral(3)), Division(x, InfiniteIntegerLiteral(6)))) checkSameExpr(e6, simplifyArithmetic(e6), Set(xId)) } test("expandAndSimplifyArithmetic") { - val e1 = Plus(IntLiteral(3), IntLiteral(2)) + val e1 = Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2)) checkSameExpr(e1, expandAndSimplifyArithmetic(e1), Set()) - val e2 = Plus(x, Plus(IntLiteral(3), IntLiteral(2))) + val e2 = Plus(x, Plus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2))) checkSameExpr(e2, expandAndSimplifyArithmetic(e2), Set(xId)) - val e3 = Minus(IntLiteral(3), IntLiteral(2)) + val e3 = Minus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2)) checkSameExpr(e3, expandAndSimplifyArithmetic(e3), Set()) - val e4 = Plus(x, Minus(IntLiteral(3), IntLiteral(2))) + val e4 = Plus(x, Minus(InfiniteIntegerLiteral(3), InfiniteIntegerLiteral(2))) checkSameExpr(e4, expandAndSimplifyArithmetic(e4), Set(xId)) - val e5 = Plus(x, Minus(x, IntLiteral(2))) + val e5 = Plus(x, Minus(x, InfiniteIntegerLiteral(2))) checkSameExpr(e5, expandAndSimplifyArithmetic(e5), Set(xId)) - val e6 = Times(IntLiteral(9), Plus(Division(x, IntLiteral(3)), Division(x, IntLiteral(6)))) + val e6 = Times(InfiniteIntegerLiteral(9), Plus(Division(x, InfiniteIntegerLiteral(3)), Division(x, InfiniteIntegerLiteral(6)))) checkSameExpr(e6, expandAndSimplifyArithmetic(e6), Set(xId)) } @@ -124,10 +124,10 @@ class TreeOpsTests extends LeonTestSuite with WithLikelyEq { } test("pre and post traversal") { - val expr = Plus(IntLiteral(1), Minus(IntLiteral(2), IntLiteral(3))) + val expr = Plus(InfiniteIntegerLiteral(1), Minus(InfiniteIntegerLiteral(2), InfiniteIntegerLiteral(3))) var res = "" def f(e: Expr): Unit = e match { - case IntLiteral(i) => res += i + case InfiniteIntegerLiteral(i) => res += i case _ : Plus => res += "P" case _ : Minus => res += "M" } @@ -141,18 +141,18 @@ class TreeOpsTests extends LeonTestSuite with WithLikelyEq { } test("pre- and postMap") { - val expr = Plus(IntLiteral(1), Minus(IntLiteral(2), IntLiteral(3))) + val expr = Plus(InfiniteIntegerLiteral(1), Minus(InfiniteIntegerLiteral(2), InfiniteIntegerLiteral(3))) def op(e : Expr ) = e match { - case Minus(IntLiteral(2), e2) => Some(IntLiteral(2)) - case IntLiteral(1) => Some(IntLiteral(2)) - case IntLiteral(2) => Some(IntLiteral(42)) + case Minus(InfiniteIntegerLiteral(two), e2) if two == BigInt(2) => Some(InfiniteIntegerLiteral(2)) + case InfiniteIntegerLiteral(one) if one == BigInt(1) => Some(InfiniteIntegerLiteral(2)) + case InfiniteIntegerLiteral(two) if two == BigInt(2) => Some(InfiniteIntegerLiteral(42)) case _ => None } - assert( preMap(op, false)(expr) == Plus(IntLiteral(2), IntLiteral(2)) ) - assert( preMap(op, true )(expr) == Plus(IntLiteral(42), IntLiteral(42)) ) - assert( postMap(op, false)(expr) == Plus(IntLiteral(2), Minus(IntLiteral(42), IntLiteral(3))) ) - assert( postMap(op, true)(expr) == Plus(IntLiteral(42), Minus(IntLiteral(42), IntLiteral(3))) ) + assert( preMap(op, false)(expr) == Plus(InfiniteIntegerLiteral(2), InfiniteIntegerLiteral(2)) ) + assert( preMap(op, true )(expr) == Plus(InfiniteIntegerLiteral(42), InfiniteIntegerLiteral(42)) ) + assert( postMap(op, false)(expr) == Plus(InfiniteIntegerLiteral(2), Minus(InfiniteIntegerLiteral(42), InfiniteIntegerLiteral(3))) ) + assert( postMap(op, true)(expr) == Plus(InfiniteIntegerLiteral(42), Minus(InfiniteIntegerLiteral(42), InfiniteIntegerLiteral(3))) ) } diff --git a/src/test/scala/leon/test/solvers/TimeoutSolverTests.scala b/src/test/scala/leon/test/solvers/TimeoutSolverTests.scala index 0c4bd2791ed8371542f7b3918260b52914c26794..4f156461982efcaea69db1de5a0498c9f758801e 100644 --- a/src/test/scala/leon/test/solvers/TimeoutSolverTests.scala +++ b/src/test/scala/leon/test/solvers/TimeoutSolverTests.scala @@ -56,14 +56,14 @@ class TimeoutSolverTests extends LeonTestSuite { assert(check(sf, BooleanLiteral(true)) === None) assert(check(sf, BooleanLiteral(false)) === None) - val x = Variable(FreshIdentifier("x").setType(Int32Type)) + val x = Variable(FreshIdentifier("x").setType(IntegerType)) assert(check(sf, Equals(x, x)) === None) } test("TimeoutSolver 2") { val sf = getTOSolver - val x = Variable(FreshIdentifier("x").setType(Int32Type)) - val o = IntLiteral(1) + val x = Variable(FreshIdentifier("x").setType(IntegerType)) + val o = InfiniteIntegerLiteral(1) assert(check(sf, Equals(Plus(x, o), Plus(o, x))) === None) assert(check(sf, Equals(Plus(x, o), x)) === None) } diff --git a/src/test/scala/leon/test/solvers/UnrollingSolverTests.scala b/src/test/scala/leon/test/solvers/UnrollingSolverTests.scala index 94ed51f643d5991cd2db73dad9cfddf37a1fb751..46f56b4e796042daa7de619b28a50837433a4fda 100644 --- a/src/test/scala/leon/test/solvers/UnrollingSolverTests.scala +++ b/src/test/scala/leon/test/solvers/UnrollingSolverTests.scala @@ -12,14 +12,14 @@ import leon.solvers.combinators._ class UnrollingSolverTests extends LeonTestSuite { - private val fx : Identifier = FreshIdentifier("x").setType(Int32Type) - private val fres : Identifier = FreshIdentifier("res").setType(Int32Type) - private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, Int32Type, ValDef(fx, Int32Type) :: Nil, DefType.MethodDef) - fDef.body = Some(IfExpr(GreaterThan(Variable(fx), IntLiteral(0)), - Plus(Variable(fx), FunctionInvocation(fDef.typed, Seq(Minus(Variable(fx), IntLiteral(1))))), - IntLiteral(1) + private val fx : Identifier = FreshIdentifier("x").setType(IntegerType) + private val fres : Identifier = FreshIdentifier("res").setType(IntegerType) + private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx, IntegerType) :: Nil, DefType.MethodDef) + fDef.body = Some(IfExpr(GreaterThan(Variable(fx), InfiniteIntegerLiteral(0)), + Plus(Variable(fx), FunctionInvocation(fDef.typed, Seq(Minus(Variable(fx), InfiniteIntegerLiteral(1))))), + InfiniteIntegerLiteral(1) )) - fDef.postcondition = Some(fres -> GreaterThan(Variable(fres), IntLiteral(0))) + fDef.postcondition = Some(fres -> GreaterThan(Variable(fres), InfiniteIntegerLiteral(0))) private val program = Program( FreshIdentifier("Minimal"), @@ -42,6 +42,6 @@ class UnrollingSolverTests extends LeonTestSuite { check(BooleanLiteral(true), Some(true), "'true' should always be valid") check(BooleanLiteral(false), Some(false), "'false' should never be valid") - check(Not(GreaterThan(FunctionInvocation(fDef.typed, Seq(Variable(FreshIdentifier("toto").setType(Int32Type)))), IntLiteral(0))), + check(Not(GreaterThan(FunctionInvocation(fDef.typed, Seq(Variable(FreshIdentifier("toto").setType(IntegerType)))), InfiniteIntegerLiteral(0))), Some(false), "unrolling should enable recursive definition verification") } diff --git a/src/test/scala/leon/test/solvers/z3/FairZ3SolverTests.scala b/src/test/scala/leon/test/solvers/z3/FairZ3SolverTests.scala index bde8cc42346edb8b5c2e53821f9a153e6e94c264..c5662615ef3d7fb189cae9a86fa664af93530976 100644 --- a/src/test/scala/leon/test/solvers/z3/FairZ3SolverTests.scala +++ b/src/test/scala/leon/test/solvers/z3/FairZ3SolverTests.scala @@ -38,9 +38,9 @@ class FairZ3SolverTests extends LeonTestSuite { ) // def f(fx : Int) : Int = fx + 1 - private val fx : Identifier = FreshIdentifier("x").setType(Int32Type) - private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, Int32Type, ValDef(fx, Int32Type) :: Nil, DefType.MethodDef) - fDef.body = Some(Plus(Variable(fx), IntLiteral(1))) + private val fx : Identifier = FreshIdentifier("x").setType(IntegerType) + private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx, IntegerType) :: Nil, DefType.MethodDef) + fDef.body = Some(Plus(Variable(fx), InfiniteIntegerLiteral(1))) private val minimalProgram = Program( FreshIdentifier("Minimal"), @@ -50,8 +50,8 @@ class FairZ3SolverTests extends LeonTestSuite { ))) ) - private val x : Expr = Variable(FreshIdentifier("x").setType(Int32Type)) - private val y : Expr = Variable(FreshIdentifier("y").setType(Int32Type)) + private val x : Expr = Variable(FreshIdentifier("x").setType(IntegerType)) + private val y : Expr = Variable(FreshIdentifier("y").setType(IntegerType)) private def f(e : Expr) : Expr = FunctionInvocation(fDef.typed, e :: Nil) private val solver = SimpleSolverAPI(SolverFactory(() => new FairZ3Solver(testContext, minimalProgram))) @@ -59,7 +59,7 @@ class FairZ3SolverTests extends LeonTestSuite { private val tautology1 : Expr = BooleanLiteral(true) assertValid(solver, tautology1) - private val tautology2 : Expr = Equals(Plus(x, x), Times(IntLiteral(2), x)) + private val tautology2 : Expr = Equals(Plus(x, x), Times(InfiniteIntegerLiteral(2), x)) assertValid(solver, tautology2) // This one contains a function invocation but is valid regardless of its @@ -73,11 +73,11 @@ class FairZ3SolverTests extends LeonTestSuite { private val wrong1 : Expr = BooleanLiteral(false) assertInvalid(solver, wrong1) - private val wrong2 : Expr = Equals(Plus(x, x), Times(IntLiteral(3), x)) + private val wrong2 : Expr = Equals(Plus(x, x), Times(InfiniteIntegerLiteral(3), x)) assertInvalid(solver, wrong2) // This is true, and FairZ3Solver should know it (by inlining). - private val unknown1 : Expr = Equals(f(x), Plus(x, IntLiteral(1))) + private val unknown1 : Expr = Equals(f(x), Plus(x, InfiniteIntegerLiteral(1))) assertValid(solver, unknown1) test("Check assumptions") { diff --git a/src/test/scala/leon/test/solvers/z3/FairZ3SolverTestsNewAPI.scala b/src/test/scala/leon/test/solvers/z3/FairZ3SolverTestsNewAPI.scala index 685bea19be921c205f0a427f3269b2b36e21cfb8..5974d31a1f954e2daaf81ec238c93684ca9bd8d8 100644 --- a/src/test/scala/leon/test/solvers/z3/FairZ3SolverTestsNewAPI.scala +++ b/src/test/scala/leon/test/solvers/z3/FairZ3SolverTestsNewAPI.scala @@ -46,9 +46,9 @@ class FairZ3SolverTestsNewAPI extends LeonTestSuite { ) // def f(fx : Int) : Int = fx + 1 - private val fx : Identifier = FreshIdentifier("x").setType(Int32Type) - private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, Int32Type, ValDef(fx, Int32Type) :: Nil, DefType.MethodDef) - fDef.body = Some(Plus(Variable(fx), IntLiteral(1))) + private val fx : Identifier = FreshIdentifier("x").setType(IntegerType) + private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx, IntegerType) :: Nil, DefType.MethodDef) + fDef.body = Some(Plus(Variable(fx), InfiniteIntegerLiteral(1))) private val minimalProgram = Program( FreshIdentifier("Minimal"), @@ -58,8 +58,8 @@ class FairZ3SolverTestsNewAPI extends LeonTestSuite { ))) ) - private val x : Expr = Variable(FreshIdentifier("x").setType(Int32Type)) - private val y : Expr = Variable(FreshIdentifier("y").setType(Int32Type)) + private val x : Expr = Variable(FreshIdentifier("x").setType(IntegerType)) + private val y : Expr = Variable(FreshIdentifier("y").setType(IntegerType)) private def f(e : Expr) : Expr = FunctionInvocation(fDef.typed, e :: Nil) private val solver = SolverFactory(() => new FairZ3Solver(testContext, minimalProgram)) @@ -67,7 +67,7 @@ class FairZ3SolverTestsNewAPI extends LeonTestSuite { private val tautology1 : Expr = BooleanLiteral(true) assertValid(solver, tautology1) - private val tautology2 : Expr = Equals(Plus(x, x), Times(IntLiteral(2), x)) + private val tautology2 : Expr = Equals(Plus(x, x), Times(InfiniteIntegerLiteral(2), x)) assertValid(solver, tautology2) // This one contains a function invocation but is valid regardless of its @@ -81,11 +81,11 @@ class FairZ3SolverTestsNewAPI extends LeonTestSuite { private val wrong1 : Expr = BooleanLiteral(false) assertInvalid(solver, wrong1) - private val wrong2 : Expr = Equals(Plus(x, x), Times(IntLiteral(3), x)) + private val wrong2 : Expr = Equals(Plus(x, x), Times(InfiniteIntegerLiteral(3), x)) assertInvalid(solver, wrong2) // This is true, and FairZ3Solver should know it (by inlining). - private val unknown1 : Expr = Equals(f(x), Plus(x, IntLiteral(1))) + private val unknown1 : Expr = Equals(f(x), Plus(x, InfiniteIntegerLiteral(1))) assertValid(solver, unknown1) test("Check assumptions") { diff --git a/src/test/scala/leon/test/solvers/z3/UninterpretedZ3SolverTests.scala b/src/test/scala/leon/test/solvers/z3/UninterpretedZ3SolverTests.scala index b2214f57304b2eca5ce241a09cd8c59ed1cda637..1c4aadaa5867eac0126fd085f885508c3dffdf1f 100644 --- a/src/test/scala/leon/test/solvers/z3/UninterpretedZ3SolverTests.scala +++ b/src/test/scala/leon/test/solvers/z3/UninterpretedZ3SolverTests.scala @@ -39,13 +39,13 @@ class UninterpretedZ3SolverTests extends LeonTestSuite { ) // def f(fx : Int) : Int = fx + 1 - private val fx : Identifier = FreshIdentifier("x").setType(Int32Type) - private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, Int32Type, ValDef(fx, Int32Type) :: Nil, DefType.MethodDef) - fDef.body = Some(Plus(Variable(fx), IntLiteral(1))) + private val fx : Identifier = FreshIdentifier("x").setType(IntegerType) + private val fDef : FunDef = new FunDef(FreshIdentifier("f"), Nil, IntegerType, ValDef(fx, IntegerType) :: Nil, DefType.MethodDef) + fDef.body = Some(Plus(Variable(fx), InfiniteIntegerLiteral(1))) // g is a function that is not in the program (on purpose) - private val gDef : FunDef = new FunDef(FreshIdentifier("g"), Nil, Int32Type, ValDef(fx, Int32Type) :: Nil, DefType.MethodDef) - gDef.body = Some(Plus(Variable(fx), IntLiteral(1))) + private val gDef : FunDef = new FunDef(FreshIdentifier("g"), Nil, IntegerType, ValDef(fx, IntegerType) :: Nil, DefType.MethodDef) + gDef.body = Some(Plus(Variable(fx), InfiniteIntegerLiteral(1))) private val minimalProgram = Program( FreshIdentifier("Minimal"), @@ -55,8 +55,8 @@ class UninterpretedZ3SolverTests extends LeonTestSuite { ))) ) - private val x : Expr = Variable(FreshIdentifier("x").setType(Int32Type)) - private val y : Expr = Variable(FreshIdentifier("y").setType(Int32Type)) + private val x : Expr = Variable(FreshIdentifier("x").setType(IntegerType)) + private val y : Expr = Variable(FreshIdentifier("y").setType(IntegerType)) private def f(e : Expr) : Expr = FunctionInvocation(fDef.typed, e :: Nil) private def g(e : Expr) : Expr = FunctionInvocation(gDef.typed, e :: Nil) @@ -65,7 +65,7 @@ class UninterpretedZ3SolverTests extends LeonTestSuite { private val tautology1 : Expr = BooleanLiteral(true) assertValid(solver, tautology1) - private val tautology2 : Expr = Equals(Plus(x, x), Times(IntLiteral(2), x)) + private val tautology2 : Expr = Equals(Plus(x, x), Times(InfiniteIntegerLiteral(2), x)) assertValid(solver, tautology2) // This one contains a function invocation but is valid regardless of its @@ -79,14 +79,14 @@ class UninterpretedZ3SolverTests extends LeonTestSuite { private val wrong1 : Expr = BooleanLiteral(false) assertInvalid(solver, wrong1) - private val wrong2 : Expr = Equals(Plus(x, x), Times(IntLiteral(3), x)) + private val wrong2 : Expr = Equals(Plus(x, x), Times(InfiniteIntegerLiteral(3), x)) assertInvalid(solver, wrong2) // This is true, but that solver shouldn't know it. // However, since the uninterpreted solver is a nice backend for the unrolling solver, // it makes more sense to allow such formulas even if they are not completely known /* - private val unknown1 : Expr = Equals(f(x), Plus(x, IntLiteral(1))) + private val unknown1 : Expr = Equals(f(x), Plus(x, InfiniteIntegerLiteral(1))) assertUnknown(solver, unknown1) */ diff --git a/src/test/scala/leon/test/synthesis/LinearEquationsSuite.scala b/src/test/scala/leon/test/synthesis/LinearEquationsSuite.scala index fe89ed2ab1a73c258b77962c9c73ae0c0480eac8..7e30c3d46531426ab4f74f70448fdbebec5ec230 100644 --- a/src/test/scala/leon/test/synthesis/LinearEquationsSuite.scala +++ b/src/test/scala/leon/test/synthesis/LinearEquationsSuite.scala @@ -16,18 +16,18 @@ import leon.synthesis.LinearEquations._ class LinearEquationsSuite extends LeonTestSuite with WithLikelyEq { - def i(x: Int) = IntLiteral(x) + def i(x: Int) = InfiniteIntegerLiteral(x) - val xId = FreshIdentifier("x").setType(Int32Type) + val xId = FreshIdentifier("x").setType(IntegerType) val x = Variable(xId) - val yId = FreshIdentifier("y").setType(Int32Type) + val yId = FreshIdentifier("y").setType(IntegerType) val y = Variable(yId) - val zId = FreshIdentifier("z").setType(Int32Type) + val zId = FreshIdentifier("z").setType(IntegerType) val z = Variable(zId) - val aId = FreshIdentifier("a").setType(Int32Type) + val aId = FreshIdentifier("a").setType(IntegerType) val a = Variable(aId) - val bId = FreshIdentifier("b").setType(Int32Type) + val bId = FreshIdentifier("b").setType(IntegerType) val b = Variable(bId) def toSum(es: Seq[Expr]) = es.reduceLeft(Plus(_, _)) @@ -41,11 +41,13 @@ class LinearEquationsSuite extends LeonTestSuite with WithLikelyEq { //use some random values to check that any vector in the basis is a valid solution to //the equation - def checkVectorSpace(basis: Array[Array[Int]], equation: Array[Int]) { + def checkVectorSpace(basis: Array[Array[Int]], equation: Array[Int]): Unit = + checkVectorSpace(basis.map(_.map(i => BigInt(i))), equation.map(i => BigInt(i))) + def checkVectorSpace(basis: Array[Array[BigInt]], equation: Array[BigInt]): Unit = { require(basis.size == basis(0).size + 1 && basis.size == equation.size) val n = basis(0).size - val min = -5 - val max = 5 + val min: BigInt = -5 + val max: BigInt = 5 val components = Array.fill(n)(min) var counter = 0 @@ -70,16 +72,16 @@ class LinearEquationsSuite extends LeonTestSuite with WithLikelyEq { } //val that the sol vector with the term in the equation - def eval(sol: Array[Int], equation: Array[Int]): Int = { + def eval(sol: Array[BigInt], equation: Array[BigInt]): BigInt = { require(sol.size == equation.size) - sol.zip(equation).foldLeft(0)((acc, p) => acc + p._1 * p._2) + sol.zip(equation).foldLeft(BigInt(0))((acc, p) => acc + p._1 * p._2) } //multiply the matrix by the vector: [M1 M2 .. Mn] * [v1 .. vn] = v1*M1 + ... + vn*Mn] - def mult(matrix: Array[Array[Int]], vector: Array[Int]): Array[Int] = { + def mult(matrix: Array[Array[BigInt]], vector: Array[BigInt]): Array[BigInt] = { require(vector.size == matrix(0).size && vector.size > 0) val tmat = matrix.transpose - var tmp: Array[Int] = null + var tmp: Array[BigInt] = null tmp = mult(vector(0), tmat(0)) var i = 1 while(i < vector.size) { @@ -89,8 +91,8 @@ class LinearEquationsSuite extends LeonTestSuite with WithLikelyEq { tmp } - def mult(c: Int, v: Array[Int]): Array[Int] = v.map(_ * c) - def add(v1: Array[Int], v2: Array[Int]): Array[Int] = { + def mult(c: BigInt, v: Array[BigInt]): Array[BigInt] = v.map(_ * c) + def add(v1: Array[BigInt], v2: Array[BigInt]): Array[BigInt] = { require(v1.size == v2.size) v1.zip(v2).map(p => p._1 + p._2) } @@ -104,60 +106,60 @@ class LinearEquationsSuite extends LeonTestSuite with WithLikelyEq { test("particularSolution basecase") { def toExpr(es: Array[Expr]): Expr = { val coef: Array[Expr] = es - val vars: Array[Expr] = Array[Expr](IntLiteral(1)) ++ Array[Expr](x, y) - es.zip(vars).foldLeft[Expr](IntLiteral(0))( (acc: Expr, p: (Expr, Expr)) => Plus(acc, Times(p._1, p._2)) ) + val vars: Array[Expr] = Array[Expr](i(1)) ++ Array[Expr](x, y) + es.zip(vars).foldLeft[Expr](i(0))( (acc: Expr, p: (Expr, Expr)) => Plus(acc, Times(p._1, p._2)) ) } val t1: Expr = Plus(a, b) - val c1: Expr = IntLiteral(4) - val d1: Expr = IntLiteral(22) + val c1: Expr = i(4) + val d1: Expr = i(22) val e1: Array[Expr] = Array(t1, c1, d1) val (pre1, (w1, w2)) = particularSolution(Set(aId, bId), t1, c1, d1) - checkSameExpr(toExpr(e1), IntLiteral(0), Set(aId, bId), pre1, Map(xId -> w1, yId -> w2)) + checkSameExpr(toExpr(e1), i(0), Set(aId, bId), pre1, Map(xId -> w1, yId -> w2)) - val t2: Expr = IntLiteral(-1) - val c2: Expr = IntLiteral(1) - val d2: Expr = IntLiteral(-1) + val t2: Expr = i(-1) + val c2: Expr = i(1) + val d2: Expr = i(-1) val e2: Array[Expr] = Array(t2, c2, d2) val (pre2, (w3, w4)) = particularSolution(Set(), t2, c2, d2) - checkSameExpr(toExpr(e2), IntLiteral(0), Set(), pre2, Map(xId -> w3, yId -> w4)) + checkSameExpr(toExpr(e2), i(0), Set(), pre2, Map(xId -> w3, yId -> w4)) } test("particularSolution preprocess") { def toExpr(es: Array[Expr], vs: Array[Expr]): Expr = { val coef: Array[Expr] = es - val vars: Array[Expr] = Array[Expr](IntLiteral(1)) ++ vs - es.zip(vars).foldLeft[Expr](IntLiteral(0))( (acc: Expr, p: (Expr, Expr)) => Plus(acc, Times(p._1, p._2)) ) + val vars: Array[Expr] = Array[Expr](i(1)) ++ vs + es.zip(vars).foldLeft[Expr](i(0))( (acc: Expr, p: (Expr, Expr)) => Plus(acc, Times(p._1, p._2)) ) } val t1: Expr = Plus(a, b) - val c1: Expr = IntLiteral(4) - val d1: Expr = IntLiteral(22) + val c1: Expr = i(4) + val d1: Expr = i(22) val e1: Array[Expr] = Array(t1, c1, d1) val (pre1, s1) = particularSolution(Set(aId, bId), e1.toList) - checkSameExpr(toExpr(e1, Array(x, y)), IntLiteral(0), Set(aId, bId), pre1, Array(xId, yId).zip(s1).toMap) + checkSameExpr(toExpr(e1, Array(x, y)), i(0), Set(aId, bId), pre1, Array(xId, yId).zip(s1).toMap) val t2: Expr = Plus(a, b) - val c2: Expr = IntLiteral(4) - val d2: Expr = IntLiteral(22) - val f2: Expr = IntLiteral(10) + val c2: Expr = i(4) + val d2: Expr = i(22) + val f2: Expr = i(10) val e2: Array[Expr] = Array(t2, c2, d2, f2) val (pre2, s2) = particularSolution(Set(aId, bId), e2.toList) - checkSameExpr(toExpr(e2, Array(x, y, z)), IntLiteral(0), Set(aId, bId), pre2, Array(xId, yId, zId).zip(s2).toMap) + checkSameExpr(toExpr(e2, Array(x, y, z)), i(0), Set(aId, bId), pre2, Array(xId, yId, zId).zip(s2).toMap) - val t3: Expr = Plus(a, Times(IntLiteral(2), b)) - val c3: Expr = IntLiteral(6) - val d3: Expr = IntLiteral(24) - val f3: Expr = IntLiteral(9) + val t3: Expr = Plus(a, Times(i(2), b)) + val c3: Expr = i(6) + val d3: Expr = i(24) + val f3: Expr = i(9) val e3: Array[Expr] = Array(t3, c3, d3, f3) val (pre3, s3) = particularSolution(Set(aId, bId), e3.toList) - checkSameExpr(toExpr(e3, Array(x, y, z)), IntLiteral(0), Set(aId, bId), pre3, Array(xId, yId, zId).zip(s3).toMap) + checkSameExpr(toExpr(e3, Array(x, y, z)), i(0), Set(aId, bId), pre3, Array(xId, yId, zId).zip(s3).toMap) val t4: Expr = Plus(a, b) - val c4: Expr = IntLiteral(4) + val c4: Expr = i(4) val e4: Array[Expr] = Array(t4, c4) val (pre4, s4) = particularSolution(Set(aId, bId), e4.toList) - checkSameExpr(toExpr(e4, Array(x)), IntLiteral(0), Set(aId, bId), pre4, Array(xId).zip(s4).toMap) + checkSameExpr(toExpr(e4, Array(x)), i(0), Set(aId, bId), pre4, Array(xId).zip(s4).toMap) } @@ -166,27 +168,27 @@ class LinearEquationsSuite extends LeonTestSuite with WithLikelyEq { val evaluator = new DefaultEvaluator(testContext, Program.empty) - val eq1 = Array(3, 4, 8) + val eq1 = Array[BigInt](3, 4, 8) val basis1 = linearSet(evaluator, as, eq1) checkVectorSpace(basis1, eq1) - val eq2 = Array(1, 2, 3) + val eq2 = Array[BigInt](1, 2, 3) val basis2 = linearSet(evaluator, as, eq2) checkVectorSpace(basis2, eq2) - val eq3 = Array(1, 1) + val eq3 = Array[BigInt](1, 1) val basis3 = linearSet(evaluator, as, eq3) checkVectorSpace(basis3, eq3) - val eq4 = Array(1, 1, 2, 7) + val eq4 = Array[BigInt](1, 1, 2, 7) val basis4 = linearSet(evaluator, as, eq4) checkVectorSpace(basis4, eq4) - val eq5 = Array(1, -1) + val eq5 = Array[BigInt](1, -1) val basis5 = linearSet(evaluator, as, eq5) checkVectorSpace(basis5, eq5) - val eq6 = Array(1, -6, 3) + val eq6 = Array[BigInt](1, -6, 3) val basis6 = linearSet(evaluator, as, eq6) checkVectorSpace(basis6, eq6) } @@ -224,35 +226,35 @@ class LinearEquationsSuite extends LeonTestSuite with WithLikelyEq { def check(t: Expr, c: List[Expr], prec: Expr, witnesses: List[Expr], freshVars: List[Identifier]) { enumerate(freshVars.size, (vals: Array[Int]) => { - val mapping: Map[Expr, Expr] = (freshVars.zip(vals.toList).map(t => (Variable(t._1), IntLiteral(t._2))).toMap) - val cWithVars: Expr = c.zip(witnesses).foldLeft[Expr](IntLiteral(0)){ case (acc, (coef, wit)) => Plus(acc, Times(coef, replace(mapping, wit))) } - checkSameExpr(Plus(t, cWithVars), IntLiteral(0), as, prec) + val mapping: Map[Expr, Expr] = (freshVars.zip(vals.toList).map(t => (Variable(t._1), i(t._2))).toMap) + val cWithVars: Expr = c.zip(witnesses).foldLeft[Expr](i(0)){ case (acc, (coef, wit)) => Plus(acc, Times(coef, replace(mapping, wit))) } + checkSameExpr(Plus(t, cWithVars), i(0), as, prec) }) } - val t1 = Minus(Times(IntLiteral(2), a), b) - val c1 = List(IntLiteral(3), IntLiteral(4), IntLiteral(8)) + val t1 = Minus(Times(i(2), a), b) + val c1 = List(i(3), i(4), i(8)) val (pre1, wit1, f1) = elimVariable(evaluator, as, t1::c1) check(t1, c1, pre1, wit1, f1) - val t2 = Plus(Plus(IntLiteral(0), IntLiteral(2)), Times(IntLiteral(-1), IntLiteral(3))) - val c2 = List(IntLiteral(1), IntLiteral(-1)) + val t2 = Plus(Plus(i(0), i(2)), Times(i(-1), i(3))) + val c2 = List(i(1), i(-1)) val (pre2, wit2, f2) = elimVariable(evaluator, Set(), t2::c2) check(t2, c2, pre2, wit2, f2) - val t3 = Minus(Times(IntLiteral(2), a), IntLiteral(3)) - val c3 = List(IntLiteral(2)) + val t3 = Minus(Times(i(2), a), i(3)) + val c3 = List(i(2)) val (pre3, wit3, f3) = elimVariable(evaluator, Set(aId), t3::c3) check(t3, c3, pre3, wit3, f3) - val t4 = Times(IntLiteral(2), a) - val c4 = List(IntLiteral(2), IntLiteral(4)) + val t4 = Times(i(2), a) + val c4 = List(i(2), i(4)) val (pre4, wit4, f4) = elimVariable(evaluator, Set(aId), t4::c4) check(t4, c4, pre4, wit4, f4) val t5 = Minus(a, b) - val c5 = List(IntLiteral(-60), IntLiteral(-3600)) + val c5 = List(i(-60), i(-3600)) val (pre5, wit5, f5) = elimVariable(evaluator, Set(aId, bId), t5::c5) check(t5, c5, pre5, wit5, f5) diff --git a/src/test/scala/leon/test/synthesis/SynthesisSuite.scala b/src/test/scala/leon/test/synthesis/SynthesisSuite.scala index 0296a1e5194b71bc8dbf232710a4808bccc0bc10..30fc1a4d7336d881859b2af6e5e0e0283d2d1bc2 100644 --- a/src/test/scala/leon/test/synthesis/SynthesisSuite.scala +++ b/src/test/scala/leon/test/synthesis/SynthesisSuite.scala @@ -199,12 +199,12 @@ object Injection { case class Nil() extends List // proved with unrolling=0 - def size(l: List) : Int = (l match { - case Nil() => 0 + def size(l: List) : BigInt = (l match { + case Nil() => BigInt(0) case Cons(t) => 1 + size(t) }) ensuring(res => res >= 0) - def simple() = choose{out: List => size(out) == 2 } + def simple() = choose{out: List => size(out) == BigInt(2) } } """ ) { @@ -270,16 +270,16 @@ import leon.lang.synthesis._ object SortedList { sealed abstract class List - case class Cons(head: Int, tail: List) extends List + case class Cons(head: BigInt, tail: List) extends List case class Nil() extends List - def size(l: List) : Int = (l match { - case Nil() => 0 + def size(l: List) : BigInt = (l match { + case Nil() => BigInt(0) case Cons(_, t) => 1 + size(t) }) ensuring(res => res >= 0) - def content(l: List): Set[Int] = l match { - case Nil() => Set.empty[Int] + def content(l: List): Set[BigInt] = l match { + case Nil() => Set.empty[BigInt] case Cons(i, t) => Set(i) ++ content(t) } @@ -294,12 +294,12 @@ object SortedList { content(out) == content(in1) ++ content(in2) } - def insert(in1: List, v: Int) = choose { + def insert(in1: List, v: BigInt) = choose { (out : List) => content(out) == content(in1) ++ Set(v) } - def insertSorted(in1: List, v: Int) = choose { + def insertSorted(in1: List, v: BigInt) = choose { (out : List) => isSorted(in1) && content(out) == content(in1) ++ Set(v) && isSorted(out) }