diff --git a/build.sbt b/build.sbt
index 121a1311a55c452093541116e74a593be8094999..fc3aa2584872a570b4301e62c145ae93ba9b7983 100644
--- a/build.sbt
+++ b/build.sbt
@@ -38,6 +38,7 @@ libraryDependencies ++= Seq(
   "info.hupel" %% "libisabelle" % "0.1.1",
   "info.hupel" %% "libisabelle-setup" % "0.1.1",
   "info.hupel" %% "pide-2015" % "0.1.1",
+  "org.ow2.asm" % "asm-all" % "5.0.4",
   "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.6.0-rc2"
 )
 
diff --git a/src/main/scala/leon/LeonContext.scala b/src/main/scala/leon/LeonContext.scala
index 8677364ee1cd5948a80001a72424e45a0538afcf..dd4e25ba35ef621c92b5cc880163be77c424295f 100644
--- a/src/main/scala/leon/LeonContext.scala
+++ b/src/main/scala/leon/LeonContext.scala
@@ -16,6 +16,7 @@ case class LeonContext(
   interruptManager: InterruptManager,
   options: Seq[LeonOption[Any]] = Seq(),
   files: Seq[File] = Seq(),
+  classDir: Option[File] = None,
   timers: TimerStorage = new TimerStorage
 ) {
 
diff --git a/src/main/scala/leon/Main.scala b/src/main/scala/leon/Main.scala
index b29f017c66eb80fb6e8fd6bb601c773cb1927a0c..3a8cb39df090fcb5ca3d3d902bedf6a52557026b 100644
--- a/src/main/scala/leon/Main.scala
+++ b/src/main/scala/leon/Main.scala
@@ -9,6 +9,7 @@ object Main {
   lazy val allPhases: List[LeonPhase[_, _]] = {
     List(
       frontends.scalac.ExtractionPhase,
+      frontends.scalac.ClassgenPhase,
       utils.TypingPhase,
       FileOutputPhase,
       purescala.RestoreMethods,
@@ -142,7 +143,7 @@ object Main {
     import purescala.Definitions.Program
     import purescala.{FunctionClosure, RestoreMethods}
     import utils.FileOutputPhase
-    import frontends.scalac.ExtractionPhase
+    import frontends.scalac.{ExtractionPhase, ClassgenPhase}
     import synthesis.SynthesisPhase
     import termination.TerminationPhase
     import xlang.FixReportLabels
@@ -172,6 +173,7 @@ object Main {
       displayHelp(ctx.reporter, error = false)
     } else {
       val pipeBegin: Pipeline[List[String], Program] =
+        ClassgenPhase andThen
         ExtractionPhase andThen
         new PreprocessingPhase(xlangF)
 
diff --git a/src/main/scala/leon/codegen/runtime/RuntimeResources.scala b/src/main/scala/leon/codegen/runtime/RuntimeResources.scala
new file mode 100644
index 0000000000000000000000000000000000000000..86c84d78396b0a59a6371906a90d4325b6bca0fd
--- /dev/null
+++ b/src/main/scala/leon/codegen/runtime/RuntimeResources.scala
@@ -0,0 +1,43 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.codegen.runtime
+
+import leon.utils.UniqueCounter
+
+import java.util.WeakHashMap
+import java.lang.ref.WeakReference
+import scala.collection.mutable.{HashMap => MutableMap}
+
+/**
+ * This class allows an evaluator to statically register a resource, identified
+ * by an integer. This identifier can be stored in bytecode, allowing .class to
+ * access the resource at runtime.
+ *
+ * The user/evaluator should keep hold of the returned Token, otherwise the
+ * resource may be garbage-collected.
+ *
+ * This is not statically-typed, but
+ *
+ *   get[A]( register[A]( ... ) )
+ *
+ *  should always be safe.
+ */
+object RuntimeResources {
+  case class Token(id: Int)
+
+  private val intCounter = new UniqueCounter[Unit]
+
+  private[this] val store = new WeakHashMap[Token, WeakReference[AnyRef]]()
+
+  def register[T <: AnyRef](data: T): Token = synchronized {
+    val t = Token(intCounter.nextGlobal)
+
+    store.put(t, new WeakReference(data))
+
+    t
+  }
+
+  def get[T <: AnyRef](id: Int): T = {
+    store.get(Token(id)).get.asInstanceOf[T]
+  }
+}
diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
index f17f9caefb644bfb08c1c5d9b7a429c2f408a872..68709c64e1bcd21df8de780c4a6c317af6384581 100644
--- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
@@ -21,7 +21,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
   val name = "evaluator"
   val description = "Recursive interpreter for PureScala expressions"
 
-  private implicit val ctx0 = ctx
+  private implicit val _ = ctx
 
   type RC <: RecContext
   type GC <: GlobalContext
@@ -29,6 +29,8 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
   case class EvalError(msg : String) extends Exception
   case class RuntimeError(msg : String) extends Exception
 
+  val scalaEv = new ScalacEvaluator(this, ctx, prog)
+
   trait RecContext {
     def mappings: Map[Identifier, Expr]
 
@@ -169,12 +171,16 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         }
       }
 
-      if(!tfd.hasBody && !rctx.mappings.isDefinedAt(tfd.id)) {
-        throw EvalError("Evaluation of function with unknown implementation.")
-      }
+      val callResult = if (tfd.fd.annotations("extern") && ctx.classDir.isDefined) {
+        scalaEv.call(tfd, evArgs)
+      } else {
+        if(!tfd.hasBody && !rctx.mappings.isDefinedAt(tfd.id)) {
+          throw EvalError("Evaluation of function with unknown implementation.")
+        }
 
-      val body = tfd.body.getOrElse(rctx.mappings(tfd.id))
-      val callResult = e(body)(frame, gctx)
+        val body = tfd.body.getOrElse(rctx.mappings(tfd.id))
+        e(body)(frame, gctx)
+      }
 
       tfd.postcondition match  {
         case Some(post) =>
diff --git a/src/main/scala/leon/evaluators/ScalacEvaluator.scala b/src/main/scala/leon/evaluators/ScalacEvaluator.scala
new file mode 100644
index 0000000000000000000000000000000000000000..2b13d2655b43bd5e9a41fd236a8acb963d106356
--- /dev/null
+++ b/src/main/scala/leon/evaluators/ScalacEvaluator.scala
@@ -0,0 +1,469 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon
+package evaluators
+
+import leon.codegen.runtime.RuntimeResources
+
+import purescala.Definitions._
+import purescala.DefOps._
+import purescala.Expressions._
+import purescala.Types._
+
+import java.io.File
+import java.nio.file.Files
+import java.net.{URL, URLClassLoader}
+import java.lang.reflect.{Constructor, Method}
+
+import frontends.scalac.FullScalaCompiler
+
+import scala.tools.nsc.{Settings=>NSCSettings,CompilerCommand}
+
+/**
+ * Call scalac-compiled functions from within Leon
+ *
+ * Known limitations:
+ *  - Multiple argument lists
+ */
+class ScalacEvaluator(ev: Evaluator, ctx: LeonContext, pgm: Program) extends LeonComponent {
+  implicit val _: Program = pgm
+
+  val name = "Evaluator of external functions"
+  val description = "Evaluator for non-purescala functions"
+
+  implicit val debugSection = utils.DebugSectionEvaluation
+
+  val classPaths: List[File] = ctx.classDir.toList
+
+  lazy val runtimeTok = {
+    RuntimeResources.register(this)
+  }
+
+  private def unsupported(err: String): Nothing = {
+    throw new RuntimeException(err)
+  }
+
+  private def encodeName(name: String): String = {
+    scala.reflect.NameTransformer.encode(name)
+  }
+
+  private def jvmName(d: Definition): String = {
+    compiledName(d).replace(".", "/")
+  }
+
+  private def jvmClassName(tpe: TypeTree): String = tpe match {
+    case IntegerType =>
+      "scala/math/BigInt"
+
+    case TupleType(subs) =>
+      f"scala/Tuple${subs.size}%d"
+
+    case UnitType =>
+      "scala/runtime/BoxedUnit"
+
+    case ct: ClassType =>
+      jvmName(ct.classDef)
+
+    case _ =>
+      ctx.reporter.internalError(s"$tpe is not a jvm class type ?!?")
+  }
+
+  private def compiledName(d: Definition): String = {
+    // Scala encodes fullname of modules using ".". After the module, it
+    // becomes an inner class, with '$'
+    val path = pathFromRoot(d)
+
+    val pathToModule = path.takeWhile{!_.isInstanceOf[ModuleDef]}
+    val rest = path.drop(pathToModule.size)
+
+    val upToModule = pathToNames(pathToModule, false).map(encodeName).mkString(".")
+
+    if(rest.isEmpty) {
+      upToModule
+    } else {
+      d match {
+        case md: ModuleDef =>
+          upToModule+"."+encodeName(md.id.name)+"$"
+        case _ =>
+          val afterModule = pathToNames(rest, false).map(encodeName).mkString("$")
+          upToModule+"."+afterModule
+      }
+    }
+  }
+
+  def call(tfd: TypedFunDef, args: Seq[Expr]): Expr = {
+    val fd = tfd.fd
+
+    val methodName = encodeName(fd.id.name)
+    
+    val jvmArgs = args.map(leonToScalac)
+
+    val (clazz, jvmRec, jvmCallArgs) = fd.methodOwner match {
+      case Some(cd) =>
+        (cd, jvmArgs.head, jvmArgs.tail)
+
+      case None =>
+        val md = moduleOf(fd).get
+
+        val jvmModule = loadClass(compiledName(md))
+        val rec       = jvmModule.getField("MODULE$").get(null)
+
+        (md, rec, jvmArgs)
+    }
+
+    val jvmClassName = compiledName(clazz)
+    val jvmClass     = loadClass(jvmClassName)
+
+    ctx.reporter.debug(s"Calling $jvmClassName.${tfd.signature}(${args.mkString(", ")})")
+
+    // Lookup method in jvmClass
+
+    jvmClass.getMethods().filter(_.getName() == methodName).toList match {
+      case List(meth) =>
+
+        val res = if (jvmCallArgs.isEmpty) {
+          meth.invoke(jvmRec)
+        } else {
+          meth.invoke(jvmRec,  jvmCallArgs: _*)
+        }
+
+        scalacToLeon(res, tfd.returnType)
+
+      case Nil =>
+        unsupported(s"Unable to lookup method")
+
+      case ms =>
+        unsupported(s"Ambiguous reference to method: ${ms.size} methods found with a matching name")
+
+    }
+  }
+
+  val localClassLoader = {
+    classOf[ScalacEvaluator].getClassLoader()
+  }
+
+  val toInstrument = {
+    val fds = (for (fd <- pgm.definedFunctions if !fd.annotations("extern")) yield {
+      encodeName(fd.id.name) -> fd
+    }).toMap
+
+    fds.groupBy { case (n, fd) =>
+      compiledName(fd.methodOwner.getOrElse(moduleOf(fd).get))
+    }
+  }
+
+  val compiledClassLoader = {
+    val classUrls = ctx.classDir.map(_.toURI.toURL)
+    val cl = new URLClassLoader(classUrls.toArray, localClassLoader)
+    new InterceptingClassLoader(cl)
+  }
+
+  def loadClass(classname: String): Class[_] = {
+    compiledClassLoader.loadClass(classname)
+  }
+
+  def leonToScalac(e: Expr): AnyRef = e match {
+    case eo: ExternalObject =>
+      eo
+
+    case CharLiteral(v) =>
+      new java.lang.Character(v)
+
+    case IntLiteral(v) =>
+      new java.lang.Integer(v)
+
+    case InfiniteIntegerLiteral(v) =>
+      v
+
+    case BooleanLiteral(v) =>
+      new java.lang.Boolean(v)
+
+    case Tuple(exprs) =>
+      val name = f"scala.Tuple${exprs.size}%d"
+
+      val cl = localClassLoader.loadClass(name)
+      val constr = cl.getConstructors().head.asInstanceOf[Constructor[AnyRef]]
+
+      constr.newInstance(exprs.map(leonToScalac) : _*)
+
+    case UnitLiteral() =>
+      Unit.box(())
+
+    case FiniteSet(exprs, tpe) =>
+
+      val cl = compiledClassLoader.loadClass("leon.lang.Set")
+      val constr = cl.getConstructors().head.asInstanceOf[Constructor[AnyRef]]
+
+      constr.newInstance(Set(exprs.toSeq.map(leonToScalac) : _*))
+
+    case FiniteMap(pairs, ktpe, vtpe) =>
+
+      val cl = compiledClassLoader.loadClass("leon.lang.Map")
+      val constr = cl.getConstructors().head.asInstanceOf[Constructor[AnyRef]]
+
+      constr.newInstance(Map(
+        pairs.map { case (k, v) =>
+          leonToScalac(k) -> leonToScalac(v)
+        }.toSeq : _*
+      ))
+
+    case CaseClass(cct, fields) =>
+
+      val name   = compiledName(cct.classDef)
+
+      val cl = loadClass(name)
+      val constr = cl.getConstructors().head.asInstanceOf[Constructor[AnyRef]]
+      constr.newInstance(fields.map(leonToScalac) : _*)
+
+
+    case Lambda(_, _) =>
+      unsupported("It is not yet possible to pass a closure to an @extern function")
+
+    case t: Terminal =>
+      unsupported("Unhandled conversion to scala runtime: "+t)
+
+    case _ =>
+      unsupported("Trying to convert non-terminal: "+e)
+  }
+
+  def productToElems(p: Product, tps: Seq[TypeTree]): Seq[Expr] = {
+    for ((t,i) <- tps.zipWithIndex) yield {
+      scalacToLeon(p.productElement(i), t)
+    }
+  }
+
+  def scalacToLeon(o: Any, t: TypeTree): Expr = t match {
+    case BooleanType =>
+      BooleanLiteral(o.asInstanceOf[Boolean].booleanValue)
+    case Int32Type =>
+      IntLiteral(o.asInstanceOf[Integer].intValue)
+    case CharType =>
+      CharLiteral(o.asInstanceOf[Character].charValue)
+    case IntegerType =>
+      InfiniteIntegerLiteral(o.asInstanceOf[BigInt])
+    case UnitType =>
+      UnitLiteral()
+    case TupleType(tps) =>
+      Tuple(productToElems(o.asInstanceOf[Product], tps))
+    case cct: CaseClassType =>
+      CaseClass(cct, productToElems(o.asInstanceOf[Product], cct.fieldsTypes))
+
+    case act: AbstractClassType =>
+      val className = o.getClass.getName
+
+      act.knownCCDescendants.find(cct => compiledName(cct.classDef) == className) match {
+        case Some(cct) =>
+          scalacToLeon(o, cct)
+
+        case None =>
+          unsupported("Expected "+act+", got: "+className)
+      }
+
+    case SetType(b) =>
+      val cl = compiledClassLoader.loadClass("leon.lang.Set")
+
+      val s = cl.getMethod("theSet").invoke(o).asInstanceOf[Set[_]]
+
+      FiniteSet(s.iterator.map(scalacToLeon(_, b)).toSet, b)
+
+    case MapType(ktpe, vtpe) =>
+
+      val cl = compiledClassLoader.loadClass("leon.lang.Map")
+
+      val s = cl.getMethod("theMap").invoke(o).asInstanceOf[Map[_, _]]
+
+      FiniteMap(s.iterator.map {
+        case (k, v) => scalacToLeon(k, ktpe) -> scalacToLeon(v, vtpe)
+      }.toSeq, ktpe, vtpe)
+
+    case FunctionType(_, _) =>
+      unsupported("It is not possible to pass a closure from @extern back to leon")
+
+    case _ =>
+      unsupported("Unhandled conversion from scala runtime: "+t)
+  }
+
+  def jvmCallBack(cName: String, fName: String, args: Array[AnyRef]): AnyRef = {
+    toInstrument.get(cName).flatMap(_.get(fName)) match {
+      case Some(fd) =>
+        val leonArgs = fd.params.map(_.getType).zip(args).map {
+          case (tpe, arg) => scalacToLeon(arg, tpe)
+        }
+
+        val fi = FunctionInvocation(fd.typed, leonArgs)
+        leonToScalac(ev.eval(fi).result.getOrElse {
+          unsupported("Evaluation in Leon failed!")
+        })
+
+      case None =>
+        unsupported("Unable to locate callback function "+cName+"."+fName)
+    }
+  }
+
+  /**
+   * Black magic here we come!
+   */
+  import org.objectweb.asm.ClassReader;
+  import org.objectweb.asm.ClassWriter;
+  import org.objectweb.asm.ClassVisitor;
+  import org.objectweb.asm.MethodVisitor;
+  import org.objectweb.asm.Opcodes;
+
+  class InterceptingClassLoader(p: ClassLoader) extends ClassLoader(p) {
+    import java.io._
+
+    var loaded = Set[String]()
+
+    override def loadClass(name: String, resolve: Boolean): Class[_] = {
+      if (loaded(name)) {
+        super.loadClass(name, resolve)
+      } else {
+        loaded += name
+
+        if (!(toInstrument contains name)) {
+          super.loadClass(name, resolve)
+        } else {
+          val bs = new ByteArrayOutputStream();
+          val is = getResourceAsStream(name.replace('.', '/') + ".class");
+          val buf = new Array[Byte](512);
+          var len = is.read(buf);
+          while (len  > 0) {
+            bs.write(buf, 0, len);
+            len = is.read(buf)
+          }
+
+          // Transform bytecode
+          val cr = new ClassReader(bs.toByteArray());
+          val cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
+          val cv = new LeonCallsClassVisitor(cw, name, toInstrument(name));
+          cr.accept(cv, 0);
+
+          val res = cw.toByteArray();
+
+          defineClass(name, res, 0, res.length);
+        }
+      }
+    }
+  }
+
+  class LeonCallsClassVisitor(cv: ClassVisitor, cName: String, fdMap: Map[String, FunDef]) extends ClassVisitor(Opcodes.ASM5, cv) {
+    override def visitMethod(access: Int, fName: String, desc: String, sig: String, exceptions: Array[String]) = {
+      val mv = super.visitMethod(access, fName, desc, sig, exceptions)
+      if ((fdMap contains fName)) {
+        new LeonCallsMethodVisitor(mv, cName, fName, fdMap(fName))
+      } else {
+        mv
+      }
+    }
+  }
+
+  class LeonCallsMethodVisitor(mv: MethodVisitor, cName: String, fName: String, fd: FunDef) extends MethodVisitor(Opcodes.ASM5, mv) {
+
+    def box(tpe: TypeTree) = tpe match {
+      case Int32Type =>
+        mv.visitTypeInsn(Opcodes.NEW, "java/lang/Integer")
+        mv.visitInsn(Opcodes.DUP_X1)
+        mv.visitInsn(Opcodes.SWAP)
+        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Integer", "<init>", "(I)V", false)
+
+      case CharType =>
+        mv.visitTypeInsn(Opcodes.NEW, "java/lang/Character")
+        mv.visitInsn(Opcodes.DUP_X1)
+        mv.visitInsn(Opcodes.SWAP)
+        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Character", "<init>", "(C)V", false)
+
+      case BooleanType  =>
+        mv.visitTypeInsn(Opcodes.NEW, "java/lang/Boolean")
+        mv.visitInsn(Opcodes.DUP_X1)
+        mv.visitInsn(Opcodes.SWAP)
+        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Boolean", "<init>", "(Z)V", false)
+
+      case _ =>
+    }
+
+    def unbox(tpe: TypeTree) = tpe match {
+      case Int32Type =>
+        mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Integer")
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false)
+
+      case CharType =>
+        mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Character")
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false)
+
+      case BooleanType  =>
+        mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean")
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false)
+
+      case tpe =>
+        mv.visitTypeInsn(Opcodes.CHECKCAST, jvmClassName(tpe))
+    }
+
+    def loadOpCode(tpe: TypeTree) = tpe match {
+      case CharType => Opcodes.ILOAD
+      case Int32Type => Opcodes.ILOAD
+      case BooleanType => Opcodes.ILOAD
+      case _ => Opcodes.ALOAD
+    }
+
+    def returnOpCode(tpe: TypeTree) = tpe match {
+      case CharType => Opcodes.IRETURN
+      case Int32Type => Opcodes.IRETURN
+      case BooleanType => Opcodes.IRETURN
+      case UnitType => Opcodes.RETURN
+      case _ => Opcodes.ARETURN
+    }
+
+
+    override def visitCode() {
+      mv.visitLdcInsn(runtimeTok.id)
+      mv.visitLdcInsn(cName)
+      mv.visitLdcInsn(fName)
+
+      // If we are visiting a method, we need to add the receiver in the arguments array
+      val readOffset = fd.methodOwner match {
+        case Some(cd) =>
+          // $this is the receiver
+          0
+        case _ =>
+          // We skip the module object
+          1
+      }
+
+      // Array of arguments called
+      mv.visitLdcInsn(fd.params.size)
+      mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object")
+
+      // Note: fd.params includes the receiver!
+      // Add actual arguments, box necessary values
+      for ((tpe, i) <- fd.params.map(_.getType).zipWithIndex) {
+        // Array ref
+        mv.visitInsn(Opcodes.DUP)
+        mv.visitLdcInsn(i)
+        // Arg Value
+        mv.visitVarInsn(loadOpCode(tpe), i+readOffset)
+        box(tpe)
+        mv.visitInsn(Opcodes.AASTORE)
+      }
+
+
+      mv.visitMethodInsn(Opcodes.INVOKESTATIC,
+                         "leon/evaluators/LeonJVMCallBacks",
+                         "callBack",
+                         "(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;",
+                          false)
+
+      unbox(fd.returnType)
+      mv.visitInsn(returnOpCode(fd.returnType))
+      mv.visitEnd();
+    }
+  }
+}
+
+case class ExternalObject(o: Any, getType: TypeTree) extends Expr with Terminal
+
+object LeonJVMCallBacks {
+  def callBack(token: Int, className: String, methodName: String, args: Array[AnyRef]): AnyRef = {
+    val ev = RuntimeResources.get[ScalacEvaluator](token)
+    ev.jvmCallBack(className, methodName, args)
+  }
+}
diff --git a/src/main/scala/leon/frontends/scalac/ClassgenPhase.scala b/src/main/scala/leon/frontends/scalac/ClassgenPhase.scala
new file mode 100644
index 0000000000000000000000000000000000000000..b2650740483613b02d3cd208b913febdb15bca5f
--- /dev/null
+++ b/src/main/scala/leon/frontends/scalac/ClassgenPhase.scala
@@ -0,0 +1,82 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package frontends.scalac
+
+import purescala.Definitions.Program
+import utils._
+
+import scala.tools.nsc.{Settings,CompilerCommand}
+import java.io.File
+import java.nio.file.Files
+
+object ClassgenPhase extends LeonPhase[List[String], List[String]] {
+
+  val optExtern = LeonFlagOptionDef("extern", "Run @extern function on the JVM", false)
+
+  override val definedOptions: Set[LeonOptionDef[Any]] = Set(optExtern)
+
+  val name = "Scalac .class generation"
+  val description = "Generation of .class for evaluation of @extern functions"
+
+  implicit val debug = DebugSectionTrees
+
+  def run(ctx: LeonContext, args: List[String]): (LeonContext, List[String]) = {
+    if (ctx.findOptionOrDefault(optExtern)) {
+      val timer = ctx.timers.frontend.extern.start()
+
+      val settings = new Settings
+
+      val scalaLib = Option(scala.Predef.getClass.getProtectionDomain.getCodeSource).map{
+        _.getLocation.getPath
+      }.orElse( for {
+        // We are in Eclipse. Look in Eclipse plugins to find scala lib
+        eclipseHome <- Option(System.getenv("ECLIPSE_HOME")) 
+        pluginsHome = eclipseHome + "/plugins"
+        plugins <- scala.util.Try(new File(pluginsHome).listFiles().map{ _.getAbsolutePath }).toOption
+        path <- plugins.find{ _ contains "scala-library"}
+      } yield path).getOrElse( ctx.reporter.fatalError(
+        "No Scala library found. If you are working in Eclipse, " +
+        "make sure to set the ECLIPSE_HOME environment variable to your Eclipse installation home directory"
+      ))
+
+      val tempOut = Files.createTempDirectory(new File("tmp/").toPath, "classes").toFile
+
+      settings.classpath.value   = scalaLib
+      settings.usejavacp.value   = false
+      settings.deprecation.value = true
+      settings.outdir.value      = tempOut.getPath
+
+      val compilerOpts = Build.libFiles ::: args.filterNot(_.startsWith("--"))
+
+      val command = new CompilerCommand(compilerOpts, settings) {
+        override val cmdName = "leon"
+      }
+
+      if(command.ok) {
+        // Debugging code for classpath crap
+        // new scala.tools.util.PathResolver(settings).Calculated.basis.foreach { cp =>
+        //   cp.foreach( p =>
+        //     println(" => "+p.toString)
+        //   )
+        // }
+
+
+        val compiler = new FullScalaCompiler(settings, ctx)
+        val run = new compiler.Run
+        run.compile(command.files)
+
+        timer.stop()
+
+        val ctx2 = ctx.copy(classDir = Some(tempOut))
+
+        (ctx2, args)
+      } else {
+        ctx.reporter.fatalError("No input program.")
+      }
+    } else {
+      (ctx, args)
+    }
+  }
+}
+
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index 9fa7606da23741a13f4d705374f867c23957fc53..299e8995a072084bba0adf0a98603e64b1611aac 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -947,7 +947,11 @@ trait CodeExtraction extends ASTExtractors {
 
     private def extractTreeOrNoTree(tr: Tree)(implicit dctx: DefContext): LeonExpr = {
       try {
-        extractTree(tr)
+        val res = extractTree(tr)
+        if (dctx.isExtern) {
+          reporter.warning(res.getPos, "External function could be extracted as Leon tree")
+        }
+        res
       } catch {
         case e: ImpureCodeEncounteredException =>
           if (dctx.isExtern) {
diff --git a/src/main/scala/leon/frontends/scalac/FullScalaCompiler.scala b/src/main/scala/leon/frontends/scalac/FullScalaCompiler.scala
new file mode 100644
index 0000000000000000000000000000000000000000..2ae74e2020ccc391f5b478d60fda42d5f2809ab5
--- /dev/null
+++ b/src/main/scala/leon/frontends/scalac/FullScalaCompiler.scala
@@ -0,0 +1,16 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package frontends.scalac
+
+import scala.tools.nsc.{Global,Settings=>NSCSettings}
+import scala.reflect.internal.Positions
+
+class FullScalaCompiler(settings: NSCSettings, ctx: LeonContext) extends Global(settings, new SimpleReporter(settings, ctx.reporter)) with Positions {
+
+  class Run extends super.Run {
+    override def progress(current: Int, total: Int) {
+      ctx.reporter.onCompilerProgress(current, total)
+    }
+  }
+}
diff --git a/src/main/scala/leon/purescala/DefOps.scala b/src/main/scala/leon/purescala/DefOps.scala
index 89c0fce8145f9ad43b1924e8cbb81f57de3d0a56..1e5e120112330ca85fccfdded79f425c0035214b 100644
--- a/src/main/scala/leon/purescala/DefOps.scala
+++ b/src/main/scala/leon/purescala/DefOps.scala
@@ -22,7 +22,13 @@ object DefOps {
     case other => pgm.units.find(_.containsDef(df))
   }
 
-  private def pathFromRoot(df: Definition)(implicit pgm: Program): List[Definition] = {
+  def moduleOf(df: Definition)(implicit pgm: Program): Option[ModuleDef] = df match {
+    case p : Program => None
+    case u : UnitDef => None
+    case other => pgm.units.flatMap(_.modules).find { _.containsDef(df) }
+  }
+
+  def pathFromRoot(df: Definition)(implicit pgm: Program): List[Definition] = {
     def rec(from: Definition): List[Definition] = {
       from :: (if (from == df) {
         Nil
diff --git a/testcases/extern/Editor.scala b/testcases/extern/Editor.scala
new file mode 100644
index 0000000000000000000000000000000000000000..d843697f1c362e0ef33ef4a980a785dc4418d789
--- /dev/null
+++ b/testcases/extern/Editor.scala
@@ -0,0 +1,229 @@
+import leon.lang._
+import leon.annotation._
+import leon.lang.synthesis._
+import leon.collection._
+import scala.reflect.runtime.universe._
+import scala.reflect.api.{TypeCreator, Universe, Mirror}
+
+
+import scala.collection.immutable.{List => ScalaList, Nil => ScalaNil}
+
+object Editor {
+  abstract class Mode
+  case object Edit extends Mode
+  case object Quitted extends Mode
+
+  case class State(line: List[Int], cursor: Int, buffer: List[Int], actions: List[Action], mode: Mode) {
+    def setLine(l: List[Int]) = State(l, cursor, buffer, actions, mode)
+    def setCursor(c: Int) = State(line, c, buffer, actions, mode)
+    def setBuffer(b: List[Int]) = State(line, cursor, b, actions, mode)
+    def addAction(a: Action) = State(line, cursor, buffer, Cons(a, actions), mode)
+    def setMode(m: Mode) = State(line, cursor, buffer, actions, m)
+  }
+
+  sealed abstract class Action
+  case object Unknown extends Action
+  case object Write extends Action
+  case object Quit extends Action
+  case object Replace extends Action
+  case object Erase extends Action
+  case class Content(l: List[Int]) extends Action
+
+  @extern
+  def getCommand(): List[Int] = {
+    print("> ")
+    readLine().toList.map(_.toInt)
+  }
+
+  @extern
+  def getOracle(): Oracle[Action] = {
+    new KeyboardOracle()
+  }
+
+  def replStep(state: State): State = {
+    if (state.mode == Quitted) {
+      state
+    } else {
+      implicit val o = getOracle()
+      val a = {
+      //val a = withOracle { implicit o: Oracle[Action] =>
+        val i = getCommand()
+
+        getAction(i, state)
+      }
+
+      val newState = doAction(state, a)
+      replStep(newState)
+    }
+  }
+
+  @extern
+  def unknown() = {
+    println("?")
+  }
+
+  @extern
+  def display(a: Action, s: State) = {
+    println("  | Action : "+a)
+    println("  | Line   : "+s.line)
+    println("  | Curs   : "+s.cursor)
+    println("  | Buff   : "+s.buffer)
+    println("  | A*     : "+s.actions.map(_.toString).mkString(", "))
+  }
+
+  def getAction(input: List[Int], state: State)(implicit o: Oracle[Action]): Action = {
+    ???
+  }
+
+  def doAction(state: State, action: Action): State = {
+    val c = state.cursor
+    val l = state.line
+
+    val tmp = display(action, state)
+
+    val ns = (action, state.actions) match {
+      case (Content(cnt), Cons(Write, _)) =>
+        val nl = l.take(c) ++ cnt ++ l.drop(c)
+        state.setLine(nl).setCursor(c + cnt.size)
+      case (Content(cnt), Cons(Replace, _)) =>
+        val nl = l.take(c) ++ cnt ++ l.drop(c+cnt.size)
+        state.setLine(nl).setCursor(c + cnt.size)
+      case (Erase, _) =>
+        state.setLine(Nil()).setCursor(0)
+      case (Quit, _) =>
+        state.setMode(Quitted)
+      case _ =>
+        unknown()
+        state
+    }
+
+    ns.addAction(action)
+  }
+
+  @ignore
+  @extern
+  class KeyboardOracle[T: TypeTag](lvl: Int = 0) extends Oracle[T] {
+    var result: T = _
+
+    val ind = "  "*lvl
+
+    lazy val h: T = {
+      val m = runtimeMirror(getClass.getClassLoader)
+      val oracleClass = typeOf[KeyboardOracle[T]].typeSymbol.asClass
+      val refOracle   = m.reflectClass(oracleClass)
+
+      val ls = Erase
+
+      val tpeClass = typeOf[T].typeSymbol.asClass
+      println(s"~${ind} Requesting value for (_ <: ${typeOf[T]}):")
+
+      var askAgain = true
+      while (askAgain) {
+        if (tpeClass.isSealed) {
+          val TypeRef(pre, sym, tpts) = typeOf[T]
+          val subClasses = tpeClass.knownDirectSubclasses.toSeq.sortBy(_.name.toString)
+
+          for ((sub, i) <- subClasses.zipWithIndex) {
+            println(f"~${ind}  $i%2d: $sub%s")
+          }
+
+          print(s"~${ind} > ")
+          val i = readLine().toInt
+          if (i >= 0 && i < subClasses.size) {
+            val subClass = subClasses(i).asClass
+            val subType  = TypeRef(pre, subClass, tpts)
+
+            val refClass = m.reflectClass(subClass)
+            val ctor     = subType.declaration(nme.CONSTRUCTOR).asMethod
+            val refCtor  = refClass.reflectConstructor(ctor)
+            val ctorTpe  = ctor.typeSignatureIn(subType).asInstanceOf[MethodType]
+
+            val rargs = for (arg <- ctorTpe.params) yield {
+              val argTpe        = arg.typeSignature
+              val oracleTpe     = typeRef(NoPrefix, oracleClass, List(argTpe))
+              val oracleCtor    = oracleTpe.declaration(nme.CONSTRUCTOR).asMethod
+              val refOracleCtor = refOracle.reflectConstructor(oracleCtor)
+
+              val typeTag = TypeTag(m, new TypeCreator {
+                def apply[U <: Universe with Singleton](m: Mirror[U]): U#Type = {
+                  if (m == runtimeMirror(getClass.getClassLoader)) {
+                    argTpe.asInstanceOf[U#Type]
+                  } else {
+                    sys.error("Unsupported")
+                  }
+                }
+              })
+
+              // Build an instance of this oracle:
+              val oracle = refOracleCtor(lvl+1, typeTag)
+
+              // We call its `head` method
+              val head = oracleTpe.declaration(("head": TermName)).asMethod
+
+              m.reflect(oracle).reflectMethod(head)()
+            }
+
+            result = refCtor(rargs: _*).asInstanceOf[T]
+            askAgain = false;
+          }
+        } else if (tpeClass.name.toString == "Int") {
+          print(s"~${ind} > ")
+          try {
+            result = readLine().toInt.asInstanceOf[T]
+            askAgain = false
+          } catch {
+            case _: Throwable =>
+          }
+        } else if (tpeClass.name.toString == "Boolean") {
+          print(s"~${ind} > ")
+          readLine() match {
+            case "true" =>
+              result = true.asInstanceOf[T]
+              askAgain = false
+            case "false" =>
+              result = false.asInstanceOf[T]
+              askAgain = false
+            case _ =>
+          }
+        } else {
+          sys.error("Don't know how to generate for non-sealed class")
+        }
+      }
+
+      result
+    }
+
+
+    lazy val l = new KeyboardOracle[T]()
+    lazy val r = new KeyboardOracle[T]()
+    override def head  = h
+    override def left  = l
+    override def right = r
+  }
+
+  def repl() = {
+    val state = State(Nil(), 0, Nil(), Nil(), Edit)
+    replStep(state)
+  }
+
+  @ignore
+  @extern
+  implicit def scalaToList[T](l: ScalaList[T]): List[T] = {
+    l.foldLeft[List[T]](Nil())( (l, e) => Cons(e, l) )
+  }
+
+  @ignore
+  @extern
+  implicit def listToScala[T](l: List[T]): ScalaList[T] = l match {
+    case Nil() => ScalaNil
+    case Cons(h, t) => h :: listToScala(t)
+  }
+
+  @ignore
+  @extern
+  implicit def listToString(l: List[Int]): String = {
+    l.map(_.toChar).mkString("")
+  }
+
+
+}
diff --git a/testcases/extern/EditorSimple.scala b/testcases/extern/EditorSimple.scala
new file mode 100644
index 0000000000000000000000000000000000000000..888f09debaa25c7223759470105d333b30148746
--- /dev/null
+++ b/testcases/extern/EditorSimple.scala
@@ -0,0 +1,170 @@
+import leon.lang._
+import leon.annotation._
+import leon.lang.synthesis._
+import leon.collection._
+import scala.reflect.runtime.universe._
+import scala.reflect.api.{TypeCreator, Universe, Mirror}
+
+
+import scala.collection.immutable.{List => ScalaList, Nil => ScalaNil}
+
+object Editor {
+  abstract class Mode
+  case object Edit extends Mode
+  case object Quitted extends Mode
+
+  case class State(line: List[Int], cursor: Int, buffer: List[Int], actions: List[Action], mode: Mode) {
+    def setLine(l: List[Int]) = State(l, cursor, buffer, actions, mode)
+    def setCursor(c: Int) = State(line, c, buffer, actions, mode)
+    def setBuffer(b: List[Int]) = State(line, cursor, b, actions, mode)
+    def addAction(a: Action) = State(line, cursor, buffer, Cons(a, actions), mode)
+    def setMode(m: Mode) = State(line, cursor, buffer, actions, m)
+  }
+
+  sealed abstract class Action
+  case object Unknown extends Action
+  case object Write extends Action
+  case object Quit extends Action
+  case class MoveCursor(to: Int) extends Action
+  case object Replace extends Action
+  case object Erase extends Action
+  case class Content(l: List[Int]) extends Action
+
+  //@extern
+  //def getCommand(): List[Int] = {
+  //  print("> ")
+  //  readLine().toList.map(_.toInt)
+  //}
+
+  def getCommand()(implicit o: Oracle[List[Int]]): List[Int] = {
+    ???
+  }
+
+  @extern
+  def unknown() = {
+    println("?")
+  }
+
+  @extern
+  def displayState(s: State) = {
+    println("  | Line   : "+listToString(s.line))
+    println("  | Cursor : "+(" "*s.cursor)+"^")
+    println("  | Buffer : "+listToString(s.buffer))
+    println("  | A*     : "+s.actions.collect {
+        case Content(l) => "Content("+listToString(l)+")"
+        case a => a.toString
+      }.mkString(", "))
+  }
+
+  @extern
+  def display(input: List[Int], a: Action, s: State) = {
+    println("  | Input  : "+listToString(input))
+    println("  | Action : "+a)
+    println("  ~~~~~~~~~~~~~~~~~~~")
+    displayState(s)
+  }
+
+  def replStep(state: State)(implicit o: Oracle[List[Int]]): State = {
+    if (state.mode == Quitted) {
+      state
+    } else {
+      val i = getCommand()
+      val a = getAction(i, state)
+
+      doAction(state, a)
+    }
+  }
+
+  def getAction(input: List[Int], state: State): Action = {
+    if (input == Cons(113, Nil())) {
+      Quit
+    } else if (input == Cons(100, Nil())) {
+      Erase
+    } else if (input == Cons(94, Nil())) {
+      MoveCursor(0)
+    } else if (input == Cons(36, Nil())) {
+      MoveCursor(-1)
+    } else if (input == Cons(114, Nil())) {
+      Replace
+    } else if (input == Cons(119, Nil())) {
+      Write
+    } else if (input.size > 1) {
+      Content(input)
+    } else {
+      Unknown
+    }
+  }
+
+  def doAction(state: State, action: Action): State = {
+    val c = state.cursor
+    val l = state.line
+
+
+    val ns = (action, state.actions) match {
+      case (Content(cnt), Cons(Write, _)) =>
+        val nl = l.take(c) ++ cnt ++ l.drop(c)
+        state.setLine(nl).setCursor(c + cnt.size)
+      case (Content(cnt), Cons(Replace, _)) =>
+        val nl = l.take(c) ++ cnt ++ l.drop(c+cnt.size)
+        state.setLine(nl).setCursor(c + cnt.size)
+      case (MoveCursor(i), _) =>
+        if (i < 0) {
+          state.setCursor(state.line.size+1+i)
+        } else {
+          state.setCursor(i)
+        }
+      case (Erase, _) =>
+        state.setLine(Nil()).setCursor(0)
+      case (Quit, _) =>
+        state.setMode(Quitted)
+      case (Unknown, _) =>
+        //unknown()
+        state
+      case _ =>
+        state
+    }
+
+    ns.addAction(action)
+  }
+
+  def repl() = {
+    val finalState = {
+      withOracle { implicit o: Oracle[List[Int]] =>
+        {
+          val state = State(Nil(), 0, Nil(), Nil(), Edit)
+          val res = replStep(replStep(replStep(state)(o.left))(o.right.left))(o.right.right.left)
+          val tmp = displayState(res)
+          res
+        } ensuring {
+          s => s.line == Cons(97, Cons(97, Cons(97, Nil()))) && s.mode == Quitted
+        }
+      }
+    }
+    finalState
+  }
+
+  @ignore
+  @extern
+  implicit def scalaToList[T](l: ScalaList[T]): List[T] = {
+    l.foldRight[List[T]](Nil())( (e, l) => Cons(e, l) )
+  }
+
+  @ignore
+  @extern
+  implicit def listToScala[T](l: List[T]): ScalaList[T] = l match {
+    case Nil() => ScalaNil
+    case Cons(h, t) => h :: listToScala(t)
+  }
+
+  @ignore
+  @extern
+  implicit def listToString(l: List[Int]): String = {
+    l.map(_.toChar).mkString("")
+  }
+
+  @ignore
+  @extern
+  def asList(l: String): List[Int] = {
+    l.toList.map(_.toInt)
+  }
+}
diff --git a/testcases/extern/Game.scala b/testcases/extern/Game.scala
new file mode 100644
index 0000000000000000000000000000000000000000..fc365d8109711e37a11ba9c5861548ec5f08ca9c
--- /dev/null
+++ b/testcases/extern/Game.scala
@@ -0,0 +1,311 @@
+import leon.lang._
+import leon.annotation._
+import leon.lang.synthesis._
+import leon.collection._
+
+object Test {
+  case class Pos(x: Int, y: Int) {
+    def up      = Pos(x, y-1)
+    def down    = Pos(x, y+1)
+    def left    = Pos(x-1, y)
+    def right   = Pos(x+1, y)
+
+    // Simple over aproximation of the distance
+    def distance(o: Pos) = {
+      val dx = o.x-x
+      val dy = o.y-y
+
+      (dx*dx + dy*dy)
+    }
+
+    def update(a: Action) = a match {
+      case MoveUp =>
+        up
+      case MoveDown =>
+        down
+      case MoveLeft =>
+        left
+      case MoveRight =>
+        right
+      case Noop =>
+        this
+    }
+  }
+
+  case class Map(walls: Set[Pos], size: Pos) {
+    // Returns whether a certain position is a valid position to be in given
+    // the map
+    def isValidPos(p: Pos): Boolean = {
+      p.x >= 0 && p.y >= 0 &&
+      p.x < size.x && p.y < size.y &&
+      !(walls contains p)
+    }
+
+    def allValidPos(lp: List[Pos]): Boolean = lp match {
+      case Cons(h, t) => isValidPos(h) && allValidPos(t)
+      case Nil() => true
+    }
+  }
+
+  abstract class Action;
+  case object MoveUp extends Action
+  case object MoveDown extends Action
+  case object MoveLeft extends Action
+  case object MoveRight extends Action
+  case object Noop extends Action
+
+  case class Game(player: Pos,
+                  monsters: List[Pos],
+                  map: Map) {
+
+    def isValidAction(pos: Pos, action: Action) = {
+      val np = pos.update(action)
+      map.isValidPos(np)
+    }
+
+    def isDead = {
+      isAtPositions(player, monsters)
+    }
+
+    def isAtPositions(p: Pos, lp: List[Pos]): Boolean = lp match {
+      case Cons(h,t) => (h == p) || isAtPositions(p, t)
+      case _ => false
+    }
+
+    def isValid = {
+      map.isValidPos(player) &&
+      map.allValidPos(monsters)
+    }
+
+    def isRunning = !isDead
+  }
+
+  def step(g: Game)(implicit o: Oracle[Action]): Game = {
+    if (g.isDead) {
+      g
+    } else {
+      val g1 = stepPlayer(g)
+      Game(g1.player, stepMonsters(g1, g1.monsters), g1.map)
+    }
+  }
+
+  def steps(g: Game, b: Int)(implicit o: Oracle[Action]): Game = {
+    if (b <= 0 || g.isDead) {
+      g
+    } else {
+      steps(step(g)(o.left), b-1)(o.right)
+    }
+  }
+
+  def gameStep(g: Game)(implicit o: Oracle[Action]): Game = {
+    val u = display(g)
+    //withOracle { implicit o: Oracle[Action] => {
+      steps(g, 1)
+      //step(step(g))
+    //  step(step(g)(o.left))(o.right)
+    //} ensuring { g => !g.isDead }}
+  }
+
+  def play(g: Game)(implicit o: Oracle[Action]): Game = {
+    val r = gameStep(g)(o.left)
+    if (r.isDead) {
+      r
+    } else {
+      play(r)(o.left)
+    }
+  }
+
+  def stepMonster(g: Game, oldPos: Pos): Pos = {
+    val a = choose { a: Action =>
+      bestTowards(g, oldPos, a, g.player)
+    }
+
+    oldPos.update(a)
+  }
+
+  def bestTowards(g: Game, old: Pos, action: Action, target: Pos): Boolean = {
+    def metric(a: Action): Int = {
+      old.update(a).distance(target)
+    }
+
+    def betterThan(a: Action, other: Action): Boolean = {
+      !g.isValidAction(old, other) || (metric(a) <= metric(other))
+    }
+
+    g.isValidAction(old, action) &&
+    betterThan(action, MoveUp) &&
+    betterThan(action, MoveDown) &&
+    betterThan(action, MoveLeft) &&
+    betterThan(action, MoveRight) &&
+    betterThan(action, Noop)
+  }
+
+  def stepMonsters(g: Game, lp: List[Pos]): List[Pos] = lp match {
+    case Cons(h,t) => Cons(stepMonster(g, h), stepMonsters(g, t))
+    case Nil() => Nil()
+  }
+
+  def stepPlayer(g: Game)(implicit o: Oracle[Action]) = {
+    val action: Action = ???
+
+    val np = g.player.update(action)
+
+    Game(if (g.map.isValidPos(np)) np else g.player, g.monsters, g.map)
+  }
+
+  def stepPlayerTmp(g: Game) = {
+    val np = withOracle{ implicit o: Oracle[Action] => {
+      val action: Action = ???
+
+      g.player.update(action)
+    } ensuring { g.map.isValidPos(_) }}
+
+    Game(if (g.map.isValidPos(np)) np else g.player, g.monsters, g.map)
+  }
+
+  @extern
+  def display(g: Game): Int = {
+    print("\033[2J\033[1;1H")
+    print("   ")
+    for (x <- 0 until g.map.size.x) {
+      print(x)
+    }
+    println
+    print("  â•”")
+    for (x <- 0 until g.map.size.x) {
+      print('═')
+    }
+    println('â•—')
+    for (y <- 0 until g.map.size.y) {
+      print(y+" â•‘")
+      for (x <- 0 until g.map.size.x) {
+        val c = Pos(x,y)
+        if (g.map.walls contains c) {
+          print('â–’')
+        } else if (g.player == c) {
+          if (g.isDead) {
+            print(Console.RED+Console.BOLD+"☠"+Console.RESET)
+          } else {
+            print(Console.GREEN+"☺"+Console.RESET)
+          }
+        } else if (g.isAtPositions(c, g.monsters)) {
+          print(Console.RED+"X"+Console.RESET)
+        } else {
+          print(" ")
+        }
+      }
+      println('â•‘')
+    }
+    print("  â•š")
+    for (x <- 0 until g.map.size.x) {
+      print('═')
+    }
+    println('╝')
+
+    42
+  }
+
+  @ignore
+  def foreach[A](l: List[A], f: A => Unit): Unit = l match {
+    case Cons(h, t) => f(h); foreach(t, f)
+    case Nil() =>
+  }
+
+  @extern
+  abstract class OracleSource[T] extends Oracle[T] {
+    def branch: OracleSource[T]
+    def value: T
+
+    lazy val v: T = value
+    lazy val l: OracleSource[T] = branch
+    lazy val r: OracleSource[T] = branch
+
+    override def head: T = v
+    override def left: Oracle[T] = l
+    override def right: Oracle[T] = r
+  }
+
+  @extern
+  class Keyboard extends OracleSource[Action] {
+    def branch = new Keyboard
+    def value = {
+      import scala.tools.jline._
+
+      var askAgain = false
+      var action: Action = Noop
+
+      val t = new UnixTerminal()
+
+      try {
+        t.init()
+
+        do {
+          if (askAgain) println("?")
+          askAgain = false
+
+          t.readVirtualKey(System.in) match {
+            case 16 =>
+              action = MoveUp
+            case 14 =>
+              action = MoveDown
+            case 6 =>
+              action = MoveRight
+            case 2 =>
+              action = MoveLeft
+            case a =>
+              println("Got "+a)
+              askAgain = true
+          }
+
+        } while(askAgain)
+
+      } finally {
+        t.restore()
+      }
+
+      action
+    }
+  }
+
+  @extern
+  class Random extends OracleSource[Action] {
+    def value = {
+      scala.util.Random.nextInt(4) match {
+        case 0 =>
+          MoveUp
+        case 1 =>
+          MoveDown
+        case 2 =>
+          MoveLeft
+        case 3 =>
+          MoveRight
+        case _ =>
+          MoveUp
+      }
+    }
+
+    def branch = new Random
+  }
+
+  @extern
+  def getOracle(): Oracle[Action] = {
+    new Keyboard
+  }
+
+  @extern
+  def pause(): Unit = {
+    readLine
+  }
+
+  def start() = {
+    val map  = Map(Set(Pos(2,2), Pos(2,3), Pos(4,4), Pos(5,5)), Pos(10,10))
+    val monsters = Cons(Pos(8,5), Cons(Pos(6,2), Nil()))
+    val init = Game(Pos(0,0), monsters, map)
+
+    val res = play(init)(getOracle())
+
+    val tmp = display(res)
+
+    res
+  }
+}
diff --git a/testcases/extern/GameDemo.scala b/testcases/extern/GameDemo.scala
new file mode 100644
index 0000000000000000000000000000000000000000..fef85891a44d37b1a29474d505709a7af53ab0c8
--- /dev/null
+++ b/testcases/extern/GameDemo.scala
@@ -0,0 +1,294 @@
+import leon.lang._
+import leon.annotation._
+import leon.lang.synthesis._
+import leon.collection._
+
+object Test {
+  case class Pos(x: Int, y: Int) {
+    def up      = Pos(x, y-1)
+    def down    = Pos(x, y+1)
+    def left    = Pos(x-1, y)
+    def right   = Pos(x+1, y)
+
+    // Simple over aproximation of the distance
+    def distance(o: Pos) = {
+      val dx = o.x-x
+      val dy = o.y-y
+
+      (dx*dx + dy*dy)
+    }
+
+    def update(a: Action) = a match {
+      case MoveUp =>
+        up
+      case MoveDown =>
+        down
+      case MoveLeft =>
+        left
+      case MoveRight =>
+        right
+      case Noop =>
+        this
+    }
+  }
+
+  case class Map(walls: Set[Pos], size: Pos) {
+    // Returns whether a certain position is a valid position to be in given
+    // the map
+    def isValidPos(p: Pos): Boolean = {
+      p.x >= 0 && p.y >= 0 &&
+      p.x < size.x && p.y < size.y &&
+      !(walls contains p)
+    }
+
+    def allValidPos(lp: List[Pos]): Boolean = lp match {
+      case Cons(h, t) => isValidPos(h) && allValidPos(t)
+      case Nil() => true
+    }
+  }
+
+  abstract class Action;
+  case object MoveUp extends Action
+  case object MoveDown extends Action
+  case object MoveLeft extends Action
+  case object MoveRight extends Action
+  case object Noop extends Action
+
+  case class Game(player: Pos,
+                  monsters: List[Pos],
+                  map: Map) {
+
+    def isValidAction(pos: Pos, action: Action) = {
+      val np = pos.update(action)
+      map.isValidPos(np)
+    }
+
+    def isDead = {
+      isAtPositions(player, monsters)
+    }
+
+    def isAtPositions(p: Pos, lp: List[Pos]): Boolean = lp match {
+      case Cons(h,t) => (h == p) || isAtPositions(p, t)
+      case _ => false
+    }
+
+    def isValid = {
+      map.isValidPos(player) &&
+      map.allValidPos(monsters)
+    }
+
+    def isRunning = !isDead
+  }
+
+  def step(g: Game)(implicit o: Oracle[Action]): Game = {
+    if (g.isDead) {
+      g
+    } else {
+      val g1 = stepPlayer(g)
+      Game(g1.player, stepMonsters(g1, g1.monsters), g1.map)
+    }
+  }
+
+  def gameStep(g: Game)(implicit o: Oracle[Action]): Game = {
+    val u = display(g)
+    //withOracle { implicit o: Oracle[Action] => {
+      step(g)
+    //} ensuring { g => !g.isDead }}
+  }
+
+  def play(g: Game)(implicit o: Oracle[Action]): Game = {
+    val r = gameStep(g)(o.left)
+    if (r.isDead) {
+      r
+    } else {
+      play(r)(o.left)
+    }
+  }
+
+
+  def stepMonster(g: Game, oldPos: Pos): Pos = {
+    val a = choose { a: Action =>
+      bestTowards(g, oldPos, a, g.player)
+    }
+
+    oldPos.update(a)
+  }
+
+  def stepPlayer(g: Game)(implicit o: Oracle[Action]) = {
+    //withOracle { implicit o: Oracle[Action] => {
+      val action: Action = ???
+
+      val np = g.player.update(action)
+
+      Game(if (g.map.isValidPos(np)) np else g.player, g.monsters, g.map)
+    //} ensuring { g => !g.isDead }}
+  }
+
+  def bestTowards(g: Game, old: Pos, action: Action, target: Pos): Boolean = {
+    def metric(a: Action): Int = {
+      old.update(a).distance(target)
+    }
+
+    def betterThan(a: Action, other: Action): Boolean = {
+      !g.isValidAction(old, other) || (metric(a) <= metric(other))
+    }
+
+    g.isValidAction(old, action) &&
+    betterThan(action, MoveUp) &&
+    betterThan(action, MoveDown) &&
+    betterThan(action, MoveLeft) &&
+    betterThan(action, MoveRight) &&
+    betterThan(action, Noop)
+  }
+
+  def stepMonsters(g: Game, lp: List[Pos]): List[Pos] = lp match {
+    case Cons(h,t) => Cons(stepMonster(g, h), stepMonsters(g, t))
+    case Nil() => Nil()
+  }
+
+  @extern
+  def display(g: Game): Int = {
+    print("\033[2J\033[1;1H")
+    print("   ")
+    for (x <- 0 until g.map.size.x) {
+      print(x)
+    }
+    println
+    print("  â•”")
+    for (x <- 0 until g.map.size.x) {
+      print('═')
+    }
+    println('â•—')
+    for (y <- 0 until g.map.size.y) {
+      print(y+" â•‘")
+      for (x <- 0 until g.map.size.x) {
+        val c = Pos(x,y)
+        if (g.map.walls contains c) {
+          print('â–’')
+        } else if (g.player == c) {
+          if (g.isDead) {
+            print(Console.RED+Console.BOLD+"☠"+Console.RESET)
+          } else {
+            print(Console.GREEN+"☺"+Console.RESET)
+          }
+        } else if (g.isAtPositions(c, g.monsters)) {
+          print(Console.RED+"X"+Console.RESET)
+        } else {
+          print(" ")
+        }
+      }
+      println('â•‘')
+    }
+    print("  â•š")
+    for (x <- 0 until g.map.size.x) {
+      print('═')
+    }
+    println('╝')
+
+    42
+  }
+
+  @ignore
+  def foreach[A](l: List[A], f: A => Unit): Unit = l match {
+    case Cons(h, t) => f(h); foreach(t, f)
+    case Nil() =>
+  }
+
+  @extern
+  abstract class OracleSource[T] extends Oracle[T] {
+    def branch: OracleSource[T]
+    def value: T
+
+    lazy val v: T = value
+    lazy val l: OracleSource[T] = branch
+    lazy val r: OracleSource[T] = branch
+
+    override def head: T = v
+    override def left: Oracle[T] = l
+    override def right: Oracle[T] = r
+  }
+
+  @extern
+  class Keyboard extends OracleSource[Action] {
+    def branch = new Keyboard
+    def value = {
+      import scala.tools.jline._
+
+      var askAgain = false
+      var action: Action = Noop
+
+      val t = new UnixTerminal()
+
+      try {
+        t.init()
+
+        do {
+          if (askAgain) println("?")
+          askAgain = false
+
+          t.readVirtualKey(System.in) match {
+            case 16 =>
+              action = MoveUp
+            case 14 =>
+              action = MoveDown
+            case 6 =>
+              action = MoveRight
+            case 2 =>
+              action = MoveLeft
+            case a =>
+              println("Got "+a)
+              askAgain = true
+          }
+
+        } while(askAgain)
+
+      } finally {
+        t.restore()
+      }
+
+      action
+    }
+  }
+
+  @extern
+  class Random extends OracleSource[Action] {
+    def value = {
+      scala.util.Random.nextInt(4) match {
+        case 0 =>
+          MoveUp
+        case 1 =>
+          MoveDown
+        case 2 =>
+          MoveLeft
+        case 3 =>
+          MoveRight
+        case _ =>
+          MoveUp
+      }
+    }
+
+    def branch = new Random
+  }
+
+  @extern
+  def getOracle(): Oracle[Action] = {
+    new Keyboard
+  }
+
+  @extern
+  def pause(): Unit = {
+    readLine
+  }
+
+  def start() = {
+    val map  = Map(Set(Pos(2,2), Pos(2,3), Pos(4,4), Pos(5,5)), Pos(10,10))
+    val monsters = Cons(Pos(8,5), Cons(Pos(6,2), Nil()))
+    val init = Game(Pos(0,0), monsters, map)
+
+    val res = play(init)(getOracle())
+
+    val tmp = display(res)
+
+    res
+  }
+}
diff --git a/testcases/extern/GameNoSet.scala b/testcases/extern/GameNoSet.scala
new file mode 100644
index 0000000000000000000000000000000000000000..b167933bfee929eb1f8e39d9135796f436320eef
--- /dev/null
+++ b/testcases/extern/GameNoSet.scala
@@ -0,0 +1,312 @@
+import leon.lang._
+import leon.annotation._
+import leon.lang.synthesis._
+import leon.collection._
+
+object Test {
+  case class Pos(x: Int, y: Int) {
+    def up      = Pos(x, y-1)
+    def down    = Pos(x, y+1)
+    def left    = Pos(x-1, y)
+    def right   = Pos(x+1, y)
+
+    // Simple over aproximation of the distance
+    def distance(o: Pos) = {
+      val dx = o.x-x
+      val dy = o.y-y
+
+      (dx*dx + dy*dy)
+    }
+
+    def update(a: Action) = a match {
+      case MoveUp =>
+        up
+      case MoveDown =>
+        down
+      case MoveLeft =>
+        left
+      case MoveRight =>
+        right
+      case Noop =>
+        this
+    }
+
+    def isAtAny(lp: List[Pos]): Boolean = lp match {
+      case Cons(h,t) => (h == this) || isAtAny(t)
+      case _ => false
+    }
+  }
+
+  case class Map(walls: List[Pos], size: Pos) {
+    // Returns whether a certain position is a valid position to be in given
+    // the map
+    def isValidPos(p: Pos): Boolean = {
+      p.x >= 0 && p.y >= 0 &&
+      p.x < size.x && p.y < size.y &&
+      !p.isAtAny(walls)
+    }
+
+    def allValidPos(lp: List[Pos]): Boolean = lp match {
+      case Cons(h, t) => isValidPos(h) && allValidPos(t)
+      case Nil() => true
+    }
+  }
+
+  abstract class Action;
+  case object MoveUp extends Action
+  case object MoveDown extends Action
+  case object MoveLeft extends Action
+  case object MoveRight extends Action
+  case object Noop extends Action
+
+  case class Game(player: Pos,
+                  monsters: List[Pos],
+                  map: Map) {
+
+    def isValidAction(pos: Pos, action: Action) = {
+      val np = pos.update(action)
+      map.isValidPos(np)
+    }
+
+    def isDead = {
+      player.isAtAny(monsters)
+    }
+
+
+    def isValid = {
+      map.isValidPos(player) &&
+      map.allValidPos(monsters)
+    }
+
+    def isRunning = !isDead
+  }
+
+  def step(g: Game)(implicit o: Oracle[Action]): Game = {
+    if (g.isDead) {
+      g
+    } else {
+      val g1 = stepPlayer(g)
+      Game(g1.player, stepMonsters(g1, g1.monsters), g1.map)
+    }
+  }
+
+  def steps(g: Game, b: Int)(implicit o: Oracle[Action]): Game = {
+    if (b <= 0 || g.isDead) {
+      g
+    } else {
+      steps(step(g)(o.left), b-1)(o.right)
+    }
+  }
+
+  def gameStep(g: Game)(implicit o: Oracle[Action]): Game = {
+    val u = display(g)
+    //withOracle { implicit o: Oracle[Action] => {
+      steps(g, 1)
+      //step(step(g))
+    //  step(step(g)(o.left))(o.right)
+    //} ensuring { g => !g.isDead }}
+  }
+
+  def play(g: Game)(implicit o: Oracle[Action]): Game = {
+    val r = gameStep(g)(o.left)
+    if (r.isDead) {
+      r
+    } else {
+      play(r)(o.left)
+    }
+  }
+
+  def stepMonster(g: Game, oldPos: Pos): Pos = {
+    val a = choose { a: Action =>
+      bestTowards(g, oldPos, a, g.player)
+    }
+
+    oldPos.update(a)
+  }
+
+  def bestTowards(g: Game, old: Pos, action: Action, target: Pos): Boolean = {
+    def metric(a: Action): Int = {
+      old.update(a).distance(target)
+    }
+
+    def betterThan(a: Action, other: Action): Boolean = {
+      !g.isValidAction(old, other) || (metric(a) <= metric(other))
+    }
+
+    g.isValidAction(old, action) &&
+    betterThan(action, MoveUp) &&
+    betterThan(action, MoveDown) &&
+    betterThan(action, MoveLeft) &&
+    betterThan(action, MoveRight) &&
+    betterThan(action, Noop)
+  }
+
+  def stepMonsters(g: Game, lp: List[Pos]): List[Pos] = lp match {
+    case Cons(h,t) => Cons(stepMonster(g, h), stepMonsters(g, t))
+    case Nil() => Nil()
+  }
+
+  def stepPlayer(g: Game)(implicit o: Oracle[Action]) = {
+    val action: Action = ???
+
+    val np = g.player.update(action)
+
+    Game(if (g.map.isValidPos(np)) np else g.player, g.monsters, g.map)
+  }
+
+  def stepPlayerTmp(g: Game) = {
+    val np = withOracle{ implicit o: Oracle[Action] => {
+      val action: Action = ???
+
+      g.player.update(action)
+    } ensuring { g.map.isValidPos(_) }}
+
+    Game(if (g.map.isValidPos(np)) np else g.player, g.monsters, g.map)
+  }
+
+  @extern
+  def display(g: Game): Int = {
+    print("\033[2J\033[1;1H")
+    print("   ")
+    for (x <- 0 until g.map.size.x) {
+      print(x)
+    }
+    println
+    print("  â•”")
+    for (x <- 0 until g.map.size.x) {
+      print('═')
+    }
+    println('â•—')
+    for (y <- 0 until g.map.size.y) {
+      print(y+" â•‘")
+      for (x <- 0 until g.map.size.x) {
+        val c = Pos(x,y)
+        if (c.isAtAny(g.map.walls)) {
+          print('â–’')
+        } else if (g.player == c) {
+          if (g.isDead) {
+            print(Console.RED+Console.BOLD+"☠"+Console.RESET)
+          } else {
+            print(Console.GREEN+"☺"+Console.RESET)
+          }
+        } else if (c.isAtAny(g.monsters)) {
+          print(Console.RED+"X"+Console.RESET)
+        } else {
+          print(" ")
+        }
+      }
+      println('â•‘')
+    }
+    print("  â•š")
+    for (x <- 0 until g.map.size.x) {
+      print('═')
+    }
+    println('╝')
+
+    42
+  }
+
+  @ignore
+  def foreach[A](l: List[A], f: A => Unit): Unit = l match {
+    case Cons(h, t) => f(h); foreach(t, f)
+    case Nil() =>
+  }
+
+  @extern
+  abstract class OracleSource[T] extends Oracle[T] {
+    def branch: OracleSource[T]
+    def value: T
+
+    lazy val v: T = value
+    lazy val l: OracleSource[T] = branch
+    lazy val r: OracleSource[T] = branch
+
+    override def head: T = v
+    override def left: Oracle[T] = l
+    override def right: Oracle[T] = r
+  }
+
+  @extern
+  class Keyboard extends OracleSource[Action] {
+    def branch = new Keyboard
+    def value = {
+      import scala.tools.jline._
+
+      var askAgain = false
+      var action: Action = Noop
+
+      val t = new UnixTerminal()
+
+      try {
+        t.init()
+
+        do {
+          if (askAgain) println("?")
+          askAgain = false
+
+          t.readVirtualKey(System.in) match {
+            case 16 =>
+              action = MoveUp
+            case 14 =>
+              action = MoveDown
+            case 6 =>
+              action = MoveRight
+            case 2 =>
+              action = MoveLeft
+            case a =>
+              println("Got "+a)
+              askAgain = true
+          }
+
+        } while(askAgain)
+
+      } finally {
+        t.restore()
+      }
+
+      action
+    }
+  }
+
+  @extern
+  class Random extends OracleSource[Action] {
+    def value = {
+      scala.util.Random.nextInt(4) match {
+        case 0 =>
+          MoveUp
+        case 1 =>
+          MoveDown
+        case 2 =>
+          MoveLeft
+        case 3 =>
+          MoveRight
+        case _ =>
+          MoveUp
+      }
+    }
+
+    def branch = new Random
+  }
+
+  @extern
+  def getOracle(): Oracle[Action] = {
+    new Keyboard
+  }
+
+  @extern
+  def pause(): Unit = {
+    readLine
+  }
+
+  def start() = {
+    val map  = Map(Cons(Pos(2,2), Cons(Pos(2,3), Nil())), Pos(10,10))
+    val monsters = Cons(Pos(8,5), Cons(Pos(6,2), Nil()))
+    val init = Game(Pos(0,0), monsters, map)
+
+    val res = play(init)(getOracle())
+
+    val tmp = display(res)
+
+    res
+  }
+}
diff --git a/testcases/extern/GameSimpler.scala b/testcases/extern/GameSimpler.scala
new file mode 100644
index 0000000000000000000000000000000000000000..6249ad535ddf00bf061b7ce3b215d1f73dc3de17
--- /dev/null
+++ b/testcases/extern/GameSimpler.scala
@@ -0,0 +1,293 @@
+import leon.lang._
+import leon.annotation._
+import leon.lang.synthesis._
+import leon.collection._
+
+object Test {
+  case class Pos(x: Int, y: Int) {
+    def up      = Pos(x, y-1)
+    def down    = Pos(x, y+1)
+    def left    = Pos(x-1, y)
+    def right   = Pos(x+1, y)
+
+    // Simple over aproximation of the distance
+    def distance(o: Pos) = {
+      val dx = o.x-x
+      val dy = o.y-y
+
+      (dx*dx + dy*dy)
+    }
+
+    def update(a: Action) = a match {
+      case MoveUp =>
+        up
+      case MoveDown =>
+        down
+      case MoveLeft =>
+        left
+      case MoveRight =>
+        right
+      case Noop =>
+        this
+    }
+  }
+
+  case class Map(size: Pos) {
+    // Returns whether a certain position is a valid position to be in given
+    // the map
+    def isValidPos(p: Pos): Boolean = {
+      p.x >= 0 && p.y >= 0 &&
+      p.x < size.x && p.y < size.y
+    }
+  }
+
+  abstract class Action;
+  case object MoveUp extends Action
+  case object MoveDown extends Action
+  case object MoveLeft extends Action
+  case object MoveRight extends Action
+  case object Noop extends Action
+
+  case class Game(player: Pos,
+                  monster: Pos,
+                  map: Map) {
+
+    def isValidAction(pos: Pos, action: Action) = {
+      val np = pos.update(action)
+      map.isValidPos(np)
+    }
+
+    def isDead = {
+      player == monster
+    }
+
+    def isValid = {
+      map.isValidPos(player) &&
+      map.isValidPos(monster)
+    }
+
+    def isRunning = !isDead
+  }
+
+  def step(g: Game)(implicit o: Oracle[Action]): Game = {
+    if (g.isDead) {
+      g
+    } else {
+      val g1 = stepPlayer(g)
+      Game(g1.player, stepMonster(g1, g1.monster), g1.map)
+    }
+  }
+
+  def steps(g: Game, b: Int)(implicit o: Oracle[Action]): Game = {
+    if (b <= 0 || g.isDead) {
+      g
+    } else {
+      steps(step(g)(o.left), b-1)(o.right)
+    }
+  }
+
+  def gameStep(g: Game)(implicit o: Oracle[Action]): Game = {
+    val u = display(g)
+    withOracle { implicit o: Oracle[Action] => {
+      steps(g, 2)
+      //step(step(g))
+    //  step(step(g)(o.left))(o.right)
+    } ensuring { g => !g.isDead }}
+  }
+
+  def play(g: Game)(implicit o: Oracle[Action]): Game = {
+    val r = gameStep(g)(o.left)
+    if (r.isDead) {
+      r
+    } else {
+      play(r)(o.left)
+    }
+  }
+
+  def stepMonster(g: Game, oldPos: Pos): Pos = {
+    val a = choose { a: Action =>
+      bestTowards(g, oldPos, a, g.player)
+    }
+
+    oldPos.update(a)
+  }
+
+  def bestTowards(g: Game, old: Pos, action: Action, target: Pos): Boolean = {
+    def metric(a: Action): Int = {
+      old.update(a).distance(target)
+    }
+
+    def betterThan(a: Action, other: Action): Boolean = {
+      !g.isValidAction(old, other) || (metric(a) <= metric(other))
+    }
+
+    g.isValidAction(old, action) &&
+    betterThan(action, MoveUp) &&
+    betterThan(action, MoveDown) &&
+    betterThan(action, MoveLeft) &&
+    betterThan(action, MoveRight) &&
+    betterThan(action, Noop)
+  }
+
+
+  def stepPlayer(g: Game)(implicit o: Oracle[Action]) = {
+    val action: Action = ???
+
+    val np = g.player.update(action)
+
+    Game(if (g.map.isValidPos(np)) np else g.player, g.monster, g.map)
+  }
+
+  def stepPlayerTmp(g: Game) = {
+    val np = withOracle{ implicit o: Oracle[Action] => {
+      val action: Action = ???
+
+      g.player.update(action)
+    } ensuring { g.map.isValidPos(_) }}
+
+    Game(if (g.map.isValidPos(np)) np else g.player, g.monster, g.map)
+  }
+
+  @extern
+  def display(g: Game): Int = {
+    print("\033[2J\033[1;1H")
+    print("   ")
+    for (x <- 0 until g.map.size.x) {
+      print(x)
+    }
+    println
+    print("  â•”")
+    for (x <- 0 until g.map.size.x) {
+      print('═')
+    }
+    println('â•—')
+    for (y <- 0 until g.map.size.y) {
+      print(y+" â•‘")
+      for (x <- 0 until g.map.size.x) {
+        val c = Pos(x,y)
+        if (g.player == c) {
+          if (g.isDead) {
+            print(Console.RED+Console.BOLD+"☠"+Console.RESET)
+          } else {
+            print(Console.GREEN+"☺"+Console.RESET)
+          }
+        } else if (c == g.monster) {
+          print(Console.RED+"X"+Console.RESET)
+        } else {
+          print(" ")
+        }
+      }
+      println('â•‘')
+    }
+    print("  â•š")
+    for (x <- 0 until g.map.size.x) {
+      print('═')
+    }
+    println('╝')
+
+    42
+  }
+
+  @ignore
+  def foreach[A](l: List[A], f: A => Unit): Unit = l match {
+    case Cons(h, t) => f(h); foreach(t, f)
+    case Nil() =>
+  }
+
+  @extern
+  abstract class OracleSource[T] extends Oracle[T] {
+    def branch: OracleSource[T]
+    def value: T
+
+    lazy val v: T = value
+    lazy val l: OracleSource[T] = branch
+    lazy val r: OracleSource[T] = branch
+
+    override def head: T = v
+    override def left: Oracle[T] = l
+    override def right: Oracle[T] = r
+  }
+
+  @extern
+  class Keyboard extends OracleSource[Action] {
+    def branch = new Keyboard
+    def value = {
+      import scala.tools.jline._
+
+      var askAgain = false
+      var action: Action = Noop
+
+      val t = new UnixTerminal()
+
+      try {
+        t.init()
+
+        do {
+          if (askAgain) println("?")
+          askAgain = false
+
+          t.readVirtualKey(System.in) match {
+            case 16 =>
+              action = MoveUp
+            case 14 =>
+              action = MoveDown
+            case 6 =>
+              action = MoveRight
+            case 2 =>
+              action = MoveLeft
+            case a =>
+              println("Got "+a)
+              askAgain = true
+          }
+
+        } while(askAgain)
+
+      } finally {
+        t.restore()
+      }
+
+      action
+    }
+  }
+
+  @extern
+  class Random extends OracleSource[Action] {
+    def value = {
+      scala.util.Random.nextInt(4) match {
+        case 0 =>
+          MoveUp
+        case 1 =>
+          MoveDown
+        case 2 =>
+          MoveLeft
+        case 3 =>
+          MoveRight
+        case _ =>
+          MoveUp
+      }
+    }
+
+    def branch = new Random
+  }
+
+  @extern
+  def getOracle(): Oracle[Action] = {
+    new Keyboard
+  }
+
+  @extern
+  def pause(): Unit = {
+    readLine
+  }
+
+  def start() = {
+    val map  = Map(Pos(10,10))
+    val init = Game(Pos(0,0), Pos(3, 3), map)
+
+    val res = play(init)(getOracle())
+
+    val tmp = display(res)
+
+    res
+  }
+}
diff --git a/testcases/extern/features.scala b/testcases/extern/features.scala
new file mode 100644
index 0000000000000000000000000000000000000000..6b3db19119aed089997bcec2592e8147e8222a19
--- /dev/null
+++ b/testcases/extern/features.scala
@@ -0,0 +1,102 @@
+package testextern
+
+import leon.lang._
+import leon.annotation._
+import leon.lang.synthesis._
+import leon.collection._
+
+object ExternTest {
+  // All types 1
+  def test1() = {
+    allTypes1(false, (1,2), ExternFoo(12), Bar(false))
+  }
+
+  // All types 2
+  def test2() = {
+    allTypes2(Set(1,2,3), Map(1->2))
+  }
+
+  // External function calling back
+  def test3() = {
+    testCallBack(51);
+  }
+
+  // External method
+  def test4() = {
+    Test(12).bar(21)
+  }
+
+  // Generics
+  def test5() = {
+    id(List[BigInt](1,2,3)).tail.head == 2
+  }
+
+  // Name encoding
+  def test6() = {
+    +*/!(1,2)
+  }
+
+  // Unit1
+  def test7() = {
+    testUnit(1, (), ((), 3))
+  }
+
+
+  def leonFun(a: BigInt): BigInt = {
+    choose((x: BigInt) => x > a && x <= a+1)
+  }
+
+
+
+  // External functions
+
+  @extern
+  def testCallBack(a: BigInt): BigInt = {
+    val f = new scala.collection.mutable.ArrayBuffer[BigInt]()
+    leonFun(a+1)
+  }
+
+  @extern
+  def +*/!(a: Int, b: BigInt): BigInt = {
+    println("asd")
+    b+b
+  }
+
+  @extern
+  def allTypes1(a: Boolean, b: (BigInt, BigInt), c: ExternFoo, d: Bar): (Boolean, (BigInt, BigInt), ExternFoo, Bar) = {
+    println("asd")
+    (a,b,c,d)
+  }
+
+  @extern
+  def allTypes2(s: Set[Int], m: Map[Int, Int]): (Set[Int], Map[Int, Int]) = {
+    println("asd")
+    (s,m)
+  }
+
+  @extern
+  def id[T](a: T): T = {
+    println("asd")
+    a
+  }
+
+  @extern
+  def testUnit(a: Int, b: Unit, c: (Unit, Int)): Unit = {
+    println("asd")
+    b
+  }
+
+  case class Test(a: Int) {
+    @extern
+    def bar(b: BigInt): BigInt = {
+      println("asd")
+      b*4+a
+    }
+  }
+
+  case class Bar(b: Boolean);
+}
+
+case class ExternFoo(a: BigInt) {
+  def leonMethod(z: Int): Int = z
+}