1

大家好。我想弄清楚如何在运行时使用 Scala.js 工具将 Scala 表达式编译为 Javascript。作为示例,这是一个简化的设置。

比如说,我们有一个简单的 DSL,它由Ctx => Boolean函数和对它们的布尔运算组成,如下所示:

implicit class Simple[Ctx](f: Ctx => Boolean) {
  def &&(g: Ctx => Boolean): Ctx => Boolean = ctx => f(ctx) && g(ctx)
  def ||(g: Ctx => Boolean): Ctx => Boolean = ctx => f(ctx) || g(ctx)
  def unary_!: Ctx => Boolean = ctx => !f(ctx)
}

假设我们有一些“构建块”硬编码、编译成 Javascript 并导出,如下所示:

@ExportJSTopLevel("foo") def foo[Ctx](ctx: Ctx): Boolean = ???
@ExportJSTopLevel("bar") def bar[Ctx](ctx: Ctx): Boolean = ???
// and so on

现在可以从这些构建块中组装简单的布尔表达式,例如:foo && barorfoo || !bar等​​。

假设一些持久实体是在运行时创建的,它们的主体是这样的表达式。我希望能够将它们编译为 Javascript,作为与上面的构建块具有相同签名的函数,这些构建块调用这些构建块。

我在网上找到了几个关于ScalaJSOptimizer在 Scala.js 工具中某处调用的神秘类的引用。但是,提供给该类的链接总是被破坏或显示它属于最新版本的“scalajs-tools”工件甚至没有的包。

完成我想做的事情的最佳方法是什么?

4

3 回答 3

2

我也不知道你的最终目标是什么,但如果你真的想在运行时编译 Scala.js,最好的办法是查看 scalafiddle.io 的源代码,它就是这样做的,然后从复制开始无论它在做什么,并从那里改变它。

这是处理从 Javascript 编译到 Scala.js 的 IR,然后从 IR 编译到 Javascript 的代码String

这里有趣的方法是compile, link(fastOptJSfullOptJS) 和export。我知道 StackOverflow 不鼓励外部链接,但代码实在太大太粗糙,不值得在这里在线复制。你最好的办法是克隆那个 repo,在你的 IDE 中打开它,然后四处看看代码如何通过所有中间步骤将进入该类code: String的构造函数的 Scala.js 转换为从方法CompilerStringexport

于 2017-08-14T12:06:59.200 回答
1

您正在尝试做的事情是可能的,并且已经在许多语言中进行了广泛的研究(深度 DSL 嵌入)。要实现您想要的,您必须:

  1. 在 Scala 中查找或构建可以输出 JavaScript 的深度嵌入框架。
  2. 确保该框架与 Scala.js 一起编译。
  3. 使用这个框架构建你的 DSL。

我知道您可以使用的框架是:

  1. DB Lab:我认为它没有 JS 后端,但可以根据您的需要添加。
  2. LMS:有一个 JS 后端,但是,你必须Rep在你的 DSL 中使用类型。

如果这些框架使用 Scala.js 编译,您必须与作者核实,以及它们的 JS 后端的状态是什么。

您的提案尝试使用 Scala.js 作为深度嵌入框架,但 Scala.js 无法使用 Scala.js 进行编译。

于 2017-08-10T14:58:32.493 回答
0

老实说,我认为将其定义为“在运行时将 Scala 表达式编译为 Javascript”正在构建失败的秘诀。Scala.js 无法编译 Scala,并且在不久的将来可能也无法编译——太多的编译器基础设施是以 JVM 为中心的。

因此,我建议重新定义问题。正式定义您希望能够在运行时使用的语言。(这很可能是 Scala 的一个子集。)使用诸如FastParse之类的 Scala.js 解析器为其编写一个解析器,生成抽象语法树,以及一个将这些语法树转换为 JavaScript 的解释器。

是的,有点费力。但这是可以实现的,尝试在运行时将任意 Scala 编译为 JavaScript,在 Scala.js 中,不是......

于 2017-08-08T16:05:36.547 回答