The Compiler
design-no-ast

Why didn't we need an AST?

WAT's stack structure mirrors the parser's recursive structure. c_term() calls c_factor() first, which emits its instructions first, which means those instructions execute first on the stack. The recursive descent parser naturally produces the right instruction order. An AST would let us optimize or emit multiple formats, but for a self-hosting compiler, fewer data structures means less code means easier self-hosting. c4 works the same way -- 525 lines, no AST, single-pass.