You use the same interpreter than the REPL:
import scala.tools.nsc.interpreter.IMain
val interpreter = new IMain
interpreter.interpret("""val x = 6.28
val eval = math.sin(x) * x""")
val x = interpreter.valueOfTerm("x")
println(x)
--
Philippe Lhoste
-- (near) Paris -- France
-- http://Phi.Lho.free.fr
-- -- -- -- -- -- -- -- -- -- -- -- -- --
https://github.com/razie/scripster/blob/master/src/main/scala/razie/base/scr
ipting/RazieInterpreterImpl.scala
def evalExpr[T](code:String): T = {
beQuietDuring {
interpret(code) match {
case IR.Success =>
try lastRequest.flatMap (_.extractionValue).get.asInstanceOf[T]
catch { case e: Exception => out println e ; throw e }
case _ => throw new IllegalStateException ("parser didn't return
success")
Exactly which tradition is that?
> Best,
> Lal
Randall Schulz
It is traditional in lot of interpreted languages, like JavaScript or PHP.
Nice in its conciseness!
I played a bit more with the interpreter, using some code found here and there, and trying
to understand the functions from the code (because the JavaDoc is... terse, to put it
politely...).
It works quite fine, but here are two strangenesses:
import scala.tools.nsc.Settings
import scala.tools.nsc.interpreter.IMain
object OtherScalaScriptTest extends App
{
val settings = new Settings
settings.usejavacp.value = true // Get the environment class path (java.class.path)
val interpreter = new IMain(settings) // Can be plain new IMain if no need for settings
// Explicit bind with type
interpreter.bind("Pi", "Double", 3.1415926)
// Bind with type deduced from given value
// Doesn't work, looks like bindValue(x: Any) sees this parameter list as a tuple!
interpreter.bindValue("c", 299792468)
// Bind with more complex type
interpreter.bind("vals", "Array[Int]", Array(1, 2, 3))
// Bind with interpreter's generated name
interpreter.bindValue("Some string")
val resName = interpreter.mostRecentVar
println("Bound using " + resName)
val r = interpreter.interpret("""val tp = 2 * Pi
println(""" + resName + """)
val eval = math.sin(tp) * tp
""")
val tp = interpreter.valueOfTerm("tp") // Incorrect!?
val eval = interpreter.valueOfTerm("eval")
println(r + ": " + tp + " -> " + eval)
val dummy = interpreter.valueOfTerm("dummy")
println("Unknown = " + dummy)
val c = interpreter.valueOfTerm("c")
println("c is " + c.getOrElse("Unknown"))
interpreter.interpret("""vals.map(_ * 2).reduceLeft(_ + _)""")
println("Current vars in interpreter:\n<<<")
interpreter.visibleTermNames foreach println
println(">>>")
interpreter.quietImport("java.util.Date")
interpreter.beQuietDuring { interpreter.interpret("val now = new Date") }
val now = interpreter.valueOfTerm("now") getOrElse 0
val df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm")
println("Now, we are %s ie. %s" format(now, df.format(now)))
}
Why tp has the same value than eval? Do I misinterpret what valueOfTerm does? Is there a
better way to access the value of a variable defined internally in interpreted code?
And it looks like the bindValue with Any parameter is taking precedence on the version
with two parameters, looking at the parameter list as a tuple. (There is an unfortunate
syntax clash/confusion between tuples and parameter list, already noticed earlier --
choosing to keep two traditional, but competing syntaxes might have not been a good
decision...)
So, is there a way to use bindValue(name, x) (special syntax construct?) or is it useless
by being permanently masked by the too generic overloaded function?