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 && bar
或 foo || !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 嵌入)。要实现你想要的,你必须:
- 在Scala中寻找或构建一个可以输出JavaScript.
的深度嵌入框架
- 确保框架使用 Scala.js 编译。
- 使用此框架构建您的 DSL。
我知道您可以使用的框架是:
如果这些框架使用 Scala.js 编译以及它们的 JS 后端状态如何,您将不得不与作者核实。
您的建议尝试使用 Scala.js 作为深度嵌入框架,但 Scala.js 无法与 Scala.js 一起编译。
我也不知道你的最终目标是什么,但如果你真的想在运行时编译 Scala.js,你最好的办法是查看 scalafiddle.io 的源代码,正是这样做的,然后从复制它正在做的任何事情开始,然后从那里改变它。
这是处理从 Javascript 到 Scala.js 的 IR,然后从 IR 到 Javascript String
的编译的代码:
这里有趣的方法是compile
、link
(fastOptJS
和fullOptJS
)和export
。我知道 Whosebug 不鼓励外部链接,但代码确实太大太粗糙,不值得在这里在线复制。你最好的选择是克隆那个 repo,在你的 IDE 中打开它,然后跳转看看代码如何转换 Scala.js code: String
进入那个 Compiler
的构造函数class,通过所有中间步骤,到最终 Javascript String
从 export
方法
返回
大家好。我想弄清楚如何在运行时使用 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 && bar
或 foo || !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 嵌入)。要实现你想要的,你必须:
- 在Scala中寻找或构建一个可以输出JavaScript. 的深度嵌入框架
- 确保框架使用 Scala.js 编译。
- 使用此框架构建您的 DSL。
我知道您可以使用的框架是:
如果这些框架使用 Scala.js 编译以及它们的 JS 后端状态如何,您将不得不与作者核实。
您的建议尝试使用 Scala.js 作为深度嵌入框架,但 Scala.js 无法与 Scala.js 一起编译。
我也不知道你的最终目标是什么,但如果你真的想在运行时编译 Scala.js,你最好的办法是查看 scalafiddle.io 的源代码,正是这样做的,然后从复制它正在做的任何事情开始,然后从那里改变它。
这是处理从 Javascript 到 Scala.js 的 IR,然后从 IR 到 Javascript String
的编译的代码:
这里有趣的方法是compile
、link
(fastOptJS
和fullOptJS
)和export
。我知道 Whosebug 不鼓励外部链接,但代码确实太大太粗糙,不值得在这里在线复制。你最好的选择是克隆那个 repo,在你的 IDE 中打开它,然后跳转看看代码如何转换 Scala.js code: String
进入那个 Compiler
的构造函数class,通过所有中间步骤,到最终 Javascript String
从 export
方法