Stage 0 compiles stage 1 to ML, stage 1 compiles stage 2 to C. Stage 1 and stage 2 share largely the same codebase, but it seems stage 1 is slightly more permissive than stage 0. There was a bug in the AST serialization code of stage 2 which was finally caught by C. Fixed it, should print and verify that code by hand. Fixed the bug and fired up the compile of stage 2 again.
This, on the other hand, I don't like. Now, I expected some bugs, cool. But the bug was a missing underscore, leaving two identifiers. The way the compiler works, one identifier referred to a type, one to a method. That means two bugs.
1. I have flat namespaces and allow all kinds of names everywhere, there is no disambiguation at the syntactic level of constructors or functions. (Like Ocaml and Haskell where constructors start with an uppercase letter.) I deal with that with one separate pass after identification which just checks all identifiers to see if they are bound legally. It missed this case.
2. The missing underscore left two identifiers, which treated as names, should have given a typing error.
I better make sure I am not working with an old compiler in which I turned checks off for speed.
(Great bug, concerning 2. It probably behaved correctly, a type name maps to its definition, a method to its type. The silliness...)