diff --git a/library/lang/package.scala b/library/lang/package.scala
index 44351d02ca9328bbbf86063745d233f2db17cd7c..18e1cb6a17861554e221fc781d79a46e5b95f8c2 100644
--- a/library/lang/package.scala
+++ b/library/lang/package.scala
@@ -67,5 +67,35 @@ package object lang {
       }
     }
   }
-
+  
+  @ignore
+  object StrOps {
+    def concat(a: String, b: String): String = {
+      a + b
+    }
+    def length(a: String): BigInt = {
+      BigInt(a.length)
+    }
+    def substring(a: String, start: BigInt, end: BigInt): String = {
+      if(start > end || start >= length(a) || end <= 0) "" else a.substring(start.toInt, end.toInt)
+    }
+    def bigIntToString(a: BigInt): String = {
+      a.toString
+    }
+    def intToString(a: Int): String = {
+      a.toString
+    }
+    def doubleToString(a: Double): String = {
+      a.toString
+    }
+    def booleanToString(a: Boolean): String = {
+      if(a) "true" else "false"
+    }
+    def charToString(a: Char): String = {
+      a.toString
+    }
+    def realToString(a: Real): String = ???
+  }
+    
+  
 }
diff --git a/src/main/java/leon/codegen/runtime/StrOps.java b/src/main/java/leon/codegen/runtime/StrOps.java
new file mode 100644
index 0000000000000000000000000000000000000000..1e5d7f60d5086dd1a45b4e3e0a52fda11db842a1
--- /dev/null
+++ b/src/main/java/leon/codegen/runtime/StrOps.java
@@ -0,0 +1,37 @@
+package leon.codegen.runtime;
+
+public class StrOps {
+	public static String concat(String a, String b) {
+      return a + b;
+    }
+	public static BigInt length(String a) {
+      return new BigInt(String.valueOf(a.length()));
+    }
+	public static String substring (String a, BigInt start, BigInt end) {
+      if(start.greaterEquals(end) || start.greaterEquals(length(a)) || end.lessEquals(new BigInt("0")))
+    	  return "";
+      else
+    	  return a.substring(start.underlying().intValue(), end.underlying().intValue());
+    }
+	public static String bigIntToString (BigInt a) {
+      return a.toString();
+    }
+	public static String intToString (int a) {
+	  return String.valueOf(a);
+    }
+	public static String doubleToString (double a) {
+      return String.valueOf(a);
+    }
+	public static String booleanToString (boolean a) {
+      if(a)
+    	  return "true";
+      else
+    	  return "false";
+    }
+	public static String charToString (char a) {
+      return String.valueOf(a);
+    }
+	public static String realToString (Real a) {
+	  return ""; // TODO: Not supported at this moment.
+	}
+}
diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala
index 33975a011737d50a45d1511b108d4a2025208eb7..995be0cf939ff2ce5212215513c17a44d1ffcfba 100644
--- a/src/main/scala/leon/codegen/CodeGeneration.scala
+++ b/src/main/scala/leon/codegen/CodeGeneration.scala
@@ -61,6 +61,7 @@ trait CodeGeneration {
 
   private[codegen] val JavaListClass             = "java/util/List"
   private[codegen] val JavaIteratorClass         = "java/util/Iterator"
+  private[codegen] val JavaStringClass           = "java/lang/String"
 
   private[codegen] val TupleClass                = "leon/codegen/runtime/Tuple"
   private[codegen] val SetClass                  = "leon/codegen/runtime/Set"
@@ -77,6 +78,7 @@ trait CodeGeneration {
   private[codegen] val GenericValuesClass        = "leon/codegen/runtime/GenericValues"
   private[codegen] val MonitorClass              = "leon/codegen/runtime/LeonCodeGenRuntimeMonitor"
   private[codegen] val HenkinClass               = "leon/codegen/runtime/LeonCodeGenRuntimeHenkinMonitor"
+  private[codegen] val StrOpsClass               = "leon/codegen/runtime/StrOps"
 
   def idToSafeJVMName(id: Identifier) = {
     scala.reflect.NameTransformer.encode(id.uniqueName).replaceAll("\\.", "\\$")
@@ -131,6 +133,9 @@ trait CodeGeneration {
 
     case TypeParameter(_) =>
       "L" + ObjectClass + ";"
+    
+    case StringType =>
+      "L" + JavaStringClass + ";"
 
     case _ => throw CompilationException("Unsupported type : " + tpe)
   }
@@ -564,6 +569,9 @@ trait CodeGeneration {
 
       case UnitLiteral() =>
         ch << Ldc(1)
+      
+      case StringLiteral(v) =>
+        ch << Ldc(v)
 
       case InfiniteIntegerLiteral(v) =>
         ch << New(BigIntClass) << DUP
@@ -888,6 +896,38 @@ trait CodeGeneration {
       case f @ Forall(args, body) =>
         compileForall(f, ch)
 
+      // String processing =>
+      case StringConcat(l, r) =>
+        mkExpr(l, ch)
+        mkExpr(r, ch)
+        ch << InvokeStatic(StrOpsClass, "concat", s"(L$JavaStringClass;L$JavaStringClass;)L$JavaStringClass;")
+        
+      case StringLength(a) =>
+        mkExpr(a, ch)
+        ch << InvokeStatic(StrOpsClass, "length", s"(L$JavaStringClass;)L$BigIntClass;")
+        
+      case Int32ToString(a) =>
+        mkExpr(a, ch)
+        ch << InvokeStatic(StrOpsClass, "intToString", s"(I)L$JavaStringClass;")
+      case BooleanToString(a) =>
+        mkExpr(a, ch)
+        ch << InvokeStatic(StrOpsClass, "booleanToString", s"(z)L$JavaStringClass;")
+      case IntegerToString(a) =>
+        mkExpr(a, ch)
+        ch << InvokeStatic(StrOpsClass, "bigIntToString", s"(L$BigIntClass;)L$JavaStringClass;")
+      case CharToString(a) =>
+        mkExpr(a, ch)
+        ch << InvokeStatic(StrOpsClass, "charToString", s"(C)L$JavaStringClass;")
+      case RealToString(a) =>
+        mkExpr(a, ch)
+        ch << InvokeStatic(StrOpsClass, "realToString", s"(L$RealClass;)L$JavaStringClass;")
+        
+      case SubString(a, start, end) =>
+        mkExpr(a, ch)
+        mkExpr(start, ch)
+        mkExpr(end, ch)
+        ch << InvokeStatic(StrOpsClass, "substring", s"(L$JavaStringClass;L$BigIntClass;L$BigIntClass;)L$JavaStringClass;")
+        
       // Arithmetic
       case Plus(l, r) =>
         mkExpr(l, ch)
@@ -1217,6 +1257,9 @@ trait CodeGeneration {
       case IntegerType =>
         ch << CheckCast(BigIntClass)
 
+      case StringType =>
+        ch << CheckCast(JavaStringClass)
+
       case RealType =>
         ch << CheckCast(RationalClass)
 
diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala
index 69f95f45559737bfd895989aba010dbc0667bb3a..fb060754e55478fe51d275269b1756d849637f6b 100644
--- a/src/main/scala/leon/codegen/CompilationUnit.scala
+++ b/src/main/scala/leon/codegen/CompilationUnit.scala
@@ -277,6 +277,9 @@ class CompilationUnit(val ctx: LeonContext,
     case (c: java.lang.Character, CharType) =>
       CharLiteral(c.toChar)
 
+    case (c: java.lang.String, StringType) =>
+      StringLiteral(c)
+
     case (cc: runtime.CaseClass, ct: ClassType) =>
       val fields = cc.productElements()
 
diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
index 80f71fd87be7f27e1793e13fe38eb09b78f78d62..4471a2eb3047ad1e9dab8ac650fa591886241650 100644
--- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
@@ -279,7 +279,27 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
 
     case RealMinus(l,r) =>
       e(RealPlus(l, RealUMinus(r)))
-
+      
+    case StringConcat(l, r) =>
+      (e(l), e(r)) match {
+        case (StringLiteral(i1), StringLiteral(i2)) => StringLiteral(i1 + i2)
+        case (le,re) => throw EvalError(typeErrorMsg(le, StringType))
+      }
+    case StringLength(a) => e(a) match {
+      case StringLiteral(a) => InfiniteIntegerLiteral(a.length)
+      case res => throw EvalError(typeErrorMsg(res, IntegerType))
+    }
+    case SubString(a, start, end) => (e(a), e(start), e(end)) match {
+      case (StringLiteral(a), InfiniteIntegerLiteral(b), InfiniteIntegerLiteral(c))  =>
+        StringLiteral(a.substring(b.toInt, c.toInt))
+      case res => throw EvalError(typeErrorMsg(res._1, StringType))
+    }
+    case Int32ToString(a) => StringLiteral(a.toString)
+    case CharToString(a) => StringLiteral(a.toString)
+    case IntegerToString(a) => StringLiteral(a.toString)
+    case BooleanToString(a) => StringLiteral(a.toString)
+    case RealToString(a) => StringLiteral(a.toString)
+    
     case BVPlus(l,r) =>
       (e(l), e(r)) match {
         case (IntLiteral(i1), IntLiteral(i2)) => IntLiteral(i1 + i2)
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index ea5318e4b96c21bbf2645afd1b791f95a22f9551..1903a0c1f7aab62aee1524078417a5adc1024e2a 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -1526,14 +1526,14 @@ trait CodeExtraction extends ASTExtractors {
             //String methods
             case (IsTyped(a1, StringType), "toString", List()) =>
               a1
-            case (IsTyped(a1, CanHaveStringType(t)), "toString", List()) =>
-              ToString(a1)
+            case (IsTyped(a1, WithStringconverter(converter)), "toString", List()) =>
+              converter(a1)
             case (IsTyped(a1, StringType), "+", List(IsTyped(a2, StringType))) =>
               StringConcat(a1, a2)
-            case (IsTyped(a1, StringType), "+", List(IsTyped(a2, CanHaveStringType(t)))) =>
-              StringConcat(a1, ToString(a2))
-            case (IsTyped(a1, CanHaveStringType(t)), "+", List(IsTyped(a2, StringType))) =>
-              StringConcat(ToString(a1), a2)
+            case (IsTyped(a1, StringType), "+", List(IsTyped(a2, WithStringconverter(converter)))) =>
+              StringConcat(a1, converter(a2))
+            case (IsTyped(a1, WithStringconverter(converter)), "+", List(IsTyped(a2, StringType))) =>
+              StringConcat(converter(a1), a2)
             case (IsTyped(a1, StringType), "length", List()) =>
               StringLength(a1)
             case (IsTyped(a1, StringType), "substring", List(IsTyped(start, IntegerType | Int32Type))) =>
diff --git a/src/main/scala/leon/purescala/Expressions.scala b/src/main/scala/leon/purescala/Expressions.scala
index 607f8fe588da87d3cc560f3339432562b1791210..8d6e00ab0271bbbdef497a539ccbce40ac293066 100644
--- a/src/main/scala/leon/purescala/Expressions.scala
+++ b/src/main/scala/leon/purescala/Expressions.scala
@@ -547,21 +547,26 @@ object Expressions {
     }
   }
   
-  /** Returns true if the underlined type can be converted to a String */
-  object CanHaveStringType {
-    def apply(t: TypeTree): Boolean = t match { case BooleanType | Int32Type | IntegerType | CharType | RealType | StringType => true case _ => false }
-    def unapply(t: TypeTree) = if(apply(t)) Some(t) else None
+  abstract class ConverterToString(fromType: TypeTree, toType: TypeTree) extends Expr {
+    def expr: Expr
+    val getType = if(expr.getType == fromType) toType else Untyped
   }
   
   /* String Theory */
-  /** $encodingof `expr.toString` for strings */
-  case class ToString(expr: Expr) extends Expr {
-    val getType = if(CanHaveStringType(expr.getType)) StringType else Untyped
-  }
+  /** $encodingof `expr.toString` for Int32 to String */
+  case class Int32ToString(expr: Expr) extends ConverterToString(Int32Type, StringType)
+  /** $encodingof `expr.toString` for boolean to String */
+  case class BooleanToString(expr: Expr) extends ConverterToString(BooleanType, StringType)
+  /** $encodingof `expr.toString` for BigInt to String */
+  case class IntegerToString(expr: Expr) extends ConverterToString(IntegerType, StringType)
+  /** $encodingof `expr.toString` for char to String */
+  case class CharToString(expr: Expr) extends ConverterToString(CharType, StringType)
+  /** $encodingof `expr.toString` for real to String */
+  case class RealToString(expr: Expr) extends ConverterToString(RealType, StringType)
   /** $encodingof `lhs + rhs` for strings */
   case class StringConcat(lhs: Expr, rhs: Expr) extends Expr {
      val getType = {
-      if (CanHaveStringType(lhs.getType) || CanHaveStringType(rhs.getType)) StringType
+      if (lhs.getType == StringType && rhs.getType == StringType) StringType
       else Untyped
     }
   }
diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala
index 0a6971eb3715aa8e87facf39296c3d73b73630b7..b79602c9ebd65d10e9b5dbda7e157afd915bdbce 100644
--- a/src/main/scala/leon/purescala/Extractors.scala
+++ b/src/main/scala/leon/purescala/Extractors.scala
@@ -29,8 +29,16 @@ object Extractors {
         Some((Seq(t), (es: Seq[Expr]) => BVNot(es.head)))
       case StringLength(t) =>
         Some((Seq(t), (es: Seq[Expr]) => StringLength(es.head)))
-      case ToString(t) =>
-        Some((Seq(t), (es: Seq[Expr]) => ToString(es.head)))
+      case Int32ToString(t) =>
+        Some((Seq(t), (es: Seq[Expr]) => Int32ToString(es.head)))
+      case BooleanToString(t) =>
+        Some((Seq(t), (es: Seq[Expr]) => BooleanToString(es.head)))
+      case IntegerToString(t) =>
+        Some((Seq(t), (es: Seq[Expr]) => IntegerToString(es.head)))
+      case CharToString(t) =>
+        Some((Seq(t), (es: Seq[Expr]) => CharToString(es.head)))
+      case RealToString(t) =>
+        Some((Seq(t), (es: Seq[Expr]) => RealToString(es.head)))
       case SetCardinality(t) =>
         Some((Seq(t), (es: Seq[Expr]) => SetCardinality(es.head)))
       case CaseClassSelector(cd, e, sel) =>
@@ -265,6 +273,17 @@ object Extractors {
   object IsTyped {
     def unapply[T <: Typed](e: T): Option[(T, TypeTree)] = Some((e, e.getType))
   }
+  
+  object WithStringconverter {
+    def unapply(t: TypeTree): Option[Expr => Expr] = t match {
+      case BooleanType => Some(BooleanToString)
+      case Int32Type   => Some(Int32ToString)
+      case IntegerType => Some(IntegerToString)
+      case CharType    => Some(CharToString)
+      case RealType    => Some(RealToString)
+      case _           => None
+    }
+  }
 
   object FiniteArray {
     def unapply(e: Expr): Option[(Map[Int, Expr], Option[Expr], Expr)] = e match {
diff --git a/testcases/stringrender/IntWrapperRender.scala b/testcases/stringrender/IntWrapperRender.scala
index c723e0f5a60172529bf46797ad2f6306c8919010..c760f64e0490d5688f60943e7435d3c04accbfef 100644
--- a/testcases/stringrender/IntWrapperRender.scala
+++ b/testcases/stringrender/IntWrapperRender.scala
@@ -6,7 +6,6 @@
   */
 
 import leon.lang._
-//import string.String
 import leon.annotation._
 import leon.collection._
 import leon.collection.ListOps._