# JOURNAL — Phase eval ## Implementation notes ### evaluator.py Built `evaluate(node) -> int | float` walking `Num`, `BinOp`, `Unary` nodes. - `Num`: returns `node.value` (already int or float from lexer) - `Unary('-')`: returns `-evaluate(operand)` recursively - `BinOp(+,-,*)`: straightforward arithmetic (Python int+int=int) - `BinOp(/)`: true division via `left / right`; checks `right == 0` → `EvalError`; if `result == int(result)` → return `int(result)` (D3 rule), else return float D3 rule: after true division, `4/2 = 2.0`; `2.0 == int(2.0)` is True, so return `int(2.0) = 2`. `7/2 = 3.5`; `3.5 != 3`, so return `3.5` (float). ### calc.py Top-level CLI at repo root. Imports from `calc.*`. Catches `LexError`, `ParseError`, `EvalError` → prints to stderr, exits 1. Traceback never escapes. ### test_evaluator.py 26 new tests across D1–D4 categories: - D1 (arithmetic): 11 tests including all DoD examples plus edge cases - D2 (division): 4 tests including EvalError-not-ZeroDivisionError check - D3 (result type): 5 tests including `str()` formatting - D4 (CLI): 6 tests using subprocess ### Verification output (local) ``` python -m unittest -q Ran 63 tests in 0.228s OK ``` ``` 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 "1/0" → error: division by zero (stderr, exit 1) python calc.py "1 +" → error: unexpected token 'EOF' (None) (stderr, exit 1) ```