diff --git a/src/main/scala/inox/Options.scala b/src/main/scala/inox/Options.scala
index e19fdff3bba2e940172440441a54fffa0ab9bbab..2b06bd4589f1c3e363842cc2dc3b9402a0d53678 100644
--- a/src/main/scala/inox/Options.scala
+++ b/src/main/scala/inox/Options.scala
@@ -62,6 +62,10 @@ case class LongOptionDef(name: String, description: String, default: Long, usage
   val parser = longParser
 }
 
+case class IntOptionDef(name: String, description: String, default: Int, usageRhs: String) extends OptionDef[Int] {
+  val parser = intParser
+}
+
 class OptionValue[A] private (val optionDef: OptionDef[A], val value: A) {
   override def toString = s"--${optionDef.name}=$value"
   override def equals(other: Any) = other match {
@@ -82,9 +86,8 @@ object OptionValue {
 object OptionParsers {
   type OptionParser[A] = String => Option[A]
 
-  val longParser: OptionParser[Long] = { s =>
-    Try(s.toLong).toOption
-  }
+  val intParser: OptionParser[Int] = { s => Try(s.toInt).toOption }
+  val longParser: OptionParser[Long] = { s => Try(s.toLong).toOption }
   val stringParser: OptionParser[String] = Some(_)
   val booleanParser: OptionParser[Boolean] = {
     case "on"  | "true"  | "yes" | "" => Some(true)
diff --git a/src/main/scala/inox/ast/CallGraph.scala b/src/main/scala/inox/ast/CallGraph.scala
index eb0c3f0835543f4344a0a5f915611b00f32a3583..047ac4151ee3ba37f5e9e32c38f379fa1c27fc86 100644
--- a/src/main/scala/inox/ast/CallGraph.scala
+++ b/src/main/scala/inox/ast/CallGraph.scala
@@ -32,6 +32,10 @@ trait CallGraph {
     graph.transitiveSucc(f) contains f
   }
 
+  def isSelfRecursive(f: FunDef) = {
+    graph.succ(f) contains f
+  }
+
   def calls(from: FunDef, to: FunDef) = {
     graph.E contains SimpleEdge(from, to)
   }
diff --git a/src/main/scala/inox/ast/Definitions.scala b/src/main/scala/inox/ast/Definitions.scala
index 3d398cebd409976d07360bee49ee1383b17d69d1..f010ad44f382adeb2a0642ed07ba3a76261b5faa 100644
--- a/src/main/scala/inox/ast/Definitions.scala
+++ b/src/main/scala/inox/ast/Definitions.scala
@@ -33,7 +33,7 @@ trait Definitions { self: Trees =>
     * Both types share much in common and being able to reason about them
     * in a uniform manner can be useful in certain cases.
     */
-  protected[ast] trait VariableSymbol extends Typed {
+  protected[ast] trait VariableSymbol extends Tree with Typed {
     val id: Identifier
     val tpe: Type
 
@@ -59,14 +59,14 @@ trait Definitions { self: Trees =>
   implicit def convertToVal = new VariableConverter[ValDef] {
     def convert(vs: VariableSymbol): ValDef = vs match {
       case v: ValDef => v
-      case _ => ValDef(vs.id, vs.tpe)
+      case _ => ValDef(vs.id, vs.tpe).copiedFrom(vs)
     }
   }
 
   implicit def convertToVariable = new VariableConverter[Variable] {
     def convert(vs: VariableSymbol): Variable = vs match {
       case v: Variable => v
-      case _ => Variable(vs.id, vs.tpe)
+      case _ => Variable(vs.id, vs.tpe).copiedFrom(vs)
     }
   }
 
@@ -259,7 +259,7 @@ trait Definitions { self: Trees =>
       tparams: Seq[TypeParameterDef] = this.tparams,
       cons: Seq[Identifier] = this.cons,
       flags: Set[Flag] = this.flags
-    ): ADTSort = new ADTSort(id, tparams, cons, flags)
+    ): ADTSort = new ADTSort(id, tparams, cons, flags).copiedFrom(this)
   }
 
   /** Case classes/ ADT constructors. For single-case classes these may coincide
@@ -304,7 +304,7 @@ trait Definitions { self: Trees =>
       sort: Option[Identifier] = this.sort,
       fields: Seq[ValDef] = this.fields,
       flags: Set[Flag] = this.flags
-    ): ADTConstructor = new ADTConstructor(id, tparams, sort, fields, flags)
+    ): ADTConstructor = new ADTConstructor(id, tparams, sort, fields, flags).copiedFrom(this)
   }
 
   /** Represents an [[ADTDefinition]] whose type parameters have been instantiated to ''tps'' */
@@ -334,11 +334,15 @@ trait Definitions { self: Trees =>
 
   /** Represents an [[ADTSort]] whose type parameters have been instantiated to ''tps'' */
   case class TypedADTSort(definition: ADTSort, tps: Seq[Type])(implicit val symbols: Symbols) extends TypedADTDefinition {
+    copiedFrom(definition)
+
     lazy val constructors: Seq[TypedADTConstructor] = definition.constructors.map(_.typed(tps))
   }
 
   /** Represents an [[ADTConstructor]] whose type parameters have been instantiated to ''tps'' */
   case class TypedADTConstructor(definition: ADTConstructor, tps: Seq[Type])(implicit val symbols: Symbols) extends TypedADTDefinition {
+    copiedFrom(definition)
+
     lazy val fields: Seq[ValDef] = {
       val tmap = (definition.typeArgs zip tps).toMap
       if (tmap.isEmpty) definition.fields
@@ -401,12 +405,14 @@ trait Definitions { self: Trees =>
       returnType: Type = this.returnType,
       fullBody: Expr = this.fullBody,
       flags: Set[Flag] = this.flags
-    ): FunDef = new FunDef(id, tparams, params, returnType, fullBody, flags)
+    ): FunDef = new FunDef(id, tparams, params, returnType, fullBody, flags).copiedFrom(this)
   }
 
 
   /** Represents a [[FunDef]] whose type parameters have been instantiated with the specified types */
   case class TypedFunDef(fd: FunDef, tps: Seq[Type])(implicit symbols: Symbols) extends Tree {
+    copiedFrom(fd)
+
     val id = fd.id
 
     def signature = {
diff --git a/src/main/scala/inox/ast/Identifier.scala b/src/main/scala/inox/ast/Identifier.scala
index f9f847b80082d85ad00ceea1d395b43f93c01ccb..557de837f7e6ded1fd8fe2cee64a14cf56fcf666 100644
--- a/src/main/scala/inox/ast/Identifier.scala
+++ b/src/main/scala/inox/ast/Identifier.scala
@@ -1,6 +1,6 @@
 package inox.ast
 
-import inox.utils.UniqueCounter
+import inox.utils.{UniqueCounter, Positioned}
 
 /** Represents a unique symbol in Inox.
   *
@@ -12,7 +12,7 @@ class Identifier (
   val globalId: Int,
   private val id: Int,
   private val alwaysShowUniqueID: Boolean = false
-) extends Ordered[Identifier] {
+) extends Ordered[Identifier] with Positioned {
 
   override def equals(other: Any): Boolean = other match {
     case null => false
diff --git a/src/main/scala/inox/ast/ProgramEncoder.scala b/src/main/scala/inox/ast/ProgramEncoder.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e7cae628d5d925b235dad502bd0fcd32174623c7
--- /dev/null
+++ b/src/main/scala/inox/ast/ProgramEncoder.scala
@@ -0,0 +1,37 @@
+/* Copyright 2009-2016 EPFL, Lausanne */
+
+package inox
+package ast
+
+trait ProgramEncoder extends TreeBijection {
+  val sourceProgram: Program
+  lazy val s: sourceProgram.trees.type = sourceProgram.trees
+  lazy val targetProgram: Program { val trees: t.type } = sourceProgram.transform(encoder)
+
+  /* @nv XXX: ideally, we would want to replace `>>` by `override def andThen`, however this
+   *          seems to break the scala compiler for some weird reason... */
+  def >>(that: TreeBijection { val s: ProgramEncoder.this.t.type }): ProgramEncoder {
+    val sourceProgram: ProgramEncoder.this.sourceProgram.type
+    val t: that.t.type
+  } = new ProgramEncoder {
+    val sourceProgram: ProgramEncoder.this.sourceProgram.type = ProgramEncoder.this.sourceProgram
+    val t: that.t.type = that.t
+
+    val encoder = ProgramEncoder.this.encoder andThen that.encoder
+    val decoder = that.decoder andThen ProgramEncoder.this.decoder
+  }
+}
+
+object ProgramEncoder {
+  def empty(p: Program): ProgramEncoder {
+    val sourceProgram: p.type
+    val t: p.trees.type
+  } = new ProgramEncoder {
+    val sourceProgram: p.type = p
+    val t: p.trees.type = p.trees
+
+    object encoder extends p.trees.IdentitySymbolTransformer
+    object decoder extends p.trees.IdentitySymbolTransformer
+  }
+}
+
diff --git a/src/main/scala/inox/evaluators/ContextualEvaluator.scala b/src/main/scala/inox/evaluators/ContextualEvaluator.scala
index fba8ac52dfc68456d48d78747636fe849ba2d15c..3b4380a5f3dcd750376a51b536be960d0ec22bcb 100644
--- a/src/main/scala/inox/evaluators/ContextualEvaluator.scala
+++ b/src/main/scala/inox/evaluators/ContextualEvaluator.scala
@@ -3,11 +3,15 @@
 package inox
 package evaluators
 
+object optMaxCalls extends IntOptionDef("maxcalls",
+  "Maximum number of function invocations allowed during evaluation", 50000, "<PosInt> | -1 (for unbounded")
+
 trait ContextualEvaluator extends Evaluator {
-  val maxSteps: Int
   import program._
   import program.trees._
 
+  lazy val maxSteps: Int = options.findOptionOrDefault(optMaxCalls)
+
   trait RecContext[RC <: RecContext[RC]] {
     def mappings: Map[ValDef, Expr]
     def newVars(news: Map[ValDef, Expr]): RC
diff --git a/src/main/scala/inox/evaluators/EncodingEvaluator.scala b/src/main/scala/inox/evaluators/EncodingEvaluator.scala
new file mode 100644
index 0000000000000000000000000000000000000000..97e887d07b75178ab5b9f5adcce39e475cc2c595
--- /dev/null
+++ b/src/main/scala/inox/evaluators/EncodingEvaluator.scala
@@ -0,0 +1,47 @@
+/* Copyright 2009-2016 EPFL, Lausanne */
+
+package inox
+package evaluators
+
+trait EncodingEvaluator extends DeterministicEvaluator { self =>
+  import program.trees._
+
+  protected val encoder: ast.ProgramEncoder { val sourceProgram: program.type }
+
+  protected val underlying: DeterministicEvaluator {
+    val program: encoder.targetProgram.type
+  }
+
+  lazy val options = underlying.options
+
+  def eval(expr: Expr, model: Map[ValDef, Expr]): EvaluationResult = {
+    val res = underlying.eval(
+      encoder.encode(expr),
+      model.map(p => encoder.encode(p._1) -> encoder.encode(p._2))
+    )
+
+    res match {
+      case EvaluationResults.Successful(v) => EvaluationResults.Successful(encoder.decode(v))
+      case EvaluationResults.RuntimeError(msg) => EvaluationResults.RuntimeError(msg)
+      case EvaluationResults.EvaluatorError(msg) => EvaluationResults.EvaluatorError(msg)
+    }
+  }
+}
+
+object EncodingEvaluator {
+  def solving(p: Program)
+             (enc: ast.ProgramEncoder { val sourceProgram: p.type })
+             (ev: DeterministicEvaluator with SolvingEvaluator { val program: enc.targetProgram.type }) = {
+    new {
+      val program: p.type = p
+    } with EncodingEvaluator with SolvingEvaluator {
+      lazy val encoder: enc.type = enc
+      lazy val underlying = ev
+
+      def getSolver(opts: OptionValue[_]*) = {
+        solvers.combinators.EncodingSolverFactory(p)(enc)(underlying.getSolver(opts : _*))
+      }
+    }
+  }
+
+}
diff --git a/src/main/scala/inox/evaluators/RecursiveEvaluator.scala b/src/main/scala/inox/evaluators/RecursiveEvaluator.scala
index d3b0e2da23d19456a9333f7c27274f9d17968f40..56ea64bf691e05c52da75c5630468299b2a0b3df 100644
--- a/src/main/scala/inox/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/inox/evaluators/RecursiveEvaluator.scala
@@ -513,9 +513,8 @@ object RecursiveEvaluator {
   def apply(p: InoxProgram, opts: Options): RecursiveEvaluator { val program: p.type } = {
     new {
       val program: p.type = p
-    } with RecursiveEvaluator with HasDefaultGlobalContext with HasDefaultRecContext {
       val options = opts
-      val maxSteps = 50000
+    } with RecursiveEvaluator with HasDefaultGlobalContext with HasDefaultRecContext {
       def getSolver(moreOpts: OptionValue[_]*) = solvers.SolverFactory(p, opts ++ moreOpts)
     }
   }
diff --git a/src/main/scala/inox/evaluators/SolvingEvaluator.scala b/src/main/scala/inox/evaluators/SolvingEvaluator.scala
index dd0e9fa5a6c41413b38f19bc98507db4c25073c6..1a720c78adcaaf8eae5a81f838cc1cb9257590bb 100644
--- a/src/main/scala/inox/evaluators/SolvingEvaluator.scala
+++ b/src/main/scala/inox/evaluators/SolvingEvaluator.scala
@@ -4,6 +4,7 @@ package inox
 package evaluators
 
 import solvers._
+import solvers.combinators._
 
 import scala.collection.mutable.{Map => MutableMap}
 
@@ -20,7 +21,10 @@ trait SolvingEvaluator extends Evaluator {
     def default = MutableMap.empty
   }
 
-  def getSolver(opts: OptionValue[_]*): SolverFactory { val program: SolvingEvaluator.this.program.type }
+  def getSolver(opts: OptionValue[_]*): SolverFactory {
+    val program: SolvingEvaluator.this.program.type
+    type S <: TimeoutSolver { val program: SolvingEvaluator.this.program.type }
+  }
 
   private val chooseCache: MutableMap[Choose, Expr] = MutableMap.empty
   private val forallCache: MutableMap[Forall, Expr] = MutableMap.empty
diff --git a/src/main/scala/inox/solvers/SolverFactory.scala b/src/main/scala/inox/solvers/SolverFactory.scala
index 3af74feb6e2a68e3ccbfab5e856d082ad3f7f2cc..c02ac30a089c2fbdfeef42c6e4c0511d073ced1d 100644
--- a/src/main/scala/inox/solvers/SolverFactory.scala
+++ b/src/main/scala/inox/solvers/SolverFactory.scala
@@ -49,66 +49,68 @@ object SolverFactory {
   def getFromName(name: String)
                  (p: Program, opts: Options)
                  (ev: DeterministicEvaluator with SolvingEvaluator { val program: p.type },
-                   enc: ProgramEncoder { val sourceProgram: p.type; val t: inox.trees.type }):
-                  SolverFactory { val program: p.type; type S <: TimeoutSolver } = name match {
-    case "nativez3" => create(p)(name, () => new {
-      val program: p.type = p
-      val options = opts
-      val encoder = enc
-    } with z3.NativeZ3Solver with TimeoutSolver {
-      val evaluator = ev
-    })
-
-    case "unrollz3" => create(p)(name, () => new {
-      val program: p.type = p
-      val options = opts
-      val encoder = enc
-    } with unrolling.UnrollingSolver with theories.Z3Theories with TimeoutSolver {
-      val evaluator = ev
+                   enc: ast.ProgramEncoder { val sourceProgram: p.type; val t: inox.trees.type }):
+                  SolverFactory { val program: p.type; type S <: TimeoutSolver { val program: p.type } } = {
+    name match {
+      case "nativez3" => create(p)(name, () => new {
+        val program: p.type = p
+        val options = opts
+        val encoder = enc
+      } with z3.NativeZ3Solver with TimeoutSolver {
+        val evaluator = ev
+      })
 
-      object underlying extends {
-        val program: targetProgram.type = targetProgram
+      case "unrollz3" => create(p)(name, () => new {
+        val program: p.type = p
         val options = opts
-      } with z3.UninterpretedZ3Solver
-    })
+        val encoder = enc
+      } with unrolling.UnrollingSolver with theories.Z3Theories with TimeoutSolver {
+        val evaluator = ev
 
-    case "smt-cvc4" => create(p)(name, () => new {
-      val program: p.type = p
-      val options = opts
-      val encoder = enc
-    } with unrolling.UnrollingSolver with theories.CVC4Theories with TimeoutSolver {
-      val evaluator = ev
+        object underlying extends {
+          val program: targetProgram.type = targetProgram
+          val options = opts
+        } with z3.UninterpretedZ3Solver
+      })
 
-      object underlying extends {
-        val program: targetProgram.type = targetProgram
+      case "smt-cvc4" => create(p)(name, () => new {
+        val program: p.type = p
         val options = opts
-      } with smtlib.CVC4Solver
-    })
+        val encoder = enc
+      } with unrolling.UnrollingSolver with theories.CVC4Theories with TimeoutSolver {
+        val evaluator = ev
 
-    case "smt-z3" => create(p)(name, () => new {
-      val program: p.type = p
-      val options = opts
-      val encoder = enc
-    } with unrolling.UnrollingSolver with theories.Z3Theories with TimeoutSolver {
-      val evaluator = ev
+        object underlying extends {
+          val program: targetProgram.type = targetProgram
+          val options = opts
+        } with smtlib.CVC4Solver
+      })
 
-      object underlying extends {
-        val program: targetProgram.type = targetProgram
+      case "smt-z3" => create(p)(name, () => new {
+        val program: p.type = p
         val options = opts
-      } with smtlib.Z3Solver
-    })
+        val encoder = enc
+      } with unrolling.UnrollingSolver with theories.Z3Theories with TimeoutSolver {
+        val evaluator = ev
 
-    case "enum" => create(p)(name, () => new {
-      val program: p.type = p
-      val options = opts
-    } with EnumerationSolver with TimeoutSolver {
-      val evaluator = ev
-      val grammars: GrammarsUniverse {val program: p.type} = new GrammarsUniverse {
-        val program: p.type = p
-      }
-    })
+        object underlying extends {
+          val program: targetProgram.type = targetProgram
+          val options = opts
+        } with smtlib.Z3Solver
+      })
 
-    case _ => throw FatalError("Unknown solver: " + name)
+      case "enum" => create(p)(name, () => new {
+        val program: p.type = p
+        val options = opts
+      } with EnumerationSolver with TimeoutSolver {
+        val evaluator = ev
+        val grammars: GrammarsUniverse {val program: p.type} = new GrammarsUniverse {
+          val program: p.type = p
+        }
+      })
+
+      case _ => throw FatalError("Unknown solver: " + name)
+    }
   }
 
   val solversPretty = "Available: " + solverNames.toSeq.sortBy(_._1).map {
@@ -117,20 +119,24 @@ object SolverFactory {
 
   val solvers: Set[String] = solverNames.map(_._1).toSet
 
-  def apply(name: String, p: InoxProgram, opts: Options): 
-            SolverFactory { val program: p.type; type S <: TimeoutSolver } = {
-    getFromName(name)(p, opts)(RecursiveEvaluator(p, opts), ProgramEncoder.empty(p))
-  }
-
-  def apply(p: InoxProgram, opts: Options): SolverFactory { val program: p.type; type S <: TimeoutSolver } =
-    opts.findOptionOrDefault(InoxOptions.optSelectedSolvers).toSeq match {
-      case Seq() => throw FatalError("No selected solver")
-      case Seq(single) => apply(single, p, opts)
-      case multiple => PortfolioSolverFactory(p) {
-        multiple.map(name => apply(name, p, opts))
-      }
+  def apply(name: String, p: InoxProgram, opts: Options): SolverFactory {
+    val program: p.type
+    type S <: TimeoutSolver { val program: p.type }
+  } = getFromName(name)(p, opts)(RecursiveEvaluator(p, opts), ast.ProgramEncoder.empty(p))
+
+  def apply(p: InoxProgram, opts: Options): SolverFactory {
+    val program: p.type
+    type S <: TimeoutSolver { val program: p.type }
+  } = opts.findOptionOrDefault(InoxOptions.optSelectedSolvers).toSeq match {
+    case Seq() => throw FatalError("No selected solver")
+    case Seq(single) => apply(single, p, opts)
+    case multiple => PortfolioSolverFactory(p) {
+      multiple.map(name => apply(name, p, opts))
     }
+  }
 
-  def default(p: InoxProgram): SolverFactory { val program: p.type; type S <: TimeoutSolver } =
-    apply(p, p.ctx.options)
+  def default(p: InoxProgram): SolverFactory {
+    val program: p.type
+    type S <: TimeoutSolver { val program: p.type }
+  } = apply(p, p.ctx.options)
 }
diff --git a/src/main/scala/inox/solvers/combinators/EncodingSolver.scala b/src/main/scala/inox/solvers/combinators/EncodingSolver.scala
index 726cbe8c61138404c6976ff5fef9083ad952023f..c02e32927008aeb6065498a198a070761d18d73d 100644
--- a/src/main/scala/inox/solvers/combinators/EncodingSolver.scala
+++ b/src/main/scala/inox/solvers/combinators/EncodingSolver.scala
@@ -4,54 +4,37 @@ package inox
 package solvers
 package combinators
 
-import ast._
-
-trait ProgramEncoder extends TreeBijection {
-  val sourceProgram: Program
-  lazy val s: sourceProgram.trees.type = sourceProgram.trees
-  lazy val targetProgram: Program { val trees: t.type } = sourceProgram.transform(encoder)
-
-  /* @nv XXX: ideally, we would want to replace `>>` by `override def andThen`, however this
-   *          seems to break the scala compiler for some weird reason... */
-  def >>(that: TreeBijection { val s: ProgramEncoder.this.t.type }): ProgramEncoder {
-    val sourceProgram: ProgramEncoder.this.sourceProgram.type
-    val t: that.t.type
-  } = new ProgramEncoder {
-    val sourceProgram: ProgramEncoder.this.sourceProgram.type = ProgramEncoder.this.sourceProgram
-    val t: that.t.type = that.t
-
-    val encoder = ProgramEncoder.this.encoder andThen that.encoder
-    val decoder = that.decoder andThen ProgramEncoder.this.decoder
-  }
-}
+trait EncodingSolver extends Solver {
+  import program.trees._
+  import SolverResponses._
 
-object ProgramEncoder {
-  def empty(p: Program): ProgramEncoder {
-    val sourceProgram: p.type
-    val t: p.trees.type
-  } = new ProgramEncoder {
-    val sourceProgram: p.type = p
-    val t: p.trees.type = p.trees
+  protected val encoder: ast.ProgramEncoder { val sourceProgram: program.type }
+  protected lazy val t: encoder.t.type = encoder.t
 
-    object encoder extends p.trees.IdentitySymbolTransformer
-    object decoder extends p.trees.IdentitySymbolTransformer
+  protected val underlying: Solver {
+    val program: encoder.targetProgram.type
   }
-}
 
-trait EncodingSolver extends Solver {
-  import program.trees._
+  lazy val name = "E:" + underlying.name
+  lazy val options = underlying.options
 
-  protected val programEncoder: ProgramEncoder { val sourceProgram: program.type }
+  def assertCnstr(expr: Expr) = underlying.assertCnstr(encoder.encode(expr))
 
-  protected def encode(vd: ValDef): programEncoder.t.ValDef = programEncoder.encode(vd)
-  protected def decode(vd: programEncoder.t.ValDef): ValDef = programEncoder.decode(vd)
-
-  protected def encode(v: Variable): programEncoder.t.Variable = programEncoder.encode(v)
-  protected def decode(v: programEncoder.t.Variable): Variable = programEncoder.decode(v)
+  private def convert(config: Configuration)
+                     (resp: config.Response[Map[t.ValDef, t.Expr], Set[t.Expr]]):
+                      config.Response[Map[ValDef, Expr], Set[Expr]] = {
+    config.convert(resp,
+      (model: Map[t.ValDef, t.Expr]) => model.map(p => encoder.decode(p._1) -> encoder.decode(p._2)),
+      (assumptions: Set[t.Expr]) => assumptions.map(encoder.decode)
+    )
+  }
 
-  protected def encode(e: Expr): programEncoder.t.Expr = programEncoder.encode(e)
-  protected def decode(e: programEncoder.t.Expr): Expr = programEncoder.decode(e)
+  def check(config: CheckConfiguration) = convert(config)(underlying.check(config))
+  def checkAssumptions(config: Configuration)(assumptions: Set[Expr]) =
+    convert(config)(underlying.checkAssumptions(config)(assumptions.map(encoder.encode)))
 
-  protected def encode(tpe: Type): programEncoder.t.Type = programEncoder.encode(tpe)
-  protected def decode(tpe: programEncoder.t.Type): Type = programEncoder.decode(tpe)
+  def free() = underlying.free()
+  def reset() = underlying.reset()
+  def push() = underlying.push()
+  def pop() = underlying.pop()
 }
diff --git a/src/main/scala/inox/solvers/combinators/EncodingSolverFactory.scala b/src/main/scala/inox/solvers/combinators/EncodingSolverFactory.scala
new file mode 100644
index 0000000000000000000000000000000000000000..0c679eca0aef6dd3a341dc7202fa071905fa17c6
--- /dev/null
+++ b/src/main/scala/inox/solvers/combinators/EncodingSolverFactory.scala
@@ -0,0 +1,28 @@
+/* Copyright 2009-2016 EPFL, Lausanne */
+
+package inox
+package solvers
+package combinators
+
+object EncodingSolverFactory {
+  def apply(p: Program)
+           (enc: ast.ProgramEncoder { val sourceProgram: p.type })
+           (sf: SolverFactory {
+             val program: enc.targetProgram.type
+             type S <: TimeoutSolver { val program: enc.targetProgram.type }
+           }): SolverFactory {
+             val program: p.type
+             type S <: TimeoutSolver { val program: p.type }
+           } = {
+
+    SolverFactory.create(p)("E:" + sf.name, () => new {
+      val program: p.type = p
+    } with EncodingSolver with TimeoutSolver {
+      val encoder: enc.type = enc
+      val underlying = sf.getNewSolver()
+
+      def interrupt() = underlying.interrupt()
+      def recoverInterrupt() = underlying.recoverInterrupt()
+    })
+  }
+}
diff --git a/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala b/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala
index 57daddc41e257a3f5f6c4faa88b8e4524ba14fff..4aaa154b56bf050835b7c68dc1ef557aac809c3a 100644
--- a/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala
+++ b/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala
@@ -21,7 +21,7 @@ object optFeelingLucky extends FlagOptionDef(
 object optUnrollAssumptions  extends FlagOptionDef(
   "unrollassumptions", "Use unsat-assumptions to drive unfolding while remaining fair", false)
 
-trait AbstractUnrollingSolver extends Solver with EncodingSolver {
+trait AbstractUnrollingSolver extends Solver {
 
   import program._
   import program.trees._
@@ -30,7 +30,7 @@ trait AbstractUnrollingSolver extends Solver with EncodingSolver {
 
   protected type Encoded
 
-  protected val encoder: ProgramEncoder { val sourceProgram: program.type }
+  protected val encoder: ast.ProgramEncoder { val sourceProgram: program.type }
 
   protected val theories: TheoryEncoder { val sourceProgram: AbstractUnrollingSolver.this.encoder.targetProgram.type }
 
@@ -40,8 +40,19 @@ trait AbstractUnrollingSolver extends Solver with EncodingSolver {
   protected lazy val t: programEncoder.t.type = programEncoder.t
   protected lazy val targetProgram: programEncoder.targetProgram.type = programEncoder.targetProgram
 
-  protected def encode(tpe: FunctionType): t.FunctionType =
-    programEncoder.encode(tpe).asInstanceOf[t.FunctionType]
+  protected final def encode(vd: ValDef): t.ValDef = programEncoder.encode(vd)
+  protected final def decode(vd: t.ValDef): ValDef = programEncoder.decode(vd)
+
+  protected final def encode(v: Variable): t.Variable = programEncoder.encode(v)
+  protected final def decode(v: t.Variable): Variable = programEncoder.decode(v)
+
+  protected final def encode(e: Expr): t.Expr = programEncoder.encode(e)
+  protected final def decode(e: t.Expr): Expr = programEncoder.decode(e)
+
+  protected final def encode(tpe: Type): t.Type = programEncoder.encode(tpe)
+  protected final def decode(tpe: t.Type): Type = programEncoder.decode(tpe)
+  protected final def encode(ft: FunctionType): t.FunctionType =
+    programEncoder.encode(ft).asInstanceOf[t.FunctionType]
 
   protected val templates: Templates {
     val program: targetProgram.type
diff --git a/src/main/scala/inox/transformers/Collector.scala b/src/main/scala/inox/transformers/Collector.scala
index 0da53d7668477d58d048443fa3ee0ea794f83a4f..191e3c73ad8bd1e22b85f83a81cfba881beff199 100644
--- a/src/main/scala/inox/transformers/Collector.scala
+++ b/src/main/scala/inox/transformers/Collector.scala
@@ -21,13 +21,16 @@ trait Collector extends Transformer {
     super.rec(e, current)
   }
 
-  /** Traverses the expression and collects */
-  final def collect(e: Expr): List[Result] = {
+  /** Traverses an [[Expr]] with the specified environment and collects */
+  final def collect(e: Expr, init: Env) = {
     results = Nil
-    transform(e)
+    transform(e, init)
     results
   }
 
+  /** Traverses an [[Expr]] with the initial environment and collects */
+  final def collect(e: Expr): List[Result] = collect(e, initEnv)
+
   /** Collect the expressions in a [[FunDef]]'s body */
   final def collect(fd: FunDef): List[Result] = collect(fd.fullBody)
 }