e7628e5cdf
The `Get`, `DefLocal`, and `DefGlobal` bound kinds now store the symbol name associated with the variable. This information is useful for debugging and provides more context in the compiled output.
133 lines
4.2 KiB
Rust
133 lines
4.2 KiB
Rust
use std::rc::Rc;
|
|
use crate::ast::types::{Value, StaticType, Identity};
|
|
use crate::ast::nodes::{Node, Symbol};
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
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
|
|
}
|
|
|
|
/// Trait for DSL-specific AST extensions (like Pipe, Series-Access, etc.)
|
|
pub trait BoundExtension<T>: std::fmt::Debug {
|
|
fn clone_box(&self) -> Box<dyn BoundExtension<T>>;
|
|
fn display_name(&self) -> String;
|
|
}
|
|
|
|
impl<T> Clone for Box<dyn BoundExtension<T>> {
|
|
fn clone(&self) -> Self {
|
|
self.clone_box()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum BoundKind<T = ()> {
|
|
Nop,
|
|
Constant(Value),
|
|
|
|
// Variable Access (Resolved)
|
|
Get {
|
|
addr: Address,
|
|
name: Symbol,
|
|
},
|
|
|
|
// Variable Update (Assignment)
|
|
Set {
|
|
addr: Address,
|
|
value: Box<Node<BoundKind<T>, T>>,
|
|
},
|
|
|
|
// Variable Declaration (Local)
|
|
DefLocal {
|
|
name: Symbol,
|
|
slot: u32,
|
|
value: Box<Node<BoundKind<T>, T>>,
|
|
captured_by: Vec<Identity>,
|
|
},
|
|
|
|
If {
|
|
cond: Box<Node<BoundKind<T>, T>>,
|
|
then_br: Box<Node<BoundKind<T>, T>>,
|
|
else_br: Option<Box<Node<BoundKind<T>, T>>>,
|
|
},
|
|
|
|
// Global Definition (Locals are implicit by stack position)
|
|
DefGlobal {
|
|
name: Symbol,
|
|
global_index: u32,
|
|
value: Box<Node<BoundKind<T>, T>>,
|
|
},
|
|
|
|
Lambda {
|
|
param_count: u32,
|
|
// The list of variables captured from enclosing scopes
|
|
upvalues: Vec<Address>,
|
|
body: Rc<Node<BoundKind<T>, T>>,
|
|
},
|
|
|
|
Call {
|
|
callee: Box<Node<BoundKind<T>, T>>,
|
|
args: Vec<Node<BoundKind<T>, T>>,
|
|
},
|
|
|
|
TailCall {
|
|
callee: Box<Node<BoundKind<T>, T>>,
|
|
args: Vec<Node<BoundKind<T>, T>>,
|
|
},
|
|
|
|
Block {
|
|
exprs: Vec<Node<BoundKind<T>, T>>,
|
|
},
|
|
|
|
Tuple {
|
|
elements: Vec<Node<BoundKind<T>, T>>,
|
|
},
|
|
|
|
Map {
|
|
entries: Vec<MapEntry<T>>,
|
|
},
|
|
|
|
/// An expanded macro call, preserving the original call for debugging and UI.
|
|
Expansion {
|
|
/// The original call from the untyped AST.
|
|
original_call: Rc<Node<crate::ast::nodes::UntypedKind>>,
|
|
/// The result of binding the expanded AST.
|
|
bound_expanded: Box<Node<BoundKind<T>, T>>,
|
|
},
|
|
|
|
/// DSL-specific extension slot
|
|
Extension(Box<dyn BoundExtension<T>>),
|
|
}
|
|
|
|
/// A single entry in a Map literal (Key-Value pair)
|
|
pub type MapEntry<T> = (Node<BoundKind<T>, T>, Node<BoundKind<T>, T>);
|
|
|
|
/// Type alias for a node that has been bound (addresses resolved) but not yet type-checked.
|
|
pub type BoundNode = Node<BoundKind<()>, ()>;
|
|
|
|
/// Type alias for a node that has been fully type-checked and is ready for execution.
|
|
pub type TypedNode = Node<BoundKind<StaticType>, StaticType>;
|
|
|
|
impl<T> BoundKind<T> {
|
|
pub fn display_name(&self) -> String {
|
|
match self {
|
|
BoundKind::Nop => "NOP".to_string(),
|
|
BoundKind::Constant(v) => format!("CONST({})", v),
|
|
BoundKind::Get { addr, name } => format!("GET({}, {:?})", name.name, addr),
|
|
BoundKind::Set { addr, .. } => format!("SET({:?})", addr),
|
|
BoundKind::DefLocal { name, slot, .. } => format!("DEF_LOCAL({}, Slot:{})", name.name, slot),
|
|
BoundKind::If { .. } => "IF".to_string(),
|
|
BoundKind::DefGlobal { name, global_index, .. } => format!("DEF_GLOBAL({}, Idx:{})", name.name, global_index),
|
|
BoundKind::Lambda { upvalues, .. } => format!("LAMBDA(Captures:{})", upvalues.len()),
|
|
BoundKind::Call { .. } => "CALL".to_string(),
|
|
BoundKind::TailCall { .. } => "T-CALL".to_string(),
|
|
BoundKind::Block { .. } => "BLOCK".to_string(),
|
|
BoundKind::Tuple { elements } => format!("TUPLE({})", elements.len()),
|
|
BoundKind::Map { entries } => format!("MAP({})", entries.len()),
|
|
BoundKind::Expansion { .. } => "EXPANSION".to_string(),
|
|
BoundKind::Extension(ext) => ext.display_name(),
|
|
}
|
|
}
|
|
}
|