diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
index fecd9f6baf5fef58e0424fce41dd93971123fa16..d58fcf0bb42c7f8f6a5315bc816021ec488c45ad 100644
--- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
@@ -14,6 +14,7 @@ import leon.solvers.{SolverFactory, HenkinModel}
 import purescala.Common._
 import purescala.Expressions._
 import purescala.Definitions._
+import leon.utils.DebugSectionSynthesis
 
 abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int)
   extends ContextualEvaluator(ctx, prog, maxSteps)
@@ -86,7 +87,9 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
     case IfExpr(cond, thenn, elze) =>
       val first = e(cond)
       first match {
-        case BooleanLiteral(true) => e(thenn)
+        case BooleanLiteral(true) =>
+          ctx.reporter.ifDebug(printer => printer(thenn))(DebugSectionSynthesis)
+          e(thenn)
         case BooleanLiteral(false) => e(elze)
         case _ => throw EvalError(typeErrorMsg(first, BooleanType))
       }
diff --git a/src/main/scala/leon/evaluators/StringTracingEvaluator.scala b/src/main/scala/leon/evaluators/StringTracingEvaluator.scala
index e2786491d198afb45c6328a7ae7ba8ad4bde4fe4..74cc6f23be5011e905746316270abadc17c18888 100644
--- a/src/main/scala/leon/evaluators/StringTracingEvaluator.scala
+++ b/src/main/scala/leon/evaluators/StringTracingEvaluator.scala
@@ -5,8 +5,10 @@ package evaluators
 
 import purescala.Extractors.Operator
 import purescala.Expressions._
+import purescala.Types._
 import purescala.Definitions.Program
 import purescala.Expressions.Expr
+import leon.utils.DebugSectionSynthesis
 
 class StringTracingEvaluator(ctx: LeonContext, prog: Program) extends ContextualEvaluator(ctx, prog, 50000) with DefaultContexts {
 
@@ -17,20 +19,50 @@ class StringTracingEvaluator(ctx: LeonContext, prog: Program) extends Contextual
   override val name: String = "String Tracing evaluator"
 
   protected def e(expr: Expr)(implicit rctx: RC, gctx: GC): (Expr, Expr) = expr match {
+    case Variable(id) =>
+      rctx.mappings.get(id) match {
+        case Some(v) if v != expr =>
+          e(v)
+        case Some(v) =>
+          (v, expr)
+        case None =>
+          (expr, expr)
+      }
+      
     case StringConcat(s1, s2) =>
       val (es1, t1) = e(s1)
       val (es2, t2) = e(s2)
-      (underlying.e(StringConcat(es1, es2)), StringConcat(t1, t2))
-
+      (es1, es2) match {
+        case (StringLiteral(_), StringLiteral(_)) =>
+          (underlying.e(StringConcat(es1, es2)), StringConcat(t1, t2))
+        case _ =>
+          (StringConcat(es1, es2), StringConcat(t1, t2))
+      }
     case StringLength(s1) => 
       val (es1, t1) = e(s1)
-      (underlying.e(StringLength(es1)), StringLength(t1))
+      es1 match {
+        case StringLiteral(_) =>
+          (underlying.e(StringLength(es1)), StringLength(t1))
+        case _ =>
+          (StringLength(es1), StringLength(t1))
+      }
 
     case expr@StringLiteral(s) => 
       (expr, expr)
+      
+    case IfExpr(cond, thenn, elze) =>
+      val first = underlying.e(cond)
+      first match {
+        case BooleanLiteral(true) =>
+          ctx.reporter.ifDebug(printer => printer(thenn))(DebugSectionSynthesis)
+          e(thenn)
+        case BooleanLiteral(false) => e(elze)
+        case _ => throw EvalError(typeErrorMsg(first, BooleanType))
+      }
 
     case Operator(es, builder) =>
       val (ees, ts) = es.map(e).unzip
+      ctx.reporter.debug("Going to evaluate this : " + builder(ees))(DebugSectionSynthesis)
       (underlying.e(builder(ees)), builder(ts))
   }
 
diff --git a/src/main/scala/leon/synthesis/rules/StringRender.scala b/src/main/scala/leon/synthesis/rules/StringRender.scala
index bc5d915caaa7a681d525cbfa08c362e111d5dadd..dc3c2bd1493b2f976cc620b3fad1cb72b4ff9591 100644
--- a/src/main/scala/leon/synthesis/rules/StringRender.scala
+++ b/src/main/scala/leon/synthesis/rules/StringRender.scala
@@ -6,6 +6,7 @@ package rules
 
 import purescala.Expressions._
 import purescala.ExprOps._
+import purescala.TypeOps
 import purescala.Extractors._
 import purescala.Constructors._
 import purescala.Types._
@@ -20,10 +21,12 @@ import scala.collection.mutable.ListBuffer
 import leon.purescala.ExprOps
 import leon.evaluators.Evaluator
 import leon.evaluators.DefaultEvaluator
+import leon.evaluators.StringTracingEvaluator
 import leon.solvers.Model
 import leon.solvers.ModelBuilder
 import leon.solvers.string.StringSolver
 import scala.annotation.tailrec
+import leon.purescala.DefOps
 
 
 /** A template generator for a given type tree. 
@@ -78,7 +81,7 @@ case object StringRender extends Rule("StringRender") {
     }
   }
   
-  val e: AbstractClassType = null
+  val booleanTemplate = (a: Identifier) => StringTemplateGenerator(Hole => IfExpr(Variable(a), Hole, Hole))
   
   /** Returns a seq of expressions such as `x + y + "1" + y + "2" + z` associated to an expected result string `"1, 2"`.
     * We use these equations so that we can find the values of the constants x, y, z and so on.
@@ -137,7 +140,7 @@ case object StringRender extends Rule("StringRender") {
   /** Returns a stream of assignments compatible with input/output examples */
   def findAssignments(ctx: LeonContext, p: Program, inputs: Seq[Identifier], examples: ExamplesBank, template: Expr): Stream[Map[Identifier, String]] = {
     //new Evaluator()
-    val e = new DefaultEvaluator(ctx, p)
+    val e = new StringTracingEvaluator(ctx, p)
     
     var invalid = false
     
@@ -147,98 +150,164 @@ case object StringRender extends Rule("StringRender") {
         if(rhExpr.length == 1) {
           val model = new ModelBuilder
           model ++= inputs.zip(in)
-          e.eval(template, model.result()).result match {
-            case None => None
-            case Some(sfExpr) =>
+          val modelResult = model.result()
+          val evalResult =  e.eval(template, modelResult)
+          evalResult.result match {
+            case None =>
+              ctx.reporter.ifDebug(printer => printer("Eval = None : ["+template+"] in ["+inputs.zip(in)+"]"))
+              None
+            case Some((sfExpr, _)) =>
               val sf = toStringForm(sfExpr)
               val rhs = toStringLiteral(rhExpr.head)
-              if(sf.isEmpty || rhs.isEmpty) None
-              else gatherEquations(q, acc += ((sf.get, rhs.get)))
+              if(sf.isEmpty || rhs.isEmpty) {
+                ctx.reporter.ifDebug(printer => printer("sf empty or rhs empty ["+sfExpr+"] => ["+sf+"] in ["+rhs+"]"))
+                None
+              } else gatherEquations(q, acc += ((sf.get, rhs.get)))
           }
-        } else None
+        } else {
+          ctx.reporter.ifDebug(printer => printer("RHS.length != 1 : ["+rhExpr+"]"))
+          None 
+        }
     }
     gatherEquations(examples.valids.collect{ case io:InOutExample => io }.toList) match {
-      case Some(problem) => StringSolver.solve(problem)
-      case None => Stream.empty
+      case Some(problem) =>
+        ctx.reporter.ifDebug(printer => printer("Problem: ["+problem+"]"))
+        StringSolver.solve(problem)
+      case None => 
+        ctx.reporter.ifDebug(printer => printer("No problem found"))
+        Stream.empty
     }
   }
   
-  def findSolutions(examples: ExamplesBank, template: Expr)(implicit hctx: SearchContext, p: Problem): RuleApplication = {
-    val solutions = findAssignments(hctx.context, hctx.program, p.as, examples, template)
+  def findSolutions(examples: ExamplesBank, program: Program, template: Expr)(implicit hctx: SearchContext, p: Problem): RuleApplication = {
+    val solutions = findAssignments(hctx.context, program, p.as, examples, template)
+    hctx.reporter.ifDebug(printer => printer("Solutions: ["+solutions.toList+"]"))
+    
     solutionStreamToRuleApplication(p, template, solutions)
   }
   
   def solutionStreamToRuleApplication(p: Problem, template: Expr, solutions: Stream[Assignment]): RuleApplication = {
     if(solutions.isEmpty) RuleFailed() else {
       RuleClosed(solutions.map((assignment: Map[Identifier, String]) => {
-        Solution(pre=p.pc, defs=Set(), term=ExprOps.replaceFromIDs(assignment.mapValues(StringLiteral), template))
+        val term = ExprOps.simplifyString(ExprOps.replaceFromIDs(assignment.mapValues(StringLiteral), template))
+        Solution(pre=p.pc, defs=Set(), term=term)
       }))
     }
   }
   
   object StringTemplateGenerator extends TypedTemplateGenerator(StringType)
   
-  def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
+  case class DependentType(caseClassParent: Option[TypeTree], typeToConvert: TypeTree)
+  
+  
+  /** Creates an empty function definition for the dependent type */
+  def createEmptyFunDef(tpe: DependentType)(implicit hctx: SearchContext): FunDef = {
+    val funName2 = tpe.caseClassParent match {
+      case None => tpe.typeToConvert.asString(hctx.context)
+      case Some(t) => tpe.typeToConvert.asString(hctx.context)+"In"+t.asString(hctx.context) + "ToString" 
+    }
+    val funName = funName2.replace("]","").replace("[","")
+    val funId = FreshIdentifier(funName, alwaysShowUniqueID = true)
+    val argId= FreshIdentifier(tpe.typeToConvert.asString(hctx.context).toLowerCase()(0).toString, tpe.typeToConvert)
+    val fd = new FunDef(funId, Nil, ValDef(argId) :: Nil, StringType) // Empty function.
+    fd
+  }
+  
+  /** Pre-updates of the function definition */
+  def preUpdateFunDefBody(tpe: DependentType, fd: FunDef, assignments: Map[DependentType, FunDef]): Map[DependentType, FunDef] = {
+    assignments.get(tpe) match {
+      case None => assignments + (tpe -> fd)
+      case Some(_) => assignments
+    }
+  }
+  
+  /** Returns a (possibly recursive) template which can render the inputs in their order.
+    * Returns an expression and path-dependent pretty printers which can be used.
+    **/
+  def createFunDefsTemplates(
+      currentCaseClassParent: Option[TypeTree],
+      adtToString: Map[DependentType, FunDef],
+      inputs: Seq[(Identifier, TypeTree)])(implicit hctx: SearchContext): (Expr, Map[DependentType, FunDef]) = {
     
-    /** Returns a (possibly recursive) template which can render the inputs in their order. */
-    def createFunDefsTemplates(adtToString: Map[TypeTree, FunDef], inputs: Seq[(Identifier, TypeTree)]): (Expr, Map[TypeTree, FunDef]) = {
-      
-      def gatherInputs(inputs: List[(Identifier, TypeTree)], adtToString: Map[TypeTree, FunDef], result: ListBuffer[Expr] = ListBuffer()): (List[Expr], Map[TypeTree, FunDef]) = inputs match {
-        case Nil => (result.toList, adtToString)
-        case (input, tpe)::q => adtToString.get(tpe) match {
-          case Some(fd) =>
-            gatherInputs(q, adtToString, result += functionInvocation(fd, Seq(Variable(input))))
-          case None =>
-            tpe match {
-              case WithStringconverter(converter) => // Base case
-                gatherInputs(q, adtToString, result += converter(Variable(input)))
-              case t: ClassType =>
-                t.root match {
-                  case AbstractClassType(acd@AbstractClassDef(id, tparams, parent), tps) =>
-                    // Create a complete fundef with pattern matching
-                    val (assignments, cases) = ((adtToString, ListBuffer[MatchCase]()) /: acd.knownChildren) {
-                      case ((adtToString, acc), ccd@CaseClassDef(id, tparams, parent, isCaseObject)) =>
-                        val fields = ccd.fields.map(vd => (vd.id, vd.tpe.get)) // TODO: What if vd.tpe is null ?
-                        val fieldsIds = fields.map(id => FreshIdentifier(id._1.name, id._2))
-                        val pattern = CaseClassPattern(None, ccd.typed, fieldsIds.map(k => WildcardPattern(Some(k))))
-                        val (rhs, assignments) = createFunDefsTemplates(adtToString, fields)
-                        (assignments, acc += MatchCase(pattern, None, rhs))
-                      case ((adtToString, acc), e) => hctx.reporter.fatalError("Could not handle class def for string rendering " + e)
-                    }
-                    
-                    ///////////////////////////
-                    // TODO: Create the function with the pattern matching.
-                    // matchExpr(Variable(input), cases)
-                    // Gather the call to the function.
-                    /////////////////////////
-                    ???
-                    gatherInputs(q, assignments, result += ???)
-                  case CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tps) =>
-                    val fields = ccd.fields.map(vd => (vd.id, vd.tpe.get)) // TODO: What if vd.tpe is null ?
-                    ///////////////////////////
-                    // TODO: Create the function with pattern matching.
-                    // Gather the call to the function.
-                    /////////////////////////
-                    ???
-                    
-                    val (expr, assignments) = createFunDefsTemplates(adtToString, fields) // TODO : Create a new function definition !!!!!!!!!!!!!!!!!!!
-                    gatherInputs(q, assignments, result += expr)
-                }
-              case _ => 
-                hctx.reporter.fatalError("Could not handle class type for string rendering " + tpe)
-            }
-        }
+    /* Returns a list of expressions converting the list of inputs to string.
+     * Holes should be inserted before, after and in-between for solving concatenation.
+     * @return Along with the list, an updated function definitions to transform (parent-dependent) types to strings */
+    @tailrec def gatherInputs(
+        currentCaseClassParent: Option[TypeTree],
+        assignments1: Map[DependentType, FunDef],
+        inputs: List[(Identifier, TypeTree)],
+        result: ListBuffer[Expr] = ListBuffer()): (List[Expr], Map[DependentType, FunDef]) = inputs match {
+      case Nil => (result.toList, assignments1)
+      case (input, tpe)::q => 
+        val dependentType = DependentType(currentCaseClassParent, tpe)
+        assignments1.get(dependentType) match {
+        case Some(fd) =>
+          hctx.reporter.debug("found a function definition " + fd)
+          
+          gatherInputs(currentCaseClassParent, assignments1, q, result += functionInvocation(fd, Seq(Variable(input))))
+        case None => // No function can render the current type.
+          tpe match {
+            case BooleanType => // Special case.
+              gatherInputs(currentCaseClassParent, assignments1, q, result += booleanTemplate(input).instantiate)
+            case WithStringconverter(converter) => // Base case
+              gatherInputs(currentCaseClassParent, assignments1, q, result += converter(Variable(input)))
+            case t: ClassType =>
+              // Create the empty function body and updates the assignments parts.
+              val fd = createEmptyFunDef(dependentType)
+              hctx.reporter.debug("Creating a new function for " + dependentType)
+              val assignments2 = preUpdateFunDefBody(dependentType, fd, assignments1) // Inserts the FunDef in the assignments so that it can already be used.
+              t.root match {
+                case act@AbstractClassType(acd@AbstractClassDef(id, tparams, parent), tps) =>
+                  hctx.reporter.debug("preparing cases classes for " + act)
+                  // Create a complete FunDef body with pattern matching
+                  val (assignments3, cases) = ((assignments2, ListBuffer[MatchCase]()) /: act.knownCCDescendants) {
+                    case ((assignments2tmp, acc), CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2)) =>
+                      val typeMap = tparams.zip(tparams2).toMap
+                      def resolveType(t: TypeTree): TypeTree = TypeOps.instantiateType(t, typeMap) 
+                      val fields = ccd.fields.map(vd => ( TypeOps.instantiateType(vd, typeMap).id, resolveType(vd.tpe.get)))
+                      val fieldsIds = fields.map(id => FreshIdentifier(id._1.name, id._2))
+                      val pattern = CaseClassPattern(None, ccd.typed(tparams2), fieldsIds.map(k => WildcardPattern(Some(k))))
+                      val (rhs, assignments2tmp2) = createFunDefsTemplates(Some(t), assignments2tmp, fields) // Invoke functions for each of the fields.
+                      (assignments2tmp2, acc += MatchCase(pattern, None, rhs))
+                    case ((adtToString, acc), e) => hctx.reporter.fatalError("Could not handle this class definition for string rendering " + e)
+                  }
+                  fd.body = Some(MatchExpr(Variable(input), cases))
+                  gatherInputs(currentCaseClassParent, assignments3, q, result += functionInvocation(fd, Seq(Variable(input))))
+                case cct@CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2) =>
+                  hctx.reporter.debug("preparing function for " + cct)
+                  val typeMap = tparams.zip(tparams2).toMap
+                  def resolveType(t: TypeTree): TypeTree = TypeOps.instantiateType(t, typeMap)
+                  val fields = ccd.fields.map(vd => (TypeOps.instantiateType(vd, typeMap).id, resolveType(vd.tpe.get)))
+                  val fieldsIds = fields.map(id => FreshIdentifier(id._1.name, id._2))
+                  val pattern = CaseClassPattern(None, ccd.typed(tparams2), fieldsIds.map(k => WildcardPattern(Some(k))))
+                  val (rhs, assignments3) = createFunDefsTemplates(Some(t), assignments2, fields) // Invoke functions for each of the fields.
+                  fd.body = Some(MatchExpr(Variable(input), Seq(MatchCase(pattern, None, rhs))))
+                  gatherInputs(currentCaseClassParent, assignments3, q, result += functionInvocation(fd, Seq(Variable(input))))
+              }
+            case TypeParameter(t) =>
+              hctx.reporter.fatalError("Could not handle type parameter for string rendering " + t)
+            case _ => 
+              hctx.reporter.fatalError("Could not handle class type for string rendering " + tpe)
+          }
       }
-      val (exprs, assignments) = gatherInputs(inputs.toList, adtToString)
-      
-      (StringTemplateGenerator(Hole => {
-        StringConcat((StringConcat(Hole, exprs.head) /: exprs.tail) {
-          case (finalExpr, expr) => StringConcat(StringConcat(finalExpr, Hole), expr)
-        }, Hole)
-      }).instantiate, assignments)
     }
-      
+    val (exprs, assignments) = gatherInputs(currentCaseClassParent, adtToString, inputs.toList)
+    /** Add post, pre and in-between holes, and returns a single expr along with the new assignments. */
     
+    val template = exprs match {
+      case Nil =>
+        StringTemplateGenerator(Hole => Hole).instantiate
+      case exprList =>
+        StringTemplateGenerator(Hole => {
+          StringConcat((StringConcat(Hole, exprs.head) /: exprs.tail) {
+            case (finalExpr, expr) => StringConcat(StringConcat(finalExpr, Hole), expr)
+          }, Hole)
+        }).instantiate
+    }
+    (template, assignments)
+  }
+  
+  def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
     
     p.xs match {
       case List(IsTyped(v, StringType)) =>
@@ -266,32 +335,27 @@ case object StringRender extends Rule("StringRender") {
           */
         
         
-        val booleanTemplate = (a: Identifier) => StringTemplateGenerator(Hole => IfExpr(Variable(a), Hole, Hole))
         
+        // Returns expr and funDefs as templates.
         
-        
-        
-        /* All input variables which are inductive in the post condition, along with their abstract data type. */
-        p.as match {
-          case List(IsTyped(a, tpe@WithStringconverter(converter))) => // Standard conversions if they work.
-            val ruleInstantiations = ListBuffer[RuleInstantiation]()
-            if(tpe == BooleanType) {
-              ruleInstantiations += RuleInstantiation("Boolean split render") {
-                val template = booleanTemplate(a).instantiate
-                findSolutions(examples, template)
-              }
-            }
-            
-            ruleInstantiations += RuleInstantiation("String conversion with pre and post") {
-                val template = StringTemplateGenerator(Hole =>
-                  StringConcat(StringConcat(Hole, converter(Variable(a))), Hole)).instantiate
-                findSolutions(examples, template)
-              }
-            ruleInstantiations.toList
-          case _ =>
-            Nil
+        val ruleInstantiations = ListBuffer[RuleInstantiation]()
+        ruleInstantiations += RuleInstantiation("String conversion") {
+          val (expr, funDefs) = createFunDefsTemplates(None, Map(), p.as.map(input => (input, input.getType)))
+          
+          val toDebug: String = (("\nInferred functions:" /: funDefs)( (t, s) =>
+                t + "\n" + s.toString
+              ))
+          hctx.reporter.ifDebug(printer => printer("Inferred expression:\n" + expr + toDebug))
+          
+          //val newProgram = DefOps.addFunDefs(hctx.program, funDefs.values, hctx.sctx.functionContext)
+          val newExpr = (expr /: funDefs.values) {
+            case (e, fd) => LetDef(fd, e)
+          }
+          findSolutions(examples, hctx.program, newExpr)
         }
         
+        ruleInstantiations.toList
+        
       case _ => Nil
     }
   }