Important invariants |
Below, we list some important invariants, which have guided us in the implementation of the compiler.
The main part of the compiler is devoted to associate unique meanings to each subexpression of the input program. Each symbol foo can have several meanings foo#1, foo#2, etc., depending on the context. These possible meanings foo#1, foo#2, etc. are created during the declaration phase. For instance, expressions foo 1 and foo "hop" might be compiled as (foo#1)(1) and (foo#2)("hop").
The main routine
The symbols of an environment are bound to their possible meanings during the declaration phase. During the main compilation phase, these meanings can no longer change. In particular, the set of converters in the environment remains fixed, which allows us to cache inferred compositions of converters and the resolution of function applications for functions and arguments of given types.