1.2 KiB
1.2 KiB
JOURNAL — eval phase
2026-06-15
Implementation approach
Read the existing lexer/parser to understand AST node shapes: Num(value), BinOp(op, left, right), Unary(op, operand).
Implemented calc/evaluator.py:
EvalError(Exception)— wraps division-by-zero and unknown nodes; never letsZeroDivisionErrorescape.evaluate(node)— recursive AST walk; delegates to_coerceafter each operation._coerce(value)— ifisinstance(value, float) and value == int(value)→ returnint(value); else return value as-is. This is the D3 rule applied uniformly at every arithmetic result.
Created calc/test_evaluator.py with 20 tests across 3 test classes (TestArithmetic, TestDivision, TestResultType).
Created top-level calc.py CLI: parses one arg, catches LexError | ParseError | EvalError, prints to stderr + exits 1 on error, prints result + exits 0 on success.
Test run output
$ python -m unittest -q
Ran 68 tests in 0.001s
OK
CLI spot-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 token 'EOF' (None)
(exit 1)