use std::collections::HashMap; use crate::ast::compiler::bound_nodes::{BoundKind, Address, BoundNode}; /// A pass that collects all global function definitions (lambdas) into a registry. /// This allows the Specializer to retrieve the original AST of a function for monomorphization. pub struct LambdaCollector<'a> { registry: &'a mut HashMap, } impl<'a> LambdaCollector<'a> { /// Performs a full traversal of the AST and populates the provided registry. pub fn collect(node: &BoundNode, registry: &'a mut HashMap) { let mut collector = Self { registry }; collector.visit(node); } fn visit(&mut self, node: &BoundNode) { match &node.kind { BoundKind::Block { exprs } => { for expr in exprs { self.visit(expr); } } BoundKind::DefGlobal { global_index, value, .. } => { // If we define a global that is a lambda, register its BODY as the template. // This allows the VM to skip the Lambda/Parameter nodes during execution. if let BoundKind::Lambda { body, .. } = &value.kind { self.registry.insert(*global_index, (**body).clone()); } self.visit(value); } BoundKind::Set { addr, value } => { // Also track assignments to globals if they hold lambdas. if let Address::Global(global_index) = addr && let BoundKind::Lambda { body, .. } = &value.kind { self.registry.insert(*global_index, (**body).clone()); } self.visit(value); } BoundKind::If { cond, then_br, else_br } => { self.visit(cond); self.visit(then_br); if let Some(e) = else_br { self.visit(e); } } BoundKind::Lambda { params, body, .. } => { self.visit(params); self.visit(body); } BoundKind::DefLocal { value, .. } => { self.visit(value); } BoundKind::Call { callee, args } | BoundKind::TailCall { callee, args } => { self.visit(callee); self.visit(args); } BoundKind::Tuple { elements } => { for el in elements { self.visit(el); } } BoundKind::Map { entries } => { for (k, v) in entries { self.visit(k); self.visit(v); } } BoundKind::Expansion { bound_expanded, .. } => { self.visit(bound_expanded); } _ => {} // Leaf nodes } } }