Files
RustAst/src/ast/compiler/bound_nodes.rs
T
Michael Schimmel e7628e5cdf Add symbol name to bound kinds
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.
2026-02-19 16:25:17 +01:00

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(),
}
}
}