Source Architecture
The compiler is organized as a pipeline. Source text enters at the syntax layer, flows through type checking and optional analysis passes, and exits as Triton VM assembly (TASM).
source.tri
|
v
syntax/ lexer -> parser -> AST
|
v
typecheck/ type checking, borrow checking, generics
|
+----> tir/ Trident IR: instruction selection + stack lowering
| +----> triton.rs (Triton VM TASM output)
|
v
output.tasm
Parallel to the main pipeline, several modules provide analysis, tooling, and package management:
cost/ static cost analysis (trace height estimation)
verify/ formal verification (symbolic execution, SMT, equivalence)
tools/ LSP, scaffolding, module resolution, introspection
package/ content-addressed package management, store, registry
Module Map
| Module | LOC | What it does |
|---|---|---|
syntax/ |
4,392 | Lexer, parser, token definitions, formatter |
typecheck/ |
3,007 | Type checker with borrow analysis, generics, and builtin registration |
tir/ |
3,678 | Trident IR: opcode definitions, AST→TIR builder, Triton lowering, stack manager |
cost/ |
2,335 | Static cost analyzer, per-function breakdown, optimization hints and reports, target cost models |
verify/ |
5,570 | Symbolic execution, constraint solving, SMT encoding, equivalence checking, invariant synthesis, JSON reports |
package/ |
6,494 | BLAKE3 hashing, Poseidon2, definitions store, registry server/client, dependency manifests, compilation cache |
tools/ |
5,004 | Language Server, code scaffolding, definition viewer, project config, module resolution, target configuration, artifact packaging |
Top-Level Files
| File | LOC | Role |
|---|---|---|
ast.rs |
371 | AST node definitions shared by every stage |
lib.rs |
2,700 | Public API, re-exports, and orchestration functions (compile, analyze_costs, check_file) |
main.rs |
2,650 | CLI entry point: argument parsing and command dispatch |
linker.rs |
134 | Multi-module linker for cross-module calls |
Total: ~36,700 lines across 57 Rust files, 5 runtime dependencies.
Compilation Pipeline
Syntax (syntax/). The lexer tokenizes source into the token types defined in lexeme.rs. The parser produces a typed AST (ast.rs). The formatter can pretty-print any AST back to canonical source.
Type Checking (typecheck/). The type checker validates types, resolves generics via monomorphization, performs borrow/move analysis, and registers builtin function signatures (builtins.rs). Diagnostics are emitted for type mismatches, undefined variables, unused bindings, and borrow violations.
TIR Pipeline (tir/). The TIR builder translates the typed AST into a flat sequence of TIROp instructions. The Triton lowering produces TASM assembly. The stack manager tracks operand positions with automatic RAM spill/reload. The linker resolves cross-module calls.
Cost Analysis (cost/). The analyzer walks the AST and sums per-instruction costs using a target-specific CostModel. The report module formats results, generates optimization hints, and provides JSON serialization for --compare workflows.
Formal Verification (verify/). The symbolic executor builds path constraints over the AST. The solver uses Schwartz-Zippel randomized testing and bounded model checking. The SMT module encodes constraints in SMT-LIB2 for external solvers. The equivalence checker proves two functions compute the same result. The synthesizer infers loop invariants automatically.
Package Management (package/). Content-addressed storage using BLAKE3 hashing with Poseidon2 for in-proof verification. The definitions store manages a local codebase of named, versioned definitions. The registry provides an HTTP server and client for publishing and pulling definitions.
Design Principles
Direct mapping. Every language construct maps to a known instruction pattern. The compiler is a thin translation layer, not an optimization engine. This makes proving costs predictable and the compiler auditable.
Target abstraction. The StackLowering trait and CostModel trait isolate all target-specific knowledge. Adding a new backend means implementing these two traits — the rest of the compiler is shared.
Re-exports for stability. lib.rs re-exports every module at the crate root so that internal reorganization does not break downstream code or the binary crate.