Search code examples
javascriptscalascala.jsruntime-compilation

Scala.js Runtime Compilation to Javascript


Hey, all. I want to figure out how to use Scala.js tools to compile Scala expressions to Javascript during runtime. Here's a simplified setup, as an example.

Say, we have a simple DSL that consists of Ctx => Boolean functions and boolean operations on them, a la the following:

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)
}

And let's assume that we have some "building blocks" hardcoded, compiled into Javascript, and exported, as follows:

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

Now one can assemble simple boolean expressions out of these building blocks, such as: foo && bar or foo || !bar, etc.

Let's say that some persistent entities are created at runtime, with such expressions as their bodies. I want to be able to compile them to Javascript, as functions with the same signature as the building blocks above, which call those building blocks.

I found several references online to the mysterious class called ScalaJSOptimizer somewhere in Scala.js tools. However, the links provided to that class are always broken or show it belonging to a package that the latest version of the "scalajs-tools" artifact doesn't even have.

What is the best way to accomplish what I want to do?


Solution

  • What you are trying to do is possible and has been researched extensively in many languages (deep DSL embedding). To achieve what you want you would have to:

    1. Find or build a deep embedding framework in Scala that can output JavaScript.
    2. Make sure that framework compiles with Scala.js.
    3. Build your DSL using this framework.

    The frameworks I know that you could use are:

    1. DB Lab: I don't think it has a JS backend but it could be added for your needs.
    2. LMS: Has a JS backend, however, you have to use Rep types in your DSLs.

    You would have to check with the authors if these frameworks compile with Scala.js and what is the state of their JS backends.

    Your proposal tries to use Scala.js as a deep embedding framework, but Scala.js can't be compiled with Scala.js.