# STATUS — phase eval ## Role Builder (Adversary monitors) ## Phase eval — evaluator + CLI ## Gates - D1: CLAIMED, awaiting Adversary - D2: CLAIMED, awaiting Adversary - D3: CLAIMED, awaiting Adversary - D4: CLAIMED, awaiting Adversary - D5: CLAIMED, awaiting Adversary --- ## Gate D1 — arithmetic CLAIMED **WHAT:** `evaluate(parse(tokenize(s)))` is correct for `+ - * /`, precedence, parens, unary minus. **HOW:** ```bash python -m unittest calc.test_evaluator.TestD1Arithmetic -v ``` **EXPECTED:** ``` test_add_mul_precedence ... ok # "2+3*4" -> 14 test_parens ... ok # "(2+3)*4" -> 20 test_left_assoc_sub ... ok # "8-3-2" -> 3 test_unary_minus ... ok # "-2+5" -> 3 test_mul_unary ... ok # "2*-3" -> -6 ``` 5 tests, 0 failures, exit 0. **WHERE:** `calc/evaluator.py` + `calc/test_evaluator.py`, commit `3e0b844` --- ## Gate D2 — division CLAIMED **WHAT:** `/` is true division (`"7/2"`→3.5). Division by zero raises `EvalError` — not bare `ZeroDivisionError`. **HOW:** ```bash python -m unittest calc.test_evaluator.TestD2Division -v ``` **EXPECTED:** ``` test_div_by_zero_not_bare ... ok test_div_by_zero_raises_eval_error ... ok test_true_division ... ok ``` 3 tests, 0 failures, exit 0. **WHERE:** `calc/evaluator.py` (EvalError defined, division guard at line 27-29), commit `3e0b844` --- ## Gate D3 — result type CLAIMED **WHAT:** Whole-valued floats print without `.0` (`"4/2"`→`2`); non-whole print as float (`"7/2"`→`3.5`). Rule is in `format_result()` in `calc/evaluator.py`. **HOW:** ```bash python -m unittest calc.test_evaluator.TestD3ResultType -v # And manually: python calc.py "4/2" # expect: 2 python calc.py "7/2" # expect: 3.5 ``` **EXPECTED:** ``` test_calc_4_div_2_whole ... ok test_calc_7_div_2_nonwhole ... ok test_format_int ... ok test_format_nonwhole_float ... ok test_format_whole_float ... ok ``` 5 tests, 0 failures, exit 0. CLI: `4/2` → `2`, `7/2` → `3.5`. **WHERE:** `calc/evaluator.py` `format_result()` + `calc.py` line using it + `calc/test_evaluator.py` TestD3ResultType, commit `3e0b844` --- ## Gate D4 — CLI CLAIMED **WHAT:** `python calc.py "2+3*4"` prints `14`, exits 0. `python calc.py "1 +"` prints error to stderr, exits non-zero (no traceback). **HOW:** ```bash python -m unittest calc.test_evaluator.TestD4CLI -v # Manual spot-checks: python calc.py "2+3*4" # stdout: 14, exit 0 python calc.py "1 +" # stderr: error:..., exit 1, stdout empty python calc.py "1/0" # stderr: error:..., exit 1 ``` **EXPECTED:** ``` test_div_by_zero_exits_nonzero ... ok test_float_result ... ok test_invalid_exits_nonzero ... ok test_parens_cli ... ok test_simple_expr ... ok test_whole_float_no_dot ... ok ``` 6 tests, 0 failures, exit 0. **WHERE:** `calc.py` (repo root) + `calc/test_evaluator.py` TestD4CLI, commit `3e0b844` --- ## Gate D5 — tests green + end-to-end CLAIMED **WHAT:** `calc/test_evaluator.py` passes covering D1–D3+D4; whole prior suite (lex+parse) still passes; no regression. **HOW:** ```bash python -m unittest -q # Full end-to-end plan verify: 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, exit 1 python calc.py "1 +" # error to stderr, exit 1 ``` **EXPECTED:** ``` Ran 50 tests in ~0.2s OK ``` Exit 0. 50 tests total: 19 lex + 12 parse + 19 evaluator (5 D1 + 3 D2 + 5 D3 + 6 D4). **WHERE:** `calc/test_evaluator.py`, `calc/test_lexer.py`, `calc/test_parser.py`, commit `3e0b844`