diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala
index 69f95f45559737bfd895989aba010dbc0667bb3a..36ad6a2a2ad1779a3a3ba75fd35181a667987268 100644
--- a/src/main/scala/leon/codegen/CompilationUnit.scala
+++ b/src/main/scala/leon/codegen/CompilationUnit.scala
@@ -505,13 +505,11 @@ class CompilationUnit(val ctx: LeonContext,
       for {
         ch <- u.classHierarchies
         c  <- ch
-      } {
-        c match {
-          case acd: AbstractClassDef =>
-            compileAbstractClassDef(acd)
-          case ccd: CaseClassDef =>
-            compileCaseClassDef(ccd)
-        }
+      } c match {
+        case acd: AbstractClassDef =>
+          compileAbstractClassDef(acd)
+        case ccd: CaseClassDef =>
+          compileCaseClassDef(ccd)
       }
 
       for (m <- u.modules) compileModule(m)
diff --git a/src/main/scala/leon/datagen/VanuatooDataGen.scala b/src/main/scala/leon/datagen/VanuatooDataGen.scala
index e68e21f011f3936797157688901018923c2127bf..1a47924426ab214bd62e3e8f17a827a382801964 100644
--- a/src/main/scala/leon/datagen/VanuatooDataGen.scala
+++ b/src/main/scala/leon/datagen/VanuatooDataGen.scala
@@ -222,7 +222,7 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator {
       (AnyPattern[Expr, TypeTree](), false)
   }
 
-  type InstrumentedResult = (EvaluationResults.Result, Option[vanuatoo.Pattern[Expr, TypeTree]])
+  type InstrumentedResult = (EvaluationResults.Result[Expr], Option[vanuatoo.Pattern[Expr, TypeTree]])
 
   def compile(expression: Expr, argorder: Seq[Identifier]) : Option[Expr=>InstrumentedResult] = {
     import leon.codegen.runtime.LeonCodeGenRuntimeException
diff --git a/src/main/scala/leon/evaluators/AngelicEvaluator.scala b/src/main/scala/leon/evaluators/AngelicEvaluator.scala
new file mode 100644
index 0000000000000000000000000000000000000000..c1374b54f39117c4ddf09c8315df012cc5d6a989
--- /dev/null
+++ b/src/main/scala/leon/evaluators/AngelicEvaluator.scala
@@ -0,0 +1,26 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package evaluators
+
+import leon.solvers.Model
+import purescala.Definitions.Program
+import purescala.Expressions.Expr
+import EvaluationResults._
+
+class AngelicEvaluator(ctx: LeonContext, prog: Program, underlying: NDEvaluator)
+  extends Evaluator(ctx, prog)
+  with DeterministicEvaluator
+{
+  val description: String = "angelic evaluator"
+  val name: String = "Interpreter that returns the first solution of a non-deterministic program"
+
+  def eval(expr: Expr, model: Model): EvaluationResult = underlying.eval(expr, model) match {
+    case Successful(Stream(h, _*)) =>
+      Successful(h)
+    case Successful(Stream()) =>
+      RuntimeError("Underlying ND-evaluator returned no solution")
+    case other@(RuntimeError(_) | EvaluatorError(_)) =>
+      other.asInstanceOf[Result[Nothing]]
+  }
+}
diff --git a/src/main/scala/leon/evaluators/CodeGenEvaluator.scala b/src/main/scala/leon/evaluators/CodeGenEvaluator.scala
index 36cd9da0c7c35cfdc9d674162c3279d461afe813..a32bce7e5a1d286bc09a65e491f6b2bd33a3efde 100644
--- a/src/main/scala/leon/evaluators/CodeGenEvaluator.scala
+++ b/src/main/scala/leon/evaluators/CodeGenEvaluator.scala
@@ -6,12 +6,11 @@ package evaluators
 import purescala.Common._
 import purescala.Definitions._
 import purescala.Expressions._
-import purescala.Quantification._
 
 import codegen.CompilationUnit
 import codegen.CodeGenParams
 
-class CodeGenEvaluator(ctx: LeonContext, val unit : CompilationUnit) extends Evaluator(ctx, unit.program) {
+class CodeGenEvaluator(ctx: LeonContext, val unit : CompilationUnit) extends Evaluator(ctx, unit.program) with DeterministicEvaluator {
   val name = "codegen-eval"
   val description = "Evaluator for PureScala expressions based on compilation to JVM"
 
diff --git a/src/main/scala/leon/evaluators/ContextualEvaluator.scala b/src/main/scala/leon/evaluators/ContextualEvaluator.scala
new file mode 100644
index 0000000000000000000000000000000000000000..59e46a658eda6ddb73b6c62f86d10836d60e7dc1
--- /dev/null
+++ b/src/main/scala/leon/evaluators/ContextualEvaluator.scala
@@ -0,0 +1,114 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package evaluators
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.Types._
+import purescala.Constructors._
+import purescala.ExprOps._
+import purescala.Quantification._
+import solvers.{HenkinModel, Model}
+
+abstract class ContextualEvaluator(ctx: LeonContext, prog: Program, val maxSteps: Int) extends Evaluator(ctx, prog) with CEvalHelpers {
+
+  protected implicit val _ = ctx
+
+  type RC <: RecContext[RC]
+  type GC <: GlobalContext
+
+  def initRC(mappings: Map[Identifier, Expr]): RC
+  def initGC(model: solvers.Model): GC
+
+  case class EvalError(msg : String) extends Exception
+  case class RuntimeError(msg : String) extends Exception
+
+  // Used by leon-web, please do not delete
+  var lastGC: Option[GC] = None
+
+  def eval(ex: Expr, model: Model) = {
+    try {
+      lastGC = Some(initGC(model))
+      ctx.timers.evaluators.recursive.runtime.start()
+      EvaluationResults.Successful(e(ex)(initRC(model.toMap), lastGC.get))
+    } catch {
+      case so: StackOverflowError =>
+        EvaluationResults.EvaluatorError("Stack overflow")
+      case EvalError(msg) =>
+        EvaluationResults.EvaluatorError(msg)
+      case e @ RuntimeError(msg) =>
+        EvaluationResults.RuntimeError(msg)
+      case jre: java.lang.RuntimeException =>
+        EvaluationResults.RuntimeError(jre.getMessage)
+    } finally {
+      ctx.timers.evaluators.recursive.runtime.stop()
+    }
+  }
+
+  protected def e(expr: Expr)(implicit rctx: RC, gctx: GC): Value
+
+  def typeErrorMsg(tree : Expr, expected : TypeTree) : String = s"Type error : expected ${expected.asString}, found ${tree.asString}."
+
+}
+
+private[evaluators] trait CEvalHelpers {
+  this: ContextualEvaluator =>
+  
+  def forallInstantiations(gctx:GC, fargs: Seq[ValDef], conj: Expr) = {
+    
+    val henkinModel: HenkinModel = gctx.model match {
+      case hm: HenkinModel => hm
+      case _ => throw EvalError("Can't evaluate foralls without henkin model")
+    }
+    
+    val vars = variablesOf(conj)
+    val args = fargs.map(_.id).filter(vars)
+    val quantified = args.toSet
+
+    val matcherQuorums = extractQuorums(conj, quantified)
+
+    matcherQuorums.flatMap { quorum =>
+      var mappings: Seq[(Identifier, Int, Int)] = Seq.empty
+      var constraints: Seq[(Expr, Int, Int)] = Seq.empty
+
+      for (((expr, args), qidx) <- quorum.zipWithIndex) {
+        val (qmappings, qconstraints) = args.zipWithIndex.partition {
+          case (Variable(id), aidx) => quantified(id)
+          case _ => false
+        }
+
+        mappings ++= qmappings.map(p => (p._1.asInstanceOf[Variable].id, qidx, p._2))
+        constraints ++= qconstraints.map(p => (p._1, qidx, p._2))
+      }
+
+      var equalities: Seq[((Int, Int), (Int, Int))] = Seq.empty
+      val mapping = for ((id, es) <- mappings.groupBy(_._1)) yield {
+        val base :: others = es.toList.map(p => (p._2, p._3))
+        equalities ++= others.map(p => base -> p)
+        (id -> base)
+      }
+
+      val argSets = quorum.foldLeft[List[Seq[Seq[Expr]]]](List(Seq.empty)) {
+            case (acc, (expr, _)) => acc.flatMap(s => henkinModel.domain(expr).map(d => s :+ d))
+          }
+
+      argSets.map { args =>
+        val argMap: Map[(Int, Int), Expr] = args.zipWithIndex.flatMap {
+          case (a, qidx) => a.zipWithIndex.map { case (e, aidx) => (qidx, aidx) -> e }
+        }.toMap
+
+        val map = mapping.map { case (id, key) => id -> argMap(key) }
+        val enabler = andJoin(constraints.map {
+          case (e, qidx, aidx) => Equals(e, argMap(qidx -> aidx))
+        } ++ equalities.map {
+          case (k1, k2) => Equals(argMap(k1), argMap(k2))
+        })
+
+        (enabler, map)
+      }
+    }
+    
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/evaluators/DefaultEvaluator.scala b/src/main/scala/leon/evaluators/DefaultEvaluator.scala
index d732d48c0d40aaacf97cd8125b077c1cef397148..5c951eedc1a68943c42d9ee4f07f8d58e5f74bf9 100644
--- a/src/main/scala/leon/evaluators/DefaultEvaluator.scala
+++ b/src/main/scala/leon/evaluators/DefaultEvaluator.scala
@@ -1,21 +1,8 @@
-/* Copyright 2009-2015 EPFL, Lausanne */
-
 package leon
 package evaluators
 
-import purescala.Common._
-import purescala.Expressions._
-import purescala.Definitions._
-import purescala.Quantification._
-
-class DefaultEvaluator(ctx: LeonContext, prog: Program) extends RecursiveEvaluator(ctx, prog, 50000) {
-  type RC = DefaultRecContext
-  type GC = GlobalContext
-
-  def initRC(mappings: Map[Identifier, Expr]) = DefaultRecContext(mappings)
-  def initGC(model: solvers.Model) = new GlobalContext(model)
+import purescala.Definitions.Program
 
-  case class DefaultRecContext(mappings: Map[Identifier, Expr]) extends RecContext {
-    def newVars(news: Map[Identifier, Expr]) = copy(news)
-  }
-}
+class DefaultEvaluator(ctx: LeonContext, prog: Program)
+  extends RecursiveEvaluator(ctx, prog, 5000)
+  with DefaultContexts
\ No newline at end of file
diff --git a/src/main/scala/leon/evaluators/DualEvaluator.scala b/src/main/scala/leon/evaluators/DualEvaluator.scala
index cd843fbb145e4f9220b2e9fe3d91e30d8ff3c1be..05f60fd270f7d7ebc28b8627b703d23f30b6e214 100644
--- a/src/main/scala/leon/evaluators/DualEvaluator.scala
+++ b/src/main/scala/leon/evaluators/DualEvaluator.scala
@@ -6,19 +6,20 @@ package evaluators
 import purescala.Common._
 import purescala.Expressions._
 import purescala.Definitions._
-import purescala.Quantification._
 import purescala.Types._
 
 import codegen._
 
 class DualEvaluator(ctx: LeonContext, prog: Program, params: CodeGenParams) extends RecursiveEvaluator(ctx, prog, params.maxFunctionInvocations) {
-  type RC = DefaultRecContext
+
+  type RC = DualRecContext
   type GC = GlobalContext
 
+  def initGC(model: solvers.Model) = new GlobalContext(model, this.maxSteps)
+
   implicit val debugSection = utils.DebugSectionEvaluation
 
-  def initRC(mappings: Map[Identifier, Expr]) = DefaultRecContext(mappings)
-  def initGC(model: solvers.Model) = new GlobalContext(model)
+  def initRC(mappings: Map[Identifier, Expr]): RC = DualRecContext(mappings)
 
   var monitor = new runtime.LeonCodeGenRuntimeMonitor(params.maxFunctionInvocations)
 
@@ -26,7 +27,7 @@ class DualEvaluator(ctx: LeonContext, prog: Program, params: CodeGenParams) exte
 
   val isCompiled = prog.definedFunctions.toSet
 
-  case class DefaultRecContext(mappings: Map[Identifier, Expr], needJVMRef: Boolean = false) extends RecContext {
+  case class DualRecContext(mappings: Map[Identifier, Expr], needJVMRef: Boolean = false) extends RecContext[DualRecContext] {
     def newVars(news: Map[Identifier, Expr]) = copy(news)
   }
 
diff --git a/src/main/scala/leon/evaluators/EvaluationResults.scala b/src/main/scala/leon/evaluators/EvaluationResults.scala
index e37c61e3b73c8261fb9ca2456abd0fd8811b1877..b9cbecdde4cdd31b2b29dcb82fdd23c50aaf9a24 100644
--- a/src/main/scala/leon/evaluators/EvaluationResults.scala
+++ b/src/main/scala/leon/evaluators/EvaluationResults.scala
@@ -3,14 +3,12 @@
 package leon
 package evaluators
 
-import purescala.Expressions.Expr
-
 object EvaluationResults {
   /** Possible results of expression evaluation. */
-  sealed abstract class Result(val result : Option[Expr])
+  sealed abstract class Result[+A](val result : Option[A])
 
   /** Represents an evaluation that successfully derived the result `value`. */
-  case class Successful(value : Expr) extends Result(Some(value))
+  case class Successful[A](value : A) extends Result(Some(value))
 
   /** Represents an evaluation that led to an error (in the program). */
   case class RuntimeError(message : String) extends Result(None)
diff --git a/src/main/scala/leon/evaluators/Evaluator.scala b/src/main/scala/leon/evaluators/Evaluator.scala
index 9d14bd3dfcc0eb6f08f5273b98ac1448038b363e..9843da81d4187e468cf418c6100f2ce68f2dfefd 100644
--- a/src/main/scala/leon/evaluators/Evaluator.scala
+++ b/src/main/scala/leon/evaluators/Evaluator.scala
@@ -6,14 +6,18 @@ package evaluators
 import purescala.Common._
 import purescala.Definitions._
 import purescala.Expressions._
-import purescala.Quantification._
-import purescala.ExprOps._
 
 import solvers.Model
 
 abstract class Evaluator(val context: LeonContext, val program: Program) extends LeonComponent {
 
-  type EvaluationResult = EvaluationResults.Result
+  /** The type of value that this [[Evaluator]] calculates
+    * Typically, it will be [[Expr]] for deterministic evaluators, and
+    * [[Stream[Expr]]] for non-deterministic ones.
+    */
+  type Value
+
+  type EvaluationResult = EvaluationResults.Result[Value]
 
   /** Evaluates an expression, using [[Model.mapping]] as a valuation function for the free variables. */
   def eval(expr: Expr, model: Model) : EvaluationResult
@@ -29,7 +33,8 @@ abstract class Evaluator(val context: LeonContext, val program: Program) extends
   /** Compiles an expression into a function, where the arguments are the free variables in the expression.
     * `argorder` specifies in which order the arguments should be passed.
     * The default implementation uses the evaluation function each time, but evaluators are free
-    * to (and encouraged to) apply any specialization. */
+    * to (and encouraged to) apply any specialization.
+    */
   def compile(expr: Expr, args: Seq[Identifier]) : Option[Model => EvaluationResult] = Some(
     (model: Model) => if(args.exists(arg => !model.isDefinedAt(arg))) {
       EvaluationResults.EvaluatorError("Wrong number of arguments for evaluation.")
@@ -39,3 +44,10 @@ abstract class Evaluator(val context: LeonContext, val program: Program) extends
   )
 }
 
+trait DeterministicEvaluator extends Evaluator {
+  type Value = Expr
+}
+
+trait NDEvaluator extends Evaluator {
+  type Value = Stream[Expr]
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/evaluators/EvaluatorContexts.scala b/src/main/scala/leon/evaluators/EvaluatorContexts.scala
new file mode 100644
index 0000000000000000000000000000000000000000..776e389dd855736132d8c066fc837cc2b4bc34ad
--- /dev/null
+++ b/src/main/scala/leon/evaluators/EvaluatorContexts.scala
@@ -0,0 +1,39 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package evaluators
+
+import purescala.Common.Identifier
+import purescala.Expressions.Expr
+import solvers.Model
+
+trait RecContext[RC <: RecContext[RC]] {
+  def mappings: Map[Identifier, Expr]
+
+  def newVars(news: Map[Identifier, Expr]): RC
+
+  def withNewVar(id: Identifier, v: Expr): RC = {
+    newVars(mappings + (id -> v))
+  }
+
+  def withNewVars(news: Map[Identifier, Expr]): RC = {
+    newVars(mappings ++ news)
+  }
+}
+
+case class DefaultRecContext(mappings: Map[Identifier, Expr]) extends RecContext[DefaultRecContext] {
+  def newVars(news: Map[Identifier, Expr]) = copy(news)
+}
+
+class GlobalContext(val model: Model, val maxSteps: Int) {
+  var stepsLeft = maxSteps
+}
+
+protected[evaluators] trait DefaultContexts extends ContextualEvaluator {
+
+  final type RC = DefaultRecContext
+  final type GC = GlobalContext
+
+  def initRC(mappings: Map[Identifier, Expr]) = DefaultRecContext(mappings)
+  def initGC(model: solvers.Model) = new GlobalContext(model, this.maxSteps)
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
index fccda2aeabd69b72bef9690e8f55fa61a562911c..d1392d498b367475191ad8e42f82aa64778f5ccc 100644
--- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
@@ -3,78 +3,28 @@
 package leon
 package evaluators
 
+import leon.purescala.Constructors._
+import leon.purescala.ExprOps._
+import leon.purescala.Expressions.Pattern
+import leon.purescala.Extractors._
+import leon.purescala.Quantification._
+import leon.purescala.TypeOps._
+import leon.purescala.Types._
+import leon.solvers.{SolverFactory, HenkinModel}
 import purescala.Common._
-import purescala.Definitions._
-import purescala.ExprOps._
 import purescala.Expressions._
-import purescala.Types._
-import purescala.TypeOps.isSubtypeOf
-import purescala.Constructors._
-import purescala.Extractors._
-import purescala.Quantification._
-import solvers.{Model, HenkinModel}
-import solvers.SolverFactory
-
-abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int) extends Evaluator(ctx, prog) {
-  val name = "evaluator"
-  val description = "Recursive interpreter for PureScala expressions"
-
-  private implicit val _ = ctx
-
-  type RC <: RecContext
-  type GC <: GlobalContext
-
-  case class EvalError(msg : String) extends Exception
-  case class RuntimeError(msg : String) extends Exception
-
-  val scalaEv = new ScalacEvaluator(this, ctx, prog)
-
-  trait RecContext {
-    def mappings: Map[Identifier, Expr]
-
-    def newVars(news: Map[Identifier, Expr]): RC
-
-    def withNewVar(id: Identifier, v: Expr): RC = {
-      newVars(mappings + (id -> v))
-    }
+import purescala.Definitions._
 
-    def withNewVars(news: Map[Identifier, Expr]): RC = {
-      newVars(mappings ++ news)
-    }
-  }
+abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int)
+  extends ContextualEvaluator(ctx, prog, maxSteps)
+  with DeterministicEvaluator {
 
-  class GlobalContext(val model: Model) {
-    def maxSteps = RecursiveEvaluator.this.maxSteps
+  val name = "evaluator"
+  val description = "Recursive interpreter for PureScala expressions"
 
-    var stepsLeft = maxSteps
-  }
+  lazy val scalaEv = new ScalacEvaluator(this, ctx, prog)
 
-  def initRC(mappings: Map[Identifier, Expr]): RC
-  def initGC(model: Model): GC
-
-  // Used by leon-web, please do not delete
-  var lastGC: Option[GC] = None
-
-  private[this] var clpCache = Map[(Choose, Seq[Expr]), Expr]()
-
-  def eval(ex: Expr, model: Model) = {
-    try {
-      lastGC = Some(initGC(model))
-      ctx.timers.evaluators.recursive.runtime.start()
-      EvaluationResults.Successful(e(ex)(initRC(model.toMap), lastGC.get))
-    } catch {
-      case so: StackOverflowError =>
-        EvaluationResults.EvaluatorError("Stack overflow")
-      case EvalError(msg) =>
-        EvaluationResults.EvaluatorError(msg)
-      case e @ RuntimeError(msg) =>
-        EvaluationResults.RuntimeError(msg)
-      case jre: java.lang.RuntimeException =>
-        EvaluationResults.RuntimeError(jre.getMessage)
-    } finally {
-      ctx.timers.evaluators.recursive.runtime.stop()
-    }
-  }
+  protected var clpCache = Map[(Choose, Seq[Expr]), Expr]()
 
   protected def e(expr: Expr)(implicit rctx: RC, gctx: GC): Expr = expr match {
     case Variable(id) =>
@@ -195,9 +145,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
 
       callResult
 
-    case And(args) if args.isEmpty =>
-      BooleanLiteral(true)
-
+    case And(args) if args.isEmpty => BooleanLiteral(true)
     case And(args) =>
       e(args.head) match {
         case BooleanLiteral(false) => BooleanLiteral(false)
@@ -220,9 +168,10 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       }
 
     case Implies(l,r) =>
-      (e(l), e(r)) match {
-        case (BooleanLiteral(b1),BooleanLiteral(b2)) => BooleanLiteral(!b1 || b2)
-        case (le, re) => throw EvalError(typeErrorMsg(le, BooleanType))
+      e(l) match {
+        case BooleanLiteral(false) => BooleanLiteral(true)
+        case BooleanLiteral(true) => e(r)
+        case le => throw EvalError(typeErrorMsg(le, BooleanType))
       }
 
     case Equals(le,re) =>
@@ -273,7 +222,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
     case RealPlus(l, r) =>
       (e(l), e(r)) match {
         case (FractionalLiteral(ln, ld), FractionalLiteral(rn, rd)) =>
-          normalizeFraction(FractionalLiteral((ln * rd + rn * ld), (ld * rd)))
+          normalizeFraction(FractionalLiteral(ln * rd + rn * ld, ld * rd))
         case (le, re) => throw EvalError(typeErrorMsg(le, RealType))
       }
 
@@ -379,7 +328,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       (e(l), e(r)) match {
         case (FractionalLiteral(ln, ld), FractionalLiteral(rn, rd)) =>
           if (rn != 0)
-            normalizeFraction(FractionalLiteral((ln * rd), (ld * rn)))
+            normalizeFraction(FractionalLiteral(ln * rd, ld * rn))
           else throw RuntimeError("Division by 0.")
         case (le,re) => throw EvalError(typeErrorMsg(le, RealType))
       }
@@ -426,8 +375,8 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 < i2)
         case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 < i2)
         case (a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) =>
-           val FractionalLiteral(n, _) = e(RealMinus(a, b))
-           BooleanLiteral(n < 0)
+          val FractionalLiteral(n, _) = e(RealMinus(a, b))
+          BooleanLiteral(n < 0)
         case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 < c2)
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
@@ -437,8 +386,8 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 > i2)
         case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 > i2)
         case (a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) =>
-           val FractionalLiteral(n, _) = e(RealMinus(a, b))
-           BooleanLiteral(n > 0)
+          val FractionalLiteral(n, _) = e(RealMinus(a, b))
+          BooleanLiteral(n > 0)
         case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 > c2)
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
@@ -448,8 +397,8 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 <= i2)
         case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 <= i2)
         case (a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) =>
-           val FractionalLiteral(n, _) = e(RealMinus(a, b))
-           BooleanLiteral(n <= 0)
+          val FractionalLiteral(n, _) = e(RealMinus(a, b))
+          BooleanLiteral(n <= 0)
         case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 <= c2)
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
@@ -459,8 +408,8 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 >= i2)
         case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 >= i2)
         case (a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) =>
-           val FractionalLiteral(n, _) = e(RealMinus(a, b))
-           BooleanLiteral(n >= 0)
+          val FractionalLiteral(n, _) = e(RealMinus(a, b))
+          BooleanLiteral(n >= 0)
         case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 >= c2)
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
@@ -475,21 +424,19 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
 
     case SetIntersection(s1,s2) =>
       (e(s1), e(s2)) match {
-        case (f @ FiniteSet(els1, _), FiniteSet(els2, _)) => {
+        case (f @ FiniteSet(els1, _), FiniteSet(els2, _)) =>
           val newElems = els1 intersect els2
           val SetType(tpe) = f.getType
           FiniteSet(newElems, tpe)
-        }
         case (le,re) => throw EvalError(typeErrorMsg(le, s1.getType))
       }
 
     case SetDifference(s1,s2) =>
       (e(s1), e(s2)) match {
-        case (f @ FiniteSet(els1, _),FiniteSet(els2, _)) => {
+        case (f @ FiniteSet(els1, _),FiniteSet(els2, _)) =>
           val SetType(tpe) = f.getType
           val newElems = els1 -- els2
           FiniteSet(newElems, tpe)
-        }
         case (le,re) => throw EvalError(typeErrorMsg(le, s1.getType))
       }
 
@@ -520,59 +467,8 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       PartialLambda(mapping.map(p => p._1.map(e) -> e(p._2)), tpe)
 
     case f @ Forall(fargs, TopLevelAnds(conjuncts)) =>
-      val henkinModel: HenkinModel = gctx.model match {
-        case hm: HenkinModel => hm
-        case _ => throw EvalError("Can't evaluate foralls without henkin model")
-      }
-
       e(andJoin(for (conj <- conjuncts) yield {
-        val vars = variablesOf(conj)
-        val args = fargs.map(_.id).filter(vars)
-        val quantified = args.toSet
-
-        val matcherQuorums = extractQuorums(conj, quantified)
-
-        val instantiations = matcherQuorums.flatMap { quorum =>
-          var mappings: Seq[(Identifier, Int, Int)] = Seq.empty
-          var constraints: Seq[(Expr, Int, Int)] = Seq.empty
-
-          for (((expr, args), qidx) <- quorum.zipWithIndex) {
-            val (qmappings, qconstraints) = args.zipWithIndex.partition {
-              case (Variable(id),aidx) => quantified(id)
-              case _ => false
-            }
-
-            mappings ++= qmappings.map(p => (p._1.asInstanceOf[Variable].id, qidx, p._2))
-            constraints ++= qconstraints.map(p => (p._1, qidx, p._2))
-          }
-
-          var equalities: Seq[((Int, Int), (Int, Int))] = Seq.empty
-          val mapping = for ((id, es) <- mappings.groupBy(_._1)) yield {
-            val base :: others = es.toList.map(p => (p._2, p._3))
-            equalities ++= others.map(p => base -> p)
-            (id -> base)
-          }
-
-          val argSets = quorum.foldLeft[List[Seq[Seq[Expr]]]](List(Seq.empty)) {
-            case (acc, (expr, _)) => acc.flatMap(s => henkinModel.domain(expr).map(d => s :+ d))
-          }
-
-          argSets.map { args =>
-            val argMap: Map[(Int, Int), Expr] = args.zipWithIndex.flatMap {
-              case (a, qidx) => a.zipWithIndex.map { case (e, aidx) => (qidx, aidx) -> e }
-            }.toMap
-
-            val map = mapping.map { case (id, key) => id -> argMap(key) }
-            val enabler = andJoin(constraints.map {
-              case (e, qidx, aidx) => Equals(e, argMap(qidx -> aidx))
-            } ++ equalities.map {
-              case (k1, k2) => Equals(argMap(k1), argMap(k2))
-            })
-
-            (enabler, map)
-          }
-        }
-
+        val instantiations = forallInstantiations(gctx, fargs, conj)
         e(andJoin(instantiations.map { case (enabler, mapping) =>
           e(Implies(enabler, conj))(rctx.withNewVars(mapping), gctx)
         }))
@@ -631,9 +527,6 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       case (l, r) => throw EvalError(typeErrorMsg(l, m.getType))
     }
 
-    case gv: GenericValue =>
-      gv
-
     case p : Passes =>
       e(p.asConstraint)
 
@@ -702,6 +595,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
           throw RuntimeError("MatchError: "+rscrut.asString+" did not match any of the cases")
       }
 
+    case gl: GenericValue => gl
     case fl : FractionalLiteral => normalizeFraction(fl)
     case l : Literal[_] => l
 
@@ -784,6 +678,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
     }
   }
 
-  def typeErrorMsg(tree : Expr, expected : TypeTree) : String = s"Type error : expected ${expected.asString}, found ${tree.asString}."
+
 
 }
+
diff --git a/src/main/scala/leon/evaluators/ScalacEvaluator.scala b/src/main/scala/leon/evaluators/ScalacEvaluator.scala
index 7c4d8ee92ad2379987c0563e388d9d4fdfb777fc..63bb9f6fa1193dee0fbda7a69500bd4c2e9fa9b8 100644
--- a/src/main/scala/leon/evaluators/ScalacEvaluator.scala
+++ b/src/main/scala/leon/evaluators/ScalacEvaluator.scala
@@ -11,13 +11,8 @@ import purescala.Expressions._
 import purescala.Types._
 
 import java.io.File
-import java.nio.file.Files
-import java.net.{URL, URLClassLoader}
-import java.lang.reflect.{Constructor, Method}
-
-import frontends.scalac.FullScalaCompiler
-
-import scala.tools.nsc.{Settings=>NSCSettings,CompilerCommand}
+import java.net.URLClassLoader
+import java.lang.reflect.Constructor
 
 /**
  * Call scalac-compiled functions from within Leon
@@ -25,7 +20,7 @@ import scala.tools.nsc.{Settings=>NSCSettings,CompilerCommand}
  * Known limitations:
  *  - Multiple argument lists
  */
-class ScalacEvaluator(ev: Evaluator, ctx: LeonContext, pgm: Program) extends LeonComponent {
+class ScalacEvaluator(ev: DeterministicEvaluator, ctx: LeonContext, pgm: Program) extends LeonComponent {
   implicit val _: Program = pgm
 
   val name = "Evaluator of external functions"
@@ -300,11 +295,11 @@ class ScalacEvaluator(ev: Evaluator, ctx: LeonContext, pgm: Program) extends Leo
   /**
    * Black magic here we come!
    */
-  import org.objectweb.asm.ClassReader;
-  import org.objectweb.asm.ClassWriter;
-  import org.objectweb.asm.ClassVisitor;
-  import org.objectweb.asm.MethodVisitor;
-  import org.objectweb.asm.Opcodes;
+  import org.objectweb.asm.ClassReader
+  import org.objectweb.asm.ClassWriter
+  import org.objectweb.asm.ClassVisitor
+  import org.objectweb.asm.MethodVisitor
+  import org.objectweb.asm.Opcodes
 
   class InterceptingClassLoader(p: ClassLoader) extends ClassLoader(p) {
     import java.io._
@@ -320,24 +315,24 @@ class ScalacEvaluator(ev: Evaluator, ctx: LeonContext, pgm: Program) extends Leo
         if (!(toInstrument contains name)) {
           super.loadClass(name, resolve)
         } else {
-          val bs = new ByteArrayOutputStream();
-          val is = getResourceAsStream(name.replace('.', '/') + ".class");
-          val buf = new Array[Byte](512);
-          var len = is.read(buf);
+          val bs = new ByteArrayOutputStream()
+          val is = getResourceAsStream(name.replace('.', '/') + ".class")
+          val buf = new Array[Byte](512)
+          var len = is.read(buf)
           while (len  > 0) {
-            bs.write(buf, 0, len);
+            bs.write(buf, 0, len)
             len = is.read(buf)
           }
 
           // Transform bytecode
-          val cr = new ClassReader(bs.toByteArray());
-          val cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
-          val cv = new LeonCallsClassVisitor(cw, name, toInstrument(name));
-          cr.accept(cv, 0);
+          val cr = new ClassReader(bs.toByteArray())
+          val cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES)
+          val cv = new LeonCallsClassVisitor(cw, name, toInstrument(name))
+          cr.accept(cv, 0)
 
-          val res = cw.toByteArray();
+          val res = cw.toByteArray()
 
-          defineClass(name, res, 0, res.length);
+          defineClass(name, res, 0, res.length)
         }
       }
     }
@@ -451,7 +446,7 @@ class ScalacEvaluator(ev: Evaluator, ctx: LeonContext, pgm: Program) extends Leo
 
       unbox(fd.returnType)
       mv.visitInsn(returnOpCode(fd.returnType))
-      mv.visitEnd();
+      mv.visitEnd()
     }
   }
 }
diff --git a/src/main/scala/leon/evaluators/StreamEvaluator.scala b/src/main/scala/leon/evaluators/StreamEvaluator.scala
new file mode 100644
index 0000000000000000000000000000000000000000..5b387368ba259ac4cbeb2cf8f716feace7d370d9
--- /dev/null
+++ b/src/main/scala/leon/evaluators/StreamEvaluator.scala
@@ -0,0 +1,591 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package evaluators
+
+import purescala.Constructors._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.TypeOps._
+import purescala.Types._
+import purescala.Common.Identifier
+import purescala.Definitions.{TypedFunDef, Program}
+import purescala.Expressions._
+
+import leon.solvers.SolverFactory
+import leon.utils.StreamUtils.cartesianProduct
+
+class StreamEvaluator(ctx: LeonContext, prog: Program)
+  extends ContextualEvaluator(ctx, prog, 50000)
+  with NDEvaluator
+  with DefaultContexts
+{
+
+  val name = "ND-evaluator"
+  val description = "Non-deterministic interpreter for Leon programs that returns a Stream of solutions"
+
+  case class NDValue(tp: TypeTree) extends Expr with Terminal {
+    val getType = tp
+  }
+
+  protected[evaluators] def e(expr: Expr)(implicit rctx: RC, gctx: GC): Stream[Expr] = expr match {
+    case Variable(id) =>
+      rctx.mappings.get(id).toStream
+
+    case Application(caller, args) =>
+      for {
+        cl <- e(caller).distinct
+        newArgs <- cartesianProduct(args map e).distinct
+        res <- cl match {
+          case l @ Lambda(params, body) =>
+            val mapping = l.paramSubst(newArgs)
+            e(body)(rctx.withNewVars(mapping), gctx).distinct
+          case PartialLambda(mapping, _) =>
+            mapping.collectFirst {
+              case (pargs, res) if (newArgs zip pargs).forall { case (f, r) => f == r } =>
+                res
+            }.toStream
+          case _ =>
+            Stream()
+        }
+      } yield res
+
+    case Let(i,v,b) =>
+      for {
+        ev <- e(v).distinct
+        eb <- e(b)(rctx.withNewVar(i, ev), gctx).distinct
+      } yield eb
+
+    case Assert(cond, oerr, body) =>
+      e(IfExpr(Not(cond), Error(expr.getType, oerr.getOrElse("Assertion failed @"+expr.getPos)), body))
+
+    case en@Ensuring(body, post) =>
+      if ( exists{
+        case Hole(_,_) => true
+        case WithOracle(_,_) => true
+        case _ => false
+      }(en)) {
+        import synthesis.ConversionPhase.convert
+        e(convert(en, ctx))
+      } else {
+        e(en.toAssert)
+      }
+
+    case Error(tpe, desc) =>
+      Stream()
+
+    case NDValue(tp) =>
+      import grammars.ValueGrammar
+      ValueGrammar.getProductions(tp).toStream.map{ g => g.builder(Seq())}
+
+    case IfExpr(cond, thenn, elze) =>
+      e(cond).distinct.flatMap {
+        case BooleanLiteral(true) => e(thenn)
+        case BooleanLiteral(false) => e(elze)
+        case other => Stream()
+      }.distinct
+
+    case FunctionInvocation(TypedFunDef(fd, Seq(tp)), Seq(set)) if fd == program.library.setToList.get =>
+      val cons = program.library.Cons.get
+      val nil = CaseClass(CaseClassType(program.library.Nil.get, Seq(tp)), Seq())
+      def mkCons(h: Expr, t: Expr) = CaseClass(CaseClassType(cons, Seq(tp)), Seq(h,t))
+      e(set).distinct.collect {
+        case FiniteSet(els, _) =>
+          els.foldRight(nil)(mkCons)
+      }.distinct
+
+    case FunctionInvocation(tfd, args) =>
+      if (gctx.stepsLeft < 0) {
+        return Stream()
+      }
+      gctx.stepsLeft -= 1
+
+      for {
+        evArgs               <- cartesianProduct(args map e).distinct
+        // build a mapping for the function...
+        frame = rctx.withNewVars(tfd.paramSubst(evArgs))
+        BooleanLiteral(true) <- e(tfd.precOrTrue)(frame, gctx).distinct
+        body                 <- tfd.body.orElse(rctx.mappings.get(tfd.id)).toStream
+        callResult           <- e(body)(frame, gctx).distinct
+        BooleanLiteral(true) <- e(application(tfd.postOrTrue, Seq(callResult)))(frame, gctx).distinct
+      } yield callResult
+
+    case And(args) if args.isEmpty =>
+      Stream(BooleanLiteral(true))
+    case And(args) =>
+      e(args.head).distinct.flatMap {
+        case BooleanLiteral(false) => Stream(BooleanLiteral(false))
+        case BooleanLiteral(true) => e(andJoin(args.tail))
+        case other => Stream()
+      }
+
+    case Or(args) if args.isEmpty =>
+      Stream(BooleanLiteral(false))
+    case Or(args) =>
+      e(args.head).distinct.flatMap {
+        case BooleanLiteral(true) => Stream(BooleanLiteral(true))
+        case BooleanLiteral(false) => e(orJoin(args.tail))
+        case other => Stream()
+      }
+
+    case Implies(lhs, rhs) =>
+      e(Or(Not(lhs), rhs))
+
+    case l @ Lambda(_, _) =>
+      val (nl, structSubst) = normalizeStructure(l)
+      val mapping = variablesOf(l).map(id =>
+        structSubst(id) -> (e(Variable(id)) match {
+          case Stream(v) => v
+          case _ => return Stream()
+        })
+      ).toMap
+      Stream(replaceFromIDs(mapping, nl))
+
+    case PartialLambda(mapping, tpe) =>
+      def solveOne(pair: (Seq[Expr], Expr)) = {
+        val (args, res) = pair
+        for {
+          as <- cartesianProduct(args map e)
+          r  <- e(res)
+        } yield as -> r
+      }
+      cartesianProduct(mapping map solveOne) map (PartialLambda(_, tpe))
+
+    case f @ Forall(fargs, TopLevelAnds(conjuncts)) =>
+
+      def solveOne(conj: Expr) = {
+        val instantiations = forallInstantiations(gctx, fargs, conj)
+        for {
+          es <- cartesianProduct(instantiations.map { case (enabler, mapping) =>
+            e(Implies(enabler, conj))(rctx.withNewVars(mapping), gctx)
+          })
+          res <- e(andJoin(es))
+        } yield res
+      }
+
+      for {
+        conj <- cartesianProduct(conjuncts map solveOne)
+        res <- e(andJoin(conj))
+      } yield res
+
+    case p : Passes =>
+      e(p.asConstraint)
+
+    case choose: Choose =>
+
+      // TODO add memoization
+      implicit val debugSection = utils.DebugSectionSynthesis
+
+      val p = synthesis.Problem.fromSpec(choose.pred)
+
+      ctx.reporter.debug("Executing choose!")
+
+      val tStart = System.currentTimeMillis
+
+      val solverf = SolverFactory.getFromSettings(ctx, program)
+      val solver  = solverf.getNewSolver()
+
+      try {
+        val eqs = p.as.map {
+          case id =>
+            Equals(Variable(id), rctx.mappings(id))
+        }
+
+        val cnstr = andJoin(eqs ::: p.pc :: p.phi :: Nil)
+        solver.assertCnstr(cnstr)
+
+        def getSolution = try {
+          solver.check match {
+            case Some(true) =>
+              val model = solver.getModel
+
+              val valModel = valuateWithModel(model) _
+
+              val res = p.xs.map(valModel)
+              val leonRes = tupleWrap(res)
+              val total = System.currentTimeMillis - tStart
+
+              ctx.reporter.debug("Synthesis took " + total + "ms")
+              ctx.reporter.debug("Finished synthesis with " + leonRes.asString)
+
+              Some(leonRes)
+            case _ =>
+              None
+          }
+        } catch {
+          case _: Throwable => None
+        }
+
+        Stream.iterate(getSolution)(prev => {
+          val ensureDistinct = Not(Equals(tupleWrap(p.xs.map{ _.toVariable}), prev.get))
+          solver.assertCnstr(ensureDistinct)
+          val sol = getSolution
+          // Clean up when the stream ends
+          if (sol.isEmpty) {
+            solverf.reclaim(solver)
+            solverf.shutdown()
+          }
+          sol
+        }).takeWhile(_.isDefined).map(_.get)
+      } catch {
+        case e: Throwable =>
+          solverf.reclaim(solver)
+          solverf.shutdown()
+          Stream()
+      }
+
+    case MatchExpr(scrut, cases) =>
+
+      def matchesCase(scrut: Expr, caze: MatchCase)(implicit rctx: RC, gctx: GC): Stream[(MatchCase, Map[Identifier, Expr])] = {
+        import purescala.TypeOps.isSubtypeOf
+
+        def matchesPattern(pat: Pattern, expr: Expr): Stream[Map[Identifier, Expr]] = (pat, expr) match {
+          case (InstanceOfPattern(ob, pct), e) =>
+            (if (isSubtypeOf(e.getType, pct)) {
+              Some(obind(ob, e))
+            } else {
+              None
+            }).toStream
+          case (WildcardPattern(ob), e) =>
+            Stream(obind(ob, e))
+
+          case (CaseClassPattern(ob, pct, subs), CaseClass(ct, args)) =>
+            if (pct == ct) {
+              val subMaps = (subs zip args).map{ case (s, a) => matchesPattern(s, a) }
+              cartesianProduct(subMaps).map( _.flatten.toMap ++ obind(ob, expr))
+            } else {
+              Stream()
+            }
+          case (up @ UnapplyPattern(ob, _, subs), scrut) =>
+            e(FunctionInvocation(up.unapplyFun, Seq(scrut))) flatMap {
+              case CaseClass(CaseClassType(cd, _), Seq()) if cd == program.library.Nil.get =>
+                None
+              case CaseClass(CaseClassType(cd, _), Seq(arg)) if cd == program.library.Cons.get =>
+                val subMaps = subs zip unwrapTuple(arg, up.unapplyFun.returnType.isInstanceOf[TupleType]) map {
+                  case (s,a) => matchesPattern(s,a)
+                }
+                cartesianProduct(subMaps).map( _.flatten.toMap ++ obind(ob, expr))
+              case other =>
+                None
+            }
+          case (TuplePattern(ob, subs), Tuple(args)) =>
+            if (subs.size == args.size) {
+              val subMaps = (subs zip args).map { case (s, a) => matchesPattern(s, a) }
+              cartesianProduct(subMaps).map(_.flatten.toMap ++ obind(ob, expr))
+            } else Stream()
+          case (LiteralPattern(ob, l1) , l2 : Literal[_]) if l1 == l2 =>
+            Stream(obind(ob,l1))
+          case _ => Stream()
+        }
+
+        def obind(ob: Option[Identifier], e: Expr): Map[Identifier, Expr] = {
+          Map[Identifier, Expr]() ++ ob.map(id => id -> e)
+        }
+
+        caze match {
+          case SimpleCase(p, rhs) =>
+            matchesPattern(p, scrut).map(r =>
+              (caze, r)
+            )
+
+          case GuardedCase(p, g, rhs) =>
+            for {
+              r <- matchesPattern(p, scrut)
+              BooleanLiteral(true) <- e(g)(rctx.withNewVars(r), gctx)
+            } yield (caze, r)
+        }
+      }
+
+      for {
+        rscrut  <- e(scrut)
+        cs      <- cases.toStream.map(c => matchesCase(rscrut, c)).find(_.nonEmpty).toStream
+        (c, mp) <- cs
+        res     <- e(c.rhs)(rctx.withNewVars(mp), gctx)
+      } yield res
+
+    case Operator(es, _) =>
+      cartesianProduct(es map e) flatMap { es =>
+        try {
+          Some(step(expr, es))
+        } catch {
+          case _: RuntimeError =>
+            // EvalErrors stop the computation alltogether
+            None
+        }
+      }
+
+    case other =>
+      context.reporter.error(other.getPos, "Error: don't know how to handle " + other.asString + " in Evaluator ("+other.getClass+").")
+      Stream()
+  }
+
+
+  protected def step(expr: Expr, subs: Seq[Expr])(implicit rctx: RC, gctx: GC): Expr = (expr, subs) match {
+    case (Tuple(_), ts) =>
+      Tuple(ts)
+
+    case (TupleSelect(_, i), rs) =>
+      rs(i - 1)
+
+    case (Assert(_, oerr, _), Seq(BooleanLiteral(cond), body)) =>
+      if (cond) body
+      else throw RuntimeError(oerr.getOrElse("Assertion failed @" + expr.getPos))
+
+    case (Error(_, desc), _) =>
+      throw RuntimeError("Error reached in evaluation: " + desc)
+
+    case (FunctionInvocation(TypedFunDef(fd, Seq(tp)), _), Seq(FiniteSet(els, _))) if fd == program.library.setToList.get =>
+      val cons = program.library.Cons.get
+      val nil = CaseClass(CaseClassType(program.library.Nil.get, Seq(tp)), Seq())
+      def mkCons(h: Expr, t: Expr) = CaseClass(CaseClassType(cons, Seq(tp)), Seq(h, t))
+      els.foldRight(nil)(mkCons)
+
+    case (Not(_), Seq(BooleanLiteral(arg))) =>
+      BooleanLiteral(!arg)
+
+    case (Implies(_, _) Seq (BooleanLiteral(b1), BooleanLiteral(b2))) =>
+      BooleanLiteral(!b1 || b2)
+
+    case (Equals(_, _), Seq(lv, rv)) =>
+      (lv, rv) match {
+        case (FiniteSet(el1, _), FiniteSet(el2, _)) => BooleanLiteral(el1 == el2)
+        case (FiniteMap(el1, _, _), FiniteMap(el2, _, _)) => BooleanLiteral(el1.toSet == el2.toSet)
+        case (PartialLambda(m1, _), PartialLambda(m2, _)) => BooleanLiteral(m1.toSet == m2.toSet)
+        case _ => BooleanLiteral(lv == rv)
+      }
+
+    case (CaseClass(cd, _), args) =>
+      CaseClass(cd, args)
+
+    case (AsInstanceOf(_, ct), Seq(ce)) =>
+      if (isSubtypeOf(ce.getType, ct)) {
+        ce
+      } else {
+        throw RuntimeError("Cast error: cannot cast " + ce.asString + " to " + ct.asString)
+      }
+
+    case (IsInstanceOf(_, ct), Seq(ce)) =>
+      BooleanLiteral(isSubtypeOf(ce.getType, ct))
+
+    case (CaseClassSelector(ct1, _, sel), Seq(CaseClass(ct2, args))) if ct1 == ct2 =>
+      args(ct1.classDef.selectorID2Index(sel))
+
+    case (Plus(_, _), Seq(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2))) =>
+      InfiniteIntegerLiteral(i1 + i2)
+
+    case (Minus(_, _), Seq(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2))) =>
+      InfiniteIntegerLiteral(i1 - i2)
+
+    case (Times(_, _), Seq(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2))) =>
+      InfiniteIntegerLiteral(i1 * i2)
+
+    case (Division(_, _), Seq(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2))) =>
+      if (i2 != BigInt(0)) InfiniteIntegerLiteral(i1 / i2)
+      else throw RuntimeError("Division by 0.")
+
+    case (Remainder(_, _), Seq(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2))) =>
+      if (i2 != BigInt(0)) InfiniteIntegerLiteral(i1 % i2)
+      else throw RuntimeError("Remainder of division by 0.")
+
+    case (Modulo(_, _), Seq(InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2))) =>
+      if (i2 < 0)
+        InfiniteIntegerLiteral(i1 mod (-i2))
+      else if (i2 != BigInt(0))
+        InfiniteIntegerLiteral(i1 mod i2)
+      else
+        throw RuntimeError("Modulo of division by 0.")
+
+    case (UMinus(_), Seq(InfiniteIntegerLiteral(i))) =>
+      InfiniteIntegerLiteral(-i)
+
+    case (RealPlus(_, _), Seq(FractionalLiteral(ln, ld), FractionalLiteral(rn, rd))) =>
+      normalizeFraction(FractionalLiteral(ln * rd + rn * ld, ld * rd))
+
+    case (RealMinus(_, _), Seq(FractionalLiteral(ln, ld), FractionalLiteral(rn, rd))) =>
+      normalizeFraction(FractionalLiteral(ln * rd - rn * ld, ld * rd))
+
+    case (RealTimes(_, _), Seq(FractionalLiteral(ln, ld), FractionalLiteral(rn, rd))) =>
+      normalizeFraction(FractionalLiteral(ln * rn, ld * rd))
+
+    case (RealDivision(_, _), Seq(FractionalLiteral(ln, ld), FractionalLiteral(rn, rd))) =>
+      if (rn != 0) normalizeFraction(FractionalLiteral(ln * rd, ld * rn))
+      else throw RuntimeError("Division by 0.")
+
+    case (BVPlus(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      IntLiteral(i1 + i2)
+
+    case (BVMinus(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      IntLiteral(i1 - i2)
+
+    case (BVUMinus(_), Seq(IntLiteral(i))) =>
+      IntLiteral(-i)
+
+    case (RealUMinus(_), Seq(FractionalLiteral(n, d))) =>
+      FractionalLiteral(-n, d)
+
+    case (BVNot(_), Seq(IntLiteral(i))) =>
+      IntLiteral(~i)
+
+    case (BVTimes(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      IntLiteral(i1 * i2)
+
+    case (BVDivision(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      if (i2 != 0) IntLiteral(i1 / i2)
+      else throw RuntimeError("Division by 0.")
+
+    case (BVRemainder(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      if (i2 != 0) IntLiteral(i1 % i2)
+      else throw RuntimeError("Remainder of division by 0.")
+
+    case (BVAnd(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      IntLiteral(i1 & i2)
+
+    case (BVOr(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      IntLiteral(i1 | i2)
+
+    case (BVXOr(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      IntLiteral(i1 ^ i2)
+
+    case (BVShiftLeft(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      IntLiteral(i1 << i2)
+
+    case (BVAShiftRight(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      IntLiteral(i1 >> i2)
+
+    case (BVLShiftRight(_, _), Seq(IntLiteral(i1), IntLiteral(i2))) =>
+      IntLiteral(i1 >>> i2)
+
+    case (LessThan(_, _), Seq(el, er)) =>
+      (el, er) match {
+        case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 < i2)
+        case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 < i2)
+        case (a@FractionalLiteral(_, _), b@FractionalLiteral(_, _)) =>
+          val FractionalLiteral(n, _) = e(RealMinus(a, b)).head
+          BooleanLiteral(n < 0)
+        case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 < c2)
+        case (le, re) => throw EvalError(typeErrorMsg(le, Int32Type))
+      }
+
+    case (GreaterThan(_, _), Seq(el, er)) =>
+      (el, er) match {
+        case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 > i2)
+        case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 > i2)
+        case (a@FractionalLiteral(_, _), b@FractionalLiteral(_, _)) =>
+          val FractionalLiteral(n, _) = e(RealMinus(a, b)).head
+          BooleanLiteral(n > 0)
+        case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 > c2)
+        case (le, re) => throw EvalError(typeErrorMsg(le, Int32Type))
+      }
+
+    case (LessEquals(_, _), Seq(el, er)) =>
+      (el, er) match {
+        case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 <= i2)
+        case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 <= i2)
+        case (a@FractionalLiteral(_, _), b@FractionalLiteral(_, _)) =>
+          val FractionalLiteral(n, _) = e(RealMinus(a, b)).head
+          BooleanLiteral(n <= 0)
+        case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 <= c2)
+        case (le, re) => throw EvalError(typeErrorMsg(le, Int32Type))
+      }
+
+    case (GreaterEquals(_, _), Seq(el, er)) =>
+      (el, er) match {
+        case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 >= i2)
+        case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 >= i2)
+        case (a@FractionalLiteral(_, _), b@FractionalLiteral(_, _)) =>
+          val FractionalLiteral(n, _) = e(RealMinus(a, b)).head
+          BooleanLiteral(n >= 0)
+        case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 >= c2)
+        case (le, re) => throw EvalError(typeErrorMsg(le, Int32Type))
+      }
+
+    case (IsTyped(su@SetUnion(s1, s2), tpe), Seq(
+      IsTyped(FiniteSet(els1, _), SetType(tpe1)),
+      IsTyped(FiniteSet(els2, _), SetType(tpe2))
+    )) =>
+      FiniteSet(
+        els1 ++ els2,
+        leastUpperBound(tpe1, tpe2).getOrElse(throw EvalError(typeErrorMsg(su, tpe)))
+      )
+
+    case (IsTyped(su@SetIntersection(s1, s2), tpe), Seq(
+      IsTyped(FiniteSet(els1, _), SetType(tpe1)),
+      IsTyped(FiniteSet(els2, _), SetType(tpe2))
+    )) =>
+      FiniteSet(
+        els1 & els2,
+        leastUpperBound(tpe1, tpe2).getOrElse(throw EvalError(typeErrorMsg(su, tpe)))
+      )
+
+    case (IsTyped(su@SetDifference(s1, s2), tpe), Seq(
+      IsTyped(FiniteSet(els1, _), SetType(tpe1)),
+      IsTyped(FiniteSet(els2, _), SetType(tpe2))
+    )) =>
+      FiniteSet(
+        els1 -- els2,
+        leastUpperBound(tpe1, tpe2).getOrElse(throw EvalError(typeErrorMsg(su, tpe)))
+      )
+
+    case (ElementOfSet(_, _), Seq(e, FiniteSet(els, _))) =>
+      BooleanLiteral(els.contains(e))
+
+    case (SubsetOf(_, _), Seq(FiniteSet(els1, _), FiniteSet(els2, _))) =>
+      BooleanLiteral(els1.subsetOf(els2))
+
+    case (SetCardinality(_), Seq(FiniteSet(els, _))) =>
+      IntLiteral(els.size)
+
+    case (FiniteSet(_, base), els) =>
+      FiniteSet(els.toSet, base)
+
+    case (ArrayLength(_), Seq(FiniteArray(_, _, IntLiteral(length)))) =>
+      IntLiteral(length)
+
+    case (ArrayUpdated(_, _, _), Seq(
+      IsTyped(FiniteArray(elems, default, length), ArrayType(tp)),
+      IntLiteral(i),
+      v
+    )) =>
+      finiteArray(elems.updated(i, v), default map {(_, length)}, tp)
+
+    case (ArraySelect(_, _), Seq(fa@FiniteArray(elems, default, IntLiteral(length)), IntLiteral(index))) =>
+      elems
+        .get(index)
+        .orElse(if (index >= 0 && index < length) default else None)
+        .getOrElse(throw RuntimeError(s"Array out of bounds error during evaluation:\n array = $fa, index = $index"))
+
+    case (fa@FiniteArray(_, _, _), subs) =>
+      val Operator(_, builder) = fa
+      builder(subs)
+
+    case (fm@FiniteMap(_, _, _), subs) =>
+      val Operator(_, builder) = fm
+      builder(subs)
+
+    case (g@MapApply(_, _), Seq(FiniteMap(m, _, _), k)) =>
+      m.getOrElse(k, throw RuntimeError("Key not found: " + k.asString))
+
+    case (u@IsTyped(MapUnion(_, _), MapType(kT, vT)), Seq(FiniteMap(m1, _, _), FiniteMap(m2, _, _))) =>
+      FiniteMap(m1 ++ m2, kT, vT)
+
+    case (i@MapIsDefinedAt(_, _), Seq(FiniteMap(elems, _, _), k)) =>
+      BooleanLiteral(elems.contains(k))
+
+    case (gv: GenericValue, Seq()) =>
+      gv
+
+    case (fl: FractionalLiteral, Seq()) =>
+      normalizeFraction(fl)
+
+    case (l: Literal[_], Seq()) =>
+      l
+
+    case (other, _) =>
+      context.reporter.error(other.getPos, "Error: don't know how to handle " + other.asString + " in Evaluator ("+other.getClass+").")
+      throw EvalError("Unhandled case in Evaluator: " + other.asString)
+
+  }
+
+
+}
+
diff --git a/src/main/scala/leon/evaluators/TracingEvaluator.scala b/src/main/scala/leon/evaluators/TracingEvaluator.scala
index ec977763f3da3f583d225cbdde8dd98aa33f312b..ad2d5723e7f9744e2e8e41e227055dc91fec9b34 100644
--- a/src/main/scala/leon/evaluators/TracingEvaluator.scala
+++ b/src/main/scala/leon/evaluators/TracingEvaluator.scala
@@ -6,7 +6,6 @@ package evaluators
 import purescala.Common._
 import purescala.Expressions._
 import purescala.Definitions._
-import purescala.Quantification._
 import purescala.Types._
 
 class TracingEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int = 1000) extends RecursiveEvaluator(ctx, prog, maxSteps) {
@@ -17,9 +16,9 @@ class TracingEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int = 1000) ex
 
   def initGC(model: solvers.Model) = new TracingGlobalContext(Nil, model)
 
-  class TracingGlobalContext(var values: List[(Tree, Expr)], model: solvers.Model) extends GlobalContext(model)
+  class TracingGlobalContext(var values: List[(Tree, Expr)], model: solvers.Model) extends GlobalContext(model, maxSteps)
 
-  case class TracingRecContext(mappings: Map[Identifier, Expr], tracingFrames: Int) extends RecContext {
+  case class TracingRecContext(mappings: Map[Identifier, Expr], tracingFrames: Int) extends RecContext[TracingRecContext] {
     def newVars(news: Map[Identifier, Expr]) = copy(mappings = news)
   }
 
diff --git a/src/main/scala/leon/purescala/Definitions.scala b/src/main/scala/leon/purescala/Definitions.scala
index cc1b716fe11ada534ebc7725f6743b3976499c6e..103ed1bee94c2203d288848184d62fd6b2d2ce09 100644
--- a/src/main/scala/leon/purescala/Definitions.scala
+++ b/src/main/scala/leon/purescala/Definitions.scala
@@ -543,6 +543,7 @@ object Definitions {
     def precondition  = fd.precondition map cached
     def precOrTrue    = cached(fd.precOrTrue)
     def postcondition = fd.postcondition map cached
+    def postOrTrue    = cached(fd.postOrTrue)
 
     def hasImplementation = body.isDefined
     def hasBody           = hasImplementation
diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala
index c8cf8f118ac17ca29272f2941f71b8d99a99af9c..7f7359795d4729400fa3a4aa74ae8b7325f17d29 100644
--- a/src/main/scala/leon/purescala/Extractors.scala
+++ b/src/main/scala/leon/purescala/Extractors.scala
@@ -47,7 +47,7 @@ object Extractors {
         val builder = (as: Seq[Expr]) => {
           def rec(kvs: Seq[Expr]): Seq[(Seq[Expr], Expr)] = kvs match {
             case seq if seq.size >= sze =>
-              val ((args :+ res), rest) = seq.splitAt(sze)
+              val (args :+ res, rest) = seq.splitAt(sze)
               (args -> res) +: rec(rest)
             case Seq() => Seq.empty
             case _ => sys.error("unexpected number of key/value expressions")
@@ -195,10 +195,7 @@ object Extractors {
         { case Seq(c, t, e) => IfExpr(c, t, e) }
       ))
       case MatchExpr(scrut, cases) => Some((
-        scrut +: cases.flatMap {
-          case SimpleCase(_, e) => Seq(e)
-          case GuardedCase(_, e1, e2) => Seq(e1, e2)
-        },
+        scrut +: cases.flatMap { _.expressions },
         (es: Seq[Expr]) => {
           var i = 1
           val newcases = for (caze <- cases) yield caze match {
@@ -210,9 +207,8 @@ object Extractors {
         }
       ))
       case Passes(in, out, cases) => Some((
-        in +: out +: cases.flatMap {
-          _.expressions
-        }, {
+        in +: out +: cases.flatMap { _.expressions },
+        {
           case Seq(in, out, es@_*) => {
             var i = 0
             val newcases = for (caze <- cases) yield caze match {
diff --git a/src/main/scala/leon/repair/RepairNDEvaluator.scala b/src/main/scala/leon/repair/RepairNDEvaluator.scala
index d3e0df1746b1fb0cb12c95764362a58b2215bd5b..e9d63b1b96db406da3aa34e80c735b7bbbe9cdf6 100644
--- a/src/main/scala/leon/repair/RepairNDEvaluator.scala
+++ b/src/main/scala/leon/repair/RepairNDEvaluator.scala
@@ -16,7 +16,7 @@ import scala.util.Try
 // If a function invocation fails or violates a postcondition for cond, 
 // it backtracks and gets executed again for !cond
 class RepairNDEvaluator(ctx: LeonContext, prog: Program, fd : FunDef, cond: Expr) extends DefaultEvaluator(ctx, prog) {
-    
+
   override def e(expr: Expr)(implicit rctx: RC, gctx: GC): Expr = expr match {
  
     case FunctionInvocation(tfd, args) if tfd.fd == fd =>
diff --git a/src/main/scala/leon/repair/RepairTrackingEvaluator.scala b/src/main/scala/leon/repair/RepairTrackingEvaluator.scala
index 664b9e3b26f0229cfb0ec12cf52bef7a53d6aa6a..2846bc4848bd12147a68f7c03a3b7319f8aae88c 100644
--- a/src/main/scala/leon/repair/RepairTrackingEvaluator.scala
+++ b/src/main/scala/leon/repair/RepairTrackingEvaluator.scala
@@ -8,9 +8,8 @@ import leon.purescala.Common._
 import leon.purescala.Expressions._
 import leon.purescala.Types._
 import leon.purescala.Definitions._
-import leon.purescala.Quantification._
 import leon.LeonContext
-import leon.evaluators.RecursiveEvaluator
+import leon.evaluators._
 
 /** 
  *  This evaluator tracks all dependencies between function calls (.fullCallGraph)
@@ -20,9 +19,9 @@ import leon.evaluators.RecursiveEvaluator
 class RepairTrackingEvaluator(ctx: LeonContext, prog: Program) extends RecursiveEvaluator(ctx, prog, 50000) {
   type RC = CollectingRecContext
   type GC = GlobalContext
-  
+
   def initRC(mappings: Map[Identifier, Expr]) = CollectingRecContext(mappings, None)
-  def initGC(model: leon.solvers.Model) = new GlobalContext(model)
+  def initGC(model: leon.solvers.Model) = new GlobalContext(model, maxSteps)
   
   type FI = (FunDef, Seq[Expr])
   
@@ -46,7 +45,7 @@ class RepairTrackingEvaluator(ctx: LeonContext, prog: Program) extends Recursive
   private def registerFailed    (fi : FI) = fiStatus_ update (fi, false)
   def fiStatus = fiStatus_.toMap.withDefaultValue(false)
   
-  case class CollectingRecContext(mappings: Map[Identifier, Expr], lastFI : Option[FI]) extends RecContext {
+  case class CollectingRecContext(mappings: Map[Identifier, Expr], lastFI : Option[FI]) extends RecContext[CollectingRecContext] {
     def newVars(news: Map[Identifier, Expr]) = copy(news, lastFI)
     def withLastFI(fi : FI) = copy(lastFI = Some(fi))
   }
diff --git a/src/main/scala/leon/repair/rules/Focus.scala b/src/main/scala/leon/repair/rules/Focus.scala
index 8c1694dbda953071d51226782965e488b406b607..d6b4d874ffc1063dc2288f39af3f862a35542371 100644
--- a/src/main/scala/leon/repair/rules/Focus.scala
+++ b/src/main/scala/leon/repair/rules/Focus.scala
@@ -75,9 +75,7 @@ case object Focus extends PreprocessingRule("Focus") {
 
     val fdSpec = {
       val id = FreshIdentifier("res", fd.returnType)
-      Let(id, fd.body.get,
-        fd.postcondition.map(l => application(l, Seq(id.toVariable))).getOrElse(BooleanLiteral(true))
-      )
+      Let(id, fd.body.get, application(fd.postOrTrue, Seq(id.toVariable)))
     }
 
     val TopLevelAnds(clauses) = p.ws
diff --git a/src/main/scala/leon/solvers/EvaluatingSolver.scala b/src/main/scala/leon/solvers/EvaluatingSolver.scala
index 3463235c918d4872b0136d84b54f44e11b36cd69..75dcb5631dd0d57e7bbef24b9ce6d5d461d902c5 100644
--- a/src/main/scala/leon/solvers/EvaluatingSolver.scala
+++ b/src/main/scala/leon/solvers/EvaluatingSolver.scala
@@ -10,7 +10,7 @@ trait EvaluatingSolver extends Solver {
 
   val useCodeGen: Boolean
 
-  lazy val evaluator: Evaluator =
+  lazy val evaluator: DeterministicEvaluator =
     if (useCodeGen) {
       new CodeGenEvaluator(context, program)
     } else {
diff --git a/src/main/scala/leon/synthesis/ConversionPhase.scala b/src/main/scala/leon/synthesis/ConversionPhase.scala
index 366037b2a68d37f2f2a0e03439b30fe3074be75d..d5f4e842f698e54d353d4170c1591073debefd5e 100644
--- a/src/main/scala/leon/synthesis/ConversionPhase.scala
+++ b/src/main/scala/leon/synthesis/ConversionPhase.scala
@@ -64,7 +64,7 @@ object ConversionPhase extends UnitPhase[Program] {
    *
    *  def foo(a: T) = {
    *    require(..a..)
-   *    ???
+   *    _
    *  } ensuring { res =>
    *    post(res)
    *  }
@@ -75,8 +75,9 @@ object ConversionPhase extends UnitPhase[Program] {
    *    require(..a..)
    *    choose(x => post(x))
    *  }
+   * (in practice, there will be no pre-and postcondition)
    *
-   * 4) Functions that have only a choose as body gets their spec from the choose. 
+   * 4) Functions that have only a choose as body gets their spec from the choose.
    *
    *  def foo(a: T) = {
    *    choose(x => post(a, x))
diff --git a/src/main/scala/leon/synthesis/LinearEquations.scala b/src/main/scala/leon/synthesis/LinearEquations.scala
index f68fea066199089f206609be028b84af9056f280..da0f918103a959b5576a3909ebebeab3ec901305 100644
--- a/src/main/scala/leon/synthesis/LinearEquations.scala
+++ b/src/main/scala/leon/synthesis/LinearEquations.scala
@@ -74,7 +74,7 @@ object LinearEquations {
       var i = 0
       while(i < sols.size) {
         // seriously ??? 
-        K(i+j+1)(j) = evaluator.eval(sols(i)).asInstanceOf[EvaluationResults.Successful].value.asInstanceOf[InfiniteIntegerLiteral].value
+        K(i+j+1)(j) = evaluator.eval(sols(i)).asInstanceOf[EvaluationResults.Successful[Expr]].value.asInstanceOf[InfiniteIntegerLiteral].value
         i += 1
       }
     }
diff --git a/src/main/scala/leon/synthesis/rules/CEGISLike.scala b/src/main/scala/leon/synthesis/rules/CEGISLike.scala
index eb91692442f0e5bd0c94ec8e5e04d9255b06f920..5d06aa76a3c1186e806edf605431643e6b2a9359 100644
--- a/src/main/scala/leon/synthesis/rules/CEGISLike.scala
+++ b/src/main/scala/leon/synthesis/rules/CEGISLike.scala
@@ -20,7 +20,6 @@ import scala.collection.mutable.{HashMap=>MutableMap, ArrayBuffer}
 
 import evaluators._
 import datagen._
-import leon.utils._
 import codegen.CodeGenParams
 
 abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
@@ -380,7 +379,7 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
       private val innerPhi = outerExprToInnerExpr(p.phi)
 
       private var programCTree: Program = _
-      private var tester: (Example, Set[Identifier]) => EvaluationResults.Result = _
+      private var tester: (Example, Set[Identifier]) => EvaluationResults.Result[Expr] = _
 
       private def setCExpr(cTreeInfo: (Expr, Seq[FunDef])): Unit = {
         val (cTree, newFds) = cTreeInfo
@@ -392,7 +391,7 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
         //println(programCTree.asString)
         //println(".. "*30)
 
-//        val evaluator  = new DualEvaluator(sctx.context, programCTree, CodeGenParams.default)
+        //val evaluator  = new DualEvaluator(sctx.context, programCTree, CodeGenParams.default)
         val evaluator  = new DefaultEvaluator(sctx.context, programCTree)
 
         tester =
diff --git a/src/main/scala/leon/utils/SeqUtils.scala b/src/main/scala/leon/utils/SeqUtils.scala
index 5a5e2dff3088da991ac99a6b8f1e46f759837629..002f2ebedc8a6dfb265fbf101c2185b3bfa17ce1 100644
--- a/src/main/scala/leon/utils/SeqUtils.scala
+++ b/src/main/scala/leon/utils/SeqUtils.scala
@@ -2,6 +2,7 @@
 
 package leon.utils
 
+import scala.collection.SeqView
 import scala.collection.mutable.ArrayBuffer
 
 object SeqUtils {
@@ -42,3 +43,47 @@ object SeqUtils {
     }
   }
 }
+
+class CartesianView[+A](views: Seq[SeqView[A, Seq[A]]]) extends SeqView[Seq[A], Seq[Seq[A]]] {
+  override protected def underlying: Seq[Seq[A]] = SeqUtils.cartesianProduct(views)
+
+  override def length: Int = views.map{ _.size }.product
+
+  override def apply(idx: Int): Seq[A] = {
+    if (idx < 0 || idx >= length) throw new IndexOutOfBoundsException
+    var c = idx
+    for (v <- views) yield {
+      val ic = c % v.size
+      c /= v.size
+      v(ic)
+    }
+  }
+
+  override def iterator: Iterator[Seq[A]] = new Iterator[Seq[A]] {
+    // It's unfortunate, but we have to use streams to memoize
+    private val streams = views.map { _.toStream }
+    private val current = streams.toArray
+
+    // We take a note if there exists an empty view to begin with
+    // (which means the whole iterator is empty)
+    private val empty = streams exists { _.isEmpty }
+
+    override def hasNext: Boolean = !empty && current.exists { _.nonEmpty }
+
+    override def next(): Seq[A] = {
+      if (!hasNext) throw new NoSuchElementException("next on empty iterator")
+      // Propagate curry
+      for (i <- (0 to streams.size).takeWhile(current(_).isEmpty)) {
+        current(i) = streams(i)
+      }
+
+      val ret = current map { _.head }
+
+      for (i <- (0 to streams.size)) {
+        current(i) = current(i).tail
+      }
+
+      ret
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/test/scala/leon/integration/evaluators/EvaluatorSuite.scala b/src/test/scala/leon/integration/evaluators/EvaluatorSuite.scala
index 810d9d40edfd4aaf18c7c54aff0a579db600f2db..82c419b043468ebe20cc5422630f96a1d5128457 100644
--- a/src/test/scala/leon/integration/evaluators/EvaluatorSuite.scala
+++ b/src/test/scala/leon/integration/evaluators/EvaluatorSuite.scala
@@ -5,7 +5,7 @@ package leon.integration.evaluators
 import leon._
 import leon.test._
 import leon.test.helpers._
-import leon.evaluators._
+import leon.evaluators.{Evaluator => _, DeterministicEvaluator => Evaluator, _}
 import leon.purescala.Common._
 import leon.purescala.Definitions._
 import leon.purescala.Expressions._
@@ -205,7 +205,8 @@ class EvaluatorSuite extends LeonTestSuiteWithProgram with ExpressionsDSL {
 
   def normalEvaluators(implicit ctx: LeonContext, pgm: Program): List[Evaluator] = {
     List(
-      new DefaultEvaluator(ctx, pgm)
+      new DefaultEvaluator(ctx, pgm),
+      new AngelicEvaluator(ctx, pgm, new StreamEvaluator(ctx, pgm))
     )
   }
 
diff --git a/src/test/scala/leon/integration/purescala/CallGraphSuite.scala b/src/test/scala/leon/integration/purescala/CallGraphSuite.scala
index 7c47baa4b1abf2ec0c6493503fd7c944983c8c50..636cd4f406d37c2786f3e3493e48db9a7a98bec7 100644
--- a/src/test/scala/leon/integration/purescala/CallGraphSuite.scala
+++ b/src/test/scala/leon/integration/purescala/CallGraphSuite.scala
@@ -4,9 +4,7 @@ package leon.integration.purescala
 
 import leon.test._
 
-import leon._
-import leon.purescala.Definitions._
-import leon.utils._
+import leon.purescala.Definitions.Program
 
 class CallGraphSuite extends LeonTestSuiteWithProgram with helpers.ExpressionsDSL {
 
diff --git a/src/test/scala/leon/integration/purescala/DataGenSuite.scala b/src/test/scala/leon/integration/purescala/DataGenSuite.scala
index 3a2eaf24fbdc5b6cbbf66625970a068b513dd595..b1acfd74c26a745c5016bd219716783a6bea0ccd 100644
--- a/src/test/scala/leon/integration/purescala/DataGenSuite.scala
+++ b/src/test/scala/leon/integration/purescala/DataGenSuite.scala
@@ -3,12 +3,9 @@
 package leon.integration.purescala
 
 import leon.test._
-import leon.utils.{TemporaryInputPhase, PreprocessingPhase}
-import leon.frontends.scalac.ExtractionPhase
 
 import leon.purescala.Common._
 import leon.purescala.Expressions._
-import leon.purescala.Definitions._
 import leon.purescala.Types._
 import leon.datagen._
 
diff --git a/src/test/scala/leon/integration/purescala/DefOpsSuite.scala b/src/test/scala/leon/integration/purescala/DefOpsSuite.scala
index 3df239fb142498445443586e49e1fc3fc57e177b..c7aad05c63a2365e711a5f093853bd5524a87473 100644
--- a/src/test/scala/leon/integration/purescala/DefOpsSuite.scala
+++ b/src/test/scala/leon/integration/purescala/DefOpsSuite.scala
@@ -4,10 +4,8 @@ package leon.integration.purescala
 
 import leon.test._
 
-import leon._
 import leon.purescala.Definitions._
 import leon.purescala.DefOps._
-import leon.utils._
 
 class DefOpsSuite extends LeonTestSuiteWithProgram {
 
diff --git a/src/test/scala/leon/integration/solvers/EnumerationSolverSuite.scala b/src/test/scala/leon/integration/solvers/EnumerationSolverSuite.scala
index 59324582603c4460234f3a493766791a34ba27d9..89031230bf40c9bcf03a27f0f41bc5be06c125a7 100644
--- a/src/test/scala/leon/integration/solvers/EnumerationSolverSuite.scala
+++ b/src/test/scala/leon/integration/solvers/EnumerationSolverSuite.scala
@@ -2,7 +2,6 @@
 
 package leon.integration.solvers
 
-import leon.test._
 import leon.solvers._
 import leon.purescala.Common._
 import leon.purescala.Definitions._
diff --git a/src/test/scala/leon/integration/solvers/FairZ3SolverTests.scala b/src/test/scala/leon/integration/solvers/FairZ3SolverTests.scala
index f89ecfd13746390086b6566573e8a45c8391ebd6..b08e7f9164173d12e681b6dce086a75a9e225990 100644
--- a/src/test/scala/leon/integration/solvers/FairZ3SolverTests.scala
+++ b/src/test/scala/leon/integration/solvers/FairZ3SolverTests.scala
@@ -2,14 +2,12 @@
 
 package leon.integration.solvers
 
-import leon.test._
 import leon.purescala.Common._
 import leon.purescala.Definitions._
 import leon.purescala.Expressions._
 import leon.purescala.Types._
 import leon.LeonContext
 
-import leon.solvers._
 import leon.solvers.z3._
 
 class FairZ3SolverTests extends LeonSolverSuite {
diff --git a/src/test/scala/leon/integration/solvers/ModelEnumerationSuite.scala b/src/test/scala/leon/integration/solvers/ModelEnumerationSuite.scala
index 38553d171ddcdb1c0738aacf97e717e05f3e8256..3b405720a004c288f33a25456b6cd961d7ed7e53 100644
--- a/src/test/scala/leon/integration/solvers/ModelEnumerationSuite.scala
+++ b/src/test/scala/leon/integration/solvers/ModelEnumerationSuite.scala
@@ -12,7 +12,7 @@ import leon.purescala.Common._
 import leon.evaluators._
 import leon.purescala.Expressions._
 
-class ModelEnumeratorSuite extends LeonTestSuiteWithProgram with ExpressionsDSL {
+class ModelEnumerationSuite extends LeonTestSuiteWithProgram with ExpressionsDSL {
   val sources = List(
     """|import leon.lang._
        |import leon.annotation._
diff --git a/src/test/scala/leon/integration/solvers/SolversSuite.scala b/src/test/scala/leon/integration/solvers/SolversSuite.scala
index 40fd073574cc9cb4f58d97ef22ca3b70ad87ce69..0e75e922ca013b4203739b58b8ecab87412966f7 100644
--- a/src/test/scala/leon/integration/solvers/SolversSuite.scala
+++ b/src/test/scala/leon/integration/solvers/SolversSuite.scala
@@ -84,7 +84,7 @@ class SolversSuite extends LeonTestSuiteWithProgram {
             fail("Constraint "+cnstr.asString+" is unsat!?")
         }
       } finally {
-        solver.free
+        solver.free()
       }
 
     }
diff --git a/src/test/scala/leon/integration/solvers/TimeoutSolverSuite.scala b/src/test/scala/leon/integration/solvers/TimeoutSolverSuite.scala
index cce647cc1eed81df80b6f64d1ffcff2acf9c84aa..4ee34098827272c7039b5865fb016b465ca9ccd4 100644
--- a/src/test/scala/leon/integration/solvers/TimeoutSolverSuite.scala
+++ b/src/test/scala/leon/integration/solvers/TimeoutSolverSuite.scala
@@ -4,7 +4,6 @@ package leon.integration.solvers
 
 import leon._
 import leon.test._
-import leon.utils.Interruptible
 import leon.solvers._
 import leon.purescala.Common._
 import leon.purescala.Definitions._
diff --git a/src/test/scala/leon/integration/solvers/UnrollingSolverSuite.scala b/src/test/scala/leon/integration/solvers/UnrollingSolverSuite.scala
index d9e4d8bb969138727a9fcbde103d709813f88c5e..b3c0f82f2d98362c873c555992fca0367fe13ba1 100644
--- a/src/test/scala/leon/integration/solvers/UnrollingSolverSuite.scala
+++ b/src/test/scala/leon/integration/solvers/UnrollingSolverSuite.scala
@@ -2,13 +2,11 @@
 
 package leon.integration.solvers
 
-import leon.test._
 import leon.LeonContext
 import leon.purescala.Expressions._
 import leon.purescala.Types._
 import leon.purescala.Common._
 import leon.purescala.Definitions._
-import leon.solvers._
 import leon.solvers.z3._
 import leon.solvers.combinators._
 
diff --git a/src/test/scala/leon/test/LeonTestSuite.scala b/src/test/scala/leon/test/LeonTestSuite.scala
index 4c459cf6b2d1608db9371d21086c3bd462528b34..18bd8fc1465988ed7c3894858cc266f975b2395c 100644
--- a/src/test/scala/leon/test/LeonTestSuite.scala
+++ b/src/test/scala/leon/test/LeonTestSuite.scala
@@ -3,10 +3,6 @@
 package leon.test
 
 import leon._
-import leon.purescala.Definitions.Program
-import leon.LeonContext
-import leon.utils._
-import leon.frontends.scalac.ExtractionPhase
 
 import org.scalatest._
 import org.scalatest.exceptions.TestFailedException
diff --git a/src/test/scala/leon/unit/evaluators/EvaluatorSuite.scala b/src/test/scala/leon/unit/evaluators/EvaluatorSuite.scala
index 4d97487f6d85a50e39efd8277d64c99958a63df4..4002a0af0fb4ef8c71bf7542af74a6f8d6d366c9 100644
--- a/src/test/scala/leon/unit/evaluators/EvaluatorSuite.scala
+++ b/src/test/scala/leon/unit/evaluators/EvaluatorSuite.scala
@@ -1,40 +1,36 @@
 /* Copyright 2009-2015 EPFL, Lausanne */
 
-package leon.unit.allEvaluators
+package leon.unit.evaluators
 
 import leon._
 import leon.test._
 import leon.evaluators._
 
-import leon.utils.{TemporaryInputPhase, PreprocessingPhase}
-import leon.frontends.scalac.ExtractionPhase
-
 import leon.purescala.Common._
 import leon.purescala.Definitions._
 import leon.purescala.Expressions._
-import leon.purescala.DefOps._
 import leon.purescala.Types._
 import leon.purescala.Extractors._
 import leon.purescala.Constructors._
-import leon.codegen._
 
 class EvaluatorSuite extends LeonTestSuite with helpers.ExpressionsDSL {
 
   implicit val pgm = Program.empty
 
-  def normalEvaluators(implicit ctx: LeonContext, pgm: Program): List[Evaluator] = {
+  def normalEvaluators(implicit ctx: LeonContext, pgm: Program): List[DeterministicEvaluator] = {
     List(
-      new DefaultEvaluator(ctx, pgm)
+      new DefaultEvaluator(ctx, pgm),
+      new AngelicEvaluator(ctx, pgm, new StreamEvaluator(ctx, pgm))
     )
   }
 
-  def codegenEvaluators(implicit ctx: LeonContext, pgm: Program): List[Evaluator] = {
+  def codegenEvaluators(implicit ctx: LeonContext, pgm: Program): List[DeterministicEvaluator] = {
     List(
       new CodeGenEvaluator(ctx, pgm)
     )
   }
 
-  def allEvaluators(implicit ctx: LeonContext, pgm: Program): List[Evaluator] = {
+  def allEvaluators(implicit ctx: LeonContext, pgm: Program): List[DeterministicEvaluator] = {
     normalEvaluators ++ codegenEvaluators
   }
 
@@ -275,7 +271,7 @@ class EvaluatorSuite extends LeonTestSuite with helpers.ExpressionsDSL {
     def success: Expr = res
   }
 
-  case class Success(expr: Expr, env: Map[Identifier, Expr], evaluator: Evaluator, res: Expr) extends EvalDSL {
+  case class Success(expr: Expr, env: Map[Identifier, Expr], evaluator: DeterministicEvaluator, res: Expr) extends EvalDSL {
     override def failed = {
       fail(s"Evaluation of '$expr' with '$evaluator' (and env $env) should have failed")
     }
@@ -285,7 +281,7 @@ class EvaluatorSuite extends LeonTestSuite with helpers.ExpressionsDSL {
     }
   }
 
-  case class Failed(expr: Expr, env: Map[Identifier, Expr], evaluator: Evaluator, err: String) extends EvalDSL {
+  case class Failed(expr: Expr, env: Map[Identifier, Expr], evaluator: DeterministicEvaluator, err: String) extends EvalDSL {
     override def success = {
       fail(s"Evaluation of '$expr' with '$evaluator' (and env $env) should have succeeded but failed with $err")
     }
@@ -295,7 +291,7 @@ class EvaluatorSuite extends LeonTestSuite with helpers.ExpressionsDSL {
     def ===(res: Expr) = success
   }
 
-  def eval(e: Evaluator, toEval: Expr, env: Map[Identifier, Expr] = Map()): EvalDSL = {
+  def eval(e: DeterministicEvaluator, toEval: Expr, env: Map[Identifier, Expr] = Map()): EvalDSL = {
     e.eval(toEval, env) match {
       case EvaluationResults.Successful(res)     => Success(toEval, env, e, res)
       case EvaluationResults.RuntimeError(err)   => Failed(toEval, env, e, err)