scala - 让 Scala 解释器在解释调用之间忘记

标签 scala compiler-construction classloader interpreter

是否可以配置一个 Scala 解释器 ( tools.nsc.IMain ) 以便它 每当我运行下一个 interpret() 时,“忘记”之前执行的代码称呼?

通常在编译源代码时,它会将它们包装在嵌套对象中,因此之前定义的所有变量、函数和绑定(bind)都可用。

不生成嵌套对象(或丢弃它们)就足够了,尽管我更喜欢一种解决方案,它甚至可以再次从类加载器中删除先前编译的类。

是否有设置,或方法,或我可以覆盖的东西,或 IMain 的替代方法?那会做到这一点吗?我需要能够仍然从主机 VM 访问生成的对象/类。

基本上我想隔离后续interpret()调用没有像创建一个新的 IMain 这样重的东西对于每次迭代。

最佳答案

这是一个可能的答案。基本上有方法reset()它调用了以下内容(大部分是私有(private)的,所以你要么购买整个包裹):

clearExecutionWrapper()
resetClassLoader()
resetAllCreators()
prevRequests.clear()
referencedNameMap.clear()
definedNameMap.clear()
virtualDirectory.clear()

就我而言,我使用的是自定义执行包装器,因此需要重新设置,并且导入也是通过常规解释周期处理的,因此要么再次添加它们,要么——更好——只是在它们前面加上执行包装器。

我想保留我的绑定(bind),它们也不见了:
import tools.nsc._
import interpreter.IMain

object Test {
  private final class Intp(cset: nsc.Settings)
    extends IMain(cset, new NewLinePrintWriter(new ConsoleWriter, autoFlush = true)) {

    override protected def parentClassLoader = Test.getClass.getClassLoader
  }

  object Foo {
    def bar() { println("BAR" )}
  }

  def run() {
    val cset = new nsc.Settings()
    cset.classpath.value += java.io.File.pathSeparator + sys.props("java.class.path")
    val i = new Intp(cset)
    i.initializeSynchronous()
    i.bind[Foo.type]("foo", Foo)
    val res0 = i.interpret("foo.bar(); val x = 33")
    println(s"res0: $res0")
    i.reset()
    val res1 = i.interpret("println(x)")
    println(s"res1: $res1")
    i.reset()
    val res2 = i.interpret("foo.bar()")
    println(s"res2: $res2")
  }
}

这将找到 Foo在第一次迭代中,正确忘记 x在第二次迭代中,但在第三次迭代中,可以看到 foo绑定(bind)也丢失了:
foo: Test.Foo.type = Test$Foo$@8bf223
BAR
x: Int = 33
res0: Success
<console>:8: error: not found: value x
              println(x)
                      ^
res1: Error
<console>:8: error: not found: value foo
              foo.bar()
              ^
res2: Error

以下似乎很好:
for(j <- 0 until 3) {
  val user  = "foo.bar()"
  val synth =  """import Test.{Foo => foo}
               """.stripMargin + user
  val res = i.interpret(synth)
  println(s"res$j: $res")
  i.reset()
}

关于scala - 让 Scala 解释器在解释调用之间忘记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16607689/

相关文章:

带有函数参数的Scala案例类

c++ - 在 C++ 中接受语法

java - GetResourceAsStream 在 Websphere 服务器上不起作用

scala - 从一个列表中提取不在另一个列表中的元素

postgresql - Play 2.5 + Slick application.conf 配置错误与 URL

scala - Play框架和scala中单选和单选的区别

language-agnostic - 是否有任何 self 改进的编译器?

xcode - Swift 中出现此错误的原因是什么?

java - 自定义类加载器可以加载类而忽略其依赖项吗?

java - 动态类加载器的 IllegalAccessError