a type-preserving closure conversion in haskell
The use of typed intermediate languages can significantly increase the reliability of a compiler. By type-checking the code produced at each transformation stage, one can identify bugs in the compiler that would otherwise be much harder to find. Also it guarantees that any property that was enforced by the source-level type-system is holds also or the generated code. Recently, several people have tried to push this effort a bit further by verifying formally that the compiler indeed preserves typing. This is usually done with proof assistants or experimental languages. Instead, we decided to use Haskell (with GHC's extensions), to see how far we can go with a more mainstream system, supported by robust compilers and plentiful libraries. This article presents one part of our type preserving compiler, namely the closure conversion and its associated hoisting phase, where we use GADTs to let Haskell's type checker verify the we obey the object language's typing rules and that we correctly preserve types from one phase to the other. This should be both a good showcase as well as a good stress test for GADTs, so we also discuss our experience, as well as some trade-offs in the choice of representation, namely between higher-order abstract syntax (HOAS) and a first order representation (i.e. de Bruijn indices) and justify our choice of a de Bruijn representation. We incidentally present a type preserving conversion from HOAS (used in earlier phases of the compiler[6]) to a de Bruijn representation.
compilation higher-order abstract syntax de bruijn typed assembly language