Scala.js 运行时编译到 Javascript

Scala.js Runtime Compilation to Javascript

大家好。我想弄清楚如何在运行时使用 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)
}

并且假设我们有一些 "building blocks" 硬编码,编译成 Javascript,并导出,如下所示:

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

现在可以 assemble 从这些构建块中提取简单的布尔表达式,例如:foo && barfoo || !bar

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

我在 Scala.js 工具的某处找到了几个关于名为 ScalaJSOptimizer 的神秘 class 的参考资料。然而,提供给那个 class 的链接总是被破坏或者显示它属于一个包,而最新版本的 "scalajs-tools" 工件甚至没有。

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

老实说,我认为将其定义为 "compile Scala expressions to Javascript during runtime" 是在构建失败的秘诀。 Scala.js 无法编译 Scala,并且可能在不久的将来也无法编译 -- 太多的编译器基础架构以 JVM 为中心。

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

是的,有点功夫。但它是可以实现的,试图在运行时将任意 Scala 编译为 JavaScript,在 Scala.js 中,不是...

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

  1. 在Scala中寻找或构建一个可以输出JavaScript.
  2. 的深度嵌入框架
  3. 确保框架使用 Scala.js 编译。
  4. 使用此框架构建您的 DSL。

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

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

如果这些框架使用 Scala.js 编译以及它们的 JS 后端状态如何,您将不得不与作者核实。

您的建议尝试使用 Scala.js 作为深度嵌入框架,但 Scala.js 无法与 Scala.js 一起编译。

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

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

这里有趣的方法是compilelinkfastOptJSfullOptJS)和export。我知道 Whosebug 不鼓励外部链接,但代码确实太大太粗糙,不值得在这里在线复制。你最好的选择是克隆那个 repo,在你的 IDE 中打开它,然后跳转看看代码如何转换 Scala.js code: String 进入那个 Compiler 的构造函数class,通过所有中间步骤,到最终 Javascript Stringexport 方法

返回