Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
quick interpreter for nescala
package necsala.embedded
import scala.tools.nsc.interpreter.AbstractFileClassLoader
import scala.tools.nsc.{Global, Settings}
import scala.tools.nsc.util.BatchSourceFile
import scala.tools.nsc.io.{AbstractFile, VirtualDirectory}
import java.io.File
import java.util.jar.JarFile
import java.net.URLClassLoader
class Interpreter private (val classpath: List[String]) {
/** Evaluate a string of Scala source. Apart from compiler execution all bets are off. */
def evaluate[A](code: String): A = {
val (name, prepared) = asInterpreterClass(code)
val compiler = new global.Run
compiler.compileSources(List(new BatchSourceFile("<text>", prepared)))
try {
val clazz = classLoader.loadClass(name)
val instance = clazz.newInstance()
val f0Any = instance.asInstanceOf[() => Any]
f0Any().asInstanceOf[A]
} catch {
case e => throw e //TODO coherent exception
}
}
/** Given raw source, generate a complete class as a subtype of () => Any. */
private def asInterpreterClass(source: String): (String, String) = {
val name = "Interpreted_%s" format (math.abs(scala.util.Random.nextLong))
name -> ("class %s extends (() => Any) { def apply() = { %s }}" format (name, source))
}
private val target = new VirtualDirectory("<memory>", None)
private val classLoader = new AbstractFileClassLoader(target, this.getClass.getClassLoader)
private val settings = {
val s = new Settings()
s.outputDirs.setSingleOutput(target)
s.classpath.value = classpath.mkString(File.pathSeparator)
s
}
private val global = new Global(settings /*, reporter*/ )
}
object Interpreter {
/** The classpath of our class loader. */
def classPath: List[String] =
this.getClass.getClassLoader.asInstanceOf[URLClassLoader].getURLs.map(_.toString).toList
/** Create a new interpreter with the current classpath. */
def local = new Interpreter(classPath)
}
@robey

This comment has been minimized.

Copy link

robey commented Mar 16, 2012

there's a more fleshed-out implementation of this in util-eval: https://github.com/twitter/util/blob/master/util-eval/src/main/scala/com/twitter/util/Eval.scala

@chrislewis

This comment has been minimized.

Copy link
Owner Author

chrislewis commented Mar 21, 2012

Thanks robey. I used this snippet in a workshop to demonstrate the technique, disclaiming its suitability for production in this form (I did mention to the twitter implementation). The point was merely to demonstrate the relative simplicity and appeal of the technique over other approaches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.