Skip to content
Jeremy B edited this page Mar 12, 2018 · 7 revisions
  • The NetLogo project contains a Parser for parsing NetLogo code into a syntax tree.
    • This parser code is almost entirely written in Scala.
    • It publishes the project code to Javascript using Scala.js to create the ParserJS artifact.
    • This setup allows NetLogo desktop and NetLogo Web to share common parsing code.
  • The Tortoise project takes a dependency on the ParserJS artifact, which is used by the compiler to transform NetLogo code into a syntax tree, and then into Javascript. The compiler is published to a JVM version for running tests and a JS for testing and also for use by Galapagos.
    • Most of this code is written in Scala, with some small bits in Javascript when necessary. But it is important to remember that the compiler is translating code into Javascript.
  • Tortoise also contains an engine that duplicates the NetLogo runtime environment.
    • This is the code that actually runs when a statement or command is executed in order to update the model state.
    • This code is almost entirely CoffeeScript, with some regular Javascript thrown in (as that is the final output language).
  • Galapagos then uses the Tortoise compiler to compile code and create the initial model widgets and view. Then it uses the Tortoise engine to run the code, taking the engine updates and transforming those into the view (widget updates, plot updates, turtles in the world, etc).

Compilation target

The output of the compiler is JavaScript code.

We aim to generate JavaScript code that will run in modern browsers. For testing purposes during development, we're using Nashorn.

Compilation environment

The Tortoise compiler is written in Scala 2.12 and reuses the early phases (parserJS) of the existing NetLogo compiler.

JS Compilation

The Tortoise compiler is cross-compiled into Scala.js for in-browser use. We build both a JVM and a Scala.js artifact because we want to be able to use JVM in Galapagos server and for testing, as well as being able to have in-browser compilation in static Galapagos. A few quick notes about cross-building in Scala.js

Classes have two implementations

Since Scala.js lacks reflection any code that needs to vary between JVM and Scala.js must have two class implementations - one for the JVM and one for Scala.js. Typically, these are kept in separate directories, with mirrored structure, but when there is only a single file (as in the current Tortoise implementation) sbt can be convinced to compile replacing only that file. Typically, the reason that you'll want a separate Scala.js implementation will be either (a) the library you want to use hasn't yet been ported to Scala.js, (b) the Scala code uses an aspect of the JVM (like reflection or File I/O) that hasn't yet been ported to Scala.js. Creating a separate implementation for other reasons should be looked at very carefully.

Macros replace reflection

Since Scala.js doesn't support reflection, any time something reflection-like is needed you may be required to write a macro. These exist in both NetLogo-Headless and Tortoise. In both projects, they typically generate a lot of very trivial code that would be tedious and error-prone to maintain by hand. They probably could use code generation instead of macros, but Scala macros are relatively straightforward to use. They can search for implicits and look up classes in the code under compilation which allows them to act as reflection tools without the need for JVM runtime reflection.

Separate artifact packaging

Scala.js artifacts are compiled into .sjsir classfiles, which can then be jar'ed and used by other scala.js projects. The tortoise project includes a separate build netLogoWeb that packages the files tortoise-compiler.js and tortoise-engine.js into a jar for independent deployment. The netLogoWeb/test task tests that the compiled javascript produces the same model output as the JVM compiler.

Runtime

The runtime is written in CoffeeScript. (We are also exploring the possibility of switching to a different “alt-JS” language.)

Module system

We're using Browserify. TLDR on Browserify: it uses the same module system as Node.js, allows you to leverage Node/NPM libraries, and bundles your code and the libraries all into one JS file when run on your project.