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: std::fmt::Debug { fn clone_box(&self) -> Box>; fn display_name(&self) -> String; } impl Clone for Box> { fn clone(&self) -> Self { self.clone_box() } } #[derive(Debug, Clone)] pub enum BoundKind { Nop, Constant(Value), // Variable Access (Resolved) Get { addr: Address, name: Symbol, }, // Variable Update (Assignment) Set { addr: Address, value: Box, T>>, }, // Variable Declaration (Local) DefLocal { name: Symbol, slot: u32, value: Box, T>>, captured_by: Vec, }, If { cond: Box, T>>, then_br: Box, T>>, else_br: Option, T>>>, }, // Global Definition (Locals are implicit by stack position) DefGlobal { name: Symbol, global_index: u32, value: Box, T>>, }, Lambda { param_count: u32, // The list of variables captured from enclosing scopes upvalues: Vec
, body: Rc, T>>, }, Call { callee: Box, T>>, args: Vec, T>>, }, TailCall { callee: Box, T>>, args: Vec, T>>, }, Block { exprs: Vec, T>>, }, Tuple { elements: Vec, T>>, }, Map { entries: Vec>, }, /// An expanded macro call, preserving the original call for debugging and UI. Expansion { /// The original call from the untyped AST. original_call: Rc>, /// The result of binding the expanded AST. bound_expanded: Box, T>>, }, /// DSL-specific extension slot Extension(Box>), } /// A single entry in a Map literal (Key-Value pair) pub type MapEntry = (Node, T>, Node, T>); /// Type alias for a node that has been bound (addresses resolved) but not yet type-checked. pub type BoundNode = Node, ()>; /// Type alias for a node that has been fully type-checked and is ready for execution. pub type TypedNode = Node, StaticType>; impl BoundKind { 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(), } } }