Architecture Overview¶
Language: Español | English
Crespi is a bilingual programming language implemented in Rust. It features a tree-walking interpreter for development and an LLVM-based native compiler for production.
High-Level Architecture¶
┌─────────────────────────────────────────────────────────────────────┐
│ Source Code │
│ (.crespi files) │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Lexer/Scanner │
│ (Tokenization with ASI, keyword mapping) │
│ English → Token ← Spanish │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Parser │
│ (Recursive descent with climbing precedence) │
│ Produces AST │
└─────────────────────────────────────────────────────────────────────┘
│
┌─────────────┴─────────────┐
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────────────┐
│ Interpreter │ │ Native Compiler │
│ (Tree-walking eval) │ │ │
│ │ │ ┌─────────────────────────┐ │
│ ┌─────────────────────┐ │ │ │ HIR (High-level IR) │ │
│ │ Environment │ │ │ │ (Lowering from AST) │ │
│ │ (Lexical scoping) │ │ │ └─────────────────────────┘ │
│ └─────────────────────┘ │ │ │ │
│ │ │ ▼ │
│ ┌─────────────────────┐ │ │ ┌─────────────────────────┐ │
│ │ Value (Rc-based) │ │ │ │ LLVM IR │ │
│ │ Interpreter types │ │ │ │ (Code generation) │ │
│ └─────────────────────┘ │ │ └─────────────────────────┘ │
└───────────────────────────┘ │ │ │
│ │ ▼ │
▼ │ ┌─────────────────────────┐ │
┌───────────────────────────┐ │ │ Native Executable │ │
│ Output │ │ │ (+ crespi-runtime) │ │
└───────────────────────────┘ │ └─────────────────────────┘ │
└───────────────────────────────────┘
Key Design Decisions¶
1. English-First Bilingual Support¶
The language core uses English as the canonical form:
- English keywords (var, class, fn, this) are primary
- Spanish keywords (variable, tipo, bloque, yo) are aliases defined in the lexer
- All internal code, compiler passes, and runtime use English identifiers
- Spanish translation happens at the lexer level (token → same TokenKind)
This ensures: - Consistent internal representation - Easy addition of more languages in the future - No runtime overhead for language switching
Language Pack Workflow¶
crespi-schemadefines the source-of-truth lists for keywords, builtins, runtime type aliases, and operator aliases.crespi-langpackvalidates.crespilangfiles against the schema (validate/diff).crespi-i18nloads packs and provides forward/reverse maps.- The lexer uses the reverse maps to normalize localized keywords/operators/builtins into English tokens and identifiers.
2. Value Model (Tagged Values)¶
The LLVM backend uses a tagged value struct (tag + payload) for dynamic
values and native machine types for statically known primitives. See
docs/llvm/abi.md for the current ABI.
3. Reference Counting with Cycle Detection¶
The runtime uses reference counting with cycle detection: - Each heap object has a reference count - Cycles detected via mark-sweep when counts don't reach zero - Closure environments properly tracked for captures
4. Two Execution Modes¶
| Mode | Binary | Use Case |
|---|---|---|
| Interpreter | crespi |
Development, REPL, debugging |
| Compiler | crespic |
Production, performance-critical |
Both modes support the full language feature set.
5. Duck-Typed Generics¶
Generics use square bracket syntax to avoid ambiguity:
class Box[T](let value) // Not <T> to avoid comparison operator ambiguity
Type parameters are parsed but not enforced at runtime (duck typing).
6. Interpreter/Compiler Parity¶
- Both modes rely on English canonical names after lexing.
- Builtins must be implemented in
crespi-core(interpreter) andcrespi-runtime(compiled), plus registered in codegen (lowering.rs,compiler.rs). - When adding keywords/operators/builtins, update
crespi-schema, language packs, and the reference docs together. - Constants like
PI/Eare aliases forpi()/e()during compilation.
Data Flow¶
Interpretation Flow¶
Source → Lexer → Parser → AST → Interpreter → Value
↓
Environment (scopes)
Compilation Flow¶
Source → Lexer → Parser → AST → HIR (lowering) → LLVM IR → Object Code
↓ ↓
Variable resolution Link with runtime
Free variable analysis ↓
Builtin translation Native Executable
Module System¶
Inspired by Swift, the module system supports:
import Helpers // Entire module
import Math.Vector // Nested module
import Helper { double, Point } // Explicit symbols
import class Math.Point // Specific class
import fn Utils.format // Specific function
Resolution order:
1. Relative to importing file
2. Source root
3. Additional -I search paths
File naming:
- snake_case.crespi → PascalCase module name
- Directories create nested modules
See Also¶
- Crate Structure - Description of each crate