From b29c5b71bd6426f6732110330fc264f3d02f45e0 Mon Sep 17 00:00:00 2001
From: Nicolas Voirol <voirol.nicolas@gmail.com>
Date: Thu, 11 Aug 2016 23:40:00 +0200
Subject: [PATCH] All unit tests pass

---
 src/main/scala/inox/ast/Expressions.scala     | 25 +++++++++++++------
 src/main/scala/inox/ast/Extractors.scala      |  2 +-
 src/main/scala/inox/ast/GenTreeOps.scala      |  7 ++++--
 .../inox/evaluators/RecursiveEvaluator.scala  | 17 +++++--------
 src/test/scala/inox/ast/ExprOpsSuite.scala    |  1 -
 .../inox/evaluators/EvaluatorSuite.scala      |  4 ++-
 6 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/src/main/scala/inox/ast/Expressions.scala b/src/main/scala/inox/ast/Expressions.scala
index 24da96276..e97cf4082 100644
--- a/src/main/scala/inox/ast/Expressions.scala
+++ b/src/main/scala/inox/ast/Expressions.scala
@@ -152,22 +152,33 @@ trait Expressions { self: Trees =>
   case class BVLiteral(value: BitSet, size: Int) extends Literal[BitSet] {
     def getType(implicit s: Symbols): Type = BVType(size)
     def toBigInt: BigInt = {
-      val res = value.foldLeft(BigInt(0))((res, i) => res + BigInt(2).pow(i))
-      if (value(size)) BigInt(2).pow(size) - res else res
+      val res = value.foldLeft(BigInt(0))((res, i) => res + BigInt(2).pow(i-1))
+      if (value(size)) res - BigInt(2).pow(size) else res
     }
   }
 
   object BVLiteral {
-    def apply(bi: BigInt, size: Int): BVLiteral = BVLiteral(
-      (1 to size).foldLeft(BitSet.empty) { case (res, i) =>
-        if ((bi & BigInt(2).pow(i)) > 0) res + i else res
-      }, size)
+    def apply(bi: BigInt, size: Int): BVLiteral = {
+      def extract(bi: BigInt): BitSet = (1 to size).foldLeft(BitSet.empty) {
+        case (res, i) => if ((bi & BigInt(2).pow(i-1)) > 0) res + i else res
+      }
+
+      val bitSet = if (bi >= 0) extract(bi) else {
+        val bs = extract(-bi)
+        (1 to size).foldLeft((BitSet.empty, false)) { case ((res, seen1), i) =>
+          if (bs(i) && !seen1) (res + i, true)
+          else (if (!seen1 || bs(i)) res else res + i, seen1)
+        }._1
+      }
+
+      BVLiteral(bitSet, size)
+    }
   }
 
   object IntLiteral {
     def apply(i: Int): BVLiteral = BVLiteral(BigInt(i), 32)
     def unapply(e: Expr): Option[Int] = e match {
-      case b @ BVLiteral(_, 32) => Some(b.toBigInt.toInt)
+      case b @ BVLiteral(bs, 32) => Some(b.toBigInt.toInt)
       case _ => None
     }
   }
diff --git a/src/main/scala/inox/ast/Extractors.scala b/src/main/scala/inox/ast/Extractors.scala
index 9a235fa84..ffc708f58 100644
--- a/src/main/scala/inox/ast/Extractors.scala
+++ b/src/main/scala/inox/ast/Extractors.scala
@@ -132,7 +132,7 @@ trait TreeDeconstructor {
       }
       (subArgs, Seq(base), builder)
     case s.FiniteMap(elems, default, kT) =>
-      val subArgs = elems.flatMap { case (k, v) => Seq(k, v) }
+      val subArgs = elems.flatMap { case (k, v) => Seq(k, v) } :+ default
       val builder = (as: Seq[t.Expr], kT: Seq[t.Type]) => {
         def rec(kvs: Seq[t.Expr]): (Seq[(t.Expr, t.Expr)], t.Expr) = kvs match {
           case Seq(k, v, t @ _*) =>
diff --git a/src/main/scala/inox/ast/GenTreeOps.scala b/src/main/scala/inox/ast/GenTreeOps.scala
index 1b8af7c4a..6584e5a43 100644
--- a/src/main/scala/inox/ast/GenTreeOps.scala
+++ b/src/main/scala/inox/ast/GenTreeOps.scala
@@ -388,8 +388,11 @@ trait GenTreeOps { self =>
   }
 
   object Same {
-    def unapply(tt: (Source, Source)): Option[(Source, Source)] = {
-      if (tt._1.getClass == tt._2.getClass) {
+    def unapply(tt: (Source, Target))(implicit ev1: Source =:= Target, ev2: Target =:= Source): Option[(Source, Target)] = {
+      val Deconstructor(es1, recons1) = tt._1
+      val Deconstructor(es2, recons2) = ev2(tt._2)
+
+      if (es1.size == es2.size && scala.util.Try(recons2(es1.map(ev1))).toOption == Some(tt._1)) {
         Some(tt)
       } else {
         None
diff --git a/src/main/scala/inox/evaluators/RecursiveEvaluator.scala b/src/main/scala/inox/evaluators/RecursiveEvaluator.scala
index 715a8d8dd..d310e98b8 100644
--- a/src/main/scala/inox/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/inox/evaluators/RecursiveEvaluator.scala
@@ -225,12 +225,7 @@ trait RecursiveEvaluator
 
     case UMinus(ex) =>
       e(ex) match {
-        case BVLiteral(b, s) =>
-          BVLiteral((1 to s).foldLeft((BitSet.empty, false)) { case ((res, seen1), i) =>
-            if (b(i) && seen1) (res + i, true)
-            else if (!seen1) (res, seen1)
-            else (if (!b(i)) res + i else res, seen1)
-          }._1, s)
+        case b @ BVLiteral(_, s) => BVLiteral(-b.toBigInt, s)
         case IntegerLiteral(i) => IntegerLiteral(-i)
         case FractionLiteral(n, d) => FractionLiteral(-n, d)
         case re => throw EvalError("Unexpected operation: -(" + re.asString + ")")
@@ -239,9 +234,9 @@ trait RecursiveEvaluator
     case Times(l,r) =>
       (e(l), e(r)) match {
         case (BVLiteral(i1, s1), BVLiteral(i2, s2)) if s1 == s2 =>
-          BVLiteral(i1.foldLeft(BitSet.empty) { case (res, i) =>
-            res ++ shift(i2, s2, i)
-          }, s1)
+          i1.foldLeft(BVLiteral(0, s1): Expr) { case (res, i) =>
+            e(Plus(res, BVLiteral(shift(i2, s2, i-1), s1)))
+          }
         case (IntegerLiteral(i1), IntegerLiteral(i2)) => IntegerLiteral(i1 * i2)
         case (FractionLiteral(ln, ld), FractionLiteral(rn, rd)) =>
           normalizeFraction(FractionLiteral((ln * rn), (ld * rd)))
@@ -509,8 +504,8 @@ trait RecursiveEvaluator
       FiniteMap(ss.map{ case (k, v) => (e(k), e(v)) }.toMap.toSeq, e(dflt), vT)
 
     case g @ MapApply(m,k) => (e(m), e(k)) match {
-      case (FiniteMap(ss, _, _), e) =>
-        ss.toMap.getOrElse(e, throw RuntimeError("Key not found: " + e.asString))
+      case (FiniteMap(ss, dflt, _), e) =>
+        ss.toMap.getOrElse(e, dflt)
       case (l,r) =>
         throw EvalError(typeErrorMsg(l, MapType(r.getType, g.getType)))
     }
diff --git a/src/test/scala/inox/ast/ExprOpsSuite.scala b/src/test/scala/inox/ast/ExprOpsSuite.scala
index 1a8c5e615..b12cad363 100644
--- a/src/test/scala/inox/ast/ExprOpsSuite.scala
+++ b/src/test/scala/inox/ast/ExprOpsSuite.scala
@@ -278,7 +278,6 @@ class ExprOpsSuite extends FunSuite {
       val v = simplestValue(t)
       assert(isSubtypeOf(v.getType, t), "SimplestValue of "+t+": "+v+":"+v.getType)
     }
-
   }
 
   test("preMapWithContext") {
diff --git a/src/test/scala/inox/evaluators/EvaluatorSuite.scala b/src/test/scala/inox/evaluators/EvaluatorSuite.scala
index c0b247934..c5db3fd3e 100644
--- a/src/test/scala/inox/evaluators/EvaluatorSuite.scala
+++ b/src/test/scala/inox/evaluators/EvaluatorSuite.scala
@@ -36,6 +36,8 @@ class EvaluatorSuite extends FunSuite {
 
     eval(e, Plus(IntLiteral(3), IntLiteral(5)))  === IntLiteral(8)
     eval(e, Plus(IntLiteral(0), IntLiteral(5)))  === IntLiteral(5)
+    eval(e, Plus(IntLiteral(1), IntLiteral(-2)))  === IntLiteral(-1)
+    eval(e, Plus(IntLiteral(Int.MaxValue), IntLiteral(1))) === IntLiteral(Int.MinValue)
     eval(e, Times(IntLiteral(3), IntLiteral(3))) === IntLiteral(9)
   }
 
@@ -229,7 +231,7 @@ class EvaluatorSuite extends FunSuite {
     eval(e, MapApply(
       FiniteMap(Seq(IntLiteral(1) -> IntLiteral(2), IntLiteral(2) -> IntLiteral(4)), IntLiteral(6), Int32Type),
       IntLiteral(1))
-    ) === IntLiteral(4)
+    ) === IntLiteral(2)
 
     eval(e, MapApply(
       FiniteMap(Seq(IntLiteral(1) -> IntLiteral(2), IntLiteral(2) -> IntLiteral(4)), IntLiteral(6), Int32Type),
-- 
GitLab