98d3344912
Introduce a TCO pass to the compiler and modify the VM to handle tail calls. This allows for deep recursion without stack overflow.
70 lines
1.8 KiB
Rust
70 lines
1.8 KiB
Rust
use std::rc::Rc;
|
|
use crate::ast::types::{Value, StaticType};
|
|
use crate::ast::nodes::Node;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
pub enum Address {
|
|
Local(u32), // Stack-Slot index (relative to frame base)
|
|
Upvalue(u32), // Index in the closure's upvalue array
|
|
Global(u32), // Index in the global environment vector
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum BoundKind {
|
|
Nop,
|
|
Constant(Value),
|
|
|
|
// Variable Access (Resolved)
|
|
Get(Address),
|
|
|
|
// Variable Update (Resolved)
|
|
Set {
|
|
addr: Address,
|
|
value: Box<Node<BoundKind, StaticType>>,
|
|
},
|
|
|
|
If {
|
|
cond: Box<Node<BoundKind, StaticType>>,
|
|
then_br: Box<Node<BoundKind, StaticType>>,
|
|
else_br: Option<Box<Node<BoundKind, StaticType>>>,
|
|
},
|
|
|
|
// Global Definition (Locals are implicit by stack position)
|
|
DefGlobal {
|
|
global_index: u32,
|
|
value: Box<Node<BoundKind, StaticType>>,
|
|
},
|
|
|
|
Lambda {
|
|
param_count: u32,
|
|
// The list of variables captured from enclosing scopes
|
|
upvalues: Vec<Address>,
|
|
body: Rc<Node<BoundKind, StaticType>>,
|
|
},
|
|
|
|
Call {
|
|
callee: Box<Node<BoundKind, StaticType>>,
|
|
args: Vec<Node<BoundKind, StaticType>>,
|
|
},
|
|
|
|
TailCall {
|
|
callee: Box<Node<BoundKind, StaticType>>,
|
|
args: Vec<Node<BoundKind, StaticType>>,
|
|
},
|
|
|
|
Block {
|
|
exprs: Vec<Node<BoundKind, StaticType>>,
|
|
},
|
|
|
|
// NEW
|
|
Tuple {
|
|
elements: Vec<Node<BoundKind, StaticType>>,
|
|
},
|
|
Map {
|
|
entries: Vec<(Node<BoundKind, StaticType>, Node<BoundKind, StaticType>)>,
|
|
},
|
|
|
|
// Extension points (need to be adapted for bound nodes if they use variables)
|
|
// For now, we assume extensions are self-contained or handled dynamically.
|
|
}
|