The pipeline
Statement and expression dispatch
Both the statement executor and the expression evaluator use the same pattern — reflection over the node’s class name, rather than a big if/elif chain or a separate visitor class per concern:Control flow inside the interpreter
return, break, and continue are implemented as internal Python
exceptions (_Return, _Break, _Continue) that unwind the Python call
stack until something is prepared to catch them — a function call catches
_Return, a loop catches _Break/_Continue. This is a standard
tree-walking-interpreter technique: it reuses Python’s own stack-unwinding
machinery instead of threading explicit “did we hit a return” signals
through every level of statement execution by hand.
Environments carry more than variables
Every statement/expression method takes anenv: Environment parameter —
the current lexical scope. As of the agent pause/resume work, Environment
also carries the current scope’s delegation and policy overrides (see
Scoping & Delegation) and, for an
agent’s own scope, a reference back to that agent (so pause() can find
“which agent am I currently inside,” the same way a variable lookup finds
“which binding am I currently inside”).
Modules and the global environment
Interpreter.globals is a single Environment holding every builtin.
Running a file (or importing a module) creates a child of globals for
that file/module’s own top-level bindings — so builtins are visible
everywhere, but two different files’ top-level variables never collide.
Imported modules are cached by absolute path and executed exactly once,
with in-progress imports tracked separately to detect cycles (see
Modules).
Continue
Indentation-sensitive lexing
How the lexer turns leading whitespace into
INDENT/DEDENT tokens.Scoping & delegation
Why
set delegation and policy live on Environment, not the
interpreter.
