# JOURNAL — eval phase ## Implementation run (2026-06-16) ### Pre-state - 44 tests passing (lex + parse phases) - `calc/lexer.py`, `calc/parser.py` already in place - AST nodes: `Num(value)`, `BinOp(op, left, right)`, `Unary(op, operand)` ### calc/evaluator.py Wrote tree-walking `evaluate(node)`: - `Num` → return `node.value` - `Unary` → `-evaluate(operand)` (only `-` is supported) - `BinOp` → recurse left/right, apply op; `/` case: raise `EvalError("division by zero")` when `right == 0`, otherwise `left / right` - Whole-float normalisation: `if isinstance(result, float) and result.is_integer(): return int(result)` ### calc/test_evaluator.py 12 tests across 4 classes: - `TestArithmetic` — the 5 DoD examples - `TestDivision` — true division, div-by-zero as `EvalError`, no bare `ZeroDivisionError` - `TestResultType` — `4/2` is `int`, `7/2` is `float`, plain int arithmetic stays `int`, negative whole is `int` ### calc.py (CLI) At repo root; uses `sys.argv[1]`, calls lex→parse→eval pipeline. Catches `LexError | ParseError | EvalError`, prints `error: {e}` to stderr, exits 1. Clean exit 0 on success. ### Test run ``` $ python -m unittest -q Ran 56 tests in 0.001s OK ``` ### CLI smoke test ``` $ python calc.py "2+3*4" → 14 $ python calc.py "(2+3)*4" → 20 $ python calc.py "7/2" → 3.5 $ python calc.py "4/2" → 2 $ python calc.py "8-3-2" → 3 $ python calc.py "-2+5" → 3 $ python calc.py "2*-3" → -6 $ python calc.py "1/0" → error: division by zero (exit 1) $ python calc.py "1 +" → error: unexpected token 'EOF' (None) (exit 1) ``` All DoD items satisfied. Writing ## DONE to STATUS-eval.md.