Session 5 — Variables, Math, Conditionals & Error Handling¶
What Was Built¶
The core features that make Terse a real general-purpose programming language — variables, arithmetic, conditional logic, and a proper error handling system.
Error Handling¶
File: src/interpreter/errors.py
A new dedicated errors module with three custom exception types:
| Class | Purpose |
|---|---|
TerseError |
Base error — message and optional line number |
TerseNameError |
Unknown node or function |
TerseSyntaxError |
Malformed statement |
TerseTypeError |
Wrong type used |
Before this session, errors produced Python tracebacks with no context. Now Terse produces clean, readable messages:
TerseError: unknown node 'dgo' — has it been declared with 'know'?
TerseError: unknown function 'clasify' — has it been defined with 'to'?
Variables¶
Variables store a value under a name and persist for the life of the program.
The interpreter stores variables in self.variables{} separately from the knowledge base. Variables can reference other variables:
Implementation Note
All parser imports must be at the top of interpreter.py — not inside methods. Python's module caching causes isinstance checks to fail silently when the same class is imported from two different module instances. This was a significant bug discovered and fixed this session.
Math Expressions¶
Full arithmetic expression support with variable references.
Supported operators: +, -, *, /
The parser collects everything on the right side of = as an expression list. The interpreter resolves variable names to their values, then evaluates the expression.
Conditionals¶
If/else conditional logic with full comparison operator support.
Supported operators: >, <, >=, <=, =, !=
Variables are resolved before comparison — if x > 5 uses the current value of x. The else body is optional.
Bug Fixes¶
Two significant bugs were discovered and fixed this session:
Multi-value facts — Previously know dog has fur followed by know dog has legs would overwrite fur with legs. Now both values are stored as a list: has: ['fur', 'legs']. Inference rules check against all values in the list.
Each loop type matching — After inference ran and updated a node's is value (e.g. dog going from is: animal to is: mammal), each beast in animal could no longer find the node. Fixed by introducing self.types{} — a separate registry that tracks original declared types and is never overwritten by inference.
Showcase Program — animal_mind.trs¶
A complete Terse program demonstrating all language features working together:
know dog is animal
know dog has fur
know dog has legs
know eagle is animal
know eagle has wings
when has fur then is mammal
when has wings then can fly
to describe creature
infer creature
return creature
each beast in animal
describe beast
Output — all four animals correctly classified, all behavioral sequences correctly predicted.
REPL Commands¶
The REPL gained a new command this session:
| Command | What it does |
|---|---|
variables |
Print all current variable assignments |
Phase 1 Progress After Session 5¶
| Component | Status |
|---|---|
| Lexer | ✅ Complete |
| Parser | ✅ Complete |
| Interpreter core | ✅ Complete |
| Facts & relationships | ✅ Complete |
| Inference rules | ✅ Complete |
| Functions with scope | ✅ Complete |
| Markov chain learning | ✅ Complete |
| Each loops | ✅ Complete |
| While loops | ✅ Complete |
| main.py | ✅ Complete |
| REPL | ✅ Complete |
| Error handling | ✅ Complete |
| Variables | ✅ Complete |
| Math expressions | ✅ Complete |
| Conditionals | ✅ Complete |
| Tensors | 🔵 Next session |
| Compression keywords | 🔵 Next session |
| Ethics rule syntax | ⚪ Planned |
Interpreter completeness: ~90%