sigil_parser/
interpreter.rs

1//! Tree-walking interpreter for Sigil.
2//!
3//! Executes Sigil AST directly for rapid prototyping and REPL.
4
5use crate::ast::*;
6use crate::span::Span;
7use std::cell::RefCell;
8use std::collections::{HashMap, HashSet};
9use std::fmt;
10use std::path::PathBuf;
11use std::rc::Rc;
12use std::sync::{mpsc, Arc, Mutex};
13use std::thread::JoinHandle;
14
15/// Runtime value in Sigil.
16#[derive(Clone)]
17pub enum Value {
18    /// Null/void
19    Null,
20    /// Boolean
21    Bool(bool),
22    /// Integer (64-bit)
23    Int(i64),
24    /// Float (64-bit)
25    Float(f64),
26    /// String
27    String(Rc<String>),
28    /// Character
29    Char(char),
30    /// Array/list
31    Array(Rc<RefCell<Vec<Value>>>),
32    /// Tuple
33    Tuple(Rc<Vec<Value>>),
34    /// Struct instance
35    Struct {
36        name: String,
37        fields: Rc<RefCell<HashMap<String, Value>>>,
38    },
39    /// Enum variant
40    Variant {
41        enum_name: String,
42        variant_name: String,
43        fields: Option<Rc<Vec<Value>>>,
44    },
45    /// Function/closure
46    Function(Rc<Function>),
47    /// Built-in function
48    BuiltIn(Rc<BuiltInFn>),
49    /// Reference to another value
50    Ref(Rc<RefCell<Value>>),
51    /// Special mathematical values
52    Infinity,
53    Empty,
54    /// Evidence-wrapped value
55    Evidential {
56        value: Box<Value>,
57        evidence: Evidence,
58    },
59    /// Affect-wrapped value (sentiment, emotion, sarcasm, etc.)
60    Affective {
61        value: Box<Value>,
62        affect: RuntimeAffect,
63    },
64    /// HashMap
65    Map(Rc<RefCell<HashMap<String, Value>>>),
66    /// HashSet (stores keys only, values are unit)
67    Set(Rc<RefCell<std::collections::HashSet<String>>>),
68    /// Channel for message passing (sender, receiver)
69    Channel(Arc<ChannelInner>),
70    /// Thread handle
71    ThreadHandle(Arc<Mutex<Option<JoinHandle<Value>>>>),
72    /// Actor (mailbox + state)
73    Actor(Arc<ActorInner>),
74    /// Future - represents an async computation
75    Future(Rc<RefCell<FutureInner>>),
76    /// Variant constructor (for creating enum variants)
77    VariantConstructor {
78        enum_name: String,
79        variant_name: String,
80    },
81    /// Default constructor (for default trait)
82    DefaultConstructor {
83        type_name: String,
84    },
85    /// Range value (start..end or start..=end)
86    Range {
87        start: Option<i64>,
88        end: Option<i64>,
89        inclusive: bool,
90    },
91    /// RefCell - interior mutability with runtime borrow checking
92    RefCellValue(Rc<RefCellInner>),
93    /// Trait object - dynamic dispatch via vtable
94    TraitObject {
95        /// The actual value being wrapped
96        value: Box<Value>,
97        /// The type name of the concrete value
98        concrete_type: String,
99        /// The trait name this object implements
100        trait_name: String,
101    },
102}
103
104/// Inner state for RefCell runtime borrow checking
105pub struct RefCellInner {
106    /// The contained value
107    pub value: RefCell<Value>,
108    /// Current borrow state
109    pub borrow_state: RefCell<BorrowState>,
110}
111
112impl Clone for RefCellInner {
113    fn clone(&self) -> Self {
114        RefCellInner {
115            value: RefCell::new(self.value.borrow().clone()),
116            borrow_state: RefCell::new(BorrowState::Unborrowed),
117        }
118    }
119}
120
121/// Borrow state for RefCell runtime checking
122#[derive(Clone, Debug)]
123pub enum BorrowState {
124    /// No active borrows
125    Unborrowed,
126    /// Count of active immutable borrows
127    Borrowed(usize),
128    /// Exclusive mutable borrow active
129    BorrowedMut,
130}
131
132/// Future state for async computations
133#[derive(Clone)]
134pub enum FutureState {
135    /// Not yet started
136    Pending,
137    /// Currently executing
138    Running,
139    /// Completed with value
140    Ready(Box<Value>),
141    /// Failed with error
142    Failed(String),
143}
144
145/// Inner future representation
146pub struct FutureInner {
147    /// Current state
148    pub state: FutureState,
149    /// The computation to run (if pending)
150    pub computation: Option<FutureComputation>,
151    /// Completion time for timer futures
152    pub complete_at: Option<std::time::Instant>,
153}
154
155impl Clone for FutureInner {
156    fn clone(&self) -> Self {
157        FutureInner {
158            state: self.state.clone(),
159            computation: self.computation.clone(),
160            complete_at: self.complete_at,
161        }
162    }
163}
164
165/// Types of future computations
166#[derive(Clone)]
167pub enum FutureComputation {
168    /// Immediate value (already resolved)
169    Immediate(Box<Value>),
170    /// Timer - completes after duration
171    Timer(std::time::Duration),
172    /// Lazy computation - function + captured args
173    Lazy {
174        func: Rc<Function>,
175        args: Vec<Value>,
176    },
177    /// Join multiple futures
178    Join(Vec<Rc<RefCell<FutureInner>>>),
179    /// Race multiple futures (first to complete wins)
180    Race(Vec<Rc<RefCell<FutureInner>>>),
181}
182
183/// Inner channel state - wraps mpsc channel
184pub struct ChannelInner {
185    pub sender: Mutex<mpsc::Sender<Value>>,
186    pub receiver: Mutex<mpsc::Receiver<Value>>,
187}
188
189impl Clone for ChannelInner {
190    fn clone(&self) -> Self {
191        // Channels can't really be cloned - create a dummy
192        // This is for the Clone requirement on Value
193        panic!("Channels cannot be cloned directly - use channel_clone()")
194    }
195}
196
197/// Inner actor state - single-threaded for interpreter (Value contains Rc)
198/// For true async actors, use the JIT backend
199pub struct ActorInner {
200    pub name: String,
201    pub message_queue: Mutex<Vec<(String, String)>>, // (msg_type, serialized_data)
202    pub message_count: std::sync::atomic::AtomicUsize,
203}
204
205/// Evidence level at runtime
206#[derive(Debug, Clone, Copy, PartialEq, Eq)]
207pub enum Evidence {
208    Known,     // !
209    Uncertain, // ?
210    Reported,  // ~
211    Paradox,   // ‽
212}
213
214/// Runtime affect markers for sentiment and emotion tracking
215#[derive(Debug, Clone, PartialEq)]
216pub struct RuntimeAffect {
217    pub sentiment: Option<RuntimeSentiment>,
218    pub sarcasm: bool, // ⸮
219    pub intensity: Option<RuntimeIntensity>,
220    pub formality: Option<RuntimeFormality>,
221    pub emotion: Option<RuntimeEmotion>,
222    pub confidence: Option<RuntimeConfidence>,
223}
224
225#[derive(Debug, Clone, Copy, PartialEq, Eq)]
226pub enum RuntimeSentiment {
227    Positive, // ⊕
228    Negative, // ⊖
229    Neutral,  // ⊜
230}
231
232#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub enum RuntimeIntensity {
234    Up,   // ↑
235    Down, // ↓
236    Max,  // ⇈
237}
238
239#[derive(Debug, Clone, Copy, PartialEq, Eq)]
240pub enum RuntimeFormality {
241    Formal,   // ♔
242    Informal, // ♟
243}
244
245#[derive(Debug, Clone, Copy, PartialEq, Eq)]
246pub enum RuntimeEmotion {
247    Joy,      // ☺
248    Sadness,  // ☹
249    Anger,    // ⚡
250    Fear,     // ❄
251    Surprise, // ✦
252    Love,     // ♡
253}
254
255#[derive(Debug, Clone, Copy, PartialEq, Eq)]
256pub enum RuntimeConfidence {
257    High,   // ◉
258    Medium, // ◎
259    Low,    // ○
260}
261
262/// A Sigil function
263pub struct Function {
264    pub name: Option<String>,
265    pub params: Vec<String>,
266    pub body: Expr,
267    pub closure: Rc<RefCell<Environment>>,
268}
269
270/// Built-in function type
271pub struct BuiltInFn {
272    pub name: String,
273    pub arity: Option<usize>, // None = variadic
274    pub func: fn(&mut Interpreter, Vec<Value>) -> Result<Value, RuntimeError>,
275}
276
277impl fmt::Debug for Value {
278    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279        match self {
280            Value::Null => write!(f, "null"),
281            Value::Bool(b) => write!(f, "{}", b),
282            Value::Int(n) => write!(f, "{}", n),
283            Value::Float(n) => write!(f, "{}", n),
284            Value::String(s) => write!(f, "\"{}\"", s),
285            Value::Char(c) => write!(f, "'{}'", c),
286            Value::Array(arr) => {
287                let arr = arr.borrow();
288                write!(f, "[")?;
289                for (i, v) in arr.iter().enumerate() {
290                    if i > 0 {
291                        write!(f, ", ")?;
292                    }
293                    write!(f, "{:?}", v)?;
294                }
295                write!(f, "]")
296            }
297            Value::Tuple(vals) => {
298                write!(f, "(")?;
299                for (i, v) in vals.iter().enumerate() {
300                    if i > 0 {
301                        write!(f, ", ")?;
302                    }
303                    write!(f, "{:?}", v)?;
304                }
305                write!(f, ")")
306            }
307            Value::Struct { name, fields } => {
308                write!(f, "{} {{ ", name)?;
309                let fields = fields.borrow();
310                for (i, (k, v)) in fields.iter().enumerate() {
311                    if i > 0 {
312                        write!(f, ", ")?;
313                    }
314                    write!(f, "{}: {:?}", k, v)?;
315                }
316                write!(f, " }}")
317            }
318            Value::Variant {
319                enum_name,
320                variant_name,
321                fields,
322            } => {
323                write!(f, "{}::{}", enum_name, variant_name)?;
324                if let Some(fields) = fields {
325                    write!(f, "(")?;
326                    for (i, v) in fields.iter().enumerate() {
327                        if i > 0 {
328                            write!(f, ", ")?;
329                        }
330                        write!(f, "{:?}", v)?;
331                    }
332                    write!(f, ")")?;
333                }
334                Ok(())
335            }
336            Value::Function(func) => {
337                write!(f, "<fn {}>", func.name.as_deref().unwrap_or("anonymous"))
338            }
339            Value::BuiltIn(b) => write!(f, "<builtin {}>", b.name),
340            Value::Ref(r) => write!(f, "&{:?}", r.borrow()),
341            Value::Infinity => write!(f, "∞"),
342            Value::Empty => write!(f, "∅"),
343            Value::Evidential { value, evidence } => {
344                write!(f, "{:?}", value)?;
345                match evidence {
346                    Evidence::Known => write!(f, "!"),
347                    Evidence::Uncertain => write!(f, "?"),
348                    Evidence::Reported => write!(f, "~"),
349                    Evidence::Paradox => write!(f, "‽"),
350                }
351            }
352            Value::Map(map) => {
353                let map = map.borrow();
354                write!(f, "{{")?;
355                for (i, (k, v)) in map.iter().enumerate() {
356                    if i > 0 {
357                        write!(f, ", ")?;
358                    }
359                    write!(f, "{:?}: {:?}", k, v)?;
360                }
361                write!(f, "}}")
362            }
363            Value::Set(set) => {
364                let set = set.borrow();
365                write!(f, "Set{{")?;
366                for (i, k) in set.iter().enumerate() {
367                    if i > 0 {
368                        write!(f, ", ")?;
369                    }
370                    write!(f, "{:?}", k)?;
371                }
372                write!(f, "}}")
373            }
374            Value::Channel(_) => write!(f, "<channel>"),
375            Value::ThreadHandle(_) => write!(f, "<thread>"),
376            Value::Actor(actor) => write!(f, "<actor {}>", actor.name),
377            Value::Future(fut) => {
378                let fut = fut.borrow();
379                match &fut.state {
380                    FutureState::Pending => write!(f, "<future pending>"),
381                    FutureState::Running => write!(f, "<future running>"),
382                    FutureState::Ready(v) => write!(f, "<future ready: {:?}>", v),
383                    FutureState::Failed(e) => write!(f, "<future failed: {}>", e),
384                }
385            }
386            Value::Affective { value, affect } => {
387                write!(f, "{:?}", value)?;
388                if let Some(s) = &affect.sentiment {
389                    match s {
390                        RuntimeSentiment::Positive => write!(f, "⊕")?,
391                        RuntimeSentiment::Negative => write!(f, "⊖")?,
392                        RuntimeSentiment::Neutral => write!(f, "⊜")?,
393                    }
394                }
395                if affect.sarcasm {
396                    write!(f, "⸮")?;
397                }
398                if let Some(i) = &affect.intensity {
399                    match i {
400                        RuntimeIntensity::Up => write!(f, "↑")?,
401                        RuntimeIntensity::Down => write!(f, "↓")?,
402                        RuntimeIntensity::Max => write!(f, "⇈")?,
403                    }
404                }
405                if let Some(fo) = &affect.formality {
406                    match fo {
407                        RuntimeFormality::Formal => write!(f, "♔")?,
408                        RuntimeFormality::Informal => write!(f, "♟")?,
409                    }
410                }
411                if let Some(e) = &affect.emotion {
412                    match e {
413                        RuntimeEmotion::Joy => write!(f, "☺")?,
414                        RuntimeEmotion::Sadness => write!(f, "☹")?,
415                        RuntimeEmotion::Anger => write!(f, "⚡")?,
416                        RuntimeEmotion::Fear => write!(f, "❄")?,
417                        RuntimeEmotion::Surprise => write!(f, "✦")?,
418                        RuntimeEmotion::Love => write!(f, "♡")?,
419                    }
420                }
421                if let Some(c) = &affect.confidence {
422                    match c {
423                        RuntimeConfidence::High => write!(f, "◉")?,
424                        RuntimeConfidence::Medium => write!(f, "◎")?,
425                        RuntimeConfidence::Low => write!(f, "○")?,
426                    }
427                }
428                Ok(())
429            }
430            Value::VariantConstructor { enum_name, variant_name } => {
431                write!(f, "<constructor {}::{}>", enum_name, variant_name)
432            }
433            Value::DefaultConstructor { type_name } => {
434                write!(f, "<default {}>", type_name)
435            }
436            Value::Range { start, end, inclusive } => {
437                match (start, end) {
438                    (Some(s), Some(e)) => if *inclusive {
439                        write!(f, "{}..={}", s, e)
440                    } else {
441                        write!(f, "{}..{}", s, e)
442                    },
443                    (Some(s), None) => write!(f, "{}..", s),
444                    (None, Some(e)) => if *inclusive {
445                        write!(f, "..={}", e)
446                    } else {
447                        write!(f, "..{}", e)
448                    },
449                    (None, None) => write!(f, ".."),
450                }
451            }
452            Value::RefCellValue(rc) => {
453                write!(f, "RefCell({:?})", rc.value.borrow())
454            }
455            Value::TraitObject { value, concrete_type, trait_name } => {
456                write!(f, "dyn {}({}: {:?})", trait_name, concrete_type, value)
457            }
458        }
459    }
460}
461
462impl fmt::Display for Value {
463    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
464        match self {
465            Value::Null => write!(f, "null"),
466            Value::Bool(b) => write!(f, "{}", b),
467            Value::Int(n) => write!(f, "{}", n),
468            Value::Float(n) => write!(f, "{}", n),
469            Value::String(s) => write!(f, "{}", s),
470            Value::Char(c) => write!(f, "{}", c),
471            Value::Array(arr) => {
472                let arr = arr.borrow();
473                write!(f, "[")?;
474                for (i, v) in arr.iter().enumerate() {
475                    if i > 0 {
476                        write!(f, ", ")?;
477                    }
478                    write!(f, "{}", v)?;
479                }
480                write!(f, "]")
481            }
482            Value::Evidential { value, .. } => write!(f, "{}", value),
483            Value::Affective { value, affect } => {
484                // Display affect markers as suffix symbols
485                let mut suffix = String::new();
486                if let Some(sent) = &affect.sentiment {
487                    suffix.push(match sent {
488                        RuntimeSentiment::Positive => '⊕',
489                        RuntimeSentiment::Negative => '⊖',
490                        RuntimeSentiment::Neutral => '⊜',
491                    });
492                }
493                if affect.sarcasm {
494                    suffix.push('⸮');
495                }
496                if let Some(int) = &affect.intensity {
497                    suffix.push(match int {
498                        RuntimeIntensity::Up => '↑',
499                        RuntimeIntensity::Down => '↓',
500                        RuntimeIntensity::Max => '⇈',
501                    });
502                }
503                if let Some(form) = &affect.formality {
504                    suffix.push(match form {
505                        RuntimeFormality::Formal => '♔',
506                        RuntimeFormality::Informal => '♟',
507                    });
508                }
509                if let Some(emo) = &affect.emotion {
510                    suffix.push(match emo {
511                        RuntimeEmotion::Joy => '☺',
512                        RuntimeEmotion::Sadness => '☹',
513                        RuntimeEmotion::Anger => '⚡',
514                        RuntimeEmotion::Fear => '❄',
515                        RuntimeEmotion::Surprise => '✦',
516                        RuntimeEmotion::Love => '♡',
517                    });
518                }
519                if let Some(conf) = &affect.confidence {
520                    suffix.push(match conf {
521                        RuntimeConfidence::High => '◉',
522                        RuntimeConfidence::Medium => '◎',
523                        RuntimeConfidence::Low => '○',
524                    });
525                }
526                write!(f, "{}{}", value, suffix)
527            }
528            Value::RefCellValue(rc) => {
529                write!(f, "RefCell({})", rc.value.borrow())
530            }
531            Value::TraitObject { value, trait_name, .. } => {
532                write!(f, "dyn {}({})", trait_name, value)
533            }
534            _ => write!(f, "{:?}", self),
535        }
536    }
537}
538
539/// Runtime error
540#[derive(Debug)]
541pub struct RuntimeError {
542    pub message: String,
543    pub span: Option<Span>,
544}
545
546impl RuntimeError {
547    pub fn new(message: impl Into<String>) -> Self {
548        Self {
549            message: message.into(),
550            span: None,
551        }
552    }
553
554    pub fn with_span(message: impl Into<String>, span: Span) -> Self {
555        Self {
556            message: message.into(),
557            span: Some(span),
558        }
559    }
560}
561
562impl fmt::Display for RuntimeError {
563    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
564        write!(f, "Runtime error: {}", self.message)?;
565        if let Some(span) = self.span {
566            write!(f, " at {}", span)?;
567        }
568        Ok(())
569    }
570}
571
572/// Control flow signals for return/break/continue
573#[derive(Debug, Clone)]
574pub enum ControlFlow {
575    Return(Value),
576    Break(Option<Value>),
577    Continue,
578}
579
580impl From<ControlFlow> for RuntimeError {
581    fn from(cf: ControlFlow) -> Self {
582        match cf {
583            ControlFlow::Return(_) => RuntimeError::new("return outside function"),
584            ControlFlow::Break(_) => RuntimeError::new("break outside loop"),
585            ControlFlow::Continue => RuntimeError::new("continue outside loop"),
586        }
587    }
588}
589
590/// Result type that can contain control flow
591pub type EvalResult = Result<Value, EvalError>;
592
593/// Error type that includes control flow
594#[derive(Debug)]
595pub enum EvalError {
596    Runtime(RuntimeError),
597    Control(ControlFlow),
598}
599
600impl From<RuntimeError> for EvalError {
601    fn from(e: RuntimeError) -> Self {
602        EvalError::Runtime(e)
603    }
604}
605
606impl From<ControlFlow> for EvalError {
607    fn from(cf: ControlFlow) -> Self {
608        EvalError::Control(cf)
609    }
610}
611
612impl fmt::Display for EvalError {
613    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
614        match self {
615            EvalError::Runtime(e) => write!(f, "{}", e),
616            EvalError::Control(cf) => write!(f, "Unexpected control flow: {:?}", cf),
617        }
618    }
619}
620
621/// Environment for variable bindings
622#[derive(Clone)]
623pub struct Environment {
624    values: HashMap<String, Value>,
625    parent: Option<Rc<RefCell<Environment>>>,
626}
627
628impl Environment {
629    pub fn new() -> Self {
630        Self {
631            values: HashMap::new(),
632            parent: None,
633        }
634    }
635
636    pub fn with_parent(parent: Rc<RefCell<Environment>>) -> Self {
637        Self {
638            values: HashMap::new(),
639            parent: Some(parent),
640        }
641    }
642
643    pub fn define(&mut self, name: String, value: Value) {
644        self.values.insert(name, value);
645    }
646
647    pub fn get(&self, name: &str) -> Option<Value> {
648        if let Some(value) = self.values.get(name) {
649            Some(value.clone())
650        } else if let Some(ref parent) = self.parent {
651            parent.borrow().get(name)
652        } else {
653            None
654        }
655    }
656
657    pub fn set(&mut self, name: &str, value: Value) -> Result<(), RuntimeError> {
658        if self.values.contains_key(name) {
659            self.values.insert(name.to_string(), value);
660            Ok(())
661        } else if let Some(ref parent) = self.parent {
662            parent.borrow_mut().set(name, value)
663        } else {
664            Err(RuntimeError::new(format!("Undefined variable: {}", name)))
665        }
666    }
667}
668
669impl Default for Environment {
670    fn default() -> Self {
671        Self::new()
672    }
673}
674
675/// The Sigil interpreter
676pub struct Interpreter {
677    /// Global environment
678    pub globals: Rc<RefCell<Environment>>,
679    /// Current environment
680    pub environment: Rc<RefCell<Environment>>,
681    /// Type definitions
682    pub types: HashMap<String, TypeDef>,
683    /// Variant constructors: qualified_name -> (enum_name, variant_name, arity)
684    pub variant_constructors: HashMap<String, (String, String, usize)>,
685    /// Structs with #[derive(Default)]
686    pub default_structs: HashMap<String, StructDef>,
687    /// Output buffer (for testing)
688    pub output: Vec<String>,
689    /// Return value from the last return statement (control flow)
690    return_value: Option<Value>,
691    /// Program arguments (overrides env::args when set)
692    pub program_args: Option<Vec<String>>,
693    /// Current module prefix for registering definitions
694    pub current_module: Option<String>,
695    /// Current Self type (when inside an impl block)
696    pub current_self_type: Option<String>,
697    /// Current source directory for resolving relative module paths
698    pub current_source_dir: Option<String>,
699    /// Loaded crates registry (crate_name -> true if loaded)
700    pub loaded_crates: HashSet<String>,
701    /// Crates currently being loaded (for circular dependency detection)
702    pub loading_crates: HashSet<String>,
703    /// Project root directory (where Sigil.toml is located)
704    pub project_root: Option<PathBuf>,
705    /// Workspace members: crate_name -> relative path from project root
706    pub workspace_members: HashMap<String, PathBuf>,
707    /// Types that implement Drop trait - call drop() when they go out of scope
708    pub drop_types: HashSet<String>,
709    /// Trait definitions: trait_name -> list of method signatures
710    pub trait_defs: HashMap<String, TraitInfo>,
711    /// Trait implementations: (type_name, trait_name) -> true
712    pub trait_impls: HashMap<(String, String), bool>,
713}
714
715/// Information about a trait definition
716#[derive(Clone, Debug)]
717pub struct TraitInfo {
718    /// Trait name
719    pub name: String,
720    /// Method names required by this trait
721    pub methods: Vec<String>,
722    /// Supertraits (traits this trait extends)
723    pub supertraits: Vec<String>,
724}
725
726/// Type definition for structs/enums
727#[derive(Clone)]
728pub enum TypeDef {
729    Struct(StructDef),
730    Enum(EnumDef),
731}
732
733impl Interpreter {
734    pub fn new() -> Self {
735        let globals = Rc::new(RefCell::new(Environment::new()));
736        let environment = globals.clone();
737
738        let mut interp = Self {
739            globals: globals.clone(),
740            environment,
741            types: HashMap::new(),
742            variant_constructors: HashMap::new(),
743            default_structs: HashMap::new(),
744            return_value: None,
745            output: Vec::new(),
746            program_args: None,
747            current_module: None,
748            current_self_type: None,
749            current_source_dir: None,
750            loaded_crates: HashSet::new(),
751            loading_crates: HashSet::new(),
752            project_root: None,
753            workspace_members: HashMap::new(),
754            drop_types: HashSet::new(),
755            trait_defs: HashMap::new(),
756            trait_impls: HashMap::new(),
757        };
758
759        // Register built-in functions
760        interp.register_builtins();
761
762        interp
763    }
764
765    /// Set program arguments (overrides env::args for the running program)
766    pub fn set_program_args(&mut self, args: Vec<String>) {
767        self.program_args = Some(args);
768    }
769
770    /// Set current module for registering definitions (module name, not file stem)
771    pub fn set_current_module(&mut self, module: Option<String>) {
772        self.current_module = module;
773    }
774
775    /// Set current source directory for resolving relative module paths
776    pub fn set_current_source_dir(&mut self, dir: Option<String>) {
777        self.current_source_dir = dir;
778    }
779
780    /// Get program arguments (uses overridden args if set, otherwise env::args)
781    pub fn get_program_args(&self) -> Vec<String> {
782        self.program_args.clone().unwrap_or_else(|| std::env::args().collect())
783    }
784
785    /// Find and parse Sigil.toml from a source directory, walking up parent directories
786    /// Looks for a workspace Sigil.toml (one with [workspace] section and members)
787    pub fn discover_project(&mut self, source_dir: &str) -> Result<(), RuntimeError> {
788        let mut current = PathBuf::from(source_dir);
789
790        // Walk up to find Sigil.toml with [workspace] section
791        loop {
792            let sigil_toml = current.join("Sigil.toml");
793            if sigil_toml.exists() {
794                if let Ok(result) = self.try_parse_workspace_toml(&sigil_toml) {
795                    if result {
796                        return Ok(());
797                    }
798                    // Not a workspace Sigil.toml, continue searching
799                }
800            }
801
802            // Also check for sigil.toml (lowercase)
803            let sigil_toml_lower = current.join("sigil.toml");
804            if sigil_toml_lower.exists() {
805                if let Ok(result) = self.try_parse_workspace_toml(&sigil_toml_lower) {
806                    if result {
807                        return Ok(());
808                    }
809                    // Not a workspace Sigil.toml, continue searching
810                }
811            }
812
813            if !current.pop() {
814                // No workspace Sigil.toml found
815                crate::sigil_debug!("DEBUG discover_project: no workspace Sigil.toml found from {}", source_dir);
816                return Ok(());
817            }
818        }
819    }
820
821    /// Try to parse a Sigil.toml as a workspace config. Returns Ok(true) if it's a workspace,
822    /// Ok(false) if it's a crate-level config, Err if parsing failed.
823    fn try_parse_workspace_toml(&mut self, path: &PathBuf) -> Result<bool, RuntimeError> {
824        let content = std::fs::read_to_string(path)
825            .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
826
827        let toml_value: toml::Value = content.parse()
828            .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
829
830        // Check if this has a [workspace] section with members
831        if let Some(workspace) = toml_value.get("workspace") {
832            if workspace.get("members").and_then(|m| m.as_array()).is_some() {
833                // This is a workspace Sigil.toml
834                return self.parse_sigil_toml(path).map(|_| true);
835            }
836        }
837
838        // Not a workspace config
839        crate::sigil_debug!("DEBUG try_parse_workspace_toml: {:?} is not a workspace config", path);
840        Ok(false)
841    }
842
843    /// Parse a Sigil.toml file and populate workspace_members
844    fn parse_sigil_toml(&mut self, path: &PathBuf) -> Result<(), RuntimeError> {
845        let content = std::fs::read_to_string(path)
846            .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
847
848        let toml_value: toml::Value = content.parse()
849            .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
850
851        self.project_root = path.parent().map(|p| p.to_path_buf());
852
853        // Parse [workspace] members
854        if let Some(workspace) = toml_value.get("workspace") {
855            if let Some(members) = workspace.get("members").and_then(|m| m.as_array()) {
856                for member in members {
857                    if let Some(member_path) = member.as_str() {
858                        // Extract crate name from path (e.g., "crates/samael-analysis" -> "samael_analysis")
859                        let crate_name = std::path::Path::new(member_path)
860                            .file_name()
861                            .and_then(|n| n.to_str())
862                            .map(|n| n.replace("-", "_"))
863                            .unwrap_or_default();
864
865                        if !crate_name.is_empty() {
866                            crate::sigil_debug!("DEBUG parse_sigil_toml: registered workspace member: {} -> {}",
867                                &crate_name, member_path);
868                            self.workspace_members.insert(crate_name, PathBuf::from(member_path));
869                        }
870                    }
871                }
872            }
873        }
874
875        crate::sigil_debug!("DEBUG parse_sigil_toml: loaded {} workspace members from {:?}",
876            self.workspace_members.len(), path);
877
878        Ok(())
879    }
880
881    /// Load an external crate by name
882    pub fn load_crate(&mut self, crate_name: &str) -> Result<bool, RuntimeError> {
883        // Check if already loaded
884        if self.loaded_crates.contains(crate_name) {
885            return Ok(true);
886        }
887
888        // Check for circular dependency
889        if self.loading_crates.contains(crate_name) {
890            return Err(RuntimeError::new(format!(
891                "Circular dependency detected: crate '{}' is already being loaded", crate_name
892            )));
893        }
894
895        // Find crate path in workspace members
896        let crate_path = match self.workspace_members.get(crate_name) {
897            Some(p) => p.clone(),
898            None => {
899                crate::sigil_debug!("DEBUG load_crate: crate '{}' not found in workspace members", crate_name);
900                return Ok(false);
901            }
902        };
903
904        let project_root = match &self.project_root {
905            Some(r) => r.clone(),
906            None => {
907                crate::sigil_debug!("DEBUG load_crate: no project root set");
908                return Ok(false);
909            }
910        };
911
912        // Build path to lib.sigil
913        let lib_path = project_root.join(&crate_path).join("src").join("lib.sigil");
914
915        if !lib_path.exists() {
916            crate::sigil_debug!("DEBUG load_crate: lib.sigil not found at {:?}", lib_path);
917            return Ok(false);
918        }
919
920        // Mark as loading (for circular dependency detection)
921        self.loading_crates.insert(crate_name.to_string());
922
923        crate::sigil_debug!("DEBUG load_crate: loading crate '{}' from {:?}", crate_name, lib_path);
924
925        // Read and parse the lib.sigil file
926        let source = std::fs::read_to_string(&lib_path)
927            .map_err(|e| RuntimeError::new(format!("Failed to read {:?}: {}", lib_path, e)))?;
928
929        // Save current state
930        let prev_module = self.current_module.clone();
931        let prev_source_dir = self.current_source_dir.clone();
932
933        // Set module context to crate name
934        self.current_module = Some(crate_name.to_string());
935        self.current_source_dir = lib_path.parent().map(|p| p.to_string_lossy().to_string());
936
937        // Parse the source
938        let mut parser = crate::Parser::new(&source);
939
940        match parser.parse_file() {
941            Ok(parsed_file) => {
942                // Execute all items to register types and functions
943                for item in &parsed_file.items {
944                    if let Err(e) = self.execute_item(&item.node) {
945                        crate::sigil_warn!("Warning: error loading crate '{}': {}", crate_name, e);
946                    }
947                }
948            }
949            Err(e) => {
950                crate::sigil_warn!("Warning: failed to parse crate '{}': {:?}", crate_name, e);
951            }
952        }
953
954        // Restore previous state
955        self.current_module = prev_module;
956        self.current_source_dir = prev_source_dir;
957
958        // Mark as loaded and no longer loading
959        self.loading_crates.remove(crate_name);
960        self.loaded_crates.insert(crate_name.to_string());
961
962        crate::sigil_debug!("DEBUG load_crate: successfully loaded crate '{}'", crate_name);
963
964        Ok(true)
965    }
966
967    fn register_builtins(&mut self) {
968        // PhantomData - zero-sized type marker
969        self.globals.borrow_mut().define("PhantomData".to_string(), Value::Null);
970
971        // Print function
972        self.define_builtin("print", None, |interp, args| {
973            let output: Vec<String> = args.iter().map(|v| format!("{}", v)).collect();
974            let line = output.join(" ");
975            println!("{}", line);
976            interp.output.push(line);
977            Ok(Value::Null)
978        });
979
980        // Type checking
981        self.define_builtin("type_of", Some(1), |_, args| {
982            let type_name = match &args[0] {
983                Value::Null => "null",
984                Value::Bool(_) => "bool",
985                Value::Int(_) => "i64",
986                Value::Float(_) => "f64",
987                Value::String(_) => "str",
988                Value::Char(_) => "char",
989                Value::Array(_) => "array",
990                Value::Tuple(_) => "tuple",
991                Value::Struct { name, .. } => name,
992                Value::Variant { enum_name, .. } => enum_name,
993                Value::Function(_) => "fn",
994                Value::BuiltIn(_) => "builtin",
995                Value::Ref(_) => "ref",
996                Value::Infinity => "infinity",
997                Value::Empty => "empty",
998                Value::Evidential { .. } => "evidential",
999                Value::Affective { .. } => "affective",
1000                Value::Map(_) => "map",
1001                Value::Set(_) => "set",
1002                Value::Channel(_) => "channel",
1003                Value::ThreadHandle(_) => "thread",
1004                Value::Actor(_) => "actor",
1005                Value::Future(_) => "future",
1006                Value::VariantConstructor { .. } => "variant_constructor",
1007                Value::DefaultConstructor { .. } => "default_constructor",
1008                Value::Range { .. } => "range",
1009                Value::RefCellValue(_) => "refcell",
1010                Value::TraitObject { trait_name, .. } => {
1011                    return Ok(Value::String(Rc::new(format!("dyn {}", trait_name))));
1012                }
1013            };
1014            Ok(Value::String(Rc::new(type_name.to_string())))
1015        });
1016
1017        // Array operations
1018        self.define_builtin("len", Some(1), |_, args| match &args[0] {
1019            Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
1020            Value::String(s) => Ok(Value::Int(s.len() as i64)),
1021            Value::Tuple(t) => Ok(Value::Int(t.len() as i64)),
1022            _ => Err(RuntimeError::new("len() requires array, string, or tuple")),
1023        });
1024
1025        self.define_builtin("push", Some(2), |_, args| match &args[0] {
1026            Value::Array(arr) => {
1027                arr.borrow_mut().push(args[1].clone());
1028                Ok(Value::Null)
1029            }
1030            _ => Err(RuntimeError::new("push() requires array")),
1031        });
1032
1033        self.define_builtin("pop", Some(1), |_, args| match &args[0] {
1034            Value::Array(arr) => arr
1035                .borrow_mut()
1036                .pop()
1037                .ok_or_else(|| RuntimeError::new("pop() on empty array")),
1038            _ => Err(RuntimeError::new("pop() requires array")),
1039        });
1040
1041        // Math functions
1042        self.define_builtin("abs", Some(1), |_, args| match &args[0] {
1043            Value::Int(n) => Ok(Value::Int(n.abs())),
1044            Value::Float(n) => Ok(Value::Float(n.abs())),
1045            _ => Err(RuntimeError::new("abs() requires number")),
1046        });
1047
1048        self.define_builtin("sqrt", Some(1), |_, args| match &args[0] {
1049            Value::Int(n) => Ok(Value::Float((*n as f64).sqrt())),
1050            Value::Float(n) => Ok(Value::Float(n.sqrt())),
1051            _ => Err(RuntimeError::new("sqrt() requires number")),
1052        });
1053
1054        self.define_builtin("sin", Some(1), |_, args| match &args[0] {
1055            Value::Int(n) => Ok(Value::Float((*n as f64).sin())),
1056            Value::Float(n) => Ok(Value::Float(n.sin())),
1057            _ => Err(RuntimeError::new("sin() requires number")),
1058        });
1059
1060        self.define_builtin("cos", Some(1), |_, args| match &args[0] {
1061            Value::Int(n) => Ok(Value::Float((*n as f64).cos())),
1062            Value::Float(n) => Ok(Value::Float(n.cos())),
1063            _ => Err(RuntimeError::new("cos() requires number")),
1064        });
1065
1066        // Evidence operations
1067        self.define_builtin("known", Some(1), |_, args| {
1068            Ok(Value::Evidential {
1069                value: Box::new(args[0].clone()),
1070                evidence: Evidence::Known,
1071            })
1072        });
1073
1074        self.define_builtin("uncertain", Some(1), |_, args| {
1075            Ok(Value::Evidential {
1076                value: Box::new(args[0].clone()),
1077                evidence: Evidence::Uncertain,
1078            })
1079        });
1080
1081        self.define_builtin("reported", Some(1), |_, args| {
1082            Ok(Value::Evidential {
1083                value: Box::new(args[0].clone()),
1084                evidence: Evidence::Reported,
1085            })
1086        });
1087
1088        // Box::new - just return the value (Sigil is GC'd)
1089        self.globals.borrow_mut().define(
1090            "Box·new".to_string(),
1091            Value::BuiltIn(Rc::new(BuiltInFn {
1092                name: "Box·new".to_string(),
1093                arity: Some(1),
1094                func: |_, args| Ok(args[0].clone()),
1095            })),
1096        );
1097
1098        // Map::new - create empty map
1099        self.globals.borrow_mut().define(
1100            "Map·new".to_string(),
1101            Value::BuiltIn(Rc::new(BuiltInFn {
1102                name: "Map·new".to_string(),
1103                arity: Some(0),
1104                func: |_, _| Ok(Value::Map(Rc::new(RefCell::new(HashMap::new())))),
1105            })),
1106        );
1107
1108        // Range function
1109        self.define_builtin("range", Some(2), |_, args| {
1110            let start = match &args[0] {
1111                Value::Int(n) => *n,
1112                _ => return Err(RuntimeError::new("range() requires integers")),
1113            };
1114            let end = match &args[1] {
1115                Value::Int(n) => *n,
1116                _ => return Err(RuntimeError::new("range() requires integers")),
1117            };
1118            let values: Vec<Value> = (start..end).map(Value::Int).collect();
1119            Ok(Value::Array(Rc::new(RefCell::new(values))))
1120        });
1121
1122        // ExitCode enum for process exit codes (like Rust's std::process::ExitCode)
1123        self.globals.borrow_mut().define(
1124            "ExitCode·SUCCESS".to_string(),
1125            Value::Variant {
1126                enum_name: "ExitCode".to_string(),
1127                variant_name: "SUCCESS".to_string(),
1128                fields: Some(Rc::new(vec![Value::Int(0)])),
1129            },
1130        );
1131        self.globals.borrow_mut().define(
1132            "ExitCode·FAILURE".to_string(),
1133            Value::Variant {
1134                enum_name: "ExitCode".to_string(),
1135                variant_name: "FAILURE".to_string(),
1136                fields: Some(Rc::new(vec![Value::Int(1)])),
1137            },
1138        );
1139
1140        // PathBuf::from - create a PathBuf from a string path
1141        self.define_builtin("PathBuf·from", Some(1), |_, args| {
1142            // Unwrap Ref types to get the actual value
1143            let arg = match &args[0] {
1144                Value::Ref(r) => r.borrow().clone(),
1145                other => other.clone(),
1146            };
1147            let path = match &arg {
1148                Value::String(s2) => s2.as_str().to_string(),
1149                _ => return Err(RuntimeError::new("PathBuf::from expects a string")),
1150            };
1151            // Represent PathBuf as a struct with a path field
1152            let mut fields = HashMap::new();
1153            fields.insert("path".to_string(), Value::String(Rc::new(path)));
1154            Ok(Value::Struct {
1155                name: "PathBuf".to_string(),
1156                fields: Rc::new(RefCell::new(fields)),
1157            })
1158        });
1159
1160        // Path::new - create a Path from a string (similar to PathBuf for our purposes)
1161        self.define_builtin("Path·new", Some(1), |_, args| {
1162            // Unwrap Ref types to get the actual value
1163            let arg = match &args[0] {
1164                Value::Ref(r) => r.borrow().clone(),
1165                other => other.clone(),
1166            };
1167            let path = match &arg {
1168                Value::String(s2) => s2.as_str().to_string(),
1169                _ => return Err(RuntimeError::new("Path::new expects a string")),
1170            };
1171            let mut fields = HashMap::new();
1172            fields.insert("path".to_string(), Value::String(Rc::new(path)));
1173            Ok(Value::Struct {
1174                name: "Path".to_string(),
1175                fields: Rc::new(RefCell::new(fields)),
1176            })
1177        });
1178
1179        // std::fs::read_to_string - read file contents as a string
1180        self.define_builtin("std·fs·read_to_string", Some(1), |interp, args| {
1181            // Recursively unwrap Ref types to get the actual value
1182            fn unwrap_refs(v: &Value) -> Value {
1183                match v {
1184                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1185                    other => other.clone(),
1186                }
1187            }
1188            let arg = unwrap_refs(&args[0]);
1189            crate::sigil_debug!("DEBUG read_to_string: arg = {:?}", arg);
1190            // Also dump the environment to see what 'path' is bound to
1191            crate::sigil_debug!("DEBUG read_to_string: env has path = {:?}", interp.environment.borrow().get("path"));
1192            let path = match &arg {
1193                Value::String(s) => s.to_string(),
1194                // Handle PathBuf or Path structs
1195                Value::Struct { name, fields, .. } => {
1196                    crate::sigil_debug!("DEBUG read_to_string: struct name = {}", name);
1197                    fields.borrow().get("path")
1198                        .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1199                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1200                }
1201                // Handle Option::Some(String)
1202                Value::Variant { enum_name, variant_name, fields } if enum_name == "Option" && variant_name == "Some" => {
1203                    if let Some(fields) = fields {
1204                        if let Some(Value::String(s)) = fields.first() {
1205                            s.to_string()
1206                        } else {
1207                            return Err(RuntimeError::new("read_to_string: Option::Some does not contain a string"));
1208                        }
1209                    } else {
1210                        return Err(RuntimeError::new("read_to_string: Option::Some has no fields"));
1211                    }
1212                }
1213                _ => return Err(RuntimeError::new(&format!("read_to_string expects a path string or PathBuf, got {:?}", arg))),
1214            };
1215            match std::fs::read_to_string(&path) {
1216                Ok(content) => Ok(Value::Variant {
1217                    enum_name: "Result".to_string(),
1218                    variant_name: "Ok".to_string(),
1219                    fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1220                }),
1221                Err(e) => Ok(Value::Variant {
1222                    enum_name: "Result".to_string(),
1223                    variant_name: "Err".to_string(),
1224                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1225                }),
1226            }
1227        });
1228
1229        // fs::read_to_string - alias without std prefix
1230        self.define_builtin("fs·read_to_string", Some(1), |_, args| {
1231            let arg = match &args[0] {
1232                Value::Ref(r) => r.borrow().clone(),
1233                other => other.clone(),
1234            };
1235            let path = match &arg {
1236                Value::String(s) => s.to_string(),
1237                Value::Struct { fields, .. } => {
1238                    fields.borrow().get("path")
1239                        .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1240                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1241                }
1242                _ => return Err(RuntimeError::new("read_to_string expects a path string or PathBuf")),
1243            };
1244            match std::fs::read_to_string(&path) {
1245                Ok(content) => Ok(Value::Variant {
1246                    enum_name: "Result".to_string(),
1247                    variant_name: "Ok".to_string(),
1248                    fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1249                }),
1250                Err(e) => Ok(Value::Variant {
1251                    enum_name: "Result".to_string(),
1252                    variant_name: "Err".to_string(),
1253                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1254                }),
1255            }
1256        });
1257
1258        // std::fs::read_dir - read directory entries
1259        self.define_builtin("std·fs·read_dir", Some(1), |_, args| {
1260            fn unwrap_refs(v: &Value) -> Value {
1261                match v {
1262                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1263                    other => other.clone(),
1264                }
1265            }
1266            let arg = unwrap_refs(&args[0]);
1267            let path = match &arg {
1268                Value::String(s) => s.to_string(),
1269                Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => {
1270                    fields.borrow().get("path")
1271                        .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1272                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1273                }
1274                _ => return Err(RuntimeError::new(&format!("read_dir expects a path, got {:?}", arg))),
1275            };
1276            match std::fs::read_dir(&path) {
1277                Ok(entries) => {
1278                    // Collect entries into a Vec of DirEntry structs wrapped in Result::Ok
1279                    let entry_values: Vec<Value> = entries
1280                        .filter_map(|e| e.ok())
1281                        .map(|e| {
1282                            let entry_path = e.path().to_string_lossy().to_string();
1283                            let mut fields = HashMap::new();
1284                            fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
1285                            // Each entry is wrapped in Result::Ok
1286                            Value::Variant {
1287                                enum_name: "Result".to_string(),
1288                                variant_name: "Ok".to_string(),
1289                                fields: Some(Rc::new(vec![Value::Struct {
1290                                    name: "DirEntry".to_string(),
1291                                    fields: Rc::new(RefCell::new(fields)),
1292                                }])),
1293                            }
1294                        })
1295                        .collect();
1296                    // The overall result is Ok(iterator/array)
1297                    Ok(Value::Variant {
1298                        enum_name: "Result".to_string(),
1299                        variant_name: "Ok".to_string(),
1300                        fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(entry_values)))])),
1301                    })
1302                }
1303                Err(e) => Ok(Value::Variant {
1304                    enum_name: "Result".to_string(),
1305                    variant_name: "Err".to_string(),
1306                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1307                }),
1308            }
1309        });
1310
1311        // fs::read_dir - alias without std prefix
1312        self.define_builtin("fs·read_dir", Some(1), |_, args| {
1313            fn unwrap_refs(v: &Value) -> Value {
1314                match v {
1315                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1316                    other => other.clone(),
1317                }
1318            }
1319            let arg = unwrap_refs(&args[0]);
1320            let path = match &arg {
1321                Value::String(s) => s.to_string(),
1322                Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => {
1323                    fields.borrow().get("path")
1324                        .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1325                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1326                }
1327                _ => return Err(RuntimeError::new(&format!("read_dir expects a path, got {:?}", arg))),
1328            };
1329            match std::fs::read_dir(&path) {
1330                Ok(entries) => {
1331                    let entry_values: Vec<Value> = entries
1332                        .filter_map(|e| e.ok())
1333                        .map(|e| {
1334                            let entry_path = e.path().to_string_lossy().to_string();
1335                            let mut fields = HashMap::new();
1336                            fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
1337                            Value::Variant {
1338                                enum_name: "Result".to_string(),
1339                                variant_name: "Ok".to_string(),
1340                                fields: Some(Rc::new(vec![Value::Struct {
1341                                    name: "DirEntry".to_string(),
1342                                    fields: Rc::new(RefCell::new(fields)),
1343                                }])),
1344                            }
1345                        })
1346                        .collect();
1347                    Ok(Value::Variant {
1348                        enum_name: "Result".to_string(),
1349                        variant_name: "Ok".to_string(),
1350                        fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(entry_values)))])),
1351                    })
1352                }
1353                Err(e) => Ok(Value::Variant {
1354                    enum_name: "Result".to_string(),
1355                    variant_name: "Err".to_string(),
1356                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1357                }),
1358            }
1359        });
1360
1361        // std::env::var - get environment variable
1362        self.define_builtin("std·env·var", Some(1), |_, args| {
1363            fn unwrap_refs(v: &Value) -> Value {
1364                match v {
1365                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1366                    other => other.clone(),
1367                }
1368            }
1369            let arg = unwrap_refs(&args[0]);
1370            let var_name = match &arg {
1371                Value::String(s) => s.to_string(),
1372                _ => return Err(RuntimeError::new("env::var expects a string")),
1373            };
1374            match std::env::var(&var_name) {
1375                Ok(value) => Ok(Value::Variant {
1376                    enum_name: "Result".to_string(),
1377                    variant_name: "Ok".to_string(),
1378                    fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
1379                }),
1380                Err(_) => Ok(Value::Variant {
1381                    enum_name: "Result".to_string(),
1382                    variant_name: "Err".to_string(),
1383                    fields: Some(Rc::new(vec![Value::String(Rc::new("Environment variable not found".to_string()))])),
1384                }),
1385            }
1386        });
1387
1388        // env::var - alias without std prefix
1389        self.define_builtin("env·var", Some(1), |_, args| {
1390            fn unwrap_refs(v: &Value) -> Value {
1391                match v {
1392                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1393                    other => other.clone(),
1394                }
1395            }
1396            let arg = unwrap_refs(&args[0]);
1397            let var_name = match &arg {
1398                Value::String(s) => s.to_string(),
1399                _ => return Err(RuntimeError::new("env::var expects a string")),
1400            };
1401            match std::env::var(&var_name) {
1402                Ok(value) => Ok(Value::Variant {
1403                    enum_name: "Result".to_string(),
1404                    variant_name: "Ok".to_string(),
1405                    fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
1406                }),
1407                Err(_) => Ok(Value::Variant {
1408                    enum_name: "Result".to_string(),
1409                    variant_name: "Err".to_string(),
1410                    fields: Some(Rc::new(vec![Value::String(Rc::new("Environment variable not found".to_string()))])),
1411                }),
1412            }
1413        });
1414
1415        // std::env::args - get command line arguments
1416        // This is a special function that returns an iterator/array of strings
1417        self.define_builtin("std·env·args", Some(0), |interp, _| {
1418            let args = interp.get_program_args();
1419            let arg_values: Vec<Value> = args.iter()
1420                .map(|s| Value::String(Rc::new(s.clone())))
1421                .collect();
1422            Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
1423        });
1424
1425        // env::args - alias without std prefix
1426        self.define_builtin("env·args", Some(0), |interp, _| {
1427            let args = interp.get_program_args();
1428            let arg_values: Vec<Value> = args.iter()
1429                .map(|s| Value::String(Rc::new(s.clone())))
1430                .collect();
1431            Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
1432        });
1433
1434        // ============================================================
1435        // Filesystem built-ins for scanner (underscore naming)
1436        // ============================================================
1437
1438        // fs_read - read entire file as string
1439        self.define_builtin("fs_read", Some(1), |_, args| {
1440            let path = match &args[0] {
1441                Value::String(s) => s.to_string(),
1442                _ => return Err(RuntimeError::new("fs_read requires a string path")),
1443            };
1444            match std::fs::read_to_string(&path) {
1445                Ok(content) => Ok(Value::String(Rc::new(content))),
1446                Err(e) => {
1447                    crate::sigil_debug!("DEBUG fs_read error for '{}': {}", path, e);
1448                    Ok(Value::Null)
1449                }
1450            }
1451        });
1452
1453        // fs_list - list directory contents as array of strings
1454        self.define_builtin("fs_list", Some(1), |_, args| {
1455            let path = match &args[0] {
1456                Value::String(s) => s.to_string(),
1457                _ => return Err(RuntimeError::new("fs_list requires a string path")),
1458            };
1459            match std::fs::read_dir(&path) {
1460                Ok(entries) => {
1461                    let files: Vec<Value> = entries
1462                        .filter_map(|e| e.ok())
1463                        .map(|e| Value::String(Rc::new(e.file_name().to_string_lossy().to_string())))
1464                        .collect();
1465                    Ok(Value::Array(Rc::new(RefCell::new(files))))
1466                }
1467                Err(e) => {
1468                    crate::sigil_debug!("DEBUG fs_list error for '{}': {}", path, e);
1469                    Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))))
1470                }
1471            }
1472        });
1473
1474        // fs_is_dir - check if path is a directory
1475        self.define_builtin("fs_is_dir", Some(1), |_, args| {
1476            let path = match &args[0] {
1477                Value::String(s) => s.to_string(),
1478                _ => return Err(RuntimeError::new("fs_is_dir requires a string path")),
1479            };
1480            Ok(Value::Bool(std::path::Path::new(&path).is_dir()))
1481        });
1482
1483        // fs_is_file - check if path is a file
1484        self.define_builtin("fs_is_file", Some(1), |_, args| {
1485            let path = match &args[0] {
1486                Value::String(s) => s.to_string(),
1487                _ => return Err(RuntimeError::new("fs_is_file requires a string path")),
1488            };
1489            Ok(Value::Bool(std::path::Path::new(&path).is_file()))
1490        });
1491
1492        // fs_exists - check if path exists
1493        self.define_builtin("fs_exists", Some(1), |_, args| {
1494            let path = match &args[0] {
1495                Value::String(s) => s.to_string(),
1496                _ => return Err(RuntimeError::new("fs_exists requires a string path")),
1497            };
1498            Ok(Value::Bool(std::path::Path::new(&path).exists()))
1499        });
1500
1501        // path_extension - get file extension
1502        self.define_builtin("path_extension", Some(1), |_, args| {
1503            let path = match &args[0] {
1504                Value::String(s) => s.to_string(),
1505                _ => return Err(RuntimeError::new("path_extension requires a string path")),
1506            };
1507            let ext = std::path::Path::new(&path)
1508                .extension()
1509                .and_then(|e| e.to_str())
1510                .map(|s| s.to_string());
1511            match ext {
1512                Some(e) => Ok(Value::String(Rc::new(e))),
1513                None => Ok(Value::Null),
1514            }
1515        });
1516
1517        // path_join - join path components
1518        self.define_builtin("path_join", Some(2), |_, args| {
1519            let base = match &args[0] {
1520                Value::String(s) => s.to_string(),
1521                _ => return Err(RuntimeError::new("path_join requires string paths")),
1522            };
1523            let part = match &args[1] {
1524                Value::String(s) => s.to_string(),
1525                _ => return Err(RuntimeError::new("path_join requires string paths")),
1526            };
1527            let joined = std::path::Path::new(&base).join(&part);
1528            Ok(Value::String(Rc::new(joined.to_string_lossy().to_string())))
1529        });
1530
1531        // path_parent - get parent directory
1532        self.define_builtin("path_parent", Some(1), |_, args| {
1533            let path = match &args[0] {
1534                Value::String(s) => s.to_string(),
1535                _ => return Err(RuntimeError::new("path_parent requires a string path")),
1536            };
1537            match std::path::Path::new(&path).parent() {
1538                Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
1539                None => Ok(Value::Null),
1540            }
1541        });
1542
1543        // path_file_name - get file name without directory
1544        self.define_builtin("path_file_name", Some(1), |_, args| {
1545            let path = match &args[0] {
1546                Value::String(s) => s.to_string(),
1547                _ => return Err(RuntimeError::new("path_file_name requires a string path")),
1548            };
1549            match std::path::Path::new(&path).file_name() {
1550                Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
1551                None => Ok(Value::Null),
1552            }
1553        });
1554
1555        // ============================================================
1556        // Tree-sitter parsing built-ins
1557        // ============================================================
1558
1559        // TreeSitterParser::new - create a tree-sitter parser for a language
1560        self.define_builtin("TreeSitterParser·new", Some(1), |_, args| {
1561            use crate::tree_sitter_support::{TSLanguage, TSParser};
1562
1563            // Get the language from the argument
1564            let lang_str = match &args[0] {
1565                Value::String(s) => s.to_string(),
1566                Value::Variant { enum_name, variant_name, .. } => {
1567                    // Handle Language::Rust style enums
1568                    format!("{}::{}", enum_name, variant_name)
1569                }
1570                other => format!("{:?}", other),
1571            };
1572
1573            // Try to create the parser
1574            let language = match TSLanguage::from_str(&lang_str) {
1575                Some(lang) => lang,
1576                None => {
1577                    return Ok(Value::Variant {
1578                        enum_name: "Result".to_string(),
1579                        variant_name: "Err".to_string(),
1580                        fields: Some(Rc::new(vec![Value::Struct {
1581                            name: "ParseError".to_string(),
1582                            fields: Rc::new(RefCell::new({
1583                                let mut f = HashMap::new();
1584                                f.insert("kind".to_string(), Value::String(Rc::new("ParserNotFound".to_string())));
1585                                f.insert("message".to_string(), Value::String(Rc::new(format!("Unsupported language: {}", lang_str))));
1586                                f
1587                            })),
1588                        }])),
1589                    });
1590                }
1591            };
1592
1593            // Create the parser and store the language
1594            match TSParser::new(language) {
1595                Ok(_) => {
1596                    // Return a TreeSitterParser struct
1597                    let mut fields = HashMap::new();
1598                    fields.insert("language".to_string(), Value::String(Rc::new(lang_str)));
1599                    fields.insert("_ts_language".to_string(), Value::String(Rc::new(format!("{:?}", language))));
1600
1601                    Ok(Value::Variant {
1602                        enum_name: "Result".to_string(),
1603                        variant_name: "Ok".to_string(),
1604                        fields: Some(Rc::new(vec![Value::Struct {
1605                            name: "TreeSitterParser".to_string(),
1606                            fields: Rc::new(RefCell::new(fields)),
1607                        }])),
1608                    })
1609                }
1610                Err(e) => {
1611                    Ok(Value::Variant {
1612                        enum_name: "Result".to_string(),
1613                        variant_name: "Err".to_string(),
1614                        fields: Some(Rc::new(vec![Value::Struct {
1615                            name: "ParseError".to_string(),
1616                            fields: Rc::new(RefCell::new({
1617                                let mut f = HashMap::new();
1618                                f.insert("kind".to_string(), Value::String(Rc::new("ParserNotFound".to_string())));
1619                                f.insert("message".to_string(), Value::String(Rc::new(e)));
1620                                f
1621                            })),
1622                        }])),
1623                    })
1624                }
1625            }
1626        });
1627
1628        // tree_sitter_parse - parse source code with tree-sitter
1629        self.define_builtin("tree_sitter_parse", Some(2), |_, args| {
1630            use crate::tree_sitter_support::{parse_source, node_to_value};
1631
1632            // First arg is the language string, second is the source code
1633            let lang_str = match &args[0] {
1634                Value::String(s) => s.to_string(),
1635                Value::Variant { enum_name, variant_name, .. } => {
1636                    format!("{}::{}", enum_name, variant_name)
1637                }
1638                other => format!("{:?}", other),
1639            };
1640
1641            let source = match &args[1] {
1642                Value::String(s) => s.to_string(),
1643                _ => return Err(RuntimeError::new("tree_sitter_parse expects source code string as second argument")),
1644            };
1645
1646            // Parse the source
1647            match parse_source(&lang_str, &source) {
1648                Ok(tree) => {
1649                    // Convert to SyntaxNode value
1650                    let root = tree.root_node();
1651                    let root_fields = node_to_value(&root);
1652
1653                    // Create TSTree struct
1654                    let mut tree_fields = HashMap::new();
1655                    tree_fields.insert("root".to_string(), Value::Struct {
1656                        name: "SyntaxNode".to_string(),
1657                        fields: Rc::new(RefCell::new(root_fields)),
1658                    });
1659                    tree_fields.insert("source".to_string(), Value::String(Rc::new(source)));
1660
1661                    Ok(Value::Variant {
1662                        enum_name: "Result".to_string(),
1663                        variant_name: "Ok".to_string(),
1664                        fields: Some(Rc::new(vec![Value::Struct {
1665                            name: "TSTree".to_string(),
1666                            fields: Rc::new(RefCell::new(tree_fields)),
1667                        }])),
1668                    })
1669                }
1670                Err(e) => {
1671                    Ok(Value::Variant {
1672                        enum_name: "Result".to_string(),
1673                        variant_name: "Err".to_string(),
1674                        fields: Some(Rc::new(vec![Value::Struct {
1675                            name: "ParseError".to_string(),
1676                            fields: Rc::new(RefCell::new({
1677                                let mut f = HashMap::new();
1678                                f.insert("kind".to_string(), Value::String(Rc::new("SyntaxError".to_string())));
1679                                f.insert("message".to_string(), Value::String(Rc::new(e)));
1680                                f
1681                            })),
1682                        }])),
1683                    })
1684                }
1685            }
1686        });
1687
1688        // tree_sitter_supported_languages - get list of supported languages
1689        self.define_builtin("tree_sitter_supported_languages", Some(0), |_, _| {
1690            use crate::tree_sitter_support::supported_languages;
1691
1692            let languages: Vec<Value> = supported_languages()
1693                .iter()
1694                .map(|s| Value::String(Rc::new(s.to_string())))
1695                .collect();
1696
1697            Ok(Value::Array(Rc::new(RefCell::new(languages))))
1698        });
1699
1700        // tree_sitter_node_text - extract text from a syntax node using the source
1701        self.define_builtin("tree_sitter_node_text", Some(2), |_, args| {
1702            // First arg is the node (with start_byte and end_byte), second is the source
1703            let (start_byte, end_byte) = match &args[0] {
1704                Value::Struct { fields, .. } => {
1705                    let fields = fields.borrow();
1706                    let start = match fields.get("start_byte") {
1707                        Some(Value::Int(n)) => *n as usize,
1708                        _ => return Err(RuntimeError::new("Node missing start_byte field")),
1709                    };
1710                    let end = match fields.get("end_byte") {
1711                        Some(Value::Int(n)) => *n as usize,
1712                        _ => return Err(RuntimeError::new("Node missing end_byte field")),
1713                    };
1714                    (start, end)
1715                }
1716                _ => return Err(RuntimeError::new("tree_sitter_node_text expects a SyntaxNode struct")),
1717            };
1718
1719            let source = match &args[1] {
1720                Value::String(s) => s.to_string(),
1721                _ => return Err(RuntimeError::new("tree_sitter_node_text expects source string as second argument")),
1722            };
1723
1724            if end_byte <= source.len() && start_byte <= end_byte {
1725                Ok(Value::String(Rc::new(source[start_byte..end_byte].to_string())))
1726            } else {
1727                Err(RuntimeError::new("Byte range out of bounds"))
1728            }
1729        });
1730
1731        // Rc::new(value) - Reference counted smart pointer (simplified)
1732        let rc_new = Value::BuiltIn(Rc::new(BuiltInFn {
1733            name: "Rc·new".to_string(),
1734            arity: Some(1),
1735            func: |_, args| {
1736                let mut fields = HashMap::new();
1737                fields.insert("_value".to_string(), args[0].clone());
1738                Ok(Value::Struct {
1739                    name: "Rc".to_string(),
1740                    fields: std::rc::Rc::new(RefCell::new(fields)),
1741                })
1742            },
1743        }));
1744        self.globals.borrow_mut().define("Rc·new".to_string(), rc_new);
1745
1746        // Cell::new(value) - Interior mutability
1747        let cell_new = Value::BuiltIn(Rc::new(BuiltInFn {
1748            name: "Cell·new".to_string(),
1749            arity: Some(1),
1750            func: |_, args| {
1751                let mut fields = HashMap::new();
1752                fields.insert("_value".to_string(), args[0].clone());
1753                Ok(Value::Struct {
1754                    name: "Cell".to_string(),
1755                    fields: std::rc::Rc::new(RefCell::new(fields)),
1756                })
1757            },
1758        }));
1759        self.globals.borrow_mut().define("Cell·new".to_string(), cell_new);
1760
1761        // RefCell::new(value) - Interior mutability with runtime borrow checking
1762        let refcell_new = Value::BuiltIn(Rc::new(BuiltInFn {
1763            name: "RefCell·new".to_string(),
1764            arity: Some(1),
1765            func: |_, args| {
1766                Ok(Value::RefCellValue(Rc::new(RefCellInner {
1767                    value: RefCell::new(args[0].clone()),
1768                    borrow_state: RefCell::new(BorrowState::Unborrowed),
1769                })))
1770            },
1771        }));
1772        self.globals.borrow_mut().define("RefCell·new".to_string(), refcell_new);
1773
1774        // as_dyn(value, "TraitName") - Create a trait object for dynamic dispatch
1775        // Usage: let drawable! = as_dyn(Circle { r: 5 }, "Drawable");
1776        //        drawable.draw();  // Dynamic dispatch to Circle·draw
1777        let as_dyn_fn = Value::BuiltIn(Rc::new(BuiltInFn {
1778            name: "as_dyn".to_string(),
1779            arity: Some(2),
1780            func: |interp, args| {
1781                let value = args[0].clone();
1782                let trait_name = match &args[1] {
1783                    Value::String(s) => (**s).clone(),
1784                    _ => return Err(RuntimeError::new("as_dyn: second argument must be trait name string")),
1785                };
1786
1787                // Get the concrete type name from the value
1788                let concrete_type = match &value {
1789                    Value::Struct { name, .. } => name.clone(),
1790                    _ => return Err(RuntimeError::new("as_dyn: first argument must be a struct")),
1791                };
1792
1793                // Verify the type implements the trait
1794                if !interp.trait_impls.contains_key(&(concrete_type.clone(), trait_name.clone())) {
1795                    return Err(RuntimeError::new(format!(
1796                        "Type '{}' does not implement trait '{}'",
1797                        concrete_type, trait_name
1798                    )));
1799                }
1800
1801                Ok(Value::TraitObject {
1802                    value: Box::new(value),
1803                    concrete_type,
1804                    trait_name,
1805                })
1806            },
1807        }));
1808        self.globals.borrow_mut().define("as_dyn".to_string(), as_dyn_fn);
1809    }
1810
1811    fn define_builtin(
1812        &mut self,
1813        name: &str,
1814        arity: Option<usize>,
1815        func: fn(&mut Interpreter, Vec<Value>) -> Result<Value, RuntimeError>,
1816    ) {
1817        let builtin = Value::BuiltIn(Rc::new(BuiltInFn {
1818            name: name.to_string(),
1819            arity,
1820            func,
1821        }));
1822        self.globals.borrow_mut().define(name.to_string(), builtin);
1823    }
1824
1825    /// Execute a source file
1826    pub fn execute(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
1827        let mut result = Value::Null;
1828
1829        for item in &file.items {
1830            result = self.execute_item(&item.node)?;
1831        }
1832
1833        // Look for main function and execute it (only if it takes no args)
1834        let main_fn = self.globals.borrow().get("main").and_then(|v| {
1835            if let Value::Function(f) = v {
1836                Some(f.clone())
1837            } else {
1838                None
1839            }
1840        });
1841        if let Some(f) = main_fn {
1842            // Only auto-call main if it takes no arguments
1843            // If main expects args, caller should call it explicitly via call_function_by_name
1844            if f.params.is_empty() {
1845                result = self.call_function(&f, vec![])?;
1846            }
1847        }
1848
1849        Ok(result)
1850    }
1851
1852    /// Execute a file but only register definitions, don't auto-call main.
1853    /// Use this when loading files as part of a multi-file workspace.
1854    pub fn execute_definitions(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
1855        let mut result = Value::Null;
1856
1857        for item in &file.items {
1858            result = self.execute_item(&item.node)?;
1859        }
1860
1861        Ok(result)
1862    }
1863
1864    fn execute_item(&mut self, item: &Item) -> Result<Value, RuntimeError> {
1865        match item {
1866            Item::Function(func) => {
1867                let fn_value = self.create_function(func)?;
1868                let fn_name = func.name.name.clone();
1869
1870                // Register with both simple name and module-qualified name
1871                self.globals.borrow_mut().define(fn_name.clone(), fn_value.clone());
1872
1873                // Also register with module prefix if we're in a module context
1874                if let Some(ref module) = self.current_module {
1875                    let qualified_name = format!("{}·{}", module, fn_name);
1876                    self.globals.borrow_mut().define(qualified_name, fn_value);
1877                }
1878
1879                Ok(Value::Null)
1880            }
1881            Item::Struct(s) => {
1882                // Register with simple name
1883                self.types
1884                    .insert(s.name.name.clone(), TypeDef::Struct(s.clone()));
1885
1886                // Also register with module-qualified name if in a module context
1887                if let Some(ref module) = self.current_module {
1888                    let qualified_name = format!("{}·{}", module, s.name.name);
1889                    self.types.insert(qualified_name, TypeDef::Struct(s.clone()));
1890                }
1891
1892                // For unit structs, register the struct name as a value (zero-sized type)
1893                if matches!(&s.fields, crate::ast::StructFields::Unit) {
1894                    let unit_value = Value::Struct {
1895                        name: s.name.name.clone(),
1896                        fields: Rc::new(RefCell::new(HashMap::new())),
1897                    };
1898                    self.globals.borrow_mut().define(s.name.name.clone(), unit_value.clone());
1899
1900                    // Also register with module-qualified name
1901                    if let Some(ref module) = self.current_module {
1902                        let qualified_name = format!("{}·{}", module, s.name.name);
1903                        self.globals.borrow_mut().define(qualified_name, unit_value);
1904                    }
1905                }
1906
1907                // Check for #[derive(Default)] attribute and store for later lookup
1908                let has_default = s.attrs.derives.iter().any(|d| matches!(d, DeriveTrait::Default));
1909                if has_default {
1910                    self.default_structs.insert(s.name.name.clone(), s.clone());
1911                    if let Some(ref module) = self.current_module {
1912                        let qualified_name = format!("{}·{}", module, s.name.name);
1913                        self.default_structs.insert(qualified_name, s.clone());
1914                    }
1915                }
1916
1917                Ok(Value::Null)
1918            }
1919            Item::Enum(e) => {
1920                // Register with simple name
1921                self.types
1922                    .insert(e.name.name.clone(), TypeDef::Enum(e.clone()));
1923
1924                // Also register with module-qualified name
1925                if let Some(ref module) = self.current_module {
1926                    let qualified_name = format!("{}·{}", module, e.name.name);
1927                    self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
1928                }
1929
1930                // Register variant constructors as EnumName·VariantName
1931                // Store them in a lookup table that the variant_constructor builtin can use
1932                let enum_name = e.name.name.clone();
1933                for variant in &e.variants {
1934                    let variant_name = variant.name.name.clone();
1935                    let qualified_name = format!("{}·{}", enum_name, variant_name);
1936
1937                    let arity = match &variant.fields {
1938                        crate::ast::StructFields::Unit => 0,
1939                        crate::ast::StructFields::Tuple(types) => types.len(),
1940                        crate::ast::StructFields::Named(fields) => fields.len(),
1941                    };
1942
1943                    // Store variant info for later lookup
1944                    self.variant_constructors.insert(qualified_name.clone(), (enum_name.clone(), variant_name.clone(), arity));
1945                }
1946                Ok(Value::Null)
1947            }
1948            Item::Const(c) => {
1949                let value = self.evaluate(&c.value)?;
1950                self.globals.borrow_mut().define(c.name.name.clone(), value);
1951                Ok(Value::Null)
1952            }
1953            Item::Static(s) => {
1954                let value = self.evaluate(&s.value)?;
1955                self.globals.borrow_mut().define(s.name.name.clone(), value);
1956                Ok(Value::Null)
1957            }
1958            Item::ExternBlock(extern_block) => {
1959                // Register extern functions as builtins
1960                for item in &extern_block.items {
1961                    if let ExternItem::Function(func) = item {
1962                        let name = func.name.name.clone();
1963                        // Register emulated FFI functions
1964                        match name.as_str() {
1965                            "sigil_read_file" => {
1966                                self.define_builtin("sigil_read_file", Some(2), |_, args| {
1967                                    // args[0] = path pointer (we'll use string), args[1] = len
1968                                    let path = match &args[0] {
1969                                        Value::String(s) => (**s).clone(),
1970                                        _ => return Err(RuntimeError::new("sigil_read_file expects string path")),
1971                                    };
1972                                    match std::fs::read_to_string(&path) {
1973                                        Ok(content) => {
1974                                            // Store content in a global for sigil_file_len to access
1975                                            Ok(Value::String(Rc::new(content)))
1976                                        }
1977                                        Err(_) => Ok(Value::Null),
1978                                    }
1979                                });
1980                            }
1981                            "sigil_file_len" => {
1982                                self.define_builtin("sigil_file_len", Some(0), |_, _| {
1983                                    // This is a placeholder - in real usage, would track last read
1984                                    Ok(Value::Int(0))
1985                                });
1986                            }
1987                            "sigil_write_file" => {
1988                                self.define_builtin("sigil_write_file", Some(4), |_, args| {
1989                                    let path = match &args[0] {
1990                                        Value::String(s) => (**s).clone(),
1991                                        _ => return Err(RuntimeError::new("sigil_write_file expects string path")),
1992                                    };
1993                                    let content = match &args[2] {
1994                                        Value::String(s) => (**s).clone(),
1995                                        _ => return Err(RuntimeError::new("sigil_write_file expects string content")),
1996                                    };
1997                                    match std::fs::write(&path, &content) {
1998                                        Ok(_) => Ok(Value::Bool(true)),
1999                                        Err(_) => Ok(Value::Bool(false)),
2000                                    }
2001                                });
2002                            }
2003                            "write" => {
2004                                self.define_builtin("write", Some(3), |_, args| {
2005                                    // write(fd, buf, count)
2006                                    let fd = match &args[0] {
2007                                        Value::Int(n) => *n,
2008                                        _ => 1,
2009                                    };
2010                                    let content = match &args[1] {
2011                                        Value::String(s) => (**s).clone(),
2012                                        _ => format!("{}", args[1]),
2013                                    };
2014                                    if fd == 1 {
2015                                        print!("{}", content);
2016                                    } else if fd == 2 {
2017                                        eprint!("{}", content);
2018                                    }
2019                                    Ok(Value::Int(content.len() as i64))
2020                                });
2021                            }
2022                            _ => {
2023                                // Unknown extern function - register a no-op
2024                            }
2025                        }
2026                    }
2027                }
2028                Ok(Value::Null)
2029            }
2030            Item::Impl(impl_block) => {
2031                // Extract type name from self_ty
2032                let type_name = match &impl_block.self_ty {
2033                    TypeExpr::Path(path) => {
2034                        path.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("::")
2035                    }
2036                    _ => return Ok(Value::Null), // Can't handle complex types
2037                };
2038
2039                // Check if this is `impl Drop for X` - register for automatic drop calls
2040                if let Some(trait_path) = &impl_block.trait_ {
2041                    let trait_name = trait_path.segments.iter()
2042                        .map(|s| s.ident.name.as_str())
2043                        .collect::<Vec<_>>()
2044                        .join("::");
2045                    if trait_name == "Drop" {
2046                        self.drop_types.insert(type_name.clone());
2047                    }
2048                }
2049
2050                // Register each method with qualified name TypeName·method
2051                for impl_item in &impl_block.items {
2052                    if let ImplItem::Function(func) = impl_item {
2053                        let fn_value = self.create_function(func)?;
2054                        let qualified_name = format!("{}·{}", type_name, func.name.name);
2055                        // Debug: track Lexer method registration
2056                        if type_name == "Lexer" && func.name.name.contains("keyword") {
2057                            crate::sigil_debug!("DEBUG registering: {}", qualified_name);
2058                        }
2059                        self.globals.borrow_mut().define(qualified_name.clone(), fn_value.clone());
2060
2061                        // Also register with module prefix if in a module context
2062                        if let Some(ref module) = self.current_module {
2063                            let fully_qualified = format!("{}·{}", module, qualified_name);
2064                            self.globals.borrow_mut().define(fully_qualified, fn_value);
2065                        }
2066                    }
2067                }
2068
2069                // Track trait implementation
2070                if let Some(trait_path) = &impl_block.trait_ {
2071                    let trait_name = trait_path.segments.iter()
2072                        .map(|s| s.ident.name.as_str())
2073                        .collect::<Vec<_>>()
2074                        .join("::");
2075                    self.trait_impls.insert((type_name.clone(), trait_name), true);
2076                }
2077
2078                Ok(Value::Null)
2079            }
2080            Item::Trait(trait_def) => {
2081                // Store trait definition
2082                let trait_name = trait_def.name.name.clone();
2083
2084                // Extract method names from trait items
2085                let methods: Vec<String> = trait_def.items.iter()
2086                    .filter_map(|item| {
2087                        if let crate::ast::TraitItem::Function(f) = item {
2088                            Some(f.name.name.clone())
2089                        } else {
2090                            None
2091                        }
2092                    })
2093                    .collect();
2094
2095                // Extract supertrait names
2096                let supertraits: Vec<String> = trait_def.supertraits.iter()
2097                    .filter_map(|t| {
2098                        if let TypeExpr::Path(path) = t {
2099                            Some(path.segments.iter()
2100                                .map(|s| s.ident.name.as_str())
2101                                .collect::<Vec<_>>()
2102                                .join("::"))
2103                        } else {
2104                            None
2105                        }
2106                    })
2107                    .collect();
2108
2109                self.trait_defs.insert(trait_name.clone(), TraitInfo {
2110                    name: trait_name,
2111                    methods,
2112                    supertraits,
2113                });
2114
2115                Ok(Value::Null)
2116            }
2117            Item::Module(module) => {
2118                // Handle module definitions
2119                let module_name = &module.name.name;
2120
2121                if let Some(items) = &module.items {
2122                    // Inline module: mod foo { ... }
2123                    // Register items with qualified names: module_name·item_name
2124                    for item in items {
2125                        match &item.node {
2126                            Item::Const(c) => {
2127                                let value = self.evaluate(&c.value)?;
2128                                let qualified_name = format!("{}·{}", module_name, c.name.name);
2129                                self.globals.borrow_mut().define(qualified_name, value);
2130                            }
2131                            Item::Static(s) => {
2132                                let value = self.evaluate(&s.value)?;
2133                                let qualified_name = format!("{}·{}", module_name, s.name.name);
2134                                self.globals.borrow_mut().define(qualified_name, value);
2135                            }
2136                            Item::Function(func) => {
2137                                let fn_value = self.create_function(func)?;
2138                                let qualified_name = format!("{}·{}", module_name, func.name.name);
2139                                self.globals.borrow_mut().define(qualified_name, fn_value);
2140                            }
2141                            Item::Struct(s) => {
2142                                let qualified_name = format!("{}·{}", module_name, s.name.name);
2143                                self.types.insert(qualified_name, TypeDef::Struct(s.clone()));
2144                            }
2145                            Item::Enum(e) => {
2146                                let qualified_name = format!("{}·{}", module_name, e.name.name);
2147                                self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
2148                            }
2149                            _ => {} // Skip other nested items for now
2150                        }
2151                    }
2152                } else {
2153                    // External module: mod foo; - try to load foo.sigil from same directory
2154                    if let Some(ref source_dir) = self.current_source_dir {
2155                        let module_path = std::path::Path::new(source_dir)
2156                            .join(format!("{}.sigil", module_name));
2157                        
2158                        if module_path.exists() {
2159                            crate::sigil_debug!("DEBUG Loading external module: {}", module_path.display());
2160                            
2161                            match std::fs::read_to_string(&module_path) {
2162                                Ok(source) => {
2163                                    // Parse the module file
2164                                    let mut parser = crate::Parser::new(&source);
2165                                    match parser.parse_file() {
2166                                        Ok(parsed_file) => {
2167                                            // Save current module context
2168                                            let prev_module = self.current_module.clone();
2169                                            
2170                                            // Set module context for registering definitions
2171                                            self.current_module = Some(module_name.clone());
2172                                            
2173                                            // Execute module definitions
2174                                            for item in &parsed_file.items {
2175                                                if let Err(e) = self.execute_item(&item.node) {
2176                                                    crate::sigil_warn!("Warning: error in module {}: {}", module_name, e);
2177                                                }
2178                                            }
2179                                            
2180                                            // Restore previous module context
2181                                            self.current_module = prev_module;
2182                                        }
2183                                        Err(e) => {
2184                                            crate::sigil_warn!("Warning: failed to parse module {}: {:?}", module_name, e);
2185                                        }
2186                                    }
2187                                }
2188                                Err(e) => {
2189                                    crate::sigil_warn!("Warning: failed to read module file {}: {}", module_path.display(), e);
2190                                }
2191                            }
2192                        } else {
2193                            crate::sigil_debug!("DEBUG Module file not found: {} (source_dir={})", module_path.display(), source_dir);
2194                        }
2195                    } else {
2196                        crate::sigil_debug!("DEBUG No source_dir set, cannot load external module: {}", module_name);
2197                    }
2198                }
2199                Ok(Value::Null)
2200            }
2201            Item::Use(use_decl) => {
2202                // Process use declarations to create type/function aliases
2203                self.process_use_tree(&use_decl.tree, &[])?;
2204                Ok(Value::Null)
2205            }
2206            _ => Ok(Value::Null), // Skip other items for now
2207        }
2208    }
2209
2210    /// Process a use tree to create type and function aliases
2211    fn process_use_tree(&mut self, tree: &crate::ast::UseTree, prefix: &[String]) -> Result<(), RuntimeError> {
2212        use crate::ast::UseTree;
2213        match tree {
2214            UseTree::Path { prefix: path_prefix, suffix } => {
2215                // Build path: prefix + this segment
2216                let mut new_prefix = prefix.to_vec();
2217                new_prefix.push(path_prefix.name.clone());
2218                self.process_use_tree(suffix, &new_prefix)
2219            }
2220            UseTree::Name(name) => {
2221                // use foo::bar::Baz -> import Baz from foo·bar·Baz
2222                let mut path = prefix.to_vec();
2223                path.push(name.name.clone());
2224                let qualified = path.join("·");
2225                let simple_name = name.name.clone();
2226
2227                // If the type/function isn't found, try loading the crate first
2228                // The crate name is the first segment of the path
2229                if !prefix.is_empty() {
2230                    let crate_name = &prefix[0];
2231                    if !self.types.contains_key(&qualified)
2232                       && self.globals.borrow().get(&qualified).is_none()
2233                       && !self.loaded_crates.contains(crate_name)
2234                    {
2235                        // Try to load the crate
2236                        if let Err(e) = self.load_crate(crate_name) {
2237                            crate::sigil_debug!("DEBUG process_use_tree: failed to load crate '{}': {}", crate_name, e);
2238                        }
2239                    }
2240                }
2241
2242                // Create alias: simple_name -> qualified
2243                // For types: if foo·bar·Baz exists in types, also register as Baz
2244                if let Some(type_def) = self.types.get(&qualified).cloned() {
2245                    self.types.insert(simple_name.clone(), type_def);
2246                }
2247                // For functions: if foo·bar·Baz exists in globals, also register as Baz
2248                let func = self.globals.borrow().get(&qualified).map(|v| v.clone());
2249                if let Some(val) = func {
2250                    self.globals.borrow_mut().define(simple_name.clone(), val);
2251                }
2252
2253                // Also import impl methods for this type
2254                // e.g., when importing samael_analysis::AnalysisConfig,
2255                // also import samael_analysis·AnalysisConfig·default as AnalysisConfig·default
2256                let method_prefix = format!("{}·", qualified);
2257                let matching_methods: Vec<(String, Value)> = {
2258                    let globals = self.globals.borrow();
2259                    globals.values.iter()
2260                        .filter(|(k, _)| k.starts_with(&method_prefix))
2261                        .map(|(k, v)| {
2262                            // samael_analysis·AnalysisConfig·default -> AnalysisConfig·default
2263                            let method_suffix = k.strip_prefix(&method_prefix).unwrap();
2264                            let new_name = format!("{}·{}", simple_name, method_suffix);
2265                            (new_name, v.clone())
2266                        })
2267                        .collect()
2268                };
2269                for (name, val) in matching_methods {
2270                    self.globals.borrow_mut().define(name, val);
2271                }
2272                Ok(())
2273            }
2274            UseTree::Rename { name, alias } => {
2275                // use foo::bar::Baz as Qux
2276                let mut path = prefix.to_vec();
2277                path.push(name.name.clone());
2278                let qualified = path.join("·");
2279                let alias_name = alias.name.clone();
2280
2281                if let Some(type_def) = self.types.get(&qualified).cloned() {
2282                    self.types.insert(alias_name.clone(), type_def);
2283                }
2284                let func = self.globals.borrow().get(&qualified).map(|v| v.clone());
2285                if let Some(val) = func {
2286                    self.globals.borrow_mut().define(alias_name, val);
2287                }
2288                Ok(())
2289            }
2290            UseTree::Glob => {
2291                // use foo::bar::* - import all from foo·bar
2292                let path_prefix = prefix.join("·");
2293                // Find all types starting with this prefix
2294                let matching_types: Vec<(String, TypeDef)> = self.types.iter()
2295                    .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
2296                    .map(|(k, v)| {
2297                        let suffix = k.strip_prefix(&path_prefix).unwrap().trim_start_matches('·');
2298                        (suffix.to_string(), v.clone())
2299                    })
2300                    .filter(|(k, _)| !k.contains('·')) // Only immediate children
2301                    .collect();
2302                for (name, def) in matching_types {
2303                    self.types.insert(name, def);
2304                }
2305                // Similar for functions
2306                let matching_funcs: Vec<(String, Value)> = {
2307                    let globals = self.globals.borrow();
2308                    globals.values.iter()
2309                        .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
2310                        .map(|(k, v)| {
2311                            let suffix = k.strip_prefix(&path_prefix).unwrap().trim_start_matches('·');
2312                            (suffix.to_string(), v.clone())
2313                        })
2314                        .filter(|(k, _)| !k.contains('·'))
2315                        .collect()
2316                };
2317                for (name, val) in matching_funcs {
2318                    self.globals.borrow_mut().define(name, val);
2319                }
2320                Ok(())
2321            }
2322            UseTree::Group(trees) => {
2323                // use foo::{Bar, Baz}
2324                for tree in trees {
2325                    self.process_use_tree(tree, prefix)?;
2326                }
2327                Ok(())
2328            }
2329        }
2330    }
2331
2332    fn create_function(&self, func: &crate::ast::Function) -> Result<Value, RuntimeError> {
2333        let params: Vec<String> = func
2334            .params
2335            .iter()
2336            .map(|p| Self::extract_param_name(&p.pattern))
2337            .collect();
2338
2339        let body = func
2340            .body
2341            .as_ref()
2342            .map(|b| Expr::Block(b.clone()))
2343            .unwrap_or(Expr::Literal(Literal::Bool(false)));
2344
2345        Ok(Value::Function(Rc::new(Function {
2346            name: Some(func.name.name.clone()),
2347            params,
2348            body,
2349            closure: self.environment.clone(),
2350        })))
2351    }
2352
2353    /// Extract parameter name from a pattern, handling &self, mut self, etc.
2354    fn extract_param_name(pattern: &Pattern) -> String {
2355        match pattern {
2356            Pattern::Ident { name, .. } => name.name.clone(),
2357            // Handle &self and &mut self
2358            Pattern::Ref { pattern: inner, .. } => Self::extract_param_name(inner),
2359            // Handle ref self
2360            Pattern::RefBinding { name, .. } => name.name.clone(),
2361            _ => "_".to_string(),
2362        }
2363    }
2364
2365    /// Evaluate an expression
2366    pub fn evaluate(&mut self, expr: &Expr) -> Result<Value, RuntimeError> {
2367        match expr {
2368            Expr::Literal(lit) => self.eval_literal(lit),
2369            Expr::Path(path) => self.eval_path(path),
2370            Expr::Binary { left, op, right } => self.eval_binary(left, op, right),
2371            Expr::Unary { op, expr } => self.eval_unary(op, expr),
2372            Expr::Call { func, args } => self.eval_call(func, args),
2373            Expr::Array(elements) => self.eval_array(elements),
2374            Expr::Tuple(elements) => self.eval_tuple(elements),
2375            Expr::Block(block) => self.eval_block(block),
2376            Expr::If {
2377                condition,
2378                then_branch,
2379                else_branch,
2380            } => self.eval_if(condition, then_branch, else_branch),
2381            Expr::Match { expr, arms } => self.eval_match(expr, arms),
2382            Expr::For {
2383                pattern,
2384                iter,
2385                body,
2386                ..
2387            } => self.eval_for(pattern, iter, body),
2388            Expr::While { condition, body, .. } => self.eval_while(condition, body),
2389            Expr::Loop { body, .. } => self.eval_loop(body),
2390            Expr::Return(value) => self.eval_return(value),
2391            Expr::Break { value, .. } => self.eval_break(value),
2392            Expr::Continue { .. } => Err(RuntimeError::new("continue")),
2393            Expr::Index { expr, index } => self.eval_index(expr, index),
2394            Expr::Field { expr, field } => self.eval_field(expr, field),
2395            Expr::MethodCall {
2396                receiver,
2397                method,
2398                args,
2399                ..
2400            } => self.eval_method_call(receiver, method, args),
2401            // Polysynthetic incorporation: path·file·read·string
2402            // Each segment is a method/function that transforms the value
2403            Expr::Incorporation { segments } => self.eval_incorporation(segments),
2404            Expr::Pipe { expr, operations } => self.eval_pipe(expr, operations),
2405            Expr::Closure { params, body, .. } => self.eval_closure(params, body),
2406            Expr::Struct { path, fields, rest } => self.eval_struct_literal(path, fields, rest),
2407            Expr::Evidential {
2408                expr,
2409                evidentiality,
2410            } => self.eval_evidential(expr, evidentiality),
2411            Expr::Range {
2412                start,
2413                end,
2414                inclusive,
2415            } => {
2416                crate::sigil_debug!("DEBUG evaluate: Expr::Range being evaluated standalone");
2417                self.eval_range(start, end, *inclusive)
2418            }
2419            Expr::Assign { target, value } => self.eval_assign(target, value),
2420            Expr::Let { pattern, value } => {
2421                // Let expression (for if-let, while-let patterns)
2422                // Evaluate the value and check if pattern matches
2423                let val = self.evaluate(value)?;
2424                // Check if pattern matches - return true/false for if-let semantics
2425                if self.pattern_matches(pattern, &val)? {
2426                    // Pattern matches - bind variables and return true
2427                    self.bind_pattern(pattern, val)?;
2428                    Ok(Value::Bool(true))
2429                } else {
2430                    // Pattern doesn't match - return false without binding
2431                    Ok(Value::Bool(false))
2432                }
2433            }
2434            Expr::Await {
2435                expr: inner,
2436                evidentiality,
2437            } => {
2438                let value = self.evaluate(inner)?;
2439                let awaited = self.await_value(value)?;
2440                // Handle evidentiality marker semantics
2441                match evidentiality {
2442                    Some(Evidentiality::Uncertain) => {
2443                        // ⌛? - propagate error like Try
2444                        self.unwrap_result_or_option(awaited, true, false)
2445                    }
2446                    Some(Evidentiality::Known) => {
2447                        // ⌛! - expect success, panic on error
2448                        self.unwrap_result_or_option(awaited, true, true)
2449                    }
2450                    Some(Evidentiality::Reported) | Some(Evidentiality::Paradox) | Some(Evidentiality::Predicted) => {
2451                        // ⌛~ or ⌛‽ or ⌛◊ - mark as external/reported/predicted, unwrap if Result/Option
2452                        self.unwrap_result_or_option(awaited, false, false)
2453                    }
2454                    None => Ok(awaited),
2455                }
2456            }
2457            // Macro invocations: format!(...), println!(...), etc.
2458            Expr::Macro { path, tokens } => {
2459                let macro_name = path.segments.last()
2460                    .map(|s| s.ident.name.as_str())
2461                    .unwrap_or("");
2462                crate::sigil_debug!("DEBUG Expr::Macro: name='{}', tokens='{}'", macro_name, tokens);
2463
2464                match macro_name {
2465                    "format" => self.eval_format_macro(tokens),
2466                    "println" => {
2467                        let formatted = self.eval_format_macro(tokens)?;
2468                        if let Value::String(s) = formatted {
2469                            println!("{}", s);
2470                        }
2471                        Ok(Value::Null)
2472                    }
2473                    "eprintln" => {
2474                        let formatted = self.eval_format_macro(tokens)?;
2475                        if let Value::String(s) = formatted {
2476                            eprintln!("{}", s);
2477                        }
2478                        Ok(Value::Null)
2479                    }
2480                    "print" => {
2481                        let formatted = self.eval_format_macro(tokens)?;
2482                        if let Value::String(s) = formatted {
2483                            print!("{}", s);
2484                        }
2485                        Ok(Value::Null)
2486                    }
2487                    "eprint" => {
2488                        let formatted = self.eval_format_macro(tokens)?;
2489                        if let Value::String(s) = formatted {
2490                            eprint!("{}", s);
2491                        }
2492                        Ok(Value::Null)
2493                    }
2494                    "vec" => {
2495                        // vec![a, b, c] - parse elements and create array
2496                        self.eval_vec_macro(tokens)
2497                    }
2498                    "panic" => {
2499                        let formatted = self.eval_format_macro(tokens)?;
2500                        let msg = if let Value::String(s) = formatted {
2501                            s.to_string()
2502                        } else {
2503                            "panic!".to_string()
2504                        };
2505                        Err(RuntimeError::new(format!("panic: {}", msg)))
2506                    }
2507                    "assert" => {
2508                        // Simple assert - just evaluate the expression
2509                        let condition = self.eval_format_macro(tokens)?;
2510                        if self.is_truthy(&condition) {
2511                            Ok(Value::Null)
2512                        } else {
2513                            Err(RuntimeError::new("assertion failed"))
2514                        }
2515                    }
2516                    _ => {
2517                        // Unknown macro - return tokens as string for debugging
2518                        Ok(Value::String(Rc::new(tokens.clone())))
2519                    }
2520                }
2521            }
2522            // Unsafe block - just evaluate the block normally
2523            Expr::Unsafe(block) => self.eval_block(block),
2524            // Async block - evaluate the block (interpreter doesn't handle true async)
2525            Expr::Async { block, .. } => self.eval_block(block),
2526            // Try expression: expr?
2527            Expr::Try(inner) => {
2528                let value = self.evaluate(inner)?;
2529                // If Result::Err or None, propagate the error
2530                // If Result::Ok or Some, unwrap the value
2531                match &value {
2532                    Value::Variant { enum_name, variant_name, fields } => {
2533                        match (enum_name.as_str(), variant_name.as_str()) {
2534                            ("Result", "Ok") => {
2535                                if let Some(f) = fields {
2536                                    Ok(f.first().cloned().unwrap_or(Value::Null))
2537                                } else {
2538                                    Ok(Value::Null)
2539                                }
2540                            }
2541                            ("Result", "Err") => {
2542                                crate::sigil_debug!("DEBUG Try propagating Result::Err with fields: {:?}", fields);
2543                                let err_msg = if let Some(f) = fields {
2544                                    let first = f.first().cloned().unwrap_or(Value::Null);
2545                                    crate::sigil_debug!("DEBUG Try error first value: {}", first);
2546                                    // Try to get more detail from the error
2547                                    match &first {
2548                                        Value::Struct { name, fields: sf } => {
2549                                            let field_str = sf.borrow().iter()
2550                                                .map(|(k, v)| format!("{}: {}", k, v))
2551                                                .collect::<Vec<_>>()
2552                                                .join(", ");
2553                                            format!("{} {{ {} }}", name, field_str)
2554                                        }
2555                                        Value::Variant { enum_name: en, variant_name: vn, fields: vf } => {
2556                                            let vf_str = vf.as_ref().map(|vs|
2557                                                vs.iter().map(|v| format!("{}", v)).collect::<Vec<_>>().join(", ")
2558                                            ).unwrap_or_default();
2559                                            format!("{}::{} {{ {} }}", en, vn, vf_str)
2560                                        }
2561                                        _ => format!("{}", first)
2562                                    }
2563                                } else {
2564                                    "error".to_string()
2565                                };
2566                                Err(RuntimeError::new(format!("try failed: {}", err_msg)))
2567                            }
2568                            ("Option", "Some") => {
2569                                if let Some(f) = fields {
2570                                    Ok(f.first().cloned().unwrap_or(Value::Null))
2571                                } else {
2572                                    Ok(Value::Null)
2573                                }
2574                            }
2575                            ("Option", "None") => {
2576                                Err(RuntimeError::new("try failed: None"))
2577                            }
2578                            _ => Ok(value), // Not a Result/Option, pass through
2579                        }
2580                    }
2581                    _ => Ok(value), // Not a variant, pass through
2582                }
2583            }
2584            // Cast expression: expr as Type
2585            Expr::Cast { expr, ty } => {
2586                let value = self.evaluate(expr)?;
2587                // Handle type casts
2588                let type_name = match ty {
2589                    TypeExpr::Path(path) => {
2590                        if !path.segments.is_empty() {
2591                            path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("")
2592                        } else {
2593                            ""
2594                        }
2595                    }
2596                    _ => "",
2597                };
2598                match (value, type_name) {
2599                    // Char to numeric
2600                    (Value::Char(c), "u8") => Ok(Value::Int(c as i64)),
2601                    (Value::Char(c), "u16") => Ok(Value::Int(c as i64)),
2602                    (Value::Char(c), "u32") => Ok(Value::Int(c as i64)),
2603                    (Value::Char(c), "u64") => Ok(Value::Int(c as i64)),
2604                    (Value::Char(c), "i8") => Ok(Value::Int(c as i64)),
2605                    (Value::Char(c), "i16") => Ok(Value::Int(c as i64)),
2606                    (Value::Char(c), "i32") => Ok(Value::Int(c as i64)),
2607                    (Value::Char(c), "i64") => Ok(Value::Int(c as i64)),
2608                    (Value::Char(c), "usize") => Ok(Value::Int(c as i64)),
2609                    (Value::Char(c), "isize") => Ok(Value::Int(c as i64)),
2610                    // Int to int (no-op in our runtime)
2611                    (Value::Int(i), "u8") => Ok(Value::Int(i)),
2612                    (Value::Int(i), "u16") => Ok(Value::Int(i)),
2613                    (Value::Int(i), "u32") => Ok(Value::Int(i)),
2614                    (Value::Int(i), "u64") => Ok(Value::Int(i)),
2615                    (Value::Int(i), "i8") => Ok(Value::Int(i)),
2616                    (Value::Int(i), "i16") => Ok(Value::Int(i)),
2617                    (Value::Int(i), "i32") => Ok(Value::Int(i)),
2618                    (Value::Int(i), "i64") => Ok(Value::Int(i)),
2619                    (Value::Int(i), "usize") => Ok(Value::Int(i)),
2620                    (Value::Int(i), "isize") => Ok(Value::Int(i)),
2621                    // Float to int
2622                    (Value::Float(f), "i32") => Ok(Value::Int(f as i64)),
2623                    (Value::Float(f), "i64") => Ok(Value::Int(f as i64)),
2624                    (Value::Float(f), "u32") => Ok(Value::Int(f as i64)),
2625                    (Value::Float(f), "u64") => Ok(Value::Int(f as i64)),
2626                    // Int to float
2627                    (Value::Int(i), "f32") => Ok(Value::Float(i as f64)),
2628                    (Value::Int(i), "f64") => Ok(Value::Float(i as f64)),
2629                    // Int to char
2630                    (Value::Int(i), "char") => {
2631                        if let Some(c) = char::from_u32(i as u32) {
2632                            Ok(Value::Char(c))
2633                        } else {
2634                            Err(RuntimeError::new(format!("invalid char code: {}", i)))
2635                        }
2636                    }
2637                    // Pass through for same type
2638                    (v, _) => Ok(v),
2639                }
2640            }
2641            _ => Err(RuntimeError::new(format!(
2642                "Unsupported expression: {:?}",
2643                expr
2644            ))),
2645        }
2646    }
2647
2648    fn eval_assign(&mut self, target: &Expr, value: &Expr) -> Result<Value, RuntimeError> {
2649        let val = self.evaluate(value)?;
2650
2651        match target {
2652            Expr::Path(path) if path.segments.len() == 1 => {
2653                let name = &path.segments[0].ident.name;
2654                self.environment.borrow_mut().set(name, val.clone())?;
2655                Ok(val)
2656            }
2657            Expr::Index { expr, index } => {
2658                // Array/map index assignment
2659                let idx = self.evaluate(index)?;
2660                let idx = match idx {
2661                    Value::Int(i) => i as usize,
2662                    _ => return Err(RuntimeError::new("Index must be an integer")),
2663                };
2664
2665                // Get the array and modify it
2666                if let Expr::Path(path) = expr.as_ref() {
2667                    if path.segments.len() == 1 {
2668                        let name = &path.segments[0].ident.name;
2669                        let current = self.environment.borrow().get(name).ok_or_else(|| {
2670                            RuntimeError::new(format!("Undefined variable: {}", name))
2671                        })?;
2672
2673                        if let Value::Array(arr) = current {
2674                            let borrowed = arr.borrow();
2675                            let mut new_arr = borrowed.clone();
2676                            drop(borrowed);
2677                            if idx < new_arr.len() {
2678                                new_arr[idx] = val.clone();
2679                                self.environment
2680                                    .borrow_mut()
2681                                    .set(name, Value::Array(Rc::new(RefCell::new(new_arr))))?;
2682                                return Ok(val);
2683                            }
2684                        }
2685                    }
2686                }
2687                Err(RuntimeError::new("Invalid index assignment target"))
2688            }
2689            Expr::Field { expr, field } => {
2690                // Field assignment: struct.field = value
2691                // Need to find the variable and update its field
2692                match expr.as_ref() {
2693                    Expr::Path(path) if path.segments.len() == 1 => {
2694                        let var_name = &path.segments[0].ident.name;
2695                        let current = self.environment.borrow().get(var_name).ok_or_else(|| {
2696                            RuntimeError::new(format!("Undefined variable: {}", var_name))
2697                        })?;
2698
2699                        match current {
2700                            Value::Struct { fields, .. } => {
2701                                fields.borrow_mut().insert(field.name.clone(), val.clone());
2702                                Ok(val)
2703                            }
2704                            Value::Ref(r) => {
2705                                let mut borrowed = r.borrow_mut();
2706                                if let Value::Struct { fields, .. } = &mut *borrowed {
2707                                    fields.borrow_mut().insert(field.name.clone(), val.clone());
2708                                    Ok(val)
2709                                } else {
2710                                    Err(RuntimeError::new("Cannot assign field on non-struct ref"))
2711                                }
2712                            }
2713                            _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
2714                        }
2715                    }
2716                    _ => {
2717                        // For now, just evaluate and try to update (won't persist for non-path exprs)
2718                        let struct_val = self.evaluate(expr)?;
2719                        match struct_val {
2720                            Value::Struct { fields, .. } => {
2721                                fields.borrow_mut().insert(field.name.clone(), val.clone());
2722                                Ok(val)
2723                            }
2724                            Value::Ref(r) => {
2725                                let mut borrowed = r.borrow_mut();
2726                                if let Value::Struct { fields, .. } = &mut *borrowed {
2727                                    fields.borrow_mut().insert(field.name.clone(), val.clone());
2728                                    Ok(val)
2729                                } else {
2730                                    Err(RuntimeError::new("Cannot assign field on non-struct"))
2731                                }
2732                            }
2733                            _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
2734                        }
2735                    }
2736                }
2737            }
2738            Expr::Unary { op: UnaryOp::Deref, expr: inner } => {
2739                // Dereference assignment: *ptr = value (parsed as Unary)
2740                // Handle mutable references (&mut T)
2741                let ptr_val = self.evaluate(inner)?;
2742                match ptr_val {
2743                    Value::Ref(r) => {
2744                        *r.borrow_mut() = val.clone();
2745                        Ok(val)
2746                    }
2747                    _ => Err(RuntimeError::new("Cannot dereference assign to non-reference")),
2748                }
2749            }
2750            Expr::Deref(inner) => {
2751                // Dereference assignment: *ptr = value (parsed as Deref)
2752                // Handle mutable references (&mut T)
2753                let ptr_val = self.evaluate(inner)?;
2754                match ptr_val {
2755                    Value::Ref(r) => {
2756                        *r.borrow_mut() = val.clone();
2757                        Ok(val)
2758                    }
2759                    _ => Err(RuntimeError::new("Cannot dereference assign to non-reference")),
2760                }
2761            }
2762            _ => Err(RuntimeError::new("Invalid assignment target")),
2763        }
2764    }
2765
2766    fn eval_literal(&mut self, lit: &Literal) -> Result<Value, RuntimeError> {
2767        match lit {
2768            Literal::Int { value, base, .. } => {
2769                let n = self.parse_int(value, base)?;
2770                Ok(Value::Int(n))
2771            }
2772            Literal::Float { value, .. } => {
2773                let n: f64 = value
2774                    .parse()
2775                    .map_err(|_| RuntimeError::new(format!("Invalid float: {}", value)))?;
2776                Ok(Value::Float(n))
2777            }
2778            Literal::String(s) => Ok(Value::String(Rc::new(s.clone()))),
2779            Literal::MultiLineString(s) => Ok(Value::String(Rc::new(s.clone()))),
2780            Literal::RawString(s) => Ok(Value::String(Rc::new(s.clone()))),
2781            Literal::ByteString(bytes) => {
2782                // Convert byte array to an array of integers
2783                let arr: Vec<Value> = bytes.iter().map(|&b| Value::Int(b as i64)).collect();
2784                Ok(Value::Array(Rc::new(RefCell::new(arr))))
2785            }
2786            Literal::InterpolatedString { parts } => {
2787                // Evaluate each part and concatenate, tracking evidentiality
2788                let mut result = String::new();
2789                let mut combined_evidence: Option<Evidence> = None;
2790
2791                for part in parts {
2792                    match part {
2793                        InterpolationPart::Text(s) => result.push_str(s),
2794                        InterpolationPart::Expr(expr) => {
2795                            let value = self.evaluate(expr)?;
2796
2797                            // Track explicit evidentiality
2798                            combined_evidence = Self::combine_evidence(
2799                                combined_evidence,
2800                                Self::extract_evidence(&value),
2801                            );
2802
2803                            // Track affect-derived evidentiality (sarcasm, confidence)
2804                            if let Some(affect) = Self::extract_affect(&value) {
2805                                combined_evidence = Self::combine_evidence(
2806                                    combined_evidence,
2807                                    Self::affect_to_evidence(affect),
2808                                );
2809                            }
2810
2811                            // Use the fully unwrapped value for display
2812                            let display_value = Self::unwrap_value(&value);
2813                            result.push_str(&format!("{}", display_value));
2814                        }
2815                    }
2816                }
2817
2818                // Wrap result with evidentiality if any interpolated values were evidential
2819                let string_value = Value::String(Rc::new(result));
2820                match combined_evidence {
2821                    Some(evidence) => Ok(Value::Evidential {
2822                        value: Box::new(string_value),
2823                        evidence,
2824                    }),
2825                    None => Ok(string_value),
2826                }
2827            }
2828            Literal::SigilStringSql(s) => {
2829                // SQL sigil string - for now just return as string
2830                // Future: could add SQL validation or templating
2831                Ok(Value::String(Rc::new(s.clone())))
2832            }
2833            Literal::SigilStringRoute(s) => {
2834                // Route sigil string - for now just return as string
2835                // Future: could add route validation or templating
2836                Ok(Value::String(Rc::new(s.clone())))
2837            }
2838            Literal::Char(c) => Ok(Value::Char(*c)),
2839            Literal::ByteChar(b) => Ok(Value::Int(*b as i64)),
2840            Literal::Bool(b) => Ok(Value::Bool(*b)),
2841            Literal::Null => Ok(Value::Null),
2842            Literal::Empty => Ok(Value::Empty),
2843            Literal::Infinity => Ok(Value::Infinity),
2844            Literal::Circle => Ok(Value::Int(0)), // ◯ = zero
2845        }
2846    }
2847
2848    fn parse_int(&self, value: &str, base: &NumBase) -> Result<i64, RuntimeError> {
2849        let (radix, prefix_len) = match base {
2850            NumBase::Binary => (2, 2), // 0b
2851            NumBase::Octal => (8, 2),  // 0o
2852            NumBase::Decimal => (10, 0),
2853            NumBase::Hex => (16, 2),         // 0x
2854            NumBase::Vigesimal => (20, 2),   // 0v
2855            NumBase::Sexagesimal => (60, 2), // 0s
2856            NumBase::Duodecimal => (12, 2),  // 0z
2857            NumBase::Explicit(b) => (*b as u32, 0),
2858        };
2859
2860        let clean = value[prefix_len..].replace('_', "");
2861        i64::from_str_radix(&clean, radix)
2862            .map_err(|_| RuntimeError::new(format!("Invalid integer: {}", value)))
2863    }
2864
2865    fn eval_path(&self, path: &TypePath) -> Result<Value, RuntimeError> {
2866        if path.segments.len() == 1 {
2867            let name = &path.segments[0].ident.name;
2868            // Look up the variable in the environment
2869            // Note: "_" may be bound by pipe operations (τ, φ, etc.), so we must check
2870            // the environment first before treating it as a wildcard
2871            if let Some(val) = self.environment.borrow().get(name) {
2872                return Ok(val);
2873            }
2874            // Handle wildcard "_" - return Null if not bound
2875            if name == "_" {
2876                return Ok(Value::Null);
2877            }
2878            // Handle "Self" as unit struct constructor (for unit structs like `pub fn new() -> Self { Self }`)
2879            if name == "Self" {
2880                if let Some(ref self_type) = self.current_self_type {
2881                    // Check if the type is a unit struct
2882                    if let Some(TypeDef::Struct(struct_def)) = self.types.get(self_type) {
2883                        if matches!(struct_def.fields, crate::ast::StructFields::Unit) {
2884                            return Ok(Value::Struct {
2885                                name: self_type.clone(),
2886                                fields: Rc::new(RefCell::new(HashMap::new())),
2887                            });
2888                        }
2889                    }
2890                    // If not a unit struct, create empty struct (best effort)
2891                    return Ok(Value::Struct {
2892                        name: self_type.clone(),
2893                        fields: Rc::new(RefCell::new(HashMap::new())),
2894                    });
2895                }
2896            }
2897            if name.len() <= 2 {
2898                crate::sigil_debug!("DEBUG Undefined variable '{}' (len={})", name, name.len());
2899            }
2900            Err(RuntimeError::new(format!("Undefined variable: {}", name)))
2901        } else {
2902            // Multi-segment path (module::item or Type·method)
2903            // Try full qualified name first (joined with ·)
2904            let full_name = path
2905                .segments
2906                .iter()
2907                .map(|s| s.ident.name.as_str())
2908                .collect::<Vec<_>>()
2909                .join("·");
2910
2911            if let Some(val) = self.environment.borrow().get(&full_name) {
2912                return Ok(val);
2913            }
2914
2915            // Check globals for qualified name (for Type::method patterns)
2916            if let Some(val) = self.globals.borrow().get(&full_name) {
2917                return Ok(val);
2918            }
2919
2920            // If in a module context, try current_module·full_name for sibling modules
2921            // e.g., when in samael_cli, "analyze::execute" -> "samael_cli·analyze·execute"
2922            if let Some(ref current_mod) = self.current_module {
2923                // Extract crate name from current_module (e.g., "samael_cli" from "samael_cli·analyze")
2924                let crate_name = current_mod.split('·').next().unwrap_or(current_mod);
2925                let crate_qualified = format!("{}·{}", crate_name, full_name);
2926                if full_name.contains("execute") {
2927                    crate::sigil_debug!("DEBUG eval_path: Looking for '{}' with crate_qualified='{}'", full_name, crate_qualified);
2928                }
2929                if let Some(val) = self.globals.borrow().get(&crate_qualified) {
2930                    crate::sigil_debug!("DEBUG eval_path: FOUND '{}' via crate_qualified", crate_qualified);
2931                    return Ok(val);
2932                }
2933            } else if full_name.contains("execute") {
2934                crate::sigil_debug!("DEBUG eval_path: current_module is None, can't resolve '{}'", full_name);
2935            }
2936
2937            // DEBUG: Check if we're looking for a ::new call
2938            if full_name.ends_with("·new") {
2939                crate::sigil_debug!("DEBUG eval_path: Looking for '{}' - NOT FOUND in globals", full_name);
2940            }
2941
2942            // Check for enum variant syntax FIRST (EnumName::Variant)
2943            // This must come before looking up just the last segment to avoid
2944            // returning a built-in function instead of the actual variant
2945            if path.segments.len() == 2 {
2946                let type_name = &path.segments[0].ident.name;
2947                let variant_name = &path.segments[1].ident.name;
2948
2949                // Check if this is an enum variant (direct type name match)
2950                if let Some(TypeDef::Enum(enum_def)) = self.types.get(type_name) {
2951                    for variant in &enum_def.variants {
2952                        if &variant.name.name == variant_name {
2953                            // Return a variant constructor or unit variant
2954                            if matches!(variant.fields, crate::ast::StructFields::Unit) {
2955                                return Ok(Value::Variant {
2956                                    enum_name: type_name.clone(),
2957                                    variant_name: variant_name.clone(),
2958                                    fields: None,
2959                                });
2960                            }
2961                        }
2962                    }
2963                }
2964
2965                // Fallback: type name might be an alias - search all enums for the variant
2966                for (actual_type_name, type_def) in &self.types {
2967                    if let TypeDef::Enum(enum_def) = type_def {
2968                        for variant in &enum_def.variants {
2969                            if &variant.name.name == variant_name {
2970                                if matches!(variant.fields, crate::ast::StructFields::Unit) {
2971                                    return Ok(Value::Variant {
2972                                        enum_name: actual_type_name.clone(),
2973                                        variant_name: variant_name.clone(),
2974                                        fields: None,
2975                                    });
2976                                }
2977                            }
2978                        }
2979                    }
2980                }
2981            }
2982
2983            // Try looking up the last segment (for Math·sqrt -> sqrt)
2984            let last_name = &path.segments.last().unwrap().ident.name;
2985            if let Some(val) = self.environment.borrow().get(last_name) {
2986                // DEBUG: Warn about fallback for new functions
2987                if last_name == "new" {
2988                    crate::sigil_debug!("DEBUG eval_path: FALLBACK from '{}' to '{}' - found in env", full_name, last_name);
2989                }
2990                return Ok(val);
2991            }
2992
2993            // Handle Self::method - use current_self_type to get the specific type
2994            if path.segments.len() == 2 && path.segments[0].ident.name == "Self" {
2995                if let Some(ref self_type) = self.current_self_type {
2996                    // Look up the specific Type·method function
2997                    let qualified = format!("{}·{}", self_type, last_name);
2998                    if let Some(val) = self.globals.borrow().get(&qualified) {
2999                        return Ok(val);
3000                    }
3001                }
3002            }
3003
3004            // Check for variant constructor in variant_constructors table
3005            if let Some((enum_name, variant_name, arity)) = self.variant_constructors.get(&full_name).cloned() {
3006                // Return a special marker that eval_call can recognize
3007                // For unit variants, return the variant directly
3008                if arity == 0 {
3009                    return Ok(Value::Variant {
3010                        enum_name,
3011                        variant_name,
3012                        fields: None,
3013                    });
3014                }
3015                // For variants with fields, we need to return something callable
3016                // We'll use a special builtin-like marker
3017                // Actually, let's just let eval_call handle it via call_function_by_name
3018            }
3019
3020            // Fallback for unknown types from external crates:
3021            if path.segments.len() == 2 {
3022                let type_name = &path.segments[0].ident.name;
3023                let method_name = &path.segments[1].ident.name;
3024
3025                // Check if this looks like a constructor/method call (lowercase or snake_case)
3026                let is_method = method_name.chars().next().map_or(false, |c| c.is_lowercase())
3027                    || method_name == "new"
3028                    || method_name == "default"
3029                    || method_name == "from"
3030                    || method_name == "try_from"
3031                    || method_name == "into"
3032                    || method_name == "with_capacity"
3033                    || method_name == "from_str";
3034
3035                if is_method {
3036                    // Return a special marker that eval_call will recognize
3037                    // Store the type name in a Struct value with a special marker name
3038                    return Ok(Value::Struct {
3039                        name: format!("__constructor__{}", type_name),
3040                        fields: Rc::new(RefCell::new(HashMap::new())),
3041                    });
3042                } else {
3043                    // Looks like an enum variant (PascalCase) - create unit variant
3044                    return Ok(Value::Variant {
3045                        enum_name: type_name.clone(),
3046                        variant_name: method_name.clone(),
3047                        fields: None,
3048                    });
3049                }
3050            }
3051
3052            Err(RuntimeError::new(format!(
3053                "Undefined: {} (tried {} and {})",
3054                full_name, full_name, last_name
3055            )))
3056        }
3057    }
3058
3059    fn eval_binary(
3060        &mut self,
3061        left: &Expr,
3062        op: &BinOp,
3063        right: &Expr,
3064    ) -> Result<Value, RuntimeError> {
3065        let lhs = self.evaluate(left)?;
3066
3067        // Short-circuit for && and ||
3068        match op {
3069            BinOp::And => {
3070                if !self.is_truthy(&lhs) {
3071                    return Ok(Value::Bool(false));
3072                }
3073                let rhs = self.evaluate(right)?;
3074                return Ok(Value::Bool(self.is_truthy(&rhs)));
3075            }
3076            BinOp::Or => {
3077                if self.is_truthy(&lhs) {
3078                    return Ok(Value::Bool(true));
3079                }
3080                let rhs = self.evaluate(right)?;
3081                return Ok(Value::Bool(self.is_truthy(&rhs)));
3082            }
3083            _ => {}
3084        }
3085
3086        let rhs = self.evaluate(right)?;
3087
3088        // Unwrap all wrappers (evidential/affective/ref) for binary operations
3089        let lhs = Self::unwrap_all(&lhs);
3090        let rhs = Self::unwrap_all(&rhs);
3091
3092        // Debug Mul operations involving potential null
3093        if matches!(op, BinOp::Mul) && (matches!(lhs, Value::Null) || matches!(rhs, Value::Null) || matches!(lhs, Value::Struct { .. }) || matches!(rhs, Value::Struct { .. })) {
3094            crate::sigil_debug!("DEBUG eval_binary Mul: left={:?}, right={:?}", left, right);
3095            crate::sigil_debug!("DEBUG eval_binary Mul: lhs={}, rhs={}", self.format_value(&lhs), self.format_value(&rhs));
3096        }
3097
3098        match (lhs, rhs) {
3099            (Value::Int(a), Value::Int(b)) => self.int_binary_op(a, b, op),
3100            (Value::Float(a), Value::Float(b)) => self.float_binary_op(a, b, op),
3101            (Value::Int(a), Value::Float(b)) => self.float_binary_op(a as f64, b, op),
3102            (Value::Float(a), Value::Int(b)) => self.float_binary_op(a, b as f64, op),
3103            (Value::String(a), Value::String(b)) => match op {
3104                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
3105                BinOp::Eq => Ok(Value::Bool(*a == *b)),
3106                BinOp::Ne => Ok(Value::Bool(*a != *b)),
3107                _ => Err(RuntimeError::new("Invalid string operation")),
3108            },
3109            (Value::Bool(a), Value::Bool(b)) => match op {
3110                BinOp::Eq => Ok(Value::Bool(a == b)),
3111                BinOp::Ne => Ok(Value::Bool(a != b)),
3112                _ => Err(RuntimeError::new("Invalid boolean operation")),
3113            },
3114            (Value::Array(a), Value::Array(b)) => match op {
3115                BinOp::Concat => {
3116                    let mut result = a.borrow().clone();
3117                    result.extend(b.borrow().iter().cloned());
3118                    Ok(Value::Array(Rc::new(RefCell::new(result))))
3119                }
3120                BinOp::Eq => Ok(Value::Bool(Rc::ptr_eq(&a, &b))),
3121                BinOp::Ne => Ok(Value::Bool(!Rc::ptr_eq(&a, &b))),
3122                _ => Err(RuntimeError::new("Invalid array operation")),
3123            },
3124            // Null equality
3125            (Value::Null, Value::Null) => match op {
3126                BinOp::Eq => Ok(Value::Bool(true)),
3127                BinOp::Ne => Ok(Value::Bool(false)),
3128                _ => {
3129                    crate::sigil_debug!("DEBUG: null op {:?} on (Null, Null)", op);
3130                    Err(RuntimeError::new(format!("Invalid null operation: {:?} on (Null, Null)", op)))
3131                }
3132            },
3133            (Value::Null, other) | (other, Value::Null) => match op {
3134                BinOp::Eq => Ok(Value::Bool(false)),
3135                BinOp::Ne => Ok(Value::Bool(true)),
3136                _ => {
3137                    crate::sigil_debug!("DEBUG: null op {:?} with other={}", op, self.format_value(&other));
3138                    Err(RuntimeError::new(format!("Invalid null operation: {:?}", op)))
3139                }
3140            },
3141            // Char comparisons
3142            (Value::Char(a), Value::Char(b)) => match op {
3143                BinOp::Eq => Ok(Value::Bool(a == b)),
3144                BinOp::Ne => Ok(Value::Bool(a != b)),
3145                BinOp::Lt => Ok(Value::Bool(a < b)),
3146                BinOp::Le => Ok(Value::Bool(a <= b)),
3147                BinOp::Gt => Ok(Value::Bool(a > b)),
3148                BinOp::Ge => Ok(Value::Bool(a >= b)),
3149                _ => Err(RuntimeError::new("Invalid char operation")),
3150            },
3151            // String and char operations
3152            (Value::String(a), Value::Char(b)) => match op {
3153                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
3154                _ => Err(RuntimeError::new("Invalid string/char operation")),
3155            },
3156            (Value::Char(a), Value::String(b)) => match op {
3157                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
3158                _ => Err(RuntimeError::new("Invalid char/string operation")),
3159            },
3160            // Variant equality
3161            (Value::Variant { enum_name: e1, variant_name: v1, fields: f1 },
3162             Value::Variant { enum_name: e2, variant_name: v2, fields: f2 }) => match op {
3163                BinOp::Eq => {
3164                    let eq = e1 == e2 && v1 == v2 && match (f1, f2) {
3165                        (None, None) => true,
3166                        (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
3167                        _ => false,
3168                    };
3169                    Ok(Value::Bool(eq))
3170                }
3171                BinOp::Ne => {
3172                    let eq = e1 == e2 && v1 == v2 && match (f1, f2) {
3173                        (None, None) => true,
3174                        (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
3175                        _ => false,
3176                    };
3177                    Ok(Value::Bool(!eq))
3178                }
3179                _ => Err(RuntimeError::new("Invalid variant operation")),
3180            },
3181            // Struct equality (by reference)
3182            (Value::Struct { name: n1, fields: f1 }, Value::Struct { name: n2, fields: f2 }) => match op {
3183                BinOp::Eq => Ok(Value::Bool(n1 == n2 && Rc::ptr_eq(&f1, &f2))),
3184                BinOp::Ne => Ok(Value::Bool(n1 != n2 || !Rc::ptr_eq(&f1, &f2))),
3185                _ => Err(RuntimeError::new("Invalid struct operation")),
3186            },
3187            (l, r) => Err(RuntimeError::new(format!(
3188                "Type mismatch in binary operation: {:?} {:?} {:?}",
3189                l, op, r
3190            ))),
3191        }
3192    }
3193
3194    fn int_binary_op(&self, a: i64, b: i64, op: &BinOp) -> Result<Value, RuntimeError> {
3195        Ok(match op {
3196            BinOp::Add => Value::Int(a + b),
3197            BinOp::Sub => Value::Int(a - b),
3198            BinOp::Mul => Value::Int(a * b),
3199            BinOp::Div => {
3200                if b == 0 {
3201                    return Err(RuntimeError::new("Division by zero"));
3202                }
3203                Value::Int(a / b)
3204            }
3205            BinOp::Rem => {
3206                if b == 0 {
3207                    return Err(RuntimeError::new("Division by zero"));
3208                }
3209                Value::Int(a % b)
3210            }
3211            BinOp::Pow => Value::Int(a.pow(b as u32)),
3212            BinOp::Eq => Value::Bool(a == b),
3213            BinOp::Ne => Value::Bool(a != b),
3214            BinOp::Lt => Value::Bool(a < b),
3215            BinOp::Le => Value::Bool(a <= b),
3216            BinOp::Gt => Value::Bool(a > b),
3217            BinOp::Ge => Value::Bool(a >= b),
3218            BinOp::BitAnd => Value::Int(a & b),
3219            BinOp::BitOr => Value::Int(a | b),
3220            BinOp::BitXor => Value::Int(a ^ b),
3221            BinOp::Shl => Value::Int(a << b),
3222            BinOp::Shr => Value::Int(a >> b),
3223            _ => return Err(RuntimeError::new("Invalid integer operation")),
3224        })
3225    }
3226
3227    fn float_binary_op(&self, a: f64, b: f64, op: &BinOp) -> Result<Value, RuntimeError> {
3228        Ok(match op {
3229            BinOp::Add => Value::Float(a + b),
3230            BinOp::Sub => Value::Float(a - b),
3231            BinOp::Mul => Value::Float(a * b),
3232            BinOp::Div => Value::Float(a / b),
3233            BinOp::Rem => Value::Float(a % b),
3234            BinOp::Pow => Value::Float(a.powf(b)),
3235            BinOp::Eq => Value::Bool((a - b).abs() < f64::EPSILON),
3236            BinOp::Ne => Value::Bool((a - b).abs() >= f64::EPSILON),
3237            BinOp::Lt => Value::Bool(a < b),
3238            BinOp::Le => Value::Bool(a <= b),
3239            BinOp::Gt => Value::Bool(a > b),
3240            BinOp::Ge => Value::Bool(a >= b),
3241            _ => return Err(RuntimeError::new("Invalid float operation")),
3242        })
3243    }
3244
3245    fn eval_unary(&mut self, op: &UnaryOp, expr: &Expr) -> Result<Value, RuntimeError> {
3246        let val = self.evaluate(expr)?;
3247        match (op, &val) {
3248            (UnaryOp::Neg, Value::Int(n)) => Ok(Value::Int(-n)),
3249            (UnaryOp::Neg, Value::Float(n)) => Ok(Value::Float(-n)),
3250            (UnaryOp::Not, Value::Bool(b)) => Ok(Value::Bool(!b)),
3251            (UnaryOp::Not, Value::Int(n)) => Ok(Value::Int(!n)),
3252            // Handle evidential values - unwrap, negate, rewrap
3253            (UnaryOp::Not, Value::Evidential { value, evidence }) => {
3254                // Negate the inner value
3255                match value.as_ref() {
3256                    Value::Bool(b) => Ok(Value::Evidential {
3257                        value: Box::new(Value::Bool(!b)),
3258                        evidence: evidence.clone(),
3259                    }),
3260                    other => {
3261                        let truthy = self.is_truthy(other);
3262                        Ok(Value::Evidential {
3263                            value: Box::new(Value::Bool(!truthy)),
3264                            evidence: evidence.clone(),
3265                        })
3266                    }
3267                }
3268            }
3269            // Handle string truthiness (non-empty = true)
3270            (UnaryOp::Not, Value::String(s)) => Ok(Value::Bool(s.is_empty())),
3271            // Handle array truthiness (non-empty = true)
3272            (UnaryOp::Not, Value::Array(arr)) => Ok(Value::Bool(arr.borrow().is_empty())),
3273            // Handle null - null is falsy
3274            (UnaryOp::Not, Value::Null) => Ok(Value::Bool(true)),
3275            (UnaryOp::Ref, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
3276            (UnaryOp::RefMut, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
3277            (UnaryOp::Deref, Value::Ref(r)) => Ok(r.borrow().clone()),
3278            (UnaryOp::Deref, Value::Struct { name, fields }) if name == "Rc" => {
3279                // Deref Rc to get inner value
3280                let borrowed = fields.borrow();
3281                if let Some(value) = borrowed.get("_value") {
3282                    Ok(value.clone())
3283                } else {
3284                    Err(RuntimeError::new("Rc has no value"))
3285                }
3286            }
3287            (UnaryOp::Deref, other) => {
3288                // Try to unwrap evidential/affective wrappers and deref
3289                let unwrapped = Self::unwrap_all(&val);
3290                if let Value::Ref(r) = &unwrapped {
3291                    return Ok(r.borrow().clone());
3292                }
3293                // For non-ref types in interpreted code, just return the value as-is
3294                // (dereferencing a copy type in Sigil is a no-op)
3295                Ok(unwrapped)
3296            }
3297            _ => Err(RuntimeError::new(format!("Invalid unary {:?} on {:?}", op, std::mem::discriminant(&val)))),
3298        }
3299    }
3300
3301    fn eval_call(&mut self, func_expr: &Expr, args: &[Expr]) -> Result<Value, RuntimeError> {
3302        // Check if func_expr is a path that might be a variant constructor or tuple struct
3303        if let Expr::Path(path) = func_expr {
3304            let qualified_name = path.segments.iter()
3305                .map(|s| s.ident.name.as_str())
3306                .collect::<Vec<_>>()
3307                .join("·");
3308
3309            // Handle Self(...) as tuple struct constructor
3310            if qualified_name == "Self" {
3311                if let Some(ref self_type) = self.current_self_type {
3312                    // Check if this type is a tuple struct - extract arity first to release borrow
3313                    let tuple_arity = if let Some(TypeDef::Struct(struct_def)) = self.types.get(self_type) {
3314                        if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
3315                            Some((self_type.clone(), field_types.len()))
3316                        } else {
3317                            None
3318                        }
3319                    } else {
3320                        None
3321                    };
3322
3323                    if let Some((type_name, expected_arity)) = tuple_arity {
3324                        // Now we can safely evaluate arguments
3325                        let arg_values: Vec<Value> = args
3326                            .iter()
3327                            .map(|a| self.evaluate(a))
3328                            .collect::<Result<_, _>>()?;
3329
3330                        if arg_values.len() != expected_arity {
3331                            return Err(RuntimeError::new(format!(
3332                                "Tuple struct {} expects {} fields, got {}",
3333                                type_name, expected_arity, arg_values.len()
3334                            )));
3335                        }
3336
3337                        // Create struct with numbered fields (0, 1, 2, ...)
3338                        let mut fields = HashMap::new();
3339                        for (i, value) in arg_values.into_iter().enumerate() {
3340                            fields.insert(i.to_string(), value);
3341                        }
3342                        return Ok(Value::Struct {
3343                            name: type_name,
3344                            fields: Rc::new(RefCell::new(fields)),
3345                        });
3346                    }
3347                }
3348            }
3349
3350            // Handle TypeName(...) as tuple struct constructor
3351            if path.segments.len() == 1 {
3352                let type_name = &path.segments[0].ident.name;
3353                // Extract arity first to release borrow
3354                let tuple_arity = if let Some(TypeDef::Struct(struct_def)) = self.types.get(type_name) {
3355                    if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
3356                        Some((type_name.clone(), field_types.len()))
3357                    } else {
3358                        None
3359                    }
3360                } else {
3361                    None
3362                };
3363
3364                if let Some((struct_name, expected_arity)) = tuple_arity {
3365                    let arg_values: Vec<Value> = args
3366                        .iter()
3367                        .map(|a| self.evaluate(a))
3368                        .collect::<Result<_, _>>()?;
3369
3370                    if arg_values.len() != expected_arity {
3371                        return Err(RuntimeError::new(format!(
3372                            "Tuple struct {} expects {} fields, got {}",
3373                            struct_name, expected_arity, arg_values.len()
3374                        )));
3375                    }
3376
3377                    let mut fields = HashMap::new();
3378                    for (i, value) in arg_values.into_iter().enumerate() {
3379                        fields.insert(i.to_string(), value);
3380                    }
3381                    return Ok(Value::Struct {
3382                        name: struct_name,
3383                        fields: Rc::new(RefCell::new(fields)),
3384                    });
3385                }
3386            }
3387
3388            // Handle Default::default() when current_self_type is set
3389            // This allows ..Default::default() to work in struct literals
3390            if qualified_name == "Default·default" && args.is_empty() {
3391                if let Some(type_name) = self.current_self_type.clone() {
3392                    // First check if type has impl Default with explicit default fn
3393                    let default_fn_name = format!("{}·default", type_name);
3394                    crate::sigil_debug!("DEBUG Default::default() looking for '{}', self_type='{}'", default_fn_name, type_name);
3395                    let func_clone = self.globals.borrow().get(&default_fn_name).map(|v| v.clone());
3396                    if let Some(Value::Function(f)) = func_clone {
3397                        crate::sigil_debug!("DEBUG Found function '{}', calling it", default_fn_name);
3398                        crate::sigil_debug!("DEBUG current_self_type before call: {:?}", self.current_self_type);
3399                        // Call the type's default implementation
3400                        let result = self.call_function(&f, vec![]);
3401                        crate::sigil_debug!("DEBUG Default call result: {:?}", result.as_ref().map(|v| self.format_value(v)).unwrap_or_else(|e| format!("ERR: {:?}", e)));
3402                        return result;
3403                    }
3404                    // Otherwise check for #[derive(Default)]
3405                    if let Some(struct_def) = self.default_structs.get(&type_name).cloned() {
3406                        let mut fields = HashMap::new();
3407                        if let StructFields::Named(field_defs) = &struct_def.fields {
3408                            for field in field_defs {
3409                                let default_val = if let Some(default_expr) = &field.default {
3410                                    self.evaluate(default_expr)?
3411                                } else {
3412                                    Value::Null
3413                                };
3414                                fields.insert(field.name.name.clone(), default_val);
3415                            }
3416                        }
3417                        return Ok(Value::Struct {
3418                            name: type_name,
3419                            fields: Rc::new(RefCell::new(fields)),
3420                        });
3421                    }
3422                }
3423            }
3424
3425            // Check for TypeName·default pattern
3426            if qualified_name.ends_with("·default") && args.is_empty() {
3427                let type_name = qualified_name.strip_suffix("·default").unwrap();
3428                // First check if type has impl Default with explicit default fn
3429                let default_fn_name = format!("{}·default", type_name);
3430                let func_clone = self.globals.borrow().get(&default_fn_name).map(|v| v.clone());
3431                if let Some(Value::Function(f)) = func_clone {
3432                    // Call the type's default implementation
3433                    return self.call_function(&f, vec![]);
3434                }
3435                // Otherwise check for #[derive(Default)]
3436                if let Some(struct_def) = self.default_structs.get(type_name).cloned() {
3437                    let mut fields = HashMap::new();
3438                    if let StructFields::Named(field_defs) = &struct_def.fields {
3439                        for field in field_defs {
3440                            let default_val = if let Some(default_expr) = &field.default {
3441                                self.evaluate(default_expr)?
3442                            } else {
3443                                // No default - use null for optional/uncertain types
3444                                Value::Null
3445                            };
3446                            fields.insert(field.name.name.clone(), default_val);
3447                        }
3448                    }
3449                    return Ok(Value::Struct {
3450                        name: type_name.to_string(),
3451                        fields: Rc::new(RefCell::new(fields)),
3452                    });
3453                }
3454            }
3455
3456            // Check variant constructors
3457            if let Some((enum_name, variant_name, arity)) = self.variant_constructors.get(&qualified_name).cloned() {
3458                let arg_values: Vec<Value> = args
3459                    .iter()
3460                    .map(|a| self.evaluate(a))
3461                    .collect::<Result<_, _>>()?;
3462
3463                if arg_values.len() != arity {
3464                    return Err(RuntimeError::new(format!(
3465                        "{} expects {} arguments, got {}",
3466                        qualified_name, arity, arg_values.len()
3467                    )));
3468                }
3469
3470                if arity == 0 {
3471                    return Ok(Value::Variant {
3472                        enum_name,
3473                        variant_name,
3474                        fields: None,
3475                    });
3476                } else {
3477                    if enum_name == "Item" {
3478                        crate::sigil_debug!("DEBUG creating Item::{} variant with {} fields", variant_name, arg_values.len());
3479                    }
3480                    return Ok(Value::Variant {
3481                        enum_name,
3482                        variant_name,
3483                        fields: Some(Rc::new(arg_values)),
3484                    });
3485                }
3486            }
3487
3488            // Check for built-in type constructors (Map::new, String::new, HashMap::new, etc.)
3489            let segments: Vec<&str> = path.segments.iter().map(|s| s.ident.name.as_str()).collect();
3490            match segments.as_slice() {
3491                ["Map", "new"] | ["HashMap", "new"] => {
3492                    // Create a new empty Map (represented as a struct with HashMap fields)
3493                    return Ok(Value::Struct {
3494                        name: "Map".to_string(),
3495                        fields: Rc::new(RefCell::new(HashMap::new())),
3496                    });
3497                }
3498                ["String", "new"] => {
3499                    return Ok(Value::String(Rc::new(String::new())));
3500                }
3501                ["Vec", "new"] | ["Array", "new"] => {
3502                    return Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))));
3503                }
3504                ["Box", "new"] => {
3505                    // Box::new(value) - just return the value (no heap allocation in interpreter)
3506                    if args.len() == 1 {
3507                        return self.evaluate(&args[0]);
3508                    }
3509                    return Err(RuntimeError::new("Box::new expects 1 argument"));
3510                }
3511                ["char", "from_u32"] => {
3512                    // char::from_u32(u32) -> Option<char>
3513                    if args.len() == 1 {
3514                        let arg = self.evaluate(&args[0])?;
3515                        let code = match arg {
3516                            Value::Int(i) => i as u32,
3517                            _ => return Err(RuntimeError::new("char::from_u32 expects u32")),
3518                        };
3519                        if let Some(c) = char::from_u32(code) {
3520                            // Return Some(char)
3521                            return Ok(Value::Variant {
3522                                enum_name: "Option".to_string(),
3523                                variant_name: "Some".to_string(),
3524                                fields: Some(Rc::new(vec![Value::Char(c)])),
3525                            });
3526                        } else {
3527                            // Return None
3528                            return Ok(Value::Variant {
3529                                enum_name: "Option".to_string(),
3530                                variant_name: "None".to_string(),
3531                                fields: None,
3532                            });
3533                        }
3534                    }
3535                    return Err(RuntimeError::new("char::from_u32 expects 1 argument"));
3536                }
3537                // Mutex::new - create a mutex wrapper around a value
3538                ["parking_lot", "Mutex", "new"] | ["std", "sync", "Mutex", "new"] | ["Mutex", "new"] => {
3539                    if args.len() == 1 {
3540                        let inner = self.evaluate(&args[0])?;
3541                        return Ok(Value::Struct {
3542                            name: "Mutex".to_string(),
3543                            fields: Rc::new(RefCell::new(HashMap::from([
3544                                ("__inner__".to_string(), inner),
3545                            ]))),
3546                        });
3547                    }
3548                    return Err(RuntimeError::new("Mutex::new expects 1 argument"));
3549                }
3550                // RwLock::new - same as Mutex for interpreter purposes
3551                ["parking_lot", "RwLock", "new"] | ["std", "sync", "RwLock", "new"] | ["RwLock", "new"] => {
3552                    if args.len() == 1 {
3553                        let inner = self.evaluate(&args[0])?;
3554                        return Ok(Value::Struct {
3555                            name: "RwLock".to_string(),
3556                            fields: Rc::new(RefCell::new(HashMap::from([
3557                                ("__inner__".to_string(), inner),
3558                            ]))),
3559                        });
3560                    }
3561                    return Err(RuntimeError::new("RwLock::new expects 1 argument"));
3562                }
3563                // Arc::new - just wrap the value (no real reference counting in interpreter)
3564                ["std", "sync", "Arc", "new"] | ["Arc", "new"] => {
3565                    if args.len() == 1 {
3566                        let inner = self.evaluate(&args[0])?;
3567                        return Ok(Value::Ref(Rc::new(RefCell::new(inner))));
3568                    }
3569                    return Err(RuntimeError::new("Arc::new expects 1 argument"));
3570                }
3571                // AtomicU64::new and similar atomics
3572                ["std", "sync", "atomic", "AtomicU64", "new"] | ["AtomicU64", "new"] => {
3573                    if args.len() == 1 {
3574                        let inner = self.evaluate(&args[0])?;
3575                        return Ok(Value::Struct {
3576                            name: "AtomicU64".to_string(),
3577                            fields: Rc::new(RefCell::new(HashMap::from([
3578                                ("__value__".to_string(), inner),
3579                            ]))),
3580                        });
3581                    }
3582                    return Err(RuntimeError::new("AtomicU64::new expects 1 argument"));
3583                }
3584                ["std", "sync", "atomic", "AtomicUsize", "new"] | ["AtomicUsize", "new"] => {
3585                    if args.len() == 1 {
3586                        let inner = self.evaluate(&args[0])?;
3587                        return Ok(Value::Struct {
3588                            name: "AtomicUsize".to_string(),
3589                            fields: Rc::new(RefCell::new(HashMap::from([
3590                                ("__value__".to_string(), inner),
3591                            ]))),
3592                        });
3593                    }
3594                    return Err(RuntimeError::new("AtomicUsize::new expects 1 argument"));
3595                }
3596                ["std", "sync", "atomic", "AtomicBool", "new"] | ["AtomicBool", "new"] => {
3597                    if args.len() == 1 {
3598                        let inner = self.evaluate(&args[0])?;
3599                        return Ok(Value::Struct {
3600                            name: "AtomicBool".to_string(),
3601                            fields: Rc::new(RefCell::new(HashMap::from([
3602                                ("__value__".to_string(), inner),
3603                            ]))),
3604                        });
3605                    }
3606                    return Err(RuntimeError::new("AtomicBool::new expects 1 argument"));
3607                }
3608                _ => {}
3609            }
3610        }
3611
3612        // If calling a qualified function (Type::method), set current_self_type
3613        let type_name_for_self = if let Expr::Path(path) = func_expr {
3614            if path.segments.len() >= 2 {
3615                // First segment is the type name
3616                let first = &path.segments[0].ident.name;
3617                // Check if it's a type name (exists in types registry)
3618                if self.types.contains_key(first) {
3619                    Some(first.clone())
3620                } else {
3621                    None
3622                }
3623            } else {
3624                None
3625            }
3626        } else {
3627            None
3628        };
3629
3630        let func = self.evaluate(func_expr)?;
3631
3632        // Track &mut path arguments for sync-back after function call
3633        // This enables proper mutable reference semantics where modifications persist
3634        let mut mut_ref_sync: Vec<(String, Rc<RefCell<Value>>)> = Vec::new();
3635
3636        let mut arg_values: Vec<Value> = Vec::new();
3637        for arg in args.iter() {
3638            let val = self.evaluate(arg)?;
3639
3640            // If this was a &mut path expression, track it for sync-back
3641            if let Expr::Unary { op: crate::ast::UnaryOp::RefMut, expr } = arg {
3642                if let Expr::Path(path) = expr.as_ref() {
3643                    if path.segments.len() == 1 {
3644                        let var_name = path.segments[0].ident.name.clone();
3645                        if let Value::Ref(r) = &val {
3646                            mut_ref_sync.push((var_name, r.clone()));
3647                        }
3648                    }
3649                }
3650            }
3651
3652            arg_values.push(val);
3653        }
3654
3655        // Set Self type if we're calling a type-associated function
3656        // Use clone instead of take to preserve for nested calls that don't set a type
3657        let old_self_type = self.current_self_type.clone();
3658        if let Some(type_name) = type_name_for_self {
3659            self.current_self_type = Some(type_name);
3660        }
3661
3662        let result = match func {
3663            Value::Function(f) => self.call_function(&f, arg_values),
3664            Value::BuiltIn(b) => self.call_builtin(&b, arg_values),
3665            // Handle constructor markers for unknown external types
3666            Value::Struct { ref name, .. } if name.starts_with("__constructor__") => {
3667                let actual_type = name.strip_prefix("__constructor__").unwrap();
3668                // Create an empty struct for the unknown type
3669                Ok(Value::Struct {
3670                    name: actual_type.to_string(),
3671                    fields: Rc::new(RefCell::new(HashMap::new())),
3672                })
3673            }
3674            _ => {
3675                crate::sigil_debug!("DEBUG Cannot call non-function: {:?}, expr: {:?}", func, func_expr);
3676                Err(RuntimeError::new("Cannot call non-function"))
3677            }
3678        };
3679
3680        // Sync mutable references back to original variables
3681        // This is what makes `fn foo(x: &mut T)` actually modify the caller's variable
3682        for (var_name, ref_val) in mut_ref_sync {
3683            let current_value = ref_val.borrow().clone();
3684            let _ = self.environment.borrow_mut().set(&var_name, current_value);
3685        }
3686
3687        // Restore old Self type
3688        self.current_self_type = old_self_type;
3689
3690        result
3691    }
3692
3693    pub fn call_function(
3694        &mut self,
3695        func: &Function,
3696        args: Vec<Value>,
3697    ) -> Result<Value, RuntimeError> {
3698        // Debug trace for relevant functions
3699        if func.name.as_ref().map_or(false, |n| n.contains("read_source") || n.contains("parse_file") || n.contains("load_from_file") || n.contains("read_to_string")) {
3700            crate::sigil_debug!("DEBUG call_function: name={:?}, params={:?}", func.name, func.params);
3701            for (i, arg) in args.iter().enumerate() {
3702                crate::sigil_debug!("  arg[{}] = {:?}", i, arg);
3703            }
3704        }
3705        if args.len() != func.params.len() {
3706            return Err(RuntimeError::new(format!(
3707                "Expected {} arguments, got {} (func={:?}, params={:?})",
3708                func.params.len(),
3709                args.len(),
3710                func.name,
3711                func.params
3712            )));
3713        }
3714
3715        // Debug: trace calls to keyword_or_ident
3716        if func.params.iter().any(|p| p == "name") {
3717            for arg in &args {
3718                let unwrapped = Self::unwrap_all(arg);
3719                if let Value::String(s) = &unwrapped {
3720                    if s.len() <= 10 {
3721                        crate::sigil_debug!("DEBUG call_function(name='{}')", s);
3722                    }
3723                }
3724            }
3725        }
3726
3727        // Create new environment for function
3728        let env = Rc::new(RefCell::new(Environment::with_parent(func.closure.clone())));
3729
3730        // Bind parameters
3731        for (param, value) in func.params.iter().zip(args) {
3732            // Debug: trace path parameter binding
3733            if param == "path" {
3734                crate::sigil_debug!("DEBUG call_function func={:?} binding param 'path' = {:?}", func.name, value);
3735            }
3736            env.borrow_mut().define(param.clone(), value);
3737        }
3738
3739        // Execute function body
3740        let prev_env = self.environment.clone();
3741        self.environment = env;
3742
3743        let result = match self.evaluate(&func.body) {
3744            Ok(val) => Ok(val),
3745            Err(e) if e.message == "return" => {
3746                // Extract return value from stored location
3747                Ok(self.return_value.take().unwrap_or(Value::Null))
3748            }
3749            Err(e) => Err(e),
3750        };
3751
3752        self.environment = prev_env;
3753        result
3754    }
3755
3756    fn call_builtin(
3757        &mut self,
3758        builtin: &BuiltInFn,
3759        args: Vec<Value>,
3760    ) -> Result<Value, RuntimeError> {
3761        if let Some(arity) = builtin.arity {
3762            if args.len() != arity {
3763                return Err(RuntimeError::new(format!(
3764                    "{}() expects {} arguments, got {}",
3765                    builtin.name,
3766                    arity,
3767                    args.len()
3768                )));
3769            }
3770        }
3771        (builtin.func)(self, args)
3772    }
3773
3774    /// Await a value - if it's a future, resolve it; otherwise return as-is
3775    pub fn await_value(&mut self, value: Value) -> Result<Value, RuntimeError> {
3776        match value {
3777            Value::Future(fut) => {
3778                let mut fut_inner = fut.borrow_mut();
3779                self.poll_future(&mut fut_inner)
3780            }
3781            // Non-futures return immediately
3782            other => Ok(other),
3783        }
3784    }
3785
3786    /// Unwrap a Result or Option value with configurable error handling
3787    /// - propagate_errors: if true, return error on Err/None; if false, just unwrap
3788    /// - panic_on_error: if true, panic instead of returning error
3789    fn unwrap_result_or_option(
3790        &self,
3791        value: Value,
3792        propagate_errors: bool,
3793        panic_on_error: bool,
3794    ) -> Result<Value, RuntimeError> {
3795        // First, determine what kind of value we have and extract any inner value
3796        let (is_ok_or_some, is_err, is_none, inner_val) = match &value {
3797            Value::Struct { name, fields } if name == "Ok" || name == "Some" => {
3798                let borrowed = fields.borrow();
3799                let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
3800                (true, false, false, inner)
3801            }
3802            Value::Struct { name, fields } if name == "Err" => {
3803                let borrowed = fields.borrow();
3804                let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
3805                (false, true, false, inner)
3806            }
3807            Value::Struct { name, .. } if name == "None" => (false, false, true, None),
3808            _ => return Ok(value),
3809        };
3810
3811        if is_ok_or_some {
3812            Ok(inner_val.unwrap_or(value))
3813        } else if is_err {
3814            let msg = format!("Error: {:?}", inner_val);
3815            if panic_on_error {
3816                panic!("{}", msg);
3817            } else if propagate_errors {
3818                Err(RuntimeError::new(msg))
3819            } else {
3820                Ok(inner_val.unwrap_or(value))
3821            }
3822        } else if is_none {
3823            if panic_on_error {
3824                panic!("Unwrapped None");
3825            } else if propagate_errors {
3826                Err(RuntimeError::new("Unwrapped None".to_string()))
3827            } else {
3828                Ok(value)
3829            }
3830        } else {
3831            Ok(value)
3832        }
3833    }
3834
3835    /// Poll a future to completion
3836    fn poll_future(&mut self, fut: &mut FutureInner) -> Result<Value, RuntimeError> {
3837        // Check if already resolved
3838        match &fut.state {
3839            FutureState::Ready(v) => return Ok((**v).clone()),
3840            FutureState::Failed(e) => return Err(RuntimeError::new(e.clone())),
3841            _ => {}
3842        }
3843
3844        // Check if it's a timer future
3845        if let Some(complete_at) = fut.complete_at {
3846            if std::time::Instant::now() >= complete_at {
3847                fut.state = FutureState::Ready(Box::new(Value::Null));
3848                return Ok(Value::Null);
3849            } else {
3850                // Timer not complete - in interpreter, we just sleep
3851                let remaining = complete_at - std::time::Instant::now();
3852                std::thread::sleep(remaining);
3853                fut.state = FutureState::Ready(Box::new(Value::Null));
3854                return Ok(Value::Null);
3855            }
3856        }
3857
3858        // Execute computation if pending
3859        if let Some(computation) = fut.computation.take() {
3860            fut.state = FutureState::Running;
3861
3862            match computation {
3863                FutureComputation::Immediate(v) => {
3864                    fut.state = FutureState::Ready(v.clone());
3865                    Ok((*v).clone())
3866                }
3867                FutureComputation::Timer(duration) => {
3868                    // Sleep for the duration
3869                    std::thread::sleep(duration);
3870                    fut.state = FutureState::Ready(Box::new(Value::Null));
3871                    Ok(Value::Null)
3872                }
3873                FutureComputation::Lazy { func, args } => {
3874                    // Execute the function
3875                    match self.call_function(&func, args) {
3876                        Ok(result) => {
3877                            fut.state = FutureState::Ready(Box::new(result.clone()));
3878                            Ok(result)
3879                        }
3880                        Err(e) => {
3881                            fut.state = FutureState::Failed(e.message.clone());
3882                            Err(e)
3883                        }
3884                    }
3885                }
3886                FutureComputation::Join(futures) => {
3887                    // Await all futures and collect results
3888                    let mut results = Vec::new();
3889                    for f in futures {
3890                        let mut f_inner = f.borrow_mut();
3891                        results.push(self.poll_future(&mut f_inner)?);
3892                    }
3893                    let result = Value::Array(Rc::new(RefCell::new(results)));
3894                    fut.state = FutureState::Ready(Box::new(result.clone()));
3895                    Ok(result)
3896                }
3897                FutureComputation::Race(futures) => {
3898                    // Return first completed future
3899                    // In interpreter, just poll in order
3900                    for f in futures {
3901                        let f_inner = f.borrow_mut();
3902                        if matches!(f_inner.state, FutureState::Ready(_)) {
3903                            if let FutureState::Ready(v) = &f_inner.state {
3904                                fut.state = FutureState::Ready(v.clone());
3905                                return Ok((**v).clone());
3906                            }
3907                        }
3908                    }
3909                    // None ready, poll first one
3910                    Err(RuntimeError::new("No futures ready in race"))
3911                }
3912            }
3913        } else {
3914            // No computation - return current state
3915            match &fut.state {
3916                FutureState::Ready(v) => Ok((**v).clone()),
3917                FutureState::Failed(e) => Err(RuntimeError::new(e.clone())),
3918                _ => Err(RuntimeError::new("Future has no computation")),
3919            }
3920        }
3921    }
3922
3923    /// Create a new future from a value
3924    pub fn make_future_immediate(&self, value: Value) -> Value {
3925        Value::Future(Rc::new(RefCell::new(FutureInner {
3926            state: FutureState::Ready(Box::new(value)),
3927            computation: None,
3928            complete_at: None,
3929        })))
3930    }
3931
3932    /// Create a pending future with lazy computation
3933    pub fn make_future_lazy(&self, func: Rc<Function>, args: Vec<Value>) -> Value {
3934        Value::Future(Rc::new(RefCell::new(FutureInner {
3935            state: FutureState::Pending,
3936            computation: Some(FutureComputation::Lazy { func, args }),
3937            complete_at: None,
3938        })))
3939    }
3940
3941    /// Create a timer future
3942    pub fn make_future_timer(&self, duration: std::time::Duration) -> Value {
3943        Value::Future(Rc::new(RefCell::new(FutureInner {
3944            state: FutureState::Pending,
3945            computation: Some(FutureComputation::Timer(duration)),
3946            complete_at: Some(std::time::Instant::now() + duration),
3947        })))
3948    }
3949
3950    fn eval_array(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
3951        let values: Vec<Value> = elements
3952            .iter()
3953            .map(|e| self.evaluate(e))
3954            .collect::<Result<_, _>>()?;
3955        Ok(Value::Array(Rc::new(RefCell::new(values))))
3956    }
3957
3958    fn eval_tuple(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
3959        let values: Vec<Value> = elements
3960            .iter()
3961            .map(|e| self.evaluate(e))
3962            .collect::<Result<_, _>>()?;
3963        Ok(Value::Tuple(Rc::new(values)))
3964    }
3965
3966    fn eval_block(&mut self, block: &Block) -> Result<Value, RuntimeError> {
3967        let env = Rc::new(RefCell::new(Environment::with_parent(
3968            self.environment.clone(),
3969        )));
3970        let prev_env = self.environment.clone();
3971        self.environment = env;
3972
3973        let mut result = Value::Null;
3974
3975        for stmt in &block.stmts {
3976            match stmt {
3977                Stmt::Let { pattern, init, .. } => {
3978                    let value = match init {
3979                        Some(expr) => self.evaluate(expr)?,
3980                        None => Value::Null,
3981                    };
3982                    self.bind_pattern(pattern, value)?;
3983                }
3984                Stmt::LetElse { pattern, init, else_branch, .. } => {
3985                    let value = self.evaluate(init)?;
3986                    // Try to bind pattern, if it fails, execute else branch
3987                    if self.bind_pattern(pattern, value.clone()).is_err() {
3988                        return self.evaluate(else_branch);
3989                    }
3990                }
3991                Stmt::Expr(expr) => {
3992                    result = self.evaluate(expr)?;
3993                }
3994                Stmt::Semi(expr) => {
3995                    self.evaluate(expr)?;
3996                    result = Value::Null;
3997                }
3998                Stmt::Item(item) => {
3999                    self.execute_item(item)?;
4000                }
4001            }
4002        }
4003
4004        if let Some(expr) = &block.expr {
4005            result = self.evaluate(expr)?;
4006        }
4007
4008        // RAII: Call Drop::drop() on values going out of scope
4009        // Collect values to drop (avoid borrowing self during iteration)
4010        let values_to_drop: Vec<(String, Value)> = self.environment
4011            .borrow()
4012            .values
4013            .iter()
4014            .filter_map(|(name, value)| {
4015                if let Value::Struct { name: struct_name, .. } = value {
4016                    if self.drop_types.contains(struct_name) {
4017                        return Some((name.clone(), value.clone()));
4018                    }
4019                }
4020                None
4021            })
4022            .collect();
4023
4024        // Call drop on each value
4025        for (_var_name, value) in values_to_drop {
4026            if let Value::Struct { name: struct_name, .. } = &value {
4027                let drop_fn_name = format!("{}·drop", struct_name);
4028                // Clone the function out of globals to avoid borrow issues
4029                let drop_fn = self.globals.borrow().get(&drop_fn_name).map(|v| v.clone());
4030                if let Some(Value::Function(f)) = drop_fn {
4031                    // Call drop(self) - the value is passed as self
4032                    let _ = self.call_function(&f, vec![value.clone()]);
4033                }
4034            }
4035        }
4036
4037        self.environment = prev_env;
4038        Ok(result)
4039    }
4040
4041    fn bind_pattern(&mut self, pattern: &Pattern, value: Value) -> Result<(), RuntimeError> {
4042        match pattern {
4043            Pattern::Ident { name, .. } => {
4044                // Don't bind "_" - it's a wildcard in identifier form
4045                if name.name != "_" {
4046                    // Debug: trace path binding
4047                    if name.name == "path" {
4048                        crate::sigil_debug!("DEBUG bind_pattern: binding 'path' = {:?}", value);
4049                    }
4050                    self.environment
4051                        .borrow_mut()
4052                        .define(name.name.clone(), value);
4053                }
4054                Ok(())
4055            }
4056            Pattern::Tuple(patterns) => {
4057                // Unwrap evidential wrappers first
4058                let unwrapped = Self::unwrap_all(&value);
4059                crate::sigil_debug!("DEBUG bind_pattern Tuple: patterns.len()={}, value type={:?}",
4060                    patterns.len(), std::mem::discriminant(&unwrapped));
4061                match unwrapped {
4062                    Value::Tuple(values) => {
4063                        if patterns.len() != values.len() {
4064                            return Err(RuntimeError::new("Tuple pattern size mismatch"));
4065                        }
4066                        for (i, (p, v)) in patterns.iter().zip(values.iter()).enumerate() {
4067                            crate::sigil_debug!("DEBUG   binding tuple element {}: {:?} = {}", i, p, self.format_value(v));
4068                            self.bind_pattern(p, v.clone())?;
4069                        }
4070                        Ok(())
4071                    }
4072                    Value::Null => {
4073                        // Null value during iteration - treat as end of iteration (no binding)
4074                        Ok(())
4075                    }
4076                    Value::Array(arr) if arr.borrow().len() == patterns.len() => {
4077                        // Allow array to be destructured as tuple
4078                        let vals = arr.borrow();
4079                        for (p, v) in patterns.iter().zip(vals.iter()) {
4080                            self.bind_pattern(p, v.clone())?;
4081                        }
4082                        Ok(())
4083                    }
4084                    _ => Err(RuntimeError::new("Expected tuple"))
4085                }
4086            }
4087            Pattern::Wildcard => Ok(()),
4088            Pattern::Struct { path, fields, .. } => {
4089                // Unwrap any wrappers first
4090                let unwrapped = Self::unwrap_all(&value);
4091                // Bind each field from the struct or variant
4092                match &unwrapped {
4093                    Value::Struct { fields: struct_fields, .. } => {
4094                        for field_pat in fields {
4095                            let field_name = &field_pat.name.name;
4096                            // Get field value or default to Null for missing optional fields
4097                            let field_val = struct_fields.borrow().get(field_name).cloned().unwrap_or(Value::Null);
4098                            if let Some(pat) = &field_pat.pattern {
4099                                self.bind_pattern(pat, field_val)?;
4100                            } else {
4101                                // Shorthand: foo: foo - bind to same name
4102                                self.environment.borrow_mut().define(field_name.clone(), field_val);
4103                            }
4104                        }
4105                        Ok(())
4106                    }
4107                    Value::Variant { enum_name, variant_name, fields: variant_fields } => {
4108                        // Handle struct-like enum variants (e.g., IrPattern::Ident { name, .. })
4109                        let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4110                        if pattern_variant == variant_name || path.segments.iter().any(|s| s.ident.name == *variant_name) {
4111                            // Variant fields are stored as a Vec, but we need to map by name
4112                            // For struct-like variants, the fields should be a Struct value with field names
4113                            if let Some(inner_fields) = variant_fields {
4114                                if inner_fields.len() == 1 {
4115                                    // Single wrapped struct with named fields
4116                                    if let Value::Struct { fields: inner_struct, .. } = &inner_fields[0] {
4117                                        for field_pat in fields {
4118                                            let field_name = &field_pat.name.name;
4119                                            // Default to Null for missing optional fields
4120                                            let field_val = inner_struct.borrow().get(field_name).cloned().unwrap_or(Value::Null);
4121                                            if let Some(pat) = &field_pat.pattern {
4122                                                self.bind_pattern(pat, field_val)?;
4123                                            } else {
4124                                                self.environment.borrow_mut().define(field_name.clone(), field_val);
4125                                            }
4126                                        }
4127                                        return Ok(());
4128                                    }
4129                                }
4130                                // Named field lookup from variant's field map
4131                                // Variants store struct fields as named HashMap inside the variant
4132                                for field_pat in fields {
4133                                    let field_name = &field_pat.name.name;
4134                                    // Look for a field with matching name in variant fields
4135                                    // Variant fields might be stored in order or as a struct
4136                                    // For now, search by name if we can find it
4137                                    let field_val = inner_fields.iter().find_map(|f| {
4138                                        if let Value::Struct { fields: fs, .. } = f {
4139                                            fs.borrow().get(field_name).cloned()
4140                                        } else {
4141                                            None
4142                                        }
4143                                    });
4144                                    if let Some(val) = field_val {
4145                                        if let Some(pat) = &field_pat.pattern {
4146                                            self.bind_pattern(pat, val)?;
4147                                        } else {
4148                                            self.environment.borrow_mut().define(field_name.clone(), val);
4149                                        }
4150                                    }
4151                                }
4152                            }
4153                            Ok(())
4154                        } else {
4155                            crate::sigil_debug!("DEBUG variant name mismatch: pattern={}, actual={}", pattern_variant, variant_name);
4156                            Err(RuntimeError::new(format!(
4157                                "Variant name mismatch: expected {} but got {}::{}",
4158                                pattern_variant, enum_name, variant_name
4159                            )))
4160                        }
4161                    }
4162                    _ => {
4163                        crate::sigil_debug!("DEBUG struct pattern bind: expected struct/variant but got {:?}", std::mem::discriminant(&unwrapped));
4164                        Err(RuntimeError::new("Expected struct or variant value for struct pattern"))
4165                    }
4166                }
4167            }
4168            Pattern::Path(_path) => {
4169                // Path patterns like Result::Ok - unit variant patterns
4170                // Don't bind anything
4171                Ok(())
4172            }
4173            Pattern::TupleStruct { path, fields } => {
4174                // Enum variant with fields: Result::Ok(value)
4175                // Unwrap any refs first
4176                let unwrapped = Self::unwrap_all(&value);
4177                let path_str = path.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("::");
4178                crate::sigil_debug!("DEBUG bind_pattern TupleStruct: path={}, value type={:?}",
4179                    path_str,
4180                    std::mem::discriminant(&unwrapped));
4181                if let Value::Variant { variant_name, fields: variant_fields, enum_name } = &unwrapped {
4182                    crate::sigil_debug!("DEBUG   Variant {}::{}, fields={}", enum_name, variant_name,
4183                        if variant_fields.is_some() { format!("Some(len={})", variant_fields.as_ref().unwrap().len()) } else { "None".to_string() });
4184                    let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4185                    if pattern_variant == variant_name {
4186                        // Unwrap fields and bind
4187                        if let Some(inner_fields) = variant_fields {
4188                            if fields.len() == 1 && inner_fields.len() == 1 {
4189                                self.bind_pattern(&fields[0], inner_fields[0].clone())?;
4190                            } else {
4191                                for (pat, val) in fields.iter().zip(inner_fields.iter()) {
4192                                    self.bind_pattern(pat, val.clone())?;
4193                                }
4194                            }
4195                        } else if !fields.is_empty() {
4196                            // Pattern expects fields but variant has none
4197                            crate::sigil_debug!("DEBUG TupleStruct: pattern expects {} fields but variant has none", fields.len());
4198                        }
4199                    }
4200                    Ok(())
4201                } else {
4202                    // Maybe it's a regular tuple being matched
4203                    if let Value::Tuple(tuple_vals) = &value {
4204                        for (pat, val) in fields.iter().zip(tuple_vals.iter()) {
4205                            self.bind_pattern(pat, val.clone())?;
4206                        }
4207                        Ok(())
4208                    } else {
4209                        Err(RuntimeError::new("Expected variant or tuple for tuple struct pattern"))
4210                    }
4211                }
4212            }
4213            Pattern::Literal(_) => {
4214                // Literal patterns don't bind anything, just match
4215                Ok(())
4216            }
4217            Pattern::Rest => {
4218                // Rest pattern .. - just ignores rest of values
4219                Ok(())
4220            }
4221            Pattern::Range { .. } => {
4222                // Range patterns like 'a'..='z' don't bind anything
4223                Ok(())
4224            }
4225            Pattern::Or(patterns) => {
4226                // Or patterns - find the matching pattern and bind its variables
4227                for p in patterns {
4228                    if self.pattern_matches(p, &value)? {
4229                        return self.bind_pattern(p, value.clone());
4230                    }
4231                }
4232                // No pattern matched - this shouldn't happen if pattern_matches returned true earlier
4233                Err(RuntimeError::new("Or pattern didn't match any alternative"))
4234            }
4235            _ => Err(RuntimeError::new(format!("Unsupported pattern: {:?}", pattern))),
4236        }
4237    }
4238
4239    fn eval_if(
4240        &mut self,
4241        condition: &Expr,
4242        then_branch: &Block,
4243        else_branch: &Option<Box<Expr>>,
4244    ) -> Result<Value, RuntimeError> {
4245        let cond = self.evaluate(condition)?;
4246        if self.is_truthy(&cond) {
4247            self.eval_block(then_branch)
4248        } else if let Some(else_expr) = else_branch {
4249            self.evaluate(else_expr)
4250        } else {
4251            Ok(Value::Null)
4252        }
4253    }
4254
4255    fn eval_match(&mut self, expr: &Expr, arms: &[MatchArm]) -> Result<Value, RuntimeError> {
4256        let value = self.evaluate(expr)?;
4257
4258        // Debug all string matches to find keyword_or_ident
4259        let unwrapped = Self::unwrap_all(&value);
4260        if let Value::String(s) = &unwrapped {
4261            if s.len() <= 10 {
4262                crate::sigil_debug!("DEBUG eval_match: string='{}', arms={}", s, arms.len());
4263            }
4264        }
4265
4266        for arm in arms {
4267            if self.pattern_matches(&arm.pattern, &value)? {
4268                // Create new environment for pattern bindings
4269                let env = Rc::new(RefCell::new(Environment::with_parent(
4270                    self.environment.clone(),
4271                )));
4272                let prev_env = self.environment.clone();
4273                self.environment = env;
4274
4275                // Bind pattern variables FIRST (before evaluating guard)
4276                // This is necessary for guards like `?fields if !fields.is_empty()`
4277                if let Err(e) = self.bind_pattern(&arm.pattern, value.clone()) {
4278                    self.environment = prev_env;
4279                    return Err(e);
4280                }
4281
4282                // Check guard if present (pattern vars are now in scope)
4283                if let Some(guard) = &arm.guard {
4284                    let guard_val = self.evaluate(guard)?;
4285                    if !self.is_truthy(&guard_val) {
4286                        // Guard failed - restore environment and try next arm
4287                        self.environment = prev_env;
4288                        continue;
4289                    }
4290                }
4291
4292                // Pattern matched and guard passed - evaluate body
4293                let result = self.evaluate(&arm.body);
4294
4295                self.environment = prev_env;
4296                return result;
4297            }
4298        }
4299
4300        // Debug: show what value we're trying to match with discriminant
4301        crate::sigil_debug!("DEBUG No matching pattern for value: {} (discriminant: {:?})",
4302            self.format_value(&value), std::mem::discriminant(&value));
4303        // Also show the arms
4304        for (i, arm) in arms.iter().enumerate() {
4305            crate::sigil_debug!("DEBUG   arm {}: {:?}", i, arm.pattern);
4306        }
4307        Err(RuntimeError::new(format!("No matching pattern for {}", self.format_value(&value))))
4308    }
4309
4310    fn pattern_matches(&mut self, pattern: &Pattern, value: &Value) -> Result<bool, RuntimeError> {
4311        // Unwrap evidential/affective/ref wrappers from value
4312        let value = Self::unwrap_all(value);
4313
4314        // Debug string pattern matching
4315        if let Value::String(s) = &value {
4316            if **s == "fn" {
4317                crate::sigil_debug!("DEBUG pattern_matches: value='fn', pattern={:?}", pattern);
4318            }
4319        }
4320
4321        match (pattern, &value) {
4322            (Pattern::Wildcard, _) => Ok(true),
4323            // Pattern::Ident with evidentiality - ?g matches Some/non-null, !g matches Known values
4324            (Pattern::Ident { evidentiality: Some(Evidentiality::Uncertain), name, .. }, val) => {
4325                // ?g pattern should match non-null values (i.e., Option::Some)
4326                let matches = match val {
4327                    Value::Null => false,
4328                    Value::Variant { variant_name, .. } if variant_name == "None" => false,
4329                    _ => true,
4330                };
4331                crate::sigil_debug!("DEBUG pattern_matches ?{}: value={} => {}", name.name, self.format_value(val), matches);
4332                Ok(matches)
4333            }
4334            (Pattern::Ident { .. }, _) => Ok(true),
4335            (Pattern::Literal(lit), val) => {
4336                let lit_val = self.eval_literal(lit)?;
4337                let result = self.values_equal(&lit_val, val);
4338                // Debug null pattern matching specifically
4339                if matches!(lit, Literal::Null) || matches!(val, Value::Null) {
4340                    crate::sigil_debug!("DEBUG literal pattern: lit={:?}, lit_val={}, val={}, result={}",
4341                        lit, self.format_value(&lit_val), self.format_value(val), result);
4342                }
4343                Ok(result)
4344            }
4345            (Pattern::Tuple(patterns), Value::Tuple(values)) => {
4346                if patterns.len() != values.len() {
4347                    return Ok(false);
4348                }
4349                for (p, v) in patterns.iter().zip(values.iter()) {
4350                    if !self.pattern_matches(p, v)? {
4351                        return Ok(false);
4352                    }
4353                }
4354                Ok(true)
4355            }
4356            // Path pattern - matches unit enum variants like CompileMode::Compile
4357            (Pattern::Path(path), Value::Variant { variant_name, fields, .. }) => {
4358                let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4359                // Match if variant name matches and has no fields
4360                Ok(pattern_variant == variant_name && fields.is_none())
4361            }
4362            // TupleStruct pattern - matches enum variants with data like Result::Ok(x)
4363            (Pattern::TupleStruct { path, fields: pat_fields }, Value::Variant { variant_name, fields, .. }) => {
4364                let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4365                if pattern_variant != variant_name {
4366                    return Ok(false);
4367                }
4368                // Match field patterns
4369                if let Some(variant_fields) = fields {
4370                    if pat_fields.len() != variant_fields.len() {
4371                        return Ok(false);
4372                    }
4373                    for (p, v) in pat_fields.iter().zip(variant_fields.iter()) {
4374                        if !self.pattern_matches(p, v)? {
4375                            return Ok(false);
4376                        }
4377                    }
4378                    Ok(true)
4379                } else {
4380                    // Variant has no fields but pattern expects some
4381                    Ok(pat_fields.is_empty())
4382                }
4383            }
4384            // Struct pattern - matches struct values
4385            (Pattern::Struct { path, fields: pat_fields, rest }, Value::Struct { name: struct_name, fields: struct_fields }) => {
4386                let pattern_name = path.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("::");
4387                if pattern_name != *struct_name {
4388                    return Ok(false);
4389                }
4390                // Check each field in the pattern
4391                let borrowed = struct_fields.borrow();
4392                for field_pat in pat_fields {
4393                    let field_name = &field_pat.name.name;
4394                    if let Some(field_val) = borrowed.get(field_name) {
4395                        if let Some(sub_pat) = &field_pat.pattern {
4396                            if !self.pattern_matches(sub_pat, field_val)? {
4397                                return Ok(false);
4398                            }
4399                        }
4400                        // If no sub-pattern, any value matches
4401                    } else if !rest {
4402                        // Field not found and no rest pattern
4403                        return Ok(false);
4404                    }
4405                }
4406                Ok(true)
4407            }
4408            // Struct pattern - matches struct-like enum variants (e.g., TypeExpr::Evidential { inner, ... })
4409            (Pattern::Struct { path, fields: pat_fields, rest }, Value::Variant { variant_name, fields: variant_fields, .. }) => {
4410                let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4411                if pattern_variant != variant_name {
4412                    return Ok(false);
4413                }
4414                // Struct-like variants store fields as a single wrapped Struct value
4415                if let Some(inner_fields) = variant_fields {
4416                    if inner_fields.len() == 1 {
4417                        if let Value::Struct { fields: inner_struct, .. } = &inner_fields[0] {
4418                            let borrowed = inner_struct.borrow();
4419                            for field_pat in pat_fields {
4420                                let field_name = &field_pat.name.name;
4421                                if let Some(field_val) = borrowed.get(field_name) {
4422                                    if let Some(sub_pat) = &field_pat.pattern {
4423                                        if !self.pattern_matches(sub_pat, field_val)? {
4424                                            return Ok(false);
4425                                        }
4426                                    }
4427                                } else if !rest {
4428                                    return Ok(false);
4429                                }
4430                            }
4431                            return Ok(true);
4432                        }
4433                    }
4434                }
4435                // No fields or structure doesn't match
4436                Ok(pat_fields.is_empty() || *rest)
4437            }
4438            // Or pattern - match if any sub-pattern matches
4439            (Pattern::Or(patterns), val) => {
4440                for p in patterns {
4441                    if self.pattern_matches(p, val)? {
4442                        return Ok(true);
4443                    }
4444                }
4445                Ok(false)
4446            }
4447            // Rest pattern always matches
4448            (Pattern::Rest, _) => Ok(true),
4449            // Range pattern: 'a'..='z' or 0..=9
4450            (Pattern::Range { start, end, inclusive }, val) => {
4451                // Helper to extract char from pattern
4452                let extract_char = |pat: &Option<Box<Pattern>>| -> Option<char> {
4453                    match pat {
4454                        Some(p) => match p.as_ref() {
4455                            Pattern::Literal(Literal::Char(c)) => Some(*c),
4456                            _ => None,
4457                        },
4458                        None => None,
4459                    }
4460                };
4461                // Helper to extract int from pattern
4462                let extract_int = |pat: &Option<Box<Pattern>>| -> Option<i64> {
4463                    match pat {
4464                        Some(p) => match p.as_ref() {
4465                            Pattern::Literal(Literal::Int { value, .. }) => value.parse().ok(),
4466                            _ => None,
4467                        },
4468                        None => None,
4469                    }
4470                };
4471
4472                match val {
4473                    Value::Char(c) => {
4474                        let start_val = extract_char(start);
4475                        let end_val = extract_char(end);
4476                        let in_range = match (start_val, end_val, *inclusive) {
4477                            (Some(s), Some(e), true) => *c >= s && *c <= e,
4478                            (Some(s), Some(e), false) => *c >= s && *c < e,
4479                            (Some(s), None, _) => *c >= s,
4480                            (None, Some(e), true) => *c <= e,
4481                            (None, Some(e), false) => *c < e,
4482                            (None, None, _) => true,
4483                        };
4484                        Ok(in_range)
4485                    }
4486                    Value::Int(i) => {
4487                        let start_val = extract_int(start);
4488                        let end_val = extract_int(end);
4489                        let in_range = match (start_val, end_val, *inclusive) {
4490                            (Some(s), Some(e), true) => *i >= s && *i <= e,
4491                            (Some(s), Some(e), false) => *i >= s && *i < e,
4492                            (Some(s), None, _) => *i >= s,
4493                            (None, Some(e), true) => *i <= e,
4494                            (None, Some(e), false) => *i < e,
4495                            (None, None, _) => true,
4496                        };
4497                        Ok(in_range)
4498                    }
4499                    _ => Ok(false),
4500                }
4501            }
4502            // Literal matching against string or char
4503            (Pattern::Literal(Literal::String(s)), Value::String(vs)) => {
4504                Ok(s == vs.as_str())
4505            }
4506            (Pattern::Literal(Literal::Char(c)), Value::Char(vc)) => {
4507                Ok(c == vc)
4508            }
4509            _ => Ok(false),
4510        }
4511    }
4512
4513    fn values_equal(&self, a: &Value, b: &Value) -> bool {
4514        // Unwrap any Ref wrappers before comparison
4515        let a_unwrapped = match a {
4516            Value::Ref(r) => r.borrow().clone(),
4517            _ => a.clone(),
4518        };
4519        let b_unwrapped = match b {
4520            Value::Ref(r) => r.borrow().clone(),
4521            _ => b.clone(),
4522        };
4523        match (&a_unwrapped, &b_unwrapped) {
4524            (Value::Null, Value::Null) => true,
4525            (Value::Bool(a), Value::Bool(b)) => a == b,
4526            (Value::Int(a), Value::Int(b)) => a == b,
4527            (Value::Float(a), Value::Float(b)) => (a - b).abs() < f64::EPSILON,
4528            (Value::String(a), Value::String(b)) => {
4529                let result = **a == **b;
4530                // Debug ALL short string comparisons
4531                if a.len() <= 5 && b.len() <= 5 {
4532                    crate::sigil_debug!("DEBUG values_equal: '{}' == '{}' -> {}", a, b, result);
4533                }
4534                result
4535            }
4536            (Value::Char(a), Value::Char(b)) => a == b,
4537            _ => false,
4538        }
4539    }
4540
4541    fn eval_for(
4542        &mut self,
4543        pattern: &Pattern,
4544        iter: &Expr,
4545        body: &Block,
4546    ) -> Result<Value, RuntimeError> {
4547        let iterable_raw = self.evaluate(iter)?;
4548        let iterable = Self::unwrap_all(&iterable_raw);
4549        let items = match iterable {
4550            Value::Array(arr) => arr.borrow().clone(),
4551            Value::Tuple(t) => (*t).clone(),
4552            Value::String(s) => s.chars().map(Value::Char).collect(),
4553            Value::Map(m) => {
4554                // Iterate over key-value pairs as tuples
4555                m.borrow()
4556                    .iter()
4557                    .map(|(k, v)| {
4558                        Value::Tuple(Rc::new(vec![
4559                            Value::String(Rc::new(k.clone())),
4560                            v.clone(),
4561                        ]))
4562                    })
4563                    .collect()
4564            }
4565            Value::Variant { fields: Some(f), .. } => (*f).clone(),
4566            _ => return Err(RuntimeError::new(format!("Cannot iterate over non-iterable: {:?}", iterable_raw))),
4567        };
4568
4569        let mut result = Value::Null;
4570        for item in items {
4571            let env = Rc::new(RefCell::new(Environment::with_parent(
4572                self.environment.clone(),
4573            )));
4574            let prev_env = self.environment.clone();
4575            self.environment = env;
4576
4577            self.bind_pattern(pattern, item)?;
4578
4579            match self.eval_block(body) {
4580                Ok(val) => result = val,
4581                Err(e) if e.message == "break" => {
4582                    self.environment = prev_env;
4583                    break;
4584                }
4585                Err(e) if e.message == "continue" => {
4586                    self.environment = prev_env;
4587                    continue;
4588                }
4589                Err(e) => {
4590                    self.environment = prev_env;
4591                    return Err(e);
4592                }
4593            }
4594
4595            self.environment = prev_env;
4596        }
4597
4598        Ok(result)
4599    }
4600
4601    fn eval_while(&mut self, condition: &Expr, body: &Block) -> Result<Value, RuntimeError> {
4602        let mut result = Value::Null;
4603        loop {
4604            let cond = self.evaluate(condition)?;
4605            if !self.is_truthy(&cond) {
4606                break;
4607            }
4608
4609            match self.eval_block(body) {
4610                Ok(val) => result = val,
4611                Err(e) if e.message == "break" => break,
4612                Err(e) if e.message == "continue" => continue,
4613                Err(e) => return Err(e),
4614            }
4615        }
4616        Ok(result)
4617    }
4618
4619    fn eval_loop(&mut self, body: &Block) -> Result<Value, RuntimeError> {
4620        loop {
4621            match self.eval_block(body) {
4622                Ok(_) => {}
4623                Err(e) if e.message == "break" => break,
4624                Err(e) if e.message == "continue" => continue,
4625                Err(e) => return Err(e),
4626            }
4627        }
4628        Ok(Value::Null)
4629    }
4630
4631    fn eval_return(&mut self, value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
4632        let val = match value {
4633            Some(expr) => self.evaluate(expr)?,
4634            None => Value::Null,
4635        };
4636        // Store return value for call_function to retrieve
4637        self.return_value = Some(val);
4638        Err(RuntimeError::new("return"))
4639    }
4640
4641    fn eval_break(&mut self, _value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
4642        // TODO: break with value for loop expressions
4643        Err(RuntimeError::new("break"))
4644    }
4645
4646    fn eval_index(&mut self, expr: &Expr, index: &Expr) -> Result<Value, RuntimeError> {
4647        let collection = self.evaluate(expr)?;
4648
4649        // Dereference Ref values to get the underlying collection
4650        let collection = match collection {
4651            Value::Ref(r) => r.borrow().clone(),
4652            other => other,
4653        };
4654
4655        // Handle range slicing before evaluating the index
4656        if let Expr::Range { start, end, inclusive } = index {
4657            let start_val = match start {
4658                Some(e) => match self.evaluate(e)? {
4659                    Value::Int(n) => n as usize,
4660                    _ => return Err(RuntimeError::new("Slice start must be an integer")),
4661                },
4662                None => 0,
4663            };
4664
4665            return match &collection {
4666                Value::Array(arr) => {
4667                    let arr = arr.borrow();
4668                    let len = arr.len();
4669                    let end_val = match end {
4670                        Some(e) => match self.evaluate(e)? {
4671                            Value::Int(n) => {
4672                                let n = n as usize;
4673                                if *inclusive { n + 1 } else { n }
4674                            },
4675                            _ => return Err(RuntimeError::new("Slice end must be an integer")),
4676                        },
4677                        None => len,  // Open-ended range: slice to end
4678                    };
4679                    let end_val = end_val.min(len);
4680                    let start_val = start_val.min(len);
4681                    let sliced: Vec<Value> = arr[start_val..end_val].to_vec();
4682                    Ok(Value::Array(Rc::new(RefCell::new(sliced))))
4683                }
4684                Value::String(s) => {
4685                    let len = s.len();
4686                    let end_val = match end {
4687                        Some(e) => match self.evaluate(e)? {
4688                            Value::Int(n) => {
4689                                let n = n as usize;
4690                                if *inclusive { n + 1 } else { n }
4691                            },
4692                            _ => return Err(RuntimeError::new("Slice end must be an integer")),
4693                        },
4694                        None => len,  // Open-ended range: slice to end
4695                    };
4696                    let end_val = end_val.min(len);
4697                    let start_val = start_val.min(len);
4698                    // Use byte slicing for consistency with char_at
4699                    let sliced = &s[start_val..end_val];
4700                    Ok(Value::String(Rc::new(sliced.to_string())))
4701                }
4702                _ => Err(RuntimeError::new("Cannot slice this type")),
4703            };
4704        }
4705
4706        let idx = self.evaluate(index)?;
4707
4708        match (collection, idx) {
4709            (Value::Array(arr), Value::Int(i)) => {
4710                let arr = arr.borrow();
4711                let i = if i < 0 { arr.len() as i64 + i } else { i } as usize;
4712                let result = arr.get(i)
4713                    .cloned()
4714                    .ok_or_else(|| RuntimeError::new("Index out of bounds"));
4715                if let Ok(ref v) = result {
4716                    crate::sigil_debug!("DEBUG eval_index: arr[{}] = {:?}", i, std::mem::discriminant(v));
4717                }
4718                result
4719            }
4720            (Value::Tuple(t), Value::Int(i)) => {
4721                let i = if i < 0 { t.len() as i64 + i } else { i } as usize;
4722                t.get(i)
4723                    .cloned()
4724                    .ok_or_else(|| RuntimeError::new("Index out of bounds"))
4725            }
4726            (Value::String(s), Value::Int(i)) => {
4727                let i = if i < 0 { s.len() as i64 + i } else { i } as usize;
4728                s.chars()
4729                    .nth(i)
4730                    .map(Value::Char)
4731                    .ok_or_else(|| RuntimeError::new("Index out of bounds"))
4732            }
4733            // Handle open-ended range slicing (from eval_range returning tuple)
4734            (Value::Array(arr), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
4735                let arr = arr.borrow();
4736                let start = match &range_tuple[0] {
4737                    Value::Int(n) => *n as usize,
4738                    _ => return Err(RuntimeError::new("Range start must be integer")),
4739                };
4740                let end = match &range_tuple[1] {
4741                    Value::Null => arr.len(),  // Open end - slice to end
4742                    Value::Int(n) => *n as usize,
4743                    _ => return Err(RuntimeError::new("Range end must be integer or None")),
4744                };
4745                let start = start.min(arr.len());
4746                let end = end.min(arr.len());
4747                let sliced: Vec<Value> = arr[start..end].to_vec();
4748                Ok(Value::Array(Rc::new(RefCell::new(sliced))))
4749            }
4750            (Value::String(s), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
4751                let start = match &range_tuple[0] {
4752                    Value::Int(n) => *n as usize,
4753                    _ => return Err(RuntimeError::new("Range start must be integer")),
4754                };
4755                let end = match &range_tuple[1] {
4756                    Value::Null => s.len(),  // Open end - slice to end
4757                    Value::Int(n) => *n as usize,
4758                    _ => return Err(RuntimeError::new("Range end must be integer or None")),
4759                };
4760                let start = start.min(s.len());
4761                let end = end.min(s.len());
4762                let sliced = &s[start..end];
4763                Ok(Value::String(Rc::new(sliced.to_string())))
4764            }
4765            (coll, idx) => {
4766                crate::sigil_debug!("DEBUG Cannot index: collection={:?}, index={:?}",
4767                    std::mem::discriminant(&coll), std::mem::discriminant(&idx));
4768                Err(RuntimeError::new("Cannot index"))
4769            }
4770        }
4771    }
4772
4773    fn eval_field(&mut self, expr: &Expr, field: &Ident) -> Result<Value, RuntimeError> {
4774        if field.name == "items" {
4775            crate::sigil_debug!("DEBUG eval_field: accessing .items on expr={:?}", expr);
4776        }
4777        // Debug evidence field access
4778        if field.name == "evidence" {
4779            crate::sigil_debug!("DEBUG eval_field: accessing .evidence");
4780        }
4781        let value = self.evaluate(expr)?;
4782        if field.name == "items" {
4783            crate::sigil_debug!("DEBUG eval_field: .items receiver value={:?}", std::mem::discriminant(&value));
4784        }
4785        if field.name == "evidence" {
4786            crate::sigil_debug!("DEBUG eval_field: .evidence receiver value type={:?}", std::mem::discriminant(&value));
4787        }
4788        // Helper to get field from a value
4789        fn get_field(val: &Value, field_name: &str) -> Result<Value, RuntimeError> {
4790            // Debug all field access on IrPattern
4791            if field_name == "evidence" {
4792                crate::sigil_debug!("DEBUG get_field 'evidence' on value type: {:?}", std::mem::discriminant(val));
4793            }
4794            match val {
4795                Value::Struct { name, fields } => {
4796                    let field_val = fields.borrow().get(field_name).cloned();
4797                    if field_val.is_none() && field_name == "path" {
4798                        crate::sigil_debug!("DEBUG Unknown field 'path': struct={}, available={:?}", name, fields.borrow().keys().collect::<Vec<_>>());
4799                    }
4800                    // Debug evidence field access
4801                    if field_name == "evidence" || name.contains("IrPattern") {
4802                        crate::sigil_debug!("DEBUG get_field on Struct: name={}, field={}, available={:?}, found={}",
4803                            name, field_name, fields.borrow().keys().collect::<Vec<_>>(), field_val.is_some());
4804                    }
4805                    // Fallback for unknown fields on external types: return null
4806                    match field_val {
4807                        Some(v) => Ok(v),
4808                        None => {
4809                            crate::sigil_warn!("WARN: Unknown field '{}' on '{}' - returning null", field_name, name);
4810                            Ok(Value::Null)
4811                        }
4812                    }
4813                }
4814                Value::Tuple(t) => {
4815                    // Tuple field access like .0, .1
4816                    let idx: usize = field_name
4817                        .parse()
4818                        .map_err(|_| RuntimeError::new("Invalid tuple index"))?;
4819                    t.get(idx)
4820                        .cloned()
4821                        .ok_or_else(|| RuntimeError::new("Tuple index out of bounds"))
4822                }
4823                Value::Ref(r) => {
4824                    // Dereference and access field on inner value
4825                    get_field(&r.borrow(), field_name)
4826                }
4827                Value::Evidential { value, .. } => {
4828                    // Unwrap evidential wrapper and access field
4829                    get_field(value, field_name)
4830                }
4831                Value::Affective { value, .. } => {
4832                    // Unwrap affective wrapper and access field
4833                    get_field(value, field_name)
4834                }
4835                Value::Variant { fields: variant_fields, .. } => {
4836                    // Handle struct-like enum variants (e.g., IrPattern::Ident { name, evidence, .. })
4837                    // Variant fields may be stored as a Struct value or as positional values
4838                    if let Some(inner_fields) = variant_fields {
4839                        // Try to find a Struct value that contains the field
4840                        for f in inner_fields.iter() {
4841                            if let Value::Struct { fields: struct_fields, .. } = f {
4842                                if let Some(field_val) = struct_fields.borrow().get(field_name).cloned() {
4843                                    return Ok(field_val);
4844                                }
4845                            }
4846                        }
4847                        // Field not found in any struct - return Null for optional fields
4848                        Ok(Value::Null)
4849                    } else {
4850                        // No fields in variant
4851                        Ok(Value::Null)
4852                    }
4853                }
4854                other => {
4855                    // Fallback for field access on non-struct types: return null
4856                    crate::sigil_warn!("WARN: Cannot access field '{}' on non-struct - returning null", field_name);
4857                    Ok(Value::Null)
4858                }
4859            }
4860        }
4861        get_field(&value, &field.name)
4862    }
4863
4864    // Helper: Extract the root variable name from a method chain
4865    fn extract_root_var(expr: &Expr) -> Option<String> {
4866        match expr {
4867            Expr::Path(path) if path.segments.len() == 1 => {
4868                Some(path.segments[0].ident.name.clone())
4869            }
4870            Expr::MethodCall { receiver, .. } => {
4871                Self::extract_root_var(receiver)
4872            }
4873            _ => None,
4874        }
4875    }
4876
4877    fn eval_method_call(
4878        &mut self,
4879        receiver: &Expr,
4880        method: &Ident,
4881        args: &[Expr],
4882    ) -> Result<Value, RuntimeError> {
4883        // Special handling for String::push/push_str - needs to mutate the variable
4884        if (method.name == "push" || method.name == "push_str") && args.len() == 1 {
4885            let recv_val = self.evaluate(receiver)?;
4886            let recv_unwrapped = Self::unwrap_all(&recv_val);
4887            if let Value::String(s) = &recv_unwrapped {
4888                let arg = self.evaluate(&args[0])?;
4889                let arg_unwrapped = Self::unwrap_all(&arg);
4890                let new_s = match arg_unwrapped {
4891                    Value::Char(c) => {
4892                        let mut new_str = (**s).clone();
4893                        new_str.push(c);
4894                        new_str
4895                    }
4896                    Value::String(ref add_s) => {
4897                        let mut new_str = (**s).clone();
4898                        new_str.push_str(add_s);
4899                        new_str
4900                    }
4901                    _ => return Err(RuntimeError::new("push expects char or string argument")),
4902                };
4903                let new_val = Value::String(Rc::new(new_s));
4904
4905                // Try to extract root variable from chain and mutate it
4906                if let Some(root_var) = Self::extract_root_var(receiver) {
4907                    self.environment.borrow_mut().set(&root_var, new_val.clone())?;
4908                    // Return the new value for method chaining
4909                    return Ok(new_val);
4910                }
4911
4912                // Handle field access like self.output.push(c)
4913                if let Expr::Field { expr: base_expr, field: field_ident } = receiver {
4914                    let base = self.evaluate(base_expr)?;
4915                    if let Value::Struct { fields, .. } = base {
4916                        fields.borrow_mut().insert(field_ident.name.clone(), new_val.clone());
4917                        // Return the new value for method chaining
4918                        return Ok(new_val);
4919                    }
4920                }
4921                // Fallback: can't mutate, just return the new string
4922                return Ok(new_val);
4923            }
4924        }
4925
4926        let recv_raw = self.evaluate(receiver)?;
4927        // Unwrap evidential/affective wrappers for method dispatch
4928        let recv = Self::unwrap_value(&recv_raw).clone();
4929
4930        // Debug: trace ALL method calls to find Lexer
4931        static METHOD_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
4932        let count = METHOD_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
4933        if count < 500 {
4934            let recv_type = match &recv {
4935                Value::Struct { name, .. } => format!("Struct({})", name),
4936                Value::String(s) => format!("String('{}')", if s.len() <= 20 { s.as_str() } else { "<long>" }),
4937                Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
4938                other => format!("{:?}", std::mem::discriminant(other)),
4939            };
4940            if recv_type.contains("Lexer") || method.name.contains("keyword") || method.name.contains("lex") {
4941                crate::sigil_debug!("DEBUG method #{}: {}.{}()", count, recv_type, method.name);
4942            }
4943        }
4944        let arg_values: Vec<Value> = args
4945            .iter()
4946            .map(|a| self.evaluate(a))
4947            .collect::<Result<_, _>>()?;
4948
4949        // Debug: Trace cloned/clone method calls
4950        if method.name == "cloned" || method.name == "clone" {
4951            let recv_type = match &recv {
4952                Value::Struct { name, .. } => format!("Struct({})", name),
4953                Value::Variant { enum_name, variant_name, .. } => format!("Variant({}::{})", enum_name, variant_name),
4954                Value::String(_) => "String".to_string(),
4955                Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
4956                Value::Null => "Null".to_string(),
4957                other => format!("{:?}", std::mem::discriminant(other)),
4958            };
4959            crate::sigil_debug!("DEBUG {}: recv_type={}", method.name, recv_type);
4960        }
4961
4962        // Debug: Trace ALL as_str calls
4963        if method.name == "as_str" {
4964            let recv_unwrapped = Self::unwrap_all(&recv);
4965            if let Value::String(s) = &recv_unwrapped {
4966                crate::sigil_debug!("DEBUG as_str CALL: recv='{}' len={}", s, s.len());
4967            } else {
4968                crate::sigil_debug!("DEBUG as_str CALL: recv={:?} (not string)", recv_unwrapped);
4969            }
4970        }
4971
4972        // Debug: trace keyword_or_ident method calls
4973        if method.name == "keyword_or_ident" {
4974            let recv_type = match &recv {
4975                Value::Struct { name, .. } => format!("Struct({})", name),
4976                Value::String(_) => "String".to_string(),
4977                Value::Ref(r) => format!("Ref({})", match &*r.borrow() {
4978                    Value::Struct { name, .. } => format!("Struct({})", name),
4979                    other => format!("{:?}", std::mem::discriminant(other)),
4980                }),
4981                other => format!("{:?}", std::mem::discriminant(other)),
4982            };
4983            crate::sigil_debug!("DEBUG keyword_or_ident: recv_type={}", recv_type);
4984        }
4985
4986        // Debug: Find "fn" as method argument
4987        for arg in &arg_values {
4988            let unwrapped = Self::unwrap_all(arg);
4989            if let Value::String(s) = &unwrapped {
4990                if **s == "fn" {
4991                    let recv_type = match &recv {
4992                        Value::Struct { name, .. } => format!("Struct({})", name),
4993                        Value::String(_) => "String".to_string(),
4994                        Value::Ref(_) => "Ref".to_string(),
4995                        other => format!("{:?}", std::mem::discriminant(other)),
4996                    };
4997                    crate::sigil_debug!("DEBUG method call with 'fn': method={}, recv_type={}", method.name, recv_type);
4998                }
4999            }
5000        }
5001
5002        // Built-in methods
5003        match (&recv, method.name.as_str()) {
5004            (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
5005            (Value::Array(arr), "push") => {
5006                if arg_values.len() != 1 {
5007                    return Err(RuntimeError::new("push expects 1 argument"));
5008                }
5009                arr.borrow_mut().push(arg_values[0].clone());
5010                Ok(Value::Null)
5011            }
5012            (Value::Array(arr), "pop") => arr
5013                .borrow_mut()
5014                .pop()
5015                .ok_or_else(|| RuntimeError::new("pop on empty array")),
5016            (Value::Array(arr), "extend") => {
5017                if arg_values.len() != 1 {
5018                    return Err(RuntimeError::new("extend expects 1 argument"));
5019                }
5020                match &arg_values[0] {
5021                    Value::Array(other) => {
5022                        arr.borrow_mut().extend(other.borrow().iter().cloned());
5023                        Ok(Value::Null)
5024                    }
5025                    _ => Err(RuntimeError::new("extend expects array argument")),
5026                }
5027            }
5028            (Value::Array(arr), "reverse") => {
5029                let mut v = arr.borrow().clone();
5030                v.reverse();
5031                Ok(Value::Array(Rc::new(RefCell::new(v))))
5032            }
5033            (Value::Array(arr), "skip") => {
5034                let n = match arg_values.first() {
5035                    Some(Value::Int(i)) => *i as usize,
5036                    _ => 1,
5037                };
5038                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
5039                Ok(Value::Array(Rc::new(RefCell::new(v))))
5040            }
5041            (Value::Array(arr), "take") => {
5042                let n = match arg_values.first() {
5043                    Some(Value::Int(i)) => *i as usize,
5044                    _ => 1,
5045                };
5046                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
5047                Ok(Value::Array(Rc::new(RefCell::new(v))))
5048            }
5049            (Value::Array(arr), "step_by") => {
5050                let n = match arg_values.first() {
5051                    Some(Value::Int(i)) if *i > 0 => *i as usize,
5052                    _ => 1,
5053                };
5054                let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
5055                Ok(Value::Array(Rc::new(RefCell::new(v))))
5056            }
5057            (Value::Array(arr), "contains") => {
5058                if arg_values.len() != 1 {
5059                    return Err(RuntimeError::new("contains expects 1 argument"));
5060                }
5061                let target = &arg_values[0];
5062                let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
5063                Ok(Value::Bool(found))
5064            }
5065            // Tuple methods
5066            (Value::Tuple(t), "to_string") | (Value::Tuple(t), "string") => {
5067                let s: Vec<String> = t.iter().map(|v| format!("{}", v)).collect();
5068                Ok(Value::String(Rc::new(format!("({})", s.join(", ")))))
5069            }
5070            (Value::Tuple(t), "len") => Ok(Value::Int(t.len() as i64)),
5071            (Value::Tuple(t), "first") => t.first().cloned().ok_or_else(|| RuntimeError::new("empty tuple")),
5072            (Value::Tuple(t), "last") => t.last().cloned().ok_or_else(|| RuntimeError::new("empty tuple")),
5073            (Value::Tuple(t), "get") => {
5074                let idx = match arg_values.first() {
5075                    Some(Value::Int(i)) => *i as usize,
5076                    _ => return Err(RuntimeError::new("get expects integer index")),
5077                };
5078                t.get(idx).cloned().ok_or_else(|| RuntimeError::new("tuple index out of bounds"))
5079            }
5080            (Value::Array(arr), "first") | (Value::Array(arr), "next") => Ok(arr
5081                .borrow()
5082                .first()
5083                .cloned()
5084                .unwrap_or(Value::Null)),
5085            (Value::Array(arr), "last") => arr
5086                .borrow()
5087                .last()
5088                .cloned()
5089                .ok_or_else(|| RuntimeError::new("empty array")),
5090            (Value::Array(arr), "iter") | (Value::Array(arr), "into_iter") => {
5091                // iter()/into_iter() on an array just returns the array - iteration happens in for loops
5092                Ok(Value::Array(arr.clone()))
5093            }
5094            (Value::Array(arr), "map") => {
5095                // map(closure) applies closure to each element
5096                if arg_values.len() != 1 {
5097                    return Err(RuntimeError::new("map expects 1 argument (closure)"));
5098                }
5099                match &arg_values[0] {
5100                    Value::Function(f) => {
5101                        let mut results = Vec::new();
5102                        for val in arr.borrow().iter() {
5103                            let result = self.call_function(f, vec![val.clone()])?;
5104                            results.push(result);
5105                        }
5106                        Ok(Value::Array(Rc::new(RefCell::new(results))))
5107                    }
5108                    _ => Err(RuntimeError::new("map expects closure argument")),
5109                }
5110            }
5111            (Value::Array(arr), "filter") => {
5112                // filter(predicate) keeps elements where predicate returns true
5113                if arg_values.len() != 1 {
5114                    return Err(RuntimeError::new("filter expects 1 argument (closure)"));
5115                }
5116                match &arg_values[0] {
5117                    Value::Function(f) => {
5118                        let mut results = Vec::new();
5119                        for val in arr.borrow().iter() {
5120                            let keep = self.call_function(f, vec![val.clone()])?;
5121                            if matches!(keep, Value::Bool(true)) {
5122                                results.push(val.clone());
5123                            }
5124                        }
5125                        Ok(Value::Array(Rc::new(RefCell::new(results))))
5126                    }
5127                    _ => Err(RuntimeError::new("filter expects closure argument")),
5128                }
5129            }
5130            (Value::Array(arr), "any") => {
5131                // any(predicate) returns true if any element satisfies predicate
5132                if arg_values.len() != 1 {
5133                    return Err(RuntimeError::new("any expects 1 argument (closure)"));
5134                }
5135                match &arg_values[0] {
5136                    Value::Function(f) => {
5137                        for val in arr.borrow().iter() {
5138                            let result = self.call_function(f, vec![val.clone()])?;
5139                            if matches!(result, Value::Bool(true)) {
5140                                return Ok(Value::Bool(true));
5141                            }
5142                        }
5143                        Ok(Value::Bool(false))
5144                    }
5145                    _ => Err(RuntimeError::new("any expects closure argument")),
5146                }
5147            }
5148            (Value::Array(arr), "all") => {
5149                // all(predicate) returns true if all elements satisfy predicate
5150                if arg_values.len() != 1 {
5151                    return Err(RuntimeError::new("all expects 1 argument (closure)"));
5152                }
5153                match &arg_values[0] {
5154                    Value::Function(f) => {
5155                        for val in arr.borrow().iter() {
5156                            let result = self.call_function(f, vec![val.clone()])?;
5157                            if !matches!(result, Value::Bool(true)) {
5158                                return Ok(Value::Bool(false));
5159                            }
5160                        }
5161                        Ok(Value::Bool(true))
5162                    }
5163                    _ => Err(RuntimeError::new("all expects closure argument")),
5164                }
5165            }
5166            (Value::Array(arr), "find") => {
5167                // find(predicate) returns first element satisfying predicate, or None
5168                if arg_values.len() != 1 {
5169                    return Err(RuntimeError::new("find expects 1 argument (closure)"));
5170                }
5171                match &arg_values[0] {
5172                    Value::Function(f) => {
5173                        for val in arr.borrow().iter() {
5174                            let result = self.call_function(f, vec![val.clone()])?;
5175                            if matches!(result, Value::Bool(true)) {
5176                                return Ok(Value::Variant {
5177                                    enum_name: "Option".to_string(),
5178                                    variant_name: "Some".to_string(),
5179                                    fields: Some(Rc::new(vec![val.clone()])),
5180                                });
5181                            }
5182                        }
5183                        Ok(Value::Variant {
5184                            enum_name: "Option".to_string(),
5185                            variant_name: "None".to_string(),
5186                            fields: None,
5187                        })
5188                    }
5189                    _ => Err(RuntimeError::new("find expects closure argument")),
5190                }
5191            }
5192            (Value::Array(arr), "enumerate") => {
5193                // enumerate() returns array of (index, value) tuples
5194                let enumerated: Vec<Value> = arr
5195                    .borrow()
5196                    .iter()
5197                    .enumerate()
5198                    .map(|(i, v)| Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()])))
5199                    .collect();
5200                Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
5201            }
5202            (Value::Array(arr), "zip") => {
5203                // zip with another array to create array of tuples
5204                if arg_values.len() != 1 {
5205                    return Err(RuntimeError::new("zip expects 1 argument"));
5206                }
5207                match &arg_values[0] {
5208                    Value::Array(other) => {
5209                        let a = arr.borrow();
5210                        let b = other.borrow();
5211                        let zipped: Vec<Value> = a.iter()
5212                            .zip(b.iter())
5213                            .map(|(x, y)| Value::Tuple(Rc::new(vec![x.clone(), y.clone()])))
5214                            .collect();
5215                        Ok(Value::Array(Rc::new(RefCell::new(zipped))))
5216                    }
5217                    _ => Err(RuntimeError::new("zip expects array argument")),
5218                }
5219            }
5220            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
5221            (Value::String(s), "chars") => {
5222                let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5223                Ok(Value::Array(Rc::new(RefCell::new(chars))))
5224            }
5225            (Value::String(s), "contains") => {
5226                if arg_values.len() != 1 {
5227                    return Err(RuntimeError::new("contains expects 1 argument"));
5228                }
5229                match &arg_values[0] {
5230                    Value::String(sub) => Ok(Value::Bool(s.contains(sub.as_str()))),
5231                    Value::Char(c) => Ok(Value::Bool(s.contains(*c))),
5232                    Value::Ref(inner) => {
5233                        if let Value::String(sub) = &*inner.borrow() {
5234                            Ok(Value::Bool(s.contains(sub.as_str())))
5235                        } else {
5236                            Err(RuntimeError::new("contains expects string or char"))
5237                        }
5238                    }
5239                    _ => Err(RuntimeError::new("contains expects string or char")),
5240                }
5241            }
5242            (Value::String(s), "as_str") => {
5243                if s.len() <= 10 { crate::sigil_debug!("DEBUG as_str: '{}'", s); }
5244                Ok(Value::String(s.clone()))
5245            }
5246            (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
5247            (Value::String(s), "into") => Ok(Value::String(s.clone())),  // into() for String just returns String
5248            (Value::String(s), "starts_with") => {
5249                if arg_values.len() != 1 {
5250                    return Err(RuntimeError::new("starts_with expects 1 argument"));
5251                }
5252                match &arg_values[0] {
5253                    Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
5254                    _ => Err(RuntimeError::new("starts_with expects string")),
5255                }
5256            }
5257            (Value::String(s), "ends_with") => {
5258                if arg_values.len() != 1 {
5259                    return Err(RuntimeError::new("ends_with expects 1 argument"));
5260                }
5261                match &arg_values[0] {
5262                    Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
5263                    _ => Err(RuntimeError::new("ends_with expects string")),
5264                }
5265            }
5266            (Value::String(s), "strip_prefix") => {
5267                if arg_values.len() != 1 {
5268                    return Err(RuntimeError::new("strip_prefix expects 1 argument"));
5269                }
5270                match &arg_values[0] {
5271                    Value::String(prefix) => {
5272                        match s.strip_prefix(prefix.as_str()) {
5273                            Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
5274                            None => Ok(Value::Null),
5275                        }
5276                    }
5277                    _ => Err(RuntimeError::new("strip_prefix expects string")),
5278                }
5279            }
5280            (Value::String(s), "strip_suffix") => {
5281                if arg_values.len() != 1 {
5282                    return Err(RuntimeError::new("strip_suffix expects 1 argument"));
5283                }
5284                match &arg_values[0] {
5285                    Value::String(suffix) => {
5286                        match s.strip_suffix(suffix.as_str()) {
5287                            Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
5288                            None => Ok(Value::Null),
5289                        }
5290                    }
5291                    _ => Err(RuntimeError::new("strip_suffix expects string")),
5292                }
5293            }
5294            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
5295            (Value::String(s), "find") => {
5296                if arg_values.len() != 1 {
5297                    return Err(RuntimeError::new("find expects 1 argument"));
5298                }
5299                match &arg_values[0] {
5300                    Value::Char(c) => {
5301                        match s.find(*c) {
5302                            Some(idx) => Ok(Value::Variant {
5303                                enum_name: "Option".to_string(),
5304                                variant_name: "Some".to_string(),
5305                                fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5306                            }),
5307                            None => Ok(Value::Variant {
5308                                enum_name: "Option".to_string(),
5309                                variant_name: "None".to_string(),
5310                                fields: None,
5311                            }),
5312                        }
5313                    }
5314                    Value::String(pattern) => {
5315                        match s.find(pattern.as_str()) {
5316                            Some(idx) => Ok(Value::Variant {
5317                                enum_name: "Option".to_string(),
5318                                variant_name: "Some".to_string(),
5319                                fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5320                            }),
5321                            None => Ok(Value::Variant {
5322                                enum_name: "Option".to_string(),
5323                                variant_name: "None".to_string(),
5324                                fields: None,
5325                            }),
5326                        }
5327                    }
5328                    Value::Function(f) => {
5329                        for (idx, c) in s.chars().enumerate() {
5330                            let result = self.call_function(f, vec![Value::Char(c)])?;
5331                            if let Value::Bool(true) = result {
5332                                return Ok(Value::Variant {
5333                                    enum_name: "Option".to_string(),
5334                                    variant_name: "Some".to_string(),
5335                                    fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5336                                });
5337                            }
5338                        }
5339                        Ok(Value::Variant {
5340                            enum_name: "Option".to_string(),
5341                            variant_name: "None".to_string(),
5342                            fields: None,
5343                        })
5344                    }
5345                    _ => Err(RuntimeError::new("find expects a char, string, or closure")),
5346                }
5347            }
5348            (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
5349            (Value::String(s), "concat") => {
5350                if arg_values.len() != 1 {
5351                    return Err(RuntimeError::new("concat expects 1 argument"));
5352                }
5353                match &arg_values[0] {
5354                    Value::String(other) => {
5355                        let mut result = (**s).clone();
5356                        result.push_str(other);
5357                        Ok(Value::String(Rc::new(result)))
5358                    }
5359                    _ => Err(RuntimeError::new("concat expects string argument")),
5360                }
5361            }
5362            (Value::String(s), "as_ptr") => {
5363                // Return the string itself - FFI emulation doesn't need real pointers
5364                Ok(Value::String(s.clone()))
5365            }
5366            (Value::String(_), "is_null") => Ok(Value::Bool(false)),
5367            (Value::Null, "is_null") => Ok(Value::Bool(true)),
5368            (Value::String(s), "char_at") => {
5369                if arg_values.len() != 1 {
5370                    return Err(RuntimeError::new("char_at expects 1 argument"));
5371                }
5372                let idx = match &arg_values[0] {
5373                    Value::Int(i) => *i as usize,
5374                    _ => return Err(RuntimeError::new("char_at expects integer index")),
5375                };
5376                // Use byte-based indexing to match the self-hosted lexer's pos tracking
5377                // which increments by c.len_utf8() (byte count, not character count)
5378                if idx < s.len() {
5379                    // Get the character starting at byte position idx
5380                    let remaining = &s[idx..];
5381                    match remaining.chars().next() {
5382                        Some(c) => Ok(Value::Char(c)),
5383                        None => Ok(Value::Null),
5384                    }
5385                } else {
5386                    Ok(Value::Null) // Out of bounds
5387                }
5388            }
5389            (Value::String(s), "chars") => {
5390                let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5391                Ok(Value::Array(Rc::new(RefCell::new(chars))))
5392            }
5393            (Value::String(s), "bytes") => {
5394                let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
5395                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
5396            }
5397            (Value::String(s), "split") => {
5398                if arg_values.len() != 1 {
5399                    return Err(RuntimeError::new("split expects 1 argument"));
5400                }
5401                match &arg_values[0] {
5402                    Value::String(sep) => {
5403                        let parts: Vec<Value> = s.split(sep.as_str())
5404                            .map(|p| Value::String(Rc::new(p.to_string())))
5405                            .collect();
5406                        Ok(Value::Array(Rc::new(RefCell::new(parts))))
5407                    }
5408                    Value::Char(sep) => {
5409                        let parts: Vec<Value> = s.split(*sep)
5410                            .map(|p| Value::String(Rc::new(p.to_string())))
5411                            .collect();
5412                        Ok(Value::Array(Rc::new(RefCell::new(parts))))
5413                    }
5414                    _ => Err(RuntimeError::new("split expects string or char separator")),
5415                }
5416            }
5417            // Char methods
5418            (Value::Char(c), "len_utf8") => Ok(Value::Int(c.len_utf8() as i64)),
5419            (Value::Char(c), "is_alphabetic") => Ok(Value::Bool(c.is_alphabetic())),
5420            (Value::Char(c), "is_alphanumeric") => Ok(Value::Bool(c.is_alphanumeric())),
5421            (Value::Char(c), "is_ascii_alphanumeric") => Ok(Value::Bool(c.is_ascii_alphanumeric())),
5422            (Value::Char(c), "is_ascii_alphabetic") => Ok(Value::Bool(c.is_ascii_alphabetic())),
5423            (Value::Char(c), "is_ascii_digit") => Ok(Value::Bool(c.is_ascii_digit())),
5424            (Value::Char(c), "is_ascii_hexdigit") => Ok(Value::Bool(c.is_ascii_hexdigit())),
5425            (Value::Char(c), "is_ascii") => Ok(Value::Bool(c.is_ascii())),
5426            (Value::Char(c), "is_digit") => {
5427                let radix = if arg_values.is_empty() { 10 } else {
5428                    match &arg_values[0] {
5429                        Value::Int(n) => *n as u32,
5430                        _ => 10,
5431                    }
5432                };
5433                Ok(Value::Bool(c.is_digit(radix)))
5434            }
5435            (Value::Char(c), "is_numeric") => Ok(Value::Bool(c.is_numeric())),
5436            (Value::Char(c), "is_whitespace") => Ok(Value::Bool(c.is_whitespace())),
5437            (Value::Char(c), "is_uppercase") => Ok(Value::Bool(c.is_uppercase())),
5438            (Value::Char(c), "is_lowercase") => Ok(Value::Bool(c.is_lowercase())),
5439            (Value::Char(c), "to_uppercase") => {
5440                let upper: String = c.to_uppercase().collect();
5441                Ok(Value::String(Rc::new(upper)))
5442            }
5443            (Value::Char(c), "to_lowercase") => {
5444                let lower: String = c.to_lowercase().collect();
5445                Ok(Value::String(Rc::new(lower)))
5446            }
5447            (Value::Char(c), "to_string") => Ok(Value::String(Rc::new(c.to_string()))),
5448            (Value::Char(c), "to_digit") => {
5449                let radix = if arg_values.is_empty() { 10 } else {
5450                    match &arg_values[0] {
5451                        Value::Int(n) => *n as u32,
5452                        _ => 10,
5453                    }
5454                };
5455                match c.to_digit(radix) {
5456                    Some(d) => Ok(Value::Int(d as i64)),
5457                    None => Ok(Value::Null),
5458                }
5459            }
5460            (Value::Char(c), "to_ascii_uppercase") => Ok(Value::Char(c.to_ascii_uppercase())),
5461            (Value::Char(c), "to_ascii_lowercase") => Ok(Value::Char(c.to_ascii_lowercase())),
5462            (Value::Char(c), "clone") => Ok(Value::Char(*c)),
5463            (Value::String(s), "upper") | (Value::String(s), "uppercase") | (Value::String(s), "to_uppercase") => {
5464                Ok(Value::String(Rc::new(s.to_uppercase())))
5465            }
5466            (Value::String(s), "lower") | (Value::String(s), "lowercase") | (Value::String(s), "to_lowercase") => {
5467                Ok(Value::String(Rc::new(s.to_lowercase())))
5468            }
5469            (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
5470            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
5471            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
5472            // Path-like methods for strings (treat string as file path)
5473            (Value::String(s), "exists") => Ok(Value::Bool(std::path::Path::new(s.as_str()).exists())),
5474            (Value::String(s), "is_dir") => Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir())),
5475            (Value::String(s), "is_file") => Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file())),
5476            (Value::String(s), "join") => {
5477                // Path join: "dir".join("file") => "dir/file"
5478                if arg_values.len() != 1 {
5479                    return Err(RuntimeError::new(&format!("join expects 1 argument, got {}", arg_values.len())));
5480                }
5481                let other = match &arg_values[0] {
5482                    Value::String(s2) => s2.as_str().to_string(),
5483                    other => return Err(RuntimeError::new(&format!("join expects String argument, got {:?}", other))),
5484                };
5485                let path = std::path::Path::new(s.as_str()).join(&other);
5486                Ok(Value::String(Rc::new(path.to_string_lossy().to_string())))
5487            }
5488            (Value::String(s), "parent") => {
5489                // Get parent directory
5490                let path = std::path::Path::new(s.as_str());
5491                match path.parent() {
5492                    Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
5493                    None => Ok(Value::Null),
5494                }
5495            }
5496            (Value::String(s), "file_name") => {
5497                // Get file name component
5498                let path = std::path::Path::new(s.as_str());
5499                match path.file_name() {
5500                    Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5501                    None => Ok(Value::Null),
5502                }
5503            }
5504            (Value::String(s), "extension") => {
5505                // Get file extension
5506                let path = std::path::Path::new(s.as_str());
5507                match path.extension() {
5508                    Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5509                    None => Ok(Value::Null),
5510                }
5511            }
5512            // Result-like chaining for strings (used when string represents a Result-like value)
5513            (Value::String(_), "and_then") | (Value::String(_), "or_else") => {
5514                // Just pass through - these are no-ops for plain strings
5515                Ok(recv.clone())
5516            }
5517            (Value::String(s), "first") => s
5518                .chars()
5519                .next()
5520                .map(Value::Char)
5521                .ok_or_else(|| RuntimeError::new("empty string")),
5522            (Value::String(s), "last") => s
5523                .chars()
5524                .last()
5525                .map(Value::Char)
5526                .ok_or_else(|| RuntimeError::new("empty string")),
5527            (Value::Array(arr), "is_empty") => Ok(Value::Bool(arr.borrow().is_empty())),
5528            (Value::Array(arr), "clone") => Ok(Value::Array(Rc::new(RefCell::new(arr.borrow().clone())))),
5529            (Value::Array(arr), "collect") => {
5530                // collect() on array just returns the array itself
5531                // It's the terminal operation that materializes pipeline results
5532                Ok(Value::Array(arr.clone()))
5533            }
5534            (Value::Array(arr), "join") => {
5535                let separator = if arg_values.is_empty() {
5536                    String::new()
5537                } else {
5538                    match &arg_values[0] {
5539                        Value::String(s) => (**s).clone(),
5540                        _ => return Err(RuntimeError::new("join separator must be string")),
5541                    }
5542                };
5543                let parts: Vec<String> = arr.borrow().iter()
5544                    .map(|v| self.format_value(v))
5545                    .collect();
5546                Ok(Value::String(Rc::new(parts.join(&separator))))
5547            }
5548            // Map methods
5549            (Value::Map(m), "insert") => {
5550                if arg_values.len() != 2 {
5551                    return Err(RuntimeError::new("insert expects 2 arguments"));
5552                }
5553                let key = match &arg_values[0] {
5554                    Value::String(s) => (**s).clone(),
5555                    _ => format!("{}", arg_values[0]),
5556                };
5557                m.borrow_mut().insert(key, arg_values[1].clone());
5558                Ok(Value::Null)
5559            }
5560            (Value::Map(m), "get") => {
5561                if arg_values.len() != 1 {
5562                    return Err(RuntimeError::new("get expects 1 argument"));
5563                }
5564                let key = match &arg_values[0] {
5565                    Value::String(s) => (**s).clone(),
5566                    _ => format!("{}", arg_values[0]),
5567                };
5568                Ok(m.borrow().get(&key).cloned().unwrap_or(Value::Null))
5569            }
5570            (Value::Map(m), "contains_key") => {
5571                if arg_values.len() != 1 {
5572                    return Err(RuntimeError::new("contains_key expects 1 argument"));
5573                }
5574                let key = match &arg_values[0] {
5575                    Value::String(s) => (**s).clone(),
5576                    _ => format!("{}", arg_values[0]),
5577                };
5578                Ok(Value::Bool(m.borrow().contains_key(&key)))
5579            }
5580            (Value::Map(m), "len") => Ok(Value::Int(m.borrow().len() as i64)),
5581            (Value::Map(m), "is_empty") => Ok(Value::Bool(m.borrow().is_empty())),
5582            (Value::Map(m), "keys") => {
5583                let keys: Vec<Value> = m.borrow().keys()
5584                    .map(|k| Value::String(Rc::new(k.clone())))
5585                    .collect();
5586                Ok(Value::Array(Rc::new(RefCell::new(keys))))
5587            }
5588            (Value::Map(m), "values") => {
5589                let values: Vec<Value> = m.borrow().values().cloned().collect();
5590                Ok(Value::Array(Rc::new(RefCell::new(values))))
5591            }
5592            // RefCell methods - interior mutability with runtime borrow checking
5593            (Value::RefCellValue(rc), "borrow") => {
5594                // Get immutable reference to inner value
5595                let state = rc.borrow_state.borrow().clone();
5596                match state {
5597                    BorrowState::BorrowedMut => {
5598                        Err(RuntimeError::new("RefCell already mutably borrowed"))
5599                    }
5600                    BorrowState::Borrowed(count) => {
5601                        *rc.borrow_state.borrow_mut() = BorrowState::Borrowed(count + 1);
5602                        Ok(rc.value.borrow().clone())
5603                    }
5604                    BorrowState::Unborrowed => {
5605                        *rc.borrow_state.borrow_mut() = BorrowState::Borrowed(1);
5606                        Ok(rc.value.borrow().clone())
5607                    }
5608                }
5609            }
5610            (Value::RefCellValue(rc), "borrow_mut") => {
5611                // Get mutable reference to inner value
5612                let state = rc.borrow_state.borrow().clone();
5613                match state {
5614                    BorrowState::BorrowedMut => {
5615                        Err(RuntimeError::new("RefCell already mutably borrowed"))
5616                    }
5617                    BorrowState::Borrowed(_) => {
5618                        Err(RuntimeError::new("RefCell already borrowed"))
5619                    }
5620                    BorrowState::Unborrowed => {
5621                        *rc.borrow_state.borrow_mut() = BorrowState::BorrowedMut;
5622                        // Return a Ref so mutations can be synced back
5623                        Ok(Value::Ref(Rc::new(RefCell::new(rc.value.borrow().clone()))))
5624                    }
5625                }
5626            }
5627            (Value::RefCellValue(rc), "get") => {
5628                // Convenience method to get a copy of the value (like Cell::get)
5629                Ok(rc.value.borrow().clone())
5630            }
5631            (Value::RefCellValue(rc), "set") => {
5632                // Set the inner value (like Cell::set but with borrow checking)
5633                if arg_values.len() != 1 {
5634                    return Err(RuntimeError::new("set expects 1 argument"));
5635                }
5636                let state = rc.borrow_state.borrow().clone();
5637                match state {
5638                    BorrowState::BorrowedMut => {
5639                        Err(RuntimeError::new("RefCell is mutably borrowed, cannot set"))
5640                    }
5641                    BorrowState::Borrowed(_) => {
5642                        Err(RuntimeError::new("RefCell is borrowed, cannot set"))
5643                    }
5644                    BorrowState::Unborrowed => {
5645                        *rc.value.borrow_mut() = arg_values[0].clone();
5646                        Ok(Value::Null)
5647                    }
5648                }
5649            }
5650            (Value::RefCellValue(rc), "into_inner") => {
5651                // Consume the RefCell and return inner value
5652                Ok(rc.value.borrow().clone())
5653            }
5654            (Value::RefCellValue(rc), "replace") => {
5655                // Replace the inner value, returning the old one
5656                if arg_values.len() != 1 {
5657                    return Err(RuntimeError::new("replace expects 1 argument"));
5658                }
5659                let state = rc.borrow_state.borrow().clone();
5660                match state {
5661                    BorrowState::BorrowedMut | BorrowState::Borrowed(_) => {
5662                        Err(RuntimeError::new("RefCell is borrowed, cannot replace"))
5663                    }
5664                    BorrowState::Unborrowed => {
5665                        let old = rc.value.borrow().clone();
5666                        *rc.value.borrow_mut() = arg_values[0].clone();
5667                        Ok(old)
5668                    }
5669                }
5670            }
5671            // TraitObject methods - dynamic dispatch
5672            (Value::TraitObject { value, concrete_type, trait_name }, _) => {
5673                // Look up the method on the concrete type
5674                let qualified_name = format!("{}·{}", concrete_type, method.name);
5675                let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
5676
5677                if let Some(func) = func {
5678                    if let Value::Function(f) = func {
5679                        // Set current Self type for Self { ... } resolution
5680                        let old_self_type = self.current_self_type.take();
5681                        self.current_self_type = Some(concrete_type.clone());
5682
5683                        // Pass the inner value as receiver
5684                        let mut all_args = vec![(**value).clone()];
5685                        all_args.extend(arg_values.clone());
5686                        let result = self.call_function(&f, all_args);
5687
5688                        // Restore old Self type
5689                        self.current_self_type = old_self_type;
5690                        return result;
5691                    } else if let Value::BuiltIn(b) = func {
5692                        let mut all_args = vec![(**value).clone()];
5693                        all_args.extend(arg_values.clone());
5694                        return (b.func)(self, all_args);
5695                    }
5696                }
5697
5698                // Method not found
5699                Err(RuntimeError::new(format!(
5700                    "Method '{}' not found for trait object '{}' with concrete type '{}'",
5701                    method.name, trait_name, concrete_type
5702                )))
5703            }
5704            // Ref methods
5705            (Value::Ref(r), "cloned") => {
5706                // Clone the inner value
5707                Ok(r.borrow().clone())
5708            }
5709            (Value::Ref(r), "borrow") => {
5710                // Return a reference to the inner value
5711                Ok(recv.clone())
5712            }
5713            (Value::Ref(r), "borrow_mut") => {
5714                // Return a reference to the inner value (mutable in place)
5715                Ok(recv.clone())
5716            }
5717            // Forward method calls on Ref to inner value (struct method lookup)
5718            (Value::Ref(r), _) => {
5719                // Dereference and look up method on inner struct
5720                let inner = r.borrow().clone();
5721                if let Value::Struct { name, fields } = &inner {
5722                    // Try struct method lookup with the inner struct
5723                    let qualified_name = format!("{}·{}", name, method.name);
5724                    let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
5725                    if let Some(func) = func {
5726                        if let Value::Function(f) = func {
5727                            // Set current Self type for Self { ... } resolution
5728                            let old_self_type = self.current_self_type.take();
5729                            self.current_self_type = Some(name.clone());
5730
5731                            // Pass the Ref as the receiver (for &mut self methods)
5732                            let mut all_args = vec![recv.clone()];
5733                            all_args.extend(arg_values.clone());
5734                            let result = self.call_function(&f, all_args);
5735
5736                            // Restore old Self type
5737                            self.current_self_type = old_self_type;
5738                            return result;
5739                        } else if let Value::BuiltIn(b) = func {
5740                            let mut all_args = vec![recv.clone()];
5741                            all_args.extend(arg_values.clone());
5742                            return (b.func)(self, all_args);
5743                        }
5744                    }
5745
5746                    // If struct name is "Self", search by matching field names
5747                    if name == "Self" {
5748                        let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
5749
5750                        // Search through registered types to find a matching struct
5751                        for (type_name, type_def) in &self.types {
5752                            if let TypeDef::Struct(struct_def) = type_def {
5753                                let def_fields: Vec<String> = match &struct_def.fields {
5754                                    crate::ast::StructFields::Named(fs) => fs.iter().map(|f| f.name.name.clone()).collect(),
5755                                    _ => continue,
5756                                };
5757
5758                                // Match if our fields exist in the definition
5759                                let matches = field_names.iter().all(|f| def_fields.contains(f));
5760                                if matches {
5761                                    let qualified_name = format!("{}·{}", type_name, method.name);
5762                                    let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
5763                                    if let Some(func) = func {
5764                                        if let Value::Function(f) = func {
5765                                            // Set current Self type for Self { ... } resolution
5766                                            let old_self_type = self.current_self_type.take();
5767                                            self.current_self_type = Some(type_name.clone());
5768
5769                                            let mut all_args = vec![recv.clone()];
5770                                            all_args.extend(arg_values.clone());
5771                                            let result = self.call_function(&f, all_args);
5772
5773                                            // Restore old Self type
5774                                            self.current_self_type = old_self_type;
5775                                            return result;
5776                                        } else if let Value::BuiltIn(b) = func {
5777                                            let mut all_args = vec![recv.clone()];
5778                                            all_args.extend(arg_values.clone());
5779                                            return (b.func)(self, all_args);
5780                                        }
5781                                    }
5782                                }
5783                            }
5784                        }
5785                    }
5786
5787                    // Built-in methods for PathBuf struct
5788                    if name == "PathBuf" || name == "Path" {
5789                        if let Some(Value::String(path)) = fields.borrow().get("path").cloned() {
5790                            match method.name.as_str() {
5791                                "exists" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).exists())),
5792                                "is_dir" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_dir())),
5793                                "is_file" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_file())),
5794                                "join" => {
5795                                    if let Some(Value::String(other)) = arg_values.first() {
5796                                        let new_path = std::path::Path::new(path.as_str()).join(other.as_str());
5797                                        let mut new_fields = std::collections::HashMap::new();
5798                                        new_fields.insert("path".to_string(), Value::String(Rc::new(new_path.to_string_lossy().to_string())));
5799                                        return Ok(Value::Struct {
5800                                            name: "PathBuf".to_string(),
5801                                            fields: Rc::new(RefCell::new(new_fields)),
5802                                        });
5803                                    }
5804                                    return Err(RuntimeError::new("join requires string argument"));
5805                                }
5806                                "parent" => {
5807                                    let p = std::path::Path::new(path.as_str());
5808                                    return match p.parent() {
5809                                        Some(par) => {
5810                                            let mut new_fields = std::collections::HashMap::new();
5811                                            new_fields.insert("path".to_string(), Value::String(Rc::new(par.to_string_lossy().to_string())));
5812                                            Ok(Value::Struct {
5813                                                name: "PathBuf".to_string(),
5814                                                fields: Rc::new(RefCell::new(new_fields)),
5815                                            })
5816                                        }
5817                                        None => Ok(Value::Null),
5818                                    };
5819                                }
5820                                "file_name" => {
5821                                    let p = std::path::Path::new(path.as_str());
5822                                    return match p.file_name() {
5823                                        Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5824                                        None => Ok(Value::Null),
5825                                    };
5826                                }
5827                                "extension" => {
5828                                    let p = std::path::Path::new(path.as_str());
5829                                    return match p.extension() {
5830                                        Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5831                                        None => Ok(Value::Null),
5832                                    };
5833                                }
5834                                "to_string" | "display" | "to_str" => {
5835                                    return Ok(Value::String(path.clone()));
5836                                }
5837                                _ => {}
5838                            }
5839                        }
5840                    }
5841
5842                    // Fallback for unknown methods on external type references: return null
5843                    crate::sigil_warn!("WARN: Unknown method '{}' on '&{}' - returning null", method.name, name);
5844                    return Ok(Value::Null);
5845                }
5846                // For non-struct refs (like &str), auto-deref and call method on inner value
5847                // Handle common methods on &str (reference to String)
5848                if let Value::String(s) = &inner {
5849                    match method.name.as_str() {
5850                        "to_string" => return Ok(Value::String(s.clone())),
5851                        "len" => return Ok(Value::Int(s.len() as i64)),
5852                        "is_empty" => return Ok(Value::Bool(s.is_empty())),
5853                        "as_str" => return Ok(Value::String(s.clone())),
5854                        "starts_with" => {
5855                            let prefix = match arg_values.first() {
5856                                Some(Value::String(p)) => p.as_str(),
5857                                Some(Value::Char(c)) => return Ok(Value::Bool(s.starts_with(*c))),
5858                                _ => return Err(RuntimeError::new("starts_with expects string or char")),
5859                            };
5860                            return Ok(Value::Bool(s.starts_with(prefix)));
5861                        }
5862                        "ends_with" => {
5863                            let suffix = match arg_values.first() {
5864                                Some(Value::String(p)) => p.as_str(),
5865                                Some(Value::Char(c)) => return Ok(Value::Bool(s.ends_with(*c))),
5866                                _ => return Err(RuntimeError::new("ends_with expects string or char")),
5867                            };
5868                            return Ok(Value::Bool(s.ends_with(suffix)));
5869                        }
5870                        "contains" => {
5871                            let substr = match arg_values.first() {
5872                                Some(Value::String(p)) => p.as_str(),
5873                                Some(Value::Char(c)) => return Ok(Value::Bool(s.contains(*c))),
5874                                _ => return Err(RuntimeError::new("contains expects string or char")),
5875                            };
5876                            return Ok(Value::Bool(s.contains(substr)));
5877                        }
5878                        "trim" => return Ok(Value::String(Rc::new(s.trim().to_string()))),
5879                        "to_lowercase" => return Ok(Value::String(Rc::new(s.to_lowercase()))),
5880                        "to_uppercase" => return Ok(Value::String(Rc::new(s.to_uppercase()))),
5881                        "chars" => {
5882                            let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5883                            return Ok(Value::Array(Rc::new(RefCell::new(chars))));
5884                        }
5885                        "split" => {
5886                            let delim = match arg_values.first() {
5887                                Some(Value::String(d)) => d.as_str().to_string(),
5888                                Some(Value::Char(c)) => c.to_string(),
5889                                _ => " ".to_string(),
5890                            };
5891                            let parts: Vec<Value> = s.split(&delim)
5892                                .map(|p| Value::String(Rc::new(p.to_string())))
5893                                .collect();
5894                            return Ok(Value::Array(Rc::new(RefCell::new(parts))));
5895                        }
5896                        "replace" => {
5897                            if arg_values.len() != 2 {
5898                                return Err(RuntimeError::new("replace expects 2 arguments"));
5899                            }
5900                            let from = match &arg_values[0] {
5901                                Value::String(f) => f.as_str().to_string(),
5902                                Value::Char(c) => c.to_string(),
5903                                _ => return Err(RuntimeError::new("replace expects strings")),
5904                            };
5905                            let to = match &arg_values[1] {
5906                                Value::String(t) => t.as_str().to_string(),
5907                                Value::Char(c) => c.to_string(),
5908                                _ => return Err(RuntimeError::new("replace expects strings")),
5909                            };
5910                            return Ok(Value::String(Rc::new(s.replace(&from, &to))));
5911                        }
5912                        _ => {}
5913                    }
5914                }
5915                // Handle methods on &[T] and &mut [T] (references to arrays/slices)
5916                if let Value::Array(arr) = &inner {
5917                    match method.name.as_str() {
5918                        "len" => return Ok(Value::Int(arr.borrow().len() as i64)),
5919                        "is_empty" => return Ok(Value::Bool(arr.borrow().is_empty())),
5920                        "push" => {
5921                            if arg_values.len() != 1 {
5922                                return Err(RuntimeError::new("push expects 1 argument"));
5923                            }
5924                            arr.borrow_mut().push(arg_values[0].clone());
5925                            return Ok(Value::Null);
5926                        }
5927                        "pop" => {
5928                            return arr.borrow_mut().pop()
5929                                .ok_or_else(|| RuntimeError::new("pop on empty array"));
5930                        }
5931                        "contains" => {
5932                            if arg_values.len() != 1 {
5933                                return Err(RuntimeError::new("contains expects 1 argument"));
5934                            }
5935                            let target = &arg_values[0];
5936                            let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
5937                            return Ok(Value::Bool(found));
5938                        }
5939                        "first" | "next" => {
5940                            return Ok(arr.borrow().first().cloned().unwrap_or(Value::Null));
5941                        }
5942                        "last" => {
5943                            return arr.borrow().last().cloned()
5944                                .ok_or_else(|| RuntimeError::new("empty array"));
5945                        }
5946                        "iter" | "into_iter" => {
5947                            return Ok(Value::Array(arr.clone()));
5948                        }
5949                        "reverse" => {
5950                            let mut v = arr.borrow().clone();
5951                            v.reverse();
5952                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
5953                        }
5954                        "skip" => {
5955                            let n = match arg_values.first() {
5956                                Some(Value::Int(i)) => *i as usize,
5957                                _ => 1,
5958                            };
5959                            let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
5960                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
5961                        }
5962                        "take" => {
5963                            let n = match arg_values.first() {
5964                                Some(Value::Int(i)) => *i as usize,
5965                                _ => 1,
5966                            };
5967                            let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
5968                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
5969                        }
5970                        "get" => {
5971                            let idx = match arg_values.first() {
5972                                Some(Value::Int(i)) => *i as usize,
5973                                _ => return Err(RuntimeError::new("get expects integer index")),
5974                            };
5975                            return Ok(arr.borrow().get(idx).cloned().unwrap_or(Value::Null));
5976                        }
5977                        _ => {}
5978                    }
5979                }
5980                // Handle clone on any Ref value - clone the inner value
5981                if method.name == "clone" {
5982                    crate::sigil_debug!("DEBUG clone: recv_type=Ref({:?})", std::mem::discriminant(&inner));
5983                    return Ok(inner.clone());
5984                }
5985                // Handle into on Ref value - convert to owned value
5986                if method.name == "into" {
5987                    return Ok(inner.clone());
5988                }
5989                // Handle to_string on Ref value
5990                if method.name == "to_string" {
5991                    return Ok(Value::String(Rc::new(format!("{}", inner))));
5992                }
5993                // Path methods for Ref containing PathBuf struct
5994                if let Value::Struct { name, fields, .. } = &inner {
5995                    if name == "PathBuf" || name == "Path" {
5996                        let borrowed = fields.borrow();
5997                        if let Some(Value::String(path)) = borrowed.get("path") {
5998                            match method.name.as_str() {
5999                                "exists" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).exists())),
6000                                "is_dir" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_dir())),
6001                                "is_file" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_file())),
6002                                "join" => {
6003                                    if let Some(Value::String(other)) = arg_values.first() {
6004                                        let new_path = std::path::Path::new(path.as_str()).join(other.as_str());
6005                                        let mut new_fields = std::collections::HashMap::new();
6006                                        new_fields.insert("path".to_string(), Value::String(Rc::new(new_path.to_string_lossy().to_string())));
6007                                        return Ok(Value::Struct {
6008                                            name: "PathBuf".to_string(),
6009                                            fields: Rc::new(RefCell::new(new_fields)),
6010                                        });
6011                                    }
6012                                    return Err(RuntimeError::new("join requires string argument"));
6013                                }
6014                                "parent" => {
6015                                    let p = std::path::Path::new(path.as_str());
6016                                    return match p.parent() {
6017                                        Some(par) => {
6018                                            let mut new_fields = std::collections::HashMap::new();
6019                                            new_fields.insert("path".to_string(), Value::String(Rc::new(par.to_string_lossy().to_string())));
6020                                            Ok(Value::Struct {
6021                                                name: "PathBuf".to_string(),
6022                                                fields: Rc::new(RefCell::new(new_fields)),
6023                                            })
6024                                        }
6025                                        None => Ok(Value::Null),
6026                                    };
6027                                }
6028                                "file_name" => {
6029                                    let p = std::path::Path::new(path.as_str());
6030                                    return match p.file_name() {
6031                                        Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
6032                                        None => Ok(Value::Null),
6033                                    };
6034                                }
6035                                "extension" => {
6036                                    let p = std::path::Path::new(path.as_str());
6037                                    return match p.extension() {
6038                                        Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
6039                                        None => Ok(Value::Null),
6040                                    };
6041                                }
6042                                "to_string" | "display" => {
6043                                    return Ok(Value::String(path.clone()));
6044                                }
6045                                _ => {}
6046                            }
6047                        }
6048                    }
6049                }
6050                // Path methods for Ref containing String (PathBuf behavior)
6051                if let Value::String(s) = &inner {
6052                    match method.name.as_str() {
6053                        "exists" => return Ok(Value::Bool(std::path::Path::new(s.as_str()).exists())),
6054                        "is_dir" => return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir())),
6055                        "is_file" => return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file())),
6056                        "join" => {
6057                            if let Some(Value::String(other)) = arg_values.first() {
6058                                let path = std::path::Path::new(s.as_str()).join(other.as_str());
6059                                return Ok(Value::String(Rc::new(path.to_string_lossy().to_string())));
6060                            }
6061                            return Err(RuntimeError::new("join requires string argument"));
6062                        }
6063                        "parent" => {
6064                            let path = std::path::Path::new(s.as_str());
6065                            return match path.parent() {
6066                                Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
6067                                None => Ok(Value::Null),
6068                            };
6069                        }
6070                        "file_name" => {
6071                            let path = std::path::Path::new(s.as_str());
6072                            return match path.file_name() {
6073                                Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
6074                                None => Ok(Value::Null),
6075                            };
6076                        }
6077                        "extension" => {
6078                            let path = std::path::Path::new(s.as_str());
6079                            return match path.extension() {
6080                                Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
6081                                None => Ok(Value::Null),
6082                            };
6083                        }
6084                        _ => {}
6085                    }
6086                }
6087                // If the inner value is a string, recursively call method dispatch
6088                // This handles cases like &s[..].find(...) where we have a Ref to a String slice
6089                if let Value::String(_) = inner {
6090                    // Recursively dispatch method call on the inner string
6091                    // Create a temporary receiver with the unwrapped string
6092                    let recv_unwrapped = inner.clone();
6093                    match (&recv_unwrapped, method.name.as_str()) {
6094                        (Value::String(s), "find") => {
6095                            if arg_values.len() != 1 {
6096                                return Err(RuntimeError::new("find expects 1 argument"));
6097                            }
6098                            match &arg_values[0] {
6099                                Value::Char(c) => {
6100                                    return match s.find(*c) {
6101                                        Some(idx) => Ok(Value::Variant {
6102                                            enum_name: "Option".to_string(),
6103                                            variant_name: "Some".to_string(),
6104                                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
6105                                        }),
6106                                        None => Ok(Value::Variant {
6107                                            enum_name: "Option".to_string(),
6108                                            variant_name: "None".to_string(),
6109                                            fields: None,
6110                                        }),
6111                                    }
6112                                }
6113                                Value::String(pattern) => {
6114                                    return match s.find(pattern.as_str()) {
6115                                        Some(idx) => Ok(Value::Variant {
6116                                            enum_name: "Option".to_string(),
6117                                            variant_name: "Some".to_string(),
6118                                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
6119                                        }),
6120                                        None => Ok(Value::Variant {
6121                                            enum_name: "Option".to_string(),
6122                                            variant_name: "None".to_string(),
6123                                            fields: None,
6124                                        }),
6125                                    }
6126                                }
6127                                Value::Function(f) => {
6128                                    for (idx, c) in s.chars().enumerate() {
6129                                        let result = self.call_function(f, vec![Value::Char(c)])?;
6130                                        if let Value::Bool(true) = result {
6131                                            return Ok(Value::Variant {
6132                                                enum_name: "Option".to_string(),
6133                                                variant_name: "Some".to_string(),
6134                                                fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
6135                                            });
6136                                        }
6137                                    }
6138                                    return Ok(Value::Variant {
6139                                        enum_name: "Option".to_string(),
6140                                        variant_name: "None".to_string(),
6141                                        fields: None,
6142                                    })
6143                                }
6144                                _ => return Err(RuntimeError::new("find expects a char, string, or closure")),
6145                            }
6146                        }
6147                        (Value::String(s), "trim") => return Ok(Value::String(Rc::new(s.trim().to_string()))),
6148                        (Value::String(s), "is_empty") => return Ok(Value::Bool(s.is_empty())),
6149                        (Value::String(s), "len") => return Ok(Value::Int(s.len() as i64)),
6150                        (Value::String(s), "to_string") => return Ok(Value::String(s.clone())),
6151                        (Value::String(s), "chars") => {
6152                            let chars: Vec<Value> = s.chars().map(Value::Char).collect();
6153                            return Ok(Value::Array(Rc::new(RefCell::new(chars))))
6154                        }
6155                        (Value::String(s), "starts_with") => {
6156                            if let Some(Value::String(prefix)) = arg_values.first() {
6157                                return Ok(Value::Bool(s.starts_with(prefix.as_str())));
6158                            }
6159                            return Err(RuntimeError::new("starts_with expects string argument"));
6160                        }
6161                        _ => {}
6162                    }
6163                }
6164                Err(RuntimeError::new(format!(
6165                    "Cannot call method {} on Ref to non-struct",
6166                    method.name
6167                )))
6168            }
6169            // Try struct method lookup: StructName·method
6170            (Value::Struct { name, fields }, _) => {
6171                // Built-in struct methods
6172                if method.name == "clone" {
6173                    // Clone the struct value
6174                    return Ok(recv.clone());
6175                }
6176                // PathBuf struct methods
6177                if name == "PathBuf" || name == "Path" {
6178                    let borrowed = fields.borrow();
6179                    if let Some(Value::String(path)) = borrowed.get("path") {
6180                        match method.name.as_str() {
6181                            "exists" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).exists())),
6182                            "is_dir" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_dir())),
6183                            "is_file" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_file())),
6184                            "join" => {
6185                                if let Some(Value::String(other)) = arg_values.first() {
6186                                    let new_path = std::path::Path::new(path.as_str()).join(other.as_str());
6187                                    let mut new_fields = std::collections::HashMap::new();
6188                                    new_fields.insert("path".to_string(), Value::String(Rc::new(new_path.to_string_lossy().to_string())));
6189                                    return Ok(Value::Struct {
6190                                        name: "PathBuf".to_string(),
6191                                        fields: Rc::new(RefCell::new(new_fields)),
6192                                    });
6193                                }
6194                                return Err(RuntimeError::new("join requires string argument"));
6195                            }
6196                            "parent" => {
6197                                let p = std::path::Path::new(path.as_str());
6198                                return match p.parent() {
6199                                    Some(par) => {
6200                                        let mut new_fields = std::collections::HashMap::new();
6201                                        new_fields.insert("path".to_string(), Value::String(Rc::new(par.to_string_lossy().to_string())));
6202                                        Ok(Value::Struct {
6203                                            name: "PathBuf".to_string(),
6204                                            fields: Rc::new(RefCell::new(new_fields)),
6205                                        })
6206                                    }
6207                                    None => Ok(Value::Null),
6208                                };
6209                            }
6210                            "file_name" => {
6211                                let p = std::path::Path::new(path.as_str());
6212                                return match p.file_name() {
6213                                    Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
6214                                    None => Ok(Value::Null),
6215                                };
6216                            }
6217                            "extension" => {
6218                                let p = std::path::Path::new(path.as_str());
6219                                return match p.extension() {
6220                                    Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
6221                                    None => Ok(Value::Null),
6222                                };
6223                            }
6224                            "to_string" | "display" => {
6225                                return Ok(Value::String(path.clone()));
6226                            }
6227                            _ => {}
6228                        }
6229                    }
6230                }
6231                // Rc struct methods
6232                if name == "Rc" {
6233                    let borrowed = fields.borrow();
6234                    if let Some(value) = borrowed.get("_value") {
6235                        match method.name.as_str() {
6236                            "clone" => {
6237                                // Return a new Rc with same value
6238                                let mut new_fields = HashMap::new();
6239                                new_fields.insert("_value".to_string(), value.clone());
6240                                return Ok(Value::Struct {
6241                                    name: "Rc".to_string(),
6242                                    fields: Rc::new(RefCell::new(new_fields)),
6243                                });
6244                            }
6245                            _ => {}
6246                        }
6247                    }
6248                }
6249                // Cell struct methods
6250                if name == "Cell" {
6251                    match method.name.as_str() {
6252                        "get" => {
6253                            let borrowed = fields.borrow();
6254                            if let Some(value) = borrowed.get("_value") {
6255                                return Ok(value.clone());
6256                            }
6257                            return Err(RuntimeError::new("Cell has no value"));
6258                        }
6259                        "set" => {
6260                            if arg_values.len() != 1 {
6261                                return Err(RuntimeError::new("set expects 1 argument"));
6262                            }
6263                            fields.borrow_mut().insert("_value".to_string(), arg_values[0].clone());
6264                            return Ok(Value::Null);
6265                        }
6266                        _ => {}
6267                    }
6268                }
6269                // Duration struct methods
6270                if name == "Duration" {
6271                    let borrowed = fields.borrow();
6272                    let secs = match borrowed.get("secs") {
6273                        Some(Value::Int(s)) => *s,
6274                        _ => 0,
6275                    };
6276                    let nanos = match borrowed.get("nanos") {
6277                        Some(Value::Int(n)) => *n,
6278                        _ => 0,
6279                    };
6280                    match method.name.as_str() {
6281                        "as_secs" => return Ok(Value::Int(secs)),
6282                        "as_millis" => return Ok(Value::Int(secs * 1000 + nanos / 1_000_000)),
6283                        "as_micros" => return Ok(Value::Int(secs * 1_000_000 + nanos / 1000)),
6284                        "as_nanos" => return Ok(Value::Int(secs * 1_000_000_000 + nanos)),
6285                        "subsec_nanos" => return Ok(Value::Int(nanos)),
6286                        "subsec_millis" => return Ok(Value::Int(nanos / 1_000_000)),
6287                        "is_zero" => return Ok(Value::Bool(secs == 0 && nanos == 0)),
6288                        _ => {}
6289                    }
6290                }
6291                // Mutex methods - lock() returns a Ref to the inner value
6292                if name == "Mutex" {
6293                    match method.name.as_str() {
6294                        "lock" => {
6295                            // lock() returns a guard that provides access to inner value
6296                            // In the interpreter, we just return a Ref to the inner value
6297                            let borrowed = fields.borrow();
6298                            if let Some(inner) = borrowed.get("__inner__") {
6299                                // Return a Ref wrapping the inner value for mutation
6300                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6301                            }
6302                            return Err(RuntimeError::new("Mutex has no inner value"));
6303                        }
6304                        "try_lock" => {
6305                            // try_lock() returns Some(guard) - in interpreter always succeeds
6306                            let borrowed = fields.borrow();
6307                            if let Some(inner) = borrowed.get("__inner__") {
6308                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6309                                return Ok(Value::Variant {
6310                                    enum_name: "Option".to_string(),
6311                                    variant_name: "Some".to_string(),
6312                                    fields: Some(Rc::new(vec![guard])),
6313                                });
6314                            }
6315                            return Ok(Value::Variant {
6316                                enum_name: "Option".to_string(),
6317                                variant_name: "None".to_string(),
6318                                fields: None,
6319                            });
6320                        }
6321                        "into_inner" => {
6322                            // into_inner() consumes the mutex and returns the inner value
6323                            let borrowed = fields.borrow();
6324                            if let Some(inner) = borrowed.get("__inner__") {
6325                                return Ok(inner.clone());
6326                            }
6327                            return Err(RuntimeError::new("Mutex has no inner value"));
6328                        }
6329                        "get_mut" => {
6330                            // get_mut() returns &mut T when we have exclusive access
6331                            let borrowed = fields.borrow();
6332                            if let Some(inner) = borrowed.get("__inner__") {
6333                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6334                            }
6335                            return Err(RuntimeError::new("Mutex has no inner value"));
6336                        }
6337                        _ => {}
6338                    }
6339                }
6340                // RwLock methods - read() and write() return guards
6341                if name == "RwLock" {
6342                    match method.name.as_str() {
6343                        "read" => {
6344                            // read() returns a read guard
6345                            let borrowed = fields.borrow();
6346                            if let Some(inner) = borrowed.get("__inner__") {
6347                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6348                            }
6349                            return Err(RuntimeError::new("RwLock has no inner value"));
6350                        }
6351                        "write" => {
6352                            // write() returns a write guard
6353                            let borrowed = fields.borrow();
6354                            if let Some(inner) = borrowed.get("__inner__") {
6355                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6356                            }
6357                            return Err(RuntimeError::new("RwLock has no inner value"));
6358                        }
6359                        "try_read" => {
6360                            let borrowed = fields.borrow();
6361                            if let Some(inner) = borrowed.get("__inner__") {
6362                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6363                                return Ok(Value::Variant {
6364                                    enum_name: "Option".to_string(),
6365                                    variant_name: "Some".to_string(),
6366                                    fields: Some(Rc::new(vec![guard])),
6367                                });
6368                            }
6369                            return Ok(Value::Variant {
6370                                enum_name: "Option".to_string(),
6371                                variant_name: "None".to_string(),
6372                                fields: None,
6373                            });
6374                        }
6375                        "try_write" => {
6376                            let borrowed = fields.borrow();
6377                            if let Some(inner) = borrowed.get("__inner__") {
6378                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6379                                return Ok(Value::Variant {
6380                                    enum_name: "Option".to_string(),
6381                                    variant_name: "Some".to_string(),
6382                                    fields: Some(Rc::new(vec![guard])),
6383                                });
6384                            }
6385                            return Ok(Value::Variant {
6386                                enum_name: "Option".to_string(),
6387                                variant_name: "None".to_string(),
6388                                fields: None,
6389                            });
6390                        }
6391                        "into_inner" => {
6392                            let borrowed = fields.borrow();
6393                            if let Some(inner) = borrowed.get("__inner__") {
6394                                return Ok(inner.clone());
6395                            }
6396                            return Err(RuntimeError::new("RwLock has no inner value"));
6397                        }
6398                        _ => {}
6399                    }
6400                }
6401                // Atomic methods - load/store/fetch_add etc.
6402                if name == "AtomicU64" || name == "AtomicUsize" || name == "AtomicI64" || name == "AtomicIsize" {
6403                    match method.name.as_str() {
6404                        "load" => {
6405                            // load() returns the current value
6406                            let borrowed = fields.borrow();
6407                            if let Some(val) = borrowed.get("__value__") {
6408                                return Ok(val.clone());
6409                            }
6410                            return Ok(Value::Int(0));
6411                        }
6412                        "store" => {
6413                            // store(value) sets the value
6414                            if let Some(new_val) = arg_values.first() {
6415                                fields.borrow_mut().insert("__value__".to_string(), new_val.clone());
6416                                return Ok(Value::Null);
6417                            }
6418                            return Err(RuntimeError::new("store requires a value"));
6419                        }
6420                        "fetch_add" => {
6421                            // fetch_add(n) adds n and returns old value
6422                            if let Some(Value::Int(n)) = arg_values.first() {
6423                                let mut borrowed = fields.borrow_mut();
6424                                let old = match borrowed.get("__value__") {
6425                                    Some(Value::Int(v)) => *v,
6426                                    _ => 0,
6427                                };
6428                                borrowed.insert("__value__".to_string(), Value::Int(old + n));
6429                                return Ok(Value::Int(old));
6430                            }
6431                            return Err(RuntimeError::new("fetch_add requires integer"));
6432                        }
6433                        "fetch_sub" => {
6434                            if let Some(Value::Int(n)) = arg_values.first() {
6435                                let mut borrowed = fields.borrow_mut();
6436                                let old = match borrowed.get("__value__") {
6437                                    Some(Value::Int(v)) => *v,
6438                                    _ => 0,
6439                                };
6440                                borrowed.insert("__value__".to_string(), Value::Int(old - n));
6441                                return Ok(Value::Int(old));
6442                            }
6443                            return Err(RuntimeError::new("fetch_sub requires integer"));
6444                        }
6445                        "swap" => {
6446                            if let Some(new_val) = arg_values.first() {
6447                                let mut borrowed = fields.borrow_mut();
6448                                let old = borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
6449                                borrowed.insert("__value__".to_string(), new_val.clone());
6450                                return Ok(old);
6451                            }
6452                            return Err(RuntimeError::new("swap requires a value"));
6453                        }
6454                        "compare_exchange" | "compare_and_swap" => {
6455                            // compare_exchange(current, new) - if value == current, set to new
6456                            if arg_values.len() >= 2 {
6457                                let current = &arg_values[0];
6458                                let new_val = &arg_values[1];
6459                                let mut borrowed = fields.borrow_mut();
6460                                let actual = borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
6461                                if self.values_equal(&actual, current) {
6462                                    borrowed.insert("__value__".to_string(), new_val.clone());
6463                                    return Ok(Value::Variant {
6464                                        enum_name: "Result".to_string(),
6465                                        variant_name: "Ok".to_string(),
6466                                        fields: Some(Rc::new(vec![actual])),
6467                                    });
6468                                } else {
6469                                    return Ok(Value::Variant {
6470                                        enum_name: "Result".to_string(),
6471                                        variant_name: "Err".to_string(),
6472                                        fields: Some(Rc::new(vec![actual])),
6473                                    });
6474                                }
6475                            }
6476                            return Err(RuntimeError::new("compare_exchange requires two arguments"));
6477                        }
6478                        _ => {}
6479                    }
6480                }
6481                // AtomicBool methods
6482                if name == "AtomicBool" {
6483                    match method.name.as_str() {
6484                        "load" => {
6485                            let borrowed = fields.borrow();
6486                            if let Some(val) = borrowed.get("__value__") {
6487                                return Ok(val.clone());
6488                            }
6489                            return Ok(Value::Bool(false));
6490                        }
6491                        "store" => {
6492                            if let Some(new_val) = arg_values.first() {
6493                                fields.borrow_mut().insert("__value__".to_string(), new_val.clone());
6494                                return Ok(Value::Null);
6495                            }
6496                            return Err(RuntimeError::new("store requires a value"));
6497                        }
6498                        "swap" => {
6499                            if let Some(new_val) = arg_values.first() {
6500                                let mut borrowed = fields.borrow_mut();
6501                                let old = borrowed.get("__value__").cloned().unwrap_or(Value::Bool(false));
6502                                borrowed.insert("__value__".to_string(), new_val.clone());
6503                                return Ok(old);
6504                            }
6505                            return Err(RuntimeError::new("swap requires a value"));
6506                        }
6507                        "fetch_and" => {
6508                            if let Some(Value::Bool(b)) = arg_values.first() {
6509                                let mut borrowed = fields.borrow_mut();
6510                                let old = match borrowed.get("__value__") {
6511                                    Some(Value::Bool(v)) => *v,
6512                                    _ => false,
6513                                };
6514                                borrowed.insert("__value__".to_string(), Value::Bool(old && *b));
6515                                return Ok(Value::Bool(old));
6516                            }
6517                            return Err(RuntimeError::new("fetch_and requires boolean"));
6518                        }
6519                        "fetch_or" => {
6520                            if let Some(Value::Bool(b)) = arg_values.first() {
6521                                let mut borrowed = fields.borrow_mut();
6522                                let old = match borrowed.get("__value__") {
6523                                    Some(Value::Bool(v)) => *v,
6524                                    _ => false,
6525                                };
6526                                borrowed.insert("__value__".to_string(), Value::Bool(old || *b));
6527                                return Ok(Value::Bool(old));
6528                            }
6529                            return Err(RuntimeError::new("fetch_or requires boolean"));
6530                        }
6531                        _ => {}
6532                    }
6533                }
6534                if method.name == "to_string" {
6535                    // Generic to_string for structs - returns a debug representation
6536                    let field_str = fields.borrow().iter()
6537                        .map(|(k, v)| format!("{}: {}", k, v))
6538                        .collect::<Vec<_>>()
6539                        .join(", ");
6540                    return Ok(Value::String(Rc::new(format!("{} {{ {} }}", name, field_str))));
6541                }
6542
6543                // Pattern methods - for AST patterns stored as structs (Pattern::Ident, Pattern::Tuple, etc.)
6544                if name.starts_with("Pattern::") {
6545                    match method.name.as_str() {
6546                        "evidentiality" => {
6547                            // Return the evidentiality field from the pattern struct
6548                            if let Some(ev) = fields.borrow().get("evidentiality") {
6549                                return Ok(ev.clone());
6550                            }
6551                            return Ok(Value::Null);
6552                        }
6553                        "name" | "binding_name" => {
6554                            // Return the name field from the pattern struct (for binding purposes)
6555                            if let Some(n) = fields.borrow().get("name") {
6556                                // The name field might be an Ident struct with a nested "name" field
6557                                // Extract the inner string if that's the case
6558                                let result = match &n {
6559                                    Value::Struct { fields: inner_fields, .. } => {
6560                                        if let Some(inner_name) = inner_fields.borrow().get("name") {
6561                                            crate::sigil_debug!("DEBUG binding_name: returning inner name {} from {}", inner_name, name);
6562                                            inner_name.clone()
6563                                        } else {
6564                                            crate::sigil_debug!("DEBUG binding_name: returning struct {} from {}", n, name);
6565                                            n.clone()
6566                                        }
6567                                    }
6568                                    _ => {
6569                                        crate::sigil_debug!("DEBUG binding_name: returning {} from {}", n, name);
6570                                        n.clone()
6571                                    }
6572                                };
6573                                return Ok(result);
6574                            }
6575                            crate::sigil_debug!("DEBUG binding_name: 'name' field not found in {}, fields: {:?}", name, fields.borrow().keys().collect::<Vec<_>>());
6576                            // For Pattern::Ident, name is the binding name
6577                            return Ok(Value::Null);
6578                        }
6579                        "mutable" => {
6580                            // Return the mutable field from the pattern struct
6581                            if let Some(m) = fields.borrow().get("mutable") {
6582                                return Ok(m.clone());
6583                            }
6584                            return Ok(Value::Bool(false));
6585                        }
6586                        "is_ident" => {
6587                            return Ok(Value::Bool(name == "Pattern::Ident"));
6588                        }
6589                        "is_wildcard" => {
6590                            return Ok(Value::Bool(name == "Pattern::Wildcard"));
6591                        }
6592                        "clone" => {
6593                            return Ok(recv.clone());
6594                        }
6595                        _ => {}
6596                    }
6597                }
6598
6599                // PathBuf methods
6600                if name == "PathBuf" || name == "Path" {
6601                    match method.name.as_str() {
6602                        "exists" => {
6603                            // Check if path exists
6604                            let path = match fields.borrow().get("path") {
6605                                Some(Value::String(s)) => s.to_string(),
6606                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6607                            };
6608                            return Ok(Value::Bool(std::path::Path::new(&path).exists()));
6609                        }
6610                        "is_dir" => {
6611                            let path = match fields.borrow().get("path") {
6612                                Some(Value::String(s)) => s.to_string(),
6613                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6614                            };
6615                            return Ok(Value::Bool(std::path::Path::new(&path).is_dir()));
6616                        }
6617                        "is_file" => {
6618                            let path = match fields.borrow().get("path") {
6619                                Some(Value::String(s)) => s.to_string(),
6620                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6621                            };
6622                            return Ok(Value::Bool(std::path::Path::new(&path).is_file()));
6623                        }
6624                        "extension" => {
6625                            let path = match fields.borrow().get("path") {
6626                                Some(Value::String(s)) => s.to_string(),
6627                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6628                            };
6629                            match std::path::Path::new(&path).extension() {
6630                                Some(ext) => {
6631                                    // Return Option::Some with an OsStr-like struct
6632                                    let ext_str = ext.to_string_lossy().to_string();
6633                                    let mut ext_fields = HashMap::new();
6634                                    ext_fields.insert("value".to_string(), Value::String(Rc::new(ext_str)));
6635                                    return Ok(Value::Variant {
6636                                        enum_name: "Option".to_string(),
6637                                        variant_name: "Some".to_string(),
6638                                        fields: Some(Rc::new(vec![Value::Struct {
6639                                            name: "OsStr".to_string(),
6640                                            fields: Rc::new(RefCell::new(ext_fields)),
6641                                        }])),
6642                                    });
6643                                }
6644                                None => {
6645                                    return Ok(Value::Variant {
6646                                        enum_name: "Option".to_string(),
6647                                        variant_name: "None".to_string(),
6648                                        fields: None,
6649                                    });
6650                                }
6651                            }
6652                        }
6653                        "file_name" => {
6654                            let path = match fields.borrow().get("path") {
6655                                Some(Value::String(s)) => s.to_string(),
6656                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6657                            };
6658                            match std::path::Path::new(&path).file_name() {
6659                                Some(fname) => {
6660                                    let fname_str = fname.to_string_lossy().to_string();
6661                                    let mut fname_fields = HashMap::new();
6662                                    fname_fields.insert("value".to_string(), Value::String(Rc::new(fname_str)));
6663                                    return Ok(Value::Variant {
6664                                        enum_name: "Option".to_string(),
6665                                        variant_name: "Some".to_string(),
6666                                        fields: Some(Rc::new(vec![Value::Struct {
6667                                            name: "OsStr".to_string(),
6668                                            fields: Rc::new(RefCell::new(fname_fields)),
6669                                        }])),
6670                                    });
6671                                }
6672                                None => {
6673                                    return Ok(Value::Variant {
6674                                        enum_name: "Option".to_string(),
6675                                        variant_name: "None".to_string(),
6676                                        fields: None,
6677                                    });
6678                                }
6679                            }
6680                        }
6681                        "parent" => {
6682                            let path = match fields.borrow().get("path") {
6683                                Some(Value::String(s)) => s.to_string(),
6684                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6685                            };
6686                            match std::path::Path::new(&path).parent() {
6687                                Some(parent) => {
6688                                    let mut parent_fields = HashMap::new();
6689                                    parent_fields.insert("path".to_string(), Value::String(Rc::new(parent.to_string_lossy().to_string())));
6690                                    return Ok(Value::Variant {
6691                                        enum_name: "Option".to_string(),
6692                                        variant_name: "Some".to_string(),
6693                                        fields: Some(Rc::new(vec![Value::Struct {
6694                                            name: "Path".to_string(),
6695                                            fields: Rc::new(RefCell::new(parent_fields)),
6696                                        }])),
6697                                    });
6698                                }
6699                                None => {
6700                                    return Ok(Value::Variant {
6701                                        enum_name: "Option".to_string(),
6702                                        variant_name: "None".to_string(),
6703                                        fields: None,
6704                                    });
6705                                }
6706                            }
6707                        }
6708                        "to_str" => {
6709                            // Convert to string (returns Option<&str>, we just return the string)
6710                            let path = match fields.borrow().get("path") {
6711                                Some(Value::String(s)) => s.clone(),
6712                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6713                            };
6714                            // Wrap in Some for unwrap() compatibility
6715                            return Ok(Value::Variant {
6716                                enum_name: "Option".to_string(),
6717                                variant_name: "Some".to_string(),
6718                                fields: Some(Rc::new(vec![Value::String(path)])),
6719                            });
6720                        }
6721                        "to_string_lossy" => {
6722                            let path = match fields.borrow().get("path") {
6723                                Some(Value::String(s)) => s.clone(),
6724                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6725                            };
6726                            return Ok(Value::String(path));
6727                        }
6728                        "join" => {
6729                            // Join path with another component
6730                            if arg_values.is_empty() {
6731                                return Err(RuntimeError::new("join expects 1 argument"));
6732                            }
6733                            let base = match fields.borrow().get("path") {
6734                                Some(Value::String(s)) => s.to_string(),
6735                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6736                            };
6737                            let component = match &arg_values[0] {
6738                                Value::String(s) => s.to_string(),
6739                                Value::Struct { name: n, fields: f } if n == "PathBuf" || n == "Path" => {
6740                                    match f.borrow().get("path") {
6741                                        Some(Value::String(s)) => s.to_string(),
6742                                        _ => return Err(RuntimeError::new("PathBuf has no path field")),
6743                                    }
6744                                }
6745                                _ => return Err(RuntimeError::new("join expects string or PathBuf")),
6746                            };
6747                            let joined = std::path::Path::new(&base).join(&component);
6748                            let mut new_fields = HashMap::new();
6749                            new_fields.insert("path".to_string(), Value::String(Rc::new(joined.to_string_lossy().to_string())));
6750                            return Ok(Value::Struct {
6751                                name: "PathBuf".to_string(),
6752                                fields: Rc::new(RefCell::new(new_fields)),
6753                            });
6754                        }
6755                        "display" => {
6756                            let path = match fields.borrow().get("path") {
6757                                Some(Value::String(s)) => s.clone(),
6758                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6759                            };
6760                            return Ok(Value::String(path));
6761                        }
6762                        "to_path_buf" => {
6763                            // Path -> PathBuf (just return a copy)
6764                            return Ok(recv.clone());
6765                        }
6766                        _ => {}
6767                    }
6768                }
6769
6770                // OsStr methods
6771                if name == "OsStr" {
6772                    match method.name.as_str() {
6773                        "to_str" => {
6774                            let val = match fields.borrow().get("value") {
6775                                Some(Value::String(s)) => s.clone(),
6776                                _ => return Err(RuntimeError::new("OsStr has no value field")),
6777                            };
6778                            return Ok(Value::Variant {
6779                                enum_name: "Option".to_string(),
6780                                variant_name: "Some".to_string(),
6781                                fields: Some(Rc::new(vec![Value::String(val)])),
6782                            });
6783                        }
6784                        "to_string_lossy" => {
6785                            let val = match fields.borrow().get("value") {
6786                                Some(Value::String(s)) => s.clone(),
6787                                _ => return Err(RuntimeError::new("OsStr has no value field")),
6788                            };
6789                            return Ok(Value::String(val));
6790                        }
6791                        "to_lowercase" => {
6792                            let val = match fields.borrow().get("value") {
6793                                Some(Value::String(s)) => s.to_lowercase(),
6794                                _ => return Err(RuntimeError::new("OsStr has no value field")),
6795                            };
6796                            return Ok(Value::String(Rc::new(val)));
6797                        }
6798                        "as_str" => {
6799                            let val = match fields.borrow().get("value") {
6800                                Some(Value::String(s)) => s.clone(),
6801                                _ => return Err(RuntimeError::new("OsStr has no value field")),
6802                            };
6803                            return Ok(Value::String(val));
6804                        }
6805                        _ => {}
6806                    }
6807                }
6808
6809                // DirEntry methods
6810                if name == "DirEntry" {
6811                    match method.name.as_str() {
6812                        "path" => {
6813                            let path = match fields.borrow().get("path") {
6814                                Some(Value::String(s)) => s.clone(),
6815                                _ => return Err(RuntimeError::new("DirEntry has no path field")),
6816                            };
6817                            let mut path_fields = HashMap::new();
6818                            path_fields.insert("path".to_string(), Value::String(path));
6819                            return Ok(Value::Struct {
6820                                name: "PathBuf".to_string(),
6821                                fields: Rc::new(RefCell::new(path_fields)),
6822                            });
6823                        }
6824                        "file_name" => {
6825                            let path = match fields.borrow().get("path") {
6826                                Some(Value::String(s)) => s.to_string(),
6827                                _ => return Err(RuntimeError::new("DirEntry has no path field")),
6828                            };
6829                            let fname = std::path::Path::new(&path)
6830                                .file_name()
6831                                .map(|f| f.to_string_lossy().to_string())
6832                                .unwrap_or_default();
6833                            let mut fname_fields = HashMap::new();
6834                            fname_fields.insert("value".to_string(), Value::String(Rc::new(fname)));
6835                            return Ok(Value::Struct {
6836                                name: "OsStr".to_string(),
6837                                fields: Rc::new(RefCell::new(fname_fields)),
6838                            });
6839                        }
6840                        _ => {}
6841                    }
6842                }
6843
6844                // Map methods - for built-in hash map operations
6845                if name == "Map" {
6846                    match method.name.as_str() {
6847                        "get" => {
6848                            // map.get(key) -> ?value
6849                            if arg_values.len() != 1 {
6850                                return Err(RuntimeError::new("Map.get expects 1 argument"));
6851                            }
6852                            let key = match &arg_values[0] {
6853                                Value::String(s) => s.to_string(),
6854                                Value::Int(n) => n.to_string(),
6855                                other => format!("{:?}", other),
6856                            };
6857                            if let Some(val) = fields.borrow().get(&key) {
6858                                return Ok(val.clone());
6859                            }
6860                            return Ok(Value::Null);
6861                        }
6862                        "insert" => {
6863                            // map.insert(key, value)
6864                            if arg_values.len() != 2 {
6865                                return Err(RuntimeError::new("Map.insert expects 2 arguments"));
6866                            }
6867                            let key = match &arg_values[0] {
6868                                Value::String(s) => s.to_string(),
6869                                Value::Int(n) => n.to_string(),
6870                                other => format!("{:?}", other),
6871                            };
6872                            crate::sigil_debug!("DEBUG Map.insert: key='{}', value={}", key, arg_values[1]);
6873                            fields.borrow_mut().insert(key, arg_values[1].clone());
6874                            return Ok(Value::Null);
6875                        }
6876                        "contains_key" => {
6877                            if arg_values.len() != 1 {
6878                                return Err(RuntimeError::new("Map.contains_key expects 1 argument"));
6879                            }
6880                            let key = match &arg_values[0] {
6881                                Value::String(s) => s.to_string(),
6882                                Value::Int(n) => n.to_string(),
6883                                other => format!("{:?}", other),
6884                            };
6885                            return Ok(Value::Bool(fields.borrow().contains_key(&key)));
6886                        }
6887                        "len" => {
6888                            return Ok(Value::Int(fields.borrow().len() as i64));
6889                        }
6890                        "is_empty" => {
6891                            return Ok(Value::Bool(fields.borrow().is_empty()));
6892                        }
6893                        "keys" => {
6894                            let keys: Vec<Value> = fields.borrow()
6895                                .keys()
6896                                .map(|k| Value::String(Rc::new(k.clone())))
6897                                .collect();
6898                            return Ok(Value::Array(Rc::new(RefCell::new(keys))));
6899                        }
6900                        "values" => {
6901                            let vals: Vec<Value> = fields.borrow()
6902                                .values()
6903                                .cloned()
6904                                .collect();
6905                            return Ok(Value::Array(Rc::new(RefCell::new(vals))));
6906                        }
6907                        "clone" => {
6908                            return Ok(recv.clone());
6909                        }
6910                        _ => {}
6911                    }
6912                }
6913
6914                let qualified_name = format!("{}·{}", name, method.name);
6915
6916                // Debug: track Parser method calls
6917                if name == "Parser" && (method.name == "parse_file" || method.name == "read_source") {
6918                    crate::sigil_debug!("DEBUG Parser method call: {}", qualified_name);
6919                    for (i, arg) in arg_values.iter().enumerate() {
6920                        crate::sigil_debug!("  arg_value[{}] = {:?}", i, arg);
6921                    }
6922                }
6923
6924                // Debug: track Lexer method calls
6925                if name == "Lexer" {
6926                    // Print all args for lex_ident_or_keyword
6927                    if method.name == "lex_ident_or_keyword" {
6928                        for (i, arg) in arg_values.iter().enumerate() {
6929                            let unwrapped = Self::unwrap_all(arg);
6930                            if let Value::Char(c) = &unwrapped {
6931                                crate::sigil_debug!("DEBUG Lexer·lex_ident_or_keyword arg[{}]='{}'", i, c);
6932                            }
6933                        }
6934                    }
6935                    crate::sigil_debug!("DEBUG Lexer method call: {}", qualified_name);
6936                }
6937                // Check if arg is "fn" string
6938                for arg in &arg_values {
6939                    let unwrapped = Self::unwrap_all(arg);
6940                    if let Value::String(s) = &unwrapped {
6941                        if **s == "fn" {
6942                            crate::sigil_debug!("DEBUG struct method with 'fn': {} recv_name={}", method.name, name);
6943                        }
6944                    }
6945                }
6946
6947                let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
6948                if let Some(func) = func {
6949                    if let Value::Function(f) = func {
6950                        // Set current Self type for Self { ... } resolution
6951                        let old_self_type = self.current_self_type.take();
6952                        self.current_self_type = Some(name.clone());
6953
6954                        // Call with self as first argument
6955                        let mut all_args = vec![recv.clone()];
6956                        all_args.extend(arg_values.clone());
6957                        let result = self.call_function(&f, all_args);
6958
6959                        // Restore old Self type
6960                        self.current_self_type = old_self_type;
6961                        return result;
6962                    } else if let Value::BuiltIn(b) = func {
6963                        let mut all_args = vec![recv.clone()];
6964                        all_args.extend(arg_values.clone());
6965                        return (b.func)(self, all_args);
6966                    }
6967                }
6968
6969                // If struct name is "Self", try to find the method by searching all types
6970                if name == "Self" {
6971                    // Get field names to match struct type
6972                    let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
6973
6974                    // Search through registered types to find a matching struct
6975                    for (type_name, type_def) in &self.types {
6976                        if let TypeDef::Struct(struct_def) = type_def {
6977                            // Check if field names match
6978                            let def_fields: Vec<String> = match &struct_def.fields {
6979                                crate::ast::StructFields::Named(fs) => fs.iter().map(|f| f.name.name.clone()).collect(),
6980                                _ => continue,
6981                            };
6982
6983                            // Rough match - if we have fields that exist in the definition
6984                            let matches = field_names.iter().all(|f| def_fields.contains(f));
6985                            if matches {
6986                                let qualified_name = format!("{}·{}", type_name, method.name);
6987                                let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
6988                                if let Some(func) = func {
6989                                    if let Value::Function(f) = func {
6990                                        // Set current Self type for Self { ... } resolution
6991                                        let old_self_type = self.current_self_type.take();
6992                                        self.current_self_type = Some(type_name.clone());
6993
6994                                        let mut all_args = vec![recv.clone()];
6995                                        all_args.extend(arg_values.clone());
6996                                        let result = self.call_function(&f, all_args);
6997
6998                                        // Restore old Self type
6999                                        self.current_self_type = old_self_type;
7000                                        return result;
7001                                    } else if let Value::BuiltIn(b) = func {
7002                                        let mut all_args = vec![recv.clone()];
7003                                        all_args.extend(arg_values.clone());
7004                                        return (b.func)(self, all_args);
7005                                    }
7006                                }
7007                            }
7008                        }
7009                    }
7010                }
7011
7012                // Fallback for unknown methods on external types: return null
7013                // This allows code using external crate types to run without full loading
7014                crate::sigil_warn!("WARN: Unknown method '{}' on '{}' - returning null", method.name, name);
7015                Ok(Value::Null)
7016            }
7017            // Try variant method lookup: EnumName·method
7018            (Value::Variant { enum_name, variant_name, fields }, _) => {
7019                // Built-in Option methods
7020                if enum_name == "Option" {
7021                    match method.name.as_str() {
7022                        "cloned" => {
7023                            // cloned() on Option<&T> returns Option<T>
7024                            // In our interpreter, just clone the value
7025                            return Ok(recv.clone());
7026                        }
7027                        "is_some" => {
7028                            return Ok(Value::Bool(variant_name == "Some"));
7029                        }
7030                        "is_none" => {
7031                            return Ok(Value::Bool(variant_name == "None"));
7032                        }
7033                        "unwrap" => {
7034                            crate::sigil_debug!("DEBUG Option.unwrap: variant={}, fields={:?}", variant_name, fields);
7035                            if variant_name == "Some" {
7036                                if let Some(f) = fields {
7037                                    let result = f.first().cloned().unwrap_or(Value::Null);
7038                                    crate::sigil_debug!("DEBUG Option.unwrap: returning {:?}", result);
7039                                    return Ok(result);
7040                                }
7041                            }
7042                            return Err(RuntimeError::new("unwrap on None"));
7043                        }
7044                        "unwrap_or" => {
7045                            if variant_name == "Some" {
7046                                if let Some(f) = fields {
7047                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
7048                                }
7049                            }
7050                            return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
7051                        }
7052                        "map" => {
7053                            // Option::map takes a closure
7054                            if variant_name == "Some" {
7055                                if let Some(f) = fields {
7056                                    if let Some(inner) = f.first() {
7057                                        if let Some(Value::Function(func)) = arg_values.first() {
7058                                            let result = self.call_function(func, vec![inner.clone()])?;
7059                                            return Ok(Value::Variant {
7060                                                enum_name: "Option".to_string(),
7061                                                variant_name: "Some".to_string(),
7062                                                fields: Some(Rc::new(vec![result])),
7063                                            });
7064                                        }
7065                                    }
7066                                }
7067                            }
7068                            return Ok(Value::Variant {
7069                                enum_name: "Option".to_string(),
7070                                variant_name: "None".to_string(),
7071                                fields: None,
7072                            });
7073                        }
7074                        "and_then" => {
7075                            // Option::and_then takes a closure that returns Option<U>
7076                            crate::sigil_debug!("DEBUG and_then: variant={}, has_fields={}, arg_count={}", variant_name, fields.is_some(), arg_values.len());
7077                            if let Some(arg) = arg_values.first() {
7078                                crate::sigil_debug!("DEBUG and_then: arg type = {:?}", std::mem::discriminant(arg));
7079                            }
7080                            if variant_name == "Some" {
7081                                if let Some(f) = fields {
7082                                    if let Some(inner) = f.first() {
7083                                        crate::sigil_debug!("DEBUG and_then: inner = {:?}", inner);
7084                                        if let Some(Value::Function(func)) = arg_values.first() {
7085                                            let result = self.call_function(func, vec![inner.clone()])?;
7086                                            crate::sigil_debug!("DEBUG and_then: result = {:?}", result);
7087                                            // The closure should return an Option, return it directly
7088                                            return Ok(result);
7089                                        } else {
7090                                            crate::sigil_debug!("DEBUG and_then: arg is not a Function!");
7091                                        }
7092                                    }
7093                                }
7094                            }
7095                            // None case - return None
7096                            return Ok(Value::Variant {
7097                                enum_name: "Option".to_string(),
7098                                variant_name: "None".to_string(),
7099                                fields: None,
7100                            });
7101                        }
7102                        "or_else" => {
7103                            // Option::or_else takes a closure that returns Option<T>
7104                            if variant_name == "Some" {
7105                                // Some case - return self
7106                                return Ok(recv.clone());
7107                            }
7108                            // None case - call the closure
7109                            if let Some(Value::Function(func)) = arg_values.first() {
7110                                return self.call_function(func, vec![]);
7111                            }
7112                            return Ok(recv.clone());
7113                        }
7114                        "ok_or" | "ok_or_else" => {
7115                            // Convert Option to Result
7116                            if variant_name == "Some" {
7117                                if let Some(f) = fields {
7118                                    if let Some(inner) = f.first() {
7119                                        return Ok(Value::Variant {
7120                                            enum_name: "Result".to_string(),
7121                                            variant_name: "Ok".to_string(),
7122                                            fields: Some(Rc::new(vec![inner.clone()])),
7123                                        });
7124                                    }
7125                                }
7126                            }
7127                            // None case - return Err with the provided value
7128                            let err_val = arg_values.first().cloned().unwrap_or(Value::String(Rc::new("None".to_string())));
7129                            return Ok(Value::Variant {
7130                                enum_name: "Result".to_string(),
7131                                variant_name: "Err".to_string(),
7132                                fields: Some(Rc::new(vec![err_val])),
7133                            });
7134                        }
7135                        _ => {}
7136                    }
7137                }
7138                // Built-in Result methods
7139                if enum_name == "Result" {
7140                    match method.name.as_str() {
7141                        "is_ok" => {
7142                            return Ok(Value::Bool(variant_name == "Ok"));
7143                        }
7144                        "is_err" => {
7145                            return Ok(Value::Bool(variant_name == "Err"));
7146                        }
7147                        "ok" => {
7148                            // Convert Result<T, E> to Option<T>
7149                            // Ok(val) -> Some(val), Err(_) -> None
7150                            if variant_name == "Ok" {
7151                                let inner = fields.as_ref()
7152                                    .and_then(|f| f.first().cloned())
7153                                    .unwrap_or(Value::Null);
7154                                return Ok(Value::Variant {
7155                                    enum_name: "Option".to_string(),
7156                                    variant_name: "Some".to_string(),
7157                                    fields: Some(Rc::new(vec![inner])),
7158                                });
7159                            }
7160                            return Ok(Value::Variant {
7161                                enum_name: "Option".to_string(),
7162                                variant_name: "None".to_string(),
7163                                fields: None,
7164                            });
7165                        }
7166                        "err" => {
7167                            // Convert Result<T, E> to Option<E>
7168                            // Ok(_) -> None, Err(e) -> Some(e)
7169                            if variant_name == "Err" {
7170                                let inner = fields.as_ref()
7171                                    .and_then(|f| f.first().cloned())
7172                                    .unwrap_or(Value::Null);
7173                                return Ok(Value::Variant {
7174                                    enum_name: "Option".to_string(),
7175                                    variant_name: "Some".to_string(),
7176                                    fields: Some(Rc::new(vec![inner])),
7177                                });
7178                            }
7179                            return Ok(Value::Variant {
7180                                enum_name: "Option".to_string(),
7181                                variant_name: "None".to_string(),
7182                                fields: None,
7183                            });
7184                        }
7185                        "unwrap" => {
7186                            if variant_name == "Ok" {
7187                                if let Some(f) = fields {
7188                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
7189                                }
7190                            }
7191                            return Err(RuntimeError::new("unwrap on Err"));
7192                        }
7193                        "unwrap_or" => {
7194                            if variant_name == "Ok" {
7195                                if let Some(f) = fields {
7196                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
7197                                }
7198                            }
7199                            return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
7200                        }
7201                        "map" => {
7202                            // map(fn) - apply fn to Ok value, leave Err unchanged
7203                            if variant_name == "Ok" {
7204                                if let Some(Value::Function(f)) = arg_values.first() {
7205                                    let inner = fields.as_ref()
7206                                        .and_then(|f| f.first().cloned())
7207                                        .unwrap_or(Value::Null);
7208                                    let result = self.call_function(f, vec![inner])?;
7209                                    return Ok(Value::Variant {
7210                                        enum_name: "Result".to_string(),
7211                                        variant_name: "Ok".to_string(),
7212                                        fields: Some(Rc::new(vec![result])),
7213                                    });
7214                                }
7215                            }
7216                            // For Err variant, return unchanged
7217                            return Ok(recv.clone());
7218                        }
7219                        "map_err" => {
7220                            // map_err(fn) - apply fn to Err value, leave Ok unchanged
7221                            if variant_name == "Err" {
7222                                if let Some(Value::Function(f)) = arg_values.first() {
7223                                    let inner = fields.as_ref()
7224                                        .and_then(|f| f.first().cloned())
7225                                        .unwrap_or(Value::Null);
7226                                    let result = self.call_function(f, vec![inner])?;
7227                                    return Ok(Value::Variant {
7228                                        enum_name: "Result".to_string(),
7229                                        variant_name: "Err".to_string(),
7230                                        fields: Some(Rc::new(vec![result])),
7231                                    });
7232                                }
7233                            }
7234                            // For Ok variant, return unchanged
7235                            return Ok(recv.clone());
7236                        }
7237                        "and_then" => {
7238                            // and_then(fn) - chain Result-returning functions
7239                            if variant_name == "Ok" {
7240                                if let Some(Value::Function(f)) = arg_values.first() {
7241                                    let inner = fields.as_ref()
7242                                        .and_then(|f| f.first().cloned())
7243                                        .unwrap_or(Value::Null);
7244                                    return self.call_function(f, vec![inner]);
7245                                }
7246                            }
7247                            // For Err variant, return unchanged
7248                            return Ok(recv.clone());
7249                        }
7250                        _ => {}
7251                    }
7252                }
7253                // Pattern methods - for AST pattern access
7254                crate::sigil_debug!("DEBUG variant method call: enum_name={}, variant_name={}, method={}", enum_name, variant_name, method.name);
7255
7256                // Type methods
7257                if enum_name == "Type" {
7258                    match method.name.as_str() {
7259                        "is_never" => {
7260                            // Type::Never is the never type, all others are not
7261                            return Ok(Value::Bool(variant_name == "Never"));
7262                        }
7263                        "to_string" => {
7264                            // Convert type to string representation
7265                            let type_str = match variant_name.as_str() {
7266                                "Bool" => "bool".to_string(),
7267                                "Int" => "i64".to_string(),
7268                                "Float" => "f64".to_string(),
7269                                "Str" => "str".to_string(),
7270                                "Char" => "char".to_string(),
7271                                "Unit" => "()".to_string(),
7272                                "Never" => "!".to_string(),
7273                                "Error" => "<error>".to_string(),
7274                                other => format!("Type::{}", other),
7275                            };
7276                            return Ok(Value::String(Rc::new(type_str)));
7277                        }
7278                        _ => {}
7279                    }
7280                }
7281
7282                if enum_name == "Pattern" {
7283                    match method.name.as_str() {
7284                        "evidentiality" => {
7285                            // Pattern::Ident { name, mutable, evidentiality } - return the evidentiality field
7286                            if variant_name == "Ident" {
7287                                if let Some(f) = fields {
7288                                    // Fields are stored as a struct or in order
7289                                    // Try to find evidentiality field
7290                                    for field_val in f.iter() {
7291                                        if let Value::Struct { fields: inner, .. } = field_val {
7292                                            if let Some(ev) = inner.borrow().get("evidentiality") {
7293                                                return Ok(ev.clone());
7294                                            }
7295                                        }
7296                                    }
7297                                    // If fields are stored in order: name, mutable, evidentiality (index 2)
7298                                    if f.len() > 2 {
7299                                        return Ok(f[2].clone());
7300                                    }
7301                                }
7302                            }
7303                            // No evidentiality for other pattern types
7304                            return Ok(Value::Null);
7305                        }
7306                        "name" => {
7307                            // Get the name from Pattern::Ident
7308                            if variant_name == "Ident" {
7309                                if let Some(f) = fields {
7310                                    for field_val in f.iter() {
7311                                        if let Value::Struct { fields: inner, .. } = field_val {
7312                                            if let Some(n) = inner.borrow().get("name") {
7313                                                return Ok(n.clone());
7314                                            }
7315                                        }
7316                                    }
7317                                    // First field is name
7318                                    if let Some(n) = f.first() {
7319                                        return Ok(n.clone());
7320                                    }
7321                                }
7322                            }
7323                            return Ok(Value::Null);
7324                        }
7325                        "mutable" => {
7326                            // Get mutable flag from Pattern::Ident
7327                            if variant_name == "Ident" {
7328                                if let Some(f) = fields {
7329                                    for field_val in f.iter() {
7330                                        if let Value::Struct { fields: inner, .. } = field_val {
7331                                            if let Some(m) = inner.borrow().get("mutable") {
7332                                                return Ok(m.clone());
7333                                            }
7334                                        }
7335                                    }
7336                                    // Second field is mutable
7337                                    if f.len() > 1 {
7338                                        return Ok(f[1].clone());
7339                                    }
7340                                }
7341                            }
7342                            return Ok(Value::Bool(false));
7343                        }
7344                        _ => {}
7345                    }
7346                }
7347                // Built-in clone method for all variants
7348                if method.name == "clone" {
7349                    return Ok(recv.clone());
7350                }
7351
7352                let qualified_name = format!("{}·{}", enum_name, method.name);
7353                let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
7354                if let Some(func) = func {
7355                    if let Value::Function(f) = func {
7356                        let mut all_args = vec![recv.clone()];
7357                        all_args.extend(arg_values.clone());
7358                        return self.call_function(&f, all_args);
7359                    } else if let Value::BuiltIn(b) = func {
7360                        let mut all_args = vec![recv.clone()];
7361                        all_args.extend(arg_values.clone());
7362                        return (b.func)(self, all_args);
7363                    }
7364                }
7365                // Fallback for unknown methods on external enum types: return null
7366                crate::sigil_warn!("WARN: Unknown method '{}' on enum '{}' - returning null", method.name, enum_name);
7367                Ok(Value::Null)
7368            }
7369            // Null-safe method handlers - methods called on null return sensible defaults
7370            (Value::Null, "len_utf8") => Ok(Value::Int(0)),
7371            (Value::Null, "is_ascii") => Ok(Value::Bool(false)),
7372            (Value::Null, "is_alphabetic") => Ok(Value::Bool(false)),
7373            (Value::Null, "is_alphanumeric") => Ok(Value::Bool(false)),
7374            (Value::Null, "is_numeric") | (Value::Null, "is_digit") => Ok(Value::Bool(false)),
7375            (Value::Null, "is_whitespace") => Ok(Value::Bool(false)),
7376            (Value::Null, "is_uppercase") => Ok(Value::Bool(false)),
7377            (Value::Null, "is_lowercase") => Ok(Value::Bool(false)),
7378            (Value::Null, "len") => Ok(Value::Int(0)),
7379            (Value::Null, "is_empty") => Ok(Value::Bool(true)),
7380            (Value::Null, "to_string") => Ok(Value::String(Rc::new("".to_string()))),
7381            (Value::Null, "clone") => Ok(Value::Null),
7382            (Value::Null, "is_some") => Ok(Value::Bool(false)),
7383            (Value::Null, "is_none") => Ok(Value::Bool(true)),
7384            (Value::Null, "unwrap_or") => {
7385                if arg_values.is_empty() {
7386                    Ok(Value::Null)
7387                } else {
7388                    Ok(arg_values[0].clone())
7389                }
7390            }
7391            // unwrap_or for non-null values returns the value itself
7392            (Value::Char(c), "unwrap_or") => Ok(Value::Char(*c)),
7393            (Value::Int(n), "unwrap_or") => Ok(Value::Int(*n)),
7394            (Value::Float(n), "unwrap_or") => Ok(Value::Float(*n)),
7395            (Value::String(s), "unwrap_or") => Ok(Value::String(s.clone())),
7396            (Value::Bool(b), "unwrap_or") => Ok(Value::Bool(*b)),
7397            // Int methods
7398            (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
7399                Ok(Value::String(Rc::new(n.to_string())))
7400            }
7401            (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
7402            (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
7403            (Value::Int(n), "duration_since") => {
7404                // Treat Int as nanoseconds since some epoch
7405                // Return a Duration struct
7406                let other_ns = match arg_values.first() {
7407                    Some(Value::Int(i)) => *i,
7408                    Some(Value::Struct { fields, .. }) => {
7409                        let borrowed = fields.borrow();
7410                        let secs = match borrowed.get("secs") {
7411                            Some(Value::Int(s)) => *s,
7412                            _ => 0,
7413                        };
7414                        let nanos = match borrowed.get("nanos") {
7415                            Some(Value::Int(n)) => *n,
7416                            _ => 0,
7417                        };
7418                        secs * 1_000_000_000 + nanos
7419                    }
7420                    _ => 0,
7421                };
7422                let diff_ns = n - other_ns;
7423                let mut fields = std::collections::HashMap::new();
7424                fields.insert("secs".to_string(), Value::Int(diff_ns / 1_000_000_000));
7425                fields.insert("nanos".to_string(), Value::Int(diff_ns % 1_000_000_000));
7426                Ok(Value::Variant {
7427                    enum_name: "Result".to_string(),
7428                    variant_name: "Ok".to_string(),
7429                    fields: Some(Rc::new(vec![Value::Struct {
7430                        name: "Duration".to_string(),
7431                        fields: Rc::new(RefCell::new(fields)),
7432                    }])),
7433                })
7434            }
7435            // Float methods
7436            (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
7437                Ok(Value::String(Rc::new(n.to_string())))
7438            }
7439            (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
7440            (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
7441            // Bool methods
7442            (Value::Bool(b), "to_string") | (Value::Bool(b), "string") => {
7443                Ok(Value::String(Rc::new(b.to_string())))
7444            }
7445            // Char methods
7446            (Value::Char(c), "to_string") | (Value::Char(c), "string") => {
7447                Ok(Value::String(Rc::new(c.to_string())))
7448            }
7449            _ => {
7450                // Debug: what type is failing method lookup
7451                let recv_type = match &recv {
7452                    Value::String(s) => format!("String(len={})", s.len()),
7453                    Value::Array(arr) => format!("Array(len={})", arr.borrow().len()),
7454                    Value::Struct { name, .. } => format!("Struct({})", name),
7455                    Value::Variant { enum_name, variant_name, .. } => format!("Variant({}::{})", enum_name, variant_name),
7456                    Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
7457                    Value::Null => "Null".to_string(),
7458                    other => format!("{:?}", std::mem::discriminant(other)),
7459                };
7460                crate::sigil_warn!("WARN: Unknown method '{}' on recv_type={} - returning null", method.name, recv_type);
7461                // Fallback for unknown methods: return null to allow external crate types
7462                Ok(Value::Null)
7463            }
7464        }
7465    }
7466
7467    /// Evaluate polysynthetic incorporation: path·file·read·string
7468    /// The first segment provides the initial value, subsequent segments are method-like transformations
7469    fn eval_incorporation(
7470        &mut self,
7471        segments: &[IncorporationSegment],
7472    ) -> Result<Value, RuntimeError> {
7473        if segments.is_empty() {
7474            return Err(RuntimeError::new("empty incorporation chain"));
7475        }
7476
7477        // First segment: get initial value (variable lookup or function call)
7478        let first = &segments[0];
7479        let mut value = if let Some(args) = &first.args {
7480            // First segment is a function call: func(args)·next·...
7481            let arg_values: Vec<Value> = args
7482                .iter()
7483                .map(|a| self.evaluate(a))
7484                .collect::<Result<_, _>>()?;
7485            self.call_function_by_name(&first.name.name, arg_values)?
7486        } else {
7487            // First segment is a variable: var·next·...
7488            self.environment
7489                .borrow()
7490                .get(&first.name.name)
7491                .ok_or_else(|| RuntimeError::new(format!("undefined: {}", first.name.name)))?
7492        };
7493
7494        // Process remaining segments as method-like calls
7495        for segment in segments.iter().skip(1) {
7496            let arg_values: Vec<Value> = segment
7497                .args
7498                .as_ref()
7499                .map(|args| {
7500                    args.iter()
7501                        .map(|a| self.evaluate(a))
7502                        .collect::<Result<Vec<_>, _>>()
7503                })
7504                .transpose()?
7505                .unwrap_or_default();
7506
7507            // Try to call as a method on the value
7508            value = self.call_incorporation_method(&value, &segment.name.name, arg_values)?;
7509        }
7510
7511        Ok(value)
7512    }
7513
7514    /// Call a method in an incorporation chain
7515    /// This looks up the segment name as a method or stdlib function
7516    fn call_incorporation_method(
7517        &mut self,
7518        receiver: &Value,
7519        method_name: &str,
7520        args: Vec<Value>,
7521    ) -> Result<Value, RuntimeError> {
7522        // First try as a method on the receiver value
7523        match (receiver, method_name) {
7524            // String methods
7525            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
7526            (Value::String(s), "upper") | (Value::String(s), "uppercase") | (Value::String(s), "to_uppercase") => {
7527                Ok(Value::String(Rc::new(s.to_uppercase())))
7528            }
7529            (Value::String(s), "lower") | (Value::String(s), "lowercase") | (Value::String(s), "to_lowercase") => {
7530                Ok(Value::String(Rc::new(s.to_lowercase())))
7531            }
7532            (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
7533            (Value::String(s), "chars") => {
7534                let chars: Vec<Value> = s
7535                    .chars()
7536                    .map(|c| Value::String(Rc::new(c.to_string())))
7537                    .collect();
7538                Ok(Value::Array(Rc::new(RefCell::new(chars))))
7539            }
7540            (Value::String(s), "lines") => {
7541                let lines: Vec<Value> = s
7542                    .lines()
7543                    .map(|l| Value::String(Rc::new(l.to_string())))
7544                    .collect();
7545                Ok(Value::Array(Rc::new(RefCell::new(lines))))
7546            }
7547            (Value::String(s), "bytes") => {
7548                let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
7549                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
7550            }
7551            (Value::String(s), "parse_int") | (Value::String(s), "to_int") => s
7552                .parse::<i64>()
7553                .map(Value::Int)
7554                .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as int", s))),
7555            (Value::String(s), "parse_float") | (Value::String(s), "to_float") => s
7556                .parse::<f64>()
7557                .map(Value::Float)
7558                .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as float", s))),
7559            (Value::String(s), "as_str") => {
7560                if s.len() <= 10 { crate::sigil_debug!("DEBUG as_str: '{}'", s); }
7561                Ok(Value::String(s.clone()))
7562            }
7563            (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
7564            (Value::String(s), "starts_with") => {
7565                if args.len() != 1 {
7566                    return Err(RuntimeError::new("starts_with expects 1 argument"));
7567                }
7568                match &args[0] {
7569                    Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
7570                    _ => Err(RuntimeError::new("starts_with expects string")),
7571                }
7572            }
7573            (Value::String(s), "ends_with") => {
7574                if args.len() != 1 {
7575                    return Err(RuntimeError::new("ends_with expects 1 argument"));
7576                }
7577                match &args[0] {
7578                    Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
7579                    _ => Err(RuntimeError::new("ends_with expects string")),
7580                }
7581            }
7582            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
7583            (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
7584            (Value::String(s), "first") => s
7585                .chars()
7586                .next()
7587                .map(Value::Char)
7588                .ok_or_else(|| RuntimeError::new("empty string")),
7589            (Value::String(s), "last") => s
7590                .chars()
7591                .last()
7592                .map(Value::Char)
7593                .ok_or_else(|| RuntimeError::new("empty string")),
7594
7595            // Array methods
7596            (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
7597            (Value::Array(arr), "first") | (Value::Array(arr), "next") => Ok(arr
7598                .borrow()
7599                .first()
7600                .cloned()
7601                .unwrap_or(Value::Null)),
7602            (Value::Array(arr), "last") => arr
7603                .borrow()
7604                .last()
7605                .cloned()
7606                .ok_or_else(|| RuntimeError::new("empty array")),
7607            (Value::Array(arr), "reverse") | (Value::Array(arr), "rev") => {
7608                let mut v = arr.borrow().clone();
7609                v.reverse();
7610                Ok(Value::Array(Rc::new(RefCell::new(v))))
7611            }
7612            (Value::Array(arr), "join") => {
7613                let sep = args
7614                    .first()
7615                    .map(|v| match v {
7616                        Value::String(s) => s.to_string(),
7617                        _ => "".to_string(),
7618                    })
7619                    .unwrap_or_default();
7620                let joined = arr
7621                    .borrow()
7622                    .iter()
7623                    .map(|v| format!("{}", v))
7624                    .collect::<Vec<_>>()
7625                    .join(&sep);
7626                Ok(Value::String(Rc::new(joined)))
7627            }
7628            (Value::Array(arr), "sum") => {
7629                let mut sum = 0i64;
7630                for v in arr.borrow().iter() {
7631                    match v {
7632                        Value::Int(i) => sum += i,
7633                        Value::Float(f) => return Ok(Value::Float(sum as f64 + f)),
7634                        _ => {}
7635                    }
7636                }
7637                Ok(Value::Int(sum))
7638            }
7639            (Value::Array(arr), "skip") => {
7640                let n = match args.first() {
7641                    Some(Value::Int(i)) => *i as usize,
7642                    _ => 1,
7643                };
7644                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
7645                Ok(Value::Array(Rc::new(RefCell::new(v))))
7646            }
7647            (Value::Array(arr), "take") => {
7648                let n = match args.first() {
7649                    Some(Value::Int(i)) => *i as usize,
7650                    _ => 1,
7651                };
7652                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
7653                Ok(Value::Array(Rc::new(RefCell::new(v))))
7654            }
7655            (Value::Array(arr), "step_by") => {
7656                let n = match args.first() {
7657                    Some(Value::Int(i)) if *i > 0 => *i as usize,
7658                    _ => 1,
7659                };
7660                let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
7661                Ok(Value::Array(Rc::new(RefCell::new(v))))
7662            }
7663
7664            // Number methods
7665            (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
7666            (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
7667            (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
7668                Ok(Value::String(Rc::new(n.to_string())))
7669            }
7670            (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
7671                Ok(Value::String(Rc::new(n.to_string())))
7672            }
7673            (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
7674            (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
7675
7676            // Map/Struct field access
7677            (Value::Map(map), field) => map
7678                .borrow()
7679                .get(field)
7680                .cloned()
7681                .ok_or_else(|| RuntimeError::new(format!("no field '{}' in map", field))),
7682            (Value::Struct { fields, .. }, field) => fields
7683                .borrow()
7684                .get(field)
7685                .cloned()
7686                .ok_or_else(|| RuntimeError::new(format!("no field '{}' in struct", field))),
7687
7688            // Try stdlib function with receiver as first arg
7689            _ => {
7690                let mut all_args = vec![receiver.clone()];
7691                all_args.extend(args);
7692                self.call_function_by_name(method_name, all_args)
7693            }
7694        }
7695    }
7696
7697    /// Call a function by name from the environment
7698    pub fn call_function_by_name(
7699        &mut self,
7700        name: &str,
7701        args: Vec<Value>,
7702    ) -> Result<Value, RuntimeError> {
7703        // Get the function value from environment (clone to avoid borrow issues)
7704        let func_value = self.environment.borrow().get(name);
7705
7706        match func_value {
7707            Some(Value::Function(f)) => self.call_function(&f, args),
7708            Some(Value::BuiltIn(b)) => self.call_builtin(&b, args),
7709            Some(_) => Err(RuntimeError::new(format!("{} is not a function", name))),
7710            None => {
7711                // Check for variant constructor
7712                if let Some((enum_name, variant_name, arity)) = self.variant_constructors.get(name).cloned() {
7713                    if arity == 0 && args.is_empty() {
7714                        return Ok(Value::Variant {
7715                            enum_name,
7716                            variant_name,
7717                            fields: None,
7718                        });
7719                    } else if args.len() == arity {
7720                        return Ok(Value::Variant {
7721                            enum_name,
7722                            variant_name,
7723                            fields: Some(Rc::new(args)),
7724                        });
7725                    } else {
7726                        return Err(RuntimeError::new(format!(
7727                            "{} expects {} arguments, got {}",
7728                            name, arity, args.len()
7729                        )));
7730                    }
7731                }
7732                Err(RuntimeError::new(format!("undefined function: {}", name)))
7733            }
7734        }
7735    }
7736
7737    fn eval_pipe(&mut self, expr: &Expr, operations: &[PipeOp]) -> Result<Value, RuntimeError> {
7738        let mut value = self.evaluate(expr)?;
7739
7740        for op in operations {
7741            value = self.apply_pipe_op(value, op)?;
7742        }
7743
7744        Ok(value)
7745    }
7746
7747    fn apply_pipe_op(&mut self, value: Value, op: &PipeOp) -> Result<Value, RuntimeError> {
7748        // Unwrap evidential/affective wrappers for pipe operations
7749        let value = Self::unwrap_all(&value);
7750
7751        match op {
7752            PipeOp::Transform(body) => {
7753                // τ{f} - map over collection or apply to single value
7754                // Extract closure parameter pattern and body
7755                let (param_pattern, inner_body) = match body.as_ref() {
7756                    Expr::Closure { params, body, .. } => {
7757                        let pattern = params.first().map(|p| p.pattern.clone());
7758                        (pattern, body.as_ref())
7759                    }
7760                    _ => (None, body.as_ref()),
7761                };
7762
7763                match value {
7764                    Value::Array(arr) => {
7765                        let results: Vec<Value> = arr
7766                            .borrow()
7767                            .iter()
7768                            .map(|item| {
7769                                // Bind the item to the pattern (supports tuple destructuring)
7770                                if let Some(ref pattern) = param_pattern {
7771                                    self.bind_pattern(pattern, item.clone())?;
7772                                } else {
7773                                    self.environment
7774                                        .borrow_mut()
7775                                        .define("_".to_string(), item.clone());
7776                                }
7777                                self.evaluate(inner_body)
7778                            })
7779                            .collect::<Result<_, _>>()?;
7780                        Ok(Value::Array(Rc::new(RefCell::new(results))))
7781                    }
7782                    single => {
7783                        if let Some(ref pattern) = param_pattern {
7784                            self.bind_pattern(pattern, single)?;
7785                        } else {
7786                            self.environment
7787                                .borrow_mut()
7788                                .define("_".to_string(), single);
7789                        }
7790                        self.evaluate(inner_body)
7791                    }
7792                }
7793            }
7794            PipeOp::Filter(predicate) => {
7795                // φ{p} - filter collection
7796                // Extract closure parameter pattern and body
7797                let (param_pattern, inner_pred) = match predicate.as_ref() {
7798                    Expr::Closure { params, body, .. } => {
7799                        let pattern = params.first().map(|p| p.pattern.clone());
7800                        (pattern, body.as_ref())
7801                    }
7802                    _ => (None, predicate.as_ref()),
7803                };
7804
7805                match value {
7806                    Value::Array(arr) => {
7807                        let results: Vec<Value> = arr
7808                            .borrow()
7809                            .iter()
7810                            .filter_map(|item| {
7811                                // Bind the item to the pattern (supports tuple destructuring)
7812                                if let Some(ref pattern) = param_pattern {
7813                                    if let Err(e) = self.bind_pattern(pattern, item.clone()) {
7814                                        return Some(Err(e));
7815                                    }
7816                                } else {
7817                                    self.environment
7818                                        .borrow_mut()
7819                                        .define("_".to_string(), item.clone());
7820                                }
7821                                match self.evaluate(inner_pred) {
7822                                    Ok(v) if self.is_truthy(&v) => Some(Ok(item.clone())),
7823                                    Ok(_) => None,
7824                                    Err(e) => Some(Err(e)),
7825                                }
7826                            })
7827                            .collect::<Result<_, _>>()?;
7828                        Ok(Value::Array(Rc::new(RefCell::new(results))))
7829                    }
7830                    _ => Err(RuntimeError::new("Filter requires array")),
7831                }
7832            }
7833            PipeOp::Sort(field) => {
7834                // σ - sort collection
7835                match value {
7836                    Value::Array(arr) => {
7837                        let mut v = arr.borrow().clone();
7838                        v.sort_by(|a, b| self.compare_values(a, b, field));
7839                        Ok(Value::Array(Rc::new(RefCell::new(v))))
7840                    }
7841                    _ => Err(RuntimeError::new("Sort requires array")),
7842                }
7843            }
7844            PipeOp::Reduce(body) => {
7845                // ρ{f} - reduce collection
7846                match value {
7847                    Value::Array(arr) => {
7848                        let arr = arr.borrow();
7849                        if arr.is_empty() {
7850                            return Err(RuntimeError::new("Cannot reduce empty array"));
7851                        }
7852                        let mut acc = arr[0].clone();
7853                        for item in arr.iter().skip(1) {
7854                            self.environment.borrow_mut().define("acc".to_string(), acc);
7855                            self.environment
7856                                .borrow_mut()
7857                                .define("_".to_string(), item.clone());
7858                            acc = self.evaluate(body)?;
7859                        }
7860                        Ok(acc)
7861                    }
7862                    _ => Err(RuntimeError::new("Reduce requires array")),
7863                }
7864            }
7865            PipeOp::ReduceSum => {
7866                // ρ+ or ρ_sum - sum all elements
7867                self.sum_values(value)
7868            }
7869            PipeOp::ReduceProd => {
7870                // ρ* or ρ_prod - multiply all elements
7871                self.product_values(value)
7872            }
7873            PipeOp::ReduceMin => {
7874                // ρ_min - find minimum element
7875                self.min_values(value)
7876            }
7877            PipeOp::ReduceMax => {
7878                // ρ_max - find maximum element
7879                self.max_values(value)
7880            }
7881            PipeOp::ReduceConcat => {
7882                // ρ++ or ρ_cat - concatenate strings/arrays
7883                self.concat_values(value)
7884            }
7885            PipeOp::ReduceAll => {
7886                // ρ& or ρ_all - logical AND (all true)
7887                self.all_values(value)
7888            }
7889            PipeOp::ReduceAny => {
7890                // ρ| or ρ_any - logical OR (any true)
7891                self.any_values(value)
7892            }
7893            PipeOp::Match(arms) => {
7894                // |match{ Pattern => expr, ... } - pattern matching in pipe
7895                for arm in arms {
7896                    if self.pattern_matches(&arm.pattern, &value)? {
7897                        // Create new scope for pattern bindings
7898                        let prev_env = self.environment.clone();
7899                        self.environment =
7900                            Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
7901
7902                        // Bind pattern variables
7903                        self.bind_pattern(&arm.pattern, value.clone())?;
7904
7905                        // Also bind _ to the piped value for convenient access
7906                        self.environment
7907                            .borrow_mut()
7908                            .define("_".to_string(), value.clone());
7909
7910                        // Check guard if present
7911                        let guard_passes = if let Some(guard) = &arm.guard {
7912                            matches!(self.evaluate(guard)?, Value::Bool(true))
7913                        } else {
7914                            true
7915                        };
7916
7917                        if guard_passes {
7918                            let result = self.evaluate(&arm.body)?;
7919                            self.environment = prev_env;
7920                            return Ok(result);
7921                        }
7922
7923                        // Guard failed, restore environment and try next arm
7924                        self.environment = prev_env;
7925                    }
7926                }
7927                Err(RuntimeError::new("No pattern matched in pipe match"))
7928            }
7929            PipeOp::TryMap(mapper) => {
7930                // |? or |?{mapper} - unwrap Result/Option or transform error
7931                match &value {
7932                    // Handle Result-like values (struct with ok/err fields)
7933                    Value::Struct { name, fields } if name == "Ok" || name.ends_with("::Ok") => {
7934                        // Extract the inner value from Ok
7935                        let fields = fields.borrow();
7936                        fields
7937                            .get("0")
7938                            .or_else(|| fields.get("value"))
7939                            .cloned()
7940                            .ok_or_else(|| RuntimeError::new("Ok variant has no value"))
7941                    }
7942                    Value::Struct { name, fields } if name == "Err" || name.ends_with("::Err") => {
7943                        // Transform error if mapper provided, otherwise propagate
7944                        let fields = fields.borrow();
7945                        let err_val = fields
7946                            .get("0")
7947                            .or_else(|| fields.get("error"))
7948                            .cloned()
7949                            .unwrap_or(Value::Null);
7950                        if let Some(mapper_expr) = mapper {
7951                            // Apply mapper to error
7952                            let prev_env = self.environment.clone();
7953                            self.environment =
7954                                Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
7955                            self.environment
7956                                .borrow_mut()
7957                                .define("_".to_string(), err_val);
7958                            let mapped = self.evaluate(mapper_expr)?;
7959                            self.environment = prev_env;
7960                            Err(RuntimeError::new(format!("Error: {:?}", mapped)))
7961                        } else {
7962                            Err(RuntimeError::new(format!("Error: {:?}", err_val)))
7963                        }
7964                    }
7965                    // Handle Option-like values
7966                    Value::Struct { name, fields }
7967                        if name == "Some" || name.ends_with("::Some") =>
7968                    {
7969                        let fields = fields.borrow();
7970                        fields
7971                            .get("0")
7972                            .or_else(|| fields.get("value"))
7973                            .cloned()
7974                            .ok_or_else(|| RuntimeError::new("Some variant has no value"))
7975                    }
7976                    Value::Struct { name, .. } if name == "None" || name.ends_with("::None") => {
7977                        Err(RuntimeError::new("Unwrapped None value"))
7978                    }
7979                    Value::Null => Err(RuntimeError::new("Unwrapped null value")),
7980                    // Pass through non-Result/Option values unchanged
7981                    _ => Ok(value),
7982                }
7983            }
7984            PipeOp::Call(callee) => {
7985                // |expr - call an arbitrary expression (like self.layer) with piped value
7986                let callee_val = self.evaluate(callee)?;
7987                match callee_val {
7988                    Value::Function(f) => {
7989                        // Call the function with the piped value as argument
7990                        self.call_function(&f, vec![value])
7991                    }
7992                    Value::BuiltIn(b) => {
7993                        // Call built-in with the piped value
7994                        self.call_builtin(&b, vec![value])
7995                    }
7996                    Value::Struct { .. } => {
7997                        // Structs that implement __call__ can be called as functions
7998                        // For now, just return the value (ML layers would override)
7999                        Ok(value)
8000                    }
8001                    _ => Err(RuntimeError::new(format!(
8002                        "Cannot call non-function value in pipe: {:?}",
8003                        callee_val
8004                    ))),
8005                }
8006            }
8007            PipeOp::Method { name, type_args: _, args } => {
8008                let arg_values: Vec<Value> = args
8009                    .iter()
8010                    .map(|a| self.evaluate(a))
8011                    .collect::<Result<_, _>>()?;
8012
8013                // Check for built-in pipe methods
8014                match name.name.as_str() {
8015                    "collect" => Ok(value), // Already collected
8016                    "sum" | "Σ" => self.sum_values(value),
8017                    "product" | "Π" => self.product_values(value),
8018                    "len" => match &value {
8019                        Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
8020                        Value::String(s) => Ok(Value::Int(s.len() as i64)),
8021                        _ => Err(RuntimeError::new("len requires array or string")),
8022                    },
8023                    "reverse" => match value {
8024                        Value::Array(arr) => {
8025                            let mut v = arr.borrow().clone();
8026                            v.reverse();
8027                            Ok(Value::Array(Rc::new(RefCell::new(v))))
8028                        }
8029                        _ => Err(RuntimeError::new("reverse requires array")),
8030                    },
8031                    "iter" | "into_iter" => {
8032                        // iter()/into_iter() returns the array for iteration (identity operation)
8033                        Ok(value)
8034                    },
8035                    "enumerate" => {
8036                        // enumerate() returns array of (index, value) tuples
8037                        match &value {
8038                            Value::Array(arr) => {
8039                                let enumerated: Vec<Value> = arr
8040                                    .borrow()
8041                                    .iter()
8042                                    .enumerate()
8043                                    .map(|(i, v)| {
8044                                        Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
8045                                    })
8046                                    .collect();
8047                                Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
8048                            }
8049                            _ => Err(RuntimeError::new("enumerate requires array")),
8050                        }
8051                    },
8052                    "first" => match &value {
8053                        Value::Array(arr) => arr
8054                            .borrow()
8055                            .first()
8056                            .cloned()
8057                            .ok_or_else(|| RuntimeError::new("first on empty array")),
8058                        _ => Err(RuntimeError::new("first requires array")),
8059                    },
8060                    "last" => match &value {
8061                        Value::Array(arr) => arr
8062                            .borrow()
8063                            .last()
8064                            .cloned()
8065                            .ok_or_else(|| RuntimeError::new("last on empty array")),
8066                        _ => Err(RuntimeError::new("last requires array")),
8067                    },
8068                    "take" => {
8069                        if arg_values.len() != 1 {
8070                            return Err(RuntimeError::new("take requires 1 argument"));
8071                        }
8072                        let n = match &arg_values[0] {
8073                            Value::Int(n) => *n as usize,
8074                            _ => return Err(RuntimeError::new("take requires integer")),
8075                        };
8076                        match value {
8077                            Value::Array(arr) => {
8078                                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
8079                                Ok(Value::Array(Rc::new(RefCell::new(v))))
8080                            }
8081                            _ => Err(RuntimeError::new("take requires array")),
8082                        }
8083                    }
8084                    "skip" => {
8085                        if arg_values.len() != 1 {
8086                            return Err(RuntimeError::new("skip requires 1 argument"));
8087                        }
8088                        let n = match &arg_values[0] {
8089                            Value::Int(n) => *n as usize,
8090                            _ => return Err(RuntimeError::new("skip requires integer")),
8091                        };
8092                        match value {
8093                            Value::Array(arr) => {
8094                                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
8095                                Ok(Value::Array(Rc::new(RefCell::new(v))))
8096                            }
8097                            _ => Err(RuntimeError::new("skip requires array")),
8098                        }
8099                    }
8100                    "join" => {
8101                        // Join array elements with a separator string
8102                        let separator = if arg_values.is_empty() {
8103                            String::new()
8104                        } else {
8105                            match &arg_values[0] {
8106                                Value::String(s) => (**s).clone(),
8107                                _ => return Err(RuntimeError::new("join separator must be string")),
8108                            }
8109                        };
8110                        match value {
8111                            Value::Array(arr) => {
8112                                let parts: Vec<String> = arr.borrow().iter()
8113                                    .map(|v| format!("{}", Self::unwrap_all(v)))
8114                                    .collect();
8115                                Ok(Value::String(Rc::new(parts.join(&separator))))
8116                            }
8117                            _ => Err(RuntimeError::new("join requires array")),
8118                        }
8119                    }
8120                    "all" => {
8121                        // Check if all elements are truthy (no predicate in Method variant)
8122                        match value {
8123                            Value::Array(arr) => {
8124                                for item in arr.borrow().iter() {
8125                                    if !self.is_truthy(item) {
8126                                        return Ok(Value::Bool(false));
8127                                    }
8128                                }
8129                                Ok(Value::Bool(true))
8130                            }
8131                            _ => Err(RuntimeError::new("all requires array")),
8132                        }
8133                    }
8134                    "any" => {
8135                        // Check if any element is truthy
8136                        match value {
8137                            Value::Array(arr) => {
8138                                for item in arr.borrow().iter() {
8139                                    if self.is_truthy(item) {
8140                                        return Ok(Value::Bool(true));
8141                                    }
8142                                }
8143                                Ok(Value::Bool(false))
8144                            }
8145                            _ => Err(RuntimeError::new("any requires array")),
8146                        }
8147                    }
8148                    "map" => {
8149                        // map(closure) applies closure to each element
8150                        if arg_values.len() != 1 {
8151                            return Err(RuntimeError::new("map expects 1 argument (closure)"));
8152                        }
8153                        match (&value, &arg_values[0]) {
8154                            (Value::Array(arr), Value::Function(f)) => {
8155                                let mut results = Vec::new();
8156                                for val in arr.borrow().iter() {
8157                                    let result = self.call_function(f, vec![val.clone()])?;
8158                                    results.push(result);
8159                                }
8160                                Ok(Value::Array(Rc::new(RefCell::new(results))))
8161                            }
8162                            (Value::Array(_), _) => Err(RuntimeError::new("map expects closure argument")),
8163                            _ => Err(RuntimeError::new("map requires array")),
8164                        }
8165                    }
8166                    "filter" => {
8167                        // filter(predicate) keeps elements where predicate returns true
8168                        if arg_values.len() != 1 {
8169                            return Err(RuntimeError::new("filter expects 1 argument (closure)"));
8170                        }
8171                        match (&value, &arg_values[0]) {
8172                            (Value::Array(arr), Value::Function(f)) => {
8173                                let mut results = Vec::new();
8174                                for val in arr.borrow().iter() {
8175                                    let keep = self.call_function(f, vec![val.clone()])?;
8176                                    if matches!(keep, Value::Bool(true)) {
8177                                        results.push(val.clone());
8178                                    }
8179                                }
8180                                Ok(Value::Array(Rc::new(RefCell::new(results))))
8181                            }
8182                            (Value::Array(_), _) => Err(RuntimeError::new("filter expects closure argument")),
8183                            _ => Err(RuntimeError::new("filter requires array")),
8184                        }
8185                    }
8186                    "fold" => {
8187                        // fold(init, closure) reduces array to single value
8188                        if arg_values.len() != 2 {
8189                            return Err(RuntimeError::new("fold expects 2 arguments (init, closure)"));
8190                        }
8191                        match (&value, &arg_values[1]) {
8192                            (Value::Array(arr), Value::Function(f)) => {
8193                                let mut acc = arg_values[0].clone();
8194                                for val in arr.borrow().iter() {
8195                                    acc = self.call_function(f, vec![acc, val.clone()])?;
8196                                }
8197                                Ok(acc)
8198                            }
8199                            (Value::Array(_), _) => Err(RuntimeError::new("fold expects closure as second argument")),
8200                            _ => Err(RuntimeError::new("fold requires array")),
8201                        }
8202                    }
8203                    _ => Err(RuntimeError::new(format!(
8204                        "Unknown pipe method: {}",
8205                        name.name
8206                    ))),
8207                }
8208            }
8209            PipeOp::Await => {
8210                // Await a future - resolve it to a value
8211                self.await_value(value)
8212            }
8213            // New access morphemes
8214            PipeOp::First => {
8215                // α - first element
8216                match &value {
8217                    Value::Array(arr) => arr
8218                        .borrow()
8219                        .first()
8220                        .cloned()
8221                        .ok_or_else(|| RuntimeError::new("first (α) on empty array")),
8222                    Value::Tuple(t) => t
8223                        .first()
8224                        .cloned()
8225                        .ok_or_else(|| RuntimeError::new("first (α) on empty tuple")),
8226                    _ => Err(RuntimeError::new("first (α) requires array or tuple")),
8227                }
8228            }
8229            PipeOp::Last => {
8230                // ω - last element
8231                match &value {
8232                    Value::Array(arr) => arr
8233                        .borrow()
8234                        .last()
8235                        .cloned()
8236                        .ok_or_else(|| RuntimeError::new("last (ω) on empty array")),
8237                    Value::Tuple(t) => t
8238                        .last()
8239                        .cloned()
8240                        .ok_or_else(|| RuntimeError::new("last (ω) on empty tuple")),
8241                    _ => Err(RuntimeError::new("last (ω) requires array or tuple")),
8242                }
8243            }
8244            PipeOp::Middle => {
8245                // μ - middle/median element
8246                match &value {
8247                    Value::Array(arr) => {
8248                        let arr = arr.borrow();
8249                        if arr.is_empty() {
8250                            return Err(RuntimeError::new("middle (μ) on empty array"));
8251                        }
8252                        let mid = arr.len() / 2;
8253                        Ok(arr[mid].clone())
8254                    }
8255                    Value::Tuple(t) => {
8256                        if t.is_empty() {
8257                            return Err(RuntimeError::new("middle (μ) on empty tuple"));
8258                        }
8259                        let mid = t.len() / 2;
8260                        Ok(t[mid].clone())
8261                    }
8262                    _ => Err(RuntimeError::new("middle (μ) requires array or tuple")),
8263                }
8264            }
8265            PipeOp::Choice => {
8266                // χ - random element
8267                use std::time::{SystemTime, UNIX_EPOCH};
8268                match &value {
8269                    Value::Array(arr) => {
8270                        let arr = arr.borrow();
8271                        if arr.is_empty() {
8272                            return Err(RuntimeError::new("choice (χ) on empty array"));
8273                        }
8274                        let seed = SystemTime::now()
8275                            .duration_since(UNIX_EPOCH)
8276                            .unwrap_or(std::time::Duration::ZERO)
8277                            .as_nanos() as u64;
8278                        let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
8279                            as usize
8280                            % arr.len();
8281                        Ok(arr[idx].clone())
8282                    }
8283                    Value::Tuple(t) => {
8284                        if t.is_empty() {
8285                            return Err(RuntimeError::new("choice (χ) on empty tuple"));
8286                        }
8287                        let seed = SystemTime::now()
8288                            .duration_since(UNIX_EPOCH)
8289                            .unwrap_or(std::time::Duration::ZERO)
8290                            .as_nanos() as u64;
8291                        let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
8292                            as usize
8293                            % t.len();
8294                        Ok(t[idx].clone())
8295                    }
8296                    _ => Err(RuntimeError::new("choice (χ) requires array or tuple")),
8297                }
8298            }
8299            PipeOp::Nth(index_expr) => {
8300                // ν{n} - nth element
8301                let index = match self.evaluate(index_expr)? {
8302                    Value::Int(n) => n,
8303                    _ => return Err(RuntimeError::new("nth (ν) index must be integer")),
8304                };
8305                match &value {
8306                    Value::Array(arr) => {
8307                        let arr = arr.borrow();
8308                        if index < 0 || index as usize >= arr.len() {
8309                            return Err(RuntimeError::new("nth (ν) index out of bounds"));
8310                        }
8311                        Ok(arr[index as usize].clone())
8312                    }
8313                    Value::Tuple(t) => {
8314                        if index < 0 || index as usize >= t.len() {
8315                            return Err(RuntimeError::new("nth (ν) index out of bounds"));
8316                        }
8317                        Ok(t[index as usize].clone())
8318                    }
8319                    _ => Err(RuntimeError::new("nth (ν) requires array or tuple")),
8320                }
8321            }
8322            PipeOp::Next => {
8323                // ξ - next element (for iterators, currently just returns first)
8324                // In a full implementation, this would advance an iterator
8325                match &value {
8326                    Value::Array(arr) => arr
8327                        .borrow()
8328                        .first()
8329                        .cloned()
8330                        .ok_or_else(|| RuntimeError::new("next (ξ) on empty array")),
8331                    Value::Tuple(t) => t
8332                        .first()
8333                        .cloned()
8334                        .ok_or_else(|| RuntimeError::new("next (ξ) on empty tuple")),
8335                    _ => Err(RuntimeError::new("next (ξ) requires array or tuple")),
8336                }
8337            }
8338            PipeOp::Named { prefix, body } => {
8339                // Named morpheme like ·map{f}
8340                let method_name = prefix
8341                    .iter()
8342                    .map(|i| i.name.as_str())
8343                    .collect::<Vec<_>>()
8344                    .join("·");
8345                match method_name.as_str() {
8346                    "map" => {
8347                        if let Some(body) = body {
8348                            match value {
8349                                Value::Array(arr) => {
8350                                    let results: Vec<Value> = arr
8351                                        .borrow()
8352                                        .iter()
8353                                        .map(|item| {
8354                                            self.environment
8355                                                .borrow_mut()
8356                                                .define("_".to_string(), item.clone());
8357                                            self.evaluate(body)
8358                                        })
8359                                        .collect::<Result<_, _>>()?;
8360                                    Ok(Value::Array(Rc::new(RefCell::new(results))))
8361                                }
8362                                _ => Err(RuntimeError::new("map requires array")),
8363                            }
8364                        } else {
8365                            Ok(value)
8366                        }
8367                    }
8368                    "filter" => {
8369                        if let Some(body) = body {
8370                            match value {
8371                                Value::Array(arr) => {
8372                                    let results: Vec<Value> = arr
8373                                        .borrow()
8374                                        .iter()
8375                                        .filter_map(|item| {
8376                                            self.environment
8377                                                .borrow_mut()
8378                                                .define("_".to_string(), item.clone());
8379                                            match self.evaluate(body) {
8380                                                Ok(v) if self.is_truthy(&v) => {
8381                                                    Some(Ok(item.clone()))
8382                                                }
8383                                                Ok(_) => None,
8384                                                Err(e) => Some(Err(e)),
8385                                            }
8386                                        })
8387                                        .collect::<Result<_, _>>()?;
8388                                    Ok(Value::Array(Rc::new(RefCell::new(results))))
8389                                }
8390                                _ => Err(RuntimeError::new("filter requires array")),
8391                            }
8392                        } else {
8393                            Ok(value)
8394                        }
8395                    }
8396                    "all" => {
8397                        if let Some(body) = body {
8398                            match value {
8399                                Value::Array(arr) => {
8400                                    for item in arr.borrow().iter() {
8401                                        self.environment
8402                                            .borrow_mut()
8403                                            .define("_".to_string(), item.clone());
8404                                        let result = self.evaluate(body)?;
8405                                        if !self.is_truthy(&result) {
8406                                            return Ok(Value::Bool(false));
8407                                        }
8408                                    }
8409                                    Ok(Value::Bool(true))
8410                                }
8411                                _ => Err(RuntimeError::new("all requires array")),
8412                            }
8413                        } else {
8414                            // Without body, check if all elements are truthy
8415                            match value {
8416                                Value::Array(arr) => {
8417                                    for item in arr.borrow().iter() {
8418                                        if !self.is_truthy(item) {
8419                                            return Ok(Value::Bool(false));
8420                                        }
8421                                    }
8422                                    Ok(Value::Bool(true))
8423                                }
8424                                _ => Err(RuntimeError::new("all requires array")),
8425                            }
8426                        }
8427                    }
8428                    "any" => {
8429                        if let Some(body) = body {
8430                            match value {
8431                                Value::Array(arr) => {
8432                                    for item in arr.borrow().iter() {
8433                                        self.environment
8434                                            .borrow_mut()
8435                                            .define("_".to_string(), item.clone());
8436                                        let result = self.evaluate(body)?;
8437                                        if self.is_truthy(&result) {
8438                                            return Ok(Value::Bool(true));
8439                                        }
8440                                    }
8441                                    Ok(Value::Bool(false))
8442                                }
8443                                _ => Err(RuntimeError::new("any requires array")),
8444                            }
8445                        } else {
8446                            // Without body, check if any elements are truthy
8447                            match value {
8448                                Value::Array(arr) => {
8449                                    for item in arr.borrow().iter() {
8450                                        if self.is_truthy(item) {
8451                                            return Ok(Value::Bool(true));
8452                                        }
8453                                    }
8454                                    Ok(Value::Bool(false))
8455                                }
8456                                _ => Err(RuntimeError::new("any requires array")),
8457                            }
8458                        }
8459                    }
8460                    _ => Err(RuntimeError::new(format!(
8461                        "Unknown named morpheme: {}",
8462                        method_name
8463                    ))),
8464                }
8465            }
8466            PipeOp::Parallel(inner_op) => {
8467                // ∥ - parallel execution of the inner operation
8468                // For arrays, execute the operation in parallel using threads
8469                match value {
8470                    Value::Array(arr) => {
8471                        use std::sync::{Arc, Mutex};
8472
8473                        let arr_ref = arr.borrow();
8474                        let len = arr_ref.len();
8475                        if len == 0 {
8476                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
8477                        }
8478
8479                        // For Transform operations, parallelize across elements
8480                        match inner_op.as_ref() {
8481                            PipeOp::Transform(body) => {
8482                                // Determine number of threads (use available parallelism)
8483                                let num_threads = std::thread::available_parallelism()
8484                                    .map(|p| p.get())
8485                                    .unwrap_or(4)
8486                                    .min(len);
8487
8488                                // For future parallel implementation
8489                                let _chunk_size = (len + num_threads - 1) / num_threads;
8490                                let _results = Arc::new(Mutex::new(vec![Value::Null; len]));
8491                                let items: Vec<Value> = arr_ref.clone();
8492                                drop(arr_ref);
8493
8494                                // Clone the body expression for each thread (for future use)
8495                                let _body_str = format!("{:?}", body);
8496
8497                                // For now, fall back to sequential since full parallelization
8498                                // requires thread-safe evaluation context
8499                                // In production, this would use Rayon or a work-stealing scheduler
8500                                let mut result_vec = Vec::with_capacity(len);
8501                                for item in items.iter() {
8502                                    self.environment
8503                                        .borrow_mut()
8504                                        .define("_".to_string(), item.clone());
8505                                    result_vec.push(self.evaluate(body)?);
8506                                }
8507                                Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
8508                            }
8509                            PipeOp::Filter(predicate) => {
8510                                // Parallel filter - evaluate predicate in parallel
8511                                let items: Vec<Value> = arr_ref.clone();
8512                                drop(arr_ref);
8513
8514                                let mut result_vec = Vec::new();
8515                                for item in items.iter() {
8516                                    self.environment
8517                                        .borrow_mut()
8518                                        .define("_".to_string(), item.clone());
8519                                    let pred_result = self.evaluate(predicate)?;
8520                                    if self.is_truthy(&pred_result) {
8521                                        result_vec.push(item.clone());
8522                                    }
8523                                }
8524                                Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
8525                            }
8526                            _ => {
8527                                // For other operations, just apply them normally
8528                                drop(arr_ref);
8529                                self.apply_pipe_op(Value::Array(arr), inner_op)
8530                            }
8531                        }
8532                    }
8533                    _ => {
8534                        // For non-arrays, just apply the inner operation
8535                        self.apply_pipe_op(value, inner_op)
8536                    }
8537                }
8538            }
8539            PipeOp::Gpu(inner_op) => {
8540                // ⊛ - GPU compute shader execution
8541                // This is a placeholder that falls back to CPU execution
8542                // In production, this would:
8543                // 1. Generate SPIR-V/WGSL compute shader
8544                // 2. Submit to GPU via wgpu/vulkan
8545                // 3. Read back results
8546                match value {
8547                    Value::Array(arr) => {
8548                        // For now, emit a hint that GPU execution would occur
8549                        // and fall back to CPU
8550                        #[cfg(debug_assertions)]
8551                        eprintln!(
8552                            "[GPU] Would execute {:?} on GPU, falling back to CPU",
8553                            inner_op
8554                        );
8555
8556                        self.apply_pipe_op(Value::Array(arr), inner_op)
8557                    }
8558                    _ => self.apply_pipe_op(value, inner_op),
8559                }
8560            }
8561
8562            // ==========================================
8563            // Protocol Operations - Sigil-native networking
8564            // All protocol results are wrapped with Reported evidentiality
8565            // since network data comes from external sources ("hearsay")
8566            // ==========================================
8567            PipeOp::Send(data_expr) => {
8568                // |send{data} or |⇒{data} - Send data over a connection
8569                // The value should be a connection object
8570                let data = self.evaluate(data_expr)?;
8571
8572                // Create a protocol response with Reported evidentiality
8573                // In production, this would actually send data over the network
8574                let response = self.protocol_send(&value, &data)?;
8575
8576                // Wrap in Reported evidentiality - network responses are hearsay
8577                Ok(self.wrap_reported(response))
8578            }
8579
8580            PipeOp::Recv => {
8581                // |recv or |⇐ - Receive data from a connection
8582                // The value should be a connection object
8583
8584                // In production, this would actually receive data from the network
8585                let response = self.protocol_recv(&value)?;
8586
8587                // Wrap in Reported evidentiality - network data is hearsay
8588                Ok(self.wrap_reported(response))
8589            }
8590
8591            PipeOp::Stream(handler_expr) => {
8592                // |stream{handler} or |≋{handler} - Stream data with a handler
8593                let handler = self.evaluate(handler_expr)?;
8594
8595                // Create a streaming iterator over network data
8596                // Each element will be wrapped in Reported evidentiality
8597                let stream = self.protocol_stream(&value, &handler)?;
8598                Ok(stream)
8599            }
8600
8601            PipeOp::Connect(config_expr) => {
8602                // |connect or |connect{config} or |⊸{config} - Establish connection
8603                let config = match config_expr {
8604                    Some(expr) => Some(self.evaluate(expr)?),
8605                    None => None,
8606                };
8607
8608                // Create a connection object
8609                let connection = self.protocol_connect(&value, config.as_ref())?;
8610                Ok(connection)
8611            }
8612
8613            PipeOp::Close => {
8614                // |close or |⊗ - Close connection gracefully
8615                self.protocol_close(&value)?;
8616                Ok(Value::Null)
8617            }
8618
8619            PipeOp::Header {
8620                name,
8621                value: value_expr,
8622            } => {
8623                // |header{name, value} - Add/set header on request
8624                let header_name = self.evaluate(name)?;
8625                let header_value = self.evaluate(value_expr)?;
8626
8627                // Add header to the request builder
8628                self.protocol_add_header(value, &header_name, &header_value)
8629            }
8630
8631            PipeOp::Body(data_expr) => {
8632                // |body{data} - Set request body
8633                let body_data = self.evaluate(data_expr)?;
8634
8635                // Set body on the request builder
8636                self.protocol_set_body(value, &body_data)
8637            }
8638
8639            PipeOp::Timeout(ms_expr) => {
8640                // |timeout{ms} or |⏱{ms} - Set operation timeout
8641                let ms = self.evaluate(ms_expr)?;
8642
8643                // Set timeout on the request/connection
8644                self.protocol_set_timeout(value, &ms)
8645            }
8646
8647            PipeOp::Retry { count, strategy } => {
8648                // |retry{count} or |retry{count, strategy} - Set retry policy
8649                let retry_count = self.evaluate(count)?;
8650                let retry_strategy = match strategy {
8651                    Some(s) => Some(self.evaluate(s)?),
8652                    None => None,
8653                };
8654
8655                // Set retry policy on the request
8656                self.protocol_set_retry(value, &retry_count, retry_strategy.as_ref())
8657            }
8658
8659            // ==========================================
8660            // Evidence Promotion Operations
8661            // ==========================================
8662            PipeOp::Validate {
8663                predicate,
8664                target_evidence,
8665            } => {
8666                // |validate!{predicate} - validate and promote evidence
8667                // Execute the predicate with the current value
8668                let predicate_result = match predicate.as_ref() {
8669                    Expr::Closure { params, body, .. } => {
8670                        if let Some(param) = params.first() {
8671                            let param_name = match &param.pattern {
8672                                Pattern::Ident { name, .. } => name.name.clone(),
8673                                _ => "it".to_string(),
8674                            };
8675                            self.environment
8676                                .borrow_mut()
8677                                .define(param_name, value.clone());
8678                        }
8679                        self.evaluate(body)?
8680                    }
8681                    _ => self.evaluate(predicate)?,
8682                };
8683
8684                // Check if validation passed
8685                match predicate_result {
8686                    Value::Bool(true) => {
8687                        // Validation passed: promote evidence
8688                        let target_ev = match target_evidence {
8689                            Evidentiality::Known => Evidence::Known,
8690                            Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
8691                            Evidentiality::Reported => Evidence::Reported,
8692                            Evidentiality::Paradox => Evidence::Paradox,
8693                        };
8694                        let inner = match value {
8695                            Value::Evidential { value: v, .. } => *v,
8696                            v => v,
8697                        };
8698                        Ok(Value::Evidential {
8699                            value: Box::new(inner),
8700                            evidence: target_ev,
8701                        })
8702                    }
8703                    Value::Bool(false) => Err(RuntimeError::new(
8704                        "validation failed: predicate returned false",
8705                    )),
8706                    _ => Err(RuntimeError::new("validation predicate must return bool")),
8707                }
8708            }
8709
8710            PipeOp::Assume {
8711                reason,
8712                target_evidence,
8713            } => {
8714                // |assume!("reason") - explicitly assume evidence (with audit trail)
8715                let reason_str: Rc<String> = if let Some(r) = reason {
8716                    match self.evaluate(r)? {
8717                        Value::String(s) => s,
8718                        _ => Rc::new("<no reason>".to_string()),
8719                    }
8720                } else {
8721                    Rc::new("<no reason>".to_string())
8722                };
8723
8724                // Log the assumption for audit purposes
8725                #[cfg(debug_assertions)]
8726                eprintln!(
8727                    "[AUDIT] Evidence assumption: {} - reason: {}",
8728                    match target_evidence {
8729                        Evidentiality::Known => "!",
8730                        Evidentiality::Uncertain | Evidentiality::Predicted => "?",
8731                        Evidentiality::Reported => "~",
8732                        Evidentiality::Paradox => "‽",
8733                    },
8734                    reason_str
8735                );
8736
8737                let target_ev = match target_evidence {
8738                    Evidentiality::Known => Evidence::Known,
8739                    Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
8740                    Evidentiality::Reported => Evidence::Reported,
8741                    Evidentiality::Paradox => Evidence::Paradox,
8742                };
8743
8744                let inner = match value {
8745                    Value::Evidential { value: v, .. } => *v,
8746                    v => v,
8747                };
8748
8749                Ok(Value::Evidential {
8750                    value: Box::new(inner),
8751                    evidence: target_ev,
8752                })
8753            }
8754
8755            PipeOp::AssertEvidence(expected) => {
8756                // |assert_evidence!{!} - assert evidence level
8757                let actual_evidence = match &value {
8758                    Value::Evidential { evidence, .. } => evidence.clone(),
8759                    _ => Evidence::Known,
8760                };
8761
8762                let expected_ev = match expected {
8763                    Evidentiality::Known => Evidence::Known,
8764                    Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
8765                    Evidentiality::Reported => Evidence::Reported,
8766                    Evidentiality::Paradox => Evidence::Paradox,
8767                };
8768
8769                // Check if actual satisfies expected
8770                let satisfies = match (&actual_evidence, &expected_ev) {
8771                    (Evidence::Known, _) => true,
8772                    (
8773                        Evidence::Uncertain,
8774                        Evidence::Uncertain | Evidence::Reported | Evidence::Paradox,
8775                    ) => true,
8776                    (Evidence::Reported, Evidence::Reported | Evidence::Paradox) => true,
8777                    (Evidence::Paradox, Evidence::Paradox) => true,
8778                    _ => false,
8779                };
8780
8781                if satisfies {
8782                    Ok(value)
8783                } else {
8784                    Err(RuntimeError::new(format!(
8785                        "evidence assertion failed: expected {:?}, found {:?}",
8786                        expected_ev, actual_evidence
8787                    )))
8788                }
8789            }
8790
8791            // ==========================================
8792            // Scope Functions (Kotlin-inspired)
8793            // ==========================================
8794            PipeOp::Also(func) => {
8795                // |also{f} - execute side effect, return original value
8796                // Execute the function with the value for side effects
8797                match func.as_ref() {
8798                    Expr::Closure { params, body, .. } => {
8799                        if let Some(param) = params.first() {
8800                            let param_name = match &param.pattern {
8801                                Pattern::Ident { name, .. } => name.name.clone(),
8802                                _ => "it".to_string(),
8803                            };
8804                            self.environment
8805                                .borrow_mut()
8806                                .define(param_name, value.clone());
8807                        }
8808                        // Execute for side effects, ignore result
8809                        let _ = self.evaluate(body);
8810                    }
8811                    _ => {
8812                        // Call as function with value as argument
8813                        let _ = self.evaluate(func);
8814                    }
8815                }
8816                // Return original value unchanged
8817                Ok(value)
8818            }
8819
8820            PipeOp::Apply(func) => {
8821                // |apply{block} - mutate value in place, return modified value
8822                // The closure receives the value and can modify it
8823                match func.as_ref() {
8824                    Expr::Closure { params, body, .. } => {
8825                        if let Some(param) = params.first() {
8826                            let param_name = match &param.pattern {
8827                                Pattern::Ident { name, .. } => name.name.clone(),
8828                                _ => "it".to_string(),
8829                            };
8830                            self.environment
8831                                .borrow_mut()
8832                                .define(param_name, value.clone());
8833                        }
8834                        // Execute the body - mutations happen via the bound variable
8835                        let _ = self.evaluate(body);
8836                    }
8837                    _ => {
8838                        let _ = self.evaluate(func);
8839                    }
8840                }
8841                // Return the (potentially modified) value
8842                Ok(value)
8843            }
8844
8845            PipeOp::TakeIf(predicate) => {
8846                // |take_if{p} - return Some(value) if predicate true, None otherwise
8847                let predicate_result = match predicate.as_ref() {
8848                    Expr::Closure { params, body, .. } => {
8849                        if let Some(param) = params.first() {
8850                            let param_name = match &param.pattern {
8851                                Pattern::Ident { name, .. } => name.name.clone(),
8852                                _ => "it".to_string(),
8853                            };
8854                            self.environment
8855                                .borrow_mut()
8856                                .define(param_name, value.clone());
8857                        }
8858                        self.evaluate(body)?
8859                    }
8860                    _ => self.evaluate(predicate)?,
8861                };
8862
8863                match predicate_result {
8864                    Value::Bool(true) => Ok(Value::Variant {
8865                        enum_name: "Option".to_string(),
8866                        variant_name: "Some".to_string(),
8867                        fields: Some(Rc::new(vec![value])),
8868                    }),
8869                    Value::Bool(false) => Ok(Value::Variant {
8870                        enum_name: "Option".to_string(),
8871                        variant_name: "None".to_string(),
8872                        fields: None,
8873                    }),
8874                    _ => Err(RuntimeError::new("take_if predicate must return bool")),
8875                }
8876            }
8877
8878            PipeOp::TakeUnless(predicate) => {
8879                // |take_unless{p} - return Some(value) if predicate false, None otherwise
8880                let predicate_result = match predicate.as_ref() {
8881                    Expr::Closure { params, body, .. } => {
8882                        if let Some(param) = params.first() {
8883                            let param_name = match &param.pattern {
8884                                Pattern::Ident { name, .. } => name.name.clone(),
8885                                _ => "it".to_string(),
8886                            };
8887                            self.environment
8888                                .borrow_mut()
8889                                .define(param_name, value.clone());
8890                        }
8891                        self.evaluate(body)?
8892                    }
8893                    _ => self.evaluate(predicate)?,
8894                };
8895
8896                match predicate_result {
8897                    Value::Bool(false) => Ok(Value::Variant {
8898                        enum_name: "Option".to_string(),
8899                        variant_name: "Some".to_string(),
8900                        fields: Some(Rc::new(vec![value])),
8901                    }),
8902                    Value::Bool(true) => Ok(Value::Variant {
8903                        enum_name: "Option".to_string(),
8904                        variant_name: "None".to_string(),
8905                        fields: None,
8906                    }),
8907                    _ => Err(RuntimeError::new("take_unless predicate must return bool")),
8908                }
8909            }
8910
8911            PipeOp::Let(func) => {
8912                // |let{f} - transform value (alias for map/transform)
8913                match func.as_ref() {
8914                    Expr::Closure { params, body, .. } => {
8915                        if let Some(param) = params.first() {
8916                            let param_name = match &param.pattern {
8917                                Pattern::Ident { name, .. } => name.name.clone(),
8918                                _ => "it".to_string(),
8919                            };
8920                            self.environment
8921                                .borrow_mut()
8922                                .define(param_name, value.clone());
8923                        }
8924                        self.evaluate(body)
8925                    }
8926                    _ => self.evaluate(func),
8927                }
8928            }
8929
8930            // ==========================================
8931            // Mathematical & APL-Inspired Operations
8932            // ==========================================
8933            PipeOp::All(pred) => {
8934                // |∀{p} - check if ALL elements satisfy predicate
8935                match value {
8936                    Value::Array(arr) => {
8937                        for elem in arr.borrow().iter() {
8938                            self.environment
8939                                .borrow_mut()
8940                                .define("_".to_string(), elem.clone());
8941                            let result = self.evaluate(pred)?;
8942                            if !self.is_truthy(&result) {
8943                                return Ok(Value::Bool(false));
8944                            }
8945                        }
8946                        Ok(Value::Bool(true))
8947                    }
8948                    _ => Err(RuntimeError::new("All requires array")),
8949                }
8950            }
8951
8952            PipeOp::Any(pred) => {
8953                // |∃{p} - check if ANY element satisfies predicate
8954                match value {
8955                    Value::Array(arr) => {
8956                        for elem in arr.borrow().iter() {
8957                            self.environment
8958                                .borrow_mut()
8959                                .define("_".to_string(), elem.clone());
8960                            let result = self.evaluate(pred)?;
8961                            if self.is_truthy(&result) {
8962                                return Ok(Value::Bool(true));
8963                            }
8964                        }
8965                        Ok(Value::Bool(false))
8966                    }
8967                    _ => Err(RuntimeError::new("Any requires array")),
8968                }
8969            }
8970
8971            PipeOp::Compose(f) => {
8972                // |∘{f} - function composition / apply function
8973                self.environment.borrow_mut().define("_".to_string(), value);
8974                self.evaluate(f)
8975            }
8976
8977            PipeOp::Zip(other_expr) => {
8978                // |⋈{other} - zip with another collection
8979                let other = self.evaluate(other_expr)?;
8980                match (value, other) {
8981                    (Value::Array(arr1), Value::Array(arr2)) => {
8982                        let zipped: Vec<Value> = arr1
8983                            .borrow()
8984                            .iter()
8985                            .zip(arr2.borrow().iter())
8986                            .map(|(a, b)| Value::Tuple(Rc::new(vec![a.clone(), b.clone()])))
8987                            .collect();
8988                        Ok(Value::Array(Rc::new(RefCell::new(zipped))))
8989                    }
8990                    _ => Err(RuntimeError::new("Zip requires two arrays")),
8991                }
8992            }
8993
8994            PipeOp::Scan(f) => {
8995                // |∫{f} - cumulative fold (scan)
8996                match value {
8997                    Value::Array(arr) => {
8998                        let arr = arr.borrow();
8999                        if arr.is_empty() {
9000                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
9001                        }
9002                        let mut results = vec![arr[0].clone()];
9003                        let mut acc = arr[0].clone();
9004                        for elem in arr.iter().skip(1) {
9005                            self.environment
9006                                .borrow_mut()
9007                                .define("acc".to_string(), acc.clone());
9008                            self.environment
9009                                .borrow_mut()
9010                                .define("_".to_string(), elem.clone());
9011                            acc = self.evaluate(f)?;
9012                            results.push(acc.clone());
9013                        }
9014                        Ok(Value::Array(Rc::new(RefCell::new(results))))
9015                    }
9016                    _ => Err(RuntimeError::new("Scan requires array")),
9017                }
9018            }
9019
9020            PipeOp::Diff => {
9021                // |∂ - differences between adjacent elements
9022                match value {
9023                    Value::Array(arr) => {
9024                        let arr = arr.borrow();
9025                        if arr.len() < 2 {
9026                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
9027                        }
9028                        let mut diffs = Vec::new();
9029                        for i in 1..arr.len() {
9030                            let diff = self.subtract_values(&arr[i], &arr[i - 1])?;
9031                            diffs.push(diff);
9032                        }
9033                        Ok(Value::Array(Rc::new(RefCell::new(diffs))))
9034                    }
9035                    _ => Err(RuntimeError::new("Diff requires array")),
9036                }
9037            }
9038
9039            PipeOp::Gradient(var_expr) => {
9040                // |∇{var} - automatic differentiation
9041                // For now, just a placeholder - real autodiff requires tape recording
9042                let _ = var_expr;
9043                Ok(Value::Float(0.0)) // TODO: Implement real autodiff
9044            }
9045
9046            PipeOp::SortAsc => {
9047                // |⍋ - sort ascending
9048                match value {
9049                    Value::Array(arr) => {
9050                        let mut v = arr.borrow().clone();
9051                        v.sort_by(|a, b| self.compare_values(a, b, &None));
9052                        Ok(Value::Array(Rc::new(RefCell::new(v))))
9053                    }
9054                    _ => Err(RuntimeError::new("SortAsc requires array")),
9055                }
9056            }
9057
9058            PipeOp::SortDesc => {
9059                // |⍒ - sort descending
9060                match value {
9061                    Value::Array(arr) => {
9062                        let mut v = arr.borrow().clone();
9063                        v.sort_by(|a, b| self.compare_values(b, a, &None));
9064                        Ok(Value::Array(Rc::new(RefCell::new(v))))
9065                    }
9066                    _ => Err(RuntimeError::new("SortDesc requires array")),
9067                }
9068            }
9069
9070            PipeOp::Reverse => {
9071                // |⌽ - reverse collection
9072                match value {
9073                    Value::Array(arr) => {
9074                        let mut v = arr.borrow().clone();
9075                        v.reverse();
9076                        Ok(Value::Array(Rc::new(RefCell::new(v))))
9077                    }
9078                    _ => Err(RuntimeError::new("Reverse requires array")),
9079                }
9080            }
9081
9082            PipeOp::Cycle(n_expr) => {
9083                // |↻{n} - repeat collection n times
9084                match value {
9085                    Value::Array(arr) => {
9086                        let n_val = self.evaluate(n_expr)?;
9087                        let n = match n_val {
9088                            Value::Int(i) => i as usize,
9089                            _ => return Err(RuntimeError::new("Cycle count must be integer")),
9090                        };
9091                        let arr = arr.borrow();
9092                        let cycled: Vec<Value> =
9093                            arr.iter().cloned().cycle().take(arr.len() * n).collect();
9094                        Ok(Value::Array(Rc::new(RefCell::new(cycled))))
9095                    }
9096                    _ => Err(RuntimeError::new("Cycle requires array")),
9097                }
9098            }
9099
9100            PipeOp::Windows(n_expr) => {
9101                // |⌺{n} - sliding windows
9102                match value {
9103                    Value::Array(arr) => {
9104                        let n_val = self.evaluate(n_expr)?;
9105                        let n = match n_val {
9106                            Value::Int(i) => i as usize,
9107                            _ => return Err(RuntimeError::new("Window size must be integer")),
9108                        };
9109                        let arr = arr.borrow();
9110                        let windows: Vec<Value> = arr
9111                            .windows(n)
9112                            .map(|w| Value::Array(Rc::new(RefCell::new(w.to_vec()))))
9113                            .collect();
9114                        Ok(Value::Array(Rc::new(RefCell::new(windows))))
9115                    }
9116                    _ => Err(RuntimeError::new("Windows requires array")),
9117                }
9118            }
9119
9120            PipeOp::Chunks(n_expr) => {
9121                // |⊞{n} - split into chunks
9122                match value {
9123                    Value::Array(arr) => {
9124                        let n_val = self.evaluate(n_expr)?;
9125                        let n = match n_val {
9126                            Value::Int(i) => i as usize,
9127                            _ => return Err(RuntimeError::new("Chunk size must be integer")),
9128                        };
9129                        let arr = arr.borrow();
9130                        let chunks: Vec<Value> = arr
9131                            .chunks(n)
9132                            .map(|c| Value::Array(Rc::new(RefCell::new(c.to_vec()))))
9133                            .collect();
9134                        Ok(Value::Array(Rc::new(RefCell::new(chunks))))
9135                    }
9136                    _ => Err(RuntimeError::new("Chunks requires array")),
9137                }
9138            }
9139
9140            PipeOp::Flatten => {
9141                // |⋳ - flatten nested collection
9142                match value {
9143                    Value::Array(arr) => {
9144                        let mut flat = Vec::new();
9145                        for elem in arr.borrow().iter() {
9146                            match elem {
9147                                Value::Array(inner) => {
9148                                    flat.extend(inner.borrow().iter().cloned());
9149                                }
9150                                other => flat.push(other.clone()),
9151                            }
9152                        }
9153                        Ok(Value::Array(Rc::new(RefCell::new(flat))))
9154                    }
9155                    _ => Err(RuntimeError::new("Flatten requires array")),
9156                }
9157            }
9158
9159            PipeOp::Unique => {
9160                // |∪ - remove duplicates
9161                match value {
9162                    Value::Array(arr) => {
9163                        let mut seen = std::collections::HashSet::new();
9164                        let mut unique = Vec::new();
9165                        for elem in arr.borrow().iter() {
9166                            let key = format!("{:?}", elem);
9167                            if seen.insert(key) {
9168                                unique.push(elem.clone());
9169                            }
9170                        }
9171                        Ok(Value::Array(Rc::new(RefCell::new(unique))))
9172                    }
9173                    _ => Err(RuntimeError::new("Unique requires array")),
9174                }
9175            }
9176
9177            PipeOp::Enumerate => {
9178                // |⍳ - pair with indices
9179                match value {
9180                    Value::Array(arr) => {
9181                        let enumerated: Vec<Value> = arr
9182                            .borrow()
9183                            .iter()
9184                            .enumerate()
9185                            .map(|(i, v)| {
9186                                Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
9187                            })
9188                            .collect();
9189                        Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
9190                    }
9191                    _ => Err(RuntimeError::new("Enumerate requires array")),
9192                }
9193            }
9194        }
9195    }
9196
9197    // ==========================================
9198    // Protocol Helper Methods
9199    // ==========================================
9200
9201    /// Wrap a value in Reported evidentiality
9202    /// Network data is "hearsay" - it comes from external sources we can't verify
9203    fn wrap_reported(&self, value: Value) -> Value {
9204        Value::Evidential {
9205            value: Box::new(value),
9206            evidence: Evidence::Reported,
9207        }
9208    }
9209
9210    /// Send data over a protocol connection
9211    fn protocol_send(&mut self, connection: &Value, data: &Value) -> Result<Value, RuntimeError> {
9212        // Extract connection info and send data
9213        match connection {
9214            Value::Map(obj) => {
9215                let obj = obj.borrow();
9216                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
9217                    match protocol.as_str() {
9218                        "http" | "https" => {
9219                            // For HTTP, "send" means execute the request
9220                            // The data becomes the body
9221                            #[cfg(debug_assertions)]
9222                            eprintln!("[HTTP] Would send request with body: {:?}", data);
9223                            Ok(Value::Map(Rc::new(RefCell::new({
9224                                let mut response = HashMap::new();
9225                                response.insert("status".to_string(), Value::Int(200));
9226                                response.insert("body".to_string(), data.clone());
9227                                response.insert(
9228                                    "__protocol__".to_string(),
9229                                    Value::String(Rc::new("http_response".to_string())),
9230                                );
9231                                response
9232                            }))))
9233                        }
9234                        "ws" | "wss" => {
9235                            // For WebSocket, send a message
9236                            #[cfg(debug_assertions)]
9237                            eprintln!("[WebSocket] Would send message: {:?}", data);
9238                            Ok(Value::Bool(true)) // Message sent successfully
9239                        }
9240                        "grpc" => {
9241                            // For gRPC, send the request message
9242                            #[cfg(debug_assertions)]
9243                            eprintln!("[gRPC] Would send message: {:?}", data);
9244                            Ok(Value::Map(Rc::new(RefCell::new({
9245                                let mut response = HashMap::new();
9246                                response.insert("status".to_string(), Value::Int(0)); // OK
9247                                response.insert("message".to_string(), data.clone());
9248                                response.insert(
9249                                    "__protocol__".to_string(),
9250                                    Value::String(Rc::new("grpc_response".to_string())),
9251                                );
9252                                response
9253                            }))))
9254                        }
9255                        "kafka" => {
9256                            // For Kafka, produce a message
9257                            #[cfg(debug_assertions)]
9258                            eprintln!("[Kafka] Would produce message: {:?}", data);
9259                            Ok(Value::Map(Rc::new(RefCell::new({
9260                                let mut result = HashMap::new();
9261                                result.insert("partition".to_string(), Value::Int(0));
9262                                result.insert("offset".to_string(), Value::Int(42));
9263                                result
9264                            }))))
9265                        }
9266                        _ => Err(RuntimeError::new(format!("Unknown protocol: {}", protocol))),
9267                    }
9268                } else {
9269                    Err(RuntimeError::new(
9270                        "Connection object missing __protocol__ field",
9271                    ))
9272                }
9273            }
9274            _ => Err(RuntimeError::new("send requires a connection object")),
9275        }
9276    }
9277
9278    /// Receive data from a protocol connection
9279    fn protocol_recv(&mut self, connection: &Value) -> Result<Value, RuntimeError> {
9280        match connection {
9281            Value::Map(obj) => {
9282                let obj = obj.borrow();
9283                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
9284                    match protocol.as_str() {
9285                        "ws" | "wss" => {
9286                            // For WebSocket, receive a message
9287                            #[cfg(debug_assertions)]
9288                            eprintln!("[WebSocket] Would receive message");
9289                            Ok(Value::String(Rc::new("received message".to_string())))
9290                        }
9291                        "kafka" => {
9292                            // For Kafka, consume a message
9293                            #[cfg(debug_assertions)]
9294                            eprintln!("[Kafka] Would consume message");
9295                            Ok(Value::Map(Rc::new(RefCell::new({
9296                                let mut msg = HashMap::new();
9297                                msg.insert("key".to_string(), Value::Null);
9298                                msg.insert(
9299                                    "value".to_string(),
9300                                    Value::String(Rc::new("consumed message".to_string())),
9301                                );
9302                                msg.insert("partition".to_string(), Value::Int(0));
9303                                msg.insert("offset".to_string(), Value::Int(100));
9304                                msg
9305                            }))))
9306                        }
9307                        "grpc" => {
9308                            // For gRPC streaming, receive next message
9309                            #[cfg(debug_assertions)]
9310                            eprintln!("[gRPC] Would receive stream message");
9311                            Ok(Value::Map(Rc::new(RefCell::new({
9312                                let mut msg = HashMap::new();
9313                                msg.insert(
9314                                    "data".to_string(),
9315                                    Value::String(Rc::new("stream data".to_string())),
9316                                );
9317                                msg
9318                            }))))
9319                        }
9320                        _ => Err(RuntimeError::new(format!(
9321                            "recv not supported for protocol: {}",
9322                            protocol
9323                        ))),
9324                    }
9325                } else {
9326                    Err(RuntimeError::new(
9327                        "Connection object missing __protocol__ field",
9328                    ))
9329                }
9330            }
9331            _ => Err(RuntimeError::new("recv requires a connection object")),
9332        }
9333    }
9334
9335    /// Create a streaming iterator over protocol data
9336    fn protocol_stream(
9337        &mut self,
9338        connection: &Value,
9339        _handler: &Value,
9340    ) -> Result<Value, RuntimeError> {
9341        // Create a lazy stream that yields values with Reported evidentiality
9342        match connection {
9343            Value::Map(obj) => {
9344                let obj = obj.borrow();
9345                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
9346                    #[cfg(debug_assertions)]
9347                    eprintln!("[{}] Would create stream", protocol);
9348
9349                    // Return a stream object that can be iterated
9350                    Ok(Value::Map(Rc::new(RefCell::new({
9351                        let mut stream = HashMap::new();
9352                        stream.insert(
9353                            "__type__".to_string(),
9354                            Value::String(Rc::new("Stream".to_string())),
9355                        );
9356                        stream.insert("__protocol__".to_string(), Value::String(protocol.clone()));
9357                        stream.insert(
9358                            "__evidentiality__".to_string(),
9359                            Value::String(Rc::new("reported".to_string())),
9360                        );
9361                        stream
9362                    }))))
9363                } else {
9364                    Err(RuntimeError::new(
9365                        "Connection object missing __protocol__ field",
9366                    ))
9367                }
9368            }
9369            _ => Err(RuntimeError::new("stream requires a connection object")),
9370        }
9371    }
9372
9373    /// Establish a protocol connection
9374    fn protocol_connect(
9375        &mut self,
9376        target: &Value,
9377        _config: Option<&Value>,
9378    ) -> Result<Value, RuntimeError> {
9379        match target {
9380            Value::String(url) => {
9381                // Parse URL to determine protocol
9382                let protocol = if url.starts_with("wss://") || url.starts_with("ws://") {
9383                    if url.starts_with("wss://") {
9384                        "wss"
9385                    } else {
9386                        "ws"
9387                    }
9388                } else if url.starts_with("https://") || url.starts_with("http://") {
9389                    if url.starts_with("https://") {
9390                        "https"
9391                    } else {
9392                        "http"
9393                    }
9394                } else if url.starts_with("grpc://") || url.starts_with("grpcs://") {
9395                    "grpc"
9396                } else if url.starts_with("kafka://") {
9397                    "kafka"
9398                } else if url.starts_with("amqp://") || url.starts_with("amqps://") {
9399                    "amqp"
9400                } else {
9401                    "unknown"
9402                };
9403
9404                #[cfg(debug_assertions)]
9405                eprintln!("[{}] Would connect to: {}", protocol, url);
9406
9407                // Return a connection object
9408                Ok(Value::Map(Rc::new(RefCell::new({
9409                    let mut conn = HashMap::new();
9410                    conn.insert(
9411                        "__protocol__".to_string(),
9412                        Value::String(Rc::new(protocol.to_string())),
9413                    );
9414                    conn.insert("url".to_string(), Value::String(url.clone()));
9415                    conn.insert("connected".to_string(), Value::Bool(true));
9416                    conn
9417                }))))
9418            }
9419            Value::Map(obj) => {
9420                // Already a connection config object
9421                let mut conn = obj.borrow().clone();
9422                conn.insert("connected".to_string(), Value::Bool(true));
9423                Ok(Value::Map(Rc::new(RefCell::new(conn))))
9424            }
9425            _ => Err(RuntimeError::new(
9426                "connect requires URL string or config object",
9427            )),
9428        }
9429    }
9430
9431    /// Close a protocol connection
9432    fn protocol_close(&mut self, connection: &Value) -> Result<(), RuntimeError> {
9433        match connection {
9434            Value::Map(obj) => {
9435                let mut obj = obj.borrow_mut();
9436                if let Some(Value::String(protocol)) = obj.get("__protocol__").cloned() {
9437                    #[cfg(debug_assertions)]
9438                    eprintln!("[{}] Would close connection", protocol);
9439                    obj.insert("connected".to_string(), Value::Bool(false));
9440                    Ok(())
9441                } else {
9442                    Err(RuntimeError::new(
9443                        "Connection object missing __protocol__ field",
9444                    ))
9445                }
9446            }
9447            _ => Err(RuntimeError::new("close requires a connection object")),
9448        }
9449    }
9450
9451    /// Add a header to a protocol request
9452    fn protocol_add_header(
9453        &mut self,
9454        mut request: Value,
9455        name: &Value,
9456        header_value: &Value,
9457    ) -> Result<Value, RuntimeError> {
9458        let name_str = match name {
9459            Value::String(s) => (**s).clone(),
9460            _ => return Err(RuntimeError::new("Header name must be a string")),
9461        };
9462        let value_str = match header_value {
9463            Value::String(s) => (**s).clone(),
9464            Value::Int(i) => i.to_string(),
9465            _ => return Err(RuntimeError::new("Header value must be string or int")),
9466        };
9467
9468        match &mut request {
9469            Value::Map(obj) => {
9470                let mut obj = obj.borrow_mut();
9471
9472                // Get or create headers map
9473                let headers = obj
9474                    .entry("headers".to_string())
9475                    .or_insert_with(|| Value::Map(Rc::new(RefCell::new(HashMap::new()))));
9476
9477                if let Value::Map(headers_obj) = headers {
9478                    headers_obj
9479                        .borrow_mut()
9480                        .insert(name_str, Value::String(Rc::new(value_str)));
9481                }
9482                drop(obj);
9483                Ok(request)
9484            }
9485            _ => Err(RuntimeError::new("header requires a request object")),
9486        }
9487    }
9488
9489    /// Set the body of a protocol request
9490    fn protocol_set_body(
9491        &mut self,
9492        mut request: Value,
9493        body: &Value,
9494    ) -> Result<Value, RuntimeError> {
9495        match &mut request {
9496            Value::Map(obj) => {
9497                obj.borrow_mut().insert("body".to_string(), body.clone());
9498                Ok(request)
9499            }
9500            _ => Err(RuntimeError::new("body requires a request object")),
9501        }
9502    }
9503
9504    /// Set the timeout for a protocol operation
9505    fn protocol_set_timeout(
9506        &mut self,
9507        mut request: Value,
9508        ms: &Value,
9509    ) -> Result<Value, RuntimeError> {
9510        let timeout_ms = match ms {
9511            Value::Int(n) => *n,
9512            Value::Float(f) => *f as i64,
9513            _ => return Err(RuntimeError::new("Timeout must be a number (milliseconds)")),
9514        };
9515
9516        match &mut request {
9517            Value::Map(obj) => {
9518                obj.borrow_mut()
9519                    .insert("timeout_ms".to_string(), Value::Int(timeout_ms));
9520                Ok(request)
9521            }
9522            _ => Err(RuntimeError::new("timeout requires a request object")),
9523        }
9524    }
9525
9526    /// Set the retry policy for a protocol operation
9527    fn protocol_set_retry(
9528        &mut self,
9529        mut request: Value,
9530        count: &Value,
9531        strategy: Option<&Value>,
9532    ) -> Result<Value, RuntimeError> {
9533        let retry_count = match count {
9534            Value::Int(n) => *n,
9535            _ => return Err(RuntimeError::new("Retry count must be an integer")),
9536        };
9537
9538        match &mut request {
9539            Value::Map(obj) => {
9540                let mut obj = obj.borrow_mut();
9541                obj.insert("retry_count".to_string(), Value::Int(retry_count));
9542                if let Some(strat) = strategy {
9543                    obj.insert("retry_strategy".to_string(), strat.clone());
9544                }
9545                drop(obj);
9546                Ok(request)
9547            }
9548            _ => Err(RuntimeError::new("retry requires a request object")),
9549        }
9550    }
9551
9552    fn sum_values(&self, value: Value) -> Result<Value, RuntimeError> {
9553        match value {
9554            Value::Array(arr) => {
9555                let arr = arr.borrow();
9556                if arr.is_empty() {
9557                    return Ok(Value::Int(0));
9558                }
9559                let mut sum = match &arr[0] {
9560                    Value::Int(_) => Value::Int(0),
9561                    Value::Float(_) => Value::Float(0.0),
9562                    _ => return Err(RuntimeError::new("Cannot sum non-numeric array")),
9563                };
9564                for item in arr.iter() {
9565                    sum = match (&sum, item) {
9566                        (Value::Int(a), Value::Int(b)) => Value::Int(a + b),
9567                        (Value::Float(a), Value::Float(b)) => Value::Float(a + b),
9568                        (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 + b),
9569                        (Value::Float(a), Value::Int(b)) => Value::Float(a + *b as f64),
9570                        _ => return Err(RuntimeError::new("Cannot sum non-numeric values")),
9571                    };
9572                }
9573                Ok(sum)
9574            }
9575            _ => Err(RuntimeError::new("sum requires array")),
9576        }
9577    }
9578
9579    fn product_values(&self, value: Value) -> Result<Value, RuntimeError> {
9580        match value {
9581            Value::Array(arr) => {
9582                let arr = arr.borrow();
9583                if arr.is_empty() {
9584                    return Ok(Value::Int(1));
9585                }
9586                let mut prod = match &arr[0] {
9587                    Value::Int(_) => Value::Int(1),
9588                    Value::Float(_) => Value::Float(1.0),
9589                    _ => return Err(RuntimeError::new("Cannot multiply non-numeric array")),
9590                };
9591                for item in arr.iter() {
9592                    prod = match (&prod, item) {
9593                        (Value::Int(a), Value::Int(b)) => Value::Int(a * b),
9594                        (Value::Float(a), Value::Float(b)) => Value::Float(a * b),
9595                        (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 * b),
9596                        (Value::Float(a), Value::Int(b)) => Value::Float(a * *b as f64),
9597                        _ => return Err(RuntimeError::new("Cannot multiply non-numeric values")),
9598                    };
9599                }
9600                Ok(prod)
9601            }
9602            _ => Err(RuntimeError::new("product requires array")),
9603        }
9604    }
9605
9606    fn min_values(&self, value: Value) -> Result<Value, RuntimeError> {
9607        match value {
9608            Value::Array(arr) => {
9609                let arr = arr.borrow();
9610                if arr.is_empty() {
9611                    return Err(RuntimeError::new("Cannot find min of empty array"));
9612                }
9613                let mut min = arr[0].clone();
9614                for item in arr.iter().skip(1) {
9615                    min = match (&min, item) {
9616                        (Value::Int(a), Value::Int(b)) => {
9617                            if *b < *a {
9618                                Value::Int(*b)
9619                            } else {
9620                                Value::Int(*a)
9621                            }
9622                        }
9623                        (Value::Float(a), Value::Float(b)) => {
9624                            if *b < *a {
9625                                Value::Float(*b)
9626                            } else {
9627                                Value::Float(*a)
9628                            }
9629                        }
9630                        (Value::Int(a), Value::Float(b)) => {
9631                            let af = *a as f64;
9632                            if *b < af {
9633                                Value::Float(*b)
9634                            } else {
9635                                Value::Float(af)
9636                            }
9637                        }
9638                        (Value::Float(a), Value::Int(b)) => {
9639                            let bf = *b as f64;
9640                            if bf < *a {
9641                                Value::Float(bf)
9642                            } else {
9643                                Value::Float(*a)
9644                            }
9645                        }
9646                        _ => {
9647                            return Err(RuntimeError::new("Cannot find min of non-numeric values"))
9648                        }
9649                    };
9650                }
9651                Ok(min)
9652            }
9653            _ => Err(RuntimeError::new("min requires array")),
9654        }
9655    }
9656
9657    fn max_values(&self, value: Value) -> Result<Value, RuntimeError> {
9658        match value {
9659            Value::Array(arr) => {
9660                let arr = arr.borrow();
9661                if arr.is_empty() {
9662                    return Err(RuntimeError::new("Cannot find max of empty array"));
9663                }
9664                let mut max = arr[0].clone();
9665                for item in arr.iter().skip(1) {
9666                    max = match (&max, item) {
9667                        (Value::Int(a), Value::Int(b)) => {
9668                            if *b > *a {
9669                                Value::Int(*b)
9670                            } else {
9671                                Value::Int(*a)
9672                            }
9673                        }
9674                        (Value::Float(a), Value::Float(b)) => {
9675                            if *b > *a {
9676                                Value::Float(*b)
9677                            } else {
9678                                Value::Float(*a)
9679                            }
9680                        }
9681                        (Value::Int(a), Value::Float(b)) => {
9682                            let af = *a as f64;
9683                            if *b > af {
9684                                Value::Float(*b)
9685                            } else {
9686                                Value::Float(af)
9687                            }
9688                        }
9689                        (Value::Float(a), Value::Int(b)) => {
9690                            let bf = *b as f64;
9691                            if bf > *a {
9692                                Value::Float(bf)
9693                            } else {
9694                                Value::Float(*a)
9695                            }
9696                        }
9697                        _ => {
9698                            return Err(RuntimeError::new("Cannot find max of non-numeric values"))
9699                        }
9700                    };
9701                }
9702                Ok(max)
9703            }
9704            _ => Err(RuntimeError::new("max requires array")),
9705        }
9706    }
9707
9708    fn concat_values(&self, value: Value) -> Result<Value, RuntimeError> {
9709        match value {
9710            Value::Array(arr) => {
9711                let arr = arr.borrow();
9712                if arr.is_empty() {
9713                    return Ok(Value::String(Rc::new(String::new())));
9714                }
9715                // Determine if we're concatenating strings or arrays
9716                match &arr[0] {
9717                    Value::String(_) => {
9718                        let mut result = String::new();
9719                        for item in arr.iter() {
9720                            if let Value::String(s) = item {
9721                                result.push_str(s);
9722                            } else {
9723                                return Err(RuntimeError::new(
9724                                    "concat requires all elements to be strings",
9725                                ));
9726                            }
9727                        }
9728                        Ok(Value::String(Rc::new(result)))
9729                    }
9730                    Value::Array(_) => {
9731                        let mut result = Vec::new();
9732                        for item in arr.iter() {
9733                            if let Value::Array(inner) = item {
9734                                result.extend(inner.borrow().iter().cloned());
9735                            } else {
9736                                return Err(RuntimeError::new(
9737                                    "concat requires all elements to be arrays",
9738                                ));
9739                            }
9740                        }
9741                        Ok(Value::Array(Rc::new(RefCell::new(result))))
9742                    }
9743                    _ => Err(RuntimeError::new("concat requires strings or arrays")),
9744                }
9745            }
9746            _ => Err(RuntimeError::new("concat requires array")),
9747        }
9748    }
9749
9750    fn all_values(&self, value: Value) -> Result<Value, RuntimeError> {
9751        match value {
9752            Value::Array(arr) => {
9753                let arr = arr.borrow();
9754                for item in arr.iter() {
9755                    match item {
9756                        Value::Bool(b) => {
9757                            if !*b {
9758                                return Ok(Value::Bool(false));
9759                            }
9760                        }
9761                        _ => return Err(RuntimeError::new("all requires array of booleans")),
9762                    }
9763                }
9764                Ok(Value::Bool(true))
9765            }
9766            _ => Err(RuntimeError::new("all requires array")),
9767        }
9768    }
9769
9770    fn any_values(&self, value: Value) -> Result<Value, RuntimeError> {
9771        match value {
9772            Value::Array(arr) => {
9773                let arr = arr.borrow();
9774                for item in arr.iter() {
9775                    match item {
9776                        Value::Bool(b) => {
9777                            if *b {
9778                                return Ok(Value::Bool(true));
9779                            }
9780                        }
9781                        _ => return Err(RuntimeError::new("any requires array of booleans")),
9782                    }
9783                }
9784                Ok(Value::Bool(false))
9785            }
9786            _ => Err(RuntimeError::new("any requires array")),
9787        }
9788    }
9789
9790    fn compare_values(&self, a: &Value, b: &Value, _field: &Option<Ident>) -> std::cmp::Ordering {
9791        // Simple comparison for now
9792        match (a, b) {
9793            (Value::Int(a), Value::Int(b)) => a.cmp(b),
9794            (Value::Float(a), Value::Float(b)) => {
9795                a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)
9796            }
9797            (Value::String(a), Value::String(b)) => a.cmp(b),
9798            _ => std::cmp::Ordering::Equal,
9799        }
9800    }
9801
9802    /// Subtract two values (for diff operation)
9803    fn subtract_values(&self, a: &Value, b: &Value) -> Result<Value, RuntimeError> {
9804        match (a, b) {
9805            (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a - b)),
9806            (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a - b)),
9807            (Value::Int(a), Value::Float(b)) => Ok(Value::Float(*a as f64 - b)),
9808            (Value::Float(a), Value::Int(b)) => Ok(Value::Float(a - *b as f64)),
9809            _ => Err(RuntimeError::new(format!(
9810                "Cannot subtract {:?} from {:?}",
9811                b, a
9812            ))),
9813        }
9814    }
9815
9816    fn eval_closure(
9817        &mut self,
9818        params: &[ClosureParam],
9819        body: &Expr,
9820    ) -> Result<Value, RuntimeError> {
9821        let param_names: Vec<String> = params
9822            .iter()
9823            .map(|p| match &p.pattern {
9824                Pattern::Ident { name, .. } => name.name.clone(),
9825                _ => "_".to_string(),
9826            })
9827            .collect();
9828
9829        Ok(Value::Function(Rc::new(Function {
9830            name: None,
9831            params: param_names,
9832            body: body.clone(),
9833            closure: self.environment.clone(),
9834        })))
9835    }
9836
9837    fn eval_struct_literal(
9838        &mut self,
9839        path: &TypePath,
9840        fields: &[FieldInit],
9841        rest: &Option<Box<Expr>>,
9842    ) -> Result<Value, RuntimeError> {
9843        let raw_name = path
9844            .segments
9845            .iter()
9846            .map(|s| s.ident.name.as_str())
9847            .collect::<Vec<_>>()
9848            .join("::");
9849
9850        // Resolve "Self" to the actual type name if we're in an impl block
9851        let name = if raw_name == "Self" {
9852            if let Some(ref self_type) = self.current_self_type {
9853                self_type.clone()
9854            } else {
9855                // Fall back to trying to infer from field names
9856                raw_name
9857            }
9858        } else {
9859            raw_name
9860        };
9861
9862        let mut field_values = HashMap::new();
9863
9864        // If there's a rest expression (..expr), evaluate it first to get base fields
9865        if let Some(rest_expr) = rest {
9866            // Set current_self_type for the rest expression (e.g., Default::default())
9867            let prev_self_type = self.current_self_type.clone();
9868            self.current_self_type = Some(name.clone());
9869
9870            let rest_value = self.evaluate(rest_expr)?;
9871
9872            self.current_self_type = prev_self_type;
9873
9874            // Extract fields from the rest value
9875            if let Value::Struct { fields: rest_fields, .. } = rest_value {
9876                for (k, v) in rest_fields.borrow().iter() {
9877                    field_values.insert(k.clone(), v.clone());
9878                }
9879            }
9880        }
9881
9882        // Override with explicitly provided fields
9883        for field in fields {
9884            let value = match &field.value {
9885                Some(expr) => self.evaluate(expr)?,
9886                None => self
9887                    .environment
9888                    .borrow()
9889                    .get(&field.name.name)
9890                    .ok_or_else(|| {
9891                        RuntimeError::new(format!("Unknown variable: {}", field.name.name))
9892                    })?,
9893            };
9894            field_values.insert(field.name.name.clone(), value);
9895        }
9896
9897        Ok(Value::Struct {
9898            name,
9899            fields: Rc::new(RefCell::new(field_values)),
9900        })
9901    }
9902
9903    /// Extract evidentiality from a value (recursively unwraps Evidential wrapper)
9904    fn extract_evidence(value: &Value) -> Option<Evidence> {
9905        match value {
9906            Value::Evidential { evidence, .. } => Some(*evidence),
9907            _ => None,
9908        }
9909    }
9910
9911    /// Extract affect from a value
9912    fn extract_affect(value: &Value) -> Option<&RuntimeAffect> {
9913        match value {
9914            Value::Affective { affect, .. } => Some(affect),
9915            _ => None,
9916        }
9917    }
9918
9919    /// Derive evidence from affect markers.
9920    /// Sarcasm implies uncertainty (meaning is inverted).
9921    /// Confidence directly maps to evidence levels.
9922    fn affect_to_evidence(affect: &RuntimeAffect) -> Option<Evidence> {
9923        // Sarcasm indicates the literal meaning shouldn't be trusted
9924        if affect.sarcasm {
9925            return Some(Evidence::Uncertain);
9926        }
9927
9928        // Confidence maps directly to evidence
9929        match affect.confidence {
9930            Some(RuntimeConfidence::High) => Some(Evidence::Known),
9931            Some(RuntimeConfidence::Low) => Some(Evidence::Uncertain),
9932            Some(RuntimeConfidence::Medium) | None => None,
9933        }
9934    }
9935
9936    /// Combine two evidence levels, returning the "worst" (most uncertain) one.
9937    /// Order: Known < Uncertain < Reported < Paradox
9938    fn combine_evidence(a: Option<Evidence>, b: Option<Evidence>) -> Option<Evidence> {
9939        match (a, b) {
9940            (None, None) => None,
9941            (Some(e), None) | (None, Some(e)) => Some(e),
9942            (Some(a), Some(b)) => {
9943                let rank = |e: Evidence| match e {
9944                    Evidence::Known => 0,
9945                    Evidence::Uncertain => 1,
9946                    Evidence::Reported => 2,
9947                    Evidence::Paradox => 3,
9948                };
9949                if rank(a) >= rank(b) {
9950                    Some(a)
9951                } else {
9952                    Some(b)
9953                }
9954            }
9955        }
9956    }
9957
9958    /// Unwrap an evidential value to get the inner value for display
9959    fn unwrap_evidential(value: &Value) -> &Value {
9960        match value {
9961            Value::Evidential { value: inner, .. } => Self::unwrap_evidential(inner),
9962            _ => value,
9963        }
9964    }
9965
9966    /// Unwrap an affective value to get the inner value
9967    fn unwrap_affective(value: &Value) -> &Value {
9968        match value {
9969            Value::Affective { value: inner, .. } => Self::unwrap_affective(inner),
9970            _ => value,
9971        }
9972    }
9973
9974    /// Unwrap both evidential and affective wrappers
9975    fn unwrap_value(value: &Value) -> &Value {
9976        match value {
9977            Value::Evidential { value: inner, .. } => Self::unwrap_value(inner),
9978            Value::Affective { value: inner, .. } => Self::unwrap_value(inner),
9979            _ => value,
9980        }
9981    }
9982
9983    /// Unwrap all wrappers including Ref for deep value access
9984    fn unwrap_all(value: &Value) -> Value {
9985        match value {
9986            Value::Evidential { value: inner, .. } => Self::unwrap_all(inner),
9987            Value::Affective { value: inner, .. } => Self::unwrap_all(inner),
9988            Value::Ref(r) => Self::unwrap_all(&r.borrow()),
9989            _ => value.clone(),
9990        }
9991    }
9992
9993    fn eval_evidential(&mut self, expr: &Expr, ev: &Evidentiality) -> Result<Value, RuntimeError> {
9994        let value = self.evaluate(expr)?;
9995
9996        // For Known (!) evidentiality - this is an "unwrap" or "assert known" operation
9997        // If the value is null, return null (propagate nulls for graceful handling)
9998        // If the value is already evidential, unwrap it
9999        // Otherwise, return the value as-is (it's implicitly known)
10000        if *ev == Evidentiality::Known {
10001            return match value {
10002                Value::Null => Ok(Value::Null),  // Null propagates
10003                Value::Evidential { value: inner, .. } => Ok(*inner),  // Unwrap evidential
10004                other => Ok(other),  // Non-null, non-evidential returns as-is
10005            };
10006        }
10007
10008        let evidence = match ev {
10009            Evidentiality::Known => Evidence::Known,  // Won't reach here
10010            Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
10011            Evidentiality::Reported => Evidence::Reported,
10012            Evidentiality::Paradox => Evidence::Paradox,
10013        };
10014        Ok(Value::Evidential {
10015            value: Box::new(value),
10016            evidence,
10017        })
10018    }
10019
10020    /// Evaluate format! macro - parse format string and arguments
10021    fn eval_format_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
10022        // Token string looks like: "\"format string\" , arg1 , arg2"
10023        // We need to parse this properly
10024
10025        // Find the format string (first quoted string)
10026        let tokens = tokens.trim();
10027        if !tokens.starts_with('"') {
10028            // No format string - just return the tokens as-is
10029            return Ok(Value::String(Rc::new(tokens.to_string())));
10030        }
10031
10032        // Find the end of the format string
10033        let mut in_escape = false;
10034        let mut format_end = 1;
10035        for (i, c) in tokens[1..].char_indices() {
10036            if in_escape {
10037                in_escape = false;
10038            } else if c == '\\' {
10039                in_escape = true;
10040            } else if c == '"' {
10041                format_end = i + 2; // +1 for starting quote, +1 for this quote
10042                break;
10043            }
10044        }
10045
10046        let format_str = &tokens[1..format_end-1]; // Remove quotes
10047        crate::sigil_debug!("DEBUG format_str: '{}'", format_str);
10048        let args_str = if format_end < tokens.len() {
10049            tokens[format_end..].trim_start_matches(',').trim()
10050        } else {
10051            ""
10052        };
10053
10054        // Parse and evaluate arguments
10055        let mut arg_values: Vec<String> = Vec::new();
10056        if !args_str.is_empty() {
10057            // Split by comma, but respect parentheses/brackets
10058            let mut depth = 0;
10059            let mut current_arg = String::new();
10060            for c in args_str.chars() {
10061                match c {
10062                    '(' | '[' | '{' => {
10063                        depth += 1;
10064                        current_arg.push(c);
10065                    }
10066                    ')' | ']' | '}' => {
10067                        depth -= 1;
10068                        current_arg.push(c);
10069                    }
10070                    ',' if depth == 0 => {
10071                        let arg = current_arg.trim().to_string();
10072                        if !arg.is_empty() {
10073                            // Parse and evaluate the argument expression
10074                            let mut parser = crate::parser::Parser::new(&arg);
10075                            match parser.parse_expr() {
10076                                Ok(expr) => {
10077                                    match self.evaluate(&expr) {
10078                                        Ok(val) => arg_values.push(self.format_value(&val)),
10079                                        Err(_) => arg_values.push(arg),
10080                                    }
10081                                }
10082                                Err(_) => arg_values.push(arg),
10083                            }
10084                        }
10085                        current_arg.clear();
10086                    }
10087                    _ => current_arg.push(c),
10088                }
10089            }
10090            // Don't forget the last argument
10091            let arg = current_arg.trim().to_string();
10092            if !arg.is_empty() {
10093                let mut parser = crate::parser::Parser::new(&arg);
10094                match parser.parse_expr() {
10095                    Ok(expr) => {
10096                        match self.evaluate(&expr) {
10097                            Ok(val) => arg_values.push(self.format_value(&val)),
10098                            Err(_) => arg_values.push(arg),
10099                        }
10100                    }
10101                    Err(_) => arg_values.push(arg),
10102                }
10103            }
10104        }
10105
10106        // Format the string by replacing {} and {:?} with arguments
10107        let mut result = String::new();
10108        let mut arg_idx = 0;
10109        let mut chars = format_str.chars().peekable();
10110
10111        while let Some(c) = chars.next() {
10112            if c == '{' {
10113                if chars.peek() == Some(&'{') {
10114                    // Escaped {{ -> {
10115                    chars.next();
10116                    result.push('{');
10117                } else {
10118                    // Consume until }
10119                    let mut placeholder = String::new();
10120                    while let Some(pc) = chars.next() {
10121                        if pc == '}' {
10122                            break;
10123                        }
10124                        placeholder.push(pc);
10125                    }
10126                    // Insert argument value
10127                    if arg_idx < arg_values.len() {
10128                        result.push_str(&arg_values[arg_idx]);
10129                        arg_idx += 1;
10130                    } else {
10131                        result.push_str(&format!("{{{}}}", placeholder));
10132                    }
10133                }
10134            } else if c == '}' {
10135                if chars.peek() == Some(&'}') {
10136                    // Escaped }} -> }
10137                    chars.next();
10138                    result.push('}');
10139                } else {
10140                    result.push('}');
10141                }
10142            } else if c == '\\' {
10143                // Handle escape sequences
10144                if let Some(next) = chars.next() {
10145                    match next {
10146                        'n' => result.push('\n'),
10147                        't' => result.push('\t'),
10148                        'r' => result.push('\r'),
10149                        '\\' => result.push('\\'),
10150                        '"' => result.push('"'),
10151                        _ => {
10152                            result.push('\\');
10153                            result.push(next);
10154                        }
10155                    }
10156                }
10157            } else {
10158                result.push(c);
10159            }
10160        }
10161
10162        Ok(Value::String(Rc::new(result)))
10163    }
10164
10165    /// Format a value for display in format!
10166    fn format_value(&self, value: &Value) -> String {
10167        match value {
10168            Value::String(s) => s.to_string(),
10169            Value::Int(n) => n.to_string(),
10170            Value::Float(f) => f.to_string(),
10171            Value::Bool(b) => b.to_string(),
10172            Value::Char(c) => c.to_string(),
10173            Value::Null => "null".to_string(),
10174            Value::Array(arr) => {
10175                let items: Vec<String> = arr.borrow().iter().map(|v| self.format_value(v)).collect();
10176                format!("[{}]", items.join(", "))
10177            }
10178            Value::Tuple(items) => {
10179                let formatted: Vec<String> = items.iter().map(|v| self.format_value(v)).collect();
10180                format!("({})", formatted.join(", "))
10181            }
10182            Value::Struct { name, fields } => {
10183                let field_strs: Vec<String> = fields.borrow().iter()
10184                    .map(|(k, v)| format!("{}: {}", k, self.format_value(v)))
10185                    .collect();
10186                format!("{} {{ {} }}", name, field_strs.join(", "))
10187            }
10188            Value::Variant { enum_name, variant_name, fields } => {
10189                match fields {
10190                    Some(f) if !f.is_empty() => {
10191                        let formatted: Vec<String> = f.iter().map(|v| self.format_value(v)).collect();
10192                        format!("{}::{}({})", enum_name, variant_name, formatted.join(", "))
10193                    }
10194                    _ => format!("{}::{}", enum_name, variant_name),
10195                }
10196            }
10197            Value::Evidential { value: inner, evidence } => {
10198                format!("{:?}{}", evidence, self.format_value(inner))
10199            }
10200            Value::Ref(r) => self.format_value(&r.borrow()),
10201            _ => format!("{:?}", value),
10202        }
10203    }
10204
10205    /// Evaluate vec! macro
10206    fn eval_vec_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
10207        // Parse comma-separated elements
10208        let mut elements = Vec::new();
10209        let mut depth = 0;
10210        let mut current = String::new();
10211
10212        for c in tokens.chars() {
10213            match c {
10214                '(' | '[' | '{' => {
10215                    depth += 1;
10216                    current.push(c);
10217                }
10218                ')' | ']' | '}' => {
10219                    depth -= 1;
10220                    current.push(c);
10221                }
10222                ',' if depth == 0 => {
10223                    let elem = current.trim().to_string();
10224                    if !elem.is_empty() {
10225                        let mut parser = crate::parser::Parser::new(&elem);
10226                        if let Ok(expr) = parser.parse_expr() {
10227                            elements.push(self.evaluate(&expr)?);
10228                        }
10229                    }
10230                    current.clear();
10231                }
10232                _ => current.push(c),
10233            }
10234        }
10235
10236        // Last element
10237        let elem = current.trim().to_string();
10238        if !elem.is_empty() {
10239            let mut parser = crate::parser::Parser::new(&elem);
10240            if let Ok(expr) = parser.parse_expr() {
10241                elements.push(self.evaluate(&expr)?);
10242            }
10243        }
10244
10245        Ok(Value::Array(Rc::new(RefCell::new(elements))))
10246    }
10247
10248    fn eval_range(
10249        &mut self,
10250        start: &Option<Box<Expr>>,
10251        end: &Option<Box<Expr>>,
10252        inclusive: bool,
10253    ) -> Result<Value, RuntimeError> {
10254        let start_val = match start {
10255            Some(e) => match self.evaluate(e)? {
10256                Value::Int(n) => n,
10257                _ => return Err(RuntimeError::new("Range requires integer bounds")),
10258            },
10259            None => 0,
10260        };
10261
10262        let end_val = match end {
10263            Some(e) => match self.evaluate(e)? {
10264                Value::Int(n) => n,
10265                _ => return Err(RuntimeError::new("Range requires integer bounds")),
10266            },
10267            None => {
10268                // Open-ended range (like 1..) - return a tuple (start, None) marker
10269                // This can be used by slice operations to slice to end
10270                return Ok(Value::Tuple(Rc::new(vec![
10271                    Value::Int(start_val),
10272                    Value::Null,  // None marker for open end
10273                ])));
10274            }
10275        };
10276
10277        let values: Vec<Value> = if inclusive {
10278            (start_val..=end_val).map(Value::Int).collect()
10279        } else {
10280            (start_val..end_val).map(Value::Int).collect()
10281        };
10282
10283        Ok(Value::Array(Rc::new(RefCell::new(values))))
10284    }
10285
10286    fn is_truthy(&self, value: &Value) -> bool {
10287        match value {
10288            Value::Null => false,
10289            Value::Bool(b) => *b,
10290            Value::Int(n) => *n != 0,
10291            Value::Float(n) => *n != 0.0,
10292            Value::String(s) => !s.is_empty(),
10293            Value::Array(arr) => !arr.borrow().is_empty(),
10294            Value::Empty => false,
10295            Value::Evidential { value, .. } => self.is_truthy(value),
10296            _ => true,
10297        }
10298    }
10299}
10300
10301impl Default for Interpreter {
10302    fn default() -> Self {
10303        Self::new()
10304    }
10305}
10306
10307#[cfg(test)]
10308mod tests {
10309    use super::*;
10310    use crate::Parser;
10311
10312    fn run(source: &str) -> Result<Value, RuntimeError> {
10313        let mut parser = Parser::new(source);
10314        let file = parser
10315            .parse_file()
10316            .map_err(|e| RuntimeError::new(e.to_string()))?;
10317        let mut interp = Interpreter::new();
10318        interp.execute(&file)
10319    }
10320
10321    #[test]
10322    fn test_arithmetic() {
10323        assert!(matches!(
10324            run("fn main() { return 2 + 3; }"),
10325            Ok(Value::Int(5))
10326        ));
10327        assert!(matches!(
10328            run("fn main() { return 10 - 4; }"),
10329            Ok(Value::Int(6))
10330        ));
10331        assert!(matches!(
10332            run("fn main() { return 3 * 4; }"),
10333            Ok(Value::Int(12))
10334        ));
10335        assert!(matches!(
10336            run("fn main() { return 15 / 3; }"),
10337            Ok(Value::Int(5))
10338        ));
10339        assert!(matches!(
10340            run("fn main() { return 2 ** 10; }"),
10341            Ok(Value::Int(1024))
10342        ));
10343    }
10344
10345    #[test]
10346    fn test_variables() {
10347        assert!(matches!(
10348            run("fn main() { let x = 42; return x; }"),
10349            Ok(Value::Int(42))
10350        ));
10351    }
10352
10353    #[test]
10354    fn test_conditionals() {
10355        assert!(matches!(
10356            run("fn main() { if true { return 1; } else { return 2; } }"),
10357            Ok(Value::Int(1))
10358        ));
10359        assert!(matches!(
10360            run("fn main() { if false { return 1; } else { return 2; } }"),
10361            Ok(Value::Int(2))
10362        ));
10363    }
10364
10365    #[test]
10366    fn test_arrays() {
10367        assert!(matches!(
10368            run("fn main() { return [1, 2, 3][1]; }"),
10369            Ok(Value::Int(2))
10370        ));
10371    }
10372
10373    #[test]
10374    fn test_functions() {
10375        let result = run("
10376            fn double(x: i64) -> i64 { return x * 2; }
10377            fn main() { return double(21); }
10378        ");
10379        assert!(matches!(result, Ok(Value::Int(42))));
10380    }
10381
10382    #[test]
10383    fn test_pipe_transform() {
10384        let result = run("fn main() { return [1, 2, 3]|τ{_ * 2}|sum; }");
10385        assert!(matches!(result, Ok(Value::Int(12))));
10386    }
10387
10388    #[test]
10389    fn test_pipe_filter() {
10390        let result = run("fn main() { return [1, 2, 3, 4, 5]|φ{_ > 2}|sum; }");
10391        assert!(matches!(result, Ok(Value::Int(12)))); // 3 + 4 + 5
10392    }
10393
10394    #[test]
10395    fn test_interpolation_evidentiality_propagation() {
10396        // Test that evidentiality propagates through string interpolation
10397        // When an evidential value is interpolated, the result string should carry that evidentiality
10398        let result = run(r#"
10399            fn main() {
10400                let rep = reported(42);
10401
10402                // Interpolating a reported value should make the string reported
10403                let s = f"Value: {rep}";
10404                return s;
10405            }
10406        "#);
10407
10408        match result {
10409            Ok(Value::Evidential {
10410                evidence: Evidence::Reported,
10411                value,
10412            }) => {
10413                // The inner value should be a string
10414                assert!(matches!(*value, Value::String(_)));
10415            }
10416            Ok(other) => panic!("Expected Evidential Reported, got {:?}", other),
10417            Err(e) => panic!("Error: {:?}", e),
10418        }
10419    }
10420
10421    #[test]
10422    fn test_interpolation_worst_evidence_wins() {
10423        // When multiple evidential values are interpolated, the worst evidence level wins
10424        let result = run(r#"
10425            fn main() {
10426                let k = known(1);         // Known is best
10427                let u = uncertain(2);     // Uncertain is worse
10428
10429                // Combining known and uncertain should yield uncertain
10430                let s = f"{k} and {u}";
10431                return s;
10432            }
10433        "#);
10434
10435        match result {
10436            Ok(Value::Evidential {
10437                evidence: Evidence::Uncertain,
10438                ..
10439            }) => (),
10440            Ok(other) => panic!("Expected Evidential Uncertain, got {:?}", other),
10441            Err(e) => panic!("Error: {:?}", e),
10442        }
10443    }
10444
10445    #[test]
10446    fn test_interpolation_no_evidential_plain_string() {
10447        // When no evidential values are interpolated, the result is a plain string
10448        let result = run(r#"
10449            fn main() {
10450                let x = 42;
10451                let s = f"Value: {x}";
10452                return s;
10453            }
10454        "#);
10455
10456        match result {
10457            Ok(Value::String(s)) => {
10458                assert_eq!(*s, "Value: 42");
10459            }
10460            Ok(other) => panic!("Expected plain String, got {:?}", other),
10461            Err(e) => panic!("Error: {:?}", e),
10462        }
10463    }
10464}