diff --git a/src/main/scala/leon/synthesis/rules/StringRender.scala b/src/main/scala/leon/synthesis/rules/StringRender.scala
index 140de9f1133d884dc242eecefea281ff6701fb5c..3c02166e853535689b138fc7c17a789dc72d8de8 100644
--- a/src/main/scala/leon/synthesis/rules/StringRender.scala
+++ b/src/main/scala/leon/synthesis/rules/StringRender.scala
@@ -93,33 +93,6 @@ case object StringRender extends Rule("StringRender") {
   /** For each solution to the problem such as `x + "1" + y + j + "2" + z = 1, 2`, outputs all possible assignments if they exist. */
   def solveProblems(problems: Seq[(Expr, String)]): Seq[Map[Identifier, String]] = ???
   
-  
-  /// Disambiguation: Enumerate different solutions, augment the size of examples by 1, and check discrepancies.
-  
-  
-    
-    
-    
-    
-    /*val inputTypeWithoutToStringFunction = inputs.collectFirst{ case (input, tpe: AbstractClassType) if
-      WithStringconverter.unapply(tpe).isEmpty &&
-      ADTToString.contains(tpe) =>
-        (input, tpe)
-    }
-    
-    inputTypeWithoutToStringFunction match {
-      case Some((input, tpe)) =>
-        val inductOn = FreshIdentifier(input.name, input.getType, true)
-        val fd = new FunDef(FreshIdentifier("rec", alwaysShowUniqueID = true),
-            Nil, ValDef(inductOn) :: Nil, StringType) // Empty function.
-        solve(ADTToString + (tpe -> fd), inputs, inlineFuns ++ Seq(fd), inlineExpr, examples) // Tail recursion.
-      case None =>
-        // Now all types have a corresponding toString function, even if it is empty for now.
-        
-        
-        
-        Stream.Empty
-    }*/
   import StringSolver.{StringFormToken, StringForm, Problem => SProblem, Equation, Assignment}
   
   /** Converts an expression to a stringForm, suitable for StringSolver */
@@ -151,7 +124,6 @@ case object StringRender extends Rule("StringRender") {
           val model = new ModelBuilder
           model ++= inputs.zip(in)
           val modelResult = model.result()
-          //ctx.reporter.debug("Going to evaluate this template:" + template)
           val evalResult =  e.eval(template, modelResult)
           evalResult.result match {
             case None =>
@@ -173,7 +145,7 @@ case object StringRender extends Rule("StringRender") {
     }
     gatherEquations(examples.valids.collect{ case io:InOutExample => io }.toList) match {
       case Some(problem) =>
-        //hctx.reporter.ifDebug(printer => printer("Problem: ["+StringSolver.renderProblem(problem)+"]"))
+        hctx.reporter.ifDebug(printer => printer("Problem: ["+StringSolver.renderProblem(problem)+"]"))
         StringSolver.solve(problem)
       case None => 
         hctx.reporter.ifDebug(printer => printer("No problem found"))
@@ -187,10 +159,6 @@ case object StringRender extends Rule("StringRender") {
     
     val wholeTemplates = JoinProgramSet.direct(funs, DirectProgramSet(template))
     
-    /*val newProgram = DefOps.addFunDefs(hctx.program, funDefs.values, hctx.sctx.functionContext)
-      val newExpr = (expr /: funDefs.values) {
-        case (e, fd) => LetDef(fd, e)
-      }*/
     def computeSolutions(funDefsBodies: Seq[(FunDef, Expr)], template: Expr): Stream[Assignment] = {
       val funDefs = for((funDef, body) <- funDefsBodies) yield  { funDef.body = Some(body); funDef }
       val newProgram = DefOps.addFunDefs(hctx.program, funDefs, hctx.sctx.functionContext)
@@ -244,6 +212,9 @@ case object StringRender extends Rule("StringRender") {
       case Some(_) => assignments
     }
   }
+
+  /** Assembles multiple MatchCase to a singleMatchExpr using the function definition fd */
+  private val mergeMatchCases = (fd: FunDef) => (cases: Seq[MatchCase]) => MatchExpr(Variable(fd.params(0).id), cases)
   
   /** 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.
@@ -255,6 +226,45 @@ case object StringRender extends Rule("StringRender") {
       adtToString: Map[DependentType, (FunDef, Stream[Expr])],
       inputs: Seq[Identifier])(implicit hctx: SearchContext): (Stream[Expr], Map[DependentType, (FunDef, Stream[Expr])]) = {
     
+    def extractCaseVariants(caseClassParent: TypeTree, cct: CaseClassType, assignments2: Map[DependentType, (FunDef, Stream[Expr])]) = cct match {
+      case CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2) =>
+        val typeMap = tparams.zip(tparams2).toMap
+        val fields = ccd.fields.map(vd => TypeOps.instantiateType(vd, typeMap).id )
+        val pattern = CaseClassPattern(None, ccd.typed(tparams2), fields.map(k => WildcardPattern(Some(k))))
+        val (rhs, assignments2tmp2) = createFunDefsTemplates(Some(caseClassParent), assignments2, fields) // Invoke functions for each of the fields.
+        val newCases = rhs.map(MatchCase(pattern, None, _))
+        (assignments2tmp2, newCases)
+    }
+    
+    /** Returns a constant pattern matching in which all classes are rendered using their proper name
+      * For example:
+      * {{{
+      * sealed abstract class Thread
+      * case class T1() extends Thread()
+      * case Class T2() extends Thread()
+      * }}}
+      * Will yield the following expression:
+      * {{{t match {
+      *   case T1() => "T1"
+      *   case T2() => "T2"
+      * }
+      * }}}
+      * 
+      * */
+    def constantPatternMatching(fd: FunDef, act: AbstractClassType): MatchExpr = {
+      val cases = (ListBuffer[MatchCase]() /: act.knownCCDescendants) {
+        case (acc, cct@CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2)) =>
+          val typeMap = tparams.zip(tparams2).toMap
+          val fields = ccd.fields.map(vd => TypeOps.instantiateType(vd, typeMap).id )
+          val pattern = CaseClassPattern(None, ccd.typed(tparams2), fields.map(k => WildcardPattern(Some(k))))
+          val rhs = StringLiteral(id.asString)
+          MatchCase(pattern, None, rhs)
+          acc += MatchCase(pattern, None, rhs)
+        case (acc, e) => hctx.reporter.fatalError("Could not handle this class definition for string rendering " + e)
+      }
+      mergeMatchCases(fd)(cases)
+    }
+    
     /* 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 */
@@ -268,7 +278,6 @@ case object StringRender extends Rule("StringRender") {
         val dependentType = DependentType(currentCaseClassParent, input.getType)
         assignments1.get(dependentType) match {
         case Some(fd) =>
-          // TODO : Maybe find other functions.
           gatherInputs(currentCaseClassParent, assignments1, q, result += Stream(functionInvocation(fd._1, Seq(Variable(input)))))
         case None => // No function can render the current type.
           input.getType match {
@@ -289,30 +298,29 @@ case object StringRender extends Rule("StringRender") {
               t.root match {
                 case act@AbstractClassType(acd@AbstractClassDef(id, tparams, parent), tps) =>
                   // Create a complete FunDef body with pattern matching
+                  
+                  val allKnownDescendantsAreCCAndHaveZeroArgs = act.knownCCDescendants.forall { x => x match {
+                    case CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2) => ccd.fields.isEmpty
+                    case _ => false
+                  }}
+                  
+                  //TODO: Test other templates not only with Wilcard patterns, but more cases options for non-recursive classes (e.g. Option, Boolean, Finite parameterless case classes.)
                   val (assignments3, cases) = ((assignments2, ListBuffer[Stream[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 ))
-                      val pattern = CaseClassPattern(None, ccd.typed(tparams2), fields.map(k => WildcardPattern(Some(k))))
-                      val (rhs, assignments2tmp2) = createFunDefsTemplates(Some(t), assignments2tmp, fields) // Invoke functions for each of the fields.
-                      (assignments2tmp2, acc += rhs.map(MatchCase(pattern, None, _)))
+                    case ((assignments2, acc), cct@CaseClassType(ccd@CaseClassDef(id, tparams, parent, isCaseObject), tparams2)) =>
+                      val (assignments2tmp2, newCases) = extractCaseVariants(t, cct, assignments2)
+                      (assignments2tmp2, acc += newCases)
                     case ((adtToString, acc), e) => hctx.reporter.fatalError("Could not handle this class definition for string rendering " + e)
                   }
-                  val recombine = (cases: Seq[MatchCase]) => MatchExpr(Variable(fd.params(0).id), cases)
-                  val allMatchExprs = JoinProgramSet(cases.map(DirectProgramSet(_)), recombine).programs
+                  
+                  val allMatchExprsEnd = JoinProgramSet(cases.map(DirectProgramSet(_)), mergeMatchCases(fd)).programs // General pattern match expressions
+                  val allMatchExprs = if(allKnownDescendantsAreCCAndHaveZeroArgs) {
+                    Stream(constantPatternMatching(fd, act)) ++ allMatchExprsEnd
+                  } else allMatchExprsEnd
                   val assignments4 = assignments3 + (dependentType -> (fd, allMatchExprs))
                   gatherInputs(currentCaseClassParent, assignments4, q, result += Stream(functionInvocation(fd, Seq(Variable(input)))))
                 case cct@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)
-                  val pattern = CaseClassPattern(None, ccd.typed(tparams2), fields.map(k => WildcardPattern(Some(k))))
-                  val (rhs, assignments3) = createFunDefsTemplates(Some(t), assignments2, fields) // Invoke functions for each of the fields.
-                  
-                  val recombine = (cases: Seq[MatchCase]) => MatchExpr(Variable(fd.params(0).id), cases)
-                  val cases = rhs.map(MatchCase(pattern, None, _))
-                  val allMatchExprs = cases.map(acase => recombine(Seq(acase)))
+                  val (assignments3, newCases) = extractCaseVariants(t, cct, assignments2)
+                  val allMatchExprs = newCases.map(acase => mergeMatchCases(fd)(Seq(acase)))
                   val assignments4 = assignments3 + (dependentType -> (fd, allMatchExprs))
                   gatherInputs(currentCaseClassParent, assignments4, q, result += Stream(functionInvocation(fd, Seq(Variable(input)))))
               }
@@ -352,26 +360,6 @@ case object StringRender extends Rule("StringRender") {
         val examplesFinder = new ExamplesFinder(hctx.context, hctx.program)
         val examples = examplesFinder.extractFromProblem(p)
         
-        /*  Possible strategies.
-          * If data structure is recursive on at least one variable (see how Induction works)
-          * then
-          *   - Inserts a new rec function deconstructing it and put it into the available preconditions to use.
-          * If the input is constant
-          *   - just a variable to compute a constant.
-          * If there are several variables
-          *   - All possible ways of linearly unbuilding the structure.
-          *   - Or maybe try to infer top-bottom the order of variables from examples?
-          * if a variable is a primitive
-          *   - Introduce an ordered string containing the content.
-          *   
-          * Once we have a skeleton, we run it on examples given and solve it.
-          * If there are multiple solutions, we generate one deeper example and ask the user which one should be better.
-          */
-        
-        
-        
-        // Returns expr and funDefs as templates.
-        
         val ruleInstantiations = ListBuffer[RuleInstantiation]()
         ruleInstantiations += RuleInstantiation("String conversion") {
           val (expr, funDefs) = createFunDefsTemplates(None, Map(), p.as)
@@ -381,10 +369,6 @@ case object StringRender extends Rule("StringRender") {
               ))
           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, expr, funDefs.values.toSeq)
         }