Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature flags jsNode and jsWeb #454

Merged
merged 9 commits into from
Jul 30, 2024
2 changes: 1 addition & 1 deletion effekt/js/src/main/scala/effekt/Backend.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package effekt

class Backend {
val compiler = generator.js.JavaScript()
val compiler = generator.js.JavaScriptWeb()
val runner = ()
}
3 changes: 2 additions & 1 deletion effekt/jvm/src/main/scala/effekt/Backend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ case class Backend[E](name: String, compiler: Compiler[E], runner: Runner[E])
object Backend {

def backend(name: String): Backend[_] = name match {
case "js" => Backend("js", js.JavaScript(), JSRunner)
case "js" => Backend("js", js.JavaScriptNode(), JSNodeRunner)
case "js-web" => Backend("js-web", js.JavaScriptWeb(), JSWebRunner)
case "chez-monadic" => Backend("chez-monadic", chez.ChezSchemeMonadic(), ChezMonadicRunner)
case "chez-callcc" => Backend("chez-callcc", chez.ChezSchemeCallCC(), ChezCallCCRunner)
case "chez-lift" => Backend("chez-lift", chez.ChezSchemeLift(), ChezLiftRunner)
Expand Down
2 changes: 1 addition & 1 deletion effekt/jvm/src/main/scala/effekt/EffektConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class EffektConfig(args: Seq[String]) extends REPLConfig(args.takeWhile(_ != "--
)

val backend: ScallopOption[Backend[_]] = choice(
choices = List("js", "chez-callcc", "chez-monadic", "chez-lift", "llvm", "ml"),
choices = List("js", "js-web", "chez-callcc", "chez-monadic", "chez-lift", "llvm", "ml"),
name = "backend",
descr = "The backend that should be used",
default = Some("js"),
Expand Down
39 changes: 38 additions & 1 deletion effekt/jvm/src/main/scala/effekt/Runner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ trait Runner[Executable] {
}
}

object JSRunner extends Runner[String] {
object JSNodeRunner extends Runner[String] {
import scala.sys.process.Process

val extension = "js"
Expand Down Expand Up @@ -157,6 +157,43 @@ object JSRunner extends Runner[String] {
createScript(exePath, "node", jsMainFilePath)
}
}
object JSWebRunner extends Runner[String] {
import scala.sys.process.Process

val extension = "js"

def standardLibraryPath(root: File): File = root / "libraries" / "common"

override def prelude: List[String] = List("effekt", "option", "list", "result", "exception", "array", "string", "ref")

def checkSetup(): Either[String, Unit] =
Left("Running js-web code directly is not supported. Use `--compile` to generate a js file / `--build` to generate a html file.")

/**
* Creates an openable `.html` file besides the given `.js` file ([[path]])
* and then errors out, printing it's path.
*/
def build(path: String)(using C: Context): String =
import java.nio.file.Path
val out = C.config.outputPath().getAbsolutePath
val jsFilePath = (out / path).unixPath
val jsFileName = jsFilePath.split("/").last
val htmlFilePath = jsFilePath.stripSuffix(s".$extension") + ".html"
val mainName = "$" + jsFileName.stripSuffix(".js") + ".main"
val htmlContent =
s"""<!DOCTYPE html>
|<html>
| <body>
| <script type="text/javascript" src="${jsFileName}"></script>
| <script type="text/javascript">
| window.onload=${mainName};
| </script>
| </body>
|</html>
|""".stripMargin
IO.createFile(htmlFilePath, htmlContent, false)
C.abort(s"Open file://${htmlFilePath} in your browser or include ${jsFilePath}.")
}

trait ChezRunner extends Runner[String] {
val extension = "ss"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import kiama.output.PrettyPrinterTypes.Document
import kiama.util.Source


class JavaScript extends Compiler[String] {
class JavaScript(additionalFeatureFlags: List[String] = Nil) extends Compiler[String] {

// Implementation of the Compiler Interface:
// -----------------------------------------
def extension = ".js"

override def supportedFeatureFlags: List[String] = TransformerMonadicWhole.jsFeatureFlags
override def supportedFeatureFlags: List[String] = additionalFeatureFlags ++ TransformerMonadicWhole.jsFeatureFlags

override def prettyIR(source: Source, stage: Stage)(using Context): Option[Document] = stage match {
case Stage.Core => Core(source).map { res => core.PrettyPrinter.format(res.core) }
Expand Down Expand Up @@ -62,3 +62,5 @@ class JavaScript extends Compiler[String] {
private def pretty(stmts: List[js.Stmt]): Document =
js.PrettyPrinter.format(stmts)
}
class JavaScriptWeb extends JavaScript(List("jsWeb")) {}
class JavaScriptNode extends JavaScript(List("jsNode")) {}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ case class Module(name: JSName, imports: List[Import], exports: List[Export], st
js.Destruct(names, js.Call(Variable(JSName("require")), List(JsString(s"./${ file }"))))
}

val exportStatement = js.Assign(RawExpr("module.exports"),
val exportStatement = js.Assign(RawExpr(s"(typeof module != \"undefined\" && module !== null ? module : {}).exports = ${name.name}"),
js.Object(exports.map { e => e.name -> e.expr })
)

Expand Down
Loading