Status: Authoritative Specification Version: 2.0.0 Last Updated: 2026-07-15 Related Documents: 05 AST Design · 09 Runtime Design · 10 Semantic Analysis · 14 Error Codes
The interpreter evaluates AST nodes sequentially, using the CheckedProgram and SymbolTable to resolve scopes.
flowchart TD
CP["CheckedProgram"]
WALK["Walk AST\nTop-to-Bottom"]
EVAL_STMT["evaluate_statement()"]
EVAL_EXPR["evaluate_expression()"]
ENV["Environment\n(read/write)"]
RESULT["Value or RuntimeError"]
CP --> WALK
WALK --> EVAL_STMT
EVAL_STMT --> EVAL_EXPR
EVAL_EXPR --> ENV
EVAL_STMT --> ENV
EVAL_EXPR --> RESULT
EVAL_STMT --> RESULT
style CP fill:#ff6b6b,color:#fff
style RESULT fill:#6bcb77,color:#fff
Expressions are evaluated by type. Sub-expressions (arithmetic, comparison, logic) map to Rust operations on Value variants. Logical operators support short-circuiting.
Statements alter the environment state. Mutable declarations update the innermost environment scope. Jump instructions (break, continue, return) return control signals.
Functions evaluate into Value::Function closures. When a method is accessed on an instance, the interpreter retrieves the MethodDecl AST node and invokes it inside a local scope with self bound to the object:
execute_method(obj, method_name, args):
method = obj.methods.get(method_name)
// Invokes the method body regardless of whether it was defined
// using 'build' or 'fun' keyword in the source code.
eval_function_body(method, args, bound_self = obj)
- Unified Dispatch: The interpreter evaluates both
buildandfunmethod declarations identically. Both compile to standard method bindings at runtime. - Dynamic Scoping: Environment lookup chains match Version 1 scoping rules, preventing binding capture regressions.
- All modules imported during execution are resolved using
.txsfile extensions. - If a script relies on importing legacy
.techfiles, rename the files before execution. - Auto-fixing linter tasks bypass the interpreter, transforming source code files directly.
- Uniform Evaluation: Handling
buildandfunidentically in the execution path avoids duplicating frame-pushing logic and simplifies debugging. - Zero-allocation Signals: Using Rust's
Result<T, Signal>enum for control flow signals (Break,Continue,Return) avoids allocation overhead during loop execution.
- v2.1: The AST interpreter will be replaced by a flat bytecode execution loop (
techscript_vm), running VM instructions sequentially. - v3.0: Functions and methods will compile directly to LLVM instructions, removing interpreter frame push overhead.