artifacts: add calculators/ — the 30 built calculators (5/variant) + machine-docs + git logs
This commit is contained in:
@ -0,0 +1,43 @@
|
||||
# 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: <msg>` 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)
|
||||
```
|
||||
Reference in New Issue
Block a user