Hacker News new | ask | show | jobs
by elbenshira 4000 days ago
If I understand correctly, the ClojureScript compiler was written in Clojure (that is, you had to run the JVM to run the compiler), which spat out JS code and then compiled by Google Closure.

Would you be able to explain, at a high level, how ClojureScript bootstrapped itself, and how Google Closure comes into play?

4 comments

Over the years the language differences between Clojure & ClojureScript have more or less been erased beyond very host specific details like String methods, no multithreading, etc. Clojure 1.7.0 landed reader conditional which permits writing conditional code based on whether the file is being compiled by Clojure or by ClojureScript.

So we simply conditionalized a few key things in the analyzer and then we just point ClojureScript JVM back at its own sources. This part was actually very simple to do. However much more challenging is the issue of macros. As with many Lisps, Clojure has only a few primitive special forms and most of the language is actually written in terms of macros. ClojureScript is no different, the macros files is longer than the analyzer or the compiler.

You can see ClojureScript's meta-circular moment here - https://github.com/clojure/clojurescript/blob/d1d3e866440626.... The macros file must load itself in order for it to be compiled into JavaScript.

Google Closure was always an additional optimization pass. The bootstrapped code we generate is still Closure compatible making it easy to run it yourself seperately as an optimization pass or to produce a single JavaScript file you can put somewhere on the Internet if you like.

Awesome work David!
One way to look at it: Replete has a bit of CLJS source which requires the reader, analyzer and compiler namespaces. When Replete's source is built (using the JVM), these additional namespaces get compiled down to JavaScript and are usable by Replete itself, in the R and E parts of the REPL. It is all JavaScript, of course, when on the device.

Google Closure is used for its dependency management (ClojureScript namespaces and how they require other namespaces). But Google Closure is not used for its optimizations (everything is built with :none mode).

Yes the ClojureScript compiler is written in Clojure, more than that it is written in a special form of Clojure that can do conditional branching depending on what environment it is running in. So now the ClojureScript compiler can be ran in ClojureScript.