Internals
Compiler Architecture
A reference overview of the Pseudo compilation pipeline. Useful for contributors and those building extensions.
This is a reference section. You do not need to understand the internals to use Pseudo.
Pipeline Overview
pipeline
Source (.pseudo)
│
▼
1. Indentation Parser → parse_indentation() / build_block_tree()
│ Handles tab/space, inline colon blocks
▼
2. Pass 1 - Registration → run_registration_pass()
│ Scans for function/variable definitions
│ Builds symbol table before execution
▼
3. PMAP Loader → PmapLoader.load()
│ Parses .pmap, builds prefix trie
│ Handles @inherit, @replace, @context
│ Cache: SHA256 hash invalidation
▼
4. Pass 2 - Resolver → MappingResolver.resolve_blocks()
│ Matches each line against trie patterns
│ Parses expressions via recursive descent
│ Builds canonical AST (ProgramNode)
▼
5. Semantic Analyzer → SemanticAnalyzer.analyze()
│ Validates undefined vars/functions
│ Checks argument counts
│ Generates warnings
▼
6. Interpreter → Interpreter.run()
│ Tree-walking execution
│ Scope management (Scope chain)
│ Built-in resolution
│ Auto-print, step mode, timeout
▼
7. (optional) Complexity → ComplexityEngine.analyze()
Static Big-O analysis
Walks AST for loop nesting, recursionFile Map
| File | Purpose | ~Lines |
|---|---|---|
pseudo/__init__.py | Package entry, version export | 4 |
pseudo/parser/tokenizer.py | Lexer - character → tokens | 266 |
pseudo/parser/normalizer.py | Whitespace normalization | 56 |
pseudo/parser/indent_parser.py | Indentation + block tree | 300 |
pseudo/parser/ast_nodes.py | All AST dataclass definitions | 293 |
pseudo/parser/expr_parser.py | Recursive descent expression parser | 577 |
pseudo/data/default.pmap | Bundled default English mappings | 163 |
pseudo/resolver/pmap_loader.py | .pmap parser + prefix trie + cache | 706 |
pseudo/resolver/pass1_register.py | Function/variable registration | 199 |
pseudo/resolver/pass2_resolver.py | Pattern matching → AST | 988 |
pseudo/analyzer/semantic.py | Static validation + warnings | 320 |
pseudo/interpreter/interpreter.py | Tree-walking executor | 1018 |
pseudo/interpreter/builtins_ds.py | DS classes (Stack, Queue, etc.) | 421 |
pseudo/analyzer/complexity.py | Big-O static analysis | 611 |
pseudo/compiler.py | Pipeline glue + CLI integration | 256 |
pseudo/cli.py | argparse CLI entry point | 293 |
pseudo/install.py | ~/.pseudo/ home setup | 88 |
Two-Pass Parsing
Pseudo uses two passes to support mutual recursion and forward references:
| Pass | What it does |
|---|---|
| Pass 1 - Registration | Scans the entire file. Registers all function names and global variables into the symbol table. No execution occurs. No .pmap matching occurs. |
| Pass 2 - Resolver | With the full symbol table available, resolves every line via .pmap pattern matching and builds the canonical AST. |
Prefix Trie (Pattern Matching)
All patterns are compiled into a prefix trie keyed by the first literal token. For a line starting with for, only patterns that start with for are tested - O(1) lookup, then O(small subset) pattern check.
Scope Chain
The interpreter maintains a chain of Scope objects:
- Global scope: top-level variables and functions
- Local scope: created per function call, parent is always global
- Reads walk up the chain; writes stay local unless
globaldeclared - Recursion limit: 1000 call stack depth
Auto-print Signal
Bare expressions and function calls that are not assigned become AutoPrintNode in the AST. The interpreter evaluates them and prints the result if it is non-null (and --no-auto-print is not set).