diff --git a/src/main/scala/leon/datagen/SolverDataGen.scala b/src/main/scala/leon/datagen/SolverDataGen.scala
new file mode 100644
index 0000000000000000000000000000000000000000..dfbf50aa68fee0beba9437dc16a2909aeb0c0c9f
--- /dev/null
+++ b/src/main/scala/leon/datagen/SolverDataGen.scala
@@ -0,0 +1,99 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package datagen
+
+import purescala.Expressions._
+import purescala.Types._
+import purescala.Definitions._
+import purescala.Common._
+import purescala.Constructors._
+import purescala.Extractors._
+import evaluators._
+import solvers._
+import solvers.combinators._
+import solvers.smtlib._
+import solvers.z3._
+import utils._
+
+
+class SolverDataGen(ctx: LeonContext, pgm: Program, sff: ((LeonContext, Program) => SolverFactory[Solver])) extends DataGenerator {
+  implicit val ctx0 = ctx
+
+  def generate(tpe: TypeTree): Iterator[Expr] = {
+    generateFor(Seq(FreshIdentifier("tmp", tpe)), BooleanLiteral(true), 20, 20).map(_.head)
+  }
+
+  def generateFor(ins: Seq[Identifier], satisfying: Expr, maxValid: Int, maxEnumerated: Int): Iterator[Seq[Expr]] = {
+    if (ins.isEmpty) {
+      Iterator.empty
+    } else {
+
+      var fds = Map[ClassDef, FunDef]()
+
+      def sizeFor(of: Expr): Expr = of.getType match {
+        case AbstractClassType(acd, tps) =>
+          val fd = fds.getOrElse(acd, {
+            val actDef = AbstractClassType(acd, acd.tparams.map(_.tp))
+
+            val e = FreshIdentifier("e", actDef)
+
+            val fd: FunDef = new FunDef(FreshIdentifier("sizeOf", Untyped),
+                                        acd.tparams,
+                                        IntegerType,
+                                        Seq(ValDef(e)))
+
+            fds += acd -> fd
+
+
+            fd.body = Some(MatchExpr(e.toVariable, 
+              actDef.knownCCDescendants.map { cct =>
+                val fields = cct.fieldsTypes.map ( t => FreshIdentifier("field", t))
+
+                val rhs = fields.foldLeft(InfiniteIntegerLiteral(1): Expr) { (i, f) =>
+                  plus(i, sizeFor(f.toVariable))
+                }
+
+                MatchCase(CaseClassPattern(None, cct, fields.map(f => WildcardPattern(Some(f)))), None, rhs)
+              }
+            ))
+
+            fd
+          })
+
+          FunctionInvocation(fd.typed(tps), Seq(of)) 
+
+        case tt @ TupleType(tps) =>
+          val exprs = for ((t,i) <- tps.zipWithIndex) yield {
+            sizeFor(tupleSelect(of, i+1, tps.size))
+          }
+
+          exprs.foldLeft(InfiniteIntegerLiteral(1): Expr)(plus _)
+
+        case _ =>
+          InfiniteIntegerLiteral(1)
+      }
+
+      val sizeOf = sizeFor(tupleWrap(ins.map(_.toVariable)))
+
+      // We need to synthesize a size function for ins' types.
+      val pgm1 = Program(pgm.units :+ UnitDef(FreshIdentifier("new"), List(
+        ModuleDef(FreshIdentifier("new"), fds.values.toSeq, false)
+      )))
+
+      val sf = sff(ctx, pgm1)
+      val modelEnum = new ModelEnumerator(ctx, pgm1, sf)
+
+      println("Generating for "+ins.map(_.getType.asString)+", satisfying "+satisfying.asString)
+
+      val enum = modelEnum.enumVarying(ins, satisfying, sizeOf, 5)
+
+      try {
+        enum.take(maxValid).map(model => ins.map(model)).toList.iterator
+      } finally {
+        enum.free()
+      }
+    }
+  }
+
+}
diff --git a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala
index f4bd40885d1b11d4d3924ad8c724874368b0dd8a..494f4b9b6fbe4b652455891d08986634d9d5ec91 100644
--- a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala
+++ b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala
@@ -17,7 +17,6 @@ import utils.Interruptible
 import evaluators._
 
 class UnrollingSolver(val context: LeonContext, program: Program, underlying: Solver) extends Solver with NaiveAssumptionSolver {
-
   val feelingLucky   = context.findOptionOrDefault(optFeelingLucky)
   val useCodeGen     = context.findOptionOrDefault(optUseCodeGen)
   val assumePreHolds = context.findOptionOrDefault(optAssumePre)
diff --git a/src/main/scala/leon/synthesis/ExamplesBank.scala b/src/main/scala/leon/synthesis/ExamplesBank.scala
index 90556b035df96c47cb1a4b9f3d277389e7010cf5..1f34fe87d8f48e9de1ff39e018bdcb0c63eaad59 100644
--- a/src/main/scala/leon/synthesis/ExamplesBank.scala
+++ b/src/main/scala/leon/synthesis/ExamplesBank.scala
@@ -88,14 +88,14 @@ case class ExamplesBank(valids: Seq[Example], invalids: Seq[Example]) {
     }
   }
 
-  def asString(title: String): String = {
+  def asString(title: String)(implicit ctx: LeonContext): String = {
     var tt = new Table(title)
 
     if (examples.nonEmpty) {
 
       val ow = examples.map {
         case InOutExample(_, out) => out.size
-        case _ => 0
+        case _ => 1
       }.max
 
       val iw = examples.map(_.ins.size).max
@@ -115,13 +115,13 @@ case class ExamplesBank(valids: Seq[Example], invalids: Seq[Example]) {
         for (t <- ts) {
           val os = t match {
             case InOutExample(_, outs) =>
-              outs.map(Cell(_))
+              outs.map(o => Cell(o.asString))
             case _ =>
               Seq(Cell("?", ow))
           }
 
           tt += Row(
-            t.ins.map(Cell(_)) ++ Seq(Cell("->")) ++ os
+            t.ins.map(i => Cell(i.asString)) ++ Seq(Cell("->")) ++ os
           )
         }
       }
diff --git a/src/main/scala/leon/synthesis/ExamplesFinder.scala b/src/main/scala/leon/synthesis/ExamplesFinder.scala
index 7877e9a34dbcee152f2a439665fa3d3697e64cff..9ef46ec5ac3b3aa3c97e315d9a6b755eba21b3bf 100644
--- a/src/main/scala/leon/synthesis/ExamplesFinder.scala
+++ b/src/main/scala/leon/synthesis/ExamplesFinder.scala
@@ -14,6 +14,9 @@ import evaluators._
 import grammars._
 import bonsai.enumerators._
 import codegen._
+import datagen._
+import solvers._
+import solvers.z3._
 
 class ExamplesFinder(ctx0: LeonContext, program: Program) {
 
@@ -104,30 +107,14 @@ class ExamplesFinder(ctx0: LeonContext, program: Program) {
   def generateForPC(ids: List[Identifier], pc: Expr, maxValid: Int = 400, maxEnumerated: Int = 1000): ExamplesBank = {
 
     val evaluator = new CodeGenEvaluator(ctx, program, CodeGenParams.default)
-    val enum      = new MemoizedEnumerator[TypeTree, Expr](ValueGrammar.getProductions)
+    val datagen   = new GrammarDataGen(evaluator, ValueGrammar)
+    val solverDataGen = new SolverDataGen(ctx, program, (ctx, pgm) => SolverFactory(() => new FairZ3Solver(ctx, pgm)))
 
-    val inputs = enum.iterator(tupleTypeWrap(ids map { _.getType})).map(unwrapTuple(_, ids.size))
+    val generatedExamples = datagen.generateFor(ids, pc, maxValid, maxEnumerated).map(InExample(_))
 
-    val filtering: Seq[Expr] => Boolean = pc match {
-      case BooleanLiteral(true) =>
-        _ => true
-      case pc =>
-        evaluator.compile(pc, ids) match {
-          case Some(evalFun) =>
-            { (e: Seq[Expr]) => evalFun(e).result == Some(BooleanLiteral(true)) }
-          case None =>
-            { _ => false }
-        }
-    }
-
-    val generatedTests = inputs
-      .take(maxEnumerated)
-      .filter(filtering)
-      .take(maxValid)
-      .map(InExample(_))
-      .toList
+    val solverExamples    = solverDataGen.generateFor(ids, pc, maxValid, maxEnumerated).map(InExample(_))
 
-    ExamplesBank(generatedTests, Nil)
+    ExamplesBank(generatedExamples.toSeq ++ solverExamples.toSeq, Nil)
   }
 
   private def extractTestsOf(e: Expr): Set[Map[Identifier, Expr]] = {
diff --git a/src/main/scala/leon/synthesis/SynthesisPhase.scala b/src/main/scala/leon/synthesis/SynthesisPhase.scala
index 2b770e0c5aeee2f8eeffaf49183d1374bf0538bb..ff822ac420879bf2808084d0672691d40f38608f 100644
--- a/src/main/scala/leon/synthesis/SynthesisPhase.scala
+++ b/src/main/scala/leon/synthesis/SynthesisPhase.scala
@@ -65,27 +65,25 @@ object SynthesisPhase extends LeonPhase[Program, Program] {
   def run(ctx: LeonContext)(program: Program): Program = {
     val options = processOptions(ctx)
 
-    def excludeByDefault(fd: FunDef): Boolean = fd.annotations contains "library"
+    def excludeByDefault(fd: FunDef): Boolean = { fd.annotations contains "library" }
 
     val fdFilter = {
       import OptionsHelpers._
-      val ciTofd = { (ci: ChooseInfo) => ci.fd }
-
-      filterInclusive(options.functions.map(fdMatcher(program)), Some(excludeByDefault _)) compose ciTofd
+      filterInclusive(options.functions.map(fdMatcher(program)), Some(excludeByDefault _))
     }
 
-    val chooses = ChooseInfo.extractFromProgram(ctx, program).filter(fdFilter)
+    val chooses = program.definedFunctions.filter(fdFilter).flatMap(ChooseInfo.extractFromFunction(ctx, program, _))
 
     var functions = Set[FunDef]()
 
-    chooses.foreach { ci =>
+    chooses.toSeq.sortBy(_.fd.id).foreach { ci =>
       val fd = ci.fd
 
       val synthesizer = new Synthesizer(ctx, program, ci, options)
+
       val (search, solutions) = synthesizer.validate(synthesizer.synthesize(), true)
 
       try {
-
         if (options.generateDerivationTrees) {
           val dot = new DotGenerator(search.g)
           dot.writeFile("derivation"+DotGenerator.nextId()+".dot")
diff --git a/src/main/scala/leon/synthesis/Synthesizer.scala b/src/main/scala/leon/synthesis/Synthesizer.scala
index 9659f2b7704520ef871211aa969d24d01fa0ece3..891ff435c98594c02a075e3a751fc2185213785a 100644
--- a/src/main/scala/leon/synthesis/Synthesizer.scala
+++ b/src/main/scala/leon/synthesis/Synthesizer.scala
@@ -24,6 +24,8 @@ class Synthesizer(val context : LeonContext,
 
   lazy val sctx = SynthesisContext.fromSynthesizer(this)
 
+  implicit val debugSection = leon.utils.DebugSectionSynthesis
+
   def getSearch: Search = {
     if (settings.manualSearch.isDefined) {
       new ManualSearch(context, ci, problem, settings.costModel, settings.manualSearch)
@@ -33,6 +35,11 @@ class Synthesizer(val context : LeonContext,
   }
 
   def synthesize(): (Search, Stream[Solution]) = {
+
+    reporter.ifDebug { printer => 
+      printer(problem.eb.asString("Tests available for synthesis")(context))
+    }
+
     val s = getSearch
 
     val t = context.timers.synthesis.search.start()
diff --git a/src/main/scala/leon/utils/FreeableIterator.scala b/src/main/scala/leon/utils/FreeableIterator.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a15922640077052f8164780df49d51866ac5fa4f
--- /dev/null
+++ b/src/main/scala/leon/utils/FreeableIterator.scala
@@ -0,0 +1,19 @@
+package leon
+package utils
+
+abstract class FreeableIterator[T] extends Iterator[T] {
+  private[this] var nextElem: Option[T] = None
+
+  def hasNext() = {
+    nextElem = computeNext()
+    nextElem.nonEmpty
+  }
+
+  def next() = {
+    nextElem.get
+  }
+
+  def computeNext(): Option[T]
+
+  def free()
+}
diff --git a/src/main/scala/leon/utils/ModelEnumerator.scala b/src/main/scala/leon/utils/ModelEnumerator.scala
index 2467a902137a37929580e33a04debbf78411069c..81bacf1623c37a83ed484004b9e84b4cbcbbb339 100644
--- a/src/main/scala/leon/utils/ModelEnumerator.scala
+++ b/src/main/scala/leon/utils/ModelEnumerator.scala
@@ -29,9 +29,8 @@ class ModelEnumerator(ctx: LeonContext, pgm: Program, sf: SolverFactory[Solver])
     enumVarying0(ids, satisfying, Some(measure), nPerMeasure)
   }
 
-  private[this] def enumVarying0(ids: Seq[Identifier], satisfying: Expr, measure: Option[Expr], nPerMeasure: Int = 1): Iterator[Map[Identifier, Expr]] = {
+  private[this] def enumVarying0(ids: Seq[Identifier], satisfying: Expr, measure: Option[Expr], nPerMeasure: Int = 1): FreeableIterator[Map[Identifier, Expr]] = {
     val s = sf.getNewSolver
-    reclaimPool ::= s
 
     s.assertCnstr(satisfying)
 
@@ -46,35 +45,40 @@ class ModelEnumerator(ctx: LeonContext, pgm: Program, sf: SolverFactory[Solver])
 
     var perMeasureRem = Map[Expr, Int]().withDefaultValue(nPerMeasure)
 
-    new Iterator[Map[Identifier, Expr]] {
-      def hasNext = {
-        s.check == Some(true)
-      }
-
-      def next() = {
-        val sm = s.getModel
-        val model = ids.map { id =>
-          id -> sm.getOrElse(id, simplestValue(id.getType))
-        }.toMap
+    new FreeableIterator[Map[Identifier, Expr]] {
+      def computeNext() = {
+        s.check match {
+          case Some(true) =>
+            val model = s.getModel
+            val idsModel = (ids.map { id =>
+              id -> model.getOrElse(id, simplestValue(id.getType))
+            }).toMap
 
+            // Vary the model
+            s.assertCnstr(not(andJoin(idsModel.toSeq.sortBy(_._1).map { case (k, v) => equality(k.toVariable, v) })))
 
-        // Vary the model
-        s.assertCnstr(not(andJoin(model.toSeq.sortBy(_._1).map { case (k,v) => equality(k.toVariable, v) })))
+            measure match {
+              case Some(ms) =>
+                val mValue = evaluator.eval(ms, idsModel).result.get
 
-        measure match {
-          case Some(ms) =>
-            val mValue = evaluator.eval(ms, model).result.get
+                perMeasureRem += (mValue -> (perMeasureRem(mValue) - 1))
 
-            perMeasureRem += (mValue -> (perMeasureRem(mValue) - 1))
+                if (perMeasureRem(mValue) <= 0) {
+                  s.assertCnstr(not(equality(m.toVariable, mValue)))
+                }
 
-            if (perMeasureRem(mValue) <= 0) {
-              s.assertCnstr(not(equality(m.toVariable, mValue)))
+              case None =>
             }
 
-          case None =>
+            Some(idsModel)
+
+          case _ =>
+            None
         }
+      }
 
-        model
+      def free() {
+        sf.reclaim(s)
       }
     }
   }
@@ -91,7 +95,7 @@ class ModelEnumerator(ctx: LeonContext, pgm: Program, sf: SolverFactory[Solver])
   case object Up   extends SearchDirection
   case object Down extends SearchDirection
 
-  private[this] def enumOptimizing(ids: Seq[Identifier], satisfying: Expr, measure: Expr, dir: SearchDirection): Iterator[Map[Identifier, Expr]] = {
+  private[this] def enumOptimizing(ids: Seq[Identifier], satisfying: Expr, measure: Expr, dir: SearchDirection): FreeableIterator[Map[Identifier, Expr]] = {
     assert(measure.getType == IntegerType)
 
     val s = sf.getNewSolver
@@ -126,73 +130,77 @@ class ModelEnumerator(ctx: LeonContext, pgm: Program, sf: SolverFactory[Solver])
       case _ => None
     }
 
-    def getNext(): Stream[Map[Identifier, Expr]] = {
-      if (rangeEmpty()) {
-        Stream.empty
-      } else {
-        // Assert a new pivot point
-        val thisTry = getPivot()
-        thisTry.foreach { t =>
-          s.push()
-          dir match {
-            case Up =>
-              s.assertCnstr(GreaterThan(mId.toVariable, InfiniteIntegerLiteral(t)))
-            case Down =>
-              s.assertCnstr(LessThan(mId.toVariable, InfiniteIntegerLiteral(t)))
-          }
-          t
-        }
-
-        s.check match {
-          case Some(true) =>
-            val sm = s.getModel
-            val m = ids.map { id =>
-              id -> sm.getOrElse(id, simplestValue(id.getType))
-            }.toMap
-
-            evaluator.eval(measure, m).result match {
-              case Some(InfiniteIntegerLiteral(measureVal)) =>
-                // Positive result
-                dir match {
-                  case Up   => lb = Some(measureVal)
-                  case Down => ub = Some(measureVal)
-                }
-
-                Stream.cons(m, getNext())
-
-              case _ =>
-                ctx.reporter.warning("Evaluator failed to evaluate measure!")
-                Stream.empty
-            }
-
-
-          case Some(false) =>
-            // Negative result
-            thisTry match {
-              case Some(t) =>
-                s.pop()
-
-                dir match {
-                  case Up   => ub = Some(t)
-                  case Down => lb = Some(t)
-                }
-                getNext()
-
-              case None =>
-                Stream.empty
+    new FreeableIterator[Map[Identifier, Expr]] {
+      def computeNext(): Option[Map[Identifier, Expr]] = {
+        if (rangeEmpty()) {
+          None
+        } else {
+          // Assert a new pivot point
+          val thisTry = getPivot().map { t =>
+            s.push()
+            dir match {
+              case Up =>
+                s.assertCnstr(GreaterThan(mId.toVariable, InfiniteIntegerLiteral(t)))
+              case Down =>
+                s.assertCnstr(LessThan(mId.toVariable, InfiniteIntegerLiteral(t)))
             }
+            t
+          }
 
-          case None =>
-            Stream.empty
+          s.check match {
+            case Some(true) =>
+              val sm = s.getModel
+              val m = (ids.map { id =>
+                id -> sm.getOrElse(id, simplestValue(id.getType))
+              }).toMap
+
+              evaluator.eval(measure, m).result match {
+                case Some(InfiniteIntegerLiteral(measureVal)) =>
+                  // Positive result
+                  dir match {
+                    case Up   => lb = Some(measureVal)
+                    case Down => ub = Some(measureVal)
+                  }
+
+                  Some(m)
+
+                case _ =>
+                  ctx.reporter.warning("Evaluator failed to evaluate measure!")
+                  None
+              }
+
+
+            case Some(false) =>
+              // Negative result
+              thisTry match {
+                case Some(t) =>
+                  s.pop()
+
+                  dir match {
+                    case Up   => ub = Some(t)
+                    case Down => lb = Some(t)
+                  }
+                  computeNext()
+
+                case None =>
+                  None
+              }
+
+            case None =>
+              None
+          }
         }
       }
-    }
 
-    getNext().iterator
+      def free() {
+        sf.reclaim(s)
+      }
+    }
   }
 
 
   def shutdown() = {
+    println("Terminating!")
     reclaimPool.foreach(sf.reclaim)
   }