use std::sync::Arc; use std::collections::HashMap; use std::fmt; use std::sync::Mutex; use lazy_static::lazy_static; use std::any::Any; /// Simple source location #[derive(Debug, Clone, Copy)] pub struct SourceLocation { pub line: u32, pub col: u32, } /// Shared identity for nodes (Location, etc.) #[derive(Debug, Clone)] pub struct NodeIdentity { pub location: SourceLocation, } pub type Identity = Arc; /// Interned string identifier #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 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 + Send + Sync { 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(Arc), Keyword(Keyword), List(Arc>), Record(Arc>), Function(Arc) -> Value + Send + Sync>), Object(Arc), // For compiled Closures and other opaque types } impl Value { pub fn is_truthy(&self) -> bool { match self { Value::Void => false, Value::Bool(b) => *b, _ => true, } } } 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, "", l.len()), Value::Record(r) => write!(f, "", r.len()), Value::Function(_) => write!(f, ""), Value::Object(o) => write!(f, "<{}>", o.type_name()), } } } impl fmt::Debug for Value { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } }