Interpreter arithmetic trace (source code)

= Interpreter arithmetic trace

Use the <compilation arithmetic example> with input $x=7$. An <abstract syntax tree> <interpreter> first reads `x`, obtains $2+3=5$, forms $7\cdot5=35$, and finally computes $35-4=31$. Interpreting the folded <abstract syntax tree> skips the <addition> but gives the same result. The compiled <stack machine> instructions instead produce the following trace; the top of the <stack> is written on the right:

``
instruction    stack after instruction
initial        []
LOAD x         [7]
PUSH 5         [7, 5]
MUL            [35]
PUSH 4         [35, 4]
SUB            [31]
``

\Image[/interpreter-tree-stack-trace.png]
{title=Execution of `x*(2+3)-4` at $x=7$: the original <abstract syntax tree> and the folded <stack machine> instructions both give $31$}
{id=image-interpreter-tree-stack-trace}

The order in `SUB` is essential: reversing its two popped operands would give $4-35=-31$. The same stored instruction sequence works for input $x=-2$, yielding $(-2)\cdot5-4=-14$, without repeating <parsing> or <constant folding>. An <abstract syntax tree> <interpreter> can likewise reuse its already-parsed tree. Reusing a representation is therefore useful to both approaches; it does not itself distinguish <compilation> from interpretation.

The pleasing part is that a nested <rooted tree> and a flat instruction sequence express the same computation. The <structural induction> in the <compilation arithmetic example> connects them by a precise <stack> property. This tiny language always terminates and has no <side effects>; richer <programming language semantics> require a correctness argument that also accounts for failures, externally visible actions, and possible nontermination.