From 4ee5234ab7c9f39a97807845d70e43c55d09f143 Mon Sep 17 00:00:00 2001
From: Etienne Kneuss <ekneuss@gmail.com>
Date: Fri, 17 Apr 2015 19:56:47 +0200
Subject: [PATCH] Leon defines its own Maps

In order to have support for maps, you need to import leon.lang._
---
 .../leon/frontends/scalac/ASTExtractors.scala |  9 +++-
 .../frontends/scalac/CodeExtraction.scala     | 41 ++++++++-----------
 .../scala/leon/purescala/PrettyPrinter.scala  |  5 +--
 src/main/scala/leon/purescala/TypeOps.scala   |  5 +++
 .../frontends/passing/ImplicitDefs2.scala     |  1 -
 .../newsolvers/valid/LiteralMaps.scala        |  1 +
 .../newsolvers/valid/PositiveMap.scala        |  2 +
 .../purescala/valid/LiteralMaps.scala         |  2 +
 .../scala/leon/test/purescala/DataGen.scala   |  3 +-
 9 files changed, 39 insertions(+), 30 deletions(-)

diff --git a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
index 6fab7051b..f7a40b953 100644
--- a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
+++ b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
@@ -25,9 +25,10 @@ trait ASTExtractors {
   protected lazy val tuple3Sym          = classFromName("scala.Tuple3")
   protected lazy val tuple4Sym          = classFromName("scala.Tuple4")
   protected lazy val tuple5Sym          = classFromName("scala.Tuple5")
-  protected lazy val mapSym             = classFromName("scala.collection.immutable.Map")
+  protected lazy val scalaMapSym        = classFromName("scala.collection.immutable.Map")
   protected lazy val scalaSetSym        = classFromName("scala.collection.immutable.Set")
   protected lazy val setSym             = classFromName("leon.lang.Set")
+  protected lazy val mapSym             = classFromName("leon.lang.Map")
   protected lazy val optionClassSym     = classFromName("scala.Option")
   protected lazy val arraySym           = classFromName("scala.Array")
   protected lazy val someClassSym       = classFromName("scala.Some")
@@ -65,10 +66,14 @@ trait ASTExtractors {
     getResolvedTypeSym(sym) == scalaSetSym
   }
 
-  def isMapTraitSym(sym: Symbol) : Boolean = {
+  def isMapSym(sym: Symbol) : Boolean = {
     getResolvedTypeSym(sym) == mapSym
   }
 
+  def isScalaMapSym(sym: Symbol) : Boolean = {
+    getResolvedTypeSym(sym) == scalaMapSym
+  }
+
   def isMultisetTraitSym(sym: Symbol) : Boolean = {
     sym == multisetTraitSym
   }
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index 70a0eacf2..fd148e997 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -1413,8 +1413,20 @@ trait CodeExtraction extends ASTExtractors {
             case cct: CaseClassType =>
               CaseClass(cct, args.map(extractTree))
 
-            case SetType(underlying) =>
-              finiteSet(args.map(extractTree).toSet, underlying)
+            case SetType(a) =>
+              finiteSet(args.map(extractTree).toSet, a)
+
+            case MapType(a, b) =>
+              val singletons: Seq[(LeonExpr, LeonExpr)] = args.collect {
+                case ExTuple(tpes, trees) if trees.size == 2 =>
+                  (extractTree(trees(0)), extractTree(trees(1)))
+              }
+
+              if (singletons.size != args.size) {
+                outOfSubsetError(tr, "Some map elements could not be extracted as Tuple2")
+              }
+
+              finiteMap(singletons, a, b)
 
             case _ =>
               outOfSubsetError(tr, "Construction of a non-case class.")
@@ -1471,26 +1483,6 @@ trait CodeExtraction extends ASTExtractors {
           val underlying = extractType(tt)
           EmptyMultiset(underlying)
 
-        case ExEmptyMap(ft, tt) =>
-          val fromUnderlying = extractType(ft)
-          val toUnderlying   = extractType(tt)
-          EmptyMap(fromUnderlying, toUnderlying)
-
-        case ExLiteralMap(ft, tt, elems) =>
-          val fromUnderlying = extractType(ft)
-          val toUnderlying   = extractType(tt)
-
-          val singletons: Seq[(LeonExpr, LeonExpr)] = elems.collect {
-            case ExTuple(tpes, trees) if trees.size == 2 =>
-              (extractTree(trees(0)), extractTree(trees(1)))
-          }
-
-          if (singletons.size != elems.size) {
-            outOfSubsetError(tr, "Some map elements could not be extracted as Tuple2")
-          }
-
-          finiteMap(singletons, fromUnderlying, toUnderlying)
-
         case ExArrayFill(baseType, length, defaultValue) =>
           val lengthRec = extractTree(length)
           val defaultValueRec = extractTree(defaultValue)
@@ -1797,13 +1789,16 @@ trait CodeExtraction extends ASTExtractors {
       case TypeRef(_, sym, btt :: Nil) if isScalaSetSym(sym) =>
         outOfSubsetError(pos, "Scala's Set API is no longer extracted. Make sure you import leon.lang.Set that defines supported Set operations.")
 
+      case TypeRef(_, sym, List(a,b)) if isScalaMapSym(sym) =>
+        outOfSubsetError(pos, "Scala's Map API is no longer extracted. Make sure you import leon.lang.Map that defines supported Map operations.")
+
       case TypeRef(_, sym, btt :: Nil) if isSetSym(sym) =>
         SetType(extractType(btt))
 
       case TypeRef(_, sym, btt :: Nil) if isMultisetTraitSym(sym) =>
         MultisetType(extractType(btt))
 
-      case TypeRef(_, sym, List(ftt,ttt)) if isMapTraitSym(sym) =>
+      case TypeRef(_, sym, List(ftt,ttt)) if isMapSym(sym) =>
         MapType(extractType(ftt), extractType(ttt))
 
       case TypeRef(_, sym, List(t1,t2)) if isTuple2(sym) =>
diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index a4718d515..f5b82b8f4 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -372,7 +372,8 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
       case BVShiftLeft(l,r)          => optP { p"$l << $r" }
       case BVAShiftRight(l,r)        => optP { p"$l >> $r" }
       case BVLShiftRight(l,r)        => optP { p"$l >>> $r" }
-      case FiniteSet(rs)             => p"{${rs.toSeq}}"
+      case fs @ FiniteSet(rs)        => p"{${rs.toSeq}}"
+      case fm @ FiniteMap(rs)        => p"{$rs}"
       case FiniteMultiset(rs)        => p"{|$rs|)"
       case EmptyMultiset(_)          => p"\u2205"
       case Not(ElementOfSet(e,s))    => p"$e \u2209 $s"
@@ -435,8 +436,6 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
       case TypeParameterDef(tp)      => p"$tp"
       case TypeParameter(id)         => p"$id"
 
-      case FiniteMap(rs) =>
-        p"{$rs}"
 
       case IfExpr(c, t, ie : IfExpr) =>
         optP {
diff --git a/src/main/scala/leon/purescala/TypeOps.scala b/src/main/scala/leon/purescala/TypeOps.scala
index c22bf4796..1f05a5d64 100644
--- a/src/main/scala/leon/purescala/TypeOps.scala
+++ b/src/main/scala/leon/purescala/TypeOps.scala
@@ -313,6 +313,11 @@ object TypeOps {
             val SetType(tp) = s.getType
             EmptySet(tpeSub(tp)).copiedFrom(s)
 
+          case m @ FiniteMap(elements) if elements.isEmpty =>
+            val MapType(a,b) = m.getType
+            EmptyMap(tpeSub(a), tpeSub(b)).copiedFrom(m)
+
+
           case v @ Variable(id) if idsMap contains id =>
             Variable(idsMap(id)).copiedFrom(v)
 
diff --git a/src/test/resources/regression/frontends/passing/ImplicitDefs2.scala b/src/test/resources/regression/frontends/passing/ImplicitDefs2.scala
index 1ab625164..a157e5dd6 100644
--- a/src/test/resources/regression/frontends/passing/ImplicitDefs2.scala
+++ b/src/test/resources/regression/frontends/passing/ImplicitDefs2.scala
@@ -7,7 +7,6 @@ import leon.collection.{Option,None,Some}
 //import leon.proof._
 
 // FIXME: the following should go into the leon.proof package object.
-import leon.annotation._
 import scala.language.implicitConversions
 object proof {
   
diff --git a/src/test/resources/regression/verification/newsolvers/valid/LiteralMaps.scala b/src/test/resources/regression/verification/newsolvers/valid/LiteralMaps.scala
index d6c07c261..0acd6c81e 100644
--- a/src/test/resources/regression/verification/newsolvers/valid/LiteralMaps.scala
+++ b/src/test/resources/regression/verification/newsolvers/valid/LiteralMaps.scala
@@ -1,4 +1,5 @@
 /* Copyright 2009-2014 EPFL, Lausanne */
+import leon.lang._
 
 object LiteralMaps {
   def test(): Map[Int, Int] = {
diff --git a/src/test/resources/regression/verification/newsolvers/valid/PositiveMap.scala b/src/test/resources/regression/verification/newsolvers/valid/PositiveMap.scala
index 0441ec26c..93c87331e 100644
--- a/src/test/resources/regression/verification/newsolvers/valid/PositiveMap.scala
+++ b/src/test/resources/regression/verification/newsolvers/valid/PositiveMap.scala
@@ -1,3 +1,5 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
 import leon.lang._
 
 object PositiveMap {
diff --git a/src/test/resources/regression/verification/purescala/valid/LiteralMaps.scala b/src/test/resources/regression/verification/purescala/valid/LiteralMaps.scala
index 4ce05fd25..07894524a 100644
--- a/src/test/resources/regression/verification/purescala/valid/LiteralMaps.scala
+++ b/src/test/resources/regression/verification/purescala/valid/LiteralMaps.scala
@@ -1,5 +1,7 @@
 /* Copyright 2009-2015 EPFL, Lausanne */
 
+import leon.lang._
+
 object LiteralMaps {
   def test(): Map[Int, Int] = {
     Map(1 -> 2, 3 -> 4, (5, 6))
diff --git a/src/test/scala/leon/test/purescala/DataGen.scala b/src/test/scala/leon/test/purescala/DataGen.scala
index 3d47e364f..8fcc97be2 100644
--- a/src/test/scala/leon/test/purescala/DataGen.scala
+++ b/src/test/scala/leon/test/purescala/DataGen.scala
@@ -30,7 +30,8 @@ class DataGen extends LeonTestSuite {
   }
 
   test("Lists") {
-    val p = """|object Program {
+    val p = """|import leon.lang._
+               |object Program {
                |  sealed abstract class List
                |  case class Cons(head : Int, tail : List) extends List
                |  case object Nil extends List
-- 
GitLab