diff --git a/project/Build.scala b/project/Build.scala
index 9347b15361d3083052191957fefe7c343d2bdb6e..a5205b3f017b0c9a6e4eacce1f2e9df4bc422537 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -79,7 +79,7 @@ object Leon extends Build {
   object Github {
     lazy val bonsai = RootProject(uri("git://github.com/colder/bonsai.git#8f485605785bda98ac61885b0c8036133783290a"))
 
-    private val scalaSmtLibVersion = "160a635e3677a185e2d5bd84669be98fcda8c574"
+    private val scalaSmtLibVersion = "d4622f38a04a191798eb29f39d3c8b2ec312e811"
     lazy val scalaSmtLib = RootProject(uri("git://github.com/regb/scala-smtlib.git#%s".format(scalaSmtLibVersion)))
   }
 }
diff --git a/project/plugins.sbt b/project/plugins.sbt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/main/scala/leon/Main.scala b/src/main/scala/leon/Main.scala
index 3195b5cfb82061b748b481a382589e45a1d1ae14..b51a0746b3d2665b659885fbf3332e2f499fa9c2 100644
--- a/src/main/scala/leon/Main.scala
+++ b/src/main/scala/leon/Main.scala
@@ -3,6 +3,7 @@
 package leon
 
 import leon.utils._
+import solvers.SolverFactory
 
 object Main {
 
@@ -34,6 +35,7 @@ object Main {
       LeonFlagOptionDef ("synthesis",   "--synthesis",          "Partial synthesis of choose() constructs"),
       LeonFlagOptionDef ("xlang",       "--xlang",              "Support for extra program constructs (imperative,...)"),
       LeonFlagOptionDef ("library",     "--library",            "Inject Leon standard library"),
+      LeonValueOptionDef("solvers",     "--solvers=s1,s2",      "Use solvers s1 and s2 (fairz3,enum,smt)"),
       LeonValueOptionDef("debug",       "--debug=<sections..>", "Enables specific messages"),
       LeonFlagOptionDef ("noop",        "--noop",               "No operation performed, just output program"),
       LeonFlagOptionDef ("help",        "--help",               "Show help")
@@ -145,6 +147,14 @@ object Main {
         settings = settings.copy(injectLibrary = value)
       case LeonFlagOption("xlang", value) =>
         settings = settings.copy(xlang = value)
+      case LeonValueOption("solvers", ListValue(ss)) =>
+        val available = SolverFactory.definedSolvers
+        val unknown = ss.toSet -- available
+        if (unknown.nonEmpty) {
+          initReporter.error("Unknown solver(s): "+unknown.mkString(", ")+" (Available: "+available.mkString(", ")+")")
+        }
+        settings = settings.copy(selectedSolvers = ss.toSet)
+
       case LeonValueOption("debug", ListValue(sections)) =>
         val debugSections = sections.flatMap { s =>
           if (s == "all") {
@@ -168,7 +178,7 @@ object Main {
     }
 
     // Create a new reporter taking settings into account
-    val reporter = new DefaultReporter(settings)
+    val reporter = new PlainTextReporter(settings)
 
     reporter.whenDebug(DebugSectionOptions) { debug =>
 
@@ -275,9 +285,6 @@ object Main {
       ctx.reporter.whenDebug(DebugSectionTimers) { debug =>
         ctx.timers.outputTable(debug)
       }
-
-      println("time: " + smtlib.SMTLIBSolver.time)
-
     } catch {
       case LeonFatalError(None) =>
         sys.exit(1)
diff --git a/src/main/scala/leon/Reporter.scala b/src/main/scala/leon/Reporter.scala
index ddd6eb9955b7cb637b196240c01cfb90fd9fb0a9..113c9ab878603dc389dcb1119625d37127fb9daa 100644
--- a/src/main/scala/leon/Reporter.scala
+++ b/src/main/scala/leon/Reporter.scala
@@ -180,3 +180,13 @@ class DefaultReporter(settings: Settings) extends Reporter(settings) {
   }
 
 }
+
+class PlainTextReporter(settings: Settings) extends DefaultReporter(settings) {
+  override protected def severityToPrefix(sev: Severity): String = sev match {
+    case ERROR    => "[ Error ]"
+    case WARNING  => "[Warning]"
+    case INFO     => "[ Info  ]"
+    case FATAL    => "[ Fatal ]"
+    case DEBUG(_) => "[ Debug ]"
+  }
+}
diff --git a/src/main/scala/leon/Settings.scala b/src/main/scala/leon/Settings.scala
index 702ef9c2e07d4b60d2670031262bd8d1f76ce568..0165a03b9f5e493fbd4ea306f446c973f3bf8f39 100644
--- a/src/main/scala/leon/Settings.scala
+++ b/src/main/scala/leon/Settings.scala
@@ -11,5 +11,7 @@ case class Settings(
   val synthesis: Boolean               = false,
   val xlang: Boolean                   = false,
   val verify: Boolean                  = true,
-  val injectLibrary: Boolean           = false
+  val injectLibrary: Boolean           = false,
+  val classPath: List[String]          = Settings.defaultClassPath(),
+  val selectedSolvers: Set[String]     = Set("fairz3")
 )
diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
index da44836d2ee6df09511c1e03718027ed66335ffe..2274336b9d7a332d760312d2c7a0c380c9d15119 100644
--- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
@@ -12,6 +12,7 @@ import purescala.TypeTrees._
 import solvers.TimeoutSolver
 
 import xlang.Trees._
+import solvers.SolverFactory
 
 abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int) extends Evaluator(ctx, prog) {
   val name = "evaluator"
@@ -375,7 +376,6 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       gv
 
     case choose: Choose =>
-      import solvers.z3.FairZ3Solver
       import purescala.TreeOps.simplestValue
 
       implicit val debugSection = utils.DebugSectionSynthesis
@@ -386,14 +386,15 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
 
       val tStart = System.currentTimeMillis;
 
-      val solver = (new FairZ3Solver(ctx, program) with TimeoutSolver).setTimeout(10000L)
+      val solver = SolverFactory.getFromSettings(ctx, program).getNewSolver
 
-      val inputsMap = p.as.map {
+      val eqs = p.as.map {
         case id =>
           Equals(Variable(id), rctx.mappings(id))
       }
 
-      solver.assertCnstr(And(Seq(p.pc, p.phi) ++ inputsMap))
+      val cnstr = And(eqs ::: p.pc :: p.phi :: Nil)
+      solver.assertCnstr(cnstr)
 
       try {
         solver.check match {
diff --git a/src/main/scala/leon/purescala/Common.scala b/src/main/scala/leon/purescala/Common.scala
index ba8b05cc2e4aa48c21dfc63a91ecc69f4d9169f8..28b197b474440807b78d55f997bf69ff93603608 100644
--- a/src/main/scala/leon/purescala/Common.scala
+++ b/src/main/scala/leon/purescala/Common.scala
@@ -29,7 +29,7 @@ object Common {
   }
 
   // the type is left blank (Untyped) for Identifiers that are not variables
-  class Identifier private[Common](val name: String, private val globalId: Int, val id: Int, alwaysShowUniqueID: Boolean = false) extends Tree with Typed {
+  class Identifier private[Common](val name: String, val globalId: Int, val id: Int, alwaysShowUniqueID: Boolean = false) extends Tree with Typed {
     self : Serializable =>
 
     override def equals(other: Any): Boolean = {
diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala
index 387b085f18b4b8b0d66a58b450667214c6c51422..c70d835e5e59fa5ebcf9733b097da20457ade32d 100644
--- a/src/main/scala/leon/purescala/Trees.scala
+++ b/src/main/scala/leon/purescala/Trees.scala
@@ -475,7 +475,8 @@ object Trees {
   }
 
   class CaseClassSelector(val classType: CaseClassType, val caseClass: Expr, val selector: Identifier) extends Expr with FixedType {
-    val fixedType = classType.fieldsTypes(classType.classDef.selectorID2Index(selector))
+    val selectorIndex = classType.classDef.selectorID2Index(selector)
+    val fixedType = classType.fieldsTypes(selectorIndex)
 
     override def equals(that: Any): Boolean = (that != null) && (that match {
       case t: CaseClassSelector => (t.classType, t.caseClass, t.selector) == (classType, caseClass, selector)
diff --git a/src/main/scala/leon/purescala/TypeTrees.scala b/src/main/scala/leon/purescala/TypeTrees.scala
index 9b518db9d357c02f6ac68b74b44497705681ec8d..a4b86d0722c0ec44ea51a041fed524b2e19bd42e 100644
--- a/src/main/scala/leon/purescala/TypeTrees.scala
+++ b/src/main/scala/leon/purescala/TypeTrees.scala
@@ -51,49 +51,6 @@ object TypeTrees {
 
   sealed abstract class TypeTree extends Tree
 
-  // returns the number of distinct values that inhabit a type
-  sealed abstract class TypeSize extends Serializable
-  case class FiniteSize(size: Int) extends TypeSize
-  case object InfiniteSize extends TypeSize
-
-  def domainSize(typeTree: TypeTree) : TypeSize = typeTree match {
-    case Untyped => FiniteSize(0)
-    case BooleanType => FiniteSize(2)
-    case UnitType => FiniteSize(1)
-    case Int32Type => InfiniteSize
-    case ListType(_) => InfiniteSize
-    case ArrayType(_) => InfiniteSize
-    case TypeParameter(_) => InfiniteSize
-    case TupleType(bases) => {
-      val baseSizes = bases.map(domainSize(_))
-      baseSizes.find(_ == InfiniteSize) match {
-        case Some(_) => InfiniteSize
-        case None => FiniteSize(baseSizes.map(_.asInstanceOf[FiniteSize].size).reduceLeft(_ * _))
-      }
-    }
-    case SetType(base) => domainSize(base) match {
-      case InfiniteSize => InfiniteSize
-      case FiniteSize(n) => FiniteSize(scala.math.pow(2, n).toInt)
-    }
-    case MultisetType(_) => InfiniteSize
-    case MapType(from,to) => (domainSize(from),domainSize(to)) match {
-      case (InfiniteSize,_) => InfiniteSize
-      case (_,InfiniteSize) => InfiniteSize
-      case (FiniteSize(n),FiniteSize(m)) => FiniteSize(scala.math.pow(m+1, n).toInt)
-    }
-    case FunctionType(fts, tt) => {
-      val fromSizes = fts map domainSize
-      val toSize = domainSize(tt)
-      if (fromSizes.exists(_ == InfiniteSize) || toSize == InfiniteSize)
-        InfiniteSize
-      else {
-        val n = toSize.asInstanceOf[FiniteSize].size
-        FiniteSize(scala.math.pow(n, fromSizes.foldLeft(1)((acc, s) => acc * s.asInstanceOf[FiniteSize].size)).toInt)
-      }
-    }
-    case c: ClassType => InfiniteSize
-  }
-
   case object Untyped extends TypeTree
   case object BooleanType extends TypeTree
   case object Int32Type extends TypeTree
diff --git a/src/main/scala/leon/smtlib/ExprToSExpr.scala b/src/main/scala/leon/smtlib/ExprToSExpr.scala
deleted file mode 100644
index b8e1be22ec7e21469560f1bf5253bf0b7861ba30..0000000000000000000000000000000000000000
--- a/src/main/scala/leon/smtlib/ExprToSExpr.scala
+++ /dev/null
@@ -1,107 +0,0 @@
-package leon
-package smtlib
-
-import purescala._
-import Common._
-import Trees._
-import Extractors._
-import TreeOps._
-import TypeTrees._
-import Definitions._
-
-import _root_.smtlib.sexpr
-import sexpr.SExprs._
-import _root_.smtlib.Commands.{Identifier => SmtLibIdentifier, _}
-
-/** This pretty-printer prints an SMTLIB2 representation of the Purescala program */
-object ExprToSExpr {
-
-  //returns the set of free identifier
-  def apply(tree: Expr): (SExpr, Set[Identifier]) = {
-
-    var freeVars: Set[Identifier] = Set()
-    
-    def rec(t: Expr): SExpr = t match {
-      case Variable(id) => {
-        val sym = id2sym(id)
-        freeVars += id
-        sym
-      }
-      //case LetTuple(ids,d,e) => SList(List(
-      //  SSymbol("let"),
-      //  SList(List(ids))
-      case Let(b,d,e) => {
-        val id = id2sym(b)
-        val value = rec(d)
-        val newBody = rec(e)
-        freeVars -= b
-        
-        SList(
-          SSymbol("let"),
-          SList(
-            SList(id, value)
-          ),
-          newBody
-        )
-      }
-
-      case er@Error(_) => {
-        val id = FreshIdentifier("error_value").setType(er.getType)
-        val sym = id2sym(id)
-        freeVars += id
-        sym
-      }
-
-      case And(exprs) => SList(SSymbol("and") :: exprs.map(rec).toList)
-      case Or(exprs) => SList(SSymbol("or") :: exprs.map(rec).toList)
-      case Not(expr) => SList(SSymbol("not"), rec(expr))
-      case Equals(l,r) => SList(SSymbol("="), rec(l), rec(r))
-      case IntLiteral(v) => SInt(v)
-      case BooleanLiteral(v) => SSymbol(v.toString) //TODO: maybe need some builtin type here
-      case StringLiteral(s) => SString(s)
-
-      case Implies(l,r) => SList(SSymbol("=>"), rec(l), rec(r))
-      case Iff(l,r) => SList(SSymbol("="), rec(l), rec(r))
-
-      case Plus(l,r) => SList(SSymbol("+"), rec(l), rec(r))
-      case UMinus(expr) => SList(SSymbol("-"), rec(expr))
-      case Minus(l,r) => SList(SSymbol("-"), rec(l), rec(r))
-      case Times(l,r) => SList(SSymbol("*"), rec(l), rec(r))
-      case Division(l,r) => SList(SSymbol("div"), rec(l), rec(r))
-      case Modulo(l,r) => SList(SSymbol("mod"), rec(l), rec(r))
-      case LessThan(l,r) => SList(SSymbol("<"), rec(l), rec(r))
-      case LessEquals(l,r) => SList(SSymbol("<="), rec(l), rec(r))
-      case GreaterThan(l,r) => SList(SSymbol(">"), rec(l), rec(r))
-      case GreaterEquals(l,r) => SList(SSymbol(">="), rec(l), rec(r))
-
-      case IfExpr(c, t, e) => SList(SSymbol("ite"), rec(c), rec(t), rec(e))
-
-      case FunctionInvocation(fd, args) => SList(id2sym(fd.id) :: args.map(rec).toList)
-
-      //case ArrayFill(length, defaultValue) => SList(
-      //  SList(SSymbol("as"), SSymbol("const"), tpe2sort(tree.getType)),
-      //  rec(defaultValue)
-      //)
-      //case ArrayMake(defaultValue) => SList(
-      //  SList(SSymbol("as"), SSymbol("const"), tpe2sort(tree.getType)),
-      //  rec(defaultValue)
-      //)
-      //case ArraySelect(array, index) => SList(SSymbol("select"), rec(array), rec(index))
-      //case ArrayUpdated(array, index, newValue) => SList(SSymbol("store"), rec(array), rec(index), rec(newValue))
-
-      case CaseClass(ccd, args) if args.isEmpty => id2sym(ccd.id)
-      case CaseClass(ccd, args) => SList(id2sym(ccd.id) :: args.map(rec(_)).toList)
-      case CaseClassSelector(_, arg, field) => SList(id2sym(field), rec(arg))
-
-      case CaseClassInstanceOf(ccd, arg) => {
-        val name = id2sym(ccd.id)
-        val testerName = SSymbol("is-" + name.s)
-        SList(testerName, rec(arg))
-      }
-      case o => sys.error("TODO converting to smtlib: " + o)
-    }
-
-    val res = rec(tree)
-    (res, freeVars)
-  }
-}
diff --git a/src/main/scala/leon/smtlib/PrettyPrinter.scala b/src/main/scala/leon/smtlib/PrettyPrinter.scala
deleted file mode 100644
index d13d4cc459dd47afeddccd5bc2ee852b9dff5cc0..0000000000000000000000000000000000000000
--- a/src/main/scala/leon/smtlib/PrettyPrinter.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-//package leon
-//package smtlib
-//
-//import purescala._
-//import Common._
-//import Trees._
-//import Extractors._
-//import TreeOps._
-//import TypeTrees._
-//import Definitions._
-//
-//import _root_.smtlib.sexpr
-//import sexpr.SExprs._
-//import _root_.smtlib.Commands.{Identifier => SmtLibIdentifier, _}
-//
-//  // prec: there should be no lets and no pattern-matching in this expression
-//  def collectWithPathCondition(matcher: Expr=>Boolean, expression: Expr) : Set[(Seq[Expr],Expr)] = {
-//    var collected : Set[(Seq[Expr],Expr)] = Set.empty
-//
-//      def rec(expr: Expr, path: List[Expr]) : Unit = {
-//        if(matcher(expr)) {
-//          collected = collected + ((path.reverse, expr))
-//        }
-//
-//        expr match {
-//          case Let(i,e,b) => {
-//            rec(e, path)
-//              rec(b, Equals(Variable(i), e) :: path)
-//          }
-//          case IfExpr(cond, thn, els) => {
-//            rec(cond, path)
-//              rec(thn, cond :: path)
-//              rec(els, Not(cond) :: path)
-//          }
-//          case NAryOperator(args, _) => args.foreach(rec(_, path))
-//            case BinaryOperator(t1, t2, _) => rec(t1, path); rec(t2, path)
-//            case UnaryOperator(t, _) => rec(t, path)
-//          case t : Terminal => ;
-//          case _ => scala.sys.error("Unhandled tree in collectWithPathCondition : " + expr)
-//        }
-//      }
-//
-//    rec(expression, Nil)
-//      collected
-//  }
-//}
diff --git a/src/main/scala/leon/smtlib/SExprToExpr.scala b/src/main/scala/leon/smtlib/SExprToExpr.scala
deleted file mode 100644
index 9dc8690a0ae8b9066356f580019bd5e285781d61..0000000000000000000000000000000000000000
--- a/src/main/scala/leon/smtlib/SExprToExpr.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package leon
-package smtlib
-
-import purescala._
-import Common._
-import Trees._
-import Extractors._
-import TreeOps._
-import TypeTrees._
-import Definitions._
-
-import _root_.smtlib.sexpr
-import sexpr.SExprs._
-import _root_.smtlib.Commands.{Identifier => SmtLibIdentifier, _}
-
-object SExprToExpr {
-
-  def apply(sexpr: SExpr, context: Map[String, Expr], constructors: Map[String, CaseClassDef]): Expr = sexpr match {
-    case SInt(n) => IntLiteral(n.toInt)
-    case SSymbol("TRUE") => BooleanLiteral(true)
-    case SSymbol("FALSE") => BooleanLiteral(false)
-    case SSymbol(s) => constructors.get(s) match {
-      case Some(app) => CaseClass(app, Seq())
-      case None => context(s)
-    }
-    case SList(SSymbol(app) :: args) if(constructors.isDefinedAt(app)) => 
-      CaseClass(constructors(app), args.map(apply(_, context, constructors)))
-
-    case SList(List(SSymbol("LET"), SList(defs), body)) => {
-      val leonDefs: Seq[(Identifier, Expr, String)] = defs.map {
-        case SList(List(SSymbol(sym), value)) => (FreshIdentifier(sym), apply(value, context, constructors), sym)
-      }
-      val recBody = apply(body, context ++ leonDefs.map(p => (p._3, p._1.toVariable)), constructors)
-      leonDefs.foldRight(recBody)((binding, b) => Let(binding._1, binding._2, b))
-    }
-    case SList(SSymbol(app) :: args) => {
-      val recArgs = args.map(arg => apply(arg, context, constructors))
-      app match {
-        case "-" => recArgs match {
-          case List(a) => UMinus(a)
-          case List(a, b) => Minus(a, b)
-        }
-      }
-    }
-    case o => sys.error("TODO converting from s-expr: " + o)
-  }
-
-}
diff --git a/src/main/scala/leon/smtlib/SMTLIBSolver.scala b/src/main/scala/leon/smtlib/SMTLIBSolver.scala
deleted file mode 100644
index 510b00ff2c11c7e655acf53c69f67e53a57aed52..0000000000000000000000000000000000000000
--- a/src/main/scala/leon/smtlib/SMTLIBSolver.scala
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Copyright 2009-2013 EPFL, Lausanne */
-
-package leon
-package smtlib
-
-import solvers.IncrementalSolver
-import utils.Interruptible
-import purescala._
-import Common._
-import Trees._
-import Extractors._
-import TreeOps._
-import TypeTrees._
-import Definitions._
-
-import _root_.smtlib.{PrettyPrinter => CommandPrinter, Commands, CommandResponses, sexpr, Interpreter => SMTLIBInterpreter}
-import Commands.{Identifier => SMTLIBIdentifier, _}
-import CommandResponses.{Error => ErrorResponse, _}
-import sexpr.SExprs._
-import _root_.smtlib.Commands.{Identifier => SmtLibIdentifier, _}
-
-
-class SMTLIBSolver(override val context: LeonContext, 
-                   val program: Program, 
-                   smtlibInterpreterFactory: () => SMTLIBInterpreter) 
-  extends IncrementalSolver with Interruptible {
-
-  override def interrupt: Unit = {}
-  override def recoverInterrupt(): Unit = {}
-
-
-  override def name: String = "smtlib-solver"
-  val out = new java.io.FileWriter("vcs/vc_" + SMTLIBSolver.counter)
-
-  //using a factory, so that creation and call to free are local to this class
-  private val smtlibInterpreter = smtlibInterpreterFactory()
-
-  private var errorConstants: Set[(SSymbol, SExpr)] = Set()
-
-  val defs: Seq[ClassTypeDef] = program.definedClasses
-
-  val partition: Seq[(AbstractClassDef, Seq[CaseClassDef])] = {
-    val parents: Seq[AbstractClassDef] = defs.filter(!_.hasParent).asInstanceOf[Seq[AbstractClassDef]]
-    parents.map(p => (p, defs.filter(c => c.parent match {
-      case Some(p2) => p == p2
-      case None => false
-    }).asInstanceOf[Seq[CaseClassDef]]))
-  }
-
-  val sorts: Seq[SExpr] = partition.map{ case (parent, children) => {
-    val name = id2sym(parent.id)
-    val constructors: List[SExpr] = children.map(child => {
-      val fields: List[SExpr] = child.fields.map{case VarDecl(id, tpe) => SList(id2sym(id), tpe2sort(tpe)) }.toList
-      if(fields.isEmpty) id2sym(child.id) else SList(id2sym(child.id) :: fields)
-    }).toList
-
-    SList(name :: constructors)
-  }}
-  val constructors: Map[String, CaseClassDef] = 
-    partition.unzip._2.flatMap(ccds => ccds.map(ccd => (ccd.id.uniqueName.toUpperCase, ccd))).toMap
-  val sortDecls = NonStandardCommand(SList(SSymbol("declare-datatypes"), SList(), SList(sorts.toList)))
-  val funDefDecls: Seq[Command] = program.definedFunctions.flatMap(fd2sexp)
-  val sortErrors: List[Command] = errorConstants.map(p => DeclareFun(p._1.s, Seq(), p._2)).toList
-
-  def declareConst(id: Identifier): Command = DeclareFun(id2sym(id).s, Seq(), tpe2sort(id.getType))
-
-    //SComment("! THEORY=1") +:
-    //SComment("Generated by Leon") +:
-  sendCommand(sortDecls)
-  sortErrors.foreach(sendCommand(_)) 
-  funDefDecls.foreach(sendCommand)
-
-      //convertedFunDefs.flatMap(_._1) ++
-      //convertedFunDefs.map(_._2) ++
-      //convertedFunDefs.flatMap(_._3) ++
-      //Seq(SList(SSymbol("check-sat")))
-
-  private var freeVars: Set[Identifier] = program.definedFunctions.flatMap(fd => fd.args.map(_.id)).toSet
-  override def assertCnstr(expression: Expr): Unit = {
-
-    val (sexpr, exprFreevars) = ExprToSExpr(expression)
-
-    val newFreeVars: Set[Identifier] = exprFreevars.diff(freeVars)
-    freeVars ++= newFreeVars
-    newFreeVars.foreach(id => sendCommand(declareConst(id)))
-
-    sendCommand(Assert(sexpr))
-  }
-
-  override def check: Option[Boolean] = sendCommand(CheckSat) match {
-    case CheckSatResponse(SatStatus) => Some(true)
-    case CheckSatResponse(UnsatStatus) => Some(false)
-    case CheckSatResponse(UnknownStatus) => None
-  }
-
-  override def getModel: Map[Identifier, Expr] = {
-    val ids: List[Identifier] = freeVars.toList
-    val sexprs: List[SSymbol] = ids.map(id => id2sym(id))
-    val cmd: Command = GetValue(sexprs.head, sexprs.tail)
-
-    val symToIds: Map[SExpr, Identifier] = sexprs.map(s => SSymbol(s.s.toUpperCase)).zip(ids).toMap
-    val GetValueResponse(valuationPairs) = sendCommand(cmd)
-    println("got valuation pairs: " + valuationPairs)
-    valuationPairs.map{ case (sym, value) => (symToIds(sym), SExprToExpr(value, Map(), constructors)) }.toMap
-  }
-
-  override def free() = {
-    sendCommand(Exit)
-    smtlibInterpreter.free()
-    out.close
-    SMTLIBSolver.counter += 1
-  }
-
-  override def push(): Unit = {
-    sendCommand(Push(1))
-  }
-  override def pop(lvl: Int = 1): Unit = {
-    sendCommand(Pop(1))
-  }
-
-  def sendCommand(cmd: Command): CommandResponse = {
-    val startTime = System.currentTimeMillis
-    CommandPrinter(cmd, out)
-    out.write("\n")
-    val response = smtlibInterpreter.eval(cmd)
-    assert(!response.isInstanceOf[Error])
-    SMTLIBSolver.time = SMTLIBSolver.time + (System.currentTimeMillis - startTime)
-    response
-  }
-
-  private def fd2sexp(funDef: FunDef): List[Command] = {
-    val name = id2sym(funDef.id)
-    val returnSort = tpe2sort(funDef.returnType)
-
-    val varDecls: List[(SSymbol, SExpr)] = funDef.args.map(vd => (id2sym(vd.id), tpe2sort(vd.tpe))).toList
-
-    val topLevelVarDecl: List[Command] = varDecls.map{ case (name, tpe) => DeclareFun(name.s, Seq(), tpe) }
-    val funDecl: Command = DeclareFun(name.s, varDecls.map(_._2), returnSort)
-
-    funDecl :: topLevelVarDecl
-  }
-}
-
-object SMTLIBSolver {
-  var counter = 0
-  var time: Long = 0
-}
diff --git a/src/main/scala/leon/smtlib/package.scala b/src/main/scala/leon/smtlib/package.scala
deleted file mode 100644
index 63f6b6c0f561a56980cf5af22fc597af20f73438..0000000000000000000000000000000000000000
--- a/src/main/scala/leon/smtlib/package.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package leon
-
-import purescala._
-import Common._
-import Trees._
-import Extractors._
-import TreeOps._
-import TypeTrees._
-import Definitions._
-
-import _root_.smtlib.sexpr
-import sexpr.SExprs._
-import _root_.smtlib.Commands.{Identifier => SmtLibIdentifier, _}
-
-package object smtlib {
-
-  private[smtlib] def id2sym(id: Identifier): SSymbol = SSymbol(id.uniqueName)
-  //return a series of declarations, an expression that defines the function, 
-  //and the seq of asserts for pre/post-conditions
-
-
-  def tpe2sort[smtlib](tpe: TypeTree): SExpr = tpe match {
-    case Int32Type => SSymbol("Int")
-    case BooleanType => SSymbol("Bool")
-    case ArrayType(baseTpe) => SList(SSymbol("Array"), SSymbol("Int"), tpe2sort(baseTpe))
-    case AbstractClassType(abs) => id2sym(abs.id)
-    case _ => sys.error("TODO tpe2sort: " + tpe)
-  }
-
-}
diff --git a/src/main/scala/leon/solvers/SolverFactory.scala b/src/main/scala/leon/solvers/SolverFactory.scala
index 44c1f4140540e1afe65c5b8289cda5ad8eb12085..5343be2d2cbc8f47613182b932b9f6be52c4b7ec 100644
--- a/src/main/scala/leon/solvers/SolverFactory.scala
+++ b/src/main/scala/leon/solvers/SolverFactory.scala
@@ -3,12 +3,13 @@
 package leon
 package solvers
 
+import purescala.Definitions._
 import scala.reflect.runtime.universe._
 
 abstract class SolverFactory[+S <: Solver : TypeTag] {
   def getNewSolver(): S
 
-  val name = "SFact("+typeOf[S].toString+")"
+  val name = typeOf[S].toString.split("\\.").last.replaceAll("Solver", "")+"*"
 }
 
 object SolverFactory {
@@ -17,4 +18,43 @@ object SolverFactory {
       def getNewSolver() = builder()
     }
   }
+
+  val definedSolvers = Set("fairz3", "enum", "smt", "smt-z3", "smt-cvc4");
+
+  def getFromSettings[S](ctx: LeonContext, program: Program): SolverFactory[TimeoutSolver] = {
+    import combinators._
+    import z3._
+    import smtlib._
+
+    def getSolver(name: String): SolverFactory[TimeoutSolver] = name match {
+      case "fairz3" =>
+        SolverFactory(() => new FairZ3Solver(ctx, program) with TimeoutSolver)
+
+      case "enum"   =>
+        SolverFactory(() => new EnumerationSolver(ctx, program) with TimeoutSolver)
+
+      case "smt" | "smt-z3" =>
+        val smtf = SolverFactory(() => new SMTLIBSolver(ctx, program) with SMTLIBZ3Target)
+        SolverFactory(() => new UnrollingSolver(ctx, smtf) with TimeoutSolver)
+
+      case "smt-cvc4" =>
+        val smtf = SolverFactory(() => new SMTLIBSolver(ctx, program) with SMTLIBCVC4Target)
+        SolverFactory(() => new UnrollingSolver(ctx, smtf) with TimeoutSolver)
+
+      case _ =>
+        ctx.reporter.fatalError("Unknown solver "+name)
+    }
+
+    val selectedSolvers = ctx.settings.selectedSolvers.map(getSolver)
+
+    if (selectedSolvers.isEmpty) {
+      ctx.reporter.fatalError("No solver selected. Aborting")
+    } else if (selectedSolvers.size == 1) {
+      selectedSolvers.head
+    } else {
+      SolverFactory( () => new PortfolioSolver(ctx, selectedSolvers.toSeq) with TimeoutSolver)
+    }
+
+  }
+
 }
diff --git a/src/main/scala/leon/solvers/combinators/FunctionTemplate.scala b/src/main/scala/leon/solvers/combinators/FunctionTemplate.scala
index 85ad52f78d1870343c9d8678d2ec2176a4eddac6..abe4b684159eab6af7e3f4c6fe0b2fa871ca4b48 100644
--- a/src/main/scala/leon/solvers/combinators/FunctionTemplate.scala
+++ b/src/main/scala/leon/solvers/combinators/FunctionTemplate.scala
@@ -95,8 +95,6 @@ class FunctionTemplate private(
 }
 
 object FunctionTemplate {
-  val splitAndOrImplies = false
-
   def mkTemplate(tfd: TypedFunDef, isRealFunDef : Boolean = true) : FunctionTemplate = {
     val condVars : MutableSet[Identifier] = MutableSet.empty
     val exprVars : MutableSet[Identifier] = MutableSet.empty
@@ -138,6 +136,13 @@ object FunctionTemplate {
       res
     }
 
+    def requireDecomposition(e: Expr) = {
+      exists{
+        case (_: FunctionInvocation) | (_: Assert) | (_: Ensuring) | (_: Choose) => true
+        case _ => false
+      }(e)
+    }
+
     def rec(pathVar : Identifier, expr : Expr) : Expr = {
       expr match {
         case a @ Assert(cond, _, body) =>
@@ -175,48 +180,16 @@ object FunctionTemplate {
         case m : MatchExpr => sys.error("MatchExpr's should have been eliminated.")
 
         case i @ Implies(lhs, rhs) =>
-          if (splitAndOrImplies) {
-            if (containsFunctionCalls(i)) {
-              rec(pathVar, IfExpr(lhs, rhs, BooleanLiteral(true)))
-            } else {
-              i
-            }
-          } else {
-            Implies(rec(pathVar, lhs), rec(pathVar, rhs))
-          }
+          Implies(rec(pathVar, lhs), rec(pathVar, rhs))
 
         case a @ And(parts) =>
-          if (splitAndOrImplies) {
-            if (containsFunctionCalls(a)) {
-              val partitions = groupWhile((e: Expr) => !containsFunctionCalls(e), parts)
-
-              val ifExpr = partitions.map(And(_)).reduceRight{ (a: Expr, b: Expr) => IfExpr(a, b, BooleanLiteral(false)) }
-
-              rec(pathVar, ifExpr)
-            } else {
-              a
-            }
-          } else {
-            And(parts.map(rec(pathVar, _)))
-          }
+          And(parts.map(rec(pathVar, _)))
 
         case o @ Or(parts) =>
-          if (splitAndOrImplies) {
-            if (containsFunctionCalls(o)) {
-              val partitions = groupWhile((e: Expr) => !containsFunctionCalls(e), parts)
-
-              val ifExpr = partitions.map(Or(_)).reduceRight{ (a: Expr, b: Expr) => IfExpr(a, BooleanLiteral(true), b) }
-
-              rec(pathVar, ifExpr)
-            } else {
-              o
-            }
-          } else {
-            Or(parts.map(rec(pathVar, _)))
-          }
+          Or(parts.map(rec(pathVar, _)))
 
         case i @ IfExpr(cond, thenn, elze) => {
-          if(!containsFunctionCalls(cond) && !containsFunctionCalls(thenn) && !containsFunctionCalls(elze)) {
+          if(!requireDecomposition(i)) {
             i
           } else {
             val newBool1 : Identifier = FreshIdentifier("b", true).setType(BooleanType)
diff --git a/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala b/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala
index 7ddf0abcde8408ab09e61b326fe2e91acf3c4dba..f9fd8a7d4beaad38ebb352ba3406bba5484eb048 100644
--- a/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala
+++ b/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala
@@ -18,28 +18,20 @@ import scala.collection.mutable.{Map=>MutableMap}
 
 import ExecutionContext.Implicits.global
 
-class PortfolioSolver(val context: LeonContext, solvers: Seq[SolverFactory[AssumptionSolver with IncrementalSolver with Interruptible]])
-        extends Solver with IncrementalSolver with Interruptible with NaiveAssumptionSolver {
+class PortfolioSolver[S <: Solver with Interruptible](val context: LeonContext, solvers: Seq[SolverFactory[S]])
+        extends Solver with Interruptible {
 
   val name = "Pfolio"
 
   var constraints = List[Expr]()
 
-  private var modelMap = Map[Identifier, Expr]()
-  private var solversInsts = solvers.map(_.getNewSolver)
+  protected var modelMap = Map[Identifier, Expr]()
+  protected var solversInsts: Seq[S] = solvers.map(_.getNewSolver)
 
   def assertCnstr(expression: Expr): Unit = {
     solversInsts.foreach(_.assertCnstr(expression))
   }
 
-  def push(): Unit = {
-    solversInsts.foreach(_.push())
-  }
-
-  def pop(lvl: Int): Unit = {
-    solversInsts.foreach(_.pop(lvl))
-  }
-
   def check: Option[Boolean] = {
     modelMap = Map()
 
@@ -88,3 +80,15 @@ class PortfolioSolver(val context: LeonContext, solvers: Seq[SolverFactory[Assum
     solversInsts.foreach(_.recoverInterrupt())
   }
 }
+
+class PortfolioSolverSynth(context: LeonContext, solvers: Seq[SolverFactory[AssumptionSolver with IncrementalSolver with Interruptible]])
+        extends PortfolioSolver[AssumptionSolver with IncrementalSolver with Interruptible](context, solvers) with IncrementalSolver with Interruptible with NaiveAssumptionSolver {
+
+  def push(): Unit = {
+    solversInsts.foreach(_.push())
+  }
+
+  def pop(lvl: Int): Unit = {
+    solversInsts.foreach(_.pop(lvl))
+  }
+}
diff --git a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala
index 728ae07eb45a5cf4b29e823f85b2494069760591..ce527cfcc5691f67aeee4102ded69b4d80f38ae4 100644
--- a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala
+++ b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala
@@ -20,9 +20,11 @@ class UnrollingSolver(val context: LeonContext, underlyings: SolverFactory[Incre
   private var theConstraint : Option[Expr] = None
   private var theModel : Option[Map[Identifier,Expr]] = None
 
+  val reporter = context.reporter
+
   private var stop: Boolean = false
 
-  def name = "Unr("+underlyings.name+")"
+  def name = "U:"+underlyings.name
 
   def free {}
 
@@ -36,14 +38,11 @@ class UnrollingSolver(val context: LeonContext, underlyings: SolverFactory[Incre
   }
 
   def check : Option[Boolean] = theConstraint.map { expr =>
-    val solver = underlyings.getNewSolver//SimpleSolverAPI(underlyings)
-
-    debugS("Check called on " + expr.asString + "...")
+    val solver = underlyings.getNewSolver
 
     val template = getTemplate(expr)
 
     val aVar : Identifier = template.activatingBool
-    var allClauses : Seq[Expr] = Nil
     var allBlockers : Map[Identifier,Set[FunctionInvocation]] = Map.empty
 
     def unrollOneStep() : List[Expr] = {
@@ -52,20 +51,24 @@ class UnrollingSolver(val context: LeonContext, underlyings: SolverFactory[Incre
       var newClauses : List[Seq[Expr]] = Nil
       var newBlockers : Map[Identifier,Set[FunctionInvocation]] = Map.empty
 
-      for(blocker <- allBlockers.keySet; FunctionInvocation(tfd, args) <- allBlockers(blocker)) {
-        val (nc, nb) = getTemplate(tfd).instantiate(blocker, args)
+      for(blocker <- allBlockers.keySet; fi @ FunctionInvocation(tfd, args) <- allBlockers(blocker)) {
+        val tmpl = getTemplate(tfd)
+
+        val (nc, nb) = tmpl.instantiate(blocker, args)
         newClauses = nc :: newClauses
         newBlockers = newBlockers ++ nb
+        //reporter.debug("Unrolling behind "+fi+" ("+nc.size+")")
+        //for (c <- nc) {
+        //  reporter.debug("  . "+c)
+        //}
       }
 
-      allClauses = newClauses.flatten ++ allClauses
       allBlockers = newBlockers
       newClauses.flatten
     }
 
     val (nc, nb) = template.instantiate(aVar, template.tfd.params.map(a => Variable(a.id)))
 
-    allClauses = nc.reverse
     allBlockers = nb
 
     var unrollingCount : Int = 0
@@ -73,46 +76,42 @@ class UnrollingSolver(val context: LeonContext, underlyings: SolverFactory[Incre
     var result : Option[Boolean] = None
 
     solver.assertCnstr(Variable(aVar))
-    solver.assertCnstr(And(allClauses))
+    solver.assertCnstr(And(nc))
     // We're now past the initial step.
     while(!done && !stop) {
-      debugS("At lvl : " + unrollingCount)
-
       solver.push()
-      //val closed : Expr = fullClosedExpr
+      reporter.debug(" - Searching with blocked literals")
       solver.assertCnstr(And(allBlockers.keySet.toSeq.map(id => Not(id.toVariable))))
-
-      debugS("Going for SAT with this:\n")
-
       solver.check match {
 
         case Some(false) =>
           solver.pop(1)
+          reporter.debug(" - Searching with unblocked literals")
           //val open = fullOpenExpr
-          debugS("Was UNSAT... Going for UNSAT with this:\n")
           solver.check match {
             case Some(false) =>
-              debugS("Was UNSAT... Done !")
               done = true
               result = Some(false)
 
-            case _ =>
-              debugS("Was SAT or UNKNOWN. Let's unroll !")
+            case r =>
               unrollingCount += 1
+              val model = solver.getModel
+              reporter.debug(" - Tentative model: "+model)
+              reporter.debug(" - more unrollings")
               val newClauses = unrollOneStep()
+              reporter.debug(s"   - ${newClauses.size} new clauses")
+              readLine()
               solver.assertCnstr(And(newClauses))
           }
 
         case Some(true) =>
           val model = solver.getModel
-          debugS("WAS SAT ! We're DONE !")
           done = true
           result = Some(true)
           theModel = Some(model)
 
         case None =>
           val model = solver.getModel
-          debugS("WAS UNKNOWN ! We're DONE !")
           done = true
           result = Some(true)
           theModel = Some(model)
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
new file mode 100644
index 0000000000000000000000000000000000000000..f9f9a59e594d5b1663c0e1d4439d9a5624e63a68
--- /dev/null
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
@@ -0,0 +1,51 @@
+/* Copyright 2009-2013 EPFL, Lausanne */
+
+package leon
+package solvers
+package smtlib
+
+import utils._
+import purescala._
+import Common._
+import Trees._
+import Extractors._
+import TypeTrees._
+
+import _root_.smtlib.sexpr.SExprs._
+import _root_.smtlib.interpreters.CVC4Interpreter
+
+trait SMTLIBCVC4Target extends SMTLIBTarget {
+  this: SMTLIBSolver =>
+
+  val targetName = "cvc4"
+
+  def getNewInterpreter() = new CVC4Interpreter
+
+  val extSym = SSymbol("_")
+
+  override def toSMT(e: Expr)(implicit bindings: Map[Identifier, SExpr]) = e match {
+      case fs @ FiniteSet(elems) =>
+        val ss = declareSort(fs.getType)
+        var res = SList(SSymbol("as"), SSymbol("const"), ss, toSMT(BooleanLiteral(false)))
+
+        for (e <- elems) {
+          res = SList(SSymbol("store"), res, toSMT(e), toSMT(BooleanLiteral(true)))
+        }
+
+        res
+
+      case sd @ SetDifference(a, b) =>
+        // a -- b
+        // becomes:
+        // a && not(b)
+        SList(SList(extSym, SSymbol("map"), SSymbol("and")), toSMT(a), SList(SList(extSym, SSymbol("map"), SSymbol("not")), toSMT(b)))
+      case SetUnion(l, r) =>
+        SList(SList(extSym, SSymbol("map"), SSymbol("or")), toSMT(l), toSMT(r))
+
+      case SetIntersection(l, r) =>
+        SList(SList(extSym, SSymbol("map"), SSymbol("and")), toSMT(l), toSMT(r))
+
+      case _ =>
+        super.toSMT(e)
+  }
+}
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a1de9e9e220dc5a8769adcebcdf14eeef08ac170
--- /dev/null
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
@@ -0,0 +1,68 @@
+/* Copyright 2009-2013 EPFL, Lausanne */
+
+package leon
+package solvers
+package smtlib
+
+import utils._
+import purescala._
+import Common._
+import Trees._
+import Extractors._
+import TreeOps._
+import TypeTrees._
+import Definitions._
+
+import _root_.smtlib.{PrettyPrinter => SMTPrinter, Interpreter => SMTInterpreter}
+import _root_.smtlib.Commands.{Identifier => _, Assert => SMTAssert, _}
+import _root_.smtlib.CommandResponses.{Error => ErrorResponse, _}
+import _root_.smtlib.sexpr.SExprs._
+import _root_.smtlib.interpreters._
+
+abstract class SMTLIBSolver(val context: LeonContext,
+                            val program: Program)
+  extends IncrementalSolver with Interruptible with SMTLIBTarget {
+
+  override def interrupt: Unit = {}
+  override def recoverInterrupt(): Unit = {}
+
+  override def name: String = "smt-"+targetName
+
+  override def assertCnstr(expr: Expr): Unit = {
+    variablesOf(expr).foreach(declareVariable)
+    val sexpr = toSMT(expr)(Map())
+    sendCommand(SMTAssert(sexpr))
+  }
+
+  override def check: Option[Boolean] = sendCommand(CheckSat) match {
+    case CheckSatResponse(SatStatus)     => Some(true)
+    case CheckSatResponse(UnsatStatus)   => Some(false)
+    case CheckSatResponse(UnknownStatus) => None
+  }
+
+  override def getModel: Map[Identifier, Expr] = {
+    val syms = variables.bSet.toList
+    val cmd: Command = GetValue(syms.head, syms.tail)
+
+    val GetValueResponse(valuationPairs) = sendCommand(cmd)
+
+    valuationPairs.collect {
+      case (sym: SSymbol, value) if variables.containsB(sym) =>
+        //println("Getting model for "+sym)
+        //println("Value "+value)
+        (variables.toA(sym), fromSMT(value)(Map()))
+    }.toMap
+  }
+
+  override def free() = {
+    interpreter.free()
+    out.close
+  }
+
+  override def push(): Unit = {
+    sendCommand(Push(1))
+  }
+  override def pop(lvl: Int = 1): Unit = {
+    sendCommand(Pop(1))
+  }
+}
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
new file mode 100644
index 0000000000000000000000000000000000000000..dc6e9adc36bffcfde7763b0674276140e48061e8
--- /dev/null
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
@@ -0,0 +1,346 @@
+package leon
+package solvers
+package smtlib
+
+import utils.Interruptible
+import purescala._
+import Common._
+import Trees.{Assert => _, _}
+import Extractors._
+import TreeOps._
+import TypeTrees._
+import Definitions._
+import utils.Bijection
+
+import _root_.smtlib.{PrettyPrinter => SMTPrinter, Interpreter => SMTInterpreter}
+import _root_.smtlib.Commands.{Identifier => _, _}
+import _root_.smtlib.CommandResponses.{Error => ErrorResponse, _}
+import _root_.smtlib.sexpr.SExprs._
+import _root_.smtlib.interpreters._
+
+trait SMTLIBTarget {
+  this: SMTLIBSolver =>
+
+  val reporter = context.reporter
+
+  def targetName: String
+  def getNewInterpreter(): SMTInterpreter
+
+  val interpreter = getNewInterpreter()
+
+  val out = new java.io.FileWriter(s"vcs-$targetName.log", true)
+  reporter.ifDebug { debug =>
+    out.write("; -----------------------------------------------------\n")
+  }
+
+  def id2sym(id: Identifier): SSymbol = SSymbol(id.name.toUpperCase+"!"+id.globalId)
+
+  // metadata for CC, and variables
+  val constructors = new Bijection[TypeTree, SSymbol]()
+  val selectors    = new Bijection[(TypeTree, Int), SSymbol]()
+  val testers      = new Bijection[TypeTree, SSymbol]()
+  val variables    = new Bijection[Identifier, SSymbol]()
+  val sorts        = new Bijection[TypeTree, SExpr]()
+  val functions    = new Bijection[TypedFunDef, SSymbol]()
+
+  def normalizeType(t: TypeTree): TypeTree = t match {
+    case ct: ClassType if ct.parent.isDefined => ct.parent.get
+    case tt: TupleType => TupleType(tt.bases.map(normalizeType))
+    case _ =>   t
+  }
+
+  def unsupported(str: Any) = reporter.fatalError(s"Unsupported in $targetName: $str")
+
+  def declareSort(t: TypeTree): SExpr = {
+    val tpe = normalizeType(t)
+    sorts.cachedB(tpe) {
+      tpe match {
+        case BooleanType => SSymbol("Bool")
+        case Int32Type => SSymbol("Int")
+        case TypeParameter(id) =>
+          val s = id2sym(id)
+          val cmd = NonStandardCommand(SList(SSymbol("declare-sort"), s))
+          sendCommand(cmd)
+          s
+        case _: ClassType | _: TupleType =>
+          declareStructuralSort(tpe)
+        case _ =>
+          unsupported("Sort "+t)
+      }
+    }
+  }
+
+  def freshSym(id: Identifier): SSymbol = freshSym(id.name)
+  def freshSym(name: String): SSymbol = id2sym(FreshIdentifier(name))
+
+  def declareStructuralSort(t: TypeTree): SExpr = {
+
+    def getHierarchy(ct: ClassType): (ClassType, Seq[CaseClassType]) = ct match {
+      case act: AbstractClassType =>
+        (act, act.knownCCDescendents)
+      case cct: CaseClassType =>
+        cct.parent match {
+          case Some(p) =>
+            getHierarchy(p)
+          case None =>
+            (cct, List(cct))
+        }
+    }
+
+    case class DataType(sym: SSymbol, cases: Seq[Constructor])
+    case class Constructor(sym: SSymbol, tpe: TypeTree, fields: Seq[(SSymbol, TypeTree)])
+
+    var datatypes = Map[TypeTree, DataType]()
+
+
+    def findDependencies(t: TypeTree): Unit = t match {
+      case ct: ClassType =>
+        val (root, sub) = getHierarchy(ct)
+
+        if (!(datatypes contains root) && !(sorts containsA root)) {
+          val sym = freshSym(ct.id)
+
+          val conss = sub.map { case cct =>
+            Constructor(freshSym(cct.id), cct, cct.fields.map(vd => (freshSym(vd.id), vd.tpe)))
+          }
+
+          datatypes += root -> DataType(sym, conss)
+
+          // look for dependencies
+          for (ct <- root +: sub; f <- ct.fields) findDependencies(f.tpe)
+        }
+      case tt @ TupleType(bases) =>
+        if (!(datatypes contains tt) && !(sorts containsA tt)) {
+          val sym = freshSym("tuple"+bases.size)
+
+          val c = Constructor(freshSym(sym.s), tt, bases.zipWithIndex.map {
+            case (tpe, i) => (freshSym("_"+(i+1)), tpe)
+          })
+
+          datatypes += tt -> DataType(sym, Seq(c))
+
+          bases.foreach(findDependencies)
+        }
+
+      case st @ SetType(base) =>
+
+
+      case _ =>
+    }
+
+    // Populates the dependencies of the structural type to define.
+    findDependencies(t)
+
+    // We pre-declare ADTs
+    for ((tpe, DataType(sym, _)) <- datatypes) {
+      sorts += tpe -> sym
+    }
+
+    def toDecl(c: Constructor): SExpr = {
+      val s = c.sym
+
+      testers += c.tpe -> SSymbol("is-"+s.s)
+      constructors += c.tpe -> s
+
+      SList(s :: c.fields.zipWithIndex.map {
+        case ((cs, t), i) =>
+          selectors += (c.tpe, i) -> cs
+          SList(cs, declareSort(t))
+      }.toList)
+    }
+
+    val adts = for ((tpe, DataType(sym, cases)) <- datatypes.toList) yield {
+      SList(sym :: cases.map(toDecl).toList)
+    }
+
+
+    val cmd = NonStandardCommand(SList(SSymbol("declare-datatypes"), SList(), SList(adts)))
+    sendCommand(cmd)
+
+    sorts.toB(t)
+  }
+
+  def declareVariable(id: Identifier): SSymbol = {
+    variables.cachedB(id) {
+      val s = id2sym(id)
+      val cmd = NonStandardCommand(SList(SSymbol("declare-const"), s, declareSort(id.getType)))
+      sendCommand(cmd)
+      s
+    }
+  }
+
+  def declareFunction(tfd: TypedFunDef): SSymbol = {
+    functions.cachedB(tfd) {
+      val id = if (tfd.tps.isEmpty) {
+        tfd.id
+      } else {
+        FreshIdentifier(tfd.id.name)
+      }
+      val s = id2sym(id)
+      sendCommand(DeclareFun(s.s, tfd.params.map(p => declareSort(p.tpe)), declareSort(tfd.returnType)))
+      s
+    }
+  }
+
+  def toSMT(e: Expr)(implicit bindings: Map[Identifier, SExpr]): SExpr = {
+    e match {
+      case Variable(id) =>
+        declareSort(e.getType)
+        bindings.getOrElse(id, variables.toB(id))
+
+      case IntLiteral(v) => SInt(v)
+      case BooleanLiteral(v) => SSymbol(if (v) "true" else "false")
+      case StringLiteral(s) => SString(s)
+      case Let(b,d,e) =>
+        val id      = id2sym(b)
+        val value   = toSMT(d)
+        val newBody = toSMT(e)(bindings + (b -> id))
+
+        SList(
+          SSymbol("let"),
+          SList(
+            SList(id, value)
+          ),
+          newBody
+        )
+
+      case er @ Error(_) =>
+        declareVariable(FreshIdentifier("error_value").setType(er.getType))
+
+      case s @ CaseClassSelector(cct, e, id) =>
+        declareSort(cct)
+        SList(selectors.toB((cct, s.selectorIndex)), toSMT(e))
+
+      case CaseClassInstanceOf(cct, e) =>
+        declareSort(cct)
+        SList(testers.toB(cct), toSMT(e))
+
+      case CaseClass(cct, es) =>
+        declareSort(cct)
+        if (es.isEmpty) {
+          constructors.toB(cct)
+        } else {
+          SList(constructors.toB(cct) :: es.map(toSMT).toList)
+        }
+
+      case t @ Tuple(es) =>
+        val tpe = normalizeType(t.getType)
+        declareSort(tpe)
+        SList(constructors.toB(tpe) :: es.map(toSMT).toList)
+
+      case ts @ TupleSelect(t, i) =>
+        val tpe = normalizeType(t.getType)
+        SList(selectors.toB((tpe, i-1)), toSMT(t))
+
+      case e @ UnaryOperator(u, _) =>
+        val op = e match {
+          case _: Not => SSymbol("not")
+          case _: UMinus => SSymbol("-")
+          case _ => reporter.fatalError("Unhandled unary "+e)
+        }
+
+        SList(op :: List(u).map(toSMT))
+
+      case e @ BinaryOperator(a, b, _) =>
+        val op = e match {
+          case _: Equals => SSymbol("=")
+          case _: Implies => SSymbol("=>")
+          case _: Iff => SSymbol("=")
+          case _: Plus => SSymbol("+")
+          case _: Minus => SSymbol("-")
+          case _: Times => SSymbol("*")
+          case _: Division => SSymbol("div")
+          case _: Modulo => SSymbol("mod")
+          case _: LessThan => SSymbol("<")
+          case _: LessEquals => SSymbol("<=")
+          case _: GreaterThan => SSymbol(">")
+          case _: GreaterEquals => SSymbol(">=")
+          case _ => reporter.fatalError("Unhandled binary "+e)
+        }
+
+        SList(op :: List(a, b).map(toSMT))
+
+      case e @ NAryOperator(sub, _) =>
+        val op = e match {
+          case _: And => SSymbol("and")
+          case _: Or => SSymbol("or")
+          case _: IfExpr => SSymbol("ite")
+          case f: FunctionInvocation => declareFunction(f.tfd)
+          case _ => reporter.fatalError("Unhandled nary "+e)
+        }
+
+        SList(op :: sub.map(toSMT).toList)
+
+
+      case o => unsupported("Tree: " + o)
+    }
+  }
+
+  def fromSMT(s: SExpr)(implicit bindings: Map[SSymbol, Expr]): Expr = s match {
+    case SInt(n)          => IntLiteral(n.toInt)
+    case SSymbol("TRUE")  => BooleanLiteral(true)
+    case SSymbol("FALSE") => BooleanLiteral(false)
+    case s: SSymbol if constructors.containsB(s) =>
+      constructors.toA(s) match {
+        case cct: CaseClassType =>
+          CaseClass(cct, Nil)
+        case t =>
+          unsupported("woot? for a single constructor for non-case-object: "+t)
+      }
+
+    case s: SSymbol =>
+      println(s)
+      bindings.getOrElse(s, variables.fromB(s).toVariable)
+
+    case SList((s: SSymbol) :: args) if(constructors.containsB(s)) => 
+      val rargs = args.map(fromSMT)
+      constructors.toA(s) match {
+        case cct: CaseClassType =>
+          CaseClass(cct, rargs)
+        case tt: TupleType =>
+          Tuple(rargs)
+        case t =>
+          unsupported("Woot? structural type that is non-structural: "+t)
+      }
+
+    case SList(List(SSymbol("LET"), SList(defs), body)) =>
+      val leonDefs: Seq[(SSymbol, Identifier, Expr)] = defs.map {
+        case SList(List(s : SSymbol, value)) =>
+          (s, FreshIdentifier(s.s), fromSMT(value))
+      }
+
+      val newBindings = bindings ++ leonDefs.map(d => d._1 -> d._3)
+      val newBody = fromSMT(body)(newBindings)
+
+      LetTuple(leonDefs.map(_._2), Tuple(leonDefs.map(_._3)), newBody)
+
+    case SList(SSymbol(app) :: args) => {
+      val recArgs = args.map(fromSMT)
+
+      app match {
+        case "-" =>
+          recArgs match {
+            case List(a) => UMinus(a)
+            case List(a, b) => Minus(a, b)
+          }
+
+        case _ =>
+          unsupported(s)
+      }
+    }
+    case _ =>
+      unsupported(s)
+  }
+
+  def sendCommand(cmd: Command): CommandResponse = {
+    reporter.ifDebug { debug =>
+      SMTPrinter(cmd, out)
+      out.write("\n")
+      out.flush
+    }
+
+    val response = interpreter.eval(cmd)
+    assert(!response.isInstanceOf[Error])
+    response
+  }
+}
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala
new file mode 100644
index 0000000000000000000000000000000000000000..0a6198af400e6ab43f08066113ea351958149586
--- /dev/null
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala
@@ -0,0 +1,82 @@
+/* Copyright 2009-2013 EPFL, Lausanne */
+
+package leon
+package solvers
+package smtlib
+
+import utils._
+import purescala._
+import Common._
+import Trees._
+import Extractors._
+import TypeTrees._
+
+import _root_.smtlib.sexpr.SExprs._
+import _root_.smtlib.interpreters.Z3Interpreter
+
+import _root_.smtlib.Commands.NonStandardCommand
+
+trait SMTLIBZ3Target extends SMTLIBTarget {
+  this: SMTLIBSolver =>
+
+  def targetName = "z3"
+
+  def getNewInterpreter() = new Z3Interpreter
+
+  val extSym = SSymbol("_")
+
+  var setSort: Option[SSymbol] = None
+
+  override def declareSort(t: TypeTree): SExpr = {
+    val tpe = normalizeType(t)
+    sorts.cachedB(tpe) {
+      tpe match {
+        case SetType(base) =>
+          declareSetSort(base)
+        case _ => super.declareSort(t)
+      }
+    }
+  }
+
+  def declareSetSort(of: TypeTree) = {
+    setSort match {
+      case None =>
+        val s = SSymbol("Set")
+        val t = SSymbol("T")
+        setSort = Some(s)
+
+        val cmd = NonStandardCommand(SList(SSymbol("define-sort"), s, SList(t), SList(SSymbol("Array"), t, SSymbol("Bool"))))
+        sendCommand(cmd)
+      case _ =>
+    }
+
+    SList(setSort.get, declareSort(of))
+  }
+
+
+  override def toSMT(e: Expr)(implicit bindings: Map[Identifier, SExpr]) = e match {
+      case fs @ FiniteSet(elems) =>
+        val ss = declareSort(fs.getType)
+        var res = SList(SList(SSymbol("as"), SSymbol("const"), ss), toSMT(BooleanLiteral(false)))
+
+        for (e <- elems) {
+          res = SList(SSymbol("store"), res, toSMT(e), toSMT(BooleanLiteral(true)))
+        }
+
+        res
+
+      case sd @ SetDifference(a, b) =>
+        // a -- b
+        // becomes:
+        // a && not(b)
+        SList(SList(extSym, SSymbol("map"), SSymbol("and")), toSMT(a), SList(SList(extSym, SSymbol("map"), SSymbol("not")), toSMT(b)))
+      case SetUnion(l, r) =>
+        SList(SList(extSym, SSymbol("map"), SSymbol("or")), toSMT(l), toSMT(r))
+
+      case SetIntersection(l, r) =>
+        SList(SList(extSym, SSymbol("map"), SSymbol("and")), toSMT(l), toSMT(r))
+
+      case _ =>
+        super.toSMT(e)
+  }
+}
diff --git a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala
index 208f8f18c30a5d1de382edb60dcf2243f83178fc..f61186f077adfe309754b52329a27432bda7935d 100644
--- a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala
+++ b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala
@@ -279,6 +279,8 @@ class FairZ3Solver(val context : LeonContext, val program: Program)
         var reintroducedSelf = false
 
         for (fi <- fis) {
+          var newCls = Seq[Z3AST]()
+
           val defBlocker = defBlockers.get(fi) match {
             case Some(defBlocker) =>
               // we already have defBlocker => f(args) = body
@@ -289,20 +291,28 @@ class FairZ3Solver(val context : LeonContext, val program: Program)
               defBlockers += fi -> defBlocker
 
               val template              = getTemplate(fi.tfd)
+              reporter.debug(template)
               val (newExprs, newBlocks) = template.instantiate(defBlocker, fi.args)
 
               for((i, fis2) <- newBlocks) {
                 registerBlocker(nextGeneration(gen), i, fis2)
               }
 
-              newClauses ++= newExprs
+              newCls ++= newExprs
               defBlocker
           }
 
           // We connect it to the defBlocker:   blocker => defBlocker
           if (defBlocker != id) {
-            newClauses ++= List(z3.mkImplies(id, defBlocker))
+            newCls ++= List(z3.mkImplies(id, defBlocker))
+          }
+
+          reporter.debug("Unrolling behind "+fi+" ("+newCls.size+")")
+          for (cl <- newCls) {
+          reporter.debug("  . "+cl)
           }
+
+          newClauses ++= newCls
         }
 
       }
@@ -548,6 +558,8 @@ class FairZ3Solver(val context : LeonContext, val program: Program)
               solver.assertCnstr(ncl)
             }
 
+            readLine()
+
             reporter.debug(" - finished unrolling")
           }
       }
diff --git a/src/main/scala/leon/synthesis/SynthesisContext.scala b/src/main/scala/leon/synthesis/SynthesisContext.scala
index 47bac75591896c4410edcf5b46f608fa485b4ccb..6aa67da6b09184fa86df2e6f477d9ce7ffc8be00 100644
--- a/src/main/scala/leon/synthesis/SynthesisContext.scala
+++ b/src/main/scala/leon/synthesis/SynthesisContext.scala
@@ -4,7 +4,7 @@ package leon
 package synthesis
 
 import solvers._
-import solvers.combinators.PortfolioSolver
+import solvers.combinators.PortfolioSolverSynth
 import solvers.z3._
 
 import purescala.Trees._
@@ -35,7 +35,7 @@ case class SynthesisContext(
   } else if (solversToUse.size == 1) {
     solversToUse.values.head
   } else {
-    SolverFactory( () => new PortfolioSolver(context, solversToUse.values.toSeq) with TimeoutAssumptionSolver)
+    SolverFactory( () => new PortfolioSolverSynth(context, solversToUse.values.toSeq) with TimeoutAssumptionSolver)
   }
 
   def newSolver: SynthesisContext.SynthesisSolver = {
diff --git a/src/main/scala/leon/synthesis/SynthesisPhase.scala b/src/main/scala/leon/synthesis/SynthesisPhase.scala
index ad404e220b2575d64fe44f274eb6f4091413c3d5..cf1321c9523d1cb3fe9cb64678e2f9e5b3a17fd0 100644
--- a/src/main/scala/leon/synthesis/SynthesisPhase.scala
+++ b/src/main/scala/leon/synthesis/SynthesisPhase.scala
@@ -1,4 +1,3 @@
-/* Copyright 2009-2014 EPFL, Lausanne */
 
 package leon
 package synthesis
@@ -25,7 +24,6 @@ object SynthesisPhase extends LeonPhase[Program, Program] {
     LeonValueOptionDef("timeout",         "--timeout=T",       "Timeout after T seconds when searching for synthesis solutions .."),
     LeonValueOptionDef("costmodel",       "--costmodel=cm",    "Use a specific cost model for this search"),
     LeonValueOptionDef("functions",       "--functions=f1:f2", "Limit synthesis of choose found within f1,f2,.."),
-    LeonValueOptionDef("solvers",         "--solvers=s1,s2",   "Use solvers s1 and s2 (fairz3,enum)", default = Some("fairz3")),
     // CEGIS options
     LeonFlagOptionDef( "cegis:gencalls",   "--cegis:gencalls",      "Include function calls in CEGIS generators",      true),
     LeonFlagOptionDef( "cegis:unintprobe", "--cegis:unintprobe",    "Check for UNSAT without bloecks and with uninterpreted functions", false),
@@ -39,8 +37,6 @@ object SynthesisPhase extends LeonPhase[Program, Program] {
   def processOptions(ctx: LeonContext): SynthesisOptions = {
     var options = SynthesisOptions()
 
-    val allSolvers = Set("fairz3", "enum")
-
     for(opt <- ctx.options) opt match {
       case LeonFlagOption("manual", v) =>
         options = options.copy(manualSearch = v)
@@ -70,13 +66,6 @@ object SynthesisPhase extends LeonPhase[Program, Program] {
             ctx.reporter.fatalError(errorMsg)
         }
 
-      case LeonValueOption("solvers", ListValue(ss)) =>
-        val unknownSolvers = ss.toSet -- allSolvers
-        if (unknownSolvers.nonEmpty) {
-          ctx.reporter.error("Unknown solver(s): "+unknownSolvers.mkString(", ")+" (Available: "+allSolvers.mkString(", ")+")")
-        }
-        options = options.copy(selectedSolvers = Set() ++ ss)
-
       case v @ LeonValueOption("timeout", _) =>
         v.asInt(ctx).foreach { t =>
           options = options.copy(timeoutMs  = Some(t.toLong))
diff --git a/src/main/scala/leon/utils/Bijection.scala b/src/main/scala/leon/utils/Bijection.scala
new file mode 100644
index 0000000000000000000000000000000000000000..12233df8ac96aba1b9cb1151b3a5663615c83479
--- /dev/null
+++ b/src/main/scala/leon/utils/Bijection.scala
@@ -0,0 +1,51 @@
+package leon.utils
+
+class Bijection[A, B] {
+  var a2b = Map[A, B]()
+  var b2a = Map[B, A]()
+
+  def +=(a: A, b: B): Unit = {
+    a2b += a -> b
+    b2a += b -> a
+  }
+
+  def +=(t: (A,B)): Unit = {
+    this += (t._1, t._2)
+  }
+
+  def clear(): Unit = {
+    a2b = Map()
+    b2a = Map()
+  }
+
+  def getA(b: B) = b2a.get(b)
+  def getB(a: A) = a2b.get(a)
+
+  def toA(b: B) = getA(b).get
+  def toB(a: A) = getB(a).get
+
+  def fromA(a: A) = getB(a).get
+  def fromB(b: B) = getA(b).get
+
+  def cachedB(a: A)(c: => B) = {
+    getB(a).getOrElse {
+      val res = c
+      this += a -> res
+      res
+    }
+  }
+
+  def cachedA(b: B)(c: => A) = {
+    getA(b).getOrElse {
+      val res = c
+      this += res -> b
+      res
+    }
+  }
+
+  def containsA(a: A) = a2b contains a
+  def containsB(b: B) = b2a contains b
+
+  def aSet = a2b.keySet
+  def bSet = b2a.keySet
+}
diff --git a/src/main/scala/leon/verification/AnalysisPhase.scala b/src/main/scala/leon/verification/AnalysisPhase.scala
index 2d8f544bcc99d21ced82ffcb47c8d53de3af22fd..6021b6b526db643cc58faa9d8e1557f70fb630f2 100644
--- a/src/main/scala/leon/verification/AnalysisPhase.scala
+++ b/src/main/scala/leon/verification/AnalysisPhase.scala
@@ -15,6 +15,8 @@ import solvers.combinators._
 
 import scala.collection.mutable.{Set => MutableSet}
 
+import _root_.smtlib.interpreters.Z3Interpreter
+
 object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
   val name = "Analysis"
   val description = "Leon Verification"
@@ -23,7 +25,6 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
 
   override val definedOptions : Set[LeonOptionDef] = Set(
     LeonValueOptionDef("functions", "--functions=f1:f2", "Limit verification to f1,f2,..."),
-    LeonValueOptionDef("solvers",   "--solvers=s1,s2",   "Use solvers s1 and s2 (fairz3,enum)", default = Some("fairz3")),
     LeonValueOptionDef("timeout",   "--timeout=T",       "Timeout after T seconds when trying to prove a verification condition.")
   )
 
@@ -147,13 +148,6 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
   def run(ctx: LeonContext)(program: Program) : VerificationReport = {
     var filterFuns: Option[Seq[String]] = None
     var timeout: Option[Int]             = None
-    var selectedSolvers                  = Set[String]("fairz3")
-
-    val allSolvers = Map(
-      "fairz3" -> SolverFactory(() => new FairZ3Solver(ctx, program) with TimeoutSolver),
-      "enum"   -> SolverFactory(() => new EnumerationSolver(ctx, program) with TimeoutSolver),
-      "smt"    -> SolverFactory(() => new smtlib.SMTLIBSolver(ctx, program, new _root_.smtlib.interpreters.Z3Interpreter))
-    )
 
     val reporter = ctx.reporter
 
@@ -161,12 +155,6 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
       case LeonValueOption("functions", ListValue(fs)) =>
         filterFuns = Some(fs)
 
-      case LeonValueOption("solvers", ListValue(ss)) =>
-        val unknownSolvers = ss.toSet -- allSolvers.keySet
-        if (unknownSolvers.nonEmpty) {
-          reporter.error("Unknown solver(s): "+unknownSolvers.mkString(", ")+" (Available: "+allSolvers.keys.mkString(", ")+")")
-        }
-        selectedSolvers = Set() ++ ss
 
       case v @ LeonValueOption("timeout", _) =>
         timeout = v.asInt(ctx)
@@ -175,15 +163,7 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
     }
 
     // Solvers selection and validation
-    val solversToUse = allSolvers.filterKeys(selectedSolvers)
-
-    val entrySolver = if (solversToUse.isEmpty) {
-      reporter.fatalError("No solver selected. Aborting")
-    } else if (solversToUse.size == 1) {
-      solversToUse.values.head
-    } else {
-      SolverFactory( () => new PortfolioSolver(ctx, solversToUse.values.toSeq) with TimeoutSolver)
-    }
+    val entrySolver = SolverFactory.getFromSettings(ctx, program)
 
     val mainSolver = timeout match {
       case Some(sec) =>
diff --git a/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala b/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala
index 86b394053f4945ad86872fbbb70bbd231aa9885a..3a52f45070b48c057b90027daebbbfed8966c8a8 100644
--- a/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala
+++ b/src/test/scala/leon/test/verification/PureScalaVerificationRegression.scala
@@ -25,7 +25,7 @@ class PureScalaVerificationRegression extends LeonTestSuite {
     PreprocessingPhase  andThen
     AnalysisPhase
 
-  private def mkTest(file : File, leonOptions : Seq[LeonOption], forError: Boolean)(block: Output=>Unit) = {
+  private def mkTest(file : File, leonOptions : Seq[String], forError: Boolean)(block: Output=>Unit) = {
     val fullName = file.getPath()
     val start = fullName.indexOf("regression")
 
@@ -39,10 +39,7 @@ class PureScalaVerificationRegression extends LeonTestSuite {
       assert(file.exists && file.isFile && file.canRead,
              "Benchmark %s is not a readable file".format(displayName))
 
-      val ctx = testContext.copy(
-        options = leonOptions.toList,
-        files   = List(file)
-      )
+      val ctx = createLeonContext((file.getPath +: leonOptions) :_*)
 
       val pipeline = mkPipeline
 
@@ -65,9 +62,10 @@ class PureScalaVerificationRegression extends LeonTestSuite {
       _.endsWith(".scala"))
 
     for(f <- fs) {
-      mkTest(f, List(LeonFlagOption("feelinglucky", true)), forError)(block)
-      mkTest(f, List(LeonFlagOption("codegen", true), LeonFlagOption("evalground", true), LeonFlagOption("feelinglucky", true)), forError)(block)
-      mkTest(f, List(LeonValueOption("solvers", "fairz3,enum"), LeonFlagOption("codegen", true), LeonFlagOption("evalground", true), LeonFlagOption("feelinglucky", true)), forError)(block)
+      mkTest(f, List("--feelinglucky", "--library=no"), forError)(block)
+      mkTest(f, List("--codegen", "--evalground", "--feelinglucky", "--library=no"), forError)(block)
+      mkTest(f, List("--solvers=fairz3,enum", "--codegen", "--evalground", "--feelinglucky", "--library=no"), forError)(block)
+      mkTest(f, List("--solvers=smt-z3", "--library=no"), forError)(block)
     }
   }