From 8b5a1abd803acbc954703f67a45a6663ec631904 Mon Sep 17 00:00:00 2001
From: Manos Koukoutos <emmanouil.koukoutos@epfl.ch>
Date: Mon, 20 Oct 2014 16:58:55 +0100
Subject: [PATCH] Literal patterns

---
 .../leon/frontends/scalac/CodeExtraction.scala      |  5 +++++
 src/main/scala/leon/purescala/FunctionClosure.scala |  1 +
 src/main/scala/leon/purescala/PrettyPrinter.scala   |  4 ++++
 src/main/scala/leon/purescala/ScopeSimplifier.scala |  2 ++
 src/main/scala/leon/purescala/TreeOps.scala         | 13 +++++++++++++
 src/main/scala/leon/purescala/Trees.scala           |  9 +++++++--
 .../synthesis/heuristics/ADTLongInduction.scala     |  2 +-
 7 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index b79616a39..fee0e7e4b 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -913,6 +913,11 @@ trait CodeExtraction extends ASTExtractors {
             outOfSubsetError(a, "Invalid type "+a.tpe+" for .isInstanceOf")
         }
 
+      case ExInt32Literal(i)   => (LiteralPattern(binder, IntLiteral(i)),     dctx)
+      case ExBooleanLiteral(b) => (LiteralPattern(binder, BooleanLiteral(b)), dctx)
+      case ExUnitLiteral()     => (LiteralPattern(binder, UnitLiteral()),     dctx)
+      case ExStringLiteral(s)  => (LiteralPattern(binder, StringLiteral(s)),  dctx)
+
       case _ =>
         outOfSubsetError(p, "Unsupported pattern: "+p.getClass)
     }
diff --git a/src/main/scala/leon/purescala/FunctionClosure.scala b/src/main/scala/leon/purescala/FunctionClosure.scala
index c80deca87..20058923c 100644
--- a/src/main/scala/leon/purescala/FunctionClosure.scala
+++ b/src/main/scala/leon/purescala/FunctionClosure.scala
@@ -177,6 +177,7 @@ object FunctionClosure extends TransformationPhase {
     case WildcardPattern(binder) => WildcardPattern(binder.map(id2freshId(_)))
     case CaseClassPattern(binder, caseClassDef, subPatterns) => CaseClassPattern(binder.map(id2freshId(_)), caseClassDef, subPatterns.map(freshIdInPat(_, id2freshId)))
     case TuplePattern(binder, subPatterns) => TuplePattern(binder.map(id2freshId(_)), subPatterns.map(freshIdInPat(_, id2freshId)))
+    case LiteralPattern(binder, lit) => LiteralPattern(binder.map(id2freshId(_)), lit)
   }
 
   //filter the list of constraints, only keeping those relevant to the set of variables
diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index f48d424aa..bc9e2fd88 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -414,6 +414,10 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
         ob.foreach { b => p"$b @ " }
         p"($subps)"
 
+      case LiteralPattern(ob, lit) =>
+        ob foreach { b => p"$b @ " }
+        p"$lit"
+
       // Types
       case Untyped               => p"<untyped>"
       case UnitType              => p"Unit"
diff --git a/src/main/scala/leon/purescala/ScopeSimplifier.scala b/src/main/scala/leon/purescala/ScopeSimplifier.scala
index 91c6afd02..238d6c720 100644
--- a/src/main/scala/leon/purescala/ScopeSimplifier.scala
+++ b/src/main/scala/leon/purescala/ScopeSimplifier.scala
@@ -103,6 +103,8 @@ class ScopeSimplifier extends Transformer {
             CaseClassPattern(newBinder, ccd, newSubPatterns)
           case TuplePattern(b, sub) =>
             TuplePattern(newBinder, newSubPatterns)
+          case LiteralPattern(_, lit) => 
+            LiteralPattern(newBinder, lit)
         }
 
 
diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala
index 8e8b831ec..4bd86173f 100644
--- a/src/main/scala/leon/purescala/TreeOps.scala
+++ b/src/main/scala/leon/purescala/TreeOps.scala
@@ -403,6 +403,7 @@ object TreeOps {
       case WildcardPattern(Some(b)) => WildcardPattern(Some(sm(b)))
       case TuplePattern(ob, sps) => TuplePattern(ob.map(sm(_)), sps.map(rewritePattern(_, sm)))
       case CaseClassPattern(ob, ccd, sps) => CaseClassPattern(ob.map(sm(_)), ccd, sps.map(rewritePattern(_, sm)))
+      case LiteralPattern(Some(bind), lit) => LiteralPattern(Some(sm(bind)), lit)
       case other => other
     }
 
@@ -694,6 +695,7 @@ object TreeOps {
           val subTests = subps.zipWithIndex.map{case (p, i) => rec(TupleSelect(in, i+1).setType(tpes(i)), p)}
           And(bind(ob, in) +: subTests)
         }
+        case LiteralPattern(ob,lit) => And(Equals(in,lit), bind(ob,in))
       }
     }
 
@@ -727,6 +729,8 @@ object TreeOps {
           case None => map
         }
       }
+      case LiteralPattern(None, lit) => Map()
+      case LiteralPattern(Some(id), lit) => Map(id -> in)
     }
 
     def rewritePM(e: Expr) : Option[Expr] = e match {
@@ -1081,6 +1085,7 @@ object TreeOps {
               WildcardPattern(simplerBinder(ob))
             case TuplePattern(ob, patterns) =>
               TuplePattern(simplerBinder(ob), patterns map simplifyPattern)
+            case LiteralPattern(ob,lit) => LiteralPattern(simplerBinder(ob), lit)
             case _ =>
               p
           }
@@ -1119,6 +1124,14 @@ object TreeOps {
               } else {
                 TuplePattern(ob, subs)
               }
+            case LiteralPattern(ob, lit) => // TODO: is this correct?
+              if (ob == Some(anchor)) {
+                sys.error("WOOOT: "+to+" <<= "+pat +" on "+anchor)
+                pat
+              } else {
+                LiteralPattern(ob,lit) 
+              }
+                
           }
 
           val newCases = resCases.flatMap { c => c match {
diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala
index c5a648ccc..cc3bd4280 100644
--- a/src/main/scala/leon/purescala/Trees.scala
+++ b/src/main/scala/leon/purescala/Trees.scala
@@ -169,8 +169,9 @@ object Trees {
           case CaseClassPattern(_, cct, _) if cct.classDef != c.classDef => false
           case _ => true
         }))
-        case t: TupleType => new MatchExpr(scrutinee, cases)
-        case _ => scala.sys.error("Constructing match expression on non-class type.")
+        case _: TupleType | Int32Type | BooleanType | UnitType => new MatchExpr(scrutinee, cases)
+        
+        case _ => scala.sys.error("Constructing match expression on non-supported type.")
       }
     }
 
@@ -229,6 +230,10 @@ object Trees {
 
   case class TuplePattern(binder: Option[Identifier], subPatterns: Seq[Pattern]) extends Pattern
 
+  case class LiteralPattern[T](binder: Option[Identifier], lit : Literal[T]) extends Pattern {
+    val subPatterns = Seq()    
+  }
+
 
   /* Propositional logic */
   object And {
diff --git a/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala b/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala
index ca9d99d88..165b3ab66 100644
--- a/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala
+++ b/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala
@@ -57,7 +57,7 @@ case object ADTLongInduction extends Rule("ADT Long Induction") with Heuristic {
 
           case CaseClassPattern(binder, sccd, sub) =>
             CaseClassPattern(binder, sccd, sub.map(unrollPattern(id, cct, withIds) _))
-
+            
           case _ => on
         }
 
-- 
GitLab