Skip to content

Instantly share code, notes, and snippets.

@SethTisue
Forked from chrislewis/interpreter.scala
Created March 10, 2012 15:51
Show Gist options
  • Save SethTisue/2011854 to your computer and use it in GitHub Desktop.
Save SethTisue/2011854 to your computer and use it in GitHub Desktop.
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 () {
/** 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.usejavacp.value = true
s
}
private val global = new Global(settings /*, reporter*/ )
}
object Interpreter {
/** Create a new interpreter with the current classpath. */
def local = new Interpreter
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment