Scala Presentation Compiler - 最小的例子

时间:2013-05-14 08:50:06

标签: scala compiler-construction

有人可以提供使用当前scala演示编译器(即scala.tools.nsc.interactive.Global)的最小示例,它可以完成以下任务吗?

  • 编译单个虚拟源文件(即不在文件系统中,但例如String
  • 从编译器中检索所有阶段的结果信息
  • 将源文件中的更改传播到编译器
  • 可能异步接收更多信息

nsc似乎有很多波动,我找不到最新的小例子。所以我非常感谢你的帮助。

3 个答案:

答案 0 :(得分:9)

好的,一周有100个赏金,但仍然没有答案所以我会亲自尝试... 非常欢迎编辑!

演示文稿编译器的关键类是scala.tools.nsc.interactive.Global。首先,我们需要创建一个编译器实例。

import scala.tools.nsc.interactive.Global
class PresentationCompiler { // we want the compiler output to be virtual val target = new VirtualDirectory("", None)
// need to be adjusted in order to work with // sbt. See this question. val settings = new Settings() // output to virtual target settings.outputDirs.setSingleOutput(target)
// can be replaced by a custom instance // of AbstractReporter to gain control. val reporter = new ConsoleReporter(settings)
val compiler = new Global(settings, reporter)
... }

对于设置the link provided by Abhishek非常有价值。

但现在有趣的是:

<强> 1。编译单个虚拟源文件

要编译String,可以创建一个带有基础BatchSourceFile的{​​{1}}。 api在这里被标记为实验性的,看起来很零散。

VirtualFile

<强> 2。从编译器中检索所有阶段的结果信息

这是棘手的部分。由于编译器的多线程特性以及标志在不同阶段中以不同含义重用的事实,因此不可能一次性获取所有内容。基本上,您将不得不采用API中记录的def compile(code: String) { val source = new BatchSourceFile("<virtual>", code) val response = new Response[Unit] compiler.askReload(List(source), response) response.get.left.foreach { _ => // success } } 种方法。例如:

askSomething

第3。将源文件中的更改传播到编译器

这是有趣的部分,我想知道这个问题。我真的不明白,因为val tcompletion = new Response[List[global.Member]] val pos = compiler.ask(() => new OffsetPosition(source, p)) global.askTypeCompletion(pos, tcompletion) tcompletion.get(5000).get match { case Left(members) => // do something with members case Right(e) => e.printStackTrace } 被描述为一个内容不会随时间变化的文件。那么需要提供BatchSourceFile的自定义实现吗?为什么不在SourceFile包中。我确信我没有抓到什么。

所以我现在的解决方案是再次调用编译方法。

答案 1 :(得分:2)

以下链接可能有帮助

https://github.com/twitter/util/blob/master/util-eval/src/main/scala/com/twitter/util/Eval.scala

我认为它可以满足您的所有要求。 :)

答案 2 :(得分:0)

可能不是你想要的,但一种方法可能是:

  1. 将要编译的源写入临时文件

  2. 运行编译后缀> output.tmp(* nix)运算符到命令,该命令应将编译器输出输出到文件中,

  3. 读取该文件并将其加载到内存中......

  4. 最后你删除了两个tmp文件。

  5. 我希望这不是唯一的解决方案,但万一其他方面是不可能的,至少这应该有用......