Journal entry for
I’ve been thinking about why GHC’s front-end code is so big and complicated/fragile feeling.
I think it might be because of the huge Expr data structure that is meant to represent the full surface syntax, and is used throughout the parser, renamer, and type checker phases.
Maybe this makes it so that various concerns are all intermingled, even though there are these separate “phases” that traditional compiler designers like to use.
A Scheme implementation doesn’t feel like that. Instead they are written as a tiny but fully featured base language with a nice hygienic macro system, and macros are used to implement all the extra features.
I think the hard part about this is to achieve good error reporting. I wonder how Typed Racket does it.
In any case, GHC differs significantly from this, because Core is a very simple AST, without any source information.
Everything to do with nice surface syntax has to happen somewhere else, because there doesn’t seem to be a way to connect Core to the original program.
Also, while GHC technically has macros it really isn’t possible to make new syntax that feels native. Macro calls have to be in special delimiters.