Scala: Как создать интерпретатор, который наследует текущий контекст? - PullRequest
1 голос
/ 07 июня 2019

В коде 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 голосов
/ 07 июня 2019

Вы можете попробовать

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)
}
...