Scala:如何实例化继承当前上下文的解释器?

时间:2019-06-07 00:35:43

标签: scala interpreter scala-reflect

在Scala代码中,我想创建一个解释器,该解释器将评估一些Scala代码的字符串,例如,使用ScriptEngine。但是我想将当前变量和类型定义传递给它,以便字符串中的代码可以使用它们,就像新解释器是从当前解释器派生的一样。

使用ScriptEngine,我可以使用“ put”方法将绑定放入其中,但这对于每个变量都必须是明确的。而且,无法传递类定义或方法等。

那有办法吗,还是我误会了什么?

目的是让动态代码使用准备好的数据和方法

这是我现在可以做的:

import javax.script._
val e = new ScriptEngineManager().getEngineByName("scala")

engine.put("x", 123) 
engine.eval("val y = x.asInstanceOf[Int] + 100")

这就是我想要做的:

case class X(a: Int, b: Int)
val x = X(1,2)

engine.eval("val x1 = X(x.a + 1, x.b + 1)")    // Use both X and x

1 个答案:

答案 0 :(得分:0)

您可以尝试

val res = engine.eval(
    """case class X(a: Int, b: Int)
      |val x = X(1,2)
      |val x1 = X(x.a + 1, x.b + 1)""".stripMargin)

您也可以使用scala.tools.reflect.ToolBox


使用导入。

package mypackage

import javax.script._

object App {
  val engine = new ScriptEngineManager().getEngineByName("scala")

  case class X(a: Int, b: Int)
  val x = X(1,2)

  val res = engine.eval("import mypackage.App._; val x1 = X(x.a + 1, x.b + 1)")
}

package mypackage

import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox

object App {
  val tb = runtimeMirror(ClassLoader.getSystemClassLoader).mkToolBox()

  case class X(a: Int, b: Int)
  val x = X(1, 2)

  val tree = tb.parse("import mypackage.App._; val x1 = X(x.a + 1, x.b + 1)")
  val res = tb.eval(tree)
}