在运行时动态编译多个Scala类

时间:2019-07-07 14:13:16

标签: java scala reflection runtime scala-reflect

我知道我可以使用以下工具箱在Scala中编译单个“代码段”:

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

object Compiler {
  val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()

  def main(args: Array[String]): Unit = {
    tb.eval(tb.parse("""println("hello!")"""))
  }
}

除了“片段”(即相互引用的类)以外,还有什么方法可以编译?像这样:

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

object Compiler {
  private val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()

  val a: String =
    """
      |package pkg {
      |
      |class A {
      |def compute(): Int = 42
      |}}
    """.stripMargin

  val b: String =
    """
      |import pkg._
      |
      |class B {
      |def fun(): Unit = {
      |    new A().compute()
      |}
      |}
    """.stripMargin

  def main(args: Array[String]): Unit = {
    val compiledA = tb.parse(a)
    val compiledB = tb.parse(b)
    tb.eval(compiledB)
  }
}

很明显,我的代码段无效,因为我必须告诉工具箱如何以某种方式解析“ A”:

  

线程“ main”中的异常scala.tools.reflect.ToolBoxError:反射编译失败:

     

未找到:输入A

1 个答案:

答案 0 :(得分:3)

尝试

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

val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()

val a = q"""
          class A {
            def compute(): Int = 42
          }"""

val symbA = tb.define(a)

val b = q"""
          class B {
            def fun(): Unit = {
              new $symbA().compute()
            }
          }"""

tb.eval(b)

https://github.com/scala/scala/blob/2.13.x/src/compiler/scala/tools/reflect/ToolBox.scala#L131-L138