Translating a highly nested Abstract Syntax Tree directly into x86-64 assembly is incredibly difficult. Instead, modern compilers translate the AST into an Intermediate Representation (IR). This acts as a universal bridge between the front-end (Parser) and the back-end (Code Generator).
Your compiler uses a Post-Order Walk (walk_ast) to generate IR. Here is exactly what happens behind the scenes:
emit() function, instructions are broken down to contain a maximum of three addresses (e.g., arg1 OP arg2 = result). This perfectly mimics real CPU registers.x = (a + b) * (c - d) in one step, your new_temp() function creates temporary variables (t0, t1) to hold the results of intermediate calculations.Watch how the compiler traverses the complex AST from the bottom-up. Every time an operator resolves, it emit()s a Quad instruction and replaces the AST branch with a single Temporary Variable!
Target Code: x = (a + b) * (c - d);