I'm not really clear about the semantics used to talk about clojurescript's compiler.
So in this document, i'm gonna call the analyzer, every phase before emit, so that include parse / macroexpansion / analyze.
How to parametrize it
If the compiler is to be made backend-agnostic, it will still need to be provided some informations about the backend.
Most notably, for the moment, the analyzer needs to know about the namespaces which contains all the cljs.core macros, to be able to expand them, see Decoupling cljs.core
So we need a way to provide this backend specific information to the analyzer. There are several options to do so.
I'm gonna sort them on how much effort is gonna be required to implement them.
First solution: Use a bunch of dynamically bound variables
This solution is easy and might work. It has several drawbacks
- No clear interface as to what the backend implementers needs to provide
- No clearly defined initialization phase for the analyzer
2. is almost more problematic than 1., because the js backend uses some variables (most notably the namespaces atom) that are backend-specific, and needs to be initialized.
If this solution is used, we'd need to wrap those access through getters that would perform needed initializations. For the moment, this only means providing a function that provides a fresh environment.
Second solution: Use a protocol, bound dynamically
This is an improvement on the previous solution. The idea is to regroup every piece that the analyzer needs onto a protocol, and to only bind that dynamically.
It mitigates the first drawback of the first solution, but still has the same problem regarding analyzer initialization
Third solution: Make the analyzer be an instance of a protocol, containing the information needed
This is probably the best solution.
- It provides a clear documentation of what the backend implementers needs to provide
- It provides a clearly defined initialization phase
- It provides a clear interface of what in the clojurescript compiler, the backend implementers are allowed to use.
Optionally, it also makes the use of several analyzers for different backends in the same program easier, by making the stateful information local to each analyzer instance.
I'm looking for feedback about how to implement this, my solution for the moment is to gradually transform the analyzer to be parametric, so using the first solution, and then maybe implement solution 3, by solidifying those changes into a protocol.
Comments and alternatives solutions much appreciated !