diff --git a/library/lang/package.scala b/library/lang/package.scala
index 7e40b880e7f89c923a60061774619e5f2d9b4b85..1b26c5006dea499e6d94632be47a20c14c723160 100644
--- a/library/lang/package.scala
+++ b/library/lang/package.scala
@@ -26,7 +26,7 @@ package object lang {
   implicit def while2Invariant(u: Unit) = InvariantFunction
 
   @ignore
-  def error[T](reason: String): T = sys.error(reason)
+  def error[T](reason: java.lang.String): T = sys.error(reason)
 
   @library
   def passes[A, B](in: A, out: B)(tests: Map[A,B]): Boolean = {
diff --git a/library/lang/string/String.scala b/library/lang/string/String.scala
new file mode 100644
index 0000000000000000000000000000000000000000..b47fcded3fb24bf362298dba9e4b701f868d79a7
--- /dev/null
+++ b/library/lang/string/String.scala
@@ -0,0 +1,12 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+package leon.lang.string
+
+case class String(chars: leon.collection.List[Char]) {
+  def +(that: String): String = {
+    String(this.chars ++ that.chars)
+  }
+
+  def size = chars.size
+
+  def length = size
+}
diff --git a/library/lang/string/package.scala b/library/lang/string/package.scala
new file mode 100644
index 0000000000000000000000000000000000000000..01080050cc39baa678b638ba7f0b844cfa88f12a
--- /dev/null
+++ b/library/lang/string/package.scala
@@ -0,0 +1,13 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon.lang
+
+import leon.annotation._
+import scala.language.implicitConversions
+
+package object string {
+  @ignore
+  implicit def strToStr(s: java.lang.String): leon.lang.string.String = {
+    String(leon.collection.Nil())
+  }
+}
diff --git a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
index b41389fc2040b4d3785098830d4328c0d7d6d5d2..0ffd0fc708b25016bc8cab85c93d498560b7445b 100644
--- a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
+++ b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
@@ -152,6 +152,16 @@ trait ASTExtractors {
       }
     }
 
+
+    object ExStringLiteral {
+      def unapply(tree: Apply): Option[String] = tree  match {
+        case Apply(ExSelected("leon", "lang", "string", "package", "strToStr"), (str: Literal) :: Nil) =>
+          Some(str.value.stringValue)
+        case _ =>
+          None
+      }
+    }
+
     object ExAssertExpression {
       /** Extracts the 'assert' contract from an expression (only if it's the
        * first call in the block). */
@@ -532,6 +542,13 @@ trait ASTExtractors {
       }
     }
 
+    object ExCharLiteral {
+      def unapply(tree: Literal): Option[Char] = tree match {
+        case Literal(c @ Constant(i)) if c.tpe == CharClass.tpe => Some(c.charValue)
+        case _ => None
+      }
+    }
+
     object ExInt32Literal {
       def unapply(tree: Literal): Option[Int] = tree match {
         case Literal(c @ Constant(i)) if c.tpe == IntClass.tpe => Some(c.intValue)
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index 3c8caa5cc7cbc3cc0f54b2e6a24e215a0769db4a..3f96d94887186aa5a1afdb995ecce21e49a8d5f0 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -367,9 +367,17 @@ trait CodeExtraction extends ASTExtractors {
       }
     }
 
-    def libraryMethod(classname: String, methodName: String): Option[(LeonClassDef, FunDef)] = {
-      classesToClasses.values.find(_.id.name == classname).flatMap { cl =>
-        cl.methods.find(_.id.name == methodName).map { fd => (cl, fd) }
+    def libraryClass(pos: Position, className: String): LeonClassDef = {
+      classesToClasses.find{ case (s, c) => s.fullName == className }.map(_._2).getOrElse {
+        outOfSubsetError(pos, "Could not find class "+className)
+      }
+    }
+
+    def libraryCaseClass(pos: Position, className: String): CaseClassDef = {
+      libraryClass(pos, className) match {
+        case ccd: CaseClassDef => ccd
+        case _ =>
+          outOfSubsetError(pos, "Class "+className+" is not a case class")
       }
     }
 
@@ -1366,6 +1374,21 @@ trait CodeExtraction extends ASTExtractors {
 
           ArrayUpdated(rar, rk, rv)
 
+        case chr @ ExCharLiteral(c) =>
+          CharLiteral(c)
+
+        case str @ ExStringLiteral(s) =>
+          val chars = s.toList.map(CharLiteral(_))
+          
+          val consChar = CaseClassType(libraryCaseClass(str.pos, "leon.collection.Cons"), Seq(CharType));
+          val nilChar  = CaseClassType(libraryCaseClass(str.pos, "leon.collection.Nil"),  Seq(CharType));
+
+          val charList = chars.foldRight(CaseClass(nilChar, Seq())) {
+            case (c, s) => CaseClass(consChar, Seq(c, s))
+          }
+
+          CaseClass(CaseClassType(libraryCaseClass(str.pos, "leon.lang.string.String"), Seq()), Seq(charList))
+
         case c @ ExCall(rec, sym, tps, args) =>
           val rrec = rec match {
             case t if (defsToDefs contains sym) && !isMethod(sym) =>
@@ -1536,6 +1559,9 @@ trait CodeExtraction extends ASTExtractors {
     }
 
     private def extractType(tpt: Type)(implicit dctx: DefContext, pos: Position): LeonType = tpt match {
+      case tpe if tpe == CharClass.tpe =>
+        CharType
+
       case tpe if tpe == IntClass.tpe =>
         Int32Type
 
@@ -1636,7 +1662,7 @@ trait CodeExtraction extends ASTExtractors {
             tp
           })
         } else {
-          outOfSubsetError(NoPosition, "Unknown class "+sym.name)
+          outOfSubsetError(NoPosition, "Unknown class "+sym.fullName)
         }
       }
     }
diff --git a/src/main/scala/leon/frontends/scalac/ExtractionPhase.scala b/src/main/scala/leon/frontends/scalac/ExtractionPhase.scala
index b647188e922f592ab0606387ac316fadcb311465..7ab53108831841b671e46a7b12c19ef80f748fa2 100644
--- a/src/main/scala/leon/frontends/scalac/ExtractionPhase.scala
+++ b/src/main/scala/leon/frontends/scalac/ExtractionPhase.scala
@@ -40,7 +40,7 @@ object ExtractionPhase extends LeonPhase[List[String], Program] {
     val injected = if (ctx.settings.injectLibrary) {
       libFiles
     } else {
-      libFiles.filter(f => f.contains("/lang/") || f.contains("/annotation/"))
+      libFiles.filter(f => (f.contains("/lang/") && !f.contains("/lang/string/")) || f.contains("/annotation/"))
     }
 
     val compilerOpts = injected ::: args.filterNot(_.startsWith("--"))
diff --git a/src/main/scala/leon/purescala/Common.scala b/src/main/scala/leon/purescala/Common.scala
index dd1a6de02e35913f3a2ab11365c49eef3f2597c1..e9501ab8aaa400396c78f9b318837ec25a371c38 100644
--- a/src/main/scala/leon/purescala/Common.scala
+++ b/src/main/scala/leon/purescala/Common.scala
@@ -65,6 +65,8 @@ object Common {
       case Some(ow) => ow.id :: ow.id.ownerChain
     }
 
+    def fullName: String = ownerChain.map(_.name).mkString(".")
+
   }
 
   private object UniqueCounter {
diff --git a/src/main/scala/leon/purescala/DefOps.scala b/src/main/scala/leon/purescala/DefOps.scala
index 50710f7a123168eb64c642f2202be4c8b42f0720..a8c8dcc59e119dc38423a5529e229b23c13d8238 100644
--- a/src/main/scala/leon/purescala/DefOps.scala
+++ b/src/main/scala/leon/purescala/DefOps.scala
@@ -107,6 +107,17 @@ object DefOps {
     (pack, finalPath)
   }
 
+  def fullName(df: Definition, fromProgram: Option[Program] = None): String = {
+    val p = fromProgram.getOrElse(inProgram(df))
+
+    val (pr, ds) = pathAsVisibleFrom(p, df)
+
+    (pr ::: ds.flatMap{
+      case _: UnitDef => None
+      case m: ModuleDef if m.isStandalone => None
+      case d => Some(d.id.name)
+    }).mkString(".")
+  }
 
   def searchByFullName (
     fullName : String,
diff --git a/src/main/scala/leon/purescala/Definitions.scala b/src/main/scala/leon/purescala/Definitions.scala
index 779aad137c1b18d7d13451b6cd2da3fc1d50275b..86c6cf16fd46cad2b0fe8a4bd52c1398c119c785 100644
--- a/src/main/scala/leon/purescala/Definitions.scala
+++ b/src/main/scala/leon/purescala/Definitions.scala
@@ -4,6 +4,7 @@ package leon
 package purescala
 
 import scala.collection.generic.CanBuildFrom
+import utils.Library
 
 object Definitions {
   import Common._
@@ -82,6 +83,8 @@ object Definitions {
     def duplicate = {
       copy(units = units.map{_.duplicate})
     }
+
+    lazy val library = Library(this)
     
     def writeScalaFile(filename: String) {
       import java.io.FileWriter
diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index 123ab89feda3b57cbeae5988bb2d8130747e3838..a00e2d2450f34e45a6dbc63806eb991144764daa 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -13,6 +13,7 @@ import utils._
 
 import java.lang.StringBuffer
 import PrinterHelpers._
+import TreeOps.isStringLiteral
 
 case class PrinterContext(
   current: Tree,
@@ -228,14 +229,24 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
         } else {
           p"""|?($es)"""
         }
+      case e @ CaseClass(cct, args) =>
 
-      case CaseClass(cct, args) =>
-        if (cct.classDef.isCaseObject) {
-          p"$cct"
-        } else {
-          p"$cct($args)"
+        isStringLiteral(e) match {
+          case Some(str) =>
+            val q = '"';
+            p"$q$str$q"
+
+          case None =>
+            if (cct.classDef.isCaseObject) {
+              p"$cct"
+            } else {
+              p"$cct($args)"
+            }
         }
 
+
+
+
       case And(exprs)           => optP { p"${nary(exprs, " && ")}" }
       case Or(exprs)            => optP { p"${nary(exprs, "| || ")}" }
       case Not(Equals(l, r))    => optP { p"$l \u2260 $r" }
@@ -244,6 +255,7 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
       case UMinus(expr)         => p"-$expr"
       case Equals(l,r)          => optP { p"$l == $r" }
       case IntLiteral(v)        => p"$v"
+      case CharLiteral(v)       => p"$v"
       case BooleanLiteral(v)    => p"$v"
       case StringLiteral(s)     => p""""$s""""
       case UnitLiteral()        => p"()"
@@ -268,8 +280,23 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
 
         if (tfd.fd.isRealFunction) p"($args)"
 
+      case BinaryMethodCall(a, op, b) =>
+        optP { p"${a} $op ${b}" }
+
+      case FcallMethodInvocation(rec, fd, id, tps, args) =>
+
+        p"${rec}.${id}"
+        if (tps.nonEmpty) {
+          p"[$tps]"
+        }
+
+        if (fd.isRealFunction) {
+          p"($args)"
+        }
+
+
       case FunctionInvocation(tfd, args) =>
-        printWithPath(tfd.fd)
+        p"${tfd.id}"
 
         if (tfd.tps.nonEmpty) {
           p"[${tfd.tps}]"
@@ -380,6 +407,7 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
       case Untyped               => p"<untyped>"
       case UnitType              => p"Unit"
       case Int32Type             => p"Int"
+      case CharType              => p"Char"
       case BooleanType           => p"Boolean"
       case ArrayType(bt)         => p"Array[$bt]"
       case SetType(bt)           => p"Set[$bt]"
@@ -526,6 +554,49 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
     
   }
 
+  object FcallMethodInvocation {
+    def unapply(fi: FunctionInvocation): Option[(Expr, FunDef, String, Seq[TypeTree], Seq[Expr])] = {
+        val FunctionInvocation(tfd, args) = fi
+        tfd.fd.origOwner match {
+          case Some(cd: ClassDef) =>
+            val (rec, rargs) = (args.head, args.tail)
+
+            val fid = tfd.fd.id
+
+            val maybeClassName = fid.name.substring(0, cd.id.name.length)
+
+            val fname = if (maybeClassName == cd.id.name) {
+              fid.name.substring(cd.id.name.length + 1) // +1 to also remove $
+            } else {
+              fid.name
+            }
+
+            val decoded = scala.reflect.NameTransformer.decode(fname)
+
+            val realtps = tfd.tps.drop(cd.tparams.size)
+
+            Some((rec, tfd.fd, decoded, realtps, rargs))
+          case _ =>
+            None
+        }
+    }
+  }
+
+  object BinaryMethodCall {
+    val makeBinary = Set("+", "-", "*", "::", "++", "--", "&&", "||", "/");
+
+    def unapply(fi: FunctionInvocation): Option[(Expr, String, Expr)] = fi match {
+      case FcallMethodInvocation(rec, _, name, Nil, List(a)) =>
+
+        if (makeBinary contains name) {
+          Some((rec, name, a))
+        } else {
+          None
+        }
+      case _ => None
+    }
+  }
+
   def requiresBraces(ex: Tree, within: Option[Tree]): Boolean = (ex, within) match {
     case (pa: PrettyPrintable, _) => pa.printRequiresBraces(within)
     case (_, None) => false
@@ -541,12 +612,12 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
   def precedence(ex: Expr): Int = ex match {
     case (pa: PrettyPrintable) => pa.printPrecedence
     case (_: ElementOfSet) => 0
-    case (_: Or) => 1
-    case (_: And) => 3
+    case (_: Or | BinaryMethodCall(_, "||", _)) => 1
+    case (_: And | BinaryMethodCall(_, "&&", _)) => 3
     case (_: GreaterThan | _: GreaterEquals  | _: LessEquals | _: LessThan) => 4
     case (_: Equals | _: Iff | _: Not) => 5
-    case (_: Plus | _: Minus | _: SetUnion| _: SetDifference) => 6
-    case (_: Times | _: Division | _: Modulo) => 7
+    case (_: Plus | _: Minus | _: SetUnion| _: SetDifference | BinaryMethodCall(_, "+" | "-", _)) => 6
+    case (_: Times | _: Division | _: Modulo | BinaryMethodCall(_, "*" | "/", _)) => 7
     case _ => 7
   }
 
@@ -558,6 +629,8 @@ class PrettyPrinter(opts: PrinterOptions, val sb: StringBuffer = new StringBuffe
     case (_, Some(_: Require)) => false
     case (_, Some(_: Definition)) => false
     case (_, Some(_: MatchExpr | _: MatchCase | _: Let | _: LetTuple | _: LetDef | _: IfExpr)) => false
+    case (b1 @ BinaryMethodCall(_, _, _), Some(b2 @ BinaryMethodCall(_, _, _))) if precedence(b1) > precedence(b2) => false
+    case (BinaryMethodCall(_, _, _), Some(_: FunctionInvocation)) => true
     case (_, Some(_: FunctionInvocation)) => false
     case (ie: IfExpr, _) => true
     case (me: MatchExpr, _ ) => true
diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala
index eece54ca86528b26062fbfd6d42f0a2c2e7a5e2d..7b70def5ddc490c87234e79c73e2edb2627ea512 100644
--- a/src/main/scala/leon/purescala/TreeOps.scala
+++ b/src/main/scala/leon/purescala/TreeOps.scala
@@ -8,6 +8,7 @@ import utils.Simplifiers
 import leon.solvers._
 
 import scala.collection.concurrent.TrieMap
+import DefOps._
 
 object TreeOps {
   import Common._
@@ -1988,6 +1989,51 @@ object TreeOps {
     (fds.values.toSet, res2)
   }
 
+  def isStringLiteral(e: Expr): Option[String] = e match {
+    case CaseClass(cct, args) =>
+      val lib = inProgram(cct.classDef).library
+
+      if (Some(cct.classDef) == lib.String) {
+        listLiteralToList(args(0)) match {
+          case Some(chars) =>
+            val str = chars.map {
+              case CharLiteral(c) => Some(c)
+              case _              => None
+            }
+
+            if (str.forall(_.isDefined)) {
+              Some(str.flatten.mkString)
+            } else {
+              None
+            }
+          case _ =>
+            None
+
+        }
+      } else {
+        None
+      }
+    case _ =>
+      None
+  }
+
+  def listLiteralToList(e: Expr): Option[List[Expr]] = e match {
+    case CaseClass(cct, args) =>
+      val lib = inProgram(cct.classDef).library
+
+      if (Some(cct.classDef) == lib.Nil) {
+        Some(Nil)
+      } else if (Some(cct.classDef) == lib.Cons) {
+        listLiteralToList(args(1)).map { t =>
+          args(0) :: t
+        }
+      } else {
+        None
+      }
+    case _ =>
+      None
+  }
+
   /**
    * Deprecated API
    * ========
diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala
index 44b98012a2ef65bf0b5dd570daab9750d4de265f..c5a648cccc458721a464caa2e3a5fba7c5ca16dc 100644
--- a/src/main/scala/leon/purescala/Trees.scala
+++ b/src/main/scala/leon/purescala/Trees.scala
@@ -434,6 +434,10 @@ object Trees {
     val fixedType = tp
   }
 
+  case class CharLiteral(value: Char) extends Literal[Char] with FixedType {
+    val fixedType = CharType
+  }
+
   case class IntLiteral(value: Int) extends Literal[Int] with FixedType {
     val fixedType = Int32Type
   }
diff --git a/src/main/scala/leon/purescala/TypeTrees.scala b/src/main/scala/leon/purescala/TypeTrees.scala
index eb6908420247e0fb0c09efbb862711293423982d..24249ad2aa3e75ae46595bda5efdad8ef86ee616 100644
--- a/src/main/scala/leon/purescala/TypeTrees.scala
+++ b/src/main/scala/leon/purescala/TypeTrees.scala
@@ -55,6 +55,7 @@ object TypeTrees {
   case object BooleanType extends TypeTree
   case object Int32Type extends TypeTree
   case object UnitType extends TypeTree
+  case object CharType extends TypeTree
 
   case class TypeParameter(id: Identifier) extends TypeTree
 
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
index 303276bdfb71ea9927c90858410fa6365c7c72d7..c31506240b3233c981a9fabe570a7d83140993c2 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
@@ -90,6 +90,7 @@ trait SMTLIBTarget {
       tpe match {
         case BooleanType => Core.BoolSort()
         case Int32Type => Ints.IntSort()
+        case CharType => FixedSizeBitVectors.BitVectorSort(32)
 
         case RawArrayType(from, to) =>
           Sort(SMTIdentifier(SSymbol("Array")), Seq(declareSort(from), declareSort(to)))
@@ -322,6 +323,7 @@ trait SMTLIBTarget {
         declareVariable(FreshIdentifier("Unit").setType(UnitType))
 
       case IntLiteral(i) => if (i > 0) Ints.NumeralLit(i) else Ints.Neg(Ints.NumeralLit(-i))
+      case CharLiteral(c) => FixedSizeBitVectors.BitVectorLit(Hexadecimal.fromInt(c.toInt).get)
       case BooleanLiteral(v) => Core.BoolConst(v)
       case StringLiteral(s) => SString(s)
       case Let(b,d,e) =>
@@ -473,6 +475,9 @@ trait SMTLIBTarget {
     case (_, UnitType) =>
       UnitLiteral()
 
+    case (SHexadecimal(h), CharType) =>
+      CharLiteral(h.toInt.toChar)
+
     case (SNumeral(n), Int32Type) =>
       IntLiteral(n.toInt)
 
diff --git a/src/main/scala/leon/synthesis/rules/Tegis.scala b/src/main/scala/leon/synthesis/rules/Tegis.scala
index faaa084e57a6f62f1efa68d45a84e12784eccb0a..a556097db125dcf73ca67ca3e1efbd2790d6ed09 100644
--- a/src/main/scala/leon/synthesis/rules/Tegis.scala
+++ b/src/main/scala/leon/synthesis/rules/Tegis.scala
@@ -30,7 +30,6 @@ case object TEGIS extends Rule("TEGIS") {
 
   def instantiateOn(sctx: SynthesisContext, p: Problem): Traversable[RuleInstantiation] = {
     var tests = p.getTests(sctx).map(_.ins).distinct
-
     if (tests.nonEmpty) {
       List(new RuleInstantiation(p, this, SolutionBuilder.none, this.name, this.priority) {
         def apply(sctx: SynthesisContext): RuleApplicationResult = {
@@ -148,7 +147,6 @@ case object TEGIS extends Rule("TEGIS") {
           var candidate: Option[Expr] = None
           var enumLimit = 10000;
 
-
           var n = 1;
           timers.generating.start()
           allExprs.take(enumLimit).takeWhile(e => candidate.isEmpty).foreach { e =>
@@ -188,8 +186,8 @@ case object TEGIS extends Rule("TEGIS") {
           }
           timers.generating.stop()
 
-          println("Found candidate "+n)
-          println("Compiled: "+evaluator.unit.compiledN)
+          //println("Found candidate "+n)
+          //println("Compiled: "+evaluator.unit.compiledN)
 
           if (candidate.isDefined) {
             RuleSuccess(Solution(BooleanLiteral(true), Set(), candidate.get), isTrusted = false)
diff --git a/src/main/scala/leon/utils/Library.scala b/src/main/scala/leon/utils/Library.scala
new file mode 100644
index 0000000000000000000000000000000000000000..d80fd76a0a1188423d01763f4392c6e376db9b7a
--- /dev/null
+++ b/src/main/scala/leon/utils/Library.scala
@@ -0,0 +1,19 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon
+package utils
+
+import purescala.Definitions._
+import purescala.DefOps.searchByFullName
+
+case class Library(pgm: Program) {
+  lazy val List = lookup("leon.collection.List")
+  lazy val Cons = lookup("leon.collection.Cons")
+  lazy val Nil  = lookup("leon.collection.Nil")
+
+  lazy val String = lookup("leon.lang.string.String")
+
+  def lookup(name: String): Option[Definition] = {
+    searchByFullName(name, pgm)
+  }
+}