# JOURNAL — eval phase ## 2026-06-15 — Implementation Built evaluator, CLI, and tests in one go. ### evaluator.py `evaluate(node)` walks the AST recursively: - `Num` → return `node.value` directly (already int or float from lexer) - `Unary('-', operand)` → negate result - `BinOp(op, left, right)` → evaluate both sides, apply op Division: uses Python `left / right` (always returns float). If `right == 0`, raises `EvalError("Division by zero")`. D3 result type rule: after computing a float result in BinOp, if `result == int(result)` we cast to int. This ensures `4/2 → 2` (int) and `7/2 → 3.5` (float). Integer arithmetic returns int naturally. ### calc.py CLI `main()` accepts exactly one argv argument (the expression string). Catches `LexError`, `ParseError`, `EvalError` → prints `Error: ` to stderr, exits 1. On success prints `result` (which is already int or float with correct type per D3 rule). ### Test run output ``` $ python -m unittest -q Ran 62 tests in 0.001s OK ``` (45 prior tests from lex+parse phases, 17 new evaluator tests) ### CLI checks ``` $ 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 (exit 1) $ python calc.py "1 +" → Error: Unexpected end of input (exit 1) ```