Skip to content

CLJS compiler analyzer

Thomas Heller edited this page Mar 1, 2017 · 2 revisions

The cljs.compiler and cljs.analyzer packages do a bunch of stuff that sometimes get in the way of what shadow-build is trying to do. Sometimes they don't get in the way but are useless or do unnecessary work.

Writing them down here so I don't forget, also monitor them in case something upstream changes.

Things that would break shadow-build

  • cljs.analyzer/*passes* if nil will set default passes of [infer-type ns-side-effects]. Must not ever run ns-side-effects so always bind *passes* before calling analyze.

  • cljs.analyzer/empty-env takes no arguments but require env/*compiler-env* and *cljs-ns* to be bound.

  • cljs.analyzer/parse-ns replaced by shadow.cljs.util/parse-ns. Some of the side effects were moved to ns-side-effects but it still modifies the compiler env and has many other side effects. Instead of making a pure version of this there is a "fake" pure version that resets compiler env back to the state it was before (WTF?). Any changes to parse-ns and (defmethod parse 'ns ...) must be ported. It still has some issues, some have tickets. shadow-build is a lot stricter about the ns form and will throw for some things the CLJS parse-ns will happily ignore. ie. duplicate requires for the same ns, duplicate imports.

  • :emit-constants, most of the issues with incremental compilation for this where fixed by using stable names for constants. It still has issues around advanced compilation since the Closure Compiler does not move the generated constants between modules. (cross module motion does not move calls with new). All of this was replaced by the closure pass to move constants. Must ensure that nothing :emit-constants related is ever activated for shadow-build.

Things that bug me

  • cljs.analyzer/analyze-form which is called for every single form calls cljs.analyzer/load-core. That method checks whether it has run before but instead should only be run ONCE instead.

  • load-core also calls (cljs.analyzer/intern-macros 'cljs.core) for EVERY SINGLE FORM.

  • (def implicit-nses '#{goog goog.object goog.string goog.array Math String}). I can understand goog, Math, String, but why are the other implicit for every single ns? Would the :require hurt so much? cljs.core already ensures that they are loaded.

Clone this wiki locally