# JOURNAL — phase eval ## Build - Read `calc/parser.py` and `calc/lexer.py` to understand AST node types (`Num`, `Unary`, `BinOp`) and token shapes. - Wrote `calc/evaluator.py`: `EvalError`, `evaluate(node)` dispatching on node type, `_normalise()` helper applying the whole-value→int rule after every operation. - Wrote `calc.py`: CLI entry-point using `tokenize → parse → evaluate`, catches `LexError`, `ParseError`, `EvalError` and prints to stderr with exit 1. - Wrote `calc/test_evaluator.py`: 20 tests covering D1 arithmetic, D2 division/EvalError, D3 result type (including isinstance checks and str representation). ## Verification Ran full suite (`python -m unittest -q`): 64 tests, 0 failures. Ran all plan CLI checks by hand; all match expected output exactly. Confirmed error output goes to stderr (stdout empty on error paths). Confirmed `EvalError` (not `ZeroDivisionError`) escapes the API. ## Commit `0323698` — feat: add evaluator, CLI, and test suite (phase eval)