Whalesong: Racket to JavaScript compiler
Go to file
2011-06-06 14:24:25 -04:00
compiler trying to clean up requires in prepwork 2011-06-01 11:43:36 -04:00
experiments Moved compiler-related stuff to compiler subdirectory 2011-05-26 19:46:49 -04:00
js-assembler compressing the output of the compiler with google-closure. Fixing the typechecks on numbers 2011-06-03 17:10:24 -04:00
lang Merge remote branch 'origin/master' 2011-06-01 13:09:32 -04:00
parser Moved compiler-related stuff to compiler subdirectory 2011-05-26 19:46:49 -04:00
simulator Working on making it easy to run whalesong from the shell. 2011-05-30 17:20:31 -04:00
tests trying to isolate the crash a bit more 2011-06-06 14:24:25 -04:00
version-case using version-case to insulate against bytecode changes 2011-05-20 10:39:39 -04:00
call-with-timeout.rkt fixing some tests 2011-06-01 14:18:15 -04:00
get-dependencies.rkt trying to clean up requires in prepwork 2011-06-01 11:43:36 -04:00
get-module-bytecode.rkt fixing some tests 2011-06-01 14:18:15 -04:00
helpers.rkt traced bug with list intersection 2011-03-23 19:19:49 -04:00
language-namespace.rkt trying to clean up; code is getting too large to manage 2011-05-13 13:57:17 -04:00
make-structs.rkt Merge remote branch 'origin/master' 2011-06-01 13:09:32 -04:00
make.rkt Merge remote branch 'origin/master' 2011-06-01 13:09:32 -04:00
Makefile fixing some tests 2011-06-01 14:18:15 -04:00
NOTES trying to use the closure compiler to reduce the size of the runtime 2011-06-03 16:45:43 -04:00
parameters.rkt trying to add a hook into the maker to deal with js-implemented modules. 2011-05-27 17:15:03 -04:00
README Fixing the README 2011-05-26 19:53:57 -04:00
sets.rkt relooper start 2011-02-28 23:01:45 -05:00
version.rkt still fixing module imports 2011-05-22 20:16:31 -04:00
whalesong.rkt trying to clean up requires in prepwork 2011-06-01 11:43:36 -04:00

======================================================================
Whalesong: a compiler from Racket to JavaScript.

Danny Yoo (dyoo@cs.wpi.edu)

======================================================================


Prerequisite: Racket 5.1.1.  The majority of the project is written
Typed Racket, and I highly recommend you use a version of Racket
that's at least 5.1.1; otherwise, compilation may take an unusual
amount of time.


======================================================================

Example usage

[FIXME]




======================================================================

Architecture:

The basic idea is to reuse most of the Racket compiler infrastructure.
We use the underlying Racket compiler to produce bytecode from Racket
source; it also performs macro expansion and module-level
optimizations for us.  We parse that bytecode using the
compiler/zo-parse collection to get an AST, compile that to an
intermediate language, and finally assemble JavaScript.


                        AST          IL                     JS
 parse-bytecode.rkt ----------> compiler.rkt --------> assembler.rkt ------->
    (todo)


The IL is intended to be translated straightforwardly.  We currently
have an assembler to JavaScript, as well as a simulator
(simulator.rkt).  The simulator allows us to test the compiler in a
controlled environment.



======================================================================

parser/parse-bytecode.rkt

This is intended to reuse the Racket compiler to produce the AST
structures defined in compiler/zo-parse.


======================================================================

compiler/compiler.rkt

translates the AST to the intermediate language.  The compiler has its
origins in the register compiler in Structure and Interpretation of
Computer Programs:

    http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-35.html#%_sec_5.5

with some significant modifications.  Since this is a stack machine,
we don't need any of the register-saving infrastructure in the
original compiler.  We also need to support slightly different linkage
structures, since we want to support multiple value contexts.  We're
trying to generate code that works effectively on a machine like the
one described in:

    http://plt.eecs.northwestern.edu/racket-machine/



The intermediate language is defined in il-structs.rkt, and a
simulator for the IL in simulator/simulator.rkt.  See
test-simulator.rkt to see the simulator in action, and
test-compiler.rkt to see how the output of the compiler can be fed
into the simulator.



The assumed machine is a stack machine with the following atomic
registers:

    val: value
    proc: procedure
    argcount: number of arguments

and two stack registers:

    env: environment stack
    control: control stack



======================================================================

js-assembler/assemble.rkt

The JavaScript assembler plays a few tricks to make things like tail
calls work:

   * Each basic block is translated to a function taking a MACHINE
     argument.

   * Every GOTO becomes a function call.

   * The head of each basic-blocked function checks to see if we
     should trampoline
     (http://en.wikipedia.org/wiki/Trampoline_(computers))

   * We support a limited form of computed jump by assigning an
     attribute to the function corresponding to a return point.  See
     the code related to the LinkedLabel structure for details.


Otherwise, the assembler is fairly straightforward.  It depends on
library functions defined in mini-runtime.js.  As soon as the compiler
stabilizes, we will be pulling in the runtime library in Moby Scheme
into this project.


The assembled output distinguishes between Primitives and Closures.
Primitives are only allowed to return single values back, and are not
allowed to do any higher-order procedure calls.  Closures, on the
other hand, have full access to the machine, but they are responsible
for calling the continuation and popping off their arguments when
they're finished.




======================================================================

Tests

The test suite in test-all.rkt runs the test suite.  You'll need to
run this on a system with a web browser, as the suite will evaluate
JavaScript and make sure it is producing values.  A bridge module
browser-evaluate.rkt brings up a temporary web server that allows us
to pass values between Racket and the JavaScript evaluator on the
browser.



======================================================================

Acknowledgements and Thanks


This uses code from the following projects:

   jshashtable (http://www.timdown.co.uk/jshashtable/)
   js-numbers (http://github.com/dyoo/js-numbers/)
   JSON (http://www.json.org/js.html)
   jquery (http://jquery.com/)


   [FIXME: add more]