use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase}; use crate::ast::ASTNode; use std::collections::HashMap; use std::sync::Weak; use std::any::Any; #[derive(Debug)] pub struct ClosureEnv { pub me_value: Option>, // Weak me (upgrade at call) pub captures: HashMap>, // P1: by-value captures } impl ClosureEnv { pub fn new() -> Self { Self { me_value: None, captures: HashMap::new() } } } #[derive(Debug)] pub struct FunctionBox { pub params: Vec, pub body: Vec, pub env: ClosureEnv, base: BoxBase, } impl FunctionBox { pub fn new(params: Vec, body: Vec) -> Self { Self { params, body, env: ClosureEnv::new(), base: BoxBase::new() } } pub fn with_env(params: Vec, body: Vec, env: ClosureEnv) -> Self { Self { params, body, env, base: BoxBase::new() } } } impl BoxCore for FunctionBox { fn box_id(&self) -> u64 { self.base.id } fn parent_type_id(&self) -> Option { self.base.parent_type_id } fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "FunctionBox(params={}, body={})", self.params.len(), self.body.len()) } fn as_any(&self) -> &dyn Any { self } fn as_any_mut(&mut self) -> &mut dyn Any { self } } impl NyashBox for FunctionBox { fn clone_box(&self) -> Box { Box::new(self.clone()) } fn share_box(&self) -> Box { self.clone_box() } fn to_string_box(&self) -> StringBox { StringBox::new(format!("FunctionBox(params={}, captures={}, body={})", self.params.len(), self.env.captures.len(), self.body.len())) } fn type_name(&self) -> &'static str { "FunctionBox" } fn equals(&self, other: &dyn NyashBox) -> BoolBox { if let Some(o) = other.as_any().downcast_ref::() { BoolBox::new(self.box_id() == o.box_id()) } else { BoolBox::new(false) } } } impl Clone for ClosureEnv { fn clone(&self) -> Self { let me_value = self.me_value.as_ref().map(|w| Weak::clone(w)); let mut captures: HashMap> = HashMap::new(); for (k, v) in &self.captures { captures.insert(k.clone(), v.clone_box()); } Self { me_value, captures } } } impl Clone for FunctionBox { fn clone(&self) -> Self { Self { params: self.params.clone(), body: self.body.clone(), env: self.env.clone(), base: BoxBase::new() } } }