Динамическая компиляция нескольких классов Scala во время выполнения - PullRequest
3 голосов
/ 07 июля 2019

Я знаю, что могу скомпилировать отдельные "фрагменты" в 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 Ответ

3 голосов
/ 07 июля 2019

Попробуйте

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...