Appendix D: Debugging
Debug flags and techniques for the Ori compiler.
Debug Flags
The debug.rs module provides debug flags:
pub struct DebugFlags(u32);
impl DebugFlags {
pub const TOKENS: Self = Self(0b0000_0001);
pub const AST: Self = Self(0b0000_0010);
pub const TYPES: Self = Self(0b0000_0100);
pub const EVAL: Self = Self(0b0000_1000);
pub const IMPORTS: Self = Self(0b0001_0000);
pub const PATTERNS: Self = Self(0b0010_0000);
pub const SALSA: Self = Self(0b0100_0000);
pub const ALL: Self = Self(0b0111_1111);
}
Environment Variable
Enable debugging via ORI_DEBUG:
# Enable all debug output
ORI_DEBUG=all ori run file.ori
# Enable specific flags
ORI_DEBUG=tokens,ast ori run file.ori
# Enable single flag
ORI_DEBUG=types ori run file.ori
Debug Macros
// In compiler code
debug_tokens!("Tokenized: {:?}", tokens);
debug_ast!("Parsed: {:?}", module);
debug_types!("Inferred type: {:?}", ty);
debug_eval!("Evaluating: {:?}", expr);
Token Debugging
ORI_DEBUG=tokens ori run file.ori
Output:
[TOKENS] let x = 42
Token { kind: Let, span: 0..3 }
Token { kind: Ident("x"), span: 4..5 }
Token { kind: Eq, span: 6..7 }
Token { kind: Int(42), span: 8..10 }
AST Debugging
ORI_DEBUG=ast ori run file.ori
Output:
[AST] Module {
functions: [
Function {
name: "main",
params: [],
body: ExprId(0),
}
]
}
[AST] ExprArena:
[0] Let { name: "x", value: ExprId(1), body: ExprId(2) }
[1] Literal(Int(42))
[2] Ident("x")
Type Debugging
ORI_DEBUG=types ori run file.ori
Output:
[TYPES] Inferring: let x = 42
x : T0 (fresh)
42 : Int
Unify(T0, Int) -> Ok
x : Int
[TYPES] Expression types:
ExprId(0): Int
ExprId(1): Int
ExprId(2): Int
Evaluation Debugging
ORI_DEBUG=eval ori run file.ori
Output:
[EVAL] Evaluating ExprId(0): Let
Evaluating value ExprId(1): Literal
-> Value::Int(42)
Binding x = Int(42)
Evaluating body ExprId(2): Ident
Lookup x -> Int(42)
-> Value::Int(42)
-> Value::Int(42)
Salsa Debugging
ORI_DEBUG=salsa ori run file.ori
Output:
[SALSA] will_execute: tokens(SourceFile(0))
[SALSA] did_execute: tokens(SourceFile(0)) in 1.2ms
[SALSA] will_execute: parsed(SourceFile(0))
[SALSA] did_execute: parsed(SourceFile(0)) in 3.4ms
[SALSA] will_execute: typed(SourceFile(0))
[SALSA] did_execute: typed(SourceFile(0)) in 2.1ms
Import Debugging
ORI_DEBUG=imports ori run file.ori
Output:
[IMPORTS] Resolving: './math'
Base: /home/user/project/src/main.ori
Resolved: /home/user/project/src/math.ori
Cache: miss
Loading...
[IMPORTS] Module './math' exports:
add: (int, int) -> int
subtract: (int, int) -> int
Pattern Debugging
ORI_DEBUG=patterns ori run file.ori
Output:
[PATTERNS] Evaluating: map
over: [1, 2, 3]
transform: <function>
[PATTERNS] map iteration:
[0] transform(1) -> 2
[1] transform(2) -> 4
[2] transform(3) -> 6
[PATTERNS] Result: [2, 4, 6]
Programmatic Debugging
// Enable in code
debug::set_flags(DebugFlags::TYPES | DebugFlags::EVAL);
// Check if enabled
if debug::is_enabled(DebugFlags::TOKENS) {
eprintln!("Tokens: {:?}", tokens);
}
IDE Integration
For VS Code debugging, launchjson:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Compiler",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/target/debug/oric",
"args": ["run", "${file}"],
"env": {
"ORI_DEBUG": "all",
"RUST_BACKTRACE": "1"
}
}
]
}
Panic Debugging
Enable backtraces:
RUST_BACKTRACE=1 ori run file.ori
RUST_BACKTRACE=full ori run file.ori
Memory Debugging
Using valgrind:
valgrind --leak-check=full target/debug/oric run file.ori
Performance Profiling
Using perf:
perf record target/release/oric run large_file.ori
perf report
Test Debugging
Debug specific test:
ORI_DEBUG=all cargo test test_type_inference -- --nocapture
Common Debug Scenarios
”Why is this type wrong?”
ORI_DEBUG=types ori check file.ori
Look for:
- Constraint generation
- Unification steps
- Final substitution
”Why isn’t this imported?”
ORI_DEBUG=imports ori run file.ori
Look for:
- Path resolution
- Export list
- Cache hits/misses
”Why is Salsa recomputing?”
ORI_DEBUG=salsa ori run file.ori
Look for:
- Which queries run
- Early cutoff misses
- Dependency changes