## DONE Phase: eval — evaluator + CLI All DoD items self-certified (BUILD phase — deferred Adversary review). --- ### Files created - `calc/evaluator.py` — `EvalError`, `evaluate(node) -> int | float` - `calc.py` — top-level CLI - `calc/test_evaluator.py` — 22 new unittest tests covering D1–D4 --- ### D1 — arithmetic WHAT: `evaluate(parse(tokenize(s)))` correct for `+`, `-`, `*`, `/`, precedence, parens, unary minus. HOW: ``` python calc.py "2+3*4" # → 14 python calc.py "(2+3)*4" # → 20 python calc.py "8-3-2" # → 3 python calc.py "-2+5" # → 3 (requires shell quoting awareness) python calc.py "2*-3" # → -6 ``` EXPECTED: outputs above WHERE: calc/evaluator.py `evaluate()` --- ### D2 — division WHAT: `/` is true division; division by zero raises `EvalError`. HOW: ``` python calc.py "7/2" # → 3.5 python calc.py "1/0" # → stderr error, exit 1 ``` EXPECTED: `3.5` for 7/2; non-zero exit + stderr for 1/0 WHERE: calc/evaluator.py BinOp `/` branch --- ### D3 — result type WHAT: Whole-valued → int (no `.0`), non-whole → float. HOW: ``` python calc.py "4/2" # → 2 (not 2.0) python calc.py "7/2" # → 3.5 ``` EXPECTED: `2` and `3.5` WHERE: calc/evaluator.py — `if isinstance(result, float) and result == int(result): return int(result)` --- ### D4 — CLI WHAT: `python calc.py "2+3*4"` → `14`, exit 0; error → stderr, non-zero exit, no traceback. HOW: ``` python calc.py "2+3*4" # → 14, exit 0 python calc.py "1 +" # → error to stderr, exit 1 ``` EXPECTED: as above WHERE: calc.py `main()` --- ### D5 — tests green + end-to-end WHAT: Full test suite (lex + parse + eval) passes; 0 failures. HOW: `python -m unittest -q` EXPECTED: ``` Ran 56 tests in 0.226s OK ``` WHERE: calc/test_lexer.py (14) + calc/test_parser.py (20) + calc/test_evaluator.py (22) --- ### Verify commands (from eval.md, verbatim) ```bash python -m unittest -q # Ran 56 tests in ...s 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 to stderr, non-zero exit python calc.py "1 +" # error to stderr, non-zero exit ``` Commit: (see git log — latest commit on main)