use std::collections::{HashMap, BTreeMap}; use std::rc::Rc; use std::cell::RefCell; use std::fmt; use lazy_static::lazy_static; use std::sync::Mutex; // Still needed for global keyword registry use std::any::Any; /// Simple source location #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct SourceLocation { pub line: u32, pub col: u32, } /// Shared identity for nodes (Location, etc.) #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct NodeIdentity { pub location: SourceLocation, } pub type Identity = Rc; /// Interned string identifier #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Keyword(pub u32); lazy_static! { static ref KEYWORD_REGISTRY: Mutex> = Mutex::new(HashMap::new()); static ref KEYWORD_REVERSE: Mutex> = Mutex::new(Vec::new()); } impl Keyword { pub fn intern(name: &str) -> Self { let mut reg = KEYWORD_REGISTRY.lock().unwrap(); if let Some(&id) = reg.get(name) { Keyword(id) } else { let mut rev = KEYWORD_REVERSE.lock().unwrap(); let id = rev.len() as u32; reg.insert(name.to_string(), id); rev.push(name.to_string()); Keyword(id) } } pub fn name(&self) -> String { let rev = KEYWORD_REVERSE.lock().unwrap(); rev[self.0 as usize].clone() } } /// Interface for custom objects (Closures, Series, Streams) pub trait Object: fmt::Debug { fn type_name(&self) -> &'static str; fn as_any(&self) -> &dyn Any; } /// Core data value in Myc Script (similar to TDataValue) #[derive(Clone)] pub enum Value { Void, Bool(bool), Int(i64), Float(f64), Text(Rc), Keyword(Keyword), List(Rc>), Record(Rc>), Function(Rc) -> Value>), Object(Rc), // For compiled Closures and other opaque types Cell(Rc>), // Boxed value for captures TailCallRequest(Box<(Rc, Vec)>), // Internal: For TCO (Boxed to keep Value small) } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum StaticType { Any, Void, Bool, Int, Float, Text, Keyword, List(Box), Record(Rc>), Function { params: Vec, ret: Box, }, Object(&'static str), } impl fmt::Display for StaticType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { StaticType::Any => write!(f, "any"), StaticType::Void => write!(f, "void"), StaticType::Bool => write!(f, "bool"), StaticType::Int => write!(f, "int"), StaticType::Float => write!(f, "float"), StaticType::Text => write!(f, "text"), StaticType::Keyword => write!(f, "keyword"), StaticType::List(inner) => write!(f, "[{}]", inner), StaticType::Record(fields) => { write!(f, "{{")?; for (i, (k, v)) in fields.iter().enumerate() { if i > 0 { write!(f, ", ")?; } write!(f, ":{} {}", k.name(), v)?; } write!(f, "}}") }, StaticType::Function { params, ret } => { write!(f, "fn(")?; for (i, p) in params.iter().enumerate() { if i > 0 { write!(f, " ")?; } write!(f, "{}", p)?; } write!(f, ") -> {}", ret) }, StaticType::Object(name) => write!(f, "{}", name), } } } impl Value { pub fn is_truthy(&self) -> bool { match self { Value::Void => false, Value::Bool(b) => *b, Value::Cell(c) => c.borrow().is_truthy(), _ => true, } } pub fn static_type(&self) -> StaticType { match self { Value::Void => StaticType::Void, Value::Bool(_) => StaticType::Bool, Value::Int(_) => StaticType::Int, Value::Float(_) => StaticType::Float, Value::Text(_) => StaticType::Text, Value::Keyword(_) => StaticType::Keyword, Value::List(_) => StaticType::List(Box::new(StaticType::Any)), Value::Record(_) => StaticType::Record(Rc::new(BTreeMap::new())), // Empty for now Value::Function { .. } => StaticType::Any, // Dynamic function Value::Object(o) => StaticType::Object(o.type_name()), Value::Cell(c) => c.borrow().static_type(), Value::TailCallRequest(_) => panic!("Internal VM state leaked: TailCallRequest"), } } } impl fmt::Display for Value { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Value::Void => write!(f, "void"), Value::Bool(b) => write!(f, "{}", b), Value::Int(i) => write!(f, "{}", i), Value::Float(fl) => write!(f, "{}", fl), Value::Text(t) => write!(f, "\"{}\"", t), Value::Keyword(k) => write!(f, ":{}", k.name()), Value::List(l) => { write!(f, "[")?; for (i, val) in l.iter().enumerate() { if i > 0 { write!(f, " ")?; } write!(f, "{}", val)?; } write!(f, "]") }, Value::Record(r) => { let mut entries: Vec<_> = r.iter().collect(); entries.sort_by_key(|(k, _)| k.name()); write!(f, "{{")?; for (i, (k, v)) in entries.iter().enumerate() { if i > 0 { write!(f, ", ")?; } write!(f, ":{} {}", k.name(), v)?; } write!(f, "}}") }, Value::Function(_) => write!(f, ""), Value::Object(o) => write!(f, "<{}>", o.type_name()), Value::Cell(c) => write!(f, "{}", c.borrow()), Value::TailCallRequest(_) => panic!("Internal VM state leaked: TailCallRequest"), } } } impl fmt::Debug for Value { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } }