From 858dc1b6a24438a2033bc292992fca36ac62d929 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mika=C3=ABl=20Mayer?= <mikael.mayer@epfl.ch>
Date: Thu, 14 Apr 2016 16:48:46 +0200
Subject: [PATCH] Added string conversion utilities when converting from String
 to String$0

---
 library/theories/String.scala                 | 42 +++++++++++++++++++
 .../leon/solvers/theories/StringEncoder.scala | 22 ++++++++++
 2 files changed, 64 insertions(+)

diff --git a/library/theories/String.scala b/library/theories/String.scala
index 85e4d90c7..8cfced9d8 100644
--- a/library/theories/String.scala
+++ b/library/theories/String.scala
@@ -30,3 +30,45 @@ sealed abstract class String {
 
 case class StringCons(head: Char, tail: String) extends String
 case class StringNil() extends String
+
+@library
+object String {
+  def fromChar(i: Char): String = {
+    StringCons(i, StringNil())
+  }
+  
+  def fromBigInt(i: BigInt): String =
+    if(i < 0) StringCons('-', fromBigInt(-i))
+    else if(i == BigInt(0)) StringCons('0', StringNil())
+    else if(i == BigInt(1)) StringCons('1', StringNil())
+    else if(i == BigInt(2)) StringCons('2', StringNil())
+    else if(i == BigInt(3)) StringCons('3', StringNil())
+    else if(i == BigInt(4)) StringCons('4', StringNil())
+    else if(i == BigInt(5)) StringCons('5', StringNil())
+    else if(i == BigInt(6)) StringCons('6', StringNil())
+    else if(i == BigInt(7)) StringCons('7', StringNil())
+    else if(i == BigInt(8)) StringCons('8', StringNil())
+    else if(i == BigInt(9)) StringCons('9', StringNil())   
+    else fromBigInt(i / 10).concat(fromBigInt(i % 10))
+
+  def fromInt(i: Int): String = i match {
+    case -2147483648 => StringCons('-', StringCons('2', fromInt(147483648)))
+    case i  if i < 0 => StringCons('-', fromInt(-i))
+    case 0 => StringCons('0', StringNil())
+    case 1 => StringCons('1', StringNil())
+    case 2 => StringCons('2', StringNil())
+    case 3 => StringCons('3', StringNil())
+    case 4 => StringCons('4', StringNil())
+    case 5 => StringCons('5', StringNil())
+    case 6 => StringCons('6', StringNil())
+    case 7 => StringCons('7', StringNil())
+    case 8 => StringCons('8', StringNil())
+    case 9 => StringCons('9', StringNil())
+    case i => fromInt(i / 10).concat(fromInt(i % 10))
+  }
+  
+  def fromBoolean(b: Boolean): String = {
+    if(b) StringCons('t', StringCons('r', StringCons('u', StringCons('e', StringNil()))))
+    else StringCons('f', StringCons('a', StringCons('l', StringCons('s', StringCons('e', StringNil())))))
+  }
+}
diff --git a/src/main/scala/leon/solvers/theories/StringEncoder.scala b/src/main/scala/leon/solvers/theories/StringEncoder.scala
index 051981440..02293fab3 100644
--- a/src/main/scala/leon/solvers/theories/StringEncoder.scala
+++ b/src/main/scala/leon/solvers/theories/StringEncoder.scala
@@ -22,6 +22,12 @@ class StringEncoder(ctx: LeonContext, p: Program) extends TheoryEncoder {
   val Drop   = p.library.lookupUnique[FunDef]("leon.theories.String.drop").typed
   val Slice  = p.library.lookupUnique[FunDef]("leon.theories.String.slice").typed
   val Concat = p.library.lookupUnique[FunDef]("leon.theories.String.concat").typed
+  
+  val FromInt      = p.library.lookupUnique[FunDef]("leon.theories.String.fromInt").typed
+  val FromChar     = p.library.lookupUnique[FunDef]("leon.theories.String.fromChar").typed
+  val FromBoolean  = p.library.lookupUnique[FunDef]("leon.theories.String.fromBoolean").typed
+  val FromBigInt   = p.library.lookupUnique[FunDef]("leon.theories.String.fromBigInt").typed
+  
 
   private val stringBijection = new Bijection[String, Expr]()
   
@@ -48,6 +54,14 @@ class StringEncoder(ctx: LeonContext, p: Program) extends TheoryEncoder {
         Some(FunctionInvocation(Take, Seq(FunctionInvocation(Drop, Seq(transform(a), transform(start))), transform(length))).copiedFrom(e))
       case SubString(a, start, end)  => 
         Some(FunctionInvocation(Slice, Seq(transform(a), transform(start), transform(end))).copiedFrom(e))
+      case Int32ToString(a) => 
+        Some(FunctionInvocation(FromInt, Seq(transform(a))).copiedFrom(e))
+      case IntegerToString(a) =>
+        Some(FunctionInvocation(FromBigInt, Seq(transform(a))).copiedFrom(e))
+      case CharToString(a) =>
+        Some(FunctionInvocation(FromChar, Seq(transform(a))).copiedFrom(e))
+      case BooleanToString(a) =>
+        Some(FunctionInvocation(FromBoolean, Seq(transform(a))).copiedFrom(e))
       case _ => None
     }
 
@@ -85,6 +99,14 @@ class StringEncoder(ctx: LeonContext, p: Program) extends TheoryEncoder {
       case FunctionInvocation(Drop, Seq(a, count)) =>
         val ra = transform(a)
         Some(SubString(ra, transform(count), StringLength(ra)).copiedFrom(e))
+      case FunctionInvocation(FromInt, Seq(a)) =>
+        Some(Int32ToString(transform(a)).copiedFrom(e))
+      case FunctionInvocation(FromBigInt, Seq(a)) =>
+        Some(IntegerToString(transform(a)).copiedFrom(e))
+      case FunctionInvocation(FromChar, Seq(a)) =>
+        Some(CharToString(transform(a)).copiedFrom(e))
+      case FunctionInvocation(FromBoolean, Seq(a)) =>
+        Some(BooleanToString(transform(a)).copiedFrom(e))
       case _ => None
     }
 
-- 
GitLab