2017-08-08 38 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。從原來的問題來看,我不清楚「運行時」是指服務器還是客戶端。這僅適用於服務器 –