2017-08-08 78 views
0

嘿,所有。我想弄清楚在运行时如何使用Scala.js工具将Scala表达式编译成Javascript。作为一个例子,这是一个简化的设置。Scala.js运行时编译为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 && barfoo || !bar

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

我在Scala.js工具的某处发现了几个在线引用的神秘类ScalaJSOptimizer。然而,提供给该类的链接总是被打破或显示它属于最新版本的“scalajs-tools”工件甚至没有的包。

什么是最好的方式来完成我想要做的事情?

+0

我不明白你想要实现的一半,但替换(长期死亡)'ScalaJSOptimizer'是['StandardLinker'](https://www.scala- js.org/api/scalajs-tools/0.6.19/#org.scalajs.core.tools.linker.StandardLinker$),它是['Linker']的工厂(https://www.scala-js.org /api/scalajs-tools/0.6.19/#org.scalajs.core.tools.linker.Linker),其重要方法是'link'。 – sjrd

+0

您正在寻找的是(至少在斯卡拉研究环境中)的“深嵌入”(或其变体)。这是一个活跃的研究课题,而不是“解决”的问题。 对于您的特定问题,我能想到的最好方法是自己编写一个JavaScript编译器,然后''评估'结果。 – gzm0

回答

1

你正在尝试做什么是可能的,并且已经在许多语言中进行了广泛的研究(深度DSL嵌入)。为了实现你想你会有什么:

  1. 查找或Scala中,可输出的JavaScript构建了深刻的嵌入框架。
  2. 确保框架使用Scala.js编译。
  3. 使用此框架构建您的DSL。

我知道,你可以使用该框架是:

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

如果这些框架与Scala.js一起编译并且它们的JS后端的状态如何,您将不得不与作者核对。

您的提议尝试使用Scala.js作为深度嵌入框架,但Scala.js不能用Scala.js编译。

+0

谢谢!我实际上已经开始尝试基于LMS的js-scala库(github.com/js-scala/js-scala),但是我在与Rep [T]一起工作时遇到了麻烦,其中T是case类。库本身提供的示例很简单,只使用基本类型。你知道更复杂的例子吗? – silverberry

+0

让我来重述一下我的问题。如何为自己的域类型提供自定义代码生成器? – silverberry

+0

我想我明白了这一点。 – silverberry

0

老实说,我认为将它定义为“在运行时将JavaScript编译为JavaScript”是构建一个失败的秘诀。 Scala.js不能编译Scala,并且在不久的将来可能无法这样做 - 编译器基础结构太多是以JVM为中心的。

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

是的,这是一个努力。但它是可以实现的,它试图在运行时在Scala.js中编译任意Scala到JavaScript,而不是...

+0

谢谢。但我不想将任意Scala编译成Javascript。只是已经编译成Javascript的构建块的布尔操作(参见上文)。 – silverberry

+0

我不知道如果js-scala可以用于这个....(https://github.com/js-scala/js-scala) – silverberry

1

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

下面是来自Javascript来Scala.js的IR编译打交道的代码,然后从红外到一个Javascript String:这里

有趣的方法是compile, (fastOptJSfullOptJS)和export。我知道StackOverflow不鼓励外部链接,但代码真的太大而且粗糙,因此值得在线复制。你最好的办法是克隆这个回购,在你的IDE中打开它,并跳过去看看代码如何通过所有的中间步骤将这个类的构造函数中的Scala.js code: String转换为最终的Javascript Stringexport方法返回

+0

但是这个东西仍然是JVM只有没有?还是它如此糟糕地攻击scalac,以至于它在JS上运行? – gzm0

+0

是的,它仍然是JVM。从原来的问题来看,我不清楚“运行时”是指服务器还是客户端。这仅适用于服务器 –