Build a Compiler from Scratch, Part 1.2: Intermediate Representation and Code Generation