From 7b4600e566e12f4ef59a6ed91feb6192ab4a3a82 Mon Sep 17 00:00:00 2001
From: Etienne Kneuss <ekneuss@gmail.com>
Date: Fri, 6 Nov 2015 17:58:46 +0100
Subject: [PATCH] Set cardinality is a bigint, and we map it to CVC4's card

---
 library/lang/Set.scala                                   | 1 +
 src/main/java/leon/codegen/runtime/Set.java              | 6 +++---
 src/main/scala/leon/codegen/CodeGeneration.scala         | 2 +-
 src/main/scala/leon/evaluators/RecursiveEvaluator.scala  | 2 +-
 .../scala/leon/frontends/scalac/CodeExtraction.scala     | 9 ++++++++-
 src/main/scala/leon/purescala/Expressions.scala          | 2 +-
 .../scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala     | 3 +++
 7 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/library/lang/Set.scala b/library/lang/Set.scala
index 36c70a837..8f4595d33 100644
--- a/library/lang/Set.scala
+++ b/library/lang/Set.scala
@@ -17,6 +17,7 @@ case class Set[T](val theSet: scala.collection.immutable.Set[T]) {
    def ++(a: Set[T]): Set[T] = new Set[T](theSet ++ a.theSet)
    def -(a: T): Set[T] = new Set[T](theSet - a)
    def --(a: Set[T]): Set[T] = new Set[T](theSet -- a.theSet)
+   def size: BigInt = theSet.size
    def contains(a: T): Boolean = theSet.contains(a)
    def isEmpty: Boolean = theSet.isEmpty
    def subsetOf(b: Set[T]): Boolean = theSet.subsetOf(b.theSet)
diff --git a/src/main/java/leon/codegen/runtime/Set.java b/src/main/java/leon/codegen/runtime/Set.java
index 965aa20df..522dbe658 100644
--- a/src/main/java/leon/codegen/runtime/Set.java
+++ b/src/main/java/leon/codegen/runtime/Set.java
@@ -49,8 +49,8 @@ public final class Set {
     return true;
   }
 
-  public int size() {
-    return _underlying.size();
+  public BigInt size() {
+    return new BigInt(""+_underlying.size());
   }
 
   public Set union(Set s) {
@@ -84,7 +84,7 @@ public final class Set {
 
     Set other = (Set)that;
 
-    return this.size() == other.size() && this.subsetOf(other);
+    return this.size().equals(other.size()) && this.subsetOf(other);
   }
 
   @Override
diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala
index 6543da029..85ed5eb0b 100644
--- a/src/main/scala/leon/codegen/CodeGeneration.scala
+++ b/src/main/scala/leon/codegen/CodeGeneration.scala
@@ -654,7 +654,7 @@ trait CodeGeneration {
 
       case SetCardinality(s) =>
         mkExpr(s, ch)
-        ch << InvokeVirtual(SetClass, "size", "()I")
+        ch << InvokeVirtual(SetClass, "size", s"()$BigIntClass;")
 
       case SubsetOf(s1, s2) =>
         mkExpr(s1, ch)
diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
index 216f51c5d..fccda2aea 100644
--- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
@@ -504,7 +504,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
     case SetCardinality(s) =>
       val sr = e(s)
       sr match {
-        case FiniteSet(els, _) => IntLiteral(els.size)
+        case FiniteSet(els, _) => InfiniteIntegerLiteral(els.size)
         case _ => throw EvalError(typeErrorMsg(sr, SetType(Untyped)))
       }
 
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index 0a75dfebc..77a6c719f 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -1623,6 +1623,9 @@ trait CodeExtraction extends ASTExtractors {
               or(a1, a2)
 
             // Set methods
+            case (IsTyped(a1, SetType(b1)), "size", Nil) =>
+              SetCardinality(a1)
+
             //case (IsTyped(a1, SetType(b1)), "min", Nil) =>
             //  SetMin(a1)
 
@@ -1842,7 +1845,11 @@ trait CodeExtraction extends ASTExtractors {
       case AnnotatedType(_, tpe) => extractType(tpe)
 
       case _ =>
-        outOfSubsetError(tpt.typeSymbol.pos, "Could not extract type as PureScala: "+tpt+" ("+tpt.getClass+")")
+        if (tpt ne null) {
+          outOfSubsetError(tpt.typeSymbol.pos, "Could not extract type as PureScala: "+tpt+" ("+tpt.getClass+")")
+        } else {
+          outOfSubsetError(NoPosition, "Tree with null-pointer as type found")
+        }
     }
 
     private def getClassType(sym: Symbol, tps: List[LeonType])(implicit dctx: DefContext) = {
diff --git a/src/main/scala/leon/purescala/Expressions.scala b/src/main/scala/leon/purescala/Expressions.scala
index b834eb9f1..6e9adae5f 100644
--- a/src/main/scala/leon/purescala/Expressions.scala
+++ b/src/main/scala/leon/purescala/Expressions.scala
@@ -765,7 +765,7 @@ object Expressions {
   }
   /** $encodingof `set.length` */
   case class SetCardinality(set: Expr) extends Expr {
-    val getType = Int32Type
+    val getType = IntegerType
   }
   /** $encodingof `set.subsetOf(set2)` */
   case class SubsetOf(set1: Expr, set2: Expr) extends Expr {
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
index cb1c3246d..3173dd652 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
@@ -138,6 +138,9 @@ trait SMTLIBCVC4Target extends SMTLIBTarget {
     case ElementOfSet(e, s) =>
       FunctionApplication(SSymbol("member"), Seq(toSMT(e), toSMT(s)))
 
+    case SetCardinality(s) =>
+      FunctionApplication(SSymbol("card"), Seq(toSMT(s)))
+
     case SetDifference(a, b) =>
       FunctionApplication(SSymbol("setminus"), Seq(toSMT(a), toSMT(b)))
 
-- 
GitLab