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}
92
93/// Future state for async computations
94#[derive(Clone)]
95pub enum FutureState {
96    /// Not yet started
97    Pending,
98    /// Currently executing
99    Running,
100    /// Completed with value
101    Ready(Box<Value>),
102    /// Failed with error
103    Failed(String),
104}
105
106/// Inner future representation
107pub struct FutureInner {
108    /// Current state
109    pub state: FutureState,
110    /// The computation to run (if pending)
111    pub computation: Option<FutureComputation>,
112    /// Completion time for timer futures
113    pub complete_at: Option<std::time::Instant>,
114}
115
116impl Clone for FutureInner {
117    fn clone(&self) -> Self {
118        FutureInner {
119            state: self.state.clone(),
120            computation: self.computation.clone(),
121            complete_at: self.complete_at,
122        }
123    }
124}
125
126/// Types of future computations
127#[derive(Clone)]
128pub enum FutureComputation {
129    /// Immediate value (already resolved)
130    Immediate(Box<Value>),
131    /// Timer - completes after duration
132    Timer(std::time::Duration),
133    /// Lazy computation - function + captured args
134    Lazy {
135        func: Rc<Function>,
136        args: Vec<Value>,
137    },
138    /// Join multiple futures
139    Join(Vec<Rc<RefCell<FutureInner>>>),
140    /// Race multiple futures (first to complete wins)
141    Race(Vec<Rc<RefCell<FutureInner>>>),
142}
143
144/// Inner channel state - wraps mpsc channel
145pub struct ChannelInner {
146    pub sender: Mutex<mpsc::Sender<Value>>,
147    pub receiver: Mutex<mpsc::Receiver<Value>>,
148}
149
150impl Clone for ChannelInner {
151    fn clone(&self) -> Self {
152        // Channels can't really be cloned - create a dummy
153        // This is for the Clone requirement on Value
154        panic!("Channels cannot be cloned directly - use channel_clone()")
155    }
156}
157
158/// Inner actor state - single-threaded for interpreter (Value contains Rc)
159/// For true async actors, use the JIT backend
160pub struct ActorInner {
161    pub name: String,
162    pub message_queue: Mutex<Vec<(String, String)>>, // (msg_type, serialized_data)
163    pub message_count: std::sync::atomic::AtomicUsize,
164}
165
166/// Evidence level at runtime
167#[derive(Debug, Clone, Copy, PartialEq, Eq)]
168pub enum Evidence {
169    Known,     // !
170    Uncertain, // ?
171    Reported,  // ~
172    Paradox,   // ‽
173}
174
175/// Runtime affect markers for sentiment and emotion tracking
176#[derive(Debug, Clone, PartialEq)]
177pub struct RuntimeAffect {
178    pub sentiment: Option<RuntimeSentiment>,
179    pub sarcasm: bool, // ⸮
180    pub intensity: Option<RuntimeIntensity>,
181    pub formality: Option<RuntimeFormality>,
182    pub emotion: Option<RuntimeEmotion>,
183    pub confidence: Option<RuntimeConfidence>,
184}
185
186#[derive(Debug, Clone, Copy, PartialEq, Eq)]
187pub enum RuntimeSentiment {
188    Positive, // ⊕
189    Negative, // ⊖
190    Neutral,  // ⊜
191}
192
193#[derive(Debug, Clone, Copy, PartialEq, Eq)]
194pub enum RuntimeIntensity {
195    Up,   // ↑
196    Down, // ↓
197    Max,  // ⇈
198}
199
200#[derive(Debug, Clone, Copy, PartialEq, Eq)]
201pub enum RuntimeFormality {
202    Formal,   // ♔
203    Informal, // ♟
204}
205
206#[derive(Debug, Clone, Copy, PartialEq, Eq)]
207pub enum RuntimeEmotion {
208    Joy,      // ☺
209    Sadness,  // ☹
210    Anger,    // ⚡
211    Fear,     // ❄
212    Surprise, // ✦
213    Love,     // ♡
214}
215
216#[derive(Debug, Clone, Copy, PartialEq, Eq)]
217pub enum RuntimeConfidence {
218    High,   // ◉
219    Medium, // ◎
220    Low,    // ○
221}
222
223/// A Sigil function
224pub struct Function {
225    pub name: Option<String>,
226    pub params: Vec<String>,
227    pub body: Expr,
228    pub closure: Rc<RefCell<Environment>>,
229}
230
231/// Built-in function type
232pub struct BuiltInFn {
233    pub name: String,
234    pub arity: Option<usize>, // None = variadic
235    pub func: fn(&mut Interpreter, Vec<Value>) -> Result<Value, RuntimeError>,
236}
237
238impl fmt::Debug for Value {
239    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240        match self {
241            Value::Null => write!(f, "null"),
242            Value::Bool(b) => write!(f, "{}", b),
243            Value::Int(n) => write!(f, "{}", n),
244            Value::Float(n) => write!(f, "{}", n),
245            Value::String(s) => write!(f, "\"{}\"", s),
246            Value::Char(c) => write!(f, "'{}'", c),
247            Value::Array(arr) => {
248                let arr = arr.borrow();
249                write!(f, "[")?;
250                for (i, v) in arr.iter().enumerate() {
251                    if i > 0 {
252                        write!(f, ", ")?;
253                    }
254                    write!(f, "{:?}", v)?;
255                }
256                write!(f, "]")
257            }
258            Value::Tuple(vals) => {
259                write!(f, "(")?;
260                for (i, v) in vals.iter().enumerate() {
261                    if i > 0 {
262                        write!(f, ", ")?;
263                    }
264                    write!(f, "{:?}", v)?;
265                }
266                write!(f, ")")
267            }
268            Value::Struct { name, fields } => {
269                write!(f, "{} {{ ", name)?;
270                let fields = fields.borrow();
271                for (i, (k, v)) in fields.iter().enumerate() {
272                    if i > 0 {
273                        write!(f, ", ")?;
274                    }
275                    write!(f, "{}: {:?}", k, v)?;
276                }
277                write!(f, " }}")
278            }
279            Value::Variant {
280                enum_name,
281                variant_name,
282                fields,
283            } => {
284                write!(f, "{}::{}", enum_name, variant_name)?;
285                if let Some(fields) = fields {
286                    write!(f, "(")?;
287                    for (i, v) in fields.iter().enumerate() {
288                        if i > 0 {
289                            write!(f, ", ")?;
290                        }
291                        write!(f, "{:?}", v)?;
292                    }
293                    write!(f, ")")?;
294                }
295                Ok(())
296            }
297            Value::Function(func) => {
298                write!(f, "<fn {}>", func.name.as_deref().unwrap_or("anonymous"))
299            }
300            Value::BuiltIn(b) => write!(f, "<builtin {}>", b.name),
301            Value::Ref(r) => write!(f, "&{:?}", r.borrow()),
302            Value::Infinity => write!(f, "∞"),
303            Value::Empty => write!(f, "∅"),
304            Value::Evidential { value, evidence } => {
305                write!(f, "{:?}", value)?;
306                match evidence {
307                    Evidence::Known => write!(f, "!"),
308                    Evidence::Uncertain => write!(f, "?"),
309                    Evidence::Reported => write!(f, "~"),
310                    Evidence::Paradox => write!(f, "‽"),
311                }
312            }
313            Value::Map(map) => {
314                let map = map.borrow();
315                write!(f, "{{")?;
316                for (i, (k, v)) in map.iter().enumerate() {
317                    if i > 0 {
318                        write!(f, ", ")?;
319                    }
320                    write!(f, "{:?}: {:?}", k, v)?;
321                }
322                write!(f, "}}")
323            }
324            Value::Set(set) => {
325                let set = set.borrow();
326                write!(f, "Set{{")?;
327                for (i, k) in set.iter().enumerate() {
328                    if i > 0 {
329                        write!(f, ", ")?;
330                    }
331                    write!(f, "{:?}", k)?;
332                }
333                write!(f, "}}")
334            }
335            Value::Channel(_) => write!(f, "<channel>"),
336            Value::ThreadHandle(_) => write!(f, "<thread>"),
337            Value::Actor(actor) => write!(f, "<actor {}>", actor.name),
338            Value::Future(fut) => {
339                let fut = fut.borrow();
340                match &fut.state {
341                    FutureState::Pending => write!(f, "<future pending>"),
342                    FutureState::Running => write!(f, "<future running>"),
343                    FutureState::Ready(v) => write!(f, "<future ready: {:?}>", v),
344                    FutureState::Failed(e) => write!(f, "<future failed: {}>", e),
345                }
346            }
347            Value::Affective { value, affect } => {
348                write!(f, "{:?}", value)?;
349                if let Some(s) = &affect.sentiment {
350                    match s {
351                        RuntimeSentiment::Positive => write!(f, "⊕")?,
352                        RuntimeSentiment::Negative => write!(f, "⊖")?,
353                        RuntimeSentiment::Neutral => write!(f, "⊜")?,
354                    }
355                }
356                if affect.sarcasm {
357                    write!(f, "⸮")?;
358                }
359                if let Some(i) = &affect.intensity {
360                    match i {
361                        RuntimeIntensity::Up => write!(f, "↑")?,
362                        RuntimeIntensity::Down => write!(f, "↓")?,
363                        RuntimeIntensity::Max => write!(f, "⇈")?,
364                    }
365                }
366                if let Some(fo) = &affect.formality {
367                    match fo {
368                        RuntimeFormality::Formal => write!(f, "♔")?,
369                        RuntimeFormality::Informal => write!(f, "♟")?,
370                    }
371                }
372                if let Some(e) = &affect.emotion {
373                    match e {
374                        RuntimeEmotion::Joy => write!(f, "☺")?,
375                        RuntimeEmotion::Sadness => write!(f, "☹")?,
376                        RuntimeEmotion::Anger => write!(f, "⚡")?,
377                        RuntimeEmotion::Fear => write!(f, "❄")?,
378                        RuntimeEmotion::Surprise => write!(f, "✦")?,
379                        RuntimeEmotion::Love => write!(f, "♡")?,
380                    }
381                }
382                if let Some(c) = &affect.confidence {
383                    match c {
384                        RuntimeConfidence::High => write!(f, "◉")?,
385                        RuntimeConfidence::Medium => write!(f, "◎")?,
386                        RuntimeConfidence::Low => write!(f, "○")?,
387                    }
388                }
389                Ok(())
390            }
391            Value::VariantConstructor { enum_name, variant_name } => {
392                write!(f, "<constructor {}::{}>", enum_name, variant_name)
393            }
394            Value::DefaultConstructor { type_name } => {
395                write!(f, "<default {}>", type_name)
396            }
397            Value::Range { start, end, inclusive } => {
398                match (start, end) {
399                    (Some(s), Some(e)) => if *inclusive {
400                        write!(f, "{}..={}", s, e)
401                    } else {
402                        write!(f, "{}..{}", s, e)
403                    },
404                    (Some(s), None) => write!(f, "{}..", s),
405                    (None, Some(e)) => if *inclusive {
406                        write!(f, "..={}", e)
407                    } else {
408                        write!(f, "..{}", e)
409                    },
410                    (None, None) => write!(f, ".."),
411                }
412            }
413        }
414    }
415}
416
417impl fmt::Display for Value {
418    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419        match self {
420            Value::Null => write!(f, "null"),
421            Value::Bool(b) => write!(f, "{}", b),
422            Value::Int(n) => write!(f, "{}", n),
423            Value::Float(n) => write!(f, "{}", n),
424            Value::String(s) => write!(f, "{}", s),
425            Value::Char(c) => write!(f, "{}", c),
426            Value::Array(arr) => {
427                let arr = arr.borrow();
428                write!(f, "[")?;
429                for (i, v) in arr.iter().enumerate() {
430                    if i > 0 {
431                        write!(f, ", ")?;
432                    }
433                    write!(f, "{}", v)?;
434                }
435                write!(f, "]")
436            }
437            Value::Evidential { value, .. } => write!(f, "{}", value),
438            Value::Affective { value, affect } => {
439                // Display affect markers as suffix symbols
440                let mut suffix = String::new();
441                if let Some(sent) = &affect.sentiment {
442                    suffix.push(match sent {
443                        RuntimeSentiment::Positive => '⊕',
444                        RuntimeSentiment::Negative => '⊖',
445                        RuntimeSentiment::Neutral => '⊜',
446                    });
447                }
448                if affect.sarcasm {
449                    suffix.push('⸮');
450                }
451                if let Some(int) = &affect.intensity {
452                    suffix.push(match int {
453                        RuntimeIntensity::Up => '↑',
454                        RuntimeIntensity::Down => '↓',
455                        RuntimeIntensity::Max => '⇈',
456                    });
457                }
458                if let Some(form) = &affect.formality {
459                    suffix.push(match form {
460                        RuntimeFormality::Formal => '♔',
461                        RuntimeFormality::Informal => '♟',
462                    });
463                }
464                if let Some(emo) = &affect.emotion {
465                    suffix.push(match emo {
466                        RuntimeEmotion::Joy => '☺',
467                        RuntimeEmotion::Sadness => '☹',
468                        RuntimeEmotion::Anger => '⚡',
469                        RuntimeEmotion::Fear => '❄',
470                        RuntimeEmotion::Surprise => '✦',
471                        RuntimeEmotion::Love => '♡',
472                    });
473                }
474                if let Some(conf) = &affect.confidence {
475                    suffix.push(match conf {
476                        RuntimeConfidence::High => '◉',
477                        RuntimeConfidence::Medium => '◎',
478                        RuntimeConfidence::Low => '○',
479                    });
480                }
481                write!(f, "{}{}", value, suffix)
482            }
483            _ => write!(f, "{:?}", self),
484        }
485    }
486}
487
488/// Runtime error
489#[derive(Debug)]
490pub struct RuntimeError {
491    pub message: String,
492    pub span: Option<Span>,
493}
494
495impl RuntimeError {
496    pub fn new(message: impl Into<String>) -> Self {
497        Self {
498            message: message.into(),
499            span: None,
500        }
501    }
502
503    pub fn with_span(message: impl Into<String>, span: Span) -> Self {
504        Self {
505            message: message.into(),
506            span: Some(span),
507        }
508    }
509}
510
511impl fmt::Display for RuntimeError {
512    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
513        write!(f, "Runtime error: {}", self.message)?;
514        if let Some(span) = self.span {
515            write!(f, " at {}", span)?;
516        }
517        Ok(())
518    }
519}
520
521/// Control flow signals for return/break/continue
522#[derive(Debug, Clone)]
523pub enum ControlFlow {
524    Return(Value),
525    Break(Option<Value>),
526    Continue,
527}
528
529impl From<ControlFlow> for RuntimeError {
530    fn from(cf: ControlFlow) -> Self {
531        match cf {
532            ControlFlow::Return(_) => RuntimeError::new("return outside function"),
533            ControlFlow::Break(_) => RuntimeError::new("break outside loop"),
534            ControlFlow::Continue => RuntimeError::new("continue outside loop"),
535        }
536    }
537}
538
539/// Result type that can contain control flow
540pub type EvalResult = Result<Value, EvalError>;
541
542/// Error type that includes control flow
543#[derive(Debug)]
544pub enum EvalError {
545    Runtime(RuntimeError),
546    Control(ControlFlow),
547}
548
549impl From<RuntimeError> for EvalError {
550    fn from(e: RuntimeError) -> Self {
551        EvalError::Runtime(e)
552    }
553}
554
555impl From<ControlFlow> for EvalError {
556    fn from(cf: ControlFlow) -> Self {
557        EvalError::Control(cf)
558    }
559}
560
561impl fmt::Display for EvalError {
562    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563        match self {
564            EvalError::Runtime(e) => write!(f, "{}", e),
565            EvalError::Control(cf) => write!(f, "Unexpected control flow: {:?}", cf),
566        }
567    }
568}
569
570/// Environment for variable bindings
571#[derive(Clone)]
572pub struct Environment {
573    values: HashMap<String, Value>,
574    parent: Option<Rc<RefCell<Environment>>>,
575}
576
577impl Environment {
578    pub fn new() -> Self {
579        Self {
580            values: HashMap::new(),
581            parent: None,
582        }
583    }
584
585    pub fn with_parent(parent: Rc<RefCell<Environment>>) -> Self {
586        Self {
587            values: HashMap::new(),
588            parent: Some(parent),
589        }
590    }
591
592    pub fn define(&mut self, name: String, value: Value) {
593        self.values.insert(name, value);
594    }
595
596    pub fn get(&self, name: &str) -> Option<Value> {
597        if let Some(value) = self.values.get(name) {
598            Some(value.clone())
599        } else if let Some(ref parent) = self.parent {
600            parent.borrow().get(name)
601        } else {
602            None
603        }
604    }
605
606    pub fn set(&mut self, name: &str, value: Value) -> Result<(), RuntimeError> {
607        if self.values.contains_key(name) {
608            self.values.insert(name.to_string(), value);
609            Ok(())
610        } else if let Some(ref parent) = self.parent {
611            parent.borrow_mut().set(name, value)
612        } else {
613            Err(RuntimeError::new(format!("Undefined variable: {}", name)))
614        }
615    }
616}
617
618impl Default for Environment {
619    fn default() -> Self {
620        Self::new()
621    }
622}
623
624/// The Sigil interpreter
625pub struct Interpreter {
626    /// Global environment
627    pub globals: Rc<RefCell<Environment>>,
628    /// Current environment
629    pub environment: Rc<RefCell<Environment>>,
630    /// Type definitions
631    pub types: HashMap<String, TypeDef>,
632    /// Variant constructors: qualified_name -> (enum_name, variant_name, arity)
633    pub variant_constructors: HashMap<String, (String, String, usize)>,
634    /// Structs with #[derive(Default)]
635    pub default_structs: HashMap<String, StructDef>,
636    /// Output buffer (for testing)
637    pub output: Vec<String>,
638    /// Return value from the last return statement (control flow)
639    return_value: Option<Value>,
640    /// Program arguments (overrides env::args when set)
641    pub program_args: Option<Vec<String>>,
642    /// Current module prefix for registering definitions
643    pub current_module: Option<String>,
644    /// Current Self type (when inside an impl block)
645    pub current_self_type: Option<String>,
646    /// Current source directory for resolving relative module paths
647    pub current_source_dir: Option<String>,
648    /// Loaded crates registry (crate_name -> true if loaded)
649    pub loaded_crates: HashSet<String>,
650    /// Crates currently being loaded (for circular dependency detection)
651    pub loading_crates: HashSet<String>,
652    /// Project root directory (where Sigil.toml is located)
653    pub project_root: Option<PathBuf>,
654    /// Workspace members: crate_name -> relative path from project root
655    pub workspace_members: HashMap<String, PathBuf>,
656    /// Types that implement Drop trait - call drop() when they go out of scope
657    pub drop_types: HashSet<String>,
658}
659
660/// Type definition for structs/enums
661#[derive(Clone)]
662pub enum TypeDef {
663    Struct(StructDef),
664    Enum(EnumDef),
665}
666
667impl Interpreter {
668    pub fn new() -> Self {
669        let globals = Rc::new(RefCell::new(Environment::new()));
670        let environment = globals.clone();
671
672        let mut interp = Self {
673            globals: globals.clone(),
674            environment,
675            types: HashMap::new(),
676            variant_constructors: HashMap::new(),
677            default_structs: HashMap::new(),
678            return_value: None,
679            output: Vec::new(),
680            program_args: None,
681            current_module: None,
682            current_self_type: None,
683            current_source_dir: None,
684            loaded_crates: HashSet::new(),
685            loading_crates: HashSet::new(),
686            project_root: None,
687            workspace_members: HashMap::new(),
688            drop_types: HashSet::new(),
689        };
690
691        // Register built-in functions
692        interp.register_builtins();
693
694        interp
695    }
696
697    /// Set program arguments (overrides env::args for the running program)
698    pub fn set_program_args(&mut self, args: Vec<String>) {
699        self.program_args = Some(args);
700    }
701
702    /// Set current module for registering definitions (module name, not file stem)
703    pub fn set_current_module(&mut self, module: Option<String>) {
704        self.current_module = module;
705    }
706
707    /// Set current source directory for resolving relative module paths
708    pub fn set_current_source_dir(&mut self, dir: Option<String>) {
709        self.current_source_dir = dir;
710    }
711
712    /// Get program arguments (uses overridden args if set, otherwise env::args)
713    pub fn get_program_args(&self) -> Vec<String> {
714        self.program_args.clone().unwrap_or_else(|| std::env::args().collect())
715    }
716
717    /// Find and parse Sigil.toml from a source directory, walking up parent directories
718    /// Looks for a workspace Sigil.toml (one with [workspace] section and members)
719    pub fn discover_project(&mut self, source_dir: &str) -> Result<(), RuntimeError> {
720        let mut current = PathBuf::from(source_dir);
721
722        // Walk up to find Sigil.toml with [workspace] section
723        loop {
724            let sigil_toml = current.join("Sigil.toml");
725            if sigil_toml.exists() {
726                if let Ok(result) = self.try_parse_workspace_toml(&sigil_toml) {
727                    if result {
728                        return Ok(());
729                    }
730                    // Not a workspace Sigil.toml, continue searching
731                }
732            }
733
734            // Also check for sigil.toml (lowercase)
735            let sigil_toml_lower = current.join("sigil.toml");
736            if sigil_toml_lower.exists() {
737                if let Ok(result) = self.try_parse_workspace_toml(&sigil_toml_lower) {
738                    if result {
739                        return Ok(());
740                    }
741                    // Not a workspace Sigil.toml, continue searching
742                }
743            }
744
745            if !current.pop() {
746                // No workspace Sigil.toml found
747                crate::sigil_debug!("DEBUG discover_project: no workspace Sigil.toml found from {}", source_dir);
748                return Ok(());
749            }
750        }
751    }
752
753    /// Try to parse a Sigil.toml as a workspace config. Returns Ok(true) if it's a workspace,
754    /// Ok(false) if it's a crate-level config, Err if parsing failed.
755    fn try_parse_workspace_toml(&mut self, path: &PathBuf) -> Result<bool, RuntimeError> {
756        let content = std::fs::read_to_string(path)
757            .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
758
759        let toml_value: toml::Value = content.parse()
760            .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
761
762        // Check if this has a [workspace] section with members
763        if let Some(workspace) = toml_value.get("workspace") {
764            if workspace.get("members").and_then(|m| m.as_array()).is_some() {
765                // This is a workspace Sigil.toml
766                return self.parse_sigil_toml(path).map(|_| true);
767            }
768        }
769
770        // Not a workspace config
771        crate::sigil_debug!("DEBUG try_parse_workspace_toml: {:?} is not a workspace config", path);
772        Ok(false)
773    }
774
775    /// Parse a Sigil.toml file and populate workspace_members
776    fn parse_sigil_toml(&mut self, path: &PathBuf) -> Result<(), RuntimeError> {
777        let content = std::fs::read_to_string(path)
778            .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
779
780        let toml_value: toml::Value = content.parse()
781            .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
782
783        self.project_root = path.parent().map(|p| p.to_path_buf());
784
785        // Parse [workspace] members
786        if let Some(workspace) = toml_value.get("workspace") {
787            if let Some(members) = workspace.get("members").and_then(|m| m.as_array()) {
788                for member in members {
789                    if let Some(member_path) = member.as_str() {
790                        // Extract crate name from path (e.g., "crates/samael-analysis" -> "samael_analysis")
791                        let crate_name = std::path::Path::new(member_path)
792                            .file_name()
793                            .and_then(|n| n.to_str())
794                            .map(|n| n.replace("-", "_"))
795                            .unwrap_or_default();
796
797                        if !crate_name.is_empty() {
798                            crate::sigil_debug!("DEBUG parse_sigil_toml: registered workspace member: {} -> {}",
799                                &crate_name, member_path);
800                            self.workspace_members.insert(crate_name, PathBuf::from(member_path));
801                        }
802                    }
803                }
804            }
805        }
806
807        crate::sigil_debug!("DEBUG parse_sigil_toml: loaded {} workspace members from {:?}",
808            self.workspace_members.len(), path);
809
810        Ok(())
811    }
812
813    /// Load an external crate by name
814    pub fn load_crate(&mut self, crate_name: &str) -> Result<bool, RuntimeError> {
815        // Check if already loaded
816        if self.loaded_crates.contains(crate_name) {
817            return Ok(true);
818        }
819
820        // Check for circular dependency
821        if self.loading_crates.contains(crate_name) {
822            return Err(RuntimeError::new(format!(
823                "Circular dependency detected: crate '{}' is already being loaded", crate_name
824            )));
825        }
826
827        // Find crate path in workspace members
828        let crate_path = match self.workspace_members.get(crate_name) {
829            Some(p) => p.clone(),
830            None => {
831                crate::sigil_debug!("DEBUG load_crate: crate '{}' not found in workspace members", crate_name);
832                return Ok(false);
833            }
834        };
835
836        let project_root = match &self.project_root {
837            Some(r) => r.clone(),
838            None => {
839                crate::sigil_debug!("DEBUG load_crate: no project root set");
840                return Ok(false);
841            }
842        };
843
844        // Build path to lib.sigil
845        let lib_path = project_root.join(&crate_path).join("src").join("lib.sigil");
846
847        if !lib_path.exists() {
848            crate::sigil_debug!("DEBUG load_crate: lib.sigil not found at {:?}", lib_path);
849            return Ok(false);
850        }
851
852        // Mark as loading (for circular dependency detection)
853        self.loading_crates.insert(crate_name.to_string());
854
855        crate::sigil_debug!("DEBUG load_crate: loading crate '{}' from {:?}", crate_name, lib_path);
856
857        // Read and parse the lib.sigil file
858        let source = std::fs::read_to_string(&lib_path)
859            .map_err(|e| RuntimeError::new(format!("Failed to read {:?}: {}", lib_path, e)))?;
860
861        // Save current state
862        let prev_module = self.current_module.clone();
863        let prev_source_dir = self.current_source_dir.clone();
864
865        // Set module context to crate name
866        self.current_module = Some(crate_name.to_string());
867        self.current_source_dir = lib_path.parent().map(|p| p.to_string_lossy().to_string());
868
869        // Parse the source
870        let mut parser = crate::Parser::new(&source);
871
872        match parser.parse_file() {
873            Ok(parsed_file) => {
874                // Execute all items to register types and functions
875                for item in &parsed_file.items {
876                    if let Err(e) = self.execute_item(&item.node) {
877                        crate::sigil_warn!("Warning: error loading crate '{}': {}", crate_name, e);
878                    }
879                }
880            }
881            Err(e) => {
882                crate::sigil_warn!("Warning: failed to parse crate '{}': {:?}", crate_name, e);
883            }
884        }
885
886        // Restore previous state
887        self.current_module = prev_module;
888        self.current_source_dir = prev_source_dir;
889
890        // Mark as loaded and no longer loading
891        self.loading_crates.remove(crate_name);
892        self.loaded_crates.insert(crate_name.to_string());
893
894        crate::sigil_debug!("DEBUG load_crate: successfully loaded crate '{}'", crate_name);
895
896        Ok(true)
897    }
898
899    fn register_builtins(&mut self) {
900        // PhantomData - zero-sized type marker
901        self.globals.borrow_mut().define("PhantomData".to_string(), Value::Null);
902
903        // Print function
904        self.define_builtin("print", None, |interp, args| {
905            let output: Vec<String> = args.iter().map(|v| format!("{}", v)).collect();
906            let line = output.join(" ");
907            println!("{}", line);
908            interp.output.push(line);
909            Ok(Value::Null)
910        });
911
912        // Type checking
913        self.define_builtin("type_of", Some(1), |_, args| {
914            let type_name = match &args[0] {
915                Value::Null => "null",
916                Value::Bool(_) => "bool",
917                Value::Int(_) => "i64",
918                Value::Float(_) => "f64",
919                Value::String(_) => "str",
920                Value::Char(_) => "char",
921                Value::Array(_) => "array",
922                Value::Tuple(_) => "tuple",
923                Value::Struct { name, .. } => name,
924                Value::Variant { enum_name, .. } => enum_name,
925                Value::Function(_) => "fn",
926                Value::BuiltIn(_) => "builtin",
927                Value::Ref(_) => "ref",
928                Value::Infinity => "infinity",
929                Value::Empty => "empty",
930                Value::Evidential { .. } => "evidential",
931                Value::Affective { .. } => "affective",
932                Value::Map(_) => "map",
933                Value::Set(_) => "set",
934                Value::Channel(_) => "channel",
935                Value::ThreadHandle(_) => "thread",
936                Value::Actor(_) => "actor",
937                Value::Future(_) => "future",
938                Value::VariantConstructor { .. } => "variant_constructor",
939                Value::DefaultConstructor { .. } => "default_constructor",
940                Value::Range { .. } => "range",
941            };
942            Ok(Value::String(Rc::new(type_name.to_string())))
943        });
944
945        // Array operations
946        self.define_builtin("len", Some(1), |_, args| match &args[0] {
947            Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
948            Value::String(s) => Ok(Value::Int(s.len() as i64)),
949            Value::Tuple(t) => Ok(Value::Int(t.len() as i64)),
950            _ => Err(RuntimeError::new("len() requires array, string, or tuple")),
951        });
952
953        self.define_builtin("push", Some(2), |_, args| match &args[0] {
954            Value::Array(arr) => {
955                arr.borrow_mut().push(args[1].clone());
956                Ok(Value::Null)
957            }
958            _ => Err(RuntimeError::new("push() requires array")),
959        });
960
961        self.define_builtin("pop", Some(1), |_, args| match &args[0] {
962            Value::Array(arr) => arr
963                .borrow_mut()
964                .pop()
965                .ok_or_else(|| RuntimeError::new("pop() on empty array")),
966            _ => Err(RuntimeError::new("pop() requires array")),
967        });
968
969        // Math functions
970        self.define_builtin("abs", Some(1), |_, args| match &args[0] {
971            Value::Int(n) => Ok(Value::Int(n.abs())),
972            Value::Float(n) => Ok(Value::Float(n.abs())),
973            _ => Err(RuntimeError::new("abs() requires number")),
974        });
975
976        self.define_builtin("sqrt", Some(1), |_, args| match &args[0] {
977            Value::Int(n) => Ok(Value::Float((*n as f64).sqrt())),
978            Value::Float(n) => Ok(Value::Float(n.sqrt())),
979            _ => Err(RuntimeError::new("sqrt() requires number")),
980        });
981
982        self.define_builtin("sin", Some(1), |_, args| match &args[0] {
983            Value::Int(n) => Ok(Value::Float((*n as f64).sin())),
984            Value::Float(n) => Ok(Value::Float(n.sin())),
985            _ => Err(RuntimeError::new("sin() requires number")),
986        });
987
988        self.define_builtin("cos", Some(1), |_, args| match &args[0] {
989            Value::Int(n) => Ok(Value::Float((*n as f64).cos())),
990            Value::Float(n) => Ok(Value::Float(n.cos())),
991            _ => Err(RuntimeError::new("cos() requires number")),
992        });
993
994        // Evidence operations
995        self.define_builtin("known", Some(1), |_, args| {
996            Ok(Value::Evidential {
997                value: Box::new(args[0].clone()),
998                evidence: Evidence::Known,
999            })
1000        });
1001
1002        self.define_builtin("uncertain", Some(1), |_, args| {
1003            Ok(Value::Evidential {
1004                value: Box::new(args[0].clone()),
1005                evidence: Evidence::Uncertain,
1006            })
1007        });
1008
1009        self.define_builtin("reported", Some(1), |_, args| {
1010            Ok(Value::Evidential {
1011                value: Box::new(args[0].clone()),
1012                evidence: Evidence::Reported,
1013            })
1014        });
1015
1016        // Box::new - just return the value (Sigil is GC'd)
1017        self.globals.borrow_mut().define(
1018            "Box·new".to_string(),
1019            Value::BuiltIn(Rc::new(BuiltInFn {
1020                name: "Box·new".to_string(),
1021                arity: Some(1),
1022                func: |_, args| Ok(args[0].clone()),
1023            })),
1024        );
1025
1026        // Map::new - create empty map
1027        self.globals.borrow_mut().define(
1028            "Map·new".to_string(),
1029            Value::BuiltIn(Rc::new(BuiltInFn {
1030                name: "Map·new".to_string(),
1031                arity: Some(0),
1032                func: |_, _| Ok(Value::Map(Rc::new(RefCell::new(HashMap::new())))),
1033            })),
1034        );
1035
1036        // Range function
1037        self.define_builtin("range", Some(2), |_, args| {
1038            let start = match &args[0] {
1039                Value::Int(n) => *n,
1040                _ => return Err(RuntimeError::new("range() requires integers")),
1041            };
1042            let end = match &args[1] {
1043                Value::Int(n) => *n,
1044                _ => return Err(RuntimeError::new("range() requires integers")),
1045            };
1046            let values: Vec<Value> = (start..end).map(Value::Int).collect();
1047            Ok(Value::Array(Rc::new(RefCell::new(values))))
1048        });
1049
1050        // ExitCode enum for process exit codes (like Rust's std::process::ExitCode)
1051        self.globals.borrow_mut().define(
1052            "ExitCode·SUCCESS".to_string(),
1053            Value::Variant {
1054                enum_name: "ExitCode".to_string(),
1055                variant_name: "SUCCESS".to_string(),
1056                fields: Some(Rc::new(vec![Value::Int(0)])),
1057            },
1058        );
1059        self.globals.borrow_mut().define(
1060            "ExitCode·FAILURE".to_string(),
1061            Value::Variant {
1062                enum_name: "ExitCode".to_string(),
1063                variant_name: "FAILURE".to_string(),
1064                fields: Some(Rc::new(vec![Value::Int(1)])),
1065            },
1066        );
1067
1068        // PathBuf::from - create a PathBuf from a string path
1069        self.define_builtin("PathBuf·from", Some(1), |_, args| {
1070            // Unwrap Ref types to get the actual value
1071            let arg = match &args[0] {
1072                Value::Ref(r) => r.borrow().clone(),
1073                other => other.clone(),
1074            };
1075            let path = match &arg {
1076                Value::String(s2) => s2.as_str().to_string(),
1077                _ => return Err(RuntimeError::new("PathBuf::from expects a string")),
1078            };
1079            // Represent PathBuf as a struct with a path field
1080            let mut fields = HashMap::new();
1081            fields.insert("path".to_string(), Value::String(Rc::new(path)));
1082            Ok(Value::Struct {
1083                name: "PathBuf".to_string(),
1084                fields: Rc::new(RefCell::new(fields)),
1085            })
1086        });
1087
1088        // Path::new - create a Path from a string (similar to PathBuf for our purposes)
1089        self.define_builtin("Path·new", Some(1), |_, args| {
1090            // Unwrap Ref types to get the actual value
1091            let arg = match &args[0] {
1092                Value::Ref(r) => r.borrow().clone(),
1093                other => other.clone(),
1094            };
1095            let path = match &arg {
1096                Value::String(s2) => s2.as_str().to_string(),
1097                _ => return Err(RuntimeError::new("Path::new expects a string")),
1098            };
1099            let mut fields = HashMap::new();
1100            fields.insert("path".to_string(), Value::String(Rc::new(path)));
1101            Ok(Value::Struct {
1102                name: "Path".to_string(),
1103                fields: Rc::new(RefCell::new(fields)),
1104            })
1105        });
1106
1107        // std::fs::read_to_string - read file contents as a string
1108        self.define_builtin("std·fs·read_to_string", Some(1), |interp, args| {
1109            // Recursively unwrap Ref types to get the actual value
1110            fn unwrap_refs(v: &Value) -> Value {
1111                match v {
1112                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1113                    other => other.clone(),
1114                }
1115            }
1116            let arg = unwrap_refs(&args[0]);
1117            crate::sigil_debug!("DEBUG read_to_string: arg = {:?}", arg);
1118            // Also dump the environment to see what 'path' is bound to
1119            crate::sigil_debug!("DEBUG read_to_string: env has path = {:?}", interp.environment.borrow().get("path"));
1120            let path = match &arg {
1121                Value::String(s) => s.to_string(),
1122                // Handle PathBuf or Path structs
1123                Value::Struct { name, fields, .. } => {
1124                    crate::sigil_debug!("DEBUG read_to_string: struct name = {}", name);
1125                    fields.borrow().get("path")
1126                        .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1127                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1128                }
1129                // Handle Option::Some(String)
1130                Value::Variant { enum_name, variant_name, fields } if enum_name == "Option" && variant_name == "Some" => {
1131                    if let Some(fields) = fields {
1132                        if let Some(Value::String(s)) = fields.first() {
1133                            s.to_string()
1134                        } else {
1135                            return Err(RuntimeError::new("read_to_string: Option::Some does not contain a string"));
1136                        }
1137                    } else {
1138                        return Err(RuntimeError::new("read_to_string: Option::Some has no fields"));
1139                    }
1140                }
1141                _ => return Err(RuntimeError::new(&format!("read_to_string expects a path string or PathBuf, got {:?}", arg))),
1142            };
1143            match std::fs::read_to_string(&path) {
1144                Ok(content) => Ok(Value::Variant {
1145                    enum_name: "Result".to_string(),
1146                    variant_name: "Ok".to_string(),
1147                    fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1148                }),
1149                Err(e) => Ok(Value::Variant {
1150                    enum_name: "Result".to_string(),
1151                    variant_name: "Err".to_string(),
1152                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1153                }),
1154            }
1155        });
1156
1157        // fs::read_to_string - alias without std prefix
1158        self.define_builtin("fs·read_to_string", Some(1), |_, args| {
1159            let arg = match &args[0] {
1160                Value::Ref(r) => r.borrow().clone(),
1161                other => other.clone(),
1162            };
1163            let path = match &arg {
1164                Value::String(s) => s.to_string(),
1165                Value::Struct { fields, .. } => {
1166                    fields.borrow().get("path")
1167                        .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1168                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1169                }
1170                _ => return Err(RuntimeError::new("read_to_string expects a path string or PathBuf")),
1171            };
1172            match std::fs::read_to_string(&path) {
1173                Ok(content) => Ok(Value::Variant {
1174                    enum_name: "Result".to_string(),
1175                    variant_name: "Ok".to_string(),
1176                    fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1177                }),
1178                Err(e) => Ok(Value::Variant {
1179                    enum_name: "Result".to_string(),
1180                    variant_name: "Err".to_string(),
1181                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1182                }),
1183            }
1184        });
1185
1186        // std::fs::read_dir - read directory entries
1187        self.define_builtin("std·fs·read_dir", Some(1), |_, args| {
1188            fn unwrap_refs(v: &Value) -> Value {
1189                match v {
1190                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1191                    other => other.clone(),
1192                }
1193            }
1194            let arg = unwrap_refs(&args[0]);
1195            let path = match &arg {
1196                Value::String(s) => s.to_string(),
1197                Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => {
1198                    fields.borrow().get("path")
1199                        .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1200                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1201                }
1202                _ => return Err(RuntimeError::new(&format!("read_dir expects a path, got {:?}", arg))),
1203            };
1204            match std::fs::read_dir(&path) {
1205                Ok(entries) => {
1206                    // Collect entries into a Vec of DirEntry structs wrapped in Result::Ok
1207                    let entry_values: Vec<Value> = entries
1208                        .filter_map(|e| e.ok())
1209                        .map(|e| {
1210                            let entry_path = e.path().to_string_lossy().to_string();
1211                            let mut fields = HashMap::new();
1212                            fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
1213                            // Each entry is wrapped in Result::Ok
1214                            Value::Variant {
1215                                enum_name: "Result".to_string(),
1216                                variant_name: "Ok".to_string(),
1217                                fields: Some(Rc::new(vec![Value::Struct {
1218                                    name: "DirEntry".to_string(),
1219                                    fields: Rc::new(RefCell::new(fields)),
1220                                }])),
1221                            }
1222                        })
1223                        .collect();
1224                    // The overall result is Ok(iterator/array)
1225                    Ok(Value::Variant {
1226                        enum_name: "Result".to_string(),
1227                        variant_name: "Ok".to_string(),
1228                        fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(entry_values)))])),
1229                    })
1230                }
1231                Err(e) => Ok(Value::Variant {
1232                    enum_name: "Result".to_string(),
1233                    variant_name: "Err".to_string(),
1234                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1235                }),
1236            }
1237        });
1238
1239        // fs::read_dir - alias without std prefix
1240        self.define_builtin("fs·read_dir", Some(1), |_, args| {
1241            fn unwrap_refs(v: &Value) -> Value {
1242                match v {
1243                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1244                    other => other.clone(),
1245                }
1246            }
1247            let arg = unwrap_refs(&args[0]);
1248            let path = match &arg {
1249                Value::String(s) => s.to_string(),
1250                Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => {
1251                    fields.borrow().get("path")
1252                        .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1253                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1254                }
1255                _ => return Err(RuntimeError::new(&format!("read_dir expects a path, got {:?}", arg))),
1256            };
1257            match std::fs::read_dir(&path) {
1258                Ok(entries) => {
1259                    let entry_values: Vec<Value> = entries
1260                        .filter_map(|e| e.ok())
1261                        .map(|e| {
1262                            let entry_path = e.path().to_string_lossy().to_string();
1263                            let mut fields = HashMap::new();
1264                            fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
1265                            Value::Variant {
1266                                enum_name: "Result".to_string(),
1267                                variant_name: "Ok".to_string(),
1268                                fields: Some(Rc::new(vec![Value::Struct {
1269                                    name: "DirEntry".to_string(),
1270                                    fields: Rc::new(RefCell::new(fields)),
1271                                }])),
1272                            }
1273                        })
1274                        .collect();
1275                    Ok(Value::Variant {
1276                        enum_name: "Result".to_string(),
1277                        variant_name: "Ok".to_string(),
1278                        fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(entry_values)))])),
1279                    })
1280                }
1281                Err(e) => Ok(Value::Variant {
1282                    enum_name: "Result".to_string(),
1283                    variant_name: "Err".to_string(),
1284                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1285                }),
1286            }
1287        });
1288
1289        // std::env::var - get environment variable
1290        self.define_builtin("std·env·var", Some(1), |_, args| {
1291            fn unwrap_refs(v: &Value) -> Value {
1292                match v {
1293                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1294                    other => other.clone(),
1295                }
1296            }
1297            let arg = unwrap_refs(&args[0]);
1298            let var_name = match &arg {
1299                Value::String(s) => s.to_string(),
1300                _ => return Err(RuntimeError::new("env::var expects a string")),
1301            };
1302            match std::env::var(&var_name) {
1303                Ok(value) => Ok(Value::Variant {
1304                    enum_name: "Result".to_string(),
1305                    variant_name: "Ok".to_string(),
1306                    fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
1307                }),
1308                Err(_) => Ok(Value::Variant {
1309                    enum_name: "Result".to_string(),
1310                    variant_name: "Err".to_string(),
1311                    fields: Some(Rc::new(vec![Value::String(Rc::new("Environment variable not found".to_string()))])),
1312                }),
1313            }
1314        });
1315
1316        // env::var - alias without std prefix
1317        self.define_builtin("env·var", Some(1), |_, args| {
1318            fn unwrap_refs(v: &Value) -> Value {
1319                match v {
1320                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1321                    other => other.clone(),
1322                }
1323            }
1324            let arg = unwrap_refs(&args[0]);
1325            let var_name = match &arg {
1326                Value::String(s) => s.to_string(),
1327                _ => return Err(RuntimeError::new("env::var expects a string")),
1328            };
1329            match std::env::var(&var_name) {
1330                Ok(value) => Ok(Value::Variant {
1331                    enum_name: "Result".to_string(),
1332                    variant_name: "Ok".to_string(),
1333                    fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
1334                }),
1335                Err(_) => Ok(Value::Variant {
1336                    enum_name: "Result".to_string(),
1337                    variant_name: "Err".to_string(),
1338                    fields: Some(Rc::new(vec![Value::String(Rc::new("Environment variable not found".to_string()))])),
1339                }),
1340            }
1341        });
1342
1343        // std::env::args - get command line arguments
1344        // This is a special function that returns an iterator/array of strings
1345        self.define_builtin("std·env·args", Some(0), |interp, _| {
1346            let args = interp.get_program_args();
1347            let arg_values: Vec<Value> = args.iter()
1348                .map(|s| Value::String(Rc::new(s.clone())))
1349                .collect();
1350            Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
1351        });
1352
1353        // env::args - alias without std prefix
1354        self.define_builtin("env·args", Some(0), |interp, _| {
1355            let args = interp.get_program_args();
1356            let arg_values: Vec<Value> = args.iter()
1357                .map(|s| Value::String(Rc::new(s.clone())))
1358                .collect();
1359            Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
1360        });
1361
1362        // ============================================================
1363        // Filesystem built-ins for scanner (underscore naming)
1364        // ============================================================
1365
1366        // fs_read - read entire file as string
1367        self.define_builtin("fs_read", Some(1), |_, args| {
1368            let path = match &args[0] {
1369                Value::String(s) => s.to_string(),
1370                _ => return Err(RuntimeError::new("fs_read requires a string path")),
1371            };
1372            match std::fs::read_to_string(&path) {
1373                Ok(content) => Ok(Value::String(Rc::new(content))),
1374                Err(e) => {
1375                    crate::sigil_debug!("DEBUG fs_read error for '{}': {}", path, e);
1376                    Ok(Value::Null)
1377                }
1378            }
1379        });
1380
1381        // fs_list - list directory contents as array of strings
1382        self.define_builtin("fs_list", Some(1), |_, args| {
1383            let path = match &args[0] {
1384                Value::String(s) => s.to_string(),
1385                _ => return Err(RuntimeError::new("fs_list requires a string path")),
1386            };
1387            match std::fs::read_dir(&path) {
1388                Ok(entries) => {
1389                    let files: Vec<Value> = entries
1390                        .filter_map(|e| e.ok())
1391                        .map(|e| Value::String(Rc::new(e.file_name().to_string_lossy().to_string())))
1392                        .collect();
1393                    Ok(Value::Array(Rc::new(RefCell::new(files))))
1394                }
1395                Err(e) => {
1396                    crate::sigil_debug!("DEBUG fs_list error for '{}': {}", path, e);
1397                    Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))))
1398                }
1399            }
1400        });
1401
1402        // fs_is_dir - check if path is a directory
1403        self.define_builtin("fs_is_dir", Some(1), |_, args| {
1404            let path = match &args[0] {
1405                Value::String(s) => s.to_string(),
1406                _ => return Err(RuntimeError::new("fs_is_dir requires a string path")),
1407            };
1408            Ok(Value::Bool(std::path::Path::new(&path).is_dir()))
1409        });
1410
1411        // fs_is_file - check if path is a file
1412        self.define_builtin("fs_is_file", Some(1), |_, args| {
1413            let path = match &args[0] {
1414                Value::String(s) => s.to_string(),
1415                _ => return Err(RuntimeError::new("fs_is_file requires a string path")),
1416            };
1417            Ok(Value::Bool(std::path::Path::new(&path).is_file()))
1418        });
1419
1420        // fs_exists - check if path exists
1421        self.define_builtin("fs_exists", Some(1), |_, args| {
1422            let path = match &args[0] {
1423                Value::String(s) => s.to_string(),
1424                _ => return Err(RuntimeError::new("fs_exists requires a string path")),
1425            };
1426            Ok(Value::Bool(std::path::Path::new(&path).exists()))
1427        });
1428
1429        // path_extension - get file extension
1430        self.define_builtin("path_extension", Some(1), |_, args| {
1431            let path = match &args[0] {
1432                Value::String(s) => s.to_string(),
1433                _ => return Err(RuntimeError::new("path_extension requires a string path")),
1434            };
1435            let ext = std::path::Path::new(&path)
1436                .extension()
1437                .and_then(|e| e.to_str())
1438                .map(|s| s.to_string());
1439            match ext {
1440                Some(e) => Ok(Value::String(Rc::new(e))),
1441                None => Ok(Value::Null),
1442            }
1443        });
1444
1445        // path_join - join path components
1446        self.define_builtin("path_join", Some(2), |_, args| {
1447            let base = match &args[0] {
1448                Value::String(s) => s.to_string(),
1449                _ => return Err(RuntimeError::new("path_join requires string paths")),
1450            };
1451            let part = match &args[1] {
1452                Value::String(s) => s.to_string(),
1453                _ => return Err(RuntimeError::new("path_join requires string paths")),
1454            };
1455            let joined = std::path::Path::new(&base).join(&part);
1456            Ok(Value::String(Rc::new(joined.to_string_lossy().to_string())))
1457        });
1458
1459        // path_parent - get parent directory
1460        self.define_builtin("path_parent", Some(1), |_, args| {
1461            let path = match &args[0] {
1462                Value::String(s) => s.to_string(),
1463                _ => return Err(RuntimeError::new("path_parent requires a string path")),
1464            };
1465            match std::path::Path::new(&path).parent() {
1466                Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
1467                None => Ok(Value::Null),
1468            }
1469        });
1470
1471        // path_file_name - get file name without directory
1472        self.define_builtin("path_file_name", Some(1), |_, args| {
1473            let path = match &args[0] {
1474                Value::String(s) => s.to_string(),
1475                _ => return Err(RuntimeError::new("path_file_name requires a string path")),
1476            };
1477            match std::path::Path::new(&path).file_name() {
1478                Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
1479                None => Ok(Value::Null),
1480            }
1481        });
1482
1483        // ============================================================
1484        // Tree-sitter parsing built-ins
1485        // ============================================================
1486
1487        // TreeSitterParser::new - create a tree-sitter parser for a language
1488        self.define_builtin("TreeSitterParser·new", Some(1), |_, args| {
1489            use crate::tree_sitter_support::{TSLanguage, TSParser};
1490
1491            // Get the language from the argument
1492            let lang_str = match &args[0] {
1493                Value::String(s) => s.to_string(),
1494                Value::Variant { enum_name, variant_name, .. } => {
1495                    // Handle Language::Rust style enums
1496                    format!("{}::{}", enum_name, variant_name)
1497                }
1498                other => format!("{:?}", other),
1499            };
1500
1501            // Try to create the parser
1502            let language = match TSLanguage::from_str(&lang_str) {
1503                Some(lang) => lang,
1504                None => {
1505                    return Ok(Value::Variant {
1506                        enum_name: "Result".to_string(),
1507                        variant_name: "Err".to_string(),
1508                        fields: Some(Rc::new(vec![Value::Struct {
1509                            name: "ParseError".to_string(),
1510                            fields: Rc::new(RefCell::new({
1511                                let mut f = HashMap::new();
1512                                f.insert("kind".to_string(), Value::String(Rc::new("ParserNotFound".to_string())));
1513                                f.insert("message".to_string(), Value::String(Rc::new(format!("Unsupported language: {}", lang_str))));
1514                                f
1515                            })),
1516                        }])),
1517                    });
1518                }
1519            };
1520
1521            // Create the parser and store the language
1522            match TSParser::new(language) {
1523                Ok(_) => {
1524                    // Return a TreeSitterParser struct
1525                    let mut fields = HashMap::new();
1526                    fields.insert("language".to_string(), Value::String(Rc::new(lang_str)));
1527                    fields.insert("_ts_language".to_string(), Value::String(Rc::new(format!("{:?}", language))));
1528
1529                    Ok(Value::Variant {
1530                        enum_name: "Result".to_string(),
1531                        variant_name: "Ok".to_string(),
1532                        fields: Some(Rc::new(vec![Value::Struct {
1533                            name: "TreeSitterParser".to_string(),
1534                            fields: Rc::new(RefCell::new(fields)),
1535                        }])),
1536                    })
1537                }
1538                Err(e) => {
1539                    Ok(Value::Variant {
1540                        enum_name: "Result".to_string(),
1541                        variant_name: "Err".to_string(),
1542                        fields: Some(Rc::new(vec![Value::Struct {
1543                            name: "ParseError".to_string(),
1544                            fields: Rc::new(RefCell::new({
1545                                let mut f = HashMap::new();
1546                                f.insert("kind".to_string(), Value::String(Rc::new("ParserNotFound".to_string())));
1547                                f.insert("message".to_string(), Value::String(Rc::new(e)));
1548                                f
1549                            })),
1550                        }])),
1551                    })
1552                }
1553            }
1554        });
1555
1556        // tree_sitter_parse - parse source code with tree-sitter
1557        self.define_builtin("tree_sitter_parse", Some(2), |_, args| {
1558            use crate::tree_sitter_support::{parse_source, node_to_value};
1559
1560            // First arg is the language string, second is the source code
1561            let lang_str = match &args[0] {
1562                Value::String(s) => s.to_string(),
1563                Value::Variant { enum_name, variant_name, .. } => {
1564                    format!("{}::{}", enum_name, variant_name)
1565                }
1566                other => format!("{:?}", other),
1567            };
1568
1569            let source = match &args[1] {
1570                Value::String(s) => s.to_string(),
1571                _ => return Err(RuntimeError::new("tree_sitter_parse expects source code string as second argument")),
1572            };
1573
1574            // Parse the source
1575            match parse_source(&lang_str, &source) {
1576                Ok(tree) => {
1577                    // Convert to SyntaxNode value
1578                    let root = tree.root_node();
1579                    let root_fields = node_to_value(&root);
1580
1581                    // Create TSTree struct
1582                    let mut tree_fields = HashMap::new();
1583                    tree_fields.insert("root".to_string(), Value::Struct {
1584                        name: "SyntaxNode".to_string(),
1585                        fields: Rc::new(RefCell::new(root_fields)),
1586                    });
1587                    tree_fields.insert("source".to_string(), Value::String(Rc::new(source)));
1588
1589                    Ok(Value::Variant {
1590                        enum_name: "Result".to_string(),
1591                        variant_name: "Ok".to_string(),
1592                        fields: Some(Rc::new(vec![Value::Struct {
1593                            name: "TSTree".to_string(),
1594                            fields: Rc::new(RefCell::new(tree_fields)),
1595                        }])),
1596                    })
1597                }
1598                Err(e) => {
1599                    Ok(Value::Variant {
1600                        enum_name: "Result".to_string(),
1601                        variant_name: "Err".to_string(),
1602                        fields: Some(Rc::new(vec![Value::Struct {
1603                            name: "ParseError".to_string(),
1604                            fields: Rc::new(RefCell::new({
1605                                let mut f = HashMap::new();
1606                                f.insert("kind".to_string(), Value::String(Rc::new("SyntaxError".to_string())));
1607                                f.insert("message".to_string(), Value::String(Rc::new(e)));
1608                                f
1609                            })),
1610                        }])),
1611                    })
1612                }
1613            }
1614        });
1615
1616        // tree_sitter_supported_languages - get list of supported languages
1617        self.define_builtin("tree_sitter_supported_languages", Some(0), |_, _| {
1618            use crate::tree_sitter_support::supported_languages;
1619
1620            let languages: Vec<Value> = supported_languages()
1621                .iter()
1622                .map(|s| Value::String(Rc::new(s.to_string())))
1623                .collect();
1624
1625            Ok(Value::Array(Rc::new(RefCell::new(languages))))
1626        });
1627
1628        // tree_sitter_node_text - extract text from a syntax node using the source
1629        self.define_builtin("tree_sitter_node_text", Some(2), |_, args| {
1630            // First arg is the node (with start_byte and end_byte), second is the source
1631            let (start_byte, end_byte) = match &args[0] {
1632                Value::Struct { fields, .. } => {
1633                    let fields = fields.borrow();
1634                    let start = match fields.get("start_byte") {
1635                        Some(Value::Int(n)) => *n as usize,
1636                        _ => return Err(RuntimeError::new("Node missing start_byte field")),
1637                    };
1638                    let end = match fields.get("end_byte") {
1639                        Some(Value::Int(n)) => *n as usize,
1640                        _ => return Err(RuntimeError::new("Node missing end_byte field")),
1641                    };
1642                    (start, end)
1643                }
1644                _ => return Err(RuntimeError::new("tree_sitter_node_text expects a SyntaxNode struct")),
1645            };
1646
1647            let source = match &args[1] {
1648                Value::String(s) => s.to_string(),
1649                _ => return Err(RuntimeError::new("tree_sitter_node_text expects source string as second argument")),
1650            };
1651
1652            if end_byte <= source.len() && start_byte <= end_byte {
1653                Ok(Value::String(Rc::new(source[start_byte..end_byte].to_string())))
1654            } else {
1655                Err(RuntimeError::new("Byte range out of bounds"))
1656            }
1657        });
1658
1659        // Rc::new(value) - Reference counted smart pointer (simplified)
1660        let rc_new = Value::BuiltIn(Rc::new(BuiltInFn {
1661            name: "Rc·new".to_string(),
1662            arity: Some(1),
1663            func: |_, args| {
1664                let mut fields = HashMap::new();
1665                fields.insert("_value".to_string(), args[0].clone());
1666                Ok(Value::Struct {
1667                    name: "Rc".to_string(),
1668                    fields: std::rc::Rc::new(RefCell::new(fields)),
1669                })
1670            },
1671        }));
1672        self.globals.borrow_mut().define("Rc·new".to_string(), rc_new);
1673
1674        // Cell::new(value) - Interior mutability
1675        let cell_new = Value::BuiltIn(Rc::new(BuiltInFn {
1676            name: "Cell·new".to_string(),
1677            arity: Some(1),
1678            func: |_, args| {
1679                let mut fields = HashMap::new();
1680                fields.insert("_value".to_string(), args[0].clone());
1681                Ok(Value::Struct {
1682                    name: "Cell".to_string(),
1683                    fields: std::rc::Rc::new(RefCell::new(fields)),
1684                })
1685            },
1686        }));
1687        self.globals.borrow_mut().define("Cell·new".to_string(), cell_new);
1688    }
1689
1690    fn define_builtin(
1691        &mut self,
1692        name: &str,
1693        arity: Option<usize>,
1694        func: fn(&mut Interpreter, Vec<Value>) -> Result<Value, RuntimeError>,
1695    ) {
1696        let builtin = Value::BuiltIn(Rc::new(BuiltInFn {
1697            name: name.to_string(),
1698            arity,
1699            func,
1700        }));
1701        self.globals.borrow_mut().define(name.to_string(), builtin);
1702    }
1703
1704    /// Execute a source file
1705    pub fn execute(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
1706        let mut result = Value::Null;
1707
1708        for item in &file.items {
1709            result = self.execute_item(&item.node)?;
1710        }
1711
1712        // Look for main function and execute it (only if it takes no args)
1713        let main_fn = self.globals.borrow().get("main").and_then(|v| {
1714            if let Value::Function(f) = v {
1715                Some(f.clone())
1716            } else {
1717                None
1718            }
1719        });
1720        if let Some(f) = main_fn {
1721            // Only auto-call main if it takes no arguments
1722            // If main expects args, caller should call it explicitly via call_function_by_name
1723            if f.params.is_empty() {
1724                result = self.call_function(&f, vec![])?;
1725            }
1726        }
1727
1728        Ok(result)
1729    }
1730
1731    /// Execute a file but only register definitions, don't auto-call main.
1732    /// Use this when loading files as part of a multi-file workspace.
1733    pub fn execute_definitions(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
1734        let mut result = Value::Null;
1735
1736        for item in &file.items {
1737            result = self.execute_item(&item.node)?;
1738        }
1739
1740        Ok(result)
1741    }
1742
1743    fn execute_item(&mut self, item: &Item) -> Result<Value, RuntimeError> {
1744        match item {
1745            Item::Function(func) => {
1746                let fn_value = self.create_function(func)?;
1747                let fn_name = func.name.name.clone();
1748
1749                // Register with both simple name and module-qualified name
1750                self.globals.borrow_mut().define(fn_name.clone(), fn_value.clone());
1751
1752                // Also register with module prefix if we're in a module context
1753                if let Some(ref module) = self.current_module {
1754                    let qualified_name = format!("{}·{}", module, fn_name);
1755                    self.globals.borrow_mut().define(qualified_name, fn_value);
1756                }
1757
1758                Ok(Value::Null)
1759            }
1760            Item::Struct(s) => {
1761                // Register with simple name
1762                self.types
1763                    .insert(s.name.name.clone(), TypeDef::Struct(s.clone()));
1764
1765                // Also register with module-qualified name if in a module context
1766                if let Some(ref module) = self.current_module {
1767                    let qualified_name = format!("{}·{}", module, s.name.name);
1768                    self.types.insert(qualified_name, TypeDef::Struct(s.clone()));
1769                }
1770
1771                // For unit structs, register the struct name as a value (zero-sized type)
1772                if matches!(&s.fields, crate::ast::StructFields::Unit) {
1773                    let unit_value = Value::Struct {
1774                        name: s.name.name.clone(),
1775                        fields: Rc::new(RefCell::new(HashMap::new())),
1776                    };
1777                    self.globals.borrow_mut().define(s.name.name.clone(), unit_value.clone());
1778
1779                    // Also register with module-qualified name
1780                    if let Some(ref module) = self.current_module {
1781                        let qualified_name = format!("{}·{}", module, s.name.name);
1782                        self.globals.borrow_mut().define(qualified_name, unit_value);
1783                    }
1784                }
1785
1786                // Check for #[derive(Default)] attribute and store for later lookup
1787                let has_default = s.attrs.derives.iter().any(|d| matches!(d, DeriveTrait::Default));
1788                if has_default {
1789                    self.default_structs.insert(s.name.name.clone(), s.clone());
1790                    if let Some(ref module) = self.current_module {
1791                        let qualified_name = format!("{}·{}", module, s.name.name);
1792                        self.default_structs.insert(qualified_name, s.clone());
1793                    }
1794                }
1795
1796                Ok(Value::Null)
1797            }
1798            Item::Enum(e) => {
1799                // Register with simple name
1800                self.types
1801                    .insert(e.name.name.clone(), TypeDef::Enum(e.clone()));
1802
1803                // Also register with module-qualified name
1804                if let Some(ref module) = self.current_module {
1805                    let qualified_name = format!("{}·{}", module, e.name.name);
1806                    self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
1807                }
1808
1809                // Register variant constructors as EnumName·VariantName
1810                // Store them in a lookup table that the variant_constructor builtin can use
1811                let enum_name = e.name.name.clone();
1812                for variant in &e.variants {
1813                    let variant_name = variant.name.name.clone();
1814                    let qualified_name = format!("{}·{}", enum_name, variant_name);
1815
1816                    let arity = match &variant.fields {
1817                        crate::ast::StructFields::Unit => 0,
1818                        crate::ast::StructFields::Tuple(types) => types.len(),
1819                        crate::ast::StructFields::Named(fields) => fields.len(),
1820                    };
1821
1822                    // Store variant info for later lookup
1823                    self.variant_constructors.insert(qualified_name.clone(), (enum_name.clone(), variant_name.clone(), arity));
1824                }
1825                Ok(Value::Null)
1826            }
1827            Item::Const(c) => {
1828                let value = self.evaluate(&c.value)?;
1829                self.globals.borrow_mut().define(c.name.name.clone(), value);
1830                Ok(Value::Null)
1831            }
1832            Item::Static(s) => {
1833                let value = self.evaluate(&s.value)?;
1834                self.globals.borrow_mut().define(s.name.name.clone(), value);
1835                Ok(Value::Null)
1836            }
1837            Item::ExternBlock(extern_block) => {
1838                // Register extern functions as builtins
1839                for item in &extern_block.items {
1840                    if let ExternItem::Function(func) = item {
1841                        let name = func.name.name.clone();
1842                        // Register emulated FFI functions
1843                        match name.as_str() {
1844                            "sigil_read_file" => {
1845                                self.define_builtin("sigil_read_file", Some(2), |_, args| {
1846                                    // args[0] = path pointer (we'll use string), args[1] = len
1847                                    let path = match &args[0] {
1848                                        Value::String(s) => (**s).clone(),
1849                                        _ => return Err(RuntimeError::new("sigil_read_file expects string path")),
1850                                    };
1851                                    match std::fs::read_to_string(&path) {
1852                                        Ok(content) => {
1853                                            // Store content in a global for sigil_file_len to access
1854                                            Ok(Value::String(Rc::new(content)))
1855                                        }
1856                                        Err(_) => Ok(Value::Null),
1857                                    }
1858                                });
1859                            }
1860                            "sigil_file_len" => {
1861                                self.define_builtin("sigil_file_len", Some(0), |_, _| {
1862                                    // This is a placeholder - in real usage, would track last read
1863                                    Ok(Value::Int(0))
1864                                });
1865                            }
1866                            "sigil_write_file" => {
1867                                self.define_builtin("sigil_write_file", Some(4), |_, args| {
1868                                    let path = match &args[0] {
1869                                        Value::String(s) => (**s).clone(),
1870                                        _ => return Err(RuntimeError::new("sigil_write_file expects string path")),
1871                                    };
1872                                    let content = match &args[2] {
1873                                        Value::String(s) => (**s).clone(),
1874                                        _ => return Err(RuntimeError::new("sigil_write_file expects string content")),
1875                                    };
1876                                    match std::fs::write(&path, &content) {
1877                                        Ok(_) => Ok(Value::Bool(true)),
1878                                        Err(_) => Ok(Value::Bool(false)),
1879                                    }
1880                                });
1881                            }
1882                            "write" => {
1883                                self.define_builtin("write", Some(3), |_, args| {
1884                                    // write(fd, buf, count)
1885                                    let fd = match &args[0] {
1886                                        Value::Int(n) => *n,
1887                                        _ => 1,
1888                                    };
1889                                    let content = match &args[1] {
1890                                        Value::String(s) => (**s).clone(),
1891                                        _ => format!("{}", args[1]),
1892                                    };
1893                                    if fd == 1 {
1894                                        print!("{}", content);
1895                                    } else if fd == 2 {
1896                                        eprint!("{}", content);
1897                                    }
1898                                    Ok(Value::Int(content.len() as i64))
1899                                });
1900                            }
1901                            _ => {
1902                                // Unknown extern function - register a no-op
1903                            }
1904                        }
1905                    }
1906                }
1907                Ok(Value::Null)
1908            }
1909            Item::Impl(impl_block) => {
1910                // Extract type name from self_ty
1911                let type_name = match &impl_block.self_ty {
1912                    TypeExpr::Path(path) => {
1913                        path.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("::")
1914                    }
1915                    _ => return Ok(Value::Null), // Can't handle complex types
1916                };
1917
1918                // Check if this is `impl Drop for X` - register for automatic drop calls
1919                if let Some(trait_path) = &impl_block.trait_ {
1920                    let trait_name = trait_path.segments.iter()
1921                        .map(|s| s.ident.name.as_str())
1922                        .collect::<Vec<_>>()
1923                        .join("::");
1924                    if trait_name == "Drop" {
1925                        self.drop_types.insert(type_name.clone());
1926                    }
1927                }
1928
1929                // Register each method with qualified name TypeName·method
1930                for impl_item in &impl_block.items {
1931                    if let ImplItem::Function(func) = impl_item {
1932                        let fn_value = self.create_function(func)?;
1933                        let qualified_name = format!("{}·{}", type_name, func.name.name);
1934                        // Debug: track Lexer method registration
1935                        if type_name == "Lexer" && func.name.name.contains("keyword") {
1936                            crate::sigil_debug!("DEBUG registering: {}", qualified_name);
1937                        }
1938                        self.globals.borrow_mut().define(qualified_name.clone(), fn_value.clone());
1939
1940                        // Also register with module prefix if in a module context
1941                        if let Some(ref module) = self.current_module {
1942                            let fully_qualified = format!("{}·{}", module, qualified_name);
1943                            self.globals.borrow_mut().define(fully_qualified, fn_value);
1944                        }
1945                    }
1946                }
1947                Ok(Value::Null)
1948            }
1949            Item::Module(module) => {
1950                // Handle module definitions
1951                let module_name = &module.name.name;
1952
1953                if let Some(items) = &module.items {
1954                    // Inline module: mod foo { ... }
1955                    // Register items with qualified names: module_name·item_name
1956                    for item in items {
1957                        match &item.node {
1958                            Item::Const(c) => {
1959                                let value = self.evaluate(&c.value)?;
1960                                let qualified_name = format!("{}·{}", module_name, c.name.name);
1961                                self.globals.borrow_mut().define(qualified_name, value);
1962                            }
1963                            Item::Static(s) => {
1964                                let value = self.evaluate(&s.value)?;
1965                                let qualified_name = format!("{}·{}", module_name, s.name.name);
1966                                self.globals.borrow_mut().define(qualified_name, value);
1967                            }
1968                            Item::Function(func) => {
1969                                let fn_value = self.create_function(func)?;
1970                                let qualified_name = format!("{}·{}", module_name, func.name.name);
1971                                self.globals.borrow_mut().define(qualified_name, fn_value);
1972                            }
1973                            Item::Struct(s) => {
1974                                let qualified_name = format!("{}·{}", module_name, s.name.name);
1975                                self.types.insert(qualified_name, TypeDef::Struct(s.clone()));
1976                            }
1977                            Item::Enum(e) => {
1978                                let qualified_name = format!("{}·{}", module_name, e.name.name);
1979                                self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
1980                            }
1981                            _ => {} // Skip other nested items for now
1982                        }
1983                    }
1984                } else {
1985                    // External module: mod foo; - try to load foo.sigil from same directory
1986                    if let Some(ref source_dir) = self.current_source_dir {
1987                        let module_path = std::path::Path::new(source_dir)
1988                            .join(format!("{}.sigil", module_name));
1989                        
1990                        if module_path.exists() {
1991                            crate::sigil_debug!("DEBUG Loading external module: {}", module_path.display());
1992                            
1993                            match std::fs::read_to_string(&module_path) {
1994                                Ok(source) => {
1995                                    // Parse the module file
1996                                    let mut parser = crate::Parser::new(&source);
1997                                    match parser.parse_file() {
1998                                        Ok(parsed_file) => {
1999                                            // Save current module context
2000                                            let prev_module = self.current_module.clone();
2001                                            
2002                                            // Set module context for registering definitions
2003                                            self.current_module = Some(module_name.clone());
2004                                            
2005                                            // Execute module definitions
2006                                            for item in &parsed_file.items {
2007                                                if let Err(e) = self.execute_item(&item.node) {
2008                                                    crate::sigil_warn!("Warning: error in module {}: {}", module_name, e);
2009                                                }
2010                                            }
2011                                            
2012                                            // Restore previous module context
2013                                            self.current_module = prev_module;
2014                                        }
2015                                        Err(e) => {
2016                                            crate::sigil_warn!("Warning: failed to parse module {}: {:?}", module_name, e);
2017                                        }
2018                                    }
2019                                }
2020                                Err(e) => {
2021                                    crate::sigil_warn!("Warning: failed to read module file {}: {}", module_path.display(), e);
2022                                }
2023                            }
2024                        } else {
2025                            crate::sigil_debug!("DEBUG Module file not found: {} (source_dir={})", module_path.display(), source_dir);
2026                        }
2027                    } else {
2028                        crate::sigil_debug!("DEBUG No source_dir set, cannot load external module: {}", module_name);
2029                    }
2030                }
2031                Ok(Value::Null)
2032            }
2033            Item::Use(use_decl) => {
2034                // Process use declarations to create type/function aliases
2035                self.process_use_tree(&use_decl.tree, &[])?;
2036                Ok(Value::Null)
2037            }
2038            _ => Ok(Value::Null), // Skip other items for now
2039        }
2040    }
2041
2042    /// Process a use tree to create type and function aliases
2043    fn process_use_tree(&mut self, tree: &crate::ast::UseTree, prefix: &[String]) -> Result<(), RuntimeError> {
2044        use crate::ast::UseTree;
2045        match tree {
2046            UseTree::Path { prefix: path_prefix, suffix } => {
2047                // Build path: prefix + this segment
2048                let mut new_prefix = prefix.to_vec();
2049                new_prefix.push(path_prefix.name.clone());
2050                self.process_use_tree(suffix, &new_prefix)
2051            }
2052            UseTree::Name(name) => {
2053                // use foo::bar::Baz -> import Baz from foo·bar·Baz
2054                let mut path = prefix.to_vec();
2055                path.push(name.name.clone());
2056                let qualified = path.join("·");
2057                let simple_name = name.name.clone();
2058
2059                // If the type/function isn't found, try loading the crate first
2060                // The crate name is the first segment of the path
2061                if !prefix.is_empty() {
2062                    let crate_name = &prefix[0];
2063                    if !self.types.contains_key(&qualified)
2064                       && self.globals.borrow().get(&qualified).is_none()
2065                       && !self.loaded_crates.contains(crate_name)
2066                    {
2067                        // Try to load the crate
2068                        if let Err(e) = self.load_crate(crate_name) {
2069                            crate::sigil_debug!("DEBUG process_use_tree: failed to load crate '{}': {}", crate_name, e);
2070                        }
2071                    }
2072                }
2073
2074                // Create alias: simple_name -> qualified
2075                // For types: if foo·bar·Baz exists in types, also register as Baz
2076                if let Some(type_def) = self.types.get(&qualified).cloned() {
2077                    self.types.insert(simple_name.clone(), type_def);
2078                }
2079                // For functions: if foo·bar·Baz exists in globals, also register as Baz
2080                let func = self.globals.borrow().get(&qualified).map(|v| v.clone());
2081                if let Some(val) = func {
2082                    self.globals.borrow_mut().define(simple_name.clone(), val);
2083                }
2084
2085                // Also import impl methods for this type
2086                // e.g., when importing samael_analysis::AnalysisConfig,
2087                // also import samael_analysis·AnalysisConfig·default as AnalysisConfig·default
2088                let method_prefix = format!("{}·", qualified);
2089                let matching_methods: Vec<(String, Value)> = {
2090                    let globals = self.globals.borrow();
2091                    globals.values.iter()
2092                        .filter(|(k, _)| k.starts_with(&method_prefix))
2093                        .map(|(k, v)| {
2094                            // samael_analysis·AnalysisConfig·default -> AnalysisConfig·default
2095                            let method_suffix = k.strip_prefix(&method_prefix).unwrap();
2096                            let new_name = format!("{}·{}", simple_name, method_suffix);
2097                            (new_name, v.clone())
2098                        })
2099                        .collect()
2100                };
2101                for (name, val) in matching_methods {
2102                    self.globals.borrow_mut().define(name, val);
2103                }
2104                Ok(())
2105            }
2106            UseTree::Rename { name, alias } => {
2107                // use foo::bar::Baz as Qux
2108                let mut path = prefix.to_vec();
2109                path.push(name.name.clone());
2110                let qualified = path.join("·");
2111                let alias_name = alias.name.clone();
2112
2113                if let Some(type_def) = self.types.get(&qualified).cloned() {
2114                    self.types.insert(alias_name.clone(), type_def);
2115                }
2116                let func = self.globals.borrow().get(&qualified).map(|v| v.clone());
2117                if let Some(val) = func {
2118                    self.globals.borrow_mut().define(alias_name, val);
2119                }
2120                Ok(())
2121            }
2122            UseTree::Glob => {
2123                // use foo::bar::* - import all from foo·bar
2124                let path_prefix = prefix.join("·");
2125                // Find all types starting with this prefix
2126                let matching_types: Vec<(String, TypeDef)> = self.types.iter()
2127                    .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
2128                    .map(|(k, v)| {
2129                        let suffix = k.strip_prefix(&path_prefix).unwrap().trim_start_matches('·');
2130                        (suffix.to_string(), v.clone())
2131                    })
2132                    .filter(|(k, _)| !k.contains('·')) // Only immediate children
2133                    .collect();
2134                for (name, def) in matching_types {
2135                    self.types.insert(name, def);
2136                }
2137                // Similar for functions
2138                let matching_funcs: Vec<(String, Value)> = {
2139                    let globals = self.globals.borrow();
2140                    globals.values.iter()
2141                        .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
2142                        .map(|(k, v)| {
2143                            let suffix = k.strip_prefix(&path_prefix).unwrap().trim_start_matches('·');
2144                            (suffix.to_string(), v.clone())
2145                        })
2146                        .filter(|(k, _)| !k.contains('·'))
2147                        .collect()
2148                };
2149                for (name, val) in matching_funcs {
2150                    self.globals.borrow_mut().define(name, val);
2151                }
2152                Ok(())
2153            }
2154            UseTree::Group(trees) => {
2155                // use foo::{Bar, Baz}
2156                for tree in trees {
2157                    self.process_use_tree(tree, prefix)?;
2158                }
2159                Ok(())
2160            }
2161        }
2162    }
2163
2164    fn create_function(&self, func: &crate::ast::Function) -> Result<Value, RuntimeError> {
2165        let params: Vec<String> = func
2166            .params
2167            .iter()
2168            .map(|p| Self::extract_param_name(&p.pattern))
2169            .collect();
2170
2171        let body = func
2172            .body
2173            .as_ref()
2174            .map(|b| Expr::Block(b.clone()))
2175            .unwrap_or(Expr::Literal(Literal::Bool(false)));
2176
2177        Ok(Value::Function(Rc::new(Function {
2178            name: Some(func.name.name.clone()),
2179            params,
2180            body,
2181            closure: self.environment.clone(),
2182        })))
2183    }
2184
2185    /// Extract parameter name from a pattern, handling &self, mut self, etc.
2186    fn extract_param_name(pattern: &Pattern) -> String {
2187        match pattern {
2188            Pattern::Ident { name, .. } => name.name.clone(),
2189            // Handle &self and &mut self
2190            Pattern::Ref { pattern: inner, .. } => Self::extract_param_name(inner),
2191            // Handle ref self
2192            Pattern::RefBinding { name, .. } => name.name.clone(),
2193            _ => "_".to_string(),
2194        }
2195    }
2196
2197    /// Evaluate an expression
2198    pub fn evaluate(&mut self, expr: &Expr) -> Result<Value, RuntimeError> {
2199        match expr {
2200            Expr::Literal(lit) => self.eval_literal(lit),
2201            Expr::Path(path) => self.eval_path(path),
2202            Expr::Binary { left, op, right } => self.eval_binary(left, op, right),
2203            Expr::Unary { op, expr } => self.eval_unary(op, expr),
2204            Expr::Call { func, args } => self.eval_call(func, args),
2205            Expr::Array(elements) => self.eval_array(elements),
2206            Expr::Tuple(elements) => self.eval_tuple(elements),
2207            Expr::Block(block) => self.eval_block(block),
2208            Expr::If {
2209                condition,
2210                then_branch,
2211                else_branch,
2212            } => self.eval_if(condition, then_branch, else_branch),
2213            Expr::Match { expr, arms } => self.eval_match(expr, arms),
2214            Expr::For {
2215                pattern,
2216                iter,
2217                body,
2218                ..
2219            } => self.eval_for(pattern, iter, body),
2220            Expr::While { condition, body, .. } => self.eval_while(condition, body),
2221            Expr::Loop { body, .. } => self.eval_loop(body),
2222            Expr::Return(value) => self.eval_return(value),
2223            Expr::Break { value, .. } => self.eval_break(value),
2224            Expr::Continue { .. } => Err(RuntimeError::new("continue")),
2225            Expr::Index { expr, index } => self.eval_index(expr, index),
2226            Expr::Field { expr, field } => self.eval_field(expr, field),
2227            Expr::MethodCall {
2228                receiver,
2229                method,
2230                args,
2231                ..
2232            } => self.eval_method_call(receiver, method, args),
2233            // Polysynthetic incorporation: path·file·read·string
2234            // Each segment is a method/function that transforms the value
2235            Expr::Incorporation { segments } => self.eval_incorporation(segments),
2236            Expr::Pipe { expr, operations } => self.eval_pipe(expr, operations),
2237            Expr::Closure { params, body, .. } => self.eval_closure(params, body),
2238            Expr::Struct { path, fields, rest } => self.eval_struct_literal(path, fields, rest),
2239            Expr::Evidential {
2240                expr,
2241                evidentiality,
2242            } => self.eval_evidential(expr, evidentiality),
2243            Expr::Range {
2244                start,
2245                end,
2246                inclusive,
2247            } => {
2248                crate::sigil_debug!("DEBUG evaluate: Expr::Range being evaluated standalone");
2249                self.eval_range(start, end, *inclusive)
2250            }
2251            Expr::Assign { target, value } => self.eval_assign(target, value),
2252            Expr::Let { pattern, value } => {
2253                // Let expression (for if-let, while-let patterns)
2254                // Evaluate the value and check if pattern matches
2255                let val = self.evaluate(value)?;
2256                // Check if pattern matches - return true/false for if-let semantics
2257                if self.pattern_matches(pattern, &val)? {
2258                    // Pattern matches - bind variables and return true
2259                    self.bind_pattern(pattern, val)?;
2260                    Ok(Value::Bool(true))
2261                } else {
2262                    // Pattern doesn't match - return false without binding
2263                    Ok(Value::Bool(false))
2264                }
2265            }
2266            Expr::Await {
2267                expr: inner,
2268                evidentiality,
2269            } => {
2270                let value = self.evaluate(inner)?;
2271                let awaited = self.await_value(value)?;
2272                // Handle evidentiality marker semantics
2273                match evidentiality {
2274                    Some(Evidentiality::Uncertain) => {
2275                        // ⌛? - propagate error like Try
2276                        self.unwrap_result_or_option(awaited, true, false)
2277                    }
2278                    Some(Evidentiality::Known) => {
2279                        // ⌛! - expect success, panic on error
2280                        self.unwrap_result_or_option(awaited, true, true)
2281                    }
2282                    Some(Evidentiality::Reported) | Some(Evidentiality::Paradox) | Some(Evidentiality::Predicted) => {
2283                        // ⌛~ or ⌛‽ or ⌛◊ - mark as external/reported/predicted, unwrap if Result/Option
2284                        self.unwrap_result_or_option(awaited, false, false)
2285                    }
2286                    None => Ok(awaited),
2287                }
2288            }
2289            // Macro invocations: format!(...), println!(...), etc.
2290            Expr::Macro { path, tokens } => {
2291                let macro_name = path.segments.last()
2292                    .map(|s| s.ident.name.as_str())
2293                    .unwrap_or("");
2294                crate::sigil_debug!("DEBUG Expr::Macro: name='{}', tokens='{}'", macro_name, tokens);
2295
2296                match macro_name {
2297                    "format" => self.eval_format_macro(tokens),
2298                    "println" => {
2299                        let formatted = self.eval_format_macro(tokens)?;
2300                        if let Value::String(s) = formatted {
2301                            println!("{}", s);
2302                        }
2303                        Ok(Value::Null)
2304                    }
2305                    "eprintln" => {
2306                        let formatted = self.eval_format_macro(tokens)?;
2307                        if let Value::String(s) = formatted {
2308                            eprintln!("{}", s);
2309                        }
2310                        Ok(Value::Null)
2311                    }
2312                    "print" => {
2313                        let formatted = self.eval_format_macro(tokens)?;
2314                        if let Value::String(s) = formatted {
2315                            print!("{}", s);
2316                        }
2317                        Ok(Value::Null)
2318                    }
2319                    "eprint" => {
2320                        let formatted = self.eval_format_macro(tokens)?;
2321                        if let Value::String(s) = formatted {
2322                            eprint!("{}", s);
2323                        }
2324                        Ok(Value::Null)
2325                    }
2326                    "vec" => {
2327                        // vec![a, b, c] - parse elements and create array
2328                        self.eval_vec_macro(tokens)
2329                    }
2330                    "panic" => {
2331                        let formatted = self.eval_format_macro(tokens)?;
2332                        let msg = if let Value::String(s) = formatted {
2333                            s.to_string()
2334                        } else {
2335                            "panic!".to_string()
2336                        };
2337                        Err(RuntimeError::new(format!("panic: {}", msg)))
2338                    }
2339                    "assert" => {
2340                        // Simple assert - just evaluate the expression
2341                        let condition = self.eval_format_macro(tokens)?;
2342                        if self.is_truthy(&condition) {
2343                            Ok(Value::Null)
2344                        } else {
2345                            Err(RuntimeError::new("assertion failed"))
2346                        }
2347                    }
2348                    _ => {
2349                        // Unknown macro - return tokens as string for debugging
2350                        Ok(Value::String(Rc::new(tokens.clone())))
2351                    }
2352                }
2353            }
2354            // Unsafe block - just evaluate the block normally
2355            Expr::Unsafe(block) => self.eval_block(block),
2356            // Async block - evaluate the block (interpreter doesn't handle true async)
2357            Expr::Async { block, .. } => self.eval_block(block),
2358            // Try expression: expr?
2359            Expr::Try(inner) => {
2360                let value = self.evaluate(inner)?;
2361                // If Result::Err or None, propagate the error
2362                // If Result::Ok or Some, unwrap the value
2363                match &value {
2364                    Value::Variant { enum_name, variant_name, fields } => {
2365                        match (enum_name.as_str(), variant_name.as_str()) {
2366                            ("Result", "Ok") => {
2367                                if let Some(f) = fields {
2368                                    Ok(f.first().cloned().unwrap_or(Value::Null))
2369                                } else {
2370                                    Ok(Value::Null)
2371                                }
2372                            }
2373                            ("Result", "Err") => {
2374                                crate::sigil_debug!("DEBUG Try propagating Result::Err with fields: {:?}", fields);
2375                                let err_msg = if let Some(f) = fields {
2376                                    let first = f.first().cloned().unwrap_or(Value::Null);
2377                                    crate::sigil_debug!("DEBUG Try error first value: {}", first);
2378                                    // Try to get more detail from the error
2379                                    match &first {
2380                                        Value::Struct { name, fields: sf } => {
2381                                            let field_str = sf.borrow().iter()
2382                                                .map(|(k, v)| format!("{}: {}", k, v))
2383                                                .collect::<Vec<_>>()
2384                                                .join(", ");
2385                                            format!("{} {{ {} }}", name, field_str)
2386                                        }
2387                                        Value::Variant { enum_name: en, variant_name: vn, fields: vf } => {
2388                                            let vf_str = vf.as_ref().map(|vs|
2389                                                vs.iter().map(|v| format!("{}", v)).collect::<Vec<_>>().join(", ")
2390                                            ).unwrap_or_default();
2391                                            format!("{}::{} {{ {} }}", en, vn, vf_str)
2392                                        }
2393                                        _ => format!("{}", first)
2394                                    }
2395                                } else {
2396                                    "error".to_string()
2397                                };
2398                                Err(RuntimeError::new(format!("try failed: {}", err_msg)))
2399                            }
2400                            ("Option", "Some") => {
2401                                if let Some(f) = fields {
2402                                    Ok(f.first().cloned().unwrap_or(Value::Null))
2403                                } else {
2404                                    Ok(Value::Null)
2405                                }
2406                            }
2407                            ("Option", "None") => {
2408                                Err(RuntimeError::new("try failed: None"))
2409                            }
2410                            _ => Ok(value), // Not a Result/Option, pass through
2411                        }
2412                    }
2413                    _ => Ok(value), // Not a variant, pass through
2414                }
2415            }
2416            // Cast expression: expr as Type
2417            Expr::Cast { expr, ty } => {
2418                let value = self.evaluate(expr)?;
2419                // Handle type casts
2420                let type_name = match ty {
2421                    TypeExpr::Path(path) => {
2422                        if !path.segments.is_empty() {
2423                            path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("")
2424                        } else {
2425                            ""
2426                        }
2427                    }
2428                    _ => "",
2429                };
2430                match (value, type_name) {
2431                    // Char to numeric
2432                    (Value::Char(c), "u8") => Ok(Value::Int(c as i64)),
2433                    (Value::Char(c), "u16") => Ok(Value::Int(c as i64)),
2434                    (Value::Char(c), "u32") => Ok(Value::Int(c as i64)),
2435                    (Value::Char(c), "u64") => Ok(Value::Int(c as i64)),
2436                    (Value::Char(c), "i8") => Ok(Value::Int(c as i64)),
2437                    (Value::Char(c), "i16") => Ok(Value::Int(c as i64)),
2438                    (Value::Char(c), "i32") => Ok(Value::Int(c as i64)),
2439                    (Value::Char(c), "i64") => Ok(Value::Int(c as i64)),
2440                    (Value::Char(c), "usize") => Ok(Value::Int(c as i64)),
2441                    (Value::Char(c), "isize") => Ok(Value::Int(c as i64)),
2442                    // Int to int (no-op in our runtime)
2443                    (Value::Int(i), "u8") => Ok(Value::Int(i)),
2444                    (Value::Int(i), "u16") => Ok(Value::Int(i)),
2445                    (Value::Int(i), "u32") => Ok(Value::Int(i)),
2446                    (Value::Int(i), "u64") => Ok(Value::Int(i)),
2447                    (Value::Int(i), "i8") => Ok(Value::Int(i)),
2448                    (Value::Int(i), "i16") => Ok(Value::Int(i)),
2449                    (Value::Int(i), "i32") => Ok(Value::Int(i)),
2450                    (Value::Int(i), "i64") => Ok(Value::Int(i)),
2451                    (Value::Int(i), "usize") => Ok(Value::Int(i)),
2452                    (Value::Int(i), "isize") => Ok(Value::Int(i)),
2453                    // Float to int
2454                    (Value::Float(f), "i32") => Ok(Value::Int(f as i64)),
2455                    (Value::Float(f), "i64") => Ok(Value::Int(f as i64)),
2456                    (Value::Float(f), "u32") => Ok(Value::Int(f as i64)),
2457                    (Value::Float(f), "u64") => Ok(Value::Int(f as i64)),
2458                    // Int to float
2459                    (Value::Int(i), "f32") => Ok(Value::Float(i as f64)),
2460                    (Value::Int(i), "f64") => Ok(Value::Float(i as f64)),
2461                    // Int to char
2462                    (Value::Int(i), "char") => {
2463                        if let Some(c) = char::from_u32(i as u32) {
2464                            Ok(Value::Char(c))
2465                        } else {
2466                            Err(RuntimeError::new(format!("invalid char code: {}", i)))
2467                        }
2468                    }
2469                    // Pass through for same type
2470                    (v, _) => Ok(v),
2471                }
2472            }
2473            _ => Err(RuntimeError::new(format!(
2474                "Unsupported expression: {:?}",
2475                expr
2476            ))),
2477        }
2478    }
2479
2480    fn eval_assign(&mut self, target: &Expr, value: &Expr) -> Result<Value, RuntimeError> {
2481        let val = self.evaluate(value)?;
2482
2483        match target {
2484            Expr::Path(path) if path.segments.len() == 1 => {
2485                let name = &path.segments[0].ident.name;
2486                self.environment.borrow_mut().set(name, val.clone())?;
2487                Ok(val)
2488            }
2489            Expr::Index { expr, index } => {
2490                // Array/map index assignment
2491                let idx = self.evaluate(index)?;
2492                let idx = match idx {
2493                    Value::Int(i) => i as usize,
2494                    _ => return Err(RuntimeError::new("Index must be an integer")),
2495                };
2496
2497                // Get the array and modify it
2498                if let Expr::Path(path) = expr.as_ref() {
2499                    if path.segments.len() == 1 {
2500                        let name = &path.segments[0].ident.name;
2501                        let current = self.environment.borrow().get(name).ok_or_else(|| {
2502                            RuntimeError::new(format!("Undefined variable: {}", name))
2503                        })?;
2504
2505                        if let Value::Array(arr) = current {
2506                            let borrowed = arr.borrow();
2507                            let mut new_arr = borrowed.clone();
2508                            drop(borrowed);
2509                            if idx < new_arr.len() {
2510                                new_arr[idx] = val.clone();
2511                                self.environment
2512                                    .borrow_mut()
2513                                    .set(name, Value::Array(Rc::new(RefCell::new(new_arr))))?;
2514                                return Ok(val);
2515                            }
2516                        }
2517                    }
2518                }
2519                Err(RuntimeError::new("Invalid index assignment target"))
2520            }
2521            Expr::Field { expr, field } => {
2522                // Field assignment: struct.field = value
2523                // Need to find the variable and update its field
2524                match expr.as_ref() {
2525                    Expr::Path(path) if path.segments.len() == 1 => {
2526                        let var_name = &path.segments[0].ident.name;
2527                        let current = self.environment.borrow().get(var_name).ok_or_else(|| {
2528                            RuntimeError::new(format!("Undefined variable: {}", var_name))
2529                        })?;
2530
2531                        match current {
2532                            Value::Struct { fields, .. } => {
2533                                fields.borrow_mut().insert(field.name.clone(), val.clone());
2534                                Ok(val)
2535                            }
2536                            Value::Ref(r) => {
2537                                let mut borrowed = r.borrow_mut();
2538                                if let Value::Struct { fields, .. } = &mut *borrowed {
2539                                    fields.borrow_mut().insert(field.name.clone(), val.clone());
2540                                    Ok(val)
2541                                } else {
2542                                    Err(RuntimeError::new("Cannot assign field on non-struct ref"))
2543                                }
2544                            }
2545                            _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
2546                        }
2547                    }
2548                    _ => {
2549                        // For now, just evaluate and try to update (won't persist for non-path exprs)
2550                        let struct_val = self.evaluate(expr)?;
2551                        match struct_val {
2552                            Value::Struct { fields, .. } => {
2553                                fields.borrow_mut().insert(field.name.clone(), val.clone());
2554                                Ok(val)
2555                            }
2556                            Value::Ref(r) => {
2557                                let mut borrowed = r.borrow_mut();
2558                                if let Value::Struct { fields, .. } = &mut *borrowed {
2559                                    fields.borrow_mut().insert(field.name.clone(), val.clone());
2560                                    Ok(val)
2561                                } else {
2562                                    Err(RuntimeError::new("Cannot assign field on non-struct"))
2563                                }
2564                            }
2565                            _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
2566                        }
2567                    }
2568                }
2569            }
2570            Expr::Unary { op: UnaryOp::Deref, expr: inner } => {
2571                // Dereference assignment: *ptr = value (parsed as Unary)
2572                // Handle mutable references (&mut T)
2573                let ptr_val = self.evaluate(inner)?;
2574                match ptr_val {
2575                    Value::Ref(r) => {
2576                        *r.borrow_mut() = val.clone();
2577                        Ok(val)
2578                    }
2579                    _ => Err(RuntimeError::new("Cannot dereference assign to non-reference")),
2580                }
2581            }
2582            Expr::Deref(inner) => {
2583                // Dereference assignment: *ptr = value (parsed as Deref)
2584                // Handle mutable references (&mut T)
2585                let ptr_val = self.evaluate(inner)?;
2586                match ptr_val {
2587                    Value::Ref(r) => {
2588                        *r.borrow_mut() = val.clone();
2589                        Ok(val)
2590                    }
2591                    _ => Err(RuntimeError::new("Cannot dereference assign to non-reference")),
2592                }
2593            }
2594            _ => Err(RuntimeError::new("Invalid assignment target")),
2595        }
2596    }
2597
2598    fn eval_literal(&mut self, lit: &Literal) -> Result<Value, RuntimeError> {
2599        match lit {
2600            Literal::Int { value, base, .. } => {
2601                let n = self.parse_int(value, base)?;
2602                Ok(Value::Int(n))
2603            }
2604            Literal::Float { value, .. } => {
2605                let n: f64 = value
2606                    .parse()
2607                    .map_err(|_| RuntimeError::new(format!("Invalid float: {}", value)))?;
2608                Ok(Value::Float(n))
2609            }
2610            Literal::String(s) => Ok(Value::String(Rc::new(s.clone()))),
2611            Literal::MultiLineString(s) => Ok(Value::String(Rc::new(s.clone()))),
2612            Literal::RawString(s) => Ok(Value::String(Rc::new(s.clone()))),
2613            Literal::ByteString(bytes) => {
2614                // Convert byte array to an array of integers
2615                let arr: Vec<Value> = bytes.iter().map(|&b| Value::Int(b as i64)).collect();
2616                Ok(Value::Array(Rc::new(RefCell::new(arr))))
2617            }
2618            Literal::InterpolatedString { parts } => {
2619                // Evaluate each part and concatenate, tracking evidentiality
2620                let mut result = String::new();
2621                let mut combined_evidence: Option<Evidence> = None;
2622
2623                for part in parts {
2624                    match part {
2625                        InterpolationPart::Text(s) => result.push_str(s),
2626                        InterpolationPart::Expr(expr) => {
2627                            let value = self.evaluate(expr)?;
2628
2629                            // Track explicit evidentiality
2630                            combined_evidence = Self::combine_evidence(
2631                                combined_evidence,
2632                                Self::extract_evidence(&value),
2633                            );
2634
2635                            // Track affect-derived evidentiality (sarcasm, confidence)
2636                            if let Some(affect) = Self::extract_affect(&value) {
2637                                combined_evidence = Self::combine_evidence(
2638                                    combined_evidence,
2639                                    Self::affect_to_evidence(affect),
2640                                );
2641                            }
2642
2643                            // Use the fully unwrapped value for display
2644                            let display_value = Self::unwrap_value(&value);
2645                            result.push_str(&format!("{}", display_value));
2646                        }
2647                    }
2648                }
2649
2650                // Wrap result with evidentiality if any interpolated values were evidential
2651                let string_value = Value::String(Rc::new(result));
2652                match combined_evidence {
2653                    Some(evidence) => Ok(Value::Evidential {
2654                        value: Box::new(string_value),
2655                        evidence,
2656                    }),
2657                    None => Ok(string_value),
2658                }
2659            }
2660            Literal::SigilStringSql(s) => {
2661                // SQL sigil string - for now just return as string
2662                // Future: could add SQL validation or templating
2663                Ok(Value::String(Rc::new(s.clone())))
2664            }
2665            Literal::SigilStringRoute(s) => {
2666                // Route sigil string - for now just return as string
2667                // Future: could add route validation or templating
2668                Ok(Value::String(Rc::new(s.clone())))
2669            }
2670            Literal::Char(c) => Ok(Value::Char(*c)),
2671            Literal::ByteChar(b) => Ok(Value::Int(*b as i64)),
2672            Literal::Bool(b) => Ok(Value::Bool(*b)),
2673            Literal::Null => Ok(Value::Null),
2674            Literal::Empty => Ok(Value::Empty),
2675            Literal::Infinity => Ok(Value::Infinity),
2676            Literal::Circle => Ok(Value::Int(0)), // ◯ = zero
2677        }
2678    }
2679
2680    fn parse_int(&self, value: &str, base: &NumBase) -> Result<i64, RuntimeError> {
2681        let (radix, prefix_len) = match base {
2682            NumBase::Binary => (2, 2), // 0b
2683            NumBase::Octal => (8, 2),  // 0o
2684            NumBase::Decimal => (10, 0),
2685            NumBase::Hex => (16, 2),         // 0x
2686            NumBase::Vigesimal => (20, 2),   // 0v
2687            NumBase::Sexagesimal => (60, 2), // 0s
2688            NumBase::Duodecimal => (12, 2),  // 0z
2689            NumBase::Explicit(b) => (*b as u32, 0),
2690        };
2691
2692        let clean = value[prefix_len..].replace('_', "");
2693        i64::from_str_radix(&clean, radix)
2694            .map_err(|_| RuntimeError::new(format!("Invalid integer: {}", value)))
2695    }
2696
2697    fn eval_path(&self, path: &TypePath) -> Result<Value, RuntimeError> {
2698        if path.segments.len() == 1 {
2699            let name = &path.segments[0].ident.name;
2700            // Look up the variable in the environment
2701            // Note: "_" may be bound by pipe operations (τ, φ, etc.), so we must check
2702            // the environment first before treating it as a wildcard
2703            if let Some(val) = self.environment.borrow().get(name) {
2704                return Ok(val);
2705            }
2706            // Handle wildcard "_" - return Null if not bound
2707            if name == "_" {
2708                return Ok(Value::Null);
2709            }
2710            // Handle "Self" as unit struct constructor (for unit structs like `pub fn new() -> Self { Self }`)
2711            if name == "Self" {
2712                if let Some(ref self_type) = self.current_self_type {
2713                    // Check if the type is a unit struct
2714                    if let Some(TypeDef::Struct(struct_def)) = self.types.get(self_type) {
2715                        if matches!(struct_def.fields, crate::ast::StructFields::Unit) {
2716                            return Ok(Value::Struct {
2717                                name: self_type.clone(),
2718                                fields: Rc::new(RefCell::new(HashMap::new())),
2719                            });
2720                        }
2721                    }
2722                    // If not a unit struct, create empty struct (best effort)
2723                    return Ok(Value::Struct {
2724                        name: self_type.clone(),
2725                        fields: Rc::new(RefCell::new(HashMap::new())),
2726                    });
2727                }
2728            }
2729            if name.len() <= 2 {
2730                crate::sigil_debug!("DEBUG Undefined variable '{}' (len={})", name, name.len());
2731            }
2732            Err(RuntimeError::new(format!("Undefined variable: {}", name)))
2733        } else {
2734            // Multi-segment path (module::item or Type·method)
2735            // Try full qualified name first (joined with ·)
2736            let full_name = path
2737                .segments
2738                .iter()
2739                .map(|s| s.ident.name.as_str())
2740                .collect::<Vec<_>>()
2741                .join("·");
2742
2743            if let Some(val) = self.environment.borrow().get(&full_name) {
2744                return Ok(val);
2745            }
2746
2747            // Check globals for qualified name (for Type::method patterns)
2748            if let Some(val) = self.globals.borrow().get(&full_name) {
2749                return Ok(val);
2750            }
2751
2752            // If in a module context, try current_module·full_name for sibling modules
2753            // e.g., when in samael_cli, "analyze::execute" -> "samael_cli·analyze·execute"
2754            if let Some(ref current_mod) = self.current_module {
2755                // Extract crate name from current_module (e.g., "samael_cli" from "samael_cli·analyze")
2756                let crate_name = current_mod.split('·').next().unwrap_or(current_mod);
2757                let crate_qualified = format!("{}·{}", crate_name, full_name);
2758                if full_name.contains("execute") {
2759                    crate::sigil_debug!("DEBUG eval_path: Looking for '{}' with crate_qualified='{}'", full_name, crate_qualified);
2760                }
2761                if let Some(val) = self.globals.borrow().get(&crate_qualified) {
2762                    crate::sigil_debug!("DEBUG eval_path: FOUND '{}' via crate_qualified", crate_qualified);
2763                    return Ok(val);
2764                }
2765            } else if full_name.contains("execute") {
2766                crate::sigil_debug!("DEBUG eval_path: current_module is None, can't resolve '{}'", full_name);
2767            }
2768
2769            // DEBUG: Check if we're looking for a ::new call
2770            if full_name.ends_with("·new") {
2771                crate::sigil_debug!("DEBUG eval_path: Looking for '{}' - NOT FOUND in globals", full_name);
2772            }
2773
2774            // Check for enum variant syntax FIRST (EnumName::Variant)
2775            // This must come before looking up just the last segment to avoid
2776            // returning a built-in function instead of the actual variant
2777            if path.segments.len() == 2 {
2778                let type_name = &path.segments[0].ident.name;
2779                let variant_name = &path.segments[1].ident.name;
2780
2781                // Check if this is an enum variant (direct type name match)
2782                if let Some(TypeDef::Enum(enum_def)) = self.types.get(type_name) {
2783                    for variant in &enum_def.variants {
2784                        if &variant.name.name == variant_name {
2785                            // Return a variant constructor or unit variant
2786                            if matches!(variant.fields, crate::ast::StructFields::Unit) {
2787                                return Ok(Value::Variant {
2788                                    enum_name: type_name.clone(),
2789                                    variant_name: variant_name.clone(),
2790                                    fields: None,
2791                                });
2792                            }
2793                        }
2794                    }
2795                }
2796
2797                // Fallback: type name might be an alias - search all enums for the variant
2798                for (actual_type_name, type_def) in &self.types {
2799                    if let TypeDef::Enum(enum_def) = type_def {
2800                        for variant in &enum_def.variants {
2801                            if &variant.name.name == variant_name {
2802                                if matches!(variant.fields, crate::ast::StructFields::Unit) {
2803                                    return Ok(Value::Variant {
2804                                        enum_name: actual_type_name.clone(),
2805                                        variant_name: variant_name.clone(),
2806                                        fields: None,
2807                                    });
2808                                }
2809                            }
2810                        }
2811                    }
2812                }
2813            }
2814
2815            // Try looking up the last segment (for Math·sqrt -> sqrt)
2816            let last_name = &path.segments.last().unwrap().ident.name;
2817            if let Some(val) = self.environment.borrow().get(last_name) {
2818                // DEBUG: Warn about fallback for new functions
2819                if last_name == "new" {
2820                    crate::sigil_debug!("DEBUG eval_path: FALLBACK from '{}' to '{}' - found in env", full_name, last_name);
2821                }
2822                return Ok(val);
2823            }
2824
2825            // Handle Self::method - use current_self_type to get the specific type
2826            if path.segments.len() == 2 && path.segments[0].ident.name == "Self" {
2827                if let Some(ref self_type) = self.current_self_type {
2828                    // Look up the specific Type·method function
2829                    let qualified = format!("{}·{}", self_type, last_name);
2830                    if let Some(val) = self.globals.borrow().get(&qualified) {
2831                        return Ok(val);
2832                    }
2833                }
2834            }
2835
2836            // Check for variant constructor in variant_constructors table
2837            if let Some((enum_name, variant_name, arity)) = self.variant_constructors.get(&full_name).cloned() {
2838                // Return a special marker that eval_call can recognize
2839                // For unit variants, return the variant directly
2840                if arity == 0 {
2841                    return Ok(Value::Variant {
2842                        enum_name,
2843                        variant_name,
2844                        fields: None,
2845                    });
2846                }
2847                // For variants with fields, we need to return something callable
2848                // We'll use a special builtin-like marker
2849                // Actually, let's just let eval_call handle it via call_function_by_name
2850            }
2851
2852            // Fallback for unknown types from external crates:
2853            if path.segments.len() == 2 {
2854                let type_name = &path.segments[0].ident.name;
2855                let method_name = &path.segments[1].ident.name;
2856
2857                // Check if this looks like a constructor/method call (lowercase or snake_case)
2858                let is_method = method_name.chars().next().map_or(false, |c| c.is_lowercase())
2859                    || method_name == "new"
2860                    || method_name == "default"
2861                    || method_name == "from"
2862                    || method_name == "try_from"
2863                    || method_name == "into"
2864                    || method_name == "with_capacity"
2865                    || method_name == "from_str";
2866
2867                if is_method {
2868                    // Return a special marker that eval_call will recognize
2869                    // Store the type name in a Struct value with a special marker name
2870                    return Ok(Value::Struct {
2871                        name: format!("__constructor__{}", type_name),
2872                        fields: Rc::new(RefCell::new(HashMap::new())),
2873                    });
2874                } else {
2875                    // Looks like an enum variant (PascalCase) - create unit variant
2876                    return Ok(Value::Variant {
2877                        enum_name: type_name.clone(),
2878                        variant_name: method_name.clone(),
2879                        fields: None,
2880                    });
2881                }
2882            }
2883
2884            Err(RuntimeError::new(format!(
2885                "Undefined: {} (tried {} and {})",
2886                full_name, full_name, last_name
2887            )))
2888        }
2889    }
2890
2891    fn eval_binary(
2892        &mut self,
2893        left: &Expr,
2894        op: &BinOp,
2895        right: &Expr,
2896    ) -> Result<Value, RuntimeError> {
2897        let lhs = self.evaluate(left)?;
2898
2899        // Short-circuit for && and ||
2900        match op {
2901            BinOp::And => {
2902                if !self.is_truthy(&lhs) {
2903                    return Ok(Value::Bool(false));
2904                }
2905                let rhs = self.evaluate(right)?;
2906                return Ok(Value::Bool(self.is_truthy(&rhs)));
2907            }
2908            BinOp::Or => {
2909                if self.is_truthy(&lhs) {
2910                    return Ok(Value::Bool(true));
2911                }
2912                let rhs = self.evaluate(right)?;
2913                return Ok(Value::Bool(self.is_truthy(&rhs)));
2914            }
2915            _ => {}
2916        }
2917
2918        let rhs = self.evaluate(right)?;
2919
2920        // Unwrap all wrappers (evidential/affective/ref) for binary operations
2921        let lhs = Self::unwrap_all(&lhs);
2922        let rhs = Self::unwrap_all(&rhs);
2923
2924        // Debug Mul operations involving potential null
2925        if matches!(op, BinOp::Mul) && (matches!(lhs, Value::Null) || matches!(rhs, Value::Null) || matches!(lhs, Value::Struct { .. }) || matches!(rhs, Value::Struct { .. })) {
2926            crate::sigil_debug!("DEBUG eval_binary Mul: left={:?}, right={:?}", left, right);
2927            crate::sigil_debug!("DEBUG eval_binary Mul: lhs={}, rhs={}", self.format_value(&lhs), self.format_value(&rhs));
2928        }
2929
2930        match (lhs, rhs) {
2931            (Value::Int(a), Value::Int(b)) => self.int_binary_op(a, b, op),
2932            (Value::Float(a), Value::Float(b)) => self.float_binary_op(a, b, op),
2933            (Value::Int(a), Value::Float(b)) => self.float_binary_op(a as f64, b, op),
2934            (Value::Float(a), Value::Int(b)) => self.float_binary_op(a, b as f64, op),
2935            (Value::String(a), Value::String(b)) => match op {
2936                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
2937                BinOp::Eq => Ok(Value::Bool(*a == *b)),
2938                BinOp::Ne => Ok(Value::Bool(*a != *b)),
2939                _ => Err(RuntimeError::new("Invalid string operation")),
2940            },
2941            (Value::Bool(a), Value::Bool(b)) => match op {
2942                BinOp::Eq => Ok(Value::Bool(a == b)),
2943                BinOp::Ne => Ok(Value::Bool(a != b)),
2944                _ => Err(RuntimeError::new("Invalid boolean operation")),
2945            },
2946            (Value::Array(a), Value::Array(b)) => match op {
2947                BinOp::Concat => {
2948                    let mut result = a.borrow().clone();
2949                    result.extend(b.borrow().iter().cloned());
2950                    Ok(Value::Array(Rc::new(RefCell::new(result))))
2951                }
2952                BinOp::Eq => Ok(Value::Bool(Rc::ptr_eq(&a, &b))),
2953                BinOp::Ne => Ok(Value::Bool(!Rc::ptr_eq(&a, &b))),
2954                _ => Err(RuntimeError::new("Invalid array operation")),
2955            },
2956            // Null equality
2957            (Value::Null, Value::Null) => match op {
2958                BinOp::Eq => Ok(Value::Bool(true)),
2959                BinOp::Ne => Ok(Value::Bool(false)),
2960                _ => {
2961                    crate::sigil_debug!("DEBUG: null op {:?} on (Null, Null)", op);
2962                    Err(RuntimeError::new(format!("Invalid null operation: {:?} on (Null, Null)", op)))
2963                }
2964            },
2965            (Value::Null, other) | (other, Value::Null) => match op {
2966                BinOp::Eq => Ok(Value::Bool(false)),
2967                BinOp::Ne => Ok(Value::Bool(true)),
2968                _ => {
2969                    crate::sigil_debug!("DEBUG: null op {:?} with other={}", op, self.format_value(&other));
2970                    Err(RuntimeError::new(format!("Invalid null operation: {:?}", op)))
2971                }
2972            },
2973            // Char comparisons
2974            (Value::Char(a), Value::Char(b)) => match op {
2975                BinOp::Eq => Ok(Value::Bool(a == b)),
2976                BinOp::Ne => Ok(Value::Bool(a != b)),
2977                BinOp::Lt => Ok(Value::Bool(a < b)),
2978                BinOp::Le => Ok(Value::Bool(a <= b)),
2979                BinOp::Gt => Ok(Value::Bool(a > b)),
2980                BinOp::Ge => Ok(Value::Bool(a >= b)),
2981                _ => Err(RuntimeError::new("Invalid char operation")),
2982            },
2983            // String and char operations
2984            (Value::String(a), Value::Char(b)) => match op {
2985                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
2986                _ => Err(RuntimeError::new("Invalid string/char operation")),
2987            },
2988            (Value::Char(a), Value::String(b)) => match op {
2989                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
2990                _ => Err(RuntimeError::new("Invalid char/string operation")),
2991            },
2992            // Variant equality
2993            (Value::Variant { enum_name: e1, variant_name: v1, fields: f1 },
2994             Value::Variant { enum_name: e2, variant_name: v2, fields: f2 }) => match op {
2995                BinOp::Eq => {
2996                    let eq = e1 == e2 && v1 == v2 && match (f1, f2) {
2997                        (None, None) => true,
2998                        (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
2999                        _ => false,
3000                    };
3001                    Ok(Value::Bool(eq))
3002                }
3003                BinOp::Ne => {
3004                    let eq = e1 == e2 && v1 == v2 && match (f1, f2) {
3005                        (None, None) => true,
3006                        (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
3007                        _ => false,
3008                    };
3009                    Ok(Value::Bool(!eq))
3010                }
3011                _ => Err(RuntimeError::new("Invalid variant operation")),
3012            },
3013            // Struct equality (by reference)
3014            (Value::Struct { name: n1, fields: f1 }, Value::Struct { name: n2, fields: f2 }) => match op {
3015                BinOp::Eq => Ok(Value::Bool(n1 == n2 && Rc::ptr_eq(&f1, &f2))),
3016                BinOp::Ne => Ok(Value::Bool(n1 != n2 || !Rc::ptr_eq(&f1, &f2))),
3017                _ => Err(RuntimeError::new("Invalid struct operation")),
3018            },
3019            (l, r) => Err(RuntimeError::new(format!(
3020                "Type mismatch in binary operation: {:?} {:?} {:?}",
3021                l, op, r
3022            ))),
3023        }
3024    }
3025
3026    fn int_binary_op(&self, a: i64, b: i64, op: &BinOp) -> Result<Value, RuntimeError> {
3027        Ok(match op {
3028            BinOp::Add => Value::Int(a + b),
3029            BinOp::Sub => Value::Int(a - b),
3030            BinOp::Mul => Value::Int(a * b),
3031            BinOp::Div => {
3032                if b == 0 {
3033                    return Err(RuntimeError::new("Division by zero"));
3034                }
3035                Value::Int(a / b)
3036            }
3037            BinOp::Rem => {
3038                if b == 0 {
3039                    return Err(RuntimeError::new("Division by zero"));
3040                }
3041                Value::Int(a % b)
3042            }
3043            BinOp::Pow => Value::Int(a.pow(b as u32)),
3044            BinOp::Eq => Value::Bool(a == b),
3045            BinOp::Ne => Value::Bool(a != b),
3046            BinOp::Lt => Value::Bool(a < b),
3047            BinOp::Le => Value::Bool(a <= b),
3048            BinOp::Gt => Value::Bool(a > b),
3049            BinOp::Ge => Value::Bool(a >= b),
3050            BinOp::BitAnd => Value::Int(a & b),
3051            BinOp::BitOr => Value::Int(a | b),
3052            BinOp::BitXor => Value::Int(a ^ b),
3053            BinOp::Shl => Value::Int(a << b),
3054            BinOp::Shr => Value::Int(a >> b),
3055            _ => return Err(RuntimeError::new("Invalid integer operation")),
3056        })
3057    }
3058
3059    fn float_binary_op(&self, a: f64, b: f64, op: &BinOp) -> Result<Value, RuntimeError> {
3060        Ok(match op {
3061            BinOp::Add => Value::Float(a + b),
3062            BinOp::Sub => Value::Float(a - b),
3063            BinOp::Mul => Value::Float(a * b),
3064            BinOp::Div => Value::Float(a / b),
3065            BinOp::Rem => Value::Float(a % b),
3066            BinOp::Pow => Value::Float(a.powf(b)),
3067            BinOp::Eq => Value::Bool((a - b).abs() < f64::EPSILON),
3068            BinOp::Ne => Value::Bool((a - b).abs() >= f64::EPSILON),
3069            BinOp::Lt => Value::Bool(a < b),
3070            BinOp::Le => Value::Bool(a <= b),
3071            BinOp::Gt => Value::Bool(a > b),
3072            BinOp::Ge => Value::Bool(a >= b),
3073            _ => return Err(RuntimeError::new("Invalid float operation")),
3074        })
3075    }
3076
3077    fn eval_unary(&mut self, op: &UnaryOp, expr: &Expr) -> Result<Value, RuntimeError> {
3078        let val = self.evaluate(expr)?;
3079        match (op, &val) {
3080            (UnaryOp::Neg, Value::Int(n)) => Ok(Value::Int(-n)),
3081            (UnaryOp::Neg, Value::Float(n)) => Ok(Value::Float(-n)),
3082            (UnaryOp::Not, Value::Bool(b)) => Ok(Value::Bool(!b)),
3083            (UnaryOp::Not, Value::Int(n)) => Ok(Value::Int(!n)),
3084            // Handle evidential values - unwrap, negate, rewrap
3085            (UnaryOp::Not, Value::Evidential { value, evidence }) => {
3086                // Negate the inner value
3087                match value.as_ref() {
3088                    Value::Bool(b) => Ok(Value::Evidential {
3089                        value: Box::new(Value::Bool(!b)),
3090                        evidence: evidence.clone(),
3091                    }),
3092                    other => {
3093                        let truthy = self.is_truthy(other);
3094                        Ok(Value::Evidential {
3095                            value: Box::new(Value::Bool(!truthy)),
3096                            evidence: evidence.clone(),
3097                        })
3098                    }
3099                }
3100            }
3101            // Handle string truthiness (non-empty = true)
3102            (UnaryOp::Not, Value::String(s)) => Ok(Value::Bool(s.is_empty())),
3103            // Handle array truthiness (non-empty = true)
3104            (UnaryOp::Not, Value::Array(arr)) => Ok(Value::Bool(arr.borrow().is_empty())),
3105            // Handle null - null is falsy
3106            (UnaryOp::Not, Value::Null) => Ok(Value::Bool(true)),
3107            (UnaryOp::Ref, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
3108            (UnaryOp::RefMut, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
3109            (UnaryOp::Deref, Value::Ref(r)) => Ok(r.borrow().clone()),
3110            (UnaryOp::Deref, Value::Struct { name, fields }) if name == "Rc" => {
3111                // Deref Rc to get inner value
3112                let borrowed = fields.borrow();
3113                if let Some(value) = borrowed.get("_value") {
3114                    Ok(value.clone())
3115                } else {
3116                    Err(RuntimeError::new("Rc has no value"))
3117                }
3118            }
3119            (UnaryOp::Deref, other) => {
3120                // Try to unwrap evidential/affective wrappers and deref
3121                let unwrapped = Self::unwrap_all(&val);
3122                if let Value::Ref(r) = &unwrapped {
3123                    return Ok(r.borrow().clone());
3124                }
3125                // For non-ref types in interpreted code, just return the value as-is
3126                // (dereferencing a copy type in Sigil is a no-op)
3127                Ok(unwrapped)
3128            }
3129            _ => Err(RuntimeError::new(format!("Invalid unary {:?} on {:?}", op, std::mem::discriminant(&val)))),
3130        }
3131    }
3132
3133    fn eval_call(&mut self, func_expr: &Expr, args: &[Expr]) -> Result<Value, RuntimeError> {
3134        // Check if func_expr is a path that might be a variant constructor or tuple struct
3135        if let Expr::Path(path) = func_expr {
3136            let qualified_name = path.segments.iter()
3137                .map(|s| s.ident.name.as_str())
3138                .collect::<Vec<_>>()
3139                .join("·");
3140
3141            // Handle Self(...) as tuple struct constructor
3142            if qualified_name == "Self" {
3143                if let Some(ref self_type) = self.current_self_type {
3144                    // Check if this type is a tuple struct - extract arity first to release borrow
3145                    let tuple_arity = if let Some(TypeDef::Struct(struct_def)) = self.types.get(self_type) {
3146                        if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
3147                            Some((self_type.clone(), field_types.len()))
3148                        } else {
3149                            None
3150                        }
3151                    } else {
3152                        None
3153                    };
3154
3155                    if let Some((type_name, expected_arity)) = tuple_arity {
3156                        // Now we can safely evaluate arguments
3157                        let arg_values: Vec<Value> = args
3158                            .iter()
3159                            .map(|a| self.evaluate(a))
3160                            .collect::<Result<_, _>>()?;
3161
3162                        if arg_values.len() != expected_arity {
3163                            return Err(RuntimeError::new(format!(
3164                                "Tuple struct {} expects {} fields, got {}",
3165                                type_name, expected_arity, arg_values.len()
3166                            )));
3167                        }
3168
3169                        // Create struct with numbered fields (0, 1, 2, ...)
3170                        let mut fields = HashMap::new();
3171                        for (i, value) in arg_values.into_iter().enumerate() {
3172                            fields.insert(i.to_string(), value);
3173                        }
3174                        return Ok(Value::Struct {
3175                            name: type_name,
3176                            fields: Rc::new(RefCell::new(fields)),
3177                        });
3178                    }
3179                }
3180            }
3181
3182            // Handle TypeName(...) as tuple struct constructor
3183            if path.segments.len() == 1 {
3184                let type_name = &path.segments[0].ident.name;
3185                // Extract arity first to release borrow
3186                let tuple_arity = if let Some(TypeDef::Struct(struct_def)) = self.types.get(type_name) {
3187                    if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
3188                        Some((type_name.clone(), field_types.len()))
3189                    } else {
3190                        None
3191                    }
3192                } else {
3193                    None
3194                };
3195
3196                if let Some((struct_name, expected_arity)) = tuple_arity {
3197                    let arg_values: Vec<Value> = args
3198                        .iter()
3199                        .map(|a| self.evaluate(a))
3200                        .collect::<Result<_, _>>()?;
3201
3202                    if arg_values.len() != expected_arity {
3203                        return Err(RuntimeError::new(format!(
3204                            "Tuple struct {} expects {} fields, got {}",
3205                            struct_name, expected_arity, arg_values.len()
3206                        )));
3207                    }
3208
3209                    let mut fields = HashMap::new();
3210                    for (i, value) in arg_values.into_iter().enumerate() {
3211                        fields.insert(i.to_string(), value);
3212                    }
3213                    return Ok(Value::Struct {
3214                        name: struct_name,
3215                        fields: Rc::new(RefCell::new(fields)),
3216                    });
3217                }
3218            }
3219
3220            // Handle Default::default() when current_self_type is set
3221            // This allows ..Default::default() to work in struct literals
3222            if qualified_name == "Default·default" && args.is_empty() {
3223                if let Some(type_name) = self.current_self_type.clone() {
3224                    // First check if type has impl Default with explicit default fn
3225                    let default_fn_name = format!("{}·default", type_name);
3226                    crate::sigil_debug!("DEBUG Default::default() looking for '{}', self_type='{}'", default_fn_name, type_name);
3227                    let func_clone = self.globals.borrow().get(&default_fn_name).map(|v| v.clone());
3228                    if let Some(Value::Function(f)) = func_clone {
3229                        crate::sigil_debug!("DEBUG Found function '{}', calling it", default_fn_name);
3230                        crate::sigil_debug!("DEBUG current_self_type before call: {:?}", self.current_self_type);
3231                        // Call the type's default implementation
3232                        let result = self.call_function(&f, vec![]);
3233                        crate::sigil_debug!("DEBUG Default call result: {:?}", result.as_ref().map(|v| self.format_value(v)).unwrap_or_else(|e| format!("ERR: {:?}", e)));
3234                        return result;
3235                    }
3236                    // Otherwise check for #[derive(Default)]
3237                    if let Some(struct_def) = self.default_structs.get(&type_name).cloned() {
3238                        let mut fields = HashMap::new();
3239                        if let StructFields::Named(field_defs) = &struct_def.fields {
3240                            for field in field_defs {
3241                                let default_val = if let Some(default_expr) = &field.default {
3242                                    self.evaluate(default_expr)?
3243                                } else {
3244                                    Value::Null
3245                                };
3246                                fields.insert(field.name.name.clone(), default_val);
3247                            }
3248                        }
3249                        return Ok(Value::Struct {
3250                            name: type_name,
3251                            fields: Rc::new(RefCell::new(fields)),
3252                        });
3253                    }
3254                }
3255            }
3256
3257            // Check for TypeName·default pattern
3258            if qualified_name.ends_with("·default") && args.is_empty() {
3259                let type_name = qualified_name.strip_suffix("·default").unwrap();
3260                // First check if type has impl Default with explicit default fn
3261                let default_fn_name = format!("{}·default", type_name);
3262                let func_clone = self.globals.borrow().get(&default_fn_name).map(|v| v.clone());
3263                if let Some(Value::Function(f)) = func_clone {
3264                    // Call the type's default implementation
3265                    return self.call_function(&f, vec![]);
3266                }
3267                // Otherwise check for #[derive(Default)]
3268                if let Some(struct_def) = self.default_structs.get(type_name).cloned() {
3269                    let mut fields = HashMap::new();
3270                    if let StructFields::Named(field_defs) = &struct_def.fields {
3271                        for field in field_defs {
3272                            let default_val = if let Some(default_expr) = &field.default {
3273                                self.evaluate(default_expr)?
3274                            } else {
3275                                // No default - use null for optional/uncertain types
3276                                Value::Null
3277                            };
3278                            fields.insert(field.name.name.clone(), default_val);
3279                        }
3280                    }
3281                    return Ok(Value::Struct {
3282                        name: type_name.to_string(),
3283                        fields: Rc::new(RefCell::new(fields)),
3284                    });
3285                }
3286            }
3287
3288            // Check variant constructors
3289            if let Some((enum_name, variant_name, arity)) = self.variant_constructors.get(&qualified_name).cloned() {
3290                let arg_values: Vec<Value> = args
3291                    .iter()
3292                    .map(|a| self.evaluate(a))
3293                    .collect::<Result<_, _>>()?;
3294
3295                if arg_values.len() != arity {
3296                    return Err(RuntimeError::new(format!(
3297                        "{} expects {} arguments, got {}",
3298                        qualified_name, arity, arg_values.len()
3299                    )));
3300                }
3301
3302                if arity == 0 {
3303                    return Ok(Value::Variant {
3304                        enum_name,
3305                        variant_name,
3306                        fields: None,
3307                    });
3308                } else {
3309                    if enum_name == "Item" {
3310                        crate::sigil_debug!("DEBUG creating Item::{} variant with {} fields", variant_name, arg_values.len());
3311                    }
3312                    return Ok(Value::Variant {
3313                        enum_name,
3314                        variant_name,
3315                        fields: Some(Rc::new(arg_values)),
3316                    });
3317                }
3318            }
3319
3320            // Check for built-in type constructors (Map::new, String::new, HashMap::new, etc.)
3321            let segments: Vec<&str> = path.segments.iter().map(|s| s.ident.name.as_str()).collect();
3322            match segments.as_slice() {
3323                ["Map", "new"] | ["HashMap", "new"] => {
3324                    // Create a new empty Map (represented as a struct with HashMap fields)
3325                    return Ok(Value::Struct {
3326                        name: "Map".to_string(),
3327                        fields: Rc::new(RefCell::new(HashMap::new())),
3328                    });
3329                }
3330                ["String", "new"] => {
3331                    return Ok(Value::String(Rc::new(String::new())));
3332                }
3333                ["Vec", "new"] | ["Array", "new"] => {
3334                    return Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))));
3335                }
3336                ["Box", "new"] => {
3337                    // Box::new(value) - just return the value (no heap allocation in interpreter)
3338                    if args.len() == 1 {
3339                        return self.evaluate(&args[0]);
3340                    }
3341                    return Err(RuntimeError::new("Box::new expects 1 argument"));
3342                }
3343                ["char", "from_u32"] => {
3344                    // char::from_u32(u32) -> Option<char>
3345                    if args.len() == 1 {
3346                        let arg = self.evaluate(&args[0])?;
3347                        let code = match arg {
3348                            Value::Int(i) => i as u32,
3349                            _ => return Err(RuntimeError::new("char::from_u32 expects u32")),
3350                        };
3351                        if let Some(c) = char::from_u32(code) {
3352                            // Return Some(char)
3353                            return Ok(Value::Variant {
3354                                enum_name: "Option".to_string(),
3355                                variant_name: "Some".to_string(),
3356                                fields: Some(Rc::new(vec![Value::Char(c)])),
3357                            });
3358                        } else {
3359                            // Return None
3360                            return Ok(Value::Variant {
3361                                enum_name: "Option".to_string(),
3362                                variant_name: "None".to_string(),
3363                                fields: None,
3364                            });
3365                        }
3366                    }
3367                    return Err(RuntimeError::new("char::from_u32 expects 1 argument"));
3368                }
3369                // Mutex::new - create a mutex wrapper around a value
3370                ["parking_lot", "Mutex", "new"] | ["std", "sync", "Mutex", "new"] | ["Mutex", "new"] => {
3371                    if args.len() == 1 {
3372                        let inner = self.evaluate(&args[0])?;
3373                        return Ok(Value::Struct {
3374                            name: "Mutex".to_string(),
3375                            fields: Rc::new(RefCell::new(HashMap::from([
3376                                ("__inner__".to_string(), inner),
3377                            ]))),
3378                        });
3379                    }
3380                    return Err(RuntimeError::new("Mutex::new expects 1 argument"));
3381                }
3382                // RwLock::new - same as Mutex for interpreter purposes
3383                ["parking_lot", "RwLock", "new"] | ["std", "sync", "RwLock", "new"] | ["RwLock", "new"] => {
3384                    if args.len() == 1 {
3385                        let inner = self.evaluate(&args[0])?;
3386                        return Ok(Value::Struct {
3387                            name: "RwLock".to_string(),
3388                            fields: Rc::new(RefCell::new(HashMap::from([
3389                                ("__inner__".to_string(), inner),
3390                            ]))),
3391                        });
3392                    }
3393                    return Err(RuntimeError::new("RwLock::new expects 1 argument"));
3394                }
3395                // Arc::new - just wrap the value (no real reference counting in interpreter)
3396                ["std", "sync", "Arc", "new"] | ["Arc", "new"] => {
3397                    if args.len() == 1 {
3398                        let inner = self.evaluate(&args[0])?;
3399                        return Ok(Value::Ref(Rc::new(RefCell::new(inner))));
3400                    }
3401                    return Err(RuntimeError::new("Arc::new expects 1 argument"));
3402                }
3403                // AtomicU64::new and similar atomics
3404                ["std", "sync", "atomic", "AtomicU64", "new"] | ["AtomicU64", "new"] => {
3405                    if args.len() == 1 {
3406                        let inner = self.evaluate(&args[0])?;
3407                        return Ok(Value::Struct {
3408                            name: "AtomicU64".to_string(),
3409                            fields: Rc::new(RefCell::new(HashMap::from([
3410                                ("__value__".to_string(), inner),
3411                            ]))),
3412                        });
3413                    }
3414                    return Err(RuntimeError::new("AtomicU64::new expects 1 argument"));
3415                }
3416                ["std", "sync", "atomic", "AtomicUsize", "new"] | ["AtomicUsize", "new"] => {
3417                    if args.len() == 1 {
3418                        let inner = self.evaluate(&args[0])?;
3419                        return Ok(Value::Struct {
3420                            name: "AtomicUsize".to_string(),
3421                            fields: Rc::new(RefCell::new(HashMap::from([
3422                                ("__value__".to_string(), inner),
3423                            ]))),
3424                        });
3425                    }
3426                    return Err(RuntimeError::new("AtomicUsize::new expects 1 argument"));
3427                }
3428                ["std", "sync", "atomic", "AtomicBool", "new"] | ["AtomicBool", "new"] => {
3429                    if args.len() == 1 {
3430                        let inner = self.evaluate(&args[0])?;
3431                        return Ok(Value::Struct {
3432                            name: "AtomicBool".to_string(),
3433                            fields: Rc::new(RefCell::new(HashMap::from([
3434                                ("__value__".to_string(), inner),
3435                            ]))),
3436                        });
3437                    }
3438                    return Err(RuntimeError::new("AtomicBool::new expects 1 argument"));
3439                }
3440                _ => {}
3441            }
3442        }
3443
3444        // If calling a qualified function (Type::method), set current_self_type
3445        let type_name_for_self = if let Expr::Path(path) = func_expr {
3446            if path.segments.len() >= 2 {
3447                // First segment is the type name
3448                let first = &path.segments[0].ident.name;
3449                // Check if it's a type name (exists in types registry)
3450                if self.types.contains_key(first) {
3451                    Some(first.clone())
3452                } else {
3453                    None
3454                }
3455            } else {
3456                None
3457            }
3458        } else {
3459            None
3460        };
3461
3462        let func = self.evaluate(func_expr)?;
3463
3464        // Track &mut path arguments for sync-back after function call
3465        // This enables proper mutable reference semantics where modifications persist
3466        let mut mut_ref_sync: Vec<(String, Rc<RefCell<Value>>)> = Vec::new();
3467
3468        let mut arg_values: Vec<Value> = Vec::new();
3469        for arg in args.iter() {
3470            let val = self.evaluate(arg)?;
3471
3472            // If this was a &mut path expression, track it for sync-back
3473            if let Expr::Unary { op: crate::ast::UnaryOp::RefMut, expr } = arg {
3474                if let Expr::Path(path) = expr.as_ref() {
3475                    if path.segments.len() == 1 {
3476                        let var_name = path.segments[0].ident.name.clone();
3477                        if let Value::Ref(r) = &val {
3478                            mut_ref_sync.push((var_name, r.clone()));
3479                        }
3480                    }
3481                }
3482            }
3483
3484            arg_values.push(val);
3485        }
3486
3487        // Set Self type if we're calling a type-associated function
3488        // Use clone instead of take to preserve for nested calls that don't set a type
3489        let old_self_type = self.current_self_type.clone();
3490        if let Some(type_name) = type_name_for_self {
3491            self.current_self_type = Some(type_name);
3492        }
3493
3494        let result = match func {
3495            Value::Function(f) => self.call_function(&f, arg_values),
3496            Value::BuiltIn(b) => self.call_builtin(&b, arg_values),
3497            // Handle constructor markers for unknown external types
3498            Value::Struct { ref name, .. } if name.starts_with("__constructor__") => {
3499                let actual_type = name.strip_prefix("__constructor__").unwrap();
3500                // Create an empty struct for the unknown type
3501                Ok(Value::Struct {
3502                    name: actual_type.to_string(),
3503                    fields: Rc::new(RefCell::new(HashMap::new())),
3504                })
3505            }
3506            _ => {
3507                crate::sigil_debug!("DEBUG Cannot call non-function: {:?}, expr: {:?}", func, func_expr);
3508                Err(RuntimeError::new("Cannot call non-function"))
3509            }
3510        };
3511
3512        // Sync mutable references back to original variables
3513        // This is what makes `fn foo(x: &mut T)` actually modify the caller's variable
3514        for (var_name, ref_val) in mut_ref_sync {
3515            let current_value = ref_val.borrow().clone();
3516            let _ = self.environment.borrow_mut().set(&var_name, current_value);
3517        }
3518
3519        // Restore old Self type
3520        self.current_self_type = old_self_type;
3521
3522        result
3523    }
3524
3525    pub fn call_function(
3526        &mut self,
3527        func: &Function,
3528        args: Vec<Value>,
3529    ) -> Result<Value, RuntimeError> {
3530        // Debug trace for relevant functions
3531        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")) {
3532            crate::sigil_debug!("DEBUG call_function: name={:?}, params={:?}", func.name, func.params);
3533            for (i, arg) in args.iter().enumerate() {
3534                crate::sigil_debug!("  arg[{}] = {:?}", i, arg);
3535            }
3536        }
3537        if args.len() != func.params.len() {
3538            return Err(RuntimeError::new(format!(
3539                "Expected {} arguments, got {} (func={:?}, params={:?})",
3540                func.params.len(),
3541                args.len(),
3542                func.name,
3543                func.params
3544            )));
3545        }
3546
3547        // Debug: trace calls to keyword_or_ident
3548        if func.params.iter().any(|p| p == "name") {
3549            for arg in &args {
3550                let unwrapped = Self::unwrap_all(arg);
3551                if let Value::String(s) = &unwrapped {
3552                    if s.len() <= 10 {
3553                        crate::sigil_debug!("DEBUG call_function(name='{}')", s);
3554                    }
3555                }
3556            }
3557        }
3558
3559        // Create new environment for function
3560        let env = Rc::new(RefCell::new(Environment::with_parent(func.closure.clone())));
3561
3562        // Bind parameters
3563        for (param, value) in func.params.iter().zip(args) {
3564            // Debug: trace path parameter binding
3565            if param == "path" {
3566                crate::sigil_debug!("DEBUG call_function func={:?} binding param 'path' = {:?}", func.name, value);
3567            }
3568            env.borrow_mut().define(param.clone(), value);
3569        }
3570
3571        // Execute function body
3572        let prev_env = self.environment.clone();
3573        self.environment = env;
3574
3575        let result = match self.evaluate(&func.body) {
3576            Ok(val) => Ok(val),
3577            Err(e) if e.message == "return" => {
3578                // Extract return value from stored location
3579                Ok(self.return_value.take().unwrap_or(Value::Null))
3580            }
3581            Err(e) => Err(e),
3582        };
3583
3584        self.environment = prev_env;
3585        result
3586    }
3587
3588    fn call_builtin(
3589        &mut self,
3590        builtin: &BuiltInFn,
3591        args: Vec<Value>,
3592    ) -> Result<Value, RuntimeError> {
3593        if let Some(arity) = builtin.arity {
3594            if args.len() != arity {
3595                return Err(RuntimeError::new(format!(
3596                    "{}() expects {} arguments, got {}",
3597                    builtin.name,
3598                    arity,
3599                    args.len()
3600                )));
3601            }
3602        }
3603        (builtin.func)(self, args)
3604    }
3605
3606    /// Await a value - if it's a future, resolve it; otherwise return as-is
3607    pub fn await_value(&mut self, value: Value) -> Result<Value, RuntimeError> {
3608        match value {
3609            Value::Future(fut) => {
3610                let mut fut_inner = fut.borrow_mut();
3611                self.poll_future(&mut fut_inner)
3612            }
3613            // Non-futures return immediately
3614            other => Ok(other),
3615        }
3616    }
3617
3618    /// Unwrap a Result or Option value with configurable error handling
3619    /// - propagate_errors: if true, return error on Err/None; if false, just unwrap
3620    /// - panic_on_error: if true, panic instead of returning error
3621    fn unwrap_result_or_option(
3622        &self,
3623        value: Value,
3624        propagate_errors: bool,
3625        panic_on_error: bool,
3626    ) -> Result<Value, RuntimeError> {
3627        // First, determine what kind of value we have and extract any inner value
3628        let (is_ok_or_some, is_err, is_none, inner_val) = match &value {
3629            Value::Struct { name, fields } if name == "Ok" || name == "Some" => {
3630                let borrowed = fields.borrow();
3631                let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
3632                (true, false, false, inner)
3633            }
3634            Value::Struct { name, fields } if name == "Err" => {
3635                let borrowed = fields.borrow();
3636                let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
3637                (false, true, false, inner)
3638            }
3639            Value::Struct { name, .. } if name == "None" => (false, false, true, None),
3640            _ => return Ok(value),
3641        };
3642
3643        if is_ok_or_some {
3644            Ok(inner_val.unwrap_or(value))
3645        } else if is_err {
3646            let msg = format!("Error: {:?}", inner_val);
3647            if panic_on_error {
3648                panic!("{}", msg);
3649            } else if propagate_errors {
3650                Err(RuntimeError::new(msg))
3651            } else {
3652                Ok(inner_val.unwrap_or(value))
3653            }
3654        } else if is_none {
3655            if panic_on_error {
3656                panic!("Unwrapped None");
3657            } else if propagate_errors {
3658                Err(RuntimeError::new("Unwrapped None".to_string()))
3659            } else {
3660                Ok(value)
3661            }
3662        } else {
3663            Ok(value)
3664        }
3665    }
3666
3667    /// Poll a future to completion
3668    fn poll_future(&mut self, fut: &mut FutureInner) -> Result<Value, RuntimeError> {
3669        // Check if already resolved
3670        match &fut.state {
3671            FutureState::Ready(v) => return Ok((**v).clone()),
3672            FutureState::Failed(e) => return Err(RuntimeError::new(e.clone())),
3673            _ => {}
3674        }
3675
3676        // Check if it's a timer future
3677        if let Some(complete_at) = fut.complete_at {
3678            if std::time::Instant::now() >= complete_at {
3679                fut.state = FutureState::Ready(Box::new(Value::Null));
3680                return Ok(Value::Null);
3681            } else {
3682                // Timer not complete - in interpreter, we just sleep
3683                let remaining = complete_at - std::time::Instant::now();
3684                std::thread::sleep(remaining);
3685                fut.state = FutureState::Ready(Box::new(Value::Null));
3686                return Ok(Value::Null);
3687            }
3688        }
3689
3690        // Execute computation if pending
3691        if let Some(computation) = fut.computation.take() {
3692            fut.state = FutureState::Running;
3693
3694            match computation {
3695                FutureComputation::Immediate(v) => {
3696                    fut.state = FutureState::Ready(v.clone());
3697                    Ok((*v).clone())
3698                }
3699                FutureComputation::Timer(duration) => {
3700                    // Sleep for the duration
3701                    std::thread::sleep(duration);
3702                    fut.state = FutureState::Ready(Box::new(Value::Null));
3703                    Ok(Value::Null)
3704                }
3705                FutureComputation::Lazy { func, args } => {
3706                    // Execute the function
3707                    match self.call_function(&func, args) {
3708                        Ok(result) => {
3709                            fut.state = FutureState::Ready(Box::new(result.clone()));
3710                            Ok(result)
3711                        }
3712                        Err(e) => {
3713                            fut.state = FutureState::Failed(e.message.clone());
3714                            Err(e)
3715                        }
3716                    }
3717                }
3718                FutureComputation::Join(futures) => {
3719                    // Await all futures and collect results
3720                    let mut results = Vec::new();
3721                    for f in futures {
3722                        let mut f_inner = f.borrow_mut();
3723                        results.push(self.poll_future(&mut f_inner)?);
3724                    }
3725                    let result = Value::Array(Rc::new(RefCell::new(results)));
3726                    fut.state = FutureState::Ready(Box::new(result.clone()));
3727                    Ok(result)
3728                }
3729                FutureComputation::Race(futures) => {
3730                    // Return first completed future
3731                    // In interpreter, just poll in order
3732                    for f in futures {
3733                        let f_inner = f.borrow_mut();
3734                        if matches!(f_inner.state, FutureState::Ready(_)) {
3735                            if let FutureState::Ready(v) = &f_inner.state {
3736                                fut.state = FutureState::Ready(v.clone());
3737                                return Ok((**v).clone());
3738                            }
3739                        }
3740                    }
3741                    // None ready, poll first one
3742                    Err(RuntimeError::new("No futures ready in race"))
3743                }
3744            }
3745        } else {
3746            // No computation - return current state
3747            match &fut.state {
3748                FutureState::Ready(v) => Ok((**v).clone()),
3749                FutureState::Failed(e) => Err(RuntimeError::new(e.clone())),
3750                _ => Err(RuntimeError::new("Future has no computation")),
3751            }
3752        }
3753    }
3754
3755    /// Create a new future from a value
3756    pub fn make_future_immediate(&self, value: Value) -> Value {
3757        Value::Future(Rc::new(RefCell::new(FutureInner {
3758            state: FutureState::Ready(Box::new(value)),
3759            computation: None,
3760            complete_at: None,
3761        })))
3762    }
3763
3764    /// Create a pending future with lazy computation
3765    pub fn make_future_lazy(&self, func: Rc<Function>, args: Vec<Value>) -> Value {
3766        Value::Future(Rc::new(RefCell::new(FutureInner {
3767            state: FutureState::Pending,
3768            computation: Some(FutureComputation::Lazy { func, args }),
3769            complete_at: None,
3770        })))
3771    }
3772
3773    /// Create a timer future
3774    pub fn make_future_timer(&self, duration: std::time::Duration) -> Value {
3775        Value::Future(Rc::new(RefCell::new(FutureInner {
3776            state: FutureState::Pending,
3777            computation: Some(FutureComputation::Timer(duration)),
3778            complete_at: Some(std::time::Instant::now() + duration),
3779        })))
3780    }
3781
3782    fn eval_array(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
3783        let values: Vec<Value> = elements
3784            .iter()
3785            .map(|e| self.evaluate(e))
3786            .collect::<Result<_, _>>()?;
3787        Ok(Value::Array(Rc::new(RefCell::new(values))))
3788    }
3789
3790    fn eval_tuple(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
3791        let values: Vec<Value> = elements
3792            .iter()
3793            .map(|e| self.evaluate(e))
3794            .collect::<Result<_, _>>()?;
3795        Ok(Value::Tuple(Rc::new(values)))
3796    }
3797
3798    fn eval_block(&mut self, block: &Block) -> Result<Value, RuntimeError> {
3799        let env = Rc::new(RefCell::new(Environment::with_parent(
3800            self.environment.clone(),
3801        )));
3802        let prev_env = self.environment.clone();
3803        self.environment = env;
3804
3805        let mut result = Value::Null;
3806
3807        for stmt in &block.stmts {
3808            match stmt {
3809                Stmt::Let { pattern, init, .. } => {
3810                    let value = match init {
3811                        Some(expr) => self.evaluate(expr)?,
3812                        None => Value::Null,
3813                    };
3814                    self.bind_pattern(pattern, value)?;
3815                }
3816                Stmt::LetElse { pattern, init, else_branch, .. } => {
3817                    let value = self.evaluate(init)?;
3818                    // Try to bind pattern, if it fails, execute else branch
3819                    if self.bind_pattern(pattern, value.clone()).is_err() {
3820                        return self.evaluate(else_branch);
3821                    }
3822                }
3823                Stmt::Expr(expr) => {
3824                    result = self.evaluate(expr)?;
3825                }
3826                Stmt::Semi(expr) => {
3827                    self.evaluate(expr)?;
3828                    result = Value::Null;
3829                }
3830                Stmt::Item(item) => {
3831                    self.execute_item(item)?;
3832                }
3833            }
3834        }
3835
3836        if let Some(expr) = &block.expr {
3837            result = self.evaluate(expr)?;
3838        }
3839
3840        // RAII: Call Drop::drop() on values going out of scope
3841        // Collect values to drop (avoid borrowing self during iteration)
3842        let values_to_drop: Vec<(String, Value)> = self.environment
3843            .borrow()
3844            .values
3845            .iter()
3846            .filter_map(|(name, value)| {
3847                if let Value::Struct { name: struct_name, .. } = value {
3848                    if self.drop_types.contains(struct_name) {
3849                        return Some((name.clone(), value.clone()));
3850                    }
3851                }
3852                None
3853            })
3854            .collect();
3855
3856        // Call drop on each value
3857        for (_var_name, value) in values_to_drop {
3858            if let Value::Struct { name: struct_name, .. } = &value {
3859                let drop_fn_name = format!("{}·drop", struct_name);
3860                // Clone the function out of globals to avoid borrow issues
3861                let drop_fn = self.globals.borrow().get(&drop_fn_name).map(|v| v.clone());
3862                if let Some(Value::Function(f)) = drop_fn {
3863                    // Call drop(self) - the value is passed as self
3864                    let _ = self.call_function(&f, vec![value.clone()]);
3865                }
3866            }
3867        }
3868
3869        self.environment = prev_env;
3870        Ok(result)
3871    }
3872
3873    fn bind_pattern(&mut self, pattern: &Pattern, value: Value) -> Result<(), RuntimeError> {
3874        match pattern {
3875            Pattern::Ident { name, .. } => {
3876                // Don't bind "_" - it's a wildcard in identifier form
3877                if name.name != "_" {
3878                    // Debug: trace path binding
3879                    if name.name == "path" {
3880                        crate::sigil_debug!("DEBUG bind_pattern: binding 'path' = {:?}", value);
3881                    }
3882                    self.environment
3883                        .borrow_mut()
3884                        .define(name.name.clone(), value);
3885                }
3886                Ok(())
3887            }
3888            Pattern::Tuple(patterns) => {
3889                // Unwrap evidential wrappers first
3890                let unwrapped = Self::unwrap_all(&value);
3891                crate::sigil_debug!("DEBUG bind_pattern Tuple: patterns.len()={}, value type={:?}",
3892                    patterns.len(), std::mem::discriminant(&unwrapped));
3893                match unwrapped {
3894                    Value::Tuple(values) => {
3895                        if patterns.len() != values.len() {
3896                            return Err(RuntimeError::new("Tuple pattern size mismatch"));
3897                        }
3898                        for (i, (p, v)) in patterns.iter().zip(values.iter()).enumerate() {
3899                            crate::sigil_debug!("DEBUG   binding tuple element {}: {:?} = {}", i, p, self.format_value(v));
3900                            self.bind_pattern(p, v.clone())?;
3901                        }
3902                        Ok(())
3903                    }
3904                    Value::Null => {
3905                        // Null value during iteration - treat as end of iteration (no binding)
3906                        Ok(())
3907                    }
3908                    Value::Array(arr) if arr.borrow().len() == patterns.len() => {
3909                        // Allow array to be destructured as tuple
3910                        let vals = arr.borrow();
3911                        for (p, v) in patterns.iter().zip(vals.iter()) {
3912                            self.bind_pattern(p, v.clone())?;
3913                        }
3914                        Ok(())
3915                    }
3916                    _ => Err(RuntimeError::new("Expected tuple"))
3917                }
3918            }
3919            Pattern::Wildcard => Ok(()),
3920            Pattern::Struct { path, fields, .. } => {
3921                // Unwrap any wrappers first
3922                let unwrapped = Self::unwrap_all(&value);
3923                // Bind each field from the struct or variant
3924                match &unwrapped {
3925                    Value::Struct { fields: struct_fields, .. } => {
3926                        for field_pat in fields {
3927                            let field_name = &field_pat.name.name;
3928                            // Get field value or default to Null for missing optional fields
3929                            let field_val = struct_fields.borrow().get(field_name).cloned().unwrap_or(Value::Null);
3930                            if let Some(pat) = &field_pat.pattern {
3931                                self.bind_pattern(pat, field_val)?;
3932                            } else {
3933                                // Shorthand: foo: foo - bind to same name
3934                                self.environment.borrow_mut().define(field_name.clone(), field_val);
3935                            }
3936                        }
3937                        Ok(())
3938                    }
3939                    Value::Variant { enum_name, variant_name, fields: variant_fields } => {
3940                        // Handle struct-like enum variants (e.g., IrPattern::Ident { name, .. })
3941                        let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
3942                        if pattern_variant == variant_name || path.segments.iter().any(|s| s.ident.name == *variant_name) {
3943                            // Variant fields are stored as a Vec, but we need to map by name
3944                            // For struct-like variants, the fields should be a Struct value with field names
3945                            if let Some(inner_fields) = variant_fields {
3946                                if inner_fields.len() == 1 {
3947                                    // Single wrapped struct with named fields
3948                                    if let Value::Struct { fields: inner_struct, .. } = &inner_fields[0] {
3949                                        for field_pat in fields {
3950                                            let field_name = &field_pat.name.name;
3951                                            // Default to Null for missing optional fields
3952                                            let field_val = inner_struct.borrow().get(field_name).cloned().unwrap_or(Value::Null);
3953                                            if let Some(pat) = &field_pat.pattern {
3954                                                self.bind_pattern(pat, field_val)?;
3955                                            } else {
3956                                                self.environment.borrow_mut().define(field_name.clone(), field_val);
3957                                            }
3958                                        }
3959                                        return Ok(());
3960                                    }
3961                                }
3962                                // Named field lookup from variant's field map
3963                                // Variants store struct fields as named HashMap inside the variant
3964                                for field_pat in fields {
3965                                    let field_name = &field_pat.name.name;
3966                                    // Look for a field with matching name in variant fields
3967                                    // Variant fields might be stored in order or as a struct
3968                                    // For now, search by name if we can find it
3969                                    let field_val = inner_fields.iter().find_map(|f| {
3970                                        if let Value::Struct { fields: fs, .. } = f {
3971                                            fs.borrow().get(field_name).cloned()
3972                                        } else {
3973                                            None
3974                                        }
3975                                    });
3976                                    if let Some(val) = field_val {
3977                                        if let Some(pat) = &field_pat.pattern {
3978                                            self.bind_pattern(pat, val)?;
3979                                        } else {
3980                                            self.environment.borrow_mut().define(field_name.clone(), val);
3981                                        }
3982                                    }
3983                                }
3984                            }
3985                            Ok(())
3986                        } else {
3987                            crate::sigil_debug!("DEBUG variant name mismatch: pattern={}, actual={}", pattern_variant, variant_name);
3988                            Err(RuntimeError::new(format!(
3989                                "Variant name mismatch: expected {} but got {}::{}",
3990                                pattern_variant, enum_name, variant_name
3991                            )))
3992                        }
3993                    }
3994                    _ => {
3995                        crate::sigil_debug!("DEBUG struct pattern bind: expected struct/variant but got {:?}", std::mem::discriminant(&unwrapped));
3996                        Err(RuntimeError::new("Expected struct or variant value for struct pattern"))
3997                    }
3998                }
3999            }
4000            Pattern::Path(_path) => {
4001                // Path patterns like Result::Ok - unit variant patterns
4002                // Don't bind anything
4003                Ok(())
4004            }
4005            Pattern::TupleStruct { path, fields } => {
4006                // Enum variant with fields: Result::Ok(value)
4007                // Unwrap any refs first
4008                let unwrapped = Self::unwrap_all(&value);
4009                let path_str = path.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("::");
4010                crate::sigil_debug!("DEBUG bind_pattern TupleStruct: path={}, value type={:?}",
4011                    path_str,
4012                    std::mem::discriminant(&unwrapped));
4013                if let Value::Variant { variant_name, fields: variant_fields, enum_name } = &unwrapped {
4014                    crate::sigil_debug!("DEBUG   Variant {}::{}, fields={}", enum_name, variant_name,
4015                        if variant_fields.is_some() { format!("Some(len={})", variant_fields.as_ref().unwrap().len()) } else { "None".to_string() });
4016                    let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4017                    if pattern_variant == variant_name {
4018                        // Unwrap fields and bind
4019                        if let Some(inner_fields) = variant_fields {
4020                            if fields.len() == 1 && inner_fields.len() == 1 {
4021                                self.bind_pattern(&fields[0], inner_fields[0].clone())?;
4022                            } else {
4023                                for (pat, val) in fields.iter().zip(inner_fields.iter()) {
4024                                    self.bind_pattern(pat, val.clone())?;
4025                                }
4026                            }
4027                        } else if !fields.is_empty() {
4028                            // Pattern expects fields but variant has none
4029                            crate::sigil_debug!("DEBUG TupleStruct: pattern expects {} fields but variant has none", fields.len());
4030                        }
4031                    }
4032                    Ok(())
4033                } else {
4034                    // Maybe it's a regular tuple being matched
4035                    if let Value::Tuple(tuple_vals) = &value {
4036                        for (pat, val) in fields.iter().zip(tuple_vals.iter()) {
4037                            self.bind_pattern(pat, val.clone())?;
4038                        }
4039                        Ok(())
4040                    } else {
4041                        Err(RuntimeError::new("Expected variant or tuple for tuple struct pattern"))
4042                    }
4043                }
4044            }
4045            Pattern::Literal(_) => {
4046                // Literal patterns don't bind anything, just match
4047                Ok(())
4048            }
4049            Pattern::Rest => {
4050                // Rest pattern .. - just ignores rest of values
4051                Ok(())
4052            }
4053            Pattern::Range { .. } => {
4054                // Range patterns like 'a'..='z' don't bind anything
4055                Ok(())
4056            }
4057            Pattern::Or(patterns) => {
4058                // Or patterns - find the matching pattern and bind its variables
4059                for p in patterns {
4060                    if self.pattern_matches(p, &value)? {
4061                        return self.bind_pattern(p, value.clone());
4062                    }
4063                }
4064                // No pattern matched - this shouldn't happen if pattern_matches returned true earlier
4065                Err(RuntimeError::new("Or pattern didn't match any alternative"))
4066            }
4067            _ => Err(RuntimeError::new(format!("Unsupported pattern: {:?}", pattern))),
4068        }
4069    }
4070
4071    fn eval_if(
4072        &mut self,
4073        condition: &Expr,
4074        then_branch: &Block,
4075        else_branch: &Option<Box<Expr>>,
4076    ) -> Result<Value, RuntimeError> {
4077        let cond = self.evaluate(condition)?;
4078        if self.is_truthy(&cond) {
4079            self.eval_block(then_branch)
4080        } else if let Some(else_expr) = else_branch {
4081            self.evaluate(else_expr)
4082        } else {
4083            Ok(Value::Null)
4084        }
4085    }
4086
4087    fn eval_match(&mut self, expr: &Expr, arms: &[MatchArm]) -> Result<Value, RuntimeError> {
4088        let value = self.evaluate(expr)?;
4089
4090        // Debug all string matches to find keyword_or_ident
4091        let unwrapped = Self::unwrap_all(&value);
4092        if let Value::String(s) = &unwrapped {
4093            if s.len() <= 10 {
4094                crate::sigil_debug!("DEBUG eval_match: string='{}', arms={}", s, arms.len());
4095            }
4096        }
4097
4098        for arm in arms {
4099            if self.pattern_matches(&arm.pattern, &value)? {
4100                // Create new environment for pattern bindings
4101                let env = Rc::new(RefCell::new(Environment::with_parent(
4102                    self.environment.clone(),
4103                )));
4104                let prev_env = self.environment.clone();
4105                self.environment = env;
4106
4107                // Bind pattern variables FIRST (before evaluating guard)
4108                // This is necessary for guards like `?fields if !fields.is_empty()`
4109                if let Err(e) = self.bind_pattern(&arm.pattern, value.clone()) {
4110                    self.environment = prev_env;
4111                    return Err(e);
4112                }
4113
4114                // Check guard if present (pattern vars are now in scope)
4115                if let Some(guard) = &arm.guard {
4116                    let guard_val = self.evaluate(guard)?;
4117                    if !self.is_truthy(&guard_val) {
4118                        // Guard failed - restore environment and try next arm
4119                        self.environment = prev_env;
4120                        continue;
4121                    }
4122                }
4123
4124                // Pattern matched and guard passed - evaluate body
4125                let result = self.evaluate(&arm.body);
4126
4127                self.environment = prev_env;
4128                return result;
4129            }
4130        }
4131
4132        // Debug: show what value we're trying to match with discriminant
4133        crate::sigil_debug!("DEBUG No matching pattern for value: {} (discriminant: {:?})",
4134            self.format_value(&value), std::mem::discriminant(&value));
4135        // Also show the arms
4136        for (i, arm) in arms.iter().enumerate() {
4137            crate::sigil_debug!("DEBUG   arm {}: {:?}", i, arm.pattern);
4138        }
4139        Err(RuntimeError::new(format!("No matching pattern for {}", self.format_value(&value))))
4140    }
4141
4142    fn pattern_matches(&mut self, pattern: &Pattern, value: &Value) -> Result<bool, RuntimeError> {
4143        // Unwrap evidential/affective/ref wrappers from value
4144        let value = Self::unwrap_all(value);
4145
4146        // Debug string pattern matching
4147        if let Value::String(s) = &value {
4148            if **s == "fn" {
4149                crate::sigil_debug!("DEBUG pattern_matches: value='fn', pattern={:?}", pattern);
4150            }
4151        }
4152
4153        match (pattern, &value) {
4154            (Pattern::Wildcard, _) => Ok(true),
4155            // Pattern::Ident with evidentiality - ?g matches Some/non-null, !g matches Known values
4156            (Pattern::Ident { evidentiality: Some(Evidentiality::Uncertain), name, .. }, val) => {
4157                // ?g pattern should match non-null values (i.e., Option::Some)
4158                let matches = match val {
4159                    Value::Null => false,
4160                    Value::Variant { variant_name, .. } if variant_name == "None" => false,
4161                    _ => true,
4162                };
4163                crate::sigil_debug!("DEBUG pattern_matches ?{}: value={} => {}", name.name, self.format_value(val), matches);
4164                Ok(matches)
4165            }
4166            (Pattern::Ident { .. }, _) => Ok(true),
4167            (Pattern::Literal(lit), val) => {
4168                let lit_val = self.eval_literal(lit)?;
4169                let result = self.values_equal(&lit_val, val);
4170                // Debug null pattern matching specifically
4171                if matches!(lit, Literal::Null) || matches!(val, Value::Null) {
4172                    crate::sigil_debug!("DEBUG literal pattern: lit={:?}, lit_val={}, val={}, result={}",
4173                        lit, self.format_value(&lit_val), self.format_value(val), result);
4174                }
4175                Ok(result)
4176            }
4177            (Pattern::Tuple(patterns), Value::Tuple(values)) => {
4178                if patterns.len() != values.len() {
4179                    return Ok(false);
4180                }
4181                for (p, v) in patterns.iter().zip(values.iter()) {
4182                    if !self.pattern_matches(p, v)? {
4183                        return Ok(false);
4184                    }
4185                }
4186                Ok(true)
4187            }
4188            // Path pattern - matches unit enum variants like CompileMode::Compile
4189            (Pattern::Path(path), Value::Variant { variant_name, fields, .. }) => {
4190                let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4191                // Match if variant name matches and has no fields
4192                Ok(pattern_variant == variant_name && fields.is_none())
4193            }
4194            // TupleStruct pattern - matches enum variants with data like Result::Ok(x)
4195            (Pattern::TupleStruct { path, fields: pat_fields }, Value::Variant { variant_name, fields, .. }) => {
4196                let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4197                if pattern_variant != variant_name {
4198                    return Ok(false);
4199                }
4200                // Match field patterns
4201                if let Some(variant_fields) = fields {
4202                    if pat_fields.len() != variant_fields.len() {
4203                        return Ok(false);
4204                    }
4205                    for (p, v) in pat_fields.iter().zip(variant_fields.iter()) {
4206                        if !self.pattern_matches(p, v)? {
4207                            return Ok(false);
4208                        }
4209                    }
4210                    Ok(true)
4211                } else {
4212                    // Variant has no fields but pattern expects some
4213                    Ok(pat_fields.is_empty())
4214                }
4215            }
4216            // Struct pattern - matches struct values
4217            (Pattern::Struct { path, fields: pat_fields, rest }, Value::Struct { name: struct_name, fields: struct_fields }) => {
4218                let pattern_name = path.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("::");
4219                if pattern_name != *struct_name {
4220                    return Ok(false);
4221                }
4222                // Check each field in the pattern
4223                let borrowed = struct_fields.borrow();
4224                for field_pat in pat_fields {
4225                    let field_name = &field_pat.name.name;
4226                    if let Some(field_val) = borrowed.get(field_name) {
4227                        if let Some(sub_pat) = &field_pat.pattern {
4228                            if !self.pattern_matches(sub_pat, field_val)? {
4229                                return Ok(false);
4230                            }
4231                        }
4232                        // If no sub-pattern, any value matches
4233                    } else if !rest {
4234                        // Field not found and no rest pattern
4235                        return Ok(false);
4236                    }
4237                }
4238                Ok(true)
4239            }
4240            // Struct pattern - matches struct-like enum variants (e.g., TypeExpr::Evidential { inner, ... })
4241            (Pattern::Struct { path, fields: pat_fields, rest }, Value::Variant { variant_name, fields: variant_fields, .. }) => {
4242                let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4243                if pattern_variant != variant_name {
4244                    return Ok(false);
4245                }
4246                // Struct-like variants store fields as a single wrapped Struct value
4247                if let Some(inner_fields) = variant_fields {
4248                    if inner_fields.len() == 1 {
4249                        if let Value::Struct { fields: inner_struct, .. } = &inner_fields[0] {
4250                            let borrowed = inner_struct.borrow();
4251                            for field_pat in pat_fields {
4252                                let field_name = &field_pat.name.name;
4253                                if let Some(field_val) = borrowed.get(field_name) {
4254                                    if let Some(sub_pat) = &field_pat.pattern {
4255                                        if !self.pattern_matches(sub_pat, field_val)? {
4256                                            return Ok(false);
4257                                        }
4258                                    }
4259                                } else if !rest {
4260                                    return Ok(false);
4261                                }
4262                            }
4263                            return Ok(true);
4264                        }
4265                    }
4266                }
4267                // No fields or structure doesn't match
4268                Ok(pat_fields.is_empty() || *rest)
4269            }
4270            // Or pattern - match if any sub-pattern matches
4271            (Pattern::Or(patterns), val) => {
4272                for p in patterns {
4273                    if self.pattern_matches(p, val)? {
4274                        return Ok(true);
4275                    }
4276                }
4277                Ok(false)
4278            }
4279            // Rest pattern always matches
4280            (Pattern::Rest, _) => Ok(true),
4281            // Range pattern: 'a'..='z' or 0..=9
4282            (Pattern::Range { start, end, inclusive }, val) => {
4283                // Helper to extract char from pattern
4284                let extract_char = |pat: &Option<Box<Pattern>>| -> Option<char> {
4285                    match pat {
4286                        Some(p) => match p.as_ref() {
4287                            Pattern::Literal(Literal::Char(c)) => Some(*c),
4288                            _ => None,
4289                        },
4290                        None => None,
4291                    }
4292                };
4293                // Helper to extract int from pattern
4294                let extract_int = |pat: &Option<Box<Pattern>>| -> Option<i64> {
4295                    match pat {
4296                        Some(p) => match p.as_ref() {
4297                            Pattern::Literal(Literal::Int { value, .. }) => value.parse().ok(),
4298                            _ => None,
4299                        },
4300                        None => None,
4301                    }
4302                };
4303
4304                match val {
4305                    Value::Char(c) => {
4306                        let start_val = extract_char(start);
4307                        let end_val = extract_char(end);
4308                        let in_range = match (start_val, end_val, *inclusive) {
4309                            (Some(s), Some(e), true) => *c >= s && *c <= e,
4310                            (Some(s), Some(e), false) => *c >= s && *c < e,
4311                            (Some(s), None, _) => *c >= s,
4312                            (None, Some(e), true) => *c <= e,
4313                            (None, Some(e), false) => *c < e,
4314                            (None, None, _) => true,
4315                        };
4316                        Ok(in_range)
4317                    }
4318                    Value::Int(i) => {
4319                        let start_val = extract_int(start);
4320                        let end_val = extract_int(end);
4321                        let in_range = match (start_val, end_val, *inclusive) {
4322                            (Some(s), Some(e), true) => *i >= s && *i <= e,
4323                            (Some(s), Some(e), false) => *i >= s && *i < e,
4324                            (Some(s), None, _) => *i >= s,
4325                            (None, Some(e), true) => *i <= e,
4326                            (None, Some(e), false) => *i < e,
4327                            (None, None, _) => true,
4328                        };
4329                        Ok(in_range)
4330                    }
4331                    _ => Ok(false),
4332                }
4333            }
4334            // Literal matching against string or char
4335            (Pattern::Literal(Literal::String(s)), Value::String(vs)) => {
4336                Ok(s == vs.as_str())
4337            }
4338            (Pattern::Literal(Literal::Char(c)), Value::Char(vc)) => {
4339                Ok(c == vc)
4340            }
4341            _ => Ok(false),
4342        }
4343    }
4344
4345    fn values_equal(&self, a: &Value, b: &Value) -> bool {
4346        // Unwrap any Ref wrappers before comparison
4347        let a_unwrapped = match a {
4348            Value::Ref(r) => r.borrow().clone(),
4349            _ => a.clone(),
4350        };
4351        let b_unwrapped = match b {
4352            Value::Ref(r) => r.borrow().clone(),
4353            _ => b.clone(),
4354        };
4355        match (&a_unwrapped, &b_unwrapped) {
4356            (Value::Null, Value::Null) => true,
4357            (Value::Bool(a), Value::Bool(b)) => a == b,
4358            (Value::Int(a), Value::Int(b)) => a == b,
4359            (Value::Float(a), Value::Float(b)) => (a - b).abs() < f64::EPSILON,
4360            (Value::String(a), Value::String(b)) => {
4361                let result = **a == **b;
4362                // Debug ALL short string comparisons
4363                if a.len() <= 5 && b.len() <= 5 {
4364                    crate::sigil_debug!("DEBUG values_equal: '{}' == '{}' -> {}", a, b, result);
4365                }
4366                result
4367            }
4368            (Value::Char(a), Value::Char(b)) => a == b,
4369            _ => false,
4370        }
4371    }
4372
4373    fn eval_for(
4374        &mut self,
4375        pattern: &Pattern,
4376        iter: &Expr,
4377        body: &Block,
4378    ) -> Result<Value, RuntimeError> {
4379        let iterable_raw = self.evaluate(iter)?;
4380        let iterable = Self::unwrap_all(&iterable_raw);
4381        let items = match iterable {
4382            Value::Array(arr) => arr.borrow().clone(),
4383            Value::Tuple(t) => (*t).clone(),
4384            Value::String(s) => s.chars().map(Value::Char).collect(),
4385            Value::Map(m) => {
4386                // Iterate over key-value pairs as tuples
4387                m.borrow()
4388                    .iter()
4389                    .map(|(k, v)| {
4390                        Value::Tuple(Rc::new(vec![
4391                            Value::String(Rc::new(k.clone())),
4392                            v.clone(),
4393                        ]))
4394                    })
4395                    .collect()
4396            }
4397            Value::Variant { fields: Some(f), .. } => (*f).clone(),
4398            _ => return Err(RuntimeError::new(format!("Cannot iterate over non-iterable: {:?}", iterable_raw))),
4399        };
4400
4401        let mut result = Value::Null;
4402        for item in items {
4403            let env = Rc::new(RefCell::new(Environment::with_parent(
4404                self.environment.clone(),
4405            )));
4406            let prev_env = self.environment.clone();
4407            self.environment = env;
4408
4409            self.bind_pattern(pattern, item)?;
4410
4411            match self.eval_block(body) {
4412                Ok(val) => result = val,
4413                Err(e) if e.message == "break" => {
4414                    self.environment = prev_env;
4415                    break;
4416                }
4417                Err(e) if e.message == "continue" => {
4418                    self.environment = prev_env;
4419                    continue;
4420                }
4421                Err(e) => {
4422                    self.environment = prev_env;
4423                    return Err(e);
4424                }
4425            }
4426
4427            self.environment = prev_env;
4428        }
4429
4430        Ok(result)
4431    }
4432
4433    fn eval_while(&mut self, condition: &Expr, body: &Block) -> Result<Value, RuntimeError> {
4434        let mut result = Value::Null;
4435        loop {
4436            let cond = self.evaluate(condition)?;
4437            if !self.is_truthy(&cond) {
4438                break;
4439            }
4440
4441            match self.eval_block(body) {
4442                Ok(val) => result = val,
4443                Err(e) if e.message == "break" => break,
4444                Err(e) if e.message == "continue" => continue,
4445                Err(e) => return Err(e),
4446            }
4447        }
4448        Ok(result)
4449    }
4450
4451    fn eval_loop(&mut self, body: &Block) -> Result<Value, RuntimeError> {
4452        loop {
4453            match self.eval_block(body) {
4454                Ok(_) => {}
4455                Err(e) if e.message == "break" => break,
4456                Err(e) if e.message == "continue" => continue,
4457                Err(e) => return Err(e),
4458            }
4459        }
4460        Ok(Value::Null)
4461    }
4462
4463    fn eval_return(&mut self, value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
4464        let val = match value {
4465            Some(expr) => self.evaluate(expr)?,
4466            None => Value::Null,
4467        };
4468        // Store return value for call_function to retrieve
4469        self.return_value = Some(val);
4470        Err(RuntimeError::new("return"))
4471    }
4472
4473    fn eval_break(&mut self, _value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
4474        // TODO: break with value for loop expressions
4475        Err(RuntimeError::new("break"))
4476    }
4477
4478    fn eval_index(&mut self, expr: &Expr, index: &Expr) -> Result<Value, RuntimeError> {
4479        let collection = self.evaluate(expr)?;
4480
4481        // Dereference Ref values to get the underlying collection
4482        let collection = match collection {
4483            Value::Ref(r) => r.borrow().clone(),
4484            other => other,
4485        };
4486
4487        // Handle range slicing before evaluating the index
4488        if let Expr::Range { start, end, inclusive } = index {
4489            let start_val = match start {
4490                Some(e) => match self.evaluate(e)? {
4491                    Value::Int(n) => n as usize,
4492                    _ => return Err(RuntimeError::new("Slice start must be an integer")),
4493                },
4494                None => 0,
4495            };
4496
4497            return match &collection {
4498                Value::Array(arr) => {
4499                    let arr = arr.borrow();
4500                    let len = arr.len();
4501                    let end_val = match end {
4502                        Some(e) => match self.evaluate(e)? {
4503                            Value::Int(n) => {
4504                                let n = n as usize;
4505                                if *inclusive { n + 1 } else { n }
4506                            },
4507                            _ => return Err(RuntimeError::new("Slice end must be an integer")),
4508                        },
4509                        None => len,  // Open-ended range: slice to end
4510                    };
4511                    let end_val = end_val.min(len);
4512                    let start_val = start_val.min(len);
4513                    let sliced: Vec<Value> = arr[start_val..end_val].to_vec();
4514                    Ok(Value::Array(Rc::new(RefCell::new(sliced))))
4515                }
4516                Value::String(s) => {
4517                    let len = s.len();
4518                    let end_val = match end {
4519                        Some(e) => match self.evaluate(e)? {
4520                            Value::Int(n) => {
4521                                let n = n as usize;
4522                                if *inclusive { n + 1 } else { n }
4523                            },
4524                            _ => return Err(RuntimeError::new("Slice end must be an integer")),
4525                        },
4526                        None => len,  // Open-ended range: slice to end
4527                    };
4528                    let end_val = end_val.min(len);
4529                    let start_val = start_val.min(len);
4530                    // Use byte slicing for consistency with char_at
4531                    let sliced = &s[start_val..end_val];
4532                    Ok(Value::String(Rc::new(sliced.to_string())))
4533                }
4534                _ => Err(RuntimeError::new("Cannot slice this type")),
4535            };
4536        }
4537
4538        let idx = self.evaluate(index)?;
4539
4540        match (collection, idx) {
4541            (Value::Array(arr), Value::Int(i)) => {
4542                let arr = arr.borrow();
4543                let i = if i < 0 { arr.len() as i64 + i } else { i } as usize;
4544                let result = arr.get(i)
4545                    .cloned()
4546                    .ok_or_else(|| RuntimeError::new("Index out of bounds"));
4547                if let Ok(ref v) = result {
4548                    crate::sigil_debug!("DEBUG eval_index: arr[{}] = {:?}", i, std::mem::discriminant(v));
4549                }
4550                result
4551            }
4552            (Value::Tuple(t), Value::Int(i)) => {
4553                let i = if i < 0 { t.len() as i64 + i } else { i } as usize;
4554                t.get(i)
4555                    .cloned()
4556                    .ok_or_else(|| RuntimeError::new("Index out of bounds"))
4557            }
4558            (Value::String(s), Value::Int(i)) => {
4559                let i = if i < 0 { s.len() as i64 + i } else { i } as usize;
4560                s.chars()
4561                    .nth(i)
4562                    .map(Value::Char)
4563                    .ok_or_else(|| RuntimeError::new("Index out of bounds"))
4564            }
4565            // Handle open-ended range slicing (from eval_range returning tuple)
4566            (Value::Array(arr), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
4567                let arr = arr.borrow();
4568                let start = match &range_tuple[0] {
4569                    Value::Int(n) => *n as usize,
4570                    _ => return Err(RuntimeError::new("Range start must be integer")),
4571                };
4572                let end = match &range_tuple[1] {
4573                    Value::Null => arr.len(),  // Open end - slice to end
4574                    Value::Int(n) => *n as usize,
4575                    _ => return Err(RuntimeError::new("Range end must be integer or None")),
4576                };
4577                let start = start.min(arr.len());
4578                let end = end.min(arr.len());
4579                let sliced: Vec<Value> = arr[start..end].to_vec();
4580                Ok(Value::Array(Rc::new(RefCell::new(sliced))))
4581            }
4582            (Value::String(s), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
4583                let start = match &range_tuple[0] {
4584                    Value::Int(n) => *n as usize,
4585                    _ => return Err(RuntimeError::new("Range start must be integer")),
4586                };
4587                let end = match &range_tuple[1] {
4588                    Value::Null => s.len(),  // Open end - slice to end
4589                    Value::Int(n) => *n as usize,
4590                    _ => return Err(RuntimeError::new("Range end must be integer or None")),
4591                };
4592                let start = start.min(s.len());
4593                let end = end.min(s.len());
4594                let sliced = &s[start..end];
4595                Ok(Value::String(Rc::new(sliced.to_string())))
4596            }
4597            (coll, idx) => {
4598                crate::sigil_debug!("DEBUG Cannot index: collection={:?}, index={:?}",
4599                    std::mem::discriminant(&coll), std::mem::discriminant(&idx));
4600                Err(RuntimeError::new("Cannot index"))
4601            }
4602        }
4603    }
4604
4605    fn eval_field(&mut self, expr: &Expr, field: &Ident) -> Result<Value, RuntimeError> {
4606        if field.name == "items" {
4607            crate::sigil_debug!("DEBUG eval_field: accessing .items on expr={:?}", expr);
4608        }
4609        // Debug evidence field access
4610        if field.name == "evidence" {
4611            crate::sigil_debug!("DEBUG eval_field: accessing .evidence");
4612        }
4613        let value = self.evaluate(expr)?;
4614        if field.name == "items" {
4615            crate::sigil_debug!("DEBUG eval_field: .items receiver value={:?}", std::mem::discriminant(&value));
4616        }
4617        if field.name == "evidence" {
4618            crate::sigil_debug!("DEBUG eval_field: .evidence receiver value type={:?}", std::mem::discriminant(&value));
4619        }
4620        // Helper to get field from a value
4621        fn get_field(val: &Value, field_name: &str) -> Result<Value, RuntimeError> {
4622            // Debug all field access on IrPattern
4623            if field_name == "evidence" {
4624                crate::sigil_debug!("DEBUG get_field 'evidence' on value type: {:?}", std::mem::discriminant(val));
4625            }
4626            match val {
4627                Value::Struct { name, fields } => {
4628                    let field_val = fields.borrow().get(field_name).cloned();
4629                    if field_val.is_none() && field_name == "path" {
4630                        crate::sigil_debug!("DEBUG Unknown field 'path': struct={}, available={:?}", name, fields.borrow().keys().collect::<Vec<_>>());
4631                    }
4632                    // Debug evidence field access
4633                    if field_name == "evidence" || name.contains("IrPattern") {
4634                        crate::sigil_debug!("DEBUG get_field on Struct: name={}, field={}, available={:?}, found={}",
4635                            name, field_name, fields.borrow().keys().collect::<Vec<_>>(), field_val.is_some());
4636                    }
4637                    // Fallback for unknown fields on external types: return null
4638                    match field_val {
4639                        Some(v) => Ok(v),
4640                        None => {
4641                            crate::sigil_warn!("WARN: Unknown field '{}' on '{}' - returning null", field_name, name);
4642                            Ok(Value::Null)
4643                        }
4644                    }
4645                }
4646                Value::Tuple(t) => {
4647                    // Tuple field access like .0, .1
4648                    let idx: usize = field_name
4649                        .parse()
4650                        .map_err(|_| RuntimeError::new("Invalid tuple index"))?;
4651                    t.get(idx)
4652                        .cloned()
4653                        .ok_or_else(|| RuntimeError::new("Tuple index out of bounds"))
4654                }
4655                Value::Ref(r) => {
4656                    // Dereference and access field on inner value
4657                    get_field(&r.borrow(), field_name)
4658                }
4659                Value::Evidential { value, .. } => {
4660                    // Unwrap evidential wrapper and access field
4661                    get_field(value, field_name)
4662                }
4663                Value::Affective { value, .. } => {
4664                    // Unwrap affective wrapper and access field
4665                    get_field(value, field_name)
4666                }
4667                Value::Variant { fields: variant_fields, .. } => {
4668                    // Handle struct-like enum variants (e.g., IrPattern::Ident { name, evidence, .. })
4669                    // Variant fields may be stored as a Struct value or as positional values
4670                    if let Some(inner_fields) = variant_fields {
4671                        // Try to find a Struct value that contains the field
4672                        for f in inner_fields.iter() {
4673                            if let Value::Struct { fields: struct_fields, .. } = f {
4674                                if let Some(field_val) = struct_fields.borrow().get(field_name).cloned() {
4675                                    return Ok(field_val);
4676                                }
4677                            }
4678                        }
4679                        // Field not found in any struct - return Null for optional fields
4680                        Ok(Value::Null)
4681                    } else {
4682                        // No fields in variant
4683                        Ok(Value::Null)
4684                    }
4685                }
4686                other => {
4687                    // Fallback for field access on non-struct types: return null
4688                    crate::sigil_warn!("WARN: Cannot access field '{}' on non-struct - returning null", field_name);
4689                    Ok(Value::Null)
4690                }
4691            }
4692        }
4693        get_field(&value, &field.name)
4694    }
4695
4696    // Helper: Extract the root variable name from a method chain
4697    fn extract_root_var(expr: &Expr) -> Option<String> {
4698        match expr {
4699            Expr::Path(path) if path.segments.len() == 1 => {
4700                Some(path.segments[0].ident.name.clone())
4701            }
4702            Expr::MethodCall { receiver, .. } => {
4703                Self::extract_root_var(receiver)
4704            }
4705            _ => None,
4706        }
4707    }
4708
4709    fn eval_method_call(
4710        &mut self,
4711        receiver: &Expr,
4712        method: &Ident,
4713        args: &[Expr],
4714    ) -> Result<Value, RuntimeError> {
4715        // Special handling for String::push/push_str - needs to mutate the variable
4716        if (method.name == "push" || method.name == "push_str") && args.len() == 1 {
4717            let recv_val = self.evaluate(receiver)?;
4718            let recv_unwrapped = Self::unwrap_all(&recv_val);
4719            if let Value::String(s) = &recv_unwrapped {
4720                let arg = self.evaluate(&args[0])?;
4721                let arg_unwrapped = Self::unwrap_all(&arg);
4722                let new_s = match arg_unwrapped {
4723                    Value::Char(c) => {
4724                        let mut new_str = (**s).clone();
4725                        new_str.push(c);
4726                        new_str
4727                    }
4728                    Value::String(ref add_s) => {
4729                        let mut new_str = (**s).clone();
4730                        new_str.push_str(add_s);
4731                        new_str
4732                    }
4733                    _ => return Err(RuntimeError::new("push expects char or string argument")),
4734                };
4735                let new_val = Value::String(Rc::new(new_s));
4736
4737                // Try to extract root variable from chain and mutate it
4738                if let Some(root_var) = Self::extract_root_var(receiver) {
4739                    self.environment.borrow_mut().set(&root_var, new_val.clone())?;
4740                    // Return the new value for method chaining
4741                    return Ok(new_val);
4742                }
4743
4744                // Handle field access like self.output.push(c)
4745                if let Expr::Field { expr: base_expr, field: field_ident } = receiver {
4746                    let base = self.evaluate(base_expr)?;
4747                    if let Value::Struct { fields, .. } = base {
4748                        fields.borrow_mut().insert(field_ident.name.clone(), new_val.clone());
4749                        // Return the new value for method chaining
4750                        return Ok(new_val);
4751                    }
4752                }
4753                // Fallback: can't mutate, just return the new string
4754                return Ok(new_val);
4755            }
4756        }
4757
4758        let recv_raw = self.evaluate(receiver)?;
4759        // Unwrap evidential/affective wrappers for method dispatch
4760        let recv = Self::unwrap_value(&recv_raw).clone();
4761
4762        // Debug: trace ALL method calls to find Lexer
4763        static METHOD_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
4764        let count = METHOD_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
4765        if count < 500 {
4766            let recv_type = match &recv {
4767                Value::Struct { name, .. } => format!("Struct({})", name),
4768                Value::String(s) => format!("String('{}')", if s.len() <= 20 { s.as_str() } else { "<long>" }),
4769                Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
4770                other => format!("{:?}", std::mem::discriminant(other)),
4771            };
4772            if recv_type.contains("Lexer") || method.name.contains("keyword") || method.name.contains("lex") {
4773                crate::sigil_debug!("DEBUG method #{}: {}.{}()", count, recv_type, method.name);
4774            }
4775        }
4776        let arg_values: Vec<Value> = args
4777            .iter()
4778            .map(|a| self.evaluate(a))
4779            .collect::<Result<_, _>>()?;
4780
4781        // Debug: Trace cloned/clone method calls
4782        if method.name == "cloned" || method.name == "clone" {
4783            let recv_type = match &recv {
4784                Value::Struct { name, .. } => format!("Struct({})", name),
4785                Value::Variant { enum_name, variant_name, .. } => format!("Variant({}::{})", enum_name, variant_name),
4786                Value::String(_) => "String".to_string(),
4787                Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
4788                Value::Null => "Null".to_string(),
4789                other => format!("{:?}", std::mem::discriminant(other)),
4790            };
4791            crate::sigil_debug!("DEBUG {}: recv_type={}", method.name, recv_type);
4792        }
4793
4794        // Debug: Trace ALL as_str calls
4795        if method.name == "as_str" {
4796            let recv_unwrapped = Self::unwrap_all(&recv);
4797            if let Value::String(s) = &recv_unwrapped {
4798                crate::sigil_debug!("DEBUG as_str CALL: recv='{}' len={}", s, s.len());
4799            } else {
4800                crate::sigil_debug!("DEBUG as_str CALL: recv={:?} (not string)", recv_unwrapped);
4801            }
4802        }
4803
4804        // Debug: trace keyword_or_ident method calls
4805        if method.name == "keyword_or_ident" {
4806            let recv_type = match &recv {
4807                Value::Struct { name, .. } => format!("Struct({})", name),
4808                Value::String(_) => "String".to_string(),
4809                Value::Ref(r) => format!("Ref({})", match &*r.borrow() {
4810                    Value::Struct { name, .. } => format!("Struct({})", name),
4811                    other => format!("{:?}", std::mem::discriminant(other)),
4812                }),
4813                other => format!("{:?}", std::mem::discriminant(other)),
4814            };
4815            crate::sigil_debug!("DEBUG keyword_or_ident: recv_type={}", recv_type);
4816        }
4817
4818        // Debug: Find "fn" as method argument
4819        for arg in &arg_values {
4820            let unwrapped = Self::unwrap_all(arg);
4821            if let Value::String(s) = &unwrapped {
4822                if **s == "fn" {
4823                    let recv_type = match &recv {
4824                        Value::Struct { name, .. } => format!("Struct({})", name),
4825                        Value::String(_) => "String".to_string(),
4826                        Value::Ref(_) => "Ref".to_string(),
4827                        other => format!("{:?}", std::mem::discriminant(other)),
4828                    };
4829                    crate::sigil_debug!("DEBUG method call with 'fn': method={}, recv_type={}", method.name, recv_type);
4830                }
4831            }
4832        }
4833
4834        // Built-in methods
4835        match (&recv, method.name.as_str()) {
4836            (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
4837            (Value::Array(arr), "push") => {
4838                if arg_values.len() != 1 {
4839                    return Err(RuntimeError::new("push expects 1 argument"));
4840                }
4841                arr.borrow_mut().push(arg_values[0].clone());
4842                Ok(Value::Null)
4843            }
4844            (Value::Array(arr), "pop") => arr
4845                .borrow_mut()
4846                .pop()
4847                .ok_or_else(|| RuntimeError::new("pop on empty array")),
4848            (Value::Array(arr), "extend") => {
4849                if arg_values.len() != 1 {
4850                    return Err(RuntimeError::new("extend expects 1 argument"));
4851                }
4852                match &arg_values[0] {
4853                    Value::Array(other) => {
4854                        arr.borrow_mut().extend(other.borrow().iter().cloned());
4855                        Ok(Value::Null)
4856                    }
4857                    _ => Err(RuntimeError::new("extend expects array argument")),
4858                }
4859            }
4860            (Value::Array(arr), "reverse") => {
4861                let mut v = arr.borrow().clone();
4862                v.reverse();
4863                Ok(Value::Array(Rc::new(RefCell::new(v))))
4864            }
4865            (Value::Array(arr), "skip") => {
4866                let n = match arg_values.first() {
4867                    Some(Value::Int(i)) => *i as usize,
4868                    _ => 1,
4869                };
4870                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
4871                Ok(Value::Array(Rc::new(RefCell::new(v))))
4872            }
4873            (Value::Array(arr), "take") => {
4874                let n = match arg_values.first() {
4875                    Some(Value::Int(i)) => *i as usize,
4876                    _ => 1,
4877                };
4878                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
4879                Ok(Value::Array(Rc::new(RefCell::new(v))))
4880            }
4881            (Value::Array(arr), "step_by") => {
4882                let n = match arg_values.first() {
4883                    Some(Value::Int(i)) if *i > 0 => *i as usize,
4884                    _ => 1,
4885                };
4886                let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
4887                Ok(Value::Array(Rc::new(RefCell::new(v))))
4888            }
4889            (Value::Array(arr), "contains") => {
4890                if arg_values.len() != 1 {
4891                    return Err(RuntimeError::new("contains expects 1 argument"));
4892                }
4893                let target = &arg_values[0];
4894                let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
4895                Ok(Value::Bool(found))
4896            }
4897            // Tuple methods
4898            (Value::Tuple(t), "to_string") | (Value::Tuple(t), "string") => {
4899                let s: Vec<String> = t.iter().map(|v| format!("{}", v)).collect();
4900                Ok(Value::String(Rc::new(format!("({})", s.join(", ")))))
4901            }
4902            (Value::Tuple(t), "len") => Ok(Value::Int(t.len() as i64)),
4903            (Value::Tuple(t), "first") => t.first().cloned().ok_or_else(|| RuntimeError::new("empty tuple")),
4904            (Value::Tuple(t), "last") => t.last().cloned().ok_or_else(|| RuntimeError::new("empty tuple")),
4905            (Value::Tuple(t), "get") => {
4906                let idx = match arg_values.first() {
4907                    Some(Value::Int(i)) => *i as usize,
4908                    _ => return Err(RuntimeError::new("get expects integer index")),
4909                };
4910                t.get(idx).cloned().ok_or_else(|| RuntimeError::new("tuple index out of bounds"))
4911            }
4912            (Value::Array(arr), "first") | (Value::Array(arr), "next") => Ok(arr
4913                .borrow()
4914                .first()
4915                .cloned()
4916                .unwrap_or(Value::Null)),
4917            (Value::Array(arr), "last") => arr
4918                .borrow()
4919                .last()
4920                .cloned()
4921                .ok_or_else(|| RuntimeError::new("empty array")),
4922            (Value::Array(arr), "iter") | (Value::Array(arr), "into_iter") => {
4923                // iter()/into_iter() on an array just returns the array - iteration happens in for loops
4924                Ok(Value::Array(arr.clone()))
4925            }
4926            (Value::Array(arr), "map") => {
4927                // map(closure) applies closure to each element
4928                if arg_values.len() != 1 {
4929                    return Err(RuntimeError::new("map expects 1 argument (closure)"));
4930                }
4931                match &arg_values[0] {
4932                    Value::Function(f) => {
4933                        let mut results = Vec::new();
4934                        for val in arr.borrow().iter() {
4935                            let result = self.call_function(f, vec![val.clone()])?;
4936                            results.push(result);
4937                        }
4938                        Ok(Value::Array(Rc::new(RefCell::new(results))))
4939                    }
4940                    _ => Err(RuntimeError::new("map expects closure argument")),
4941                }
4942            }
4943            (Value::Array(arr), "filter") => {
4944                // filter(predicate) keeps elements where predicate returns true
4945                if arg_values.len() != 1 {
4946                    return Err(RuntimeError::new("filter expects 1 argument (closure)"));
4947                }
4948                match &arg_values[0] {
4949                    Value::Function(f) => {
4950                        let mut results = Vec::new();
4951                        for val in arr.borrow().iter() {
4952                            let keep = self.call_function(f, vec![val.clone()])?;
4953                            if matches!(keep, Value::Bool(true)) {
4954                                results.push(val.clone());
4955                            }
4956                        }
4957                        Ok(Value::Array(Rc::new(RefCell::new(results))))
4958                    }
4959                    _ => Err(RuntimeError::new("filter expects closure argument")),
4960                }
4961            }
4962            (Value::Array(arr), "any") => {
4963                // any(predicate) returns true if any element satisfies predicate
4964                if arg_values.len() != 1 {
4965                    return Err(RuntimeError::new("any expects 1 argument (closure)"));
4966                }
4967                match &arg_values[0] {
4968                    Value::Function(f) => {
4969                        for val in arr.borrow().iter() {
4970                            let result = self.call_function(f, vec![val.clone()])?;
4971                            if matches!(result, Value::Bool(true)) {
4972                                return Ok(Value::Bool(true));
4973                            }
4974                        }
4975                        Ok(Value::Bool(false))
4976                    }
4977                    _ => Err(RuntimeError::new("any expects closure argument")),
4978                }
4979            }
4980            (Value::Array(arr), "all") => {
4981                // all(predicate) returns true if all elements satisfy predicate
4982                if arg_values.len() != 1 {
4983                    return Err(RuntimeError::new("all expects 1 argument (closure)"));
4984                }
4985                match &arg_values[0] {
4986                    Value::Function(f) => {
4987                        for val in arr.borrow().iter() {
4988                            let result = self.call_function(f, vec![val.clone()])?;
4989                            if !matches!(result, Value::Bool(true)) {
4990                                return Ok(Value::Bool(false));
4991                            }
4992                        }
4993                        Ok(Value::Bool(true))
4994                    }
4995                    _ => Err(RuntimeError::new("all expects closure argument")),
4996                }
4997            }
4998            (Value::Array(arr), "find") => {
4999                // find(predicate) returns first element satisfying predicate, or None
5000                if arg_values.len() != 1 {
5001                    return Err(RuntimeError::new("find expects 1 argument (closure)"));
5002                }
5003                match &arg_values[0] {
5004                    Value::Function(f) => {
5005                        for val in arr.borrow().iter() {
5006                            let result = self.call_function(f, vec![val.clone()])?;
5007                            if matches!(result, Value::Bool(true)) {
5008                                return Ok(Value::Variant {
5009                                    enum_name: "Option".to_string(),
5010                                    variant_name: "Some".to_string(),
5011                                    fields: Some(Rc::new(vec![val.clone()])),
5012                                });
5013                            }
5014                        }
5015                        Ok(Value::Variant {
5016                            enum_name: "Option".to_string(),
5017                            variant_name: "None".to_string(),
5018                            fields: None,
5019                        })
5020                    }
5021                    _ => Err(RuntimeError::new("find expects closure argument")),
5022                }
5023            }
5024            (Value::Array(arr), "enumerate") => {
5025                // enumerate() returns array of (index, value) tuples
5026                let enumerated: Vec<Value> = arr
5027                    .borrow()
5028                    .iter()
5029                    .enumerate()
5030                    .map(|(i, v)| Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()])))
5031                    .collect();
5032                Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
5033            }
5034            (Value::Array(arr), "zip") => {
5035                // zip with another array to create array of tuples
5036                if arg_values.len() != 1 {
5037                    return Err(RuntimeError::new("zip expects 1 argument"));
5038                }
5039                match &arg_values[0] {
5040                    Value::Array(other) => {
5041                        let a = arr.borrow();
5042                        let b = other.borrow();
5043                        let zipped: Vec<Value> = a.iter()
5044                            .zip(b.iter())
5045                            .map(|(x, y)| Value::Tuple(Rc::new(vec![x.clone(), y.clone()])))
5046                            .collect();
5047                        Ok(Value::Array(Rc::new(RefCell::new(zipped))))
5048                    }
5049                    _ => Err(RuntimeError::new("zip expects array argument")),
5050                }
5051            }
5052            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
5053            (Value::String(s), "chars") => {
5054                let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5055                Ok(Value::Array(Rc::new(RefCell::new(chars))))
5056            }
5057            (Value::String(s), "contains") => {
5058                if arg_values.len() != 1 {
5059                    return Err(RuntimeError::new("contains expects 1 argument"));
5060                }
5061                match &arg_values[0] {
5062                    Value::String(sub) => Ok(Value::Bool(s.contains(sub.as_str()))),
5063                    Value::Char(c) => Ok(Value::Bool(s.contains(*c))),
5064                    Value::Ref(inner) => {
5065                        if let Value::String(sub) = &*inner.borrow() {
5066                            Ok(Value::Bool(s.contains(sub.as_str())))
5067                        } else {
5068                            Err(RuntimeError::new("contains expects string or char"))
5069                        }
5070                    }
5071                    _ => Err(RuntimeError::new("contains expects string or char")),
5072                }
5073            }
5074            (Value::String(s), "as_str") => {
5075                if s.len() <= 10 { crate::sigil_debug!("DEBUG as_str: '{}'", s); }
5076                Ok(Value::String(s.clone()))
5077            }
5078            (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
5079            (Value::String(s), "into") => Ok(Value::String(s.clone())),  // into() for String just returns String
5080            (Value::String(s), "starts_with") => {
5081                if arg_values.len() != 1 {
5082                    return Err(RuntimeError::new("starts_with expects 1 argument"));
5083                }
5084                match &arg_values[0] {
5085                    Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
5086                    _ => Err(RuntimeError::new("starts_with expects string")),
5087                }
5088            }
5089            (Value::String(s), "ends_with") => {
5090                if arg_values.len() != 1 {
5091                    return Err(RuntimeError::new("ends_with expects 1 argument"));
5092                }
5093                match &arg_values[0] {
5094                    Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
5095                    _ => Err(RuntimeError::new("ends_with expects string")),
5096                }
5097            }
5098            (Value::String(s), "strip_prefix") => {
5099                if arg_values.len() != 1 {
5100                    return Err(RuntimeError::new("strip_prefix expects 1 argument"));
5101                }
5102                match &arg_values[0] {
5103                    Value::String(prefix) => {
5104                        match s.strip_prefix(prefix.as_str()) {
5105                            Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
5106                            None => Ok(Value::Null),
5107                        }
5108                    }
5109                    _ => Err(RuntimeError::new("strip_prefix expects string")),
5110                }
5111            }
5112            (Value::String(s), "strip_suffix") => {
5113                if arg_values.len() != 1 {
5114                    return Err(RuntimeError::new("strip_suffix expects 1 argument"));
5115                }
5116                match &arg_values[0] {
5117                    Value::String(suffix) => {
5118                        match s.strip_suffix(suffix.as_str()) {
5119                            Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
5120                            None => Ok(Value::Null),
5121                        }
5122                    }
5123                    _ => Err(RuntimeError::new("strip_suffix expects string")),
5124                }
5125            }
5126            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
5127            (Value::String(s), "find") => {
5128                if arg_values.len() != 1 {
5129                    return Err(RuntimeError::new("find expects 1 argument"));
5130                }
5131                match &arg_values[0] {
5132                    Value::Char(c) => {
5133                        match s.find(*c) {
5134                            Some(idx) => Ok(Value::Variant {
5135                                enum_name: "Option".to_string(),
5136                                variant_name: "Some".to_string(),
5137                                fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5138                            }),
5139                            None => Ok(Value::Variant {
5140                                enum_name: "Option".to_string(),
5141                                variant_name: "None".to_string(),
5142                                fields: None,
5143                            }),
5144                        }
5145                    }
5146                    Value::String(pattern) => {
5147                        match s.find(pattern.as_str()) {
5148                            Some(idx) => Ok(Value::Variant {
5149                                enum_name: "Option".to_string(),
5150                                variant_name: "Some".to_string(),
5151                                fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5152                            }),
5153                            None => Ok(Value::Variant {
5154                                enum_name: "Option".to_string(),
5155                                variant_name: "None".to_string(),
5156                                fields: None,
5157                            }),
5158                        }
5159                    }
5160                    Value::Function(f) => {
5161                        for (idx, c) in s.chars().enumerate() {
5162                            let result = self.call_function(f, vec![Value::Char(c)])?;
5163                            if let Value::Bool(true) = result {
5164                                return Ok(Value::Variant {
5165                                    enum_name: "Option".to_string(),
5166                                    variant_name: "Some".to_string(),
5167                                    fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5168                                });
5169                            }
5170                        }
5171                        Ok(Value::Variant {
5172                            enum_name: "Option".to_string(),
5173                            variant_name: "None".to_string(),
5174                            fields: None,
5175                        })
5176                    }
5177                    _ => Err(RuntimeError::new("find expects a char, string, or closure")),
5178                }
5179            }
5180            (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
5181            (Value::String(s), "concat") => {
5182                if arg_values.len() != 1 {
5183                    return Err(RuntimeError::new("concat expects 1 argument"));
5184                }
5185                match &arg_values[0] {
5186                    Value::String(other) => {
5187                        let mut result = (**s).clone();
5188                        result.push_str(other);
5189                        Ok(Value::String(Rc::new(result)))
5190                    }
5191                    _ => Err(RuntimeError::new("concat expects string argument")),
5192                }
5193            }
5194            (Value::String(s), "as_ptr") => {
5195                // Return the string itself - FFI emulation doesn't need real pointers
5196                Ok(Value::String(s.clone()))
5197            }
5198            (Value::String(_), "is_null") => Ok(Value::Bool(false)),
5199            (Value::Null, "is_null") => Ok(Value::Bool(true)),
5200            (Value::String(s), "char_at") => {
5201                if arg_values.len() != 1 {
5202                    return Err(RuntimeError::new("char_at expects 1 argument"));
5203                }
5204                let idx = match &arg_values[0] {
5205                    Value::Int(i) => *i as usize,
5206                    _ => return Err(RuntimeError::new("char_at expects integer index")),
5207                };
5208                // Use byte-based indexing to match the self-hosted lexer's pos tracking
5209                // which increments by c.len_utf8() (byte count, not character count)
5210                if idx < s.len() {
5211                    // Get the character starting at byte position idx
5212                    let remaining = &s[idx..];
5213                    match remaining.chars().next() {
5214                        Some(c) => Ok(Value::Char(c)),
5215                        None => Ok(Value::Null),
5216                    }
5217                } else {
5218                    Ok(Value::Null) // Out of bounds
5219                }
5220            }
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), "bytes") => {
5226                let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
5227                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
5228            }
5229            (Value::String(s), "split") => {
5230                if arg_values.len() != 1 {
5231                    return Err(RuntimeError::new("split expects 1 argument"));
5232                }
5233                match &arg_values[0] {
5234                    Value::String(sep) => {
5235                        let parts: Vec<Value> = s.split(sep.as_str())
5236                            .map(|p| Value::String(Rc::new(p.to_string())))
5237                            .collect();
5238                        Ok(Value::Array(Rc::new(RefCell::new(parts))))
5239                    }
5240                    Value::Char(sep) => {
5241                        let parts: Vec<Value> = s.split(*sep)
5242                            .map(|p| Value::String(Rc::new(p.to_string())))
5243                            .collect();
5244                        Ok(Value::Array(Rc::new(RefCell::new(parts))))
5245                    }
5246                    _ => Err(RuntimeError::new("split expects string or char separator")),
5247                }
5248            }
5249            // Char methods
5250            (Value::Char(c), "len_utf8") => Ok(Value::Int(c.len_utf8() as i64)),
5251            (Value::Char(c), "is_alphabetic") => Ok(Value::Bool(c.is_alphabetic())),
5252            (Value::Char(c), "is_alphanumeric") => Ok(Value::Bool(c.is_alphanumeric())),
5253            (Value::Char(c), "is_ascii_alphanumeric") => Ok(Value::Bool(c.is_ascii_alphanumeric())),
5254            (Value::Char(c), "is_ascii_alphabetic") => Ok(Value::Bool(c.is_ascii_alphabetic())),
5255            (Value::Char(c), "is_ascii_digit") => Ok(Value::Bool(c.is_ascii_digit())),
5256            (Value::Char(c), "is_ascii_hexdigit") => Ok(Value::Bool(c.is_ascii_hexdigit())),
5257            (Value::Char(c), "is_ascii") => Ok(Value::Bool(c.is_ascii())),
5258            (Value::Char(c), "is_digit") => {
5259                let radix = if arg_values.is_empty() { 10 } else {
5260                    match &arg_values[0] {
5261                        Value::Int(n) => *n as u32,
5262                        _ => 10,
5263                    }
5264                };
5265                Ok(Value::Bool(c.is_digit(radix)))
5266            }
5267            (Value::Char(c), "is_numeric") => Ok(Value::Bool(c.is_numeric())),
5268            (Value::Char(c), "is_whitespace") => Ok(Value::Bool(c.is_whitespace())),
5269            (Value::Char(c), "is_uppercase") => Ok(Value::Bool(c.is_uppercase())),
5270            (Value::Char(c), "is_lowercase") => Ok(Value::Bool(c.is_lowercase())),
5271            (Value::Char(c), "to_uppercase") => {
5272                let upper: String = c.to_uppercase().collect();
5273                Ok(Value::String(Rc::new(upper)))
5274            }
5275            (Value::Char(c), "to_lowercase") => {
5276                let lower: String = c.to_lowercase().collect();
5277                Ok(Value::String(Rc::new(lower)))
5278            }
5279            (Value::Char(c), "to_string") => Ok(Value::String(Rc::new(c.to_string()))),
5280            (Value::Char(c), "to_digit") => {
5281                let radix = if arg_values.is_empty() { 10 } else {
5282                    match &arg_values[0] {
5283                        Value::Int(n) => *n as u32,
5284                        _ => 10,
5285                    }
5286                };
5287                match c.to_digit(radix) {
5288                    Some(d) => Ok(Value::Int(d as i64)),
5289                    None => Ok(Value::Null),
5290                }
5291            }
5292            (Value::Char(c), "to_ascii_uppercase") => Ok(Value::Char(c.to_ascii_uppercase())),
5293            (Value::Char(c), "to_ascii_lowercase") => Ok(Value::Char(c.to_ascii_lowercase())),
5294            (Value::Char(c), "clone") => Ok(Value::Char(*c)),
5295            (Value::String(s), "upper") | (Value::String(s), "uppercase") | (Value::String(s), "to_uppercase") => {
5296                Ok(Value::String(Rc::new(s.to_uppercase())))
5297            }
5298            (Value::String(s), "lower") | (Value::String(s), "lowercase") | (Value::String(s), "to_lowercase") => {
5299                Ok(Value::String(Rc::new(s.to_lowercase())))
5300            }
5301            (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
5302            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
5303            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
5304            // Path-like methods for strings (treat string as file path)
5305            (Value::String(s), "exists") => Ok(Value::Bool(std::path::Path::new(s.as_str()).exists())),
5306            (Value::String(s), "is_dir") => Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir())),
5307            (Value::String(s), "is_file") => Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file())),
5308            (Value::String(s), "join") => {
5309                // Path join: "dir".join("file") => "dir/file"
5310                if arg_values.len() != 1 {
5311                    return Err(RuntimeError::new(&format!("join expects 1 argument, got {}", arg_values.len())));
5312                }
5313                let other = match &arg_values[0] {
5314                    Value::String(s2) => s2.as_str().to_string(),
5315                    other => return Err(RuntimeError::new(&format!("join expects String argument, got {:?}", other))),
5316                };
5317                let path = std::path::Path::new(s.as_str()).join(&other);
5318                Ok(Value::String(Rc::new(path.to_string_lossy().to_string())))
5319            }
5320            (Value::String(s), "parent") => {
5321                // Get parent directory
5322                let path = std::path::Path::new(s.as_str());
5323                match path.parent() {
5324                    Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
5325                    None => Ok(Value::Null),
5326                }
5327            }
5328            (Value::String(s), "file_name") => {
5329                // Get file name component
5330                let path = std::path::Path::new(s.as_str());
5331                match path.file_name() {
5332                    Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5333                    None => Ok(Value::Null),
5334                }
5335            }
5336            (Value::String(s), "extension") => {
5337                // Get file extension
5338                let path = std::path::Path::new(s.as_str());
5339                match path.extension() {
5340                    Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5341                    None => Ok(Value::Null),
5342                }
5343            }
5344            // Result-like chaining for strings (used when string represents a Result-like value)
5345            (Value::String(_), "and_then") | (Value::String(_), "or_else") => {
5346                // Just pass through - these are no-ops for plain strings
5347                Ok(recv.clone())
5348            }
5349            (Value::String(s), "first") => s
5350                .chars()
5351                .next()
5352                .map(Value::Char)
5353                .ok_or_else(|| RuntimeError::new("empty string")),
5354            (Value::String(s), "last") => s
5355                .chars()
5356                .last()
5357                .map(Value::Char)
5358                .ok_or_else(|| RuntimeError::new("empty string")),
5359            (Value::Array(arr), "is_empty") => Ok(Value::Bool(arr.borrow().is_empty())),
5360            (Value::Array(arr), "clone") => Ok(Value::Array(Rc::new(RefCell::new(arr.borrow().clone())))),
5361            (Value::Array(arr), "collect") => {
5362                // collect() on array just returns the array itself
5363                // It's the terminal operation that materializes pipeline results
5364                Ok(Value::Array(arr.clone()))
5365            }
5366            (Value::Array(arr), "join") => {
5367                let separator = if arg_values.is_empty() {
5368                    String::new()
5369                } else {
5370                    match &arg_values[0] {
5371                        Value::String(s) => (**s).clone(),
5372                        _ => return Err(RuntimeError::new("join separator must be string")),
5373                    }
5374                };
5375                let parts: Vec<String> = arr.borrow().iter()
5376                    .map(|v| self.format_value(v))
5377                    .collect();
5378                Ok(Value::String(Rc::new(parts.join(&separator))))
5379            }
5380            // Map methods
5381            (Value::Map(m), "insert") => {
5382                if arg_values.len() != 2 {
5383                    return Err(RuntimeError::new("insert expects 2 arguments"));
5384                }
5385                let key = match &arg_values[0] {
5386                    Value::String(s) => (**s).clone(),
5387                    _ => format!("{}", arg_values[0]),
5388                };
5389                m.borrow_mut().insert(key, arg_values[1].clone());
5390                Ok(Value::Null)
5391            }
5392            (Value::Map(m), "get") => {
5393                if arg_values.len() != 1 {
5394                    return Err(RuntimeError::new("get expects 1 argument"));
5395                }
5396                let key = match &arg_values[0] {
5397                    Value::String(s) => (**s).clone(),
5398                    _ => format!("{}", arg_values[0]),
5399                };
5400                Ok(m.borrow().get(&key).cloned().unwrap_or(Value::Null))
5401            }
5402            (Value::Map(m), "contains_key") => {
5403                if arg_values.len() != 1 {
5404                    return Err(RuntimeError::new("contains_key expects 1 argument"));
5405                }
5406                let key = match &arg_values[0] {
5407                    Value::String(s) => (**s).clone(),
5408                    _ => format!("{}", arg_values[0]),
5409                };
5410                Ok(Value::Bool(m.borrow().contains_key(&key)))
5411            }
5412            (Value::Map(m), "len") => Ok(Value::Int(m.borrow().len() as i64)),
5413            (Value::Map(m), "is_empty") => Ok(Value::Bool(m.borrow().is_empty())),
5414            (Value::Map(m), "keys") => {
5415                let keys: Vec<Value> = m.borrow().keys()
5416                    .map(|k| Value::String(Rc::new(k.clone())))
5417                    .collect();
5418                Ok(Value::Array(Rc::new(RefCell::new(keys))))
5419            }
5420            (Value::Map(m), "values") => {
5421                let values: Vec<Value> = m.borrow().values().cloned().collect();
5422                Ok(Value::Array(Rc::new(RefCell::new(values))))
5423            }
5424            // Ref methods
5425            (Value::Ref(r), "cloned") => {
5426                // Clone the inner value
5427                Ok(r.borrow().clone())
5428            }
5429            (Value::Ref(r), "borrow") => {
5430                // Return a reference to the inner value
5431                Ok(recv.clone())
5432            }
5433            (Value::Ref(r), "borrow_mut") => {
5434                // Return a reference to the inner value (mutable in place)
5435                Ok(recv.clone())
5436            }
5437            // Forward method calls on Ref to inner value (struct method lookup)
5438            (Value::Ref(r), _) => {
5439                // Dereference and look up method on inner struct
5440                let inner = r.borrow().clone();
5441                if let Value::Struct { name, fields } = &inner {
5442                    // Try struct method lookup with the inner struct
5443                    let qualified_name = format!("{}·{}", name, method.name);
5444                    let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
5445                    if let Some(func) = func {
5446                        if let Value::Function(f) = func {
5447                            // Set current Self type for Self { ... } resolution
5448                            let old_self_type = self.current_self_type.take();
5449                            self.current_self_type = Some(name.clone());
5450
5451                            // Pass the Ref as the receiver (for &mut self methods)
5452                            let mut all_args = vec![recv.clone()];
5453                            all_args.extend(arg_values.clone());
5454                            let result = self.call_function(&f, all_args);
5455
5456                            // Restore old Self type
5457                            self.current_self_type = old_self_type;
5458                            return result;
5459                        } else if let Value::BuiltIn(b) = func {
5460                            let mut all_args = vec![recv.clone()];
5461                            all_args.extend(arg_values.clone());
5462                            return (b.func)(self, all_args);
5463                        }
5464                    }
5465
5466                    // If struct name is "Self", search by matching field names
5467                    if name == "Self" {
5468                        let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
5469
5470                        // Search through registered types to find a matching struct
5471                        for (type_name, type_def) in &self.types {
5472                            if let TypeDef::Struct(struct_def) = type_def {
5473                                let def_fields: Vec<String> = match &struct_def.fields {
5474                                    crate::ast::StructFields::Named(fs) => fs.iter().map(|f| f.name.name.clone()).collect(),
5475                                    _ => continue,
5476                                };
5477
5478                                // Match if our fields exist in the definition
5479                                let matches = field_names.iter().all(|f| def_fields.contains(f));
5480                                if matches {
5481                                    let qualified_name = format!("{}·{}", type_name, method.name);
5482                                    let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
5483                                    if let Some(func) = func {
5484                                        if let Value::Function(f) = func {
5485                                            // Set current Self type for Self { ... } resolution
5486                                            let old_self_type = self.current_self_type.take();
5487                                            self.current_self_type = Some(type_name.clone());
5488
5489                                            let mut all_args = vec![recv.clone()];
5490                                            all_args.extend(arg_values.clone());
5491                                            let result = self.call_function(&f, all_args);
5492
5493                                            // Restore old Self type
5494                                            self.current_self_type = old_self_type;
5495                                            return result;
5496                                        } else if let Value::BuiltIn(b) = func {
5497                                            let mut all_args = vec![recv.clone()];
5498                                            all_args.extend(arg_values.clone());
5499                                            return (b.func)(self, all_args);
5500                                        }
5501                                    }
5502                                }
5503                            }
5504                        }
5505                    }
5506
5507                    // Built-in methods for PathBuf struct
5508                    if name == "PathBuf" || name == "Path" {
5509                        if let Some(Value::String(path)) = fields.borrow().get("path").cloned() {
5510                            match method.name.as_str() {
5511                                "exists" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).exists())),
5512                                "is_dir" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_dir())),
5513                                "is_file" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_file())),
5514                                "join" => {
5515                                    if let Some(Value::String(other)) = arg_values.first() {
5516                                        let new_path = std::path::Path::new(path.as_str()).join(other.as_str());
5517                                        let mut new_fields = std::collections::HashMap::new();
5518                                        new_fields.insert("path".to_string(), Value::String(Rc::new(new_path.to_string_lossy().to_string())));
5519                                        return Ok(Value::Struct {
5520                                            name: "PathBuf".to_string(),
5521                                            fields: Rc::new(RefCell::new(new_fields)),
5522                                        });
5523                                    }
5524                                    return Err(RuntimeError::new("join requires string argument"));
5525                                }
5526                                "parent" => {
5527                                    let p = std::path::Path::new(path.as_str());
5528                                    return match p.parent() {
5529                                        Some(par) => {
5530                                            let mut new_fields = std::collections::HashMap::new();
5531                                            new_fields.insert("path".to_string(), Value::String(Rc::new(par.to_string_lossy().to_string())));
5532                                            Ok(Value::Struct {
5533                                                name: "PathBuf".to_string(),
5534                                                fields: Rc::new(RefCell::new(new_fields)),
5535                                            })
5536                                        }
5537                                        None => Ok(Value::Null),
5538                                    };
5539                                }
5540                                "file_name" => {
5541                                    let p = std::path::Path::new(path.as_str());
5542                                    return match p.file_name() {
5543                                        Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5544                                        None => Ok(Value::Null),
5545                                    };
5546                                }
5547                                "extension" => {
5548                                    let p = std::path::Path::new(path.as_str());
5549                                    return match p.extension() {
5550                                        Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5551                                        None => Ok(Value::Null),
5552                                    };
5553                                }
5554                                "to_string" | "display" | "to_str" => {
5555                                    return Ok(Value::String(path.clone()));
5556                                }
5557                                _ => {}
5558                            }
5559                        }
5560                    }
5561
5562                    // Fallback for unknown methods on external type references: return null
5563                    crate::sigil_warn!("WARN: Unknown method '{}' on '&{}' - returning null", method.name, name);
5564                    return Ok(Value::Null);
5565                }
5566                // For non-struct refs (like &str), auto-deref and call method on inner value
5567                // Handle common methods on &str (reference to String)
5568                if let Value::String(s) = &inner {
5569                    match method.name.as_str() {
5570                        "to_string" => return Ok(Value::String(s.clone())),
5571                        "len" => return Ok(Value::Int(s.len() as i64)),
5572                        "is_empty" => return Ok(Value::Bool(s.is_empty())),
5573                        "as_str" => return Ok(Value::String(s.clone())),
5574                        "starts_with" => {
5575                            let prefix = match arg_values.first() {
5576                                Some(Value::String(p)) => p.as_str(),
5577                                Some(Value::Char(c)) => return Ok(Value::Bool(s.starts_with(*c))),
5578                                _ => return Err(RuntimeError::new("starts_with expects string or char")),
5579                            };
5580                            return Ok(Value::Bool(s.starts_with(prefix)));
5581                        }
5582                        "ends_with" => {
5583                            let suffix = match arg_values.first() {
5584                                Some(Value::String(p)) => p.as_str(),
5585                                Some(Value::Char(c)) => return Ok(Value::Bool(s.ends_with(*c))),
5586                                _ => return Err(RuntimeError::new("ends_with expects string or char")),
5587                            };
5588                            return Ok(Value::Bool(s.ends_with(suffix)));
5589                        }
5590                        "contains" => {
5591                            let substr = match arg_values.first() {
5592                                Some(Value::String(p)) => p.as_str(),
5593                                Some(Value::Char(c)) => return Ok(Value::Bool(s.contains(*c))),
5594                                _ => return Err(RuntimeError::new("contains expects string or char")),
5595                            };
5596                            return Ok(Value::Bool(s.contains(substr)));
5597                        }
5598                        "trim" => return Ok(Value::String(Rc::new(s.trim().to_string()))),
5599                        "to_lowercase" => return Ok(Value::String(Rc::new(s.to_lowercase()))),
5600                        "to_uppercase" => return Ok(Value::String(Rc::new(s.to_uppercase()))),
5601                        "chars" => {
5602                            let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5603                            return Ok(Value::Array(Rc::new(RefCell::new(chars))));
5604                        }
5605                        "split" => {
5606                            let delim = match arg_values.first() {
5607                                Some(Value::String(d)) => d.as_str().to_string(),
5608                                Some(Value::Char(c)) => c.to_string(),
5609                                _ => " ".to_string(),
5610                            };
5611                            let parts: Vec<Value> = s.split(&delim)
5612                                .map(|p| Value::String(Rc::new(p.to_string())))
5613                                .collect();
5614                            return Ok(Value::Array(Rc::new(RefCell::new(parts))));
5615                        }
5616                        "replace" => {
5617                            if arg_values.len() != 2 {
5618                                return Err(RuntimeError::new("replace expects 2 arguments"));
5619                            }
5620                            let from = match &arg_values[0] {
5621                                Value::String(f) => f.as_str().to_string(),
5622                                Value::Char(c) => c.to_string(),
5623                                _ => return Err(RuntimeError::new("replace expects strings")),
5624                            };
5625                            let to = match &arg_values[1] {
5626                                Value::String(t) => t.as_str().to_string(),
5627                                Value::Char(c) => c.to_string(),
5628                                _ => return Err(RuntimeError::new("replace expects strings")),
5629                            };
5630                            return Ok(Value::String(Rc::new(s.replace(&from, &to))));
5631                        }
5632                        _ => {}
5633                    }
5634                }
5635                // Handle methods on &[T] and &mut [T] (references to arrays/slices)
5636                if let Value::Array(arr) = &inner {
5637                    match method.name.as_str() {
5638                        "len" => return Ok(Value::Int(arr.borrow().len() as i64)),
5639                        "is_empty" => return Ok(Value::Bool(arr.borrow().is_empty())),
5640                        "push" => {
5641                            if arg_values.len() != 1 {
5642                                return Err(RuntimeError::new("push expects 1 argument"));
5643                            }
5644                            arr.borrow_mut().push(arg_values[0].clone());
5645                            return Ok(Value::Null);
5646                        }
5647                        "pop" => {
5648                            return arr.borrow_mut().pop()
5649                                .ok_or_else(|| RuntimeError::new("pop on empty array"));
5650                        }
5651                        "contains" => {
5652                            if arg_values.len() != 1 {
5653                                return Err(RuntimeError::new("contains expects 1 argument"));
5654                            }
5655                            let target = &arg_values[0];
5656                            let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
5657                            return Ok(Value::Bool(found));
5658                        }
5659                        "first" | "next" => {
5660                            return Ok(arr.borrow().first().cloned().unwrap_or(Value::Null));
5661                        }
5662                        "last" => {
5663                            return arr.borrow().last().cloned()
5664                                .ok_or_else(|| RuntimeError::new("empty array"));
5665                        }
5666                        "iter" | "into_iter" => {
5667                            return Ok(Value::Array(arr.clone()));
5668                        }
5669                        "reverse" => {
5670                            let mut v = arr.borrow().clone();
5671                            v.reverse();
5672                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
5673                        }
5674                        "skip" => {
5675                            let n = match arg_values.first() {
5676                                Some(Value::Int(i)) => *i as usize,
5677                                _ => 1,
5678                            };
5679                            let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
5680                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
5681                        }
5682                        "take" => {
5683                            let n = match arg_values.first() {
5684                                Some(Value::Int(i)) => *i as usize,
5685                                _ => 1,
5686                            };
5687                            let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
5688                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
5689                        }
5690                        "get" => {
5691                            let idx = match arg_values.first() {
5692                                Some(Value::Int(i)) => *i as usize,
5693                                _ => return Err(RuntimeError::new("get expects integer index")),
5694                            };
5695                            return Ok(arr.borrow().get(idx).cloned().unwrap_or(Value::Null));
5696                        }
5697                        _ => {}
5698                    }
5699                }
5700                // Handle clone on any Ref value - clone the inner value
5701                if method.name == "clone" {
5702                    crate::sigil_debug!("DEBUG clone: recv_type=Ref({:?})", std::mem::discriminant(&inner));
5703                    return Ok(inner.clone());
5704                }
5705                // Handle into on Ref value - convert to owned value
5706                if method.name == "into" {
5707                    return Ok(inner.clone());
5708                }
5709                // Handle to_string on Ref value
5710                if method.name == "to_string" {
5711                    return Ok(Value::String(Rc::new(format!("{}", inner))));
5712                }
5713                // Path methods for Ref containing PathBuf struct
5714                if let Value::Struct { name, fields, .. } = &inner {
5715                    if name == "PathBuf" || name == "Path" {
5716                        let borrowed = fields.borrow();
5717                        if let Some(Value::String(path)) = borrowed.get("path") {
5718                            match method.name.as_str() {
5719                                "exists" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).exists())),
5720                                "is_dir" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_dir())),
5721                                "is_file" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_file())),
5722                                "join" => {
5723                                    if let Some(Value::String(other)) = arg_values.first() {
5724                                        let new_path = std::path::Path::new(path.as_str()).join(other.as_str());
5725                                        let mut new_fields = std::collections::HashMap::new();
5726                                        new_fields.insert("path".to_string(), Value::String(Rc::new(new_path.to_string_lossy().to_string())));
5727                                        return Ok(Value::Struct {
5728                                            name: "PathBuf".to_string(),
5729                                            fields: Rc::new(RefCell::new(new_fields)),
5730                                        });
5731                                    }
5732                                    return Err(RuntimeError::new("join requires string argument"));
5733                                }
5734                                "parent" => {
5735                                    let p = std::path::Path::new(path.as_str());
5736                                    return match p.parent() {
5737                                        Some(par) => {
5738                                            let mut new_fields = std::collections::HashMap::new();
5739                                            new_fields.insert("path".to_string(), Value::String(Rc::new(par.to_string_lossy().to_string())));
5740                                            Ok(Value::Struct {
5741                                                name: "PathBuf".to_string(),
5742                                                fields: Rc::new(RefCell::new(new_fields)),
5743                                            })
5744                                        }
5745                                        None => Ok(Value::Null),
5746                                    };
5747                                }
5748                                "file_name" => {
5749                                    let p = std::path::Path::new(path.as_str());
5750                                    return match p.file_name() {
5751                                        Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5752                                        None => Ok(Value::Null),
5753                                    };
5754                                }
5755                                "extension" => {
5756                                    let p = std::path::Path::new(path.as_str());
5757                                    return match p.extension() {
5758                                        Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5759                                        None => Ok(Value::Null),
5760                                    };
5761                                }
5762                                "to_string" | "display" => {
5763                                    return Ok(Value::String(path.clone()));
5764                                }
5765                                _ => {}
5766                            }
5767                        }
5768                    }
5769                }
5770                // Path methods for Ref containing String (PathBuf behavior)
5771                if let Value::String(s) = &inner {
5772                    match method.name.as_str() {
5773                        "exists" => return Ok(Value::Bool(std::path::Path::new(s.as_str()).exists())),
5774                        "is_dir" => return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir())),
5775                        "is_file" => return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file())),
5776                        "join" => {
5777                            if let Some(Value::String(other)) = arg_values.first() {
5778                                let path = std::path::Path::new(s.as_str()).join(other.as_str());
5779                                return Ok(Value::String(Rc::new(path.to_string_lossy().to_string())));
5780                            }
5781                            return Err(RuntimeError::new("join requires string argument"));
5782                        }
5783                        "parent" => {
5784                            let path = std::path::Path::new(s.as_str());
5785                            return match path.parent() {
5786                                Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
5787                                None => Ok(Value::Null),
5788                            };
5789                        }
5790                        "file_name" => {
5791                            let path = std::path::Path::new(s.as_str());
5792                            return match path.file_name() {
5793                                Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5794                                None => Ok(Value::Null),
5795                            };
5796                        }
5797                        "extension" => {
5798                            let path = std::path::Path::new(s.as_str());
5799                            return match path.extension() {
5800                                Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5801                                None => Ok(Value::Null),
5802                            };
5803                        }
5804                        _ => {}
5805                    }
5806                }
5807                // If the inner value is a string, recursively call method dispatch
5808                // This handles cases like &s[..].find(...) where we have a Ref to a String slice
5809                if let Value::String(_) = inner {
5810                    // Recursively dispatch method call on the inner string
5811                    // Create a temporary receiver with the unwrapped string
5812                    let recv_unwrapped = inner.clone();
5813                    match (&recv_unwrapped, method.name.as_str()) {
5814                        (Value::String(s), "find") => {
5815                            if arg_values.len() != 1 {
5816                                return Err(RuntimeError::new("find expects 1 argument"));
5817                            }
5818                            match &arg_values[0] {
5819                                Value::Char(c) => {
5820                                    return match s.find(*c) {
5821                                        Some(idx) => Ok(Value::Variant {
5822                                            enum_name: "Option".to_string(),
5823                                            variant_name: "Some".to_string(),
5824                                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5825                                        }),
5826                                        None => Ok(Value::Variant {
5827                                            enum_name: "Option".to_string(),
5828                                            variant_name: "None".to_string(),
5829                                            fields: None,
5830                                        }),
5831                                    }
5832                                }
5833                                Value::String(pattern) => {
5834                                    return match s.find(pattern.as_str()) {
5835                                        Some(idx) => Ok(Value::Variant {
5836                                            enum_name: "Option".to_string(),
5837                                            variant_name: "Some".to_string(),
5838                                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5839                                        }),
5840                                        None => Ok(Value::Variant {
5841                                            enum_name: "Option".to_string(),
5842                                            variant_name: "None".to_string(),
5843                                            fields: None,
5844                                        }),
5845                                    }
5846                                }
5847                                Value::Function(f) => {
5848                                    for (idx, c) in s.chars().enumerate() {
5849                                        let result = self.call_function(f, vec![Value::Char(c)])?;
5850                                        if let Value::Bool(true) = result {
5851                                            return Ok(Value::Variant {
5852                                                enum_name: "Option".to_string(),
5853                                                variant_name: "Some".to_string(),
5854                                                fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5855                                            });
5856                                        }
5857                                    }
5858                                    return Ok(Value::Variant {
5859                                        enum_name: "Option".to_string(),
5860                                        variant_name: "None".to_string(),
5861                                        fields: None,
5862                                    })
5863                                }
5864                                _ => return Err(RuntimeError::new("find expects a char, string, or closure")),
5865                            }
5866                        }
5867                        (Value::String(s), "trim") => return Ok(Value::String(Rc::new(s.trim().to_string()))),
5868                        (Value::String(s), "is_empty") => return Ok(Value::Bool(s.is_empty())),
5869                        (Value::String(s), "len") => return Ok(Value::Int(s.len() as i64)),
5870                        (Value::String(s), "to_string") => return Ok(Value::String(s.clone())),
5871                        (Value::String(s), "chars") => {
5872                            let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5873                            return Ok(Value::Array(Rc::new(RefCell::new(chars))))
5874                        }
5875                        (Value::String(s), "starts_with") => {
5876                            if let Some(Value::String(prefix)) = arg_values.first() {
5877                                return Ok(Value::Bool(s.starts_with(prefix.as_str())));
5878                            }
5879                            return Err(RuntimeError::new("starts_with expects string argument"));
5880                        }
5881                        _ => {}
5882                    }
5883                }
5884                Err(RuntimeError::new(format!(
5885                    "Cannot call method {} on Ref to non-struct",
5886                    method.name
5887                )))
5888            }
5889            // Try struct method lookup: StructName·method
5890            (Value::Struct { name, fields }, _) => {
5891                // Built-in struct methods
5892                if method.name == "clone" {
5893                    // Clone the struct value
5894                    return Ok(recv.clone());
5895                }
5896                // PathBuf struct methods
5897                if name == "PathBuf" || name == "Path" {
5898                    let borrowed = fields.borrow();
5899                    if let Some(Value::String(path)) = borrowed.get("path") {
5900                        match method.name.as_str() {
5901                            "exists" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).exists())),
5902                            "is_dir" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_dir())),
5903                            "is_file" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_file())),
5904                            "join" => {
5905                                if let Some(Value::String(other)) = arg_values.first() {
5906                                    let new_path = std::path::Path::new(path.as_str()).join(other.as_str());
5907                                    let mut new_fields = std::collections::HashMap::new();
5908                                    new_fields.insert("path".to_string(), Value::String(Rc::new(new_path.to_string_lossy().to_string())));
5909                                    return Ok(Value::Struct {
5910                                        name: "PathBuf".to_string(),
5911                                        fields: Rc::new(RefCell::new(new_fields)),
5912                                    });
5913                                }
5914                                return Err(RuntimeError::new("join requires string argument"));
5915                            }
5916                            "parent" => {
5917                                let p = std::path::Path::new(path.as_str());
5918                                return match p.parent() {
5919                                    Some(par) => {
5920                                        let mut new_fields = std::collections::HashMap::new();
5921                                        new_fields.insert("path".to_string(), Value::String(Rc::new(par.to_string_lossy().to_string())));
5922                                        Ok(Value::Struct {
5923                                            name: "PathBuf".to_string(),
5924                                            fields: Rc::new(RefCell::new(new_fields)),
5925                                        })
5926                                    }
5927                                    None => Ok(Value::Null),
5928                                };
5929                            }
5930                            "file_name" => {
5931                                let p = std::path::Path::new(path.as_str());
5932                                return match p.file_name() {
5933                                    Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5934                                    None => Ok(Value::Null),
5935                                };
5936                            }
5937                            "extension" => {
5938                                let p = std::path::Path::new(path.as_str());
5939                                return match p.extension() {
5940                                    Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5941                                    None => Ok(Value::Null),
5942                                };
5943                            }
5944                            "to_string" | "display" => {
5945                                return Ok(Value::String(path.clone()));
5946                            }
5947                            _ => {}
5948                        }
5949                    }
5950                }
5951                // Rc struct methods
5952                if name == "Rc" {
5953                    let borrowed = fields.borrow();
5954                    if let Some(value) = borrowed.get("_value") {
5955                        match method.name.as_str() {
5956                            "clone" => {
5957                                // Return a new Rc with same value
5958                                let mut new_fields = HashMap::new();
5959                                new_fields.insert("_value".to_string(), value.clone());
5960                                return Ok(Value::Struct {
5961                                    name: "Rc".to_string(),
5962                                    fields: Rc::new(RefCell::new(new_fields)),
5963                                });
5964                            }
5965                            _ => {}
5966                        }
5967                    }
5968                }
5969                // Cell struct methods
5970                if name == "Cell" {
5971                    match method.name.as_str() {
5972                        "get" => {
5973                            let borrowed = fields.borrow();
5974                            if let Some(value) = borrowed.get("_value") {
5975                                return Ok(value.clone());
5976                            }
5977                            return Err(RuntimeError::new("Cell has no value"));
5978                        }
5979                        "set" => {
5980                            if arg_values.len() != 1 {
5981                                return Err(RuntimeError::new("set expects 1 argument"));
5982                            }
5983                            fields.borrow_mut().insert("_value".to_string(), arg_values[0].clone());
5984                            return Ok(Value::Null);
5985                        }
5986                        _ => {}
5987                    }
5988                }
5989                // Duration struct methods
5990                if name == "Duration" {
5991                    let borrowed = fields.borrow();
5992                    let secs = match borrowed.get("secs") {
5993                        Some(Value::Int(s)) => *s,
5994                        _ => 0,
5995                    };
5996                    let nanos = match borrowed.get("nanos") {
5997                        Some(Value::Int(n)) => *n,
5998                        _ => 0,
5999                    };
6000                    match method.name.as_str() {
6001                        "as_secs" => return Ok(Value::Int(secs)),
6002                        "as_millis" => return Ok(Value::Int(secs * 1000 + nanos / 1_000_000)),
6003                        "as_micros" => return Ok(Value::Int(secs * 1_000_000 + nanos / 1000)),
6004                        "as_nanos" => return Ok(Value::Int(secs * 1_000_000_000 + nanos)),
6005                        "subsec_nanos" => return Ok(Value::Int(nanos)),
6006                        "subsec_millis" => return Ok(Value::Int(nanos / 1_000_000)),
6007                        "is_zero" => return Ok(Value::Bool(secs == 0 && nanos == 0)),
6008                        _ => {}
6009                    }
6010                }
6011                // Mutex methods - lock() returns a Ref to the inner value
6012                if name == "Mutex" {
6013                    match method.name.as_str() {
6014                        "lock" => {
6015                            // lock() returns a guard that provides access to inner value
6016                            // In the interpreter, we just return a Ref to the inner value
6017                            let borrowed = fields.borrow();
6018                            if let Some(inner) = borrowed.get("__inner__") {
6019                                // Return a Ref wrapping the inner value for mutation
6020                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6021                            }
6022                            return Err(RuntimeError::new("Mutex has no inner value"));
6023                        }
6024                        "try_lock" => {
6025                            // try_lock() returns Some(guard) - in interpreter always succeeds
6026                            let borrowed = fields.borrow();
6027                            if let Some(inner) = borrowed.get("__inner__") {
6028                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6029                                return Ok(Value::Variant {
6030                                    enum_name: "Option".to_string(),
6031                                    variant_name: "Some".to_string(),
6032                                    fields: Some(Rc::new(vec![guard])),
6033                                });
6034                            }
6035                            return Ok(Value::Variant {
6036                                enum_name: "Option".to_string(),
6037                                variant_name: "None".to_string(),
6038                                fields: None,
6039                            });
6040                        }
6041                        "into_inner" => {
6042                            // into_inner() consumes the mutex and returns the inner value
6043                            let borrowed = fields.borrow();
6044                            if let Some(inner) = borrowed.get("__inner__") {
6045                                return Ok(inner.clone());
6046                            }
6047                            return Err(RuntimeError::new("Mutex has no inner value"));
6048                        }
6049                        "get_mut" => {
6050                            // get_mut() returns &mut T when we have exclusive access
6051                            let borrowed = fields.borrow();
6052                            if let Some(inner) = borrowed.get("__inner__") {
6053                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6054                            }
6055                            return Err(RuntimeError::new("Mutex has no inner value"));
6056                        }
6057                        _ => {}
6058                    }
6059                }
6060                // RwLock methods - read() and write() return guards
6061                if name == "RwLock" {
6062                    match method.name.as_str() {
6063                        "read" => {
6064                            // read() returns a read guard
6065                            let borrowed = fields.borrow();
6066                            if let Some(inner) = borrowed.get("__inner__") {
6067                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6068                            }
6069                            return Err(RuntimeError::new("RwLock has no inner value"));
6070                        }
6071                        "write" => {
6072                            // write() returns a write guard
6073                            let borrowed = fields.borrow();
6074                            if let Some(inner) = borrowed.get("__inner__") {
6075                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6076                            }
6077                            return Err(RuntimeError::new("RwLock has no inner value"));
6078                        }
6079                        "try_read" => {
6080                            let borrowed = fields.borrow();
6081                            if let Some(inner) = borrowed.get("__inner__") {
6082                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6083                                return Ok(Value::Variant {
6084                                    enum_name: "Option".to_string(),
6085                                    variant_name: "Some".to_string(),
6086                                    fields: Some(Rc::new(vec![guard])),
6087                                });
6088                            }
6089                            return Ok(Value::Variant {
6090                                enum_name: "Option".to_string(),
6091                                variant_name: "None".to_string(),
6092                                fields: None,
6093                            });
6094                        }
6095                        "try_write" => {
6096                            let borrowed = fields.borrow();
6097                            if let Some(inner) = borrowed.get("__inner__") {
6098                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6099                                return Ok(Value::Variant {
6100                                    enum_name: "Option".to_string(),
6101                                    variant_name: "Some".to_string(),
6102                                    fields: Some(Rc::new(vec![guard])),
6103                                });
6104                            }
6105                            return Ok(Value::Variant {
6106                                enum_name: "Option".to_string(),
6107                                variant_name: "None".to_string(),
6108                                fields: None,
6109                            });
6110                        }
6111                        "into_inner" => {
6112                            let borrowed = fields.borrow();
6113                            if let Some(inner) = borrowed.get("__inner__") {
6114                                return Ok(inner.clone());
6115                            }
6116                            return Err(RuntimeError::new("RwLock has no inner value"));
6117                        }
6118                        _ => {}
6119                    }
6120                }
6121                // Atomic methods - load/store/fetch_add etc.
6122                if name == "AtomicU64" || name == "AtomicUsize" || name == "AtomicI64" || name == "AtomicIsize" {
6123                    match method.name.as_str() {
6124                        "load" => {
6125                            // load() returns the current value
6126                            let borrowed = fields.borrow();
6127                            if let Some(val) = borrowed.get("__value__") {
6128                                return Ok(val.clone());
6129                            }
6130                            return Ok(Value::Int(0));
6131                        }
6132                        "store" => {
6133                            // store(value) sets the value
6134                            if let Some(new_val) = arg_values.first() {
6135                                fields.borrow_mut().insert("__value__".to_string(), new_val.clone());
6136                                return Ok(Value::Null);
6137                            }
6138                            return Err(RuntimeError::new("store requires a value"));
6139                        }
6140                        "fetch_add" => {
6141                            // fetch_add(n) adds n and returns old value
6142                            if let Some(Value::Int(n)) = arg_values.first() {
6143                                let mut borrowed = fields.borrow_mut();
6144                                let old = match borrowed.get("__value__") {
6145                                    Some(Value::Int(v)) => *v,
6146                                    _ => 0,
6147                                };
6148                                borrowed.insert("__value__".to_string(), Value::Int(old + n));
6149                                return Ok(Value::Int(old));
6150                            }
6151                            return Err(RuntimeError::new("fetch_add requires integer"));
6152                        }
6153                        "fetch_sub" => {
6154                            if let Some(Value::Int(n)) = arg_values.first() {
6155                                let mut borrowed = fields.borrow_mut();
6156                                let old = match borrowed.get("__value__") {
6157                                    Some(Value::Int(v)) => *v,
6158                                    _ => 0,
6159                                };
6160                                borrowed.insert("__value__".to_string(), Value::Int(old - n));
6161                                return Ok(Value::Int(old));
6162                            }
6163                            return Err(RuntimeError::new("fetch_sub requires integer"));
6164                        }
6165                        "swap" => {
6166                            if let Some(new_val) = arg_values.first() {
6167                                let mut borrowed = fields.borrow_mut();
6168                                let old = borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
6169                                borrowed.insert("__value__".to_string(), new_val.clone());
6170                                return Ok(old);
6171                            }
6172                            return Err(RuntimeError::new("swap requires a value"));
6173                        }
6174                        "compare_exchange" | "compare_and_swap" => {
6175                            // compare_exchange(current, new) - if value == current, set to new
6176                            if arg_values.len() >= 2 {
6177                                let current = &arg_values[0];
6178                                let new_val = &arg_values[1];
6179                                let mut borrowed = fields.borrow_mut();
6180                                let actual = borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
6181                                if self.values_equal(&actual, current) {
6182                                    borrowed.insert("__value__".to_string(), new_val.clone());
6183                                    return Ok(Value::Variant {
6184                                        enum_name: "Result".to_string(),
6185                                        variant_name: "Ok".to_string(),
6186                                        fields: Some(Rc::new(vec![actual])),
6187                                    });
6188                                } else {
6189                                    return Ok(Value::Variant {
6190                                        enum_name: "Result".to_string(),
6191                                        variant_name: "Err".to_string(),
6192                                        fields: Some(Rc::new(vec![actual])),
6193                                    });
6194                                }
6195                            }
6196                            return Err(RuntimeError::new("compare_exchange requires two arguments"));
6197                        }
6198                        _ => {}
6199                    }
6200                }
6201                // AtomicBool methods
6202                if name == "AtomicBool" {
6203                    match method.name.as_str() {
6204                        "load" => {
6205                            let borrowed = fields.borrow();
6206                            if let Some(val) = borrowed.get("__value__") {
6207                                return Ok(val.clone());
6208                            }
6209                            return Ok(Value::Bool(false));
6210                        }
6211                        "store" => {
6212                            if let Some(new_val) = arg_values.first() {
6213                                fields.borrow_mut().insert("__value__".to_string(), new_val.clone());
6214                                return Ok(Value::Null);
6215                            }
6216                            return Err(RuntimeError::new("store requires a value"));
6217                        }
6218                        "swap" => {
6219                            if let Some(new_val) = arg_values.first() {
6220                                let mut borrowed = fields.borrow_mut();
6221                                let old = borrowed.get("__value__").cloned().unwrap_or(Value::Bool(false));
6222                                borrowed.insert("__value__".to_string(), new_val.clone());
6223                                return Ok(old);
6224                            }
6225                            return Err(RuntimeError::new("swap requires a value"));
6226                        }
6227                        "fetch_and" => {
6228                            if let Some(Value::Bool(b)) = arg_values.first() {
6229                                let mut borrowed = fields.borrow_mut();
6230                                let old = match borrowed.get("__value__") {
6231                                    Some(Value::Bool(v)) => *v,
6232                                    _ => false,
6233                                };
6234                                borrowed.insert("__value__".to_string(), Value::Bool(old && *b));
6235                                return Ok(Value::Bool(old));
6236                            }
6237                            return Err(RuntimeError::new("fetch_and requires boolean"));
6238                        }
6239                        "fetch_or" => {
6240                            if let Some(Value::Bool(b)) = arg_values.first() {
6241                                let mut borrowed = fields.borrow_mut();
6242                                let old = match borrowed.get("__value__") {
6243                                    Some(Value::Bool(v)) => *v,
6244                                    _ => false,
6245                                };
6246                                borrowed.insert("__value__".to_string(), Value::Bool(old || *b));
6247                                return Ok(Value::Bool(old));
6248                            }
6249                            return Err(RuntimeError::new("fetch_or requires boolean"));
6250                        }
6251                        _ => {}
6252                    }
6253                }
6254                if method.name == "to_string" {
6255                    // Generic to_string for structs - returns a debug representation
6256                    let field_str = fields.borrow().iter()
6257                        .map(|(k, v)| format!("{}: {}", k, v))
6258                        .collect::<Vec<_>>()
6259                        .join(", ");
6260                    return Ok(Value::String(Rc::new(format!("{} {{ {} }}", name, field_str))));
6261                }
6262
6263                // Pattern methods - for AST patterns stored as structs (Pattern::Ident, Pattern::Tuple, etc.)
6264                if name.starts_with("Pattern::") {
6265                    match method.name.as_str() {
6266                        "evidentiality" => {
6267                            // Return the evidentiality field from the pattern struct
6268                            if let Some(ev) = fields.borrow().get("evidentiality") {
6269                                return Ok(ev.clone());
6270                            }
6271                            return Ok(Value::Null);
6272                        }
6273                        "name" | "binding_name" => {
6274                            // Return the name field from the pattern struct (for binding purposes)
6275                            if let Some(n) = fields.borrow().get("name") {
6276                                // The name field might be an Ident struct with a nested "name" field
6277                                // Extract the inner string if that's the case
6278                                let result = match &n {
6279                                    Value::Struct { fields: inner_fields, .. } => {
6280                                        if let Some(inner_name) = inner_fields.borrow().get("name") {
6281                                            crate::sigil_debug!("DEBUG binding_name: returning inner name {} from {}", inner_name, name);
6282                                            inner_name.clone()
6283                                        } else {
6284                                            crate::sigil_debug!("DEBUG binding_name: returning struct {} from {}", n, name);
6285                                            n.clone()
6286                                        }
6287                                    }
6288                                    _ => {
6289                                        crate::sigil_debug!("DEBUG binding_name: returning {} from {}", n, name);
6290                                        n.clone()
6291                                    }
6292                                };
6293                                return Ok(result);
6294                            }
6295                            crate::sigil_debug!("DEBUG binding_name: 'name' field not found in {}, fields: {:?}", name, fields.borrow().keys().collect::<Vec<_>>());
6296                            // For Pattern::Ident, name is the binding name
6297                            return Ok(Value::Null);
6298                        }
6299                        "mutable" => {
6300                            // Return the mutable field from the pattern struct
6301                            if let Some(m) = fields.borrow().get("mutable") {
6302                                return Ok(m.clone());
6303                            }
6304                            return Ok(Value::Bool(false));
6305                        }
6306                        "is_ident" => {
6307                            return Ok(Value::Bool(name == "Pattern::Ident"));
6308                        }
6309                        "is_wildcard" => {
6310                            return Ok(Value::Bool(name == "Pattern::Wildcard"));
6311                        }
6312                        "clone" => {
6313                            return Ok(recv.clone());
6314                        }
6315                        _ => {}
6316                    }
6317                }
6318
6319                // PathBuf methods
6320                if name == "PathBuf" || name == "Path" {
6321                    match method.name.as_str() {
6322                        "exists" => {
6323                            // Check if path exists
6324                            let path = match fields.borrow().get("path") {
6325                                Some(Value::String(s)) => s.to_string(),
6326                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6327                            };
6328                            return Ok(Value::Bool(std::path::Path::new(&path).exists()));
6329                        }
6330                        "is_dir" => {
6331                            let path = match fields.borrow().get("path") {
6332                                Some(Value::String(s)) => s.to_string(),
6333                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6334                            };
6335                            return Ok(Value::Bool(std::path::Path::new(&path).is_dir()));
6336                        }
6337                        "is_file" => {
6338                            let path = match fields.borrow().get("path") {
6339                                Some(Value::String(s)) => s.to_string(),
6340                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6341                            };
6342                            return Ok(Value::Bool(std::path::Path::new(&path).is_file()));
6343                        }
6344                        "extension" => {
6345                            let path = match fields.borrow().get("path") {
6346                                Some(Value::String(s)) => s.to_string(),
6347                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6348                            };
6349                            match std::path::Path::new(&path).extension() {
6350                                Some(ext) => {
6351                                    // Return Option::Some with an OsStr-like struct
6352                                    let ext_str = ext.to_string_lossy().to_string();
6353                                    let mut ext_fields = HashMap::new();
6354                                    ext_fields.insert("value".to_string(), Value::String(Rc::new(ext_str)));
6355                                    return Ok(Value::Variant {
6356                                        enum_name: "Option".to_string(),
6357                                        variant_name: "Some".to_string(),
6358                                        fields: Some(Rc::new(vec![Value::Struct {
6359                                            name: "OsStr".to_string(),
6360                                            fields: Rc::new(RefCell::new(ext_fields)),
6361                                        }])),
6362                                    });
6363                                }
6364                                None => {
6365                                    return Ok(Value::Variant {
6366                                        enum_name: "Option".to_string(),
6367                                        variant_name: "None".to_string(),
6368                                        fields: None,
6369                                    });
6370                                }
6371                            }
6372                        }
6373                        "file_name" => {
6374                            let path = match fields.borrow().get("path") {
6375                                Some(Value::String(s)) => s.to_string(),
6376                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6377                            };
6378                            match std::path::Path::new(&path).file_name() {
6379                                Some(fname) => {
6380                                    let fname_str = fname.to_string_lossy().to_string();
6381                                    let mut fname_fields = HashMap::new();
6382                                    fname_fields.insert("value".to_string(), Value::String(Rc::new(fname_str)));
6383                                    return Ok(Value::Variant {
6384                                        enum_name: "Option".to_string(),
6385                                        variant_name: "Some".to_string(),
6386                                        fields: Some(Rc::new(vec![Value::Struct {
6387                                            name: "OsStr".to_string(),
6388                                            fields: Rc::new(RefCell::new(fname_fields)),
6389                                        }])),
6390                                    });
6391                                }
6392                                None => {
6393                                    return Ok(Value::Variant {
6394                                        enum_name: "Option".to_string(),
6395                                        variant_name: "None".to_string(),
6396                                        fields: None,
6397                                    });
6398                                }
6399                            }
6400                        }
6401                        "parent" => {
6402                            let path = match fields.borrow().get("path") {
6403                                Some(Value::String(s)) => s.to_string(),
6404                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6405                            };
6406                            match std::path::Path::new(&path).parent() {
6407                                Some(parent) => {
6408                                    let mut parent_fields = HashMap::new();
6409                                    parent_fields.insert("path".to_string(), Value::String(Rc::new(parent.to_string_lossy().to_string())));
6410                                    return Ok(Value::Variant {
6411                                        enum_name: "Option".to_string(),
6412                                        variant_name: "Some".to_string(),
6413                                        fields: Some(Rc::new(vec![Value::Struct {
6414                                            name: "Path".to_string(),
6415                                            fields: Rc::new(RefCell::new(parent_fields)),
6416                                        }])),
6417                                    });
6418                                }
6419                                None => {
6420                                    return Ok(Value::Variant {
6421                                        enum_name: "Option".to_string(),
6422                                        variant_name: "None".to_string(),
6423                                        fields: None,
6424                                    });
6425                                }
6426                            }
6427                        }
6428                        "to_str" => {
6429                            // Convert to string (returns Option<&str>, we just return the string)
6430                            let path = match fields.borrow().get("path") {
6431                                Some(Value::String(s)) => s.clone(),
6432                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6433                            };
6434                            // Wrap in Some for unwrap() compatibility
6435                            return Ok(Value::Variant {
6436                                enum_name: "Option".to_string(),
6437                                variant_name: "Some".to_string(),
6438                                fields: Some(Rc::new(vec![Value::String(path)])),
6439                            });
6440                        }
6441                        "to_string_lossy" => {
6442                            let path = match fields.borrow().get("path") {
6443                                Some(Value::String(s)) => s.clone(),
6444                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6445                            };
6446                            return Ok(Value::String(path));
6447                        }
6448                        "join" => {
6449                            // Join path with another component
6450                            if arg_values.is_empty() {
6451                                return Err(RuntimeError::new("join expects 1 argument"));
6452                            }
6453                            let base = match fields.borrow().get("path") {
6454                                Some(Value::String(s)) => s.to_string(),
6455                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6456                            };
6457                            let component = match &arg_values[0] {
6458                                Value::String(s) => s.to_string(),
6459                                Value::Struct { name: n, fields: f } if n == "PathBuf" || n == "Path" => {
6460                                    match f.borrow().get("path") {
6461                                        Some(Value::String(s)) => s.to_string(),
6462                                        _ => return Err(RuntimeError::new("PathBuf has no path field")),
6463                                    }
6464                                }
6465                                _ => return Err(RuntimeError::new("join expects string or PathBuf")),
6466                            };
6467                            let joined = std::path::Path::new(&base).join(&component);
6468                            let mut new_fields = HashMap::new();
6469                            new_fields.insert("path".to_string(), Value::String(Rc::new(joined.to_string_lossy().to_string())));
6470                            return Ok(Value::Struct {
6471                                name: "PathBuf".to_string(),
6472                                fields: Rc::new(RefCell::new(new_fields)),
6473                            });
6474                        }
6475                        "display" => {
6476                            let path = match fields.borrow().get("path") {
6477                                Some(Value::String(s)) => s.clone(),
6478                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
6479                            };
6480                            return Ok(Value::String(path));
6481                        }
6482                        "to_path_buf" => {
6483                            // Path -> PathBuf (just return a copy)
6484                            return Ok(recv.clone());
6485                        }
6486                        _ => {}
6487                    }
6488                }
6489
6490                // OsStr methods
6491                if name == "OsStr" {
6492                    match method.name.as_str() {
6493                        "to_str" => {
6494                            let val = match fields.borrow().get("value") {
6495                                Some(Value::String(s)) => s.clone(),
6496                                _ => return Err(RuntimeError::new("OsStr has no value field")),
6497                            };
6498                            return Ok(Value::Variant {
6499                                enum_name: "Option".to_string(),
6500                                variant_name: "Some".to_string(),
6501                                fields: Some(Rc::new(vec![Value::String(val)])),
6502                            });
6503                        }
6504                        "to_string_lossy" => {
6505                            let val = match fields.borrow().get("value") {
6506                                Some(Value::String(s)) => s.clone(),
6507                                _ => return Err(RuntimeError::new("OsStr has no value field")),
6508                            };
6509                            return Ok(Value::String(val));
6510                        }
6511                        "to_lowercase" => {
6512                            let val = match fields.borrow().get("value") {
6513                                Some(Value::String(s)) => s.to_lowercase(),
6514                                _ => return Err(RuntimeError::new("OsStr has no value field")),
6515                            };
6516                            return Ok(Value::String(Rc::new(val)));
6517                        }
6518                        "as_str" => {
6519                            let val = match fields.borrow().get("value") {
6520                                Some(Value::String(s)) => s.clone(),
6521                                _ => return Err(RuntimeError::new("OsStr has no value field")),
6522                            };
6523                            return Ok(Value::String(val));
6524                        }
6525                        _ => {}
6526                    }
6527                }
6528
6529                // DirEntry methods
6530                if name == "DirEntry" {
6531                    match method.name.as_str() {
6532                        "path" => {
6533                            let path = match fields.borrow().get("path") {
6534                                Some(Value::String(s)) => s.clone(),
6535                                _ => return Err(RuntimeError::new("DirEntry has no path field")),
6536                            };
6537                            let mut path_fields = HashMap::new();
6538                            path_fields.insert("path".to_string(), Value::String(path));
6539                            return Ok(Value::Struct {
6540                                name: "PathBuf".to_string(),
6541                                fields: Rc::new(RefCell::new(path_fields)),
6542                            });
6543                        }
6544                        "file_name" => {
6545                            let path = match fields.borrow().get("path") {
6546                                Some(Value::String(s)) => s.to_string(),
6547                                _ => return Err(RuntimeError::new("DirEntry has no path field")),
6548                            };
6549                            let fname = std::path::Path::new(&path)
6550                                .file_name()
6551                                .map(|f| f.to_string_lossy().to_string())
6552                                .unwrap_or_default();
6553                            let mut fname_fields = HashMap::new();
6554                            fname_fields.insert("value".to_string(), Value::String(Rc::new(fname)));
6555                            return Ok(Value::Struct {
6556                                name: "OsStr".to_string(),
6557                                fields: Rc::new(RefCell::new(fname_fields)),
6558                            });
6559                        }
6560                        _ => {}
6561                    }
6562                }
6563
6564                // Map methods - for built-in hash map operations
6565                if name == "Map" {
6566                    match method.name.as_str() {
6567                        "get" => {
6568                            // map.get(key) -> ?value
6569                            if arg_values.len() != 1 {
6570                                return Err(RuntimeError::new("Map.get expects 1 argument"));
6571                            }
6572                            let key = match &arg_values[0] {
6573                                Value::String(s) => s.to_string(),
6574                                Value::Int(n) => n.to_string(),
6575                                other => format!("{:?}", other),
6576                            };
6577                            if let Some(val) = fields.borrow().get(&key) {
6578                                return Ok(val.clone());
6579                            }
6580                            return Ok(Value::Null);
6581                        }
6582                        "insert" => {
6583                            // map.insert(key, value)
6584                            if arg_values.len() != 2 {
6585                                return Err(RuntimeError::new("Map.insert expects 2 arguments"));
6586                            }
6587                            let key = match &arg_values[0] {
6588                                Value::String(s) => s.to_string(),
6589                                Value::Int(n) => n.to_string(),
6590                                other => format!("{:?}", other),
6591                            };
6592                            crate::sigil_debug!("DEBUG Map.insert: key='{}', value={}", key, arg_values[1]);
6593                            fields.borrow_mut().insert(key, arg_values[1].clone());
6594                            return Ok(Value::Null);
6595                        }
6596                        "contains_key" => {
6597                            if arg_values.len() != 1 {
6598                                return Err(RuntimeError::new("Map.contains_key expects 1 argument"));
6599                            }
6600                            let key = match &arg_values[0] {
6601                                Value::String(s) => s.to_string(),
6602                                Value::Int(n) => n.to_string(),
6603                                other => format!("{:?}", other),
6604                            };
6605                            return Ok(Value::Bool(fields.borrow().contains_key(&key)));
6606                        }
6607                        "len" => {
6608                            return Ok(Value::Int(fields.borrow().len() as i64));
6609                        }
6610                        "is_empty" => {
6611                            return Ok(Value::Bool(fields.borrow().is_empty()));
6612                        }
6613                        "keys" => {
6614                            let keys: Vec<Value> = fields.borrow()
6615                                .keys()
6616                                .map(|k| Value::String(Rc::new(k.clone())))
6617                                .collect();
6618                            return Ok(Value::Array(Rc::new(RefCell::new(keys))));
6619                        }
6620                        "values" => {
6621                            let vals: Vec<Value> = fields.borrow()
6622                                .values()
6623                                .cloned()
6624                                .collect();
6625                            return Ok(Value::Array(Rc::new(RefCell::new(vals))));
6626                        }
6627                        "clone" => {
6628                            return Ok(recv.clone());
6629                        }
6630                        _ => {}
6631                    }
6632                }
6633
6634                let qualified_name = format!("{}·{}", name, method.name);
6635
6636                // Debug: track Parser method calls
6637                if name == "Parser" && (method.name == "parse_file" || method.name == "read_source") {
6638                    crate::sigil_debug!("DEBUG Parser method call: {}", qualified_name);
6639                    for (i, arg) in arg_values.iter().enumerate() {
6640                        crate::sigil_debug!("  arg_value[{}] = {:?}", i, arg);
6641                    }
6642                }
6643
6644                // Debug: track Lexer method calls
6645                if name == "Lexer" {
6646                    // Print all args for lex_ident_or_keyword
6647                    if method.name == "lex_ident_or_keyword" {
6648                        for (i, arg) in arg_values.iter().enumerate() {
6649                            let unwrapped = Self::unwrap_all(arg);
6650                            if let Value::Char(c) = &unwrapped {
6651                                crate::sigil_debug!("DEBUG Lexer·lex_ident_or_keyword arg[{}]='{}'", i, c);
6652                            }
6653                        }
6654                    }
6655                    crate::sigil_debug!("DEBUG Lexer method call: {}", qualified_name);
6656                }
6657                // Check if arg is "fn" string
6658                for arg in &arg_values {
6659                    let unwrapped = Self::unwrap_all(arg);
6660                    if let Value::String(s) = &unwrapped {
6661                        if **s == "fn" {
6662                            crate::sigil_debug!("DEBUG struct method with 'fn': {} recv_name={}", method.name, name);
6663                        }
6664                    }
6665                }
6666
6667                let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
6668                if let Some(func) = func {
6669                    if let Value::Function(f) = func {
6670                        // Set current Self type for Self { ... } resolution
6671                        let old_self_type = self.current_self_type.take();
6672                        self.current_self_type = Some(name.clone());
6673
6674                        // Call with self as first argument
6675                        let mut all_args = vec![recv.clone()];
6676                        all_args.extend(arg_values.clone());
6677                        let result = self.call_function(&f, all_args);
6678
6679                        // Restore old Self type
6680                        self.current_self_type = old_self_type;
6681                        return result;
6682                    } else if let Value::BuiltIn(b) = func {
6683                        let mut all_args = vec![recv.clone()];
6684                        all_args.extend(arg_values.clone());
6685                        return (b.func)(self, all_args);
6686                    }
6687                }
6688
6689                // If struct name is "Self", try to find the method by searching all types
6690                if name == "Self" {
6691                    // Get field names to match struct type
6692                    let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
6693
6694                    // Search through registered types to find a matching struct
6695                    for (type_name, type_def) in &self.types {
6696                        if let TypeDef::Struct(struct_def) = type_def {
6697                            // Check if field names match
6698                            let def_fields: Vec<String> = match &struct_def.fields {
6699                                crate::ast::StructFields::Named(fs) => fs.iter().map(|f| f.name.name.clone()).collect(),
6700                                _ => continue,
6701                            };
6702
6703                            // Rough match - if we have fields that exist in the definition
6704                            let matches = field_names.iter().all(|f| def_fields.contains(f));
6705                            if matches {
6706                                let qualified_name = format!("{}·{}", type_name, method.name);
6707                                let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
6708                                if let Some(func) = func {
6709                                    if let Value::Function(f) = func {
6710                                        // Set current Self type for Self { ... } resolution
6711                                        let old_self_type = self.current_self_type.take();
6712                                        self.current_self_type = Some(type_name.clone());
6713
6714                                        let mut all_args = vec![recv.clone()];
6715                                        all_args.extend(arg_values.clone());
6716                                        let result = self.call_function(&f, all_args);
6717
6718                                        // Restore old Self type
6719                                        self.current_self_type = old_self_type;
6720                                        return result;
6721                                    } else if let Value::BuiltIn(b) = func {
6722                                        let mut all_args = vec![recv.clone()];
6723                                        all_args.extend(arg_values.clone());
6724                                        return (b.func)(self, all_args);
6725                                    }
6726                                }
6727                            }
6728                        }
6729                    }
6730                }
6731
6732                // Fallback for unknown methods on external types: return null
6733                // This allows code using external crate types to run without full loading
6734                crate::sigil_warn!("WARN: Unknown method '{}' on '{}' - returning null", method.name, name);
6735                Ok(Value::Null)
6736            }
6737            // Try variant method lookup: EnumName·method
6738            (Value::Variant { enum_name, variant_name, fields }, _) => {
6739                // Built-in Option methods
6740                if enum_name == "Option" {
6741                    match method.name.as_str() {
6742                        "cloned" => {
6743                            // cloned() on Option<&T> returns Option<T>
6744                            // In our interpreter, just clone the value
6745                            return Ok(recv.clone());
6746                        }
6747                        "is_some" => {
6748                            return Ok(Value::Bool(variant_name == "Some"));
6749                        }
6750                        "is_none" => {
6751                            return Ok(Value::Bool(variant_name == "None"));
6752                        }
6753                        "unwrap" => {
6754                            crate::sigil_debug!("DEBUG Option.unwrap: variant={}, fields={:?}", variant_name, fields);
6755                            if variant_name == "Some" {
6756                                if let Some(f) = fields {
6757                                    let result = f.first().cloned().unwrap_or(Value::Null);
6758                                    crate::sigil_debug!("DEBUG Option.unwrap: returning {:?}", result);
6759                                    return Ok(result);
6760                                }
6761                            }
6762                            return Err(RuntimeError::new("unwrap on None"));
6763                        }
6764                        "unwrap_or" => {
6765                            if variant_name == "Some" {
6766                                if let Some(f) = fields {
6767                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
6768                                }
6769                            }
6770                            return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
6771                        }
6772                        "map" => {
6773                            // Option::map takes a closure
6774                            if variant_name == "Some" {
6775                                if let Some(f) = fields {
6776                                    if let Some(inner) = f.first() {
6777                                        if let Some(Value::Function(func)) = arg_values.first() {
6778                                            let result = self.call_function(func, vec![inner.clone()])?;
6779                                            return Ok(Value::Variant {
6780                                                enum_name: "Option".to_string(),
6781                                                variant_name: "Some".to_string(),
6782                                                fields: Some(Rc::new(vec![result])),
6783                                            });
6784                                        }
6785                                    }
6786                                }
6787                            }
6788                            return Ok(Value::Variant {
6789                                enum_name: "Option".to_string(),
6790                                variant_name: "None".to_string(),
6791                                fields: None,
6792                            });
6793                        }
6794                        "and_then" => {
6795                            // Option::and_then takes a closure that returns Option<U>
6796                            crate::sigil_debug!("DEBUG and_then: variant={}, has_fields={}, arg_count={}", variant_name, fields.is_some(), arg_values.len());
6797                            if let Some(arg) = arg_values.first() {
6798                                crate::sigil_debug!("DEBUG and_then: arg type = {:?}", std::mem::discriminant(arg));
6799                            }
6800                            if variant_name == "Some" {
6801                                if let Some(f) = fields {
6802                                    if let Some(inner) = f.first() {
6803                                        crate::sigil_debug!("DEBUG and_then: inner = {:?}", inner);
6804                                        if let Some(Value::Function(func)) = arg_values.first() {
6805                                            let result = self.call_function(func, vec![inner.clone()])?;
6806                                            crate::sigil_debug!("DEBUG and_then: result = {:?}", result);
6807                                            // The closure should return an Option, return it directly
6808                                            return Ok(result);
6809                                        } else {
6810                                            crate::sigil_debug!("DEBUG and_then: arg is not a Function!");
6811                                        }
6812                                    }
6813                                }
6814                            }
6815                            // None case - return None
6816                            return Ok(Value::Variant {
6817                                enum_name: "Option".to_string(),
6818                                variant_name: "None".to_string(),
6819                                fields: None,
6820                            });
6821                        }
6822                        "or_else" => {
6823                            // Option::or_else takes a closure that returns Option<T>
6824                            if variant_name == "Some" {
6825                                // Some case - return self
6826                                return Ok(recv.clone());
6827                            }
6828                            // None case - call the closure
6829                            if let Some(Value::Function(func)) = arg_values.first() {
6830                                return self.call_function(func, vec![]);
6831                            }
6832                            return Ok(recv.clone());
6833                        }
6834                        "ok_or" | "ok_or_else" => {
6835                            // Convert Option to Result
6836                            if variant_name == "Some" {
6837                                if let Some(f) = fields {
6838                                    if let Some(inner) = f.first() {
6839                                        return Ok(Value::Variant {
6840                                            enum_name: "Result".to_string(),
6841                                            variant_name: "Ok".to_string(),
6842                                            fields: Some(Rc::new(vec![inner.clone()])),
6843                                        });
6844                                    }
6845                                }
6846                            }
6847                            // None case - return Err with the provided value
6848                            let err_val = arg_values.first().cloned().unwrap_or(Value::String(Rc::new("None".to_string())));
6849                            return Ok(Value::Variant {
6850                                enum_name: "Result".to_string(),
6851                                variant_name: "Err".to_string(),
6852                                fields: Some(Rc::new(vec![err_val])),
6853                            });
6854                        }
6855                        _ => {}
6856                    }
6857                }
6858                // Built-in Result methods
6859                if enum_name == "Result" {
6860                    match method.name.as_str() {
6861                        "is_ok" => {
6862                            return Ok(Value::Bool(variant_name == "Ok"));
6863                        }
6864                        "is_err" => {
6865                            return Ok(Value::Bool(variant_name == "Err"));
6866                        }
6867                        "ok" => {
6868                            // Convert Result<T, E> to Option<T>
6869                            // Ok(val) -> Some(val), Err(_) -> None
6870                            if variant_name == "Ok" {
6871                                let inner = fields.as_ref()
6872                                    .and_then(|f| f.first().cloned())
6873                                    .unwrap_or(Value::Null);
6874                                return Ok(Value::Variant {
6875                                    enum_name: "Option".to_string(),
6876                                    variant_name: "Some".to_string(),
6877                                    fields: Some(Rc::new(vec![inner])),
6878                                });
6879                            }
6880                            return Ok(Value::Variant {
6881                                enum_name: "Option".to_string(),
6882                                variant_name: "None".to_string(),
6883                                fields: None,
6884                            });
6885                        }
6886                        "err" => {
6887                            // Convert Result<T, E> to Option<E>
6888                            // Ok(_) -> None, Err(e) -> Some(e)
6889                            if variant_name == "Err" {
6890                                let inner = fields.as_ref()
6891                                    .and_then(|f| f.first().cloned())
6892                                    .unwrap_or(Value::Null);
6893                                return Ok(Value::Variant {
6894                                    enum_name: "Option".to_string(),
6895                                    variant_name: "Some".to_string(),
6896                                    fields: Some(Rc::new(vec![inner])),
6897                                });
6898                            }
6899                            return Ok(Value::Variant {
6900                                enum_name: "Option".to_string(),
6901                                variant_name: "None".to_string(),
6902                                fields: None,
6903                            });
6904                        }
6905                        "unwrap" => {
6906                            if variant_name == "Ok" {
6907                                if let Some(f) = fields {
6908                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
6909                                }
6910                            }
6911                            return Err(RuntimeError::new("unwrap on Err"));
6912                        }
6913                        "unwrap_or" => {
6914                            if variant_name == "Ok" {
6915                                if let Some(f) = fields {
6916                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
6917                                }
6918                            }
6919                            return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
6920                        }
6921                        "map" => {
6922                            // map(fn) - apply fn to Ok value, leave Err unchanged
6923                            if variant_name == "Ok" {
6924                                if let Some(Value::Function(f)) = arg_values.first() {
6925                                    let inner = fields.as_ref()
6926                                        .and_then(|f| f.first().cloned())
6927                                        .unwrap_or(Value::Null);
6928                                    let result = self.call_function(f, vec![inner])?;
6929                                    return Ok(Value::Variant {
6930                                        enum_name: "Result".to_string(),
6931                                        variant_name: "Ok".to_string(),
6932                                        fields: Some(Rc::new(vec![result])),
6933                                    });
6934                                }
6935                            }
6936                            // For Err variant, return unchanged
6937                            return Ok(recv.clone());
6938                        }
6939                        "map_err" => {
6940                            // map_err(fn) - apply fn to Err value, leave Ok unchanged
6941                            if variant_name == "Err" {
6942                                if let Some(Value::Function(f)) = arg_values.first() {
6943                                    let inner = fields.as_ref()
6944                                        .and_then(|f| f.first().cloned())
6945                                        .unwrap_or(Value::Null);
6946                                    let result = self.call_function(f, vec![inner])?;
6947                                    return Ok(Value::Variant {
6948                                        enum_name: "Result".to_string(),
6949                                        variant_name: "Err".to_string(),
6950                                        fields: Some(Rc::new(vec![result])),
6951                                    });
6952                                }
6953                            }
6954                            // For Ok variant, return unchanged
6955                            return Ok(recv.clone());
6956                        }
6957                        "and_then" => {
6958                            // and_then(fn) - chain Result-returning functions
6959                            if variant_name == "Ok" {
6960                                if let Some(Value::Function(f)) = arg_values.first() {
6961                                    let inner = fields.as_ref()
6962                                        .and_then(|f| f.first().cloned())
6963                                        .unwrap_or(Value::Null);
6964                                    return self.call_function(f, vec![inner]);
6965                                }
6966                            }
6967                            // For Err variant, return unchanged
6968                            return Ok(recv.clone());
6969                        }
6970                        _ => {}
6971                    }
6972                }
6973                // Pattern methods - for AST pattern access
6974                crate::sigil_debug!("DEBUG variant method call: enum_name={}, variant_name={}, method={}", enum_name, variant_name, method.name);
6975
6976                // Type methods
6977                if enum_name == "Type" {
6978                    match method.name.as_str() {
6979                        "is_never" => {
6980                            // Type::Never is the never type, all others are not
6981                            return Ok(Value::Bool(variant_name == "Never"));
6982                        }
6983                        "to_string" => {
6984                            // Convert type to string representation
6985                            let type_str = match variant_name.as_str() {
6986                                "Bool" => "bool".to_string(),
6987                                "Int" => "i64".to_string(),
6988                                "Float" => "f64".to_string(),
6989                                "Str" => "str".to_string(),
6990                                "Char" => "char".to_string(),
6991                                "Unit" => "()".to_string(),
6992                                "Never" => "!".to_string(),
6993                                "Error" => "<error>".to_string(),
6994                                other => format!("Type::{}", other),
6995                            };
6996                            return Ok(Value::String(Rc::new(type_str)));
6997                        }
6998                        _ => {}
6999                    }
7000                }
7001
7002                if enum_name == "Pattern" {
7003                    match method.name.as_str() {
7004                        "evidentiality" => {
7005                            // Pattern::Ident { name, mutable, evidentiality } - return the evidentiality field
7006                            if variant_name == "Ident" {
7007                                if let Some(f) = fields {
7008                                    // Fields are stored as a struct or in order
7009                                    // Try to find evidentiality field
7010                                    for field_val in f.iter() {
7011                                        if let Value::Struct { fields: inner, .. } = field_val {
7012                                            if let Some(ev) = inner.borrow().get("evidentiality") {
7013                                                return Ok(ev.clone());
7014                                            }
7015                                        }
7016                                    }
7017                                    // If fields are stored in order: name, mutable, evidentiality (index 2)
7018                                    if f.len() > 2 {
7019                                        return Ok(f[2].clone());
7020                                    }
7021                                }
7022                            }
7023                            // No evidentiality for other pattern types
7024                            return Ok(Value::Null);
7025                        }
7026                        "name" => {
7027                            // Get the name from Pattern::Ident
7028                            if variant_name == "Ident" {
7029                                if let Some(f) = fields {
7030                                    for field_val in f.iter() {
7031                                        if let Value::Struct { fields: inner, .. } = field_val {
7032                                            if let Some(n) = inner.borrow().get("name") {
7033                                                return Ok(n.clone());
7034                                            }
7035                                        }
7036                                    }
7037                                    // First field is name
7038                                    if let Some(n) = f.first() {
7039                                        return Ok(n.clone());
7040                                    }
7041                                }
7042                            }
7043                            return Ok(Value::Null);
7044                        }
7045                        "mutable" => {
7046                            // Get mutable flag from Pattern::Ident
7047                            if variant_name == "Ident" {
7048                                if let Some(f) = fields {
7049                                    for field_val in f.iter() {
7050                                        if let Value::Struct { fields: inner, .. } = field_val {
7051                                            if let Some(m) = inner.borrow().get("mutable") {
7052                                                return Ok(m.clone());
7053                                            }
7054                                        }
7055                                    }
7056                                    // Second field is mutable
7057                                    if f.len() > 1 {
7058                                        return Ok(f[1].clone());
7059                                    }
7060                                }
7061                            }
7062                            return Ok(Value::Bool(false));
7063                        }
7064                        _ => {}
7065                    }
7066                }
7067                // Built-in clone method for all variants
7068                if method.name == "clone" {
7069                    return Ok(recv.clone());
7070                }
7071
7072                let qualified_name = format!("{}·{}", enum_name, method.name);
7073                let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
7074                if let Some(func) = func {
7075                    if let Value::Function(f) = func {
7076                        let mut all_args = vec![recv.clone()];
7077                        all_args.extend(arg_values.clone());
7078                        return self.call_function(&f, all_args);
7079                    } else if let Value::BuiltIn(b) = func {
7080                        let mut all_args = vec![recv.clone()];
7081                        all_args.extend(arg_values.clone());
7082                        return (b.func)(self, all_args);
7083                    }
7084                }
7085                // Fallback for unknown methods on external enum types: return null
7086                crate::sigil_warn!("WARN: Unknown method '{}' on enum '{}' - returning null", method.name, enum_name);
7087                Ok(Value::Null)
7088            }
7089            // Null-safe method handlers - methods called on null return sensible defaults
7090            (Value::Null, "len_utf8") => Ok(Value::Int(0)),
7091            (Value::Null, "is_ascii") => Ok(Value::Bool(false)),
7092            (Value::Null, "is_alphabetic") => Ok(Value::Bool(false)),
7093            (Value::Null, "is_alphanumeric") => Ok(Value::Bool(false)),
7094            (Value::Null, "is_numeric") | (Value::Null, "is_digit") => Ok(Value::Bool(false)),
7095            (Value::Null, "is_whitespace") => Ok(Value::Bool(false)),
7096            (Value::Null, "is_uppercase") => Ok(Value::Bool(false)),
7097            (Value::Null, "is_lowercase") => Ok(Value::Bool(false)),
7098            (Value::Null, "len") => Ok(Value::Int(0)),
7099            (Value::Null, "is_empty") => Ok(Value::Bool(true)),
7100            (Value::Null, "to_string") => Ok(Value::String(Rc::new("".to_string()))),
7101            (Value::Null, "clone") => Ok(Value::Null),
7102            (Value::Null, "is_some") => Ok(Value::Bool(false)),
7103            (Value::Null, "is_none") => Ok(Value::Bool(true)),
7104            (Value::Null, "unwrap_or") => {
7105                if arg_values.is_empty() {
7106                    Ok(Value::Null)
7107                } else {
7108                    Ok(arg_values[0].clone())
7109                }
7110            }
7111            // unwrap_or for non-null values returns the value itself
7112            (Value::Char(c), "unwrap_or") => Ok(Value::Char(*c)),
7113            (Value::Int(n), "unwrap_or") => Ok(Value::Int(*n)),
7114            (Value::Float(n), "unwrap_or") => Ok(Value::Float(*n)),
7115            (Value::String(s), "unwrap_or") => Ok(Value::String(s.clone())),
7116            (Value::Bool(b), "unwrap_or") => Ok(Value::Bool(*b)),
7117            // Int methods
7118            (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
7119                Ok(Value::String(Rc::new(n.to_string())))
7120            }
7121            (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
7122            (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
7123            (Value::Int(n), "duration_since") => {
7124                // Treat Int as nanoseconds since some epoch
7125                // Return a Duration struct
7126                let other_ns = match arg_values.first() {
7127                    Some(Value::Int(i)) => *i,
7128                    Some(Value::Struct { fields, .. }) => {
7129                        let borrowed = fields.borrow();
7130                        let secs = match borrowed.get("secs") {
7131                            Some(Value::Int(s)) => *s,
7132                            _ => 0,
7133                        };
7134                        let nanos = match borrowed.get("nanos") {
7135                            Some(Value::Int(n)) => *n,
7136                            _ => 0,
7137                        };
7138                        secs * 1_000_000_000 + nanos
7139                    }
7140                    _ => 0,
7141                };
7142                let diff_ns = n - other_ns;
7143                let mut fields = std::collections::HashMap::new();
7144                fields.insert("secs".to_string(), Value::Int(diff_ns / 1_000_000_000));
7145                fields.insert("nanos".to_string(), Value::Int(diff_ns % 1_000_000_000));
7146                Ok(Value::Variant {
7147                    enum_name: "Result".to_string(),
7148                    variant_name: "Ok".to_string(),
7149                    fields: Some(Rc::new(vec![Value::Struct {
7150                        name: "Duration".to_string(),
7151                        fields: Rc::new(RefCell::new(fields)),
7152                    }])),
7153                })
7154            }
7155            // Float methods
7156            (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
7157                Ok(Value::String(Rc::new(n.to_string())))
7158            }
7159            (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
7160            (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
7161            // Bool methods
7162            (Value::Bool(b), "to_string") | (Value::Bool(b), "string") => {
7163                Ok(Value::String(Rc::new(b.to_string())))
7164            }
7165            // Char methods
7166            (Value::Char(c), "to_string") | (Value::Char(c), "string") => {
7167                Ok(Value::String(Rc::new(c.to_string())))
7168            }
7169            _ => {
7170                // Debug: what type is failing method lookup
7171                let recv_type = match &recv {
7172                    Value::String(s) => format!("String(len={})", s.len()),
7173                    Value::Array(arr) => format!("Array(len={})", arr.borrow().len()),
7174                    Value::Struct { name, .. } => format!("Struct({})", name),
7175                    Value::Variant { enum_name, variant_name, .. } => format!("Variant({}::{})", enum_name, variant_name),
7176                    Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
7177                    Value::Null => "Null".to_string(),
7178                    other => format!("{:?}", std::mem::discriminant(other)),
7179                };
7180                crate::sigil_warn!("WARN: Unknown method '{}' on recv_type={} - returning null", method.name, recv_type);
7181                // Fallback for unknown methods: return null to allow external crate types
7182                Ok(Value::Null)
7183            }
7184        }
7185    }
7186
7187    /// Evaluate polysynthetic incorporation: path·file·read·string
7188    /// The first segment provides the initial value, subsequent segments are method-like transformations
7189    fn eval_incorporation(
7190        &mut self,
7191        segments: &[IncorporationSegment],
7192    ) -> Result<Value, RuntimeError> {
7193        if segments.is_empty() {
7194            return Err(RuntimeError::new("empty incorporation chain"));
7195        }
7196
7197        // First segment: get initial value (variable lookup or function call)
7198        let first = &segments[0];
7199        let mut value = if let Some(args) = &first.args {
7200            // First segment is a function call: func(args)·next·...
7201            let arg_values: Vec<Value> = args
7202                .iter()
7203                .map(|a| self.evaluate(a))
7204                .collect::<Result<_, _>>()?;
7205            self.call_function_by_name(&first.name.name, arg_values)?
7206        } else {
7207            // First segment is a variable: var·next·...
7208            self.environment
7209                .borrow()
7210                .get(&first.name.name)
7211                .ok_or_else(|| RuntimeError::new(format!("undefined: {}", first.name.name)))?
7212        };
7213
7214        // Process remaining segments as method-like calls
7215        for segment in segments.iter().skip(1) {
7216            let arg_values: Vec<Value> = segment
7217                .args
7218                .as_ref()
7219                .map(|args| {
7220                    args.iter()
7221                        .map(|a| self.evaluate(a))
7222                        .collect::<Result<Vec<_>, _>>()
7223                })
7224                .transpose()?
7225                .unwrap_or_default();
7226
7227            // Try to call as a method on the value
7228            value = self.call_incorporation_method(&value, &segment.name.name, arg_values)?;
7229        }
7230
7231        Ok(value)
7232    }
7233
7234    /// Call a method in an incorporation chain
7235    /// This looks up the segment name as a method or stdlib function
7236    fn call_incorporation_method(
7237        &mut self,
7238        receiver: &Value,
7239        method_name: &str,
7240        args: Vec<Value>,
7241    ) -> Result<Value, RuntimeError> {
7242        // First try as a method on the receiver value
7243        match (receiver, method_name) {
7244            // String methods
7245            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
7246            (Value::String(s), "upper") | (Value::String(s), "uppercase") | (Value::String(s), "to_uppercase") => {
7247                Ok(Value::String(Rc::new(s.to_uppercase())))
7248            }
7249            (Value::String(s), "lower") | (Value::String(s), "lowercase") | (Value::String(s), "to_lowercase") => {
7250                Ok(Value::String(Rc::new(s.to_lowercase())))
7251            }
7252            (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
7253            (Value::String(s), "chars") => {
7254                let chars: Vec<Value> = s
7255                    .chars()
7256                    .map(|c| Value::String(Rc::new(c.to_string())))
7257                    .collect();
7258                Ok(Value::Array(Rc::new(RefCell::new(chars))))
7259            }
7260            (Value::String(s), "lines") => {
7261                let lines: Vec<Value> = s
7262                    .lines()
7263                    .map(|l| Value::String(Rc::new(l.to_string())))
7264                    .collect();
7265                Ok(Value::Array(Rc::new(RefCell::new(lines))))
7266            }
7267            (Value::String(s), "bytes") => {
7268                let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
7269                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
7270            }
7271            (Value::String(s), "parse_int") | (Value::String(s), "to_int") => s
7272                .parse::<i64>()
7273                .map(Value::Int)
7274                .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as int", s))),
7275            (Value::String(s), "parse_float") | (Value::String(s), "to_float") => s
7276                .parse::<f64>()
7277                .map(Value::Float)
7278                .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as float", s))),
7279            (Value::String(s), "as_str") => {
7280                if s.len() <= 10 { crate::sigil_debug!("DEBUG as_str: '{}'", s); }
7281                Ok(Value::String(s.clone()))
7282            }
7283            (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
7284            (Value::String(s), "starts_with") => {
7285                if args.len() != 1 {
7286                    return Err(RuntimeError::new("starts_with expects 1 argument"));
7287                }
7288                match &args[0] {
7289                    Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
7290                    _ => Err(RuntimeError::new("starts_with expects string")),
7291                }
7292            }
7293            (Value::String(s), "ends_with") => {
7294                if args.len() != 1 {
7295                    return Err(RuntimeError::new("ends_with expects 1 argument"));
7296                }
7297                match &args[0] {
7298                    Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
7299                    _ => Err(RuntimeError::new("ends_with expects string")),
7300                }
7301            }
7302            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
7303            (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
7304            (Value::String(s), "first") => s
7305                .chars()
7306                .next()
7307                .map(Value::Char)
7308                .ok_or_else(|| RuntimeError::new("empty string")),
7309            (Value::String(s), "last") => s
7310                .chars()
7311                .last()
7312                .map(Value::Char)
7313                .ok_or_else(|| RuntimeError::new("empty string")),
7314
7315            // Array methods
7316            (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
7317            (Value::Array(arr), "first") | (Value::Array(arr), "next") => Ok(arr
7318                .borrow()
7319                .first()
7320                .cloned()
7321                .unwrap_or(Value::Null)),
7322            (Value::Array(arr), "last") => arr
7323                .borrow()
7324                .last()
7325                .cloned()
7326                .ok_or_else(|| RuntimeError::new("empty array")),
7327            (Value::Array(arr), "reverse") | (Value::Array(arr), "rev") => {
7328                let mut v = arr.borrow().clone();
7329                v.reverse();
7330                Ok(Value::Array(Rc::new(RefCell::new(v))))
7331            }
7332            (Value::Array(arr), "join") => {
7333                let sep = args
7334                    .first()
7335                    .map(|v| match v {
7336                        Value::String(s) => s.to_string(),
7337                        _ => "".to_string(),
7338                    })
7339                    .unwrap_or_default();
7340                let joined = arr
7341                    .borrow()
7342                    .iter()
7343                    .map(|v| format!("{}", v))
7344                    .collect::<Vec<_>>()
7345                    .join(&sep);
7346                Ok(Value::String(Rc::new(joined)))
7347            }
7348            (Value::Array(arr), "sum") => {
7349                let mut sum = 0i64;
7350                for v in arr.borrow().iter() {
7351                    match v {
7352                        Value::Int(i) => sum += i,
7353                        Value::Float(f) => return Ok(Value::Float(sum as f64 + f)),
7354                        _ => {}
7355                    }
7356                }
7357                Ok(Value::Int(sum))
7358            }
7359            (Value::Array(arr), "skip") => {
7360                let n = match args.first() {
7361                    Some(Value::Int(i)) => *i as usize,
7362                    _ => 1,
7363                };
7364                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
7365                Ok(Value::Array(Rc::new(RefCell::new(v))))
7366            }
7367            (Value::Array(arr), "take") => {
7368                let n = match args.first() {
7369                    Some(Value::Int(i)) => *i as usize,
7370                    _ => 1,
7371                };
7372                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
7373                Ok(Value::Array(Rc::new(RefCell::new(v))))
7374            }
7375            (Value::Array(arr), "step_by") => {
7376                let n = match args.first() {
7377                    Some(Value::Int(i)) if *i > 0 => *i as usize,
7378                    _ => 1,
7379                };
7380                let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
7381                Ok(Value::Array(Rc::new(RefCell::new(v))))
7382            }
7383
7384            // Number methods
7385            (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
7386            (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
7387            (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
7388                Ok(Value::String(Rc::new(n.to_string())))
7389            }
7390            (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
7391                Ok(Value::String(Rc::new(n.to_string())))
7392            }
7393            (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
7394            (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
7395
7396            // Map/Struct field access
7397            (Value::Map(map), field) => map
7398                .borrow()
7399                .get(field)
7400                .cloned()
7401                .ok_or_else(|| RuntimeError::new(format!("no field '{}' in map", field))),
7402            (Value::Struct { fields, .. }, field) => fields
7403                .borrow()
7404                .get(field)
7405                .cloned()
7406                .ok_or_else(|| RuntimeError::new(format!("no field '{}' in struct", field))),
7407
7408            // Try stdlib function with receiver as first arg
7409            _ => {
7410                let mut all_args = vec![receiver.clone()];
7411                all_args.extend(args);
7412                self.call_function_by_name(method_name, all_args)
7413            }
7414        }
7415    }
7416
7417    /// Call a function by name from the environment
7418    pub fn call_function_by_name(
7419        &mut self,
7420        name: &str,
7421        args: Vec<Value>,
7422    ) -> Result<Value, RuntimeError> {
7423        // Get the function value from environment (clone to avoid borrow issues)
7424        let func_value = self.environment.borrow().get(name);
7425
7426        match func_value {
7427            Some(Value::Function(f)) => self.call_function(&f, args),
7428            Some(Value::BuiltIn(b)) => self.call_builtin(&b, args),
7429            Some(_) => Err(RuntimeError::new(format!("{} is not a function", name))),
7430            None => {
7431                // Check for variant constructor
7432                if let Some((enum_name, variant_name, arity)) = self.variant_constructors.get(name).cloned() {
7433                    if arity == 0 && args.is_empty() {
7434                        return Ok(Value::Variant {
7435                            enum_name,
7436                            variant_name,
7437                            fields: None,
7438                        });
7439                    } else if args.len() == arity {
7440                        return Ok(Value::Variant {
7441                            enum_name,
7442                            variant_name,
7443                            fields: Some(Rc::new(args)),
7444                        });
7445                    } else {
7446                        return Err(RuntimeError::new(format!(
7447                            "{} expects {} arguments, got {}",
7448                            name, arity, args.len()
7449                        )));
7450                    }
7451                }
7452                Err(RuntimeError::new(format!("undefined function: {}", name)))
7453            }
7454        }
7455    }
7456
7457    fn eval_pipe(&mut self, expr: &Expr, operations: &[PipeOp]) -> Result<Value, RuntimeError> {
7458        let mut value = self.evaluate(expr)?;
7459
7460        for op in operations {
7461            value = self.apply_pipe_op(value, op)?;
7462        }
7463
7464        Ok(value)
7465    }
7466
7467    fn apply_pipe_op(&mut self, value: Value, op: &PipeOp) -> Result<Value, RuntimeError> {
7468        // Unwrap evidential/affective wrappers for pipe operations
7469        let value = Self::unwrap_all(&value);
7470
7471        match op {
7472            PipeOp::Transform(body) => {
7473                // τ{f} - map over collection or apply to single value
7474                // Extract closure parameter pattern and body
7475                let (param_pattern, inner_body) = match body.as_ref() {
7476                    Expr::Closure { params, body, .. } => {
7477                        let pattern = params.first().map(|p| p.pattern.clone());
7478                        (pattern, body.as_ref())
7479                    }
7480                    _ => (None, body.as_ref()),
7481                };
7482
7483                match value {
7484                    Value::Array(arr) => {
7485                        let results: Vec<Value> = arr
7486                            .borrow()
7487                            .iter()
7488                            .map(|item| {
7489                                // Bind the item to the pattern (supports tuple destructuring)
7490                                if let Some(ref pattern) = param_pattern {
7491                                    self.bind_pattern(pattern, item.clone())?;
7492                                } else {
7493                                    self.environment
7494                                        .borrow_mut()
7495                                        .define("_".to_string(), item.clone());
7496                                }
7497                                self.evaluate(inner_body)
7498                            })
7499                            .collect::<Result<_, _>>()?;
7500                        Ok(Value::Array(Rc::new(RefCell::new(results))))
7501                    }
7502                    single => {
7503                        if let Some(ref pattern) = param_pattern {
7504                            self.bind_pattern(pattern, single)?;
7505                        } else {
7506                            self.environment
7507                                .borrow_mut()
7508                                .define("_".to_string(), single);
7509                        }
7510                        self.evaluate(inner_body)
7511                    }
7512                }
7513            }
7514            PipeOp::Filter(predicate) => {
7515                // φ{p} - filter collection
7516                // Extract closure parameter pattern and body
7517                let (param_pattern, inner_pred) = match predicate.as_ref() {
7518                    Expr::Closure { params, body, .. } => {
7519                        let pattern = params.first().map(|p| p.pattern.clone());
7520                        (pattern, body.as_ref())
7521                    }
7522                    _ => (None, predicate.as_ref()),
7523                };
7524
7525                match value {
7526                    Value::Array(arr) => {
7527                        let results: Vec<Value> = arr
7528                            .borrow()
7529                            .iter()
7530                            .filter_map(|item| {
7531                                // Bind the item to the pattern (supports tuple destructuring)
7532                                if let Some(ref pattern) = param_pattern {
7533                                    if let Err(e) = self.bind_pattern(pattern, item.clone()) {
7534                                        return Some(Err(e));
7535                                    }
7536                                } else {
7537                                    self.environment
7538                                        .borrow_mut()
7539                                        .define("_".to_string(), item.clone());
7540                                }
7541                                match self.evaluate(inner_pred) {
7542                                    Ok(v) if self.is_truthy(&v) => Some(Ok(item.clone())),
7543                                    Ok(_) => None,
7544                                    Err(e) => Some(Err(e)),
7545                                }
7546                            })
7547                            .collect::<Result<_, _>>()?;
7548                        Ok(Value::Array(Rc::new(RefCell::new(results))))
7549                    }
7550                    _ => Err(RuntimeError::new("Filter requires array")),
7551                }
7552            }
7553            PipeOp::Sort(field) => {
7554                // σ - sort collection
7555                match value {
7556                    Value::Array(arr) => {
7557                        let mut v = arr.borrow().clone();
7558                        v.sort_by(|a, b| self.compare_values(a, b, field));
7559                        Ok(Value::Array(Rc::new(RefCell::new(v))))
7560                    }
7561                    _ => Err(RuntimeError::new("Sort requires array")),
7562                }
7563            }
7564            PipeOp::Reduce(body) => {
7565                // ρ{f} - reduce collection
7566                match value {
7567                    Value::Array(arr) => {
7568                        let arr = arr.borrow();
7569                        if arr.is_empty() {
7570                            return Err(RuntimeError::new("Cannot reduce empty array"));
7571                        }
7572                        let mut acc = arr[0].clone();
7573                        for item in arr.iter().skip(1) {
7574                            self.environment.borrow_mut().define("acc".to_string(), acc);
7575                            self.environment
7576                                .borrow_mut()
7577                                .define("_".to_string(), item.clone());
7578                            acc = self.evaluate(body)?;
7579                        }
7580                        Ok(acc)
7581                    }
7582                    _ => Err(RuntimeError::new("Reduce requires array")),
7583                }
7584            }
7585            PipeOp::ReduceSum => {
7586                // ρ+ or ρ_sum - sum all elements
7587                self.sum_values(value)
7588            }
7589            PipeOp::ReduceProd => {
7590                // ρ* or ρ_prod - multiply all elements
7591                self.product_values(value)
7592            }
7593            PipeOp::ReduceMin => {
7594                // ρ_min - find minimum element
7595                self.min_values(value)
7596            }
7597            PipeOp::ReduceMax => {
7598                // ρ_max - find maximum element
7599                self.max_values(value)
7600            }
7601            PipeOp::ReduceConcat => {
7602                // ρ++ or ρ_cat - concatenate strings/arrays
7603                self.concat_values(value)
7604            }
7605            PipeOp::ReduceAll => {
7606                // ρ& or ρ_all - logical AND (all true)
7607                self.all_values(value)
7608            }
7609            PipeOp::ReduceAny => {
7610                // ρ| or ρ_any - logical OR (any true)
7611                self.any_values(value)
7612            }
7613            PipeOp::Match(arms) => {
7614                // |match{ Pattern => expr, ... } - pattern matching in pipe
7615                for arm in arms {
7616                    if self.pattern_matches(&arm.pattern, &value)? {
7617                        // Create new scope for pattern bindings
7618                        let prev_env = self.environment.clone();
7619                        self.environment =
7620                            Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
7621
7622                        // Bind pattern variables
7623                        self.bind_pattern(&arm.pattern, value.clone())?;
7624
7625                        // Also bind _ to the piped value for convenient access
7626                        self.environment
7627                            .borrow_mut()
7628                            .define("_".to_string(), value.clone());
7629
7630                        // Check guard if present
7631                        let guard_passes = if let Some(guard) = &arm.guard {
7632                            matches!(self.evaluate(guard)?, Value::Bool(true))
7633                        } else {
7634                            true
7635                        };
7636
7637                        if guard_passes {
7638                            let result = self.evaluate(&arm.body)?;
7639                            self.environment = prev_env;
7640                            return Ok(result);
7641                        }
7642
7643                        // Guard failed, restore environment and try next arm
7644                        self.environment = prev_env;
7645                    }
7646                }
7647                Err(RuntimeError::new("No pattern matched in pipe match"))
7648            }
7649            PipeOp::TryMap(mapper) => {
7650                // |? or |?{mapper} - unwrap Result/Option or transform error
7651                match &value {
7652                    // Handle Result-like values (struct with ok/err fields)
7653                    Value::Struct { name, fields } if name == "Ok" || name.ends_with("::Ok") => {
7654                        // Extract the inner value from Ok
7655                        let fields = fields.borrow();
7656                        fields
7657                            .get("0")
7658                            .or_else(|| fields.get("value"))
7659                            .cloned()
7660                            .ok_or_else(|| RuntimeError::new("Ok variant has no value"))
7661                    }
7662                    Value::Struct { name, fields } if name == "Err" || name.ends_with("::Err") => {
7663                        // Transform error if mapper provided, otherwise propagate
7664                        let fields = fields.borrow();
7665                        let err_val = fields
7666                            .get("0")
7667                            .or_else(|| fields.get("error"))
7668                            .cloned()
7669                            .unwrap_or(Value::Null);
7670                        if let Some(mapper_expr) = mapper {
7671                            // Apply mapper to error
7672                            let prev_env = self.environment.clone();
7673                            self.environment =
7674                                Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
7675                            self.environment
7676                                .borrow_mut()
7677                                .define("_".to_string(), err_val);
7678                            let mapped = self.evaluate(mapper_expr)?;
7679                            self.environment = prev_env;
7680                            Err(RuntimeError::new(format!("Error: {:?}", mapped)))
7681                        } else {
7682                            Err(RuntimeError::new(format!("Error: {:?}", err_val)))
7683                        }
7684                    }
7685                    // Handle Option-like values
7686                    Value::Struct { name, fields }
7687                        if name == "Some" || name.ends_with("::Some") =>
7688                    {
7689                        let fields = fields.borrow();
7690                        fields
7691                            .get("0")
7692                            .or_else(|| fields.get("value"))
7693                            .cloned()
7694                            .ok_or_else(|| RuntimeError::new("Some variant has no value"))
7695                    }
7696                    Value::Struct { name, .. } if name == "None" || name.ends_with("::None") => {
7697                        Err(RuntimeError::new("Unwrapped None value"))
7698                    }
7699                    Value::Null => Err(RuntimeError::new("Unwrapped null value")),
7700                    // Pass through non-Result/Option values unchanged
7701                    _ => Ok(value),
7702                }
7703            }
7704            PipeOp::Call(callee) => {
7705                // |expr - call an arbitrary expression (like self.layer) with piped value
7706                let callee_val = self.evaluate(callee)?;
7707                match callee_val {
7708                    Value::Function(f) => {
7709                        // Call the function with the piped value as argument
7710                        self.call_function(&f, vec![value])
7711                    }
7712                    Value::BuiltIn(b) => {
7713                        // Call built-in with the piped value
7714                        self.call_builtin(&b, vec![value])
7715                    }
7716                    Value::Struct { .. } => {
7717                        // Structs that implement __call__ can be called as functions
7718                        // For now, just return the value (ML layers would override)
7719                        Ok(value)
7720                    }
7721                    _ => Err(RuntimeError::new(format!(
7722                        "Cannot call non-function value in pipe: {:?}",
7723                        callee_val
7724                    ))),
7725                }
7726            }
7727            PipeOp::Method { name, type_args: _, args } => {
7728                let arg_values: Vec<Value> = args
7729                    .iter()
7730                    .map(|a| self.evaluate(a))
7731                    .collect::<Result<_, _>>()?;
7732
7733                // Check for built-in pipe methods
7734                match name.name.as_str() {
7735                    "collect" => Ok(value), // Already collected
7736                    "sum" | "Σ" => self.sum_values(value),
7737                    "product" | "Π" => self.product_values(value),
7738                    "len" => match &value {
7739                        Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
7740                        Value::String(s) => Ok(Value::Int(s.len() as i64)),
7741                        _ => Err(RuntimeError::new("len requires array or string")),
7742                    },
7743                    "reverse" => match value {
7744                        Value::Array(arr) => {
7745                            let mut v = arr.borrow().clone();
7746                            v.reverse();
7747                            Ok(Value::Array(Rc::new(RefCell::new(v))))
7748                        }
7749                        _ => Err(RuntimeError::new("reverse requires array")),
7750                    },
7751                    "iter" | "into_iter" => {
7752                        // iter()/into_iter() returns the array for iteration (identity operation)
7753                        Ok(value)
7754                    },
7755                    "enumerate" => {
7756                        // enumerate() returns array of (index, value) tuples
7757                        match &value {
7758                            Value::Array(arr) => {
7759                                let enumerated: Vec<Value> = arr
7760                                    .borrow()
7761                                    .iter()
7762                                    .enumerate()
7763                                    .map(|(i, v)| {
7764                                        Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
7765                                    })
7766                                    .collect();
7767                                Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
7768                            }
7769                            _ => Err(RuntimeError::new("enumerate requires array")),
7770                        }
7771                    },
7772                    "first" => match &value {
7773                        Value::Array(arr) => arr
7774                            .borrow()
7775                            .first()
7776                            .cloned()
7777                            .ok_or_else(|| RuntimeError::new("first on empty array")),
7778                        _ => Err(RuntimeError::new("first requires array")),
7779                    },
7780                    "last" => match &value {
7781                        Value::Array(arr) => arr
7782                            .borrow()
7783                            .last()
7784                            .cloned()
7785                            .ok_or_else(|| RuntimeError::new("last on empty array")),
7786                        _ => Err(RuntimeError::new("last requires array")),
7787                    },
7788                    "take" => {
7789                        if arg_values.len() != 1 {
7790                            return Err(RuntimeError::new("take requires 1 argument"));
7791                        }
7792                        let n = match &arg_values[0] {
7793                            Value::Int(n) => *n as usize,
7794                            _ => return Err(RuntimeError::new("take requires integer")),
7795                        };
7796                        match value {
7797                            Value::Array(arr) => {
7798                                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
7799                                Ok(Value::Array(Rc::new(RefCell::new(v))))
7800                            }
7801                            _ => Err(RuntimeError::new("take requires array")),
7802                        }
7803                    }
7804                    "skip" => {
7805                        if arg_values.len() != 1 {
7806                            return Err(RuntimeError::new("skip requires 1 argument"));
7807                        }
7808                        let n = match &arg_values[0] {
7809                            Value::Int(n) => *n as usize,
7810                            _ => return Err(RuntimeError::new("skip requires integer")),
7811                        };
7812                        match value {
7813                            Value::Array(arr) => {
7814                                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
7815                                Ok(Value::Array(Rc::new(RefCell::new(v))))
7816                            }
7817                            _ => Err(RuntimeError::new("skip requires array")),
7818                        }
7819                    }
7820                    "join" => {
7821                        // Join array elements with a separator string
7822                        let separator = if arg_values.is_empty() {
7823                            String::new()
7824                        } else {
7825                            match &arg_values[0] {
7826                                Value::String(s) => (**s).clone(),
7827                                _ => return Err(RuntimeError::new("join separator must be string")),
7828                            }
7829                        };
7830                        match value {
7831                            Value::Array(arr) => {
7832                                let parts: Vec<String> = arr.borrow().iter()
7833                                    .map(|v| format!("{}", Self::unwrap_all(v)))
7834                                    .collect();
7835                                Ok(Value::String(Rc::new(parts.join(&separator))))
7836                            }
7837                            _ => Err(RuntimeError::new("join requires array")),
7838                        }
7839                    }
7840                    "all" => {
7841                        // Check if all elements are truthy (no predicate in Method variant)
7842                        match value {
7843                            Value::Array(arr) => {
7844                                for item in arr.borrow().iter() {
7845                                    if !self.is_truthy(item) {
7846                                        return Ok(Value::Bool(false));
7847                                    }
7848                                }
7849                                Ok(Value::Bool(true))
7850                            }
7851                            _ => Err(RuntimeError::new("all requires array")),
7852                        }
7853                    }
7854                    "any" => {
7855                        // Check if any element is truthy
7856                        match value {
7857                            Value::Array(arr) => {
7858                                for item in arr.borrow().iter() {
7859                                    if self.is_truthy(item) {
7860                                        return Ok(Value::Bool(true));
7861                                    }
7862                                }
7863                                Ok(Value::Bool(false))
7864                            }
7865                            _ => Err(RuntimeError::new("any requires array")),
7866                        }
7867                    }
7868                    "map" => {
7869                        // map(closure) applies closure to each element
7870                        if arg_values.len() != 1 {
7871                            return Err(RuntimeError::new("map expects 1 argument (closure)"));
7872                        }
7873                        match (&value, &arg_values[0]) {
7874                            (Value::Array(arr), Value::Function(f)) => {
7875                                let mut results = Vec::new();
7876                                for val in arr.borrow().iter() {
7877                                    let result = self.call_function(f, vec![val.clone()])?;
7878                                    results.push(result);
7879                                }
7880                                Ok(Value::Array(Rc::new(RefCell::new(results))))
7881                            }
7882                            (Value::Array(_), _) => Err(RuntimeError::new("map expects closure argument")),
7883                            _ => Err(RuntimeError::new("map requires array")),
7884                        }
7885                    }
7886                    "filter" => {
7887                        // filter(predicate) keeps elements where predicate returns true
7888                        if arg_values.len() != 1 {
7889                            return Err(RuntimeError::new("filter expects 1 argument (closure)"));
7890                        }
7891                        match (&value, &arg_values[0]) {
7892                            (Value::Array(arr), Value::Function(f)) => {
7893                                let mut results = Vec::new();
7894                                for val in arr.borrow().iter() {
7895                                    let keep = self.call_function(f, vec![val.clone()])?;
7896                                    if matches!(keep, Value::Bool(true)) {
7897                                        results.push(val.clone());
7898                                    }
7899                                }
7900                                Ok(Value::Array(Rc::new(RefCell::new(results))))
7901                            }
7902                            (Value::Array(_), _) => Err(RuntimeError::new("filter expects closure argument")),
7903                            _ => Err(RuntimeError::new("filter requires array")),
7904                        }
7905                    }
7906                    "fold" => {
7907                        // fold(init, closure) reduces array to single value
7908                        if arg_values.len() != 2 {
7909                            return Err(RuntimeError::new("fold expects 2 arguments (init, closure)"));
7910                        }
7911                        match (&value, &arg_values[1]) {
7912                            (Value::Array(arr), Value::Function(f)) => {
7913                                let mut acc = arg_values[0].clone();
7914                                for val in arr.borrow().iter() {
7915                                    acc = self.call_function(f, vec![acc, val.clone()])?;
7916                                }
7917                                Ok(acc)
7918                            }
7919                            (Value::Array(_), _) => Err(RuntimeError::new("fold expects closure as second argument")),
7920                            _ => Err(RuntimeError::new("fold requires array")),
7921                        }
7922                    }
7923                    _ => Err(RuntimeError::new(format!(
7924                        "Unknown pipe method: {}",
7925                        name.name
7926                    ))),
7927                }
7928            }
7929            PipeOp::Await => {
7930                // Await a future - resolve it to a value
7931                self.await_value(value)
7932            }
7933            // New access morphemes
7934            PipeOp::First => {
7935                // α - first element
7936                match &value {
7937                    Value::Array(arr) => arr
7938                        .borrow()
7939                        .first()
7940                        .cloned()
7941                        .ok_or_else(|| RuntimeError::new("first (α) on empty array")),
7942                    Value::Tuple(t) => t
7943                        .first()
7944                        .cloned()
7945                        .ok_or_else(|| RuntimeError::new("first (α) on empty tuple")),
7946                    _ => Err(RuntimeError::new("first (α) requires array or tuple")),
7947                }
7948            }
7949            PipeOp::Last => {
7950                // ω - last element
7951                match &value {
7952                    Value::Array(arr) => arr
7953                        .borrow()
7954                        .last()
7955                        .cloned()
7956                        .ok_or_else(|| RuntimeError::new("last (ω) on empty array")),
7957                    Value::Tuple(t) => t
7958                        .last()
7959                        .cloned()
7960                        .ok_or_else(|| RuntimeError::new("last (ω) on empty tuple")),
7961                    _ => Err(RuntimeError::new("last (ω) requires array or tuple")),
7962                }
7963            }
7964            PipeOp::Middle => {
7965                // μ - middle/median element
7966                match &value {
7967                    Value::Array(arr) => {
7968                        let arr = arr.borrow();
7969                        if arr.is_empty() {
7970                            return Err(RuntimeError::new("middle (μ) on empty array"));
7971                        }
7972                        let mid = arr.len() / 2;
7973                        Ok(arr[mid].clone())
7974                    }
7975                    Value::Tuple(t) => {
7976                        if t.is_empty() {
7977                            return Err(RuntimeError::new("middle (μ) on empty tuple"));
7978                        }
7979                        let mid = t.len() / 2;
7980                        Ok(t[mid].clone())
7981                    }
7982                    _ => Err(RuntimeError::new("middle (μ) requires array or tuple")),
7983                }
7984            }
7985            PipeOp::Choice => {
7986                // χ - random element
7987                use std::time::{SystemTime, UNIX_EPOCH};
7988                match &value {
7989                    Value::Array(arr) => {
7990                        let arr = arr.borrow();
7991                        if arr.is_empty() {
7992                            return Err(RuntimeError::new("choice (χ) on empty array"));
7993                        }
7994                        let seed = SystemTime::now()
7995                            .duration_since(UNIX_EPOCH)
7996                            .unwrap_or(std::time::Duration::ZERO)
7997                            .as_nanos() as u64;
7998                        let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
7999                            as usize
8000                            % arr.len();
8001                        Ok(arr[idx].clone())
8002                    }
8003                    Value::Tuple(t) => {
8004                        if t.is_empty() {
8005                            return Err(RuntimeError::new("choice (χ) on empty tuple"));
8006                        }
8007                        let seed = SystemTime::now()
8008                            .duration_since(UNIX_EPOCH)
8009                            .unwrap_or(std::time::Duration::ZERO)
8010                            .as_nanos() as u64;
8011                        let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
8012                            as usize
8013                            % t.len();
8014                        Ok(t[idx].clone())
8015                    }
8016                    _ => Err(RuntimeError::new("choice (χ) requires array or tuple")),
8017                }
8018            }
8019            PipeOp::Nth(index_expr) => {
8020                // ν{n} - nth element
8021                let index = match self.evaluate(index_expr)? {
8022                    Value::Int(n) => n,
8023                    _ => return Err(RuntimeError::new("nth (ν) index must be integer")),
8024                };
8025                match &value {
8026                    Value::Array(arr) => {
8027                        let arr = arr.borrow();
8028                        if index < 0 || index as usize >= arr.len() {
8029                            return Err(RuntimeError::new("nth (ν) index out of bounds"));
8030                        }
8031                        Ok(arr[index as usize].clone())
8032                    }
8033                    Value::Tuple(t) => {
8034                        if index < 0 || index as usize >= t.len() {
8035                            return Err(RuntimeError::new("nth (ν) index out of bounds"));
8036                        }
8037                        Ok(t[index as usize].clone())
8038                    }
8039                    _ => Err(RuntimeError::new("nth (ν) requires array or tuple")),
8040                }
8041            }
8042            PipeOp::Next => {
8043                // ξ - next element (for iterators, currently just returns first)
8044                // In a full implementation, this would advance an iterator
8045                match &value {
8046                    Value::Array(arr) => arr
8047                        .borrow()
8048                        .first()
8049                        .cloned()
8050                        .ok_or_else(|| RuntimeError::new("next (ξ) on empty array")),
8051                    Value::Tuple(t) => t
8052                        .first()
8053                        .cloned()
8054                        .ok_or_else(|| RuntimeError::new("next (ξ) on empty tuple")),
8055                    _ => Err(RuntimeError::new("next (ξ) requires array or tuple")),
8056                }
8057            }
8058            PipeOp::Named { prefix, body } => {
8059                // Named morpheme like ·map{f}
8060                let method_name = prefix
8061                    .iter()
8062                    .map(|i| i.name.as_str())
8063                    .collect::<Vec<_>>()
8064                    .join("·");
8065                match method_name.as_str() {
8066                    "map" => {
8067                        if let Some(body) = body {
8068                            match value {
8069                                Value::Array(arr) => {
8070                                    let results: Vec<Value> = arr
8071                                        .borrow()
8072                                        .iter()
8073                                        .map(|item| {
8074                                            self.environment
8075                                                .borrow_mut()
8076                                                .define("_".to_string(), item.clone());
8077                                            self.evaluate(body)
8078                                        })
8079                                        .collect::<Result<_, _>>()?;
8080                                    Ok(Value::Array(Rc::new(RefCell::new(results))))
8081                                }
8082                                _ => Err(RuntimeError::new("map requires array")),
8083                            }
8084                        } else {
8085                            Ok(value)
8086                        }
8087                    }
8088                    "filter" => {
8089                        if let Some(body) = body {
8090                            match value {
8091                                Value::Array(arr) => {
8092                                    let results: Vec<Value> = arr
8093                                        .borrow()
8094                                        .iter()
8095                                        .filter_map(|item| {
8096                                            self.environment
8097                                                .borrow_mut()
8098                                                .define("_".to_string(), item.clone());
8099                                            match self.evaluate(body) {
8100                                                Ok(v) if self.is_truthy(&v) => {
8101                                                    Some(Ok(item.clone()))
8102                                                }
8103                                                Ok(_) => None,
8104                                                Err(e) => Some(Err(e)),
8105                                            }
8106                                        })
8107                                        .collect::<Result<_, _>>()?;
8108                                    Ok(Value::Array(Rc::new(RefCell::new(results))))
8109                                }
8110                                _ => Err(RuntimeError::new("filter requires array")),
8111                            }
8112                        } else {
8113                            Ok(value)
8114                        }
8115                    }
8116                    "all" => {
8117                        if let Some(body) = body {
8118                            match value {
8119                                Value::Array(arr) => {
8120                                    for item in arr.borrow().iter() {
8121                                        self.environment
8122                                            .borrow_mut()
8123                                            .define("_".to_string(), item.clone());
8124                                        let result = self.evaluate(body)?;
8125                                        if !self.is_truthy(&result) {
8126                                            return Ok(Value::Bool(false));
8127                                        }
8128                                    }
8129                                    Ok(Value::Bool(true))
8130                                }
8131                                _ => Err(RuntimeError::new("all requires array")),
8132                            }
8133                        } else {
8134                            // Without body, check if all elements are truthy
8135                            match value {
8136                                Value::Array(arr) => {
8137                                    for item in arr.borrow().iter() {
8138                                        if !self.is_truthy(item) {
8139                                            return Ok(Value::Bool(false));
8140                                        }
8141                                    }
8142                                    Ok(Value::Bool(true))
8143                                }
8144                                _ => Err(RuntimeError::new("all requires array")),
8145                            }
8146                        }
8147                    }
8148                    "any" => {
8149                        if let Some(body) = body {
8150                            match value {
8151                                Value::Array(arr) => {
8152                                    for item in arr.borrow().iter() {
8153                                        self.environment
8154                                            .borrow_mut()
8155                                            .define("_".to_string(), item.clone());
8156                                        let result = self.evaluate(body)?;
8157                                        if self.is_truthy(&result) {
8158                                            return Ok(Value::Bool(true));
8159                                        }
8160                                    }
8161                                    Ok(Value::Bool(false))
8162                                }
8163                                _ => Err(RuntimeError::new("any requires array")),
8164                            }
8165                        } else {
8166                            // Without body, check if any elements are truthy
8167                            match value {
8168                                Value::Array(arr) => {
8169                                    for item in arr.borrow().iter() {
8170                                        if self.is_truthy(item) {
8171                                            return Ok(Value::Bool(true));
8172                                        }
8173                                    }
8174                                    Ok(Value::Bool(false))
8175                                }
8176                                _ => Err(RuntimeError::new("any requires array")),
8177                            }
8178                        }
8179                    }
8180                    _ => Err(RuntimeError::new(format!(
8181                        "Unknown named morpheme: {}",
8182                        method_name
8183                    ))),
8184                }
8185            }
8186            PipeOp::Parallel(inner_op) => {
8187                // ∥ - parallel execution of the inner operation
8188                // For arrays, execute the operation in parallel using threads
8189                match value {
8190                    Value::Array(arr) => {
8191                        use std::sync::{Arc, Mutex};
8192
8193                        let arr_ref = arr.borrow();
8194                        let len = arr_ref.len();
8195                        if len == 0 {
8196                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
8197                        }
8198
8199                        // For Transform operations, parallelize across elements
8200                        match inner_op.as_ref() {
8201                            PipeOp::Transform(body) => {
8202                                // Determine number of threads (use available parallelism)
8203                                let num_threads = std::thread::available_parallelism()
8204                                    .map(|p| p.get())
8205                                    .unwrap_or(4)
8206                                    .min(len);
8207
8208                                // For future parallel implementation
8209                                let _chunk_size = (len + num_threads - 1) / num_threads;
8210                                let _results = Arc::new(Mutex::new(vec![Value::Null; len]));
8211                                let items: Vec<Value> = arr_ref.clone();
8212                                drop(arr_ref);
8213
8214                                // Clone the body expression for each thread (for future use)
8215                                let _body_str = format!("{:?}", body);
8216
8217                                // For now, fall back to sequential since full parallelization
8218                                // requires thread-safe evaluation context
8219                                // In production, this would use Rayon or a work-stealing scheduler
8220                                let mut result_vec = Vec::with_capacity(len);
8221                                for item in items.iter() {
8222                                    self.environment
8223                                        .borrow_mut()
8224                                        .define("_".to_string(), item.clone());
8225                                    result_vec.push(self.evaluate(body)?);
8226                                }
8227                                Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
8228                            }
8229                            PipeOp::Filter(predicate) => {
8230                                // Parallel filter - evaluate predicate in parallel
8231                                let items: Vec<Value> = arr_ref.clone();
8232                                drop(arr_ref);
8233
8234                                let mut result_vec = Vec::new();
8235                                for item in items.iter() {
8236                                    self.environment
8237                                        .borrow_mut()
8238                                        .define("_".to_string(), item.clone());
8239                                    let pred_result = self.evaluate(predicate)?;
8240                                    if self.is_truthy(&pred_result) {
8241                                        result_vec.push(item.clone());
8242                                    }
8243                                }
8244                                Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
8245                            }
8246                            _ => {
8247                                // For other operations, just apply them normally
8248                                drop(arr_ref);
8249                                self.apply_pipe_op(Value::Array(arr), inner_op)
8250                            }
8251                        }
8252                    }
8253                    _ => {
8254                        // For non-arrays, just apply the inner operation
8255                        self.apply_pipe_op(value, inner_op)
8256                    }
8257                }
8258            }
8259            PipeOp::Gpu(inner_op) => {
8260                // ⊛ - GPU compute shader execution
8261                // This is a placeholder that falls back to CPU execution
8262                // In production, this would:
8263                // 1. Generate SPIR-V/WGSL compute shader
8264                // 2. Submit to GPU via wgpu/vulkan
8265                // 3. Read back results
8266                match value {
8267                    Value::Array(arr) => {
8268                        // For now, emit a hint that GPU execution would occur
8269                        // and fall back to CPU
8270                        #[cfg(debug_assertions)]
8271                        eprintln!(
8272                            "[GPU] Would execute {:?} on GPU, falling back to CPU",
8273                            inner_op
8274                        );
8275
8276                        self.apply_pipe_op(Value::Array(arr), inner_op)
8277                    }
8278                    _ => self.apply_pipe_op(value, inner_op),
8279                }
8280            }
8281
8282            // ==========================================
8283            // Protocol Operations - Sigil-native networking
8284            // All protocol results are wrapped with Reported evidentiality
8285            // since network data comes from external sources ("hearsay")
8286            // ==========================================
8287            PipeOp::Send(data_expr) => {
8288                // |send{data} or |⇒{data} - Send data over a connection
8289                // The value should be a connection object
8290                let data = self.evaluate(data_expr)?;
8291
8292                // Create a protocol response with Reported evidentiality
8293                // In production, this would actually send data over the network
8294                let response = self.protocol_send(&value, &data)?;
8295
8296                // Wrap in Reported evidentiality - network responses are hearsay
8297                Ok(self.wrap_reported(response))
8298            }
8299
8300            PipeOp::Recv => {
8301                // |recv or |⇐ - Receive data from a connection
8302                // The value should be a connection object
8303
8304                // In production, this would actually receive data from the network
8305                let response = self.protocol_recv(&value)?;
8306
8307                // Wrap in Reported evidentiality - network data is hearsay
8308                Ok(self.wrap_reported(response))
8309            }
8310
8311            PipeOp::Stream(handler_expr) => {
8312                // |stream{handler} or |≋{handler} - Stream data with a handler
8313                let handler = self.evaluate(handler_expr)?;
8314
8315                // Create a streaming iterator over network data
8316                // Each element will be wrapped in Reported evidentiality
8317                let stream = self.protocol_stream(&value, &handler)?;
8318                Ok(stream)
8319            }
8320
8321            PipeOp::Connect(config_expr) => {
8322                // |connect or |connect{config} or |⊸{config} - Establish connection
8323                let config = match config_expr {
8324                    Some(expr) => Some(self.evaluate(expr)?),
8325                    None => None,
8326                };
8327
8328                // Create a connection object
8329                let connection = self.protocol_connect(&value, config.as_ref())?;
8330                Ok(connection)
8331            }
8332
8333            PipeOp::Close => {
8334                // |close or |⊗ - Close connection gracefully
8335                self.protocol_close(&value)?;
8336                Ok(Value::Null)
8337            }
8338
8339            PipeOp::Header {
8340                name,
8341                value: value_expr,
8342            } => {
8343                // |header{name, value} - Add/set header on request
8344                let header_name = self.evaluate(name)?;
8345                let header_value = self.evaluate(value_expr)?;
8346
8347                // Add header to the request builder
8348                self.protocol_add_header(value, &header_name, &header_value)
8349            }
8350
8351            PipeOp::Body(data_expr) => {
8352                // |body{data} - Set request body
8353                let body_data = self.evaluate(data_expr)?;
8354
8355                // Set body on the request builder
8356                self.protocol_set_body(value, &body_data)
8357            }
8358
8359            PipeOp::Timeout(ms_expr) => {
8360                // |timeout{ms} or |⏱{ms} - Set operation timeout
8361                let ms = self.evaluate(ms_expr)?;
8362
8363                // Set timeout on the request/connection
8364                self.protocol_set_timeout(value, &ms)
8365            }
8366
8367            PipeOp::Retry { count, strategy } => {
8368                // |retry{count} or |retry{count, strategy} - Set retry policy
8369                let retry_count = self.evaluate(count)?;
8370                let retry_strategy = match strategy {
8371                    Some(s) => Some(self.evaluate(s)?),
8372                    None => None,
8373                };
8374
8375                // Set retry policy on the request
8376                self.protocol_set_retry(value, &retry_count, retry_strategy.as_ref())
8377            }
8378
8379            // ==========================================
8380            // Evidence Promotion Operations
8381            // ==========================================
8382            PipeOp::Validate {
8383                predicate,
8384                target_evidence,
8385            } => {
8386                // |validate!{predicate} - validate and promote evidence
8387                // Execute the predicate with the current value
8388                let predicate_result = match predicate.as_ref() {
8389                    Expr::Closure { params, body, .. } => {
8390                        if let Some(param) = params.first() {
8391                            let param_name = match &param.pattern {
8392                                Pattern::Ident { name, .. } => name.name.clone(),
8393                                _ => "it".to_string(),
8394                            };
8395                            self.environment
8396                                .borrow_mut()
8397                                .define(param_name, value.clone());
8398                        }
8399                        self.evaluate(body)?
8400                    }
8401                    _ => self.evaluate(predicate)?,
8402                };
8403
8404                // Check if validation passed
8405                match predicate_result {
8406                    Value::Bool(true) => {
8407                        // Validation passed: promote evidence
8408                        let target_ev = match target_evidence {
8409                            Evidentiality::Known => Evidence::Known,
8410                            Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
8411                            Evidentiality::Reported => Evidence::Reported,
8412                            Evidentiality::Paradox => Evidence::Paradox,
8413                        };
8414                        let inner = match value {
8415                            Value::Evidential { value: v, .. } => *v,
8416                            v => v,
8417                        };
8418                        Ok(Value::Evidential {
8419                            value: Box::new(inner),
8420                            evidence: target_ev,
8421                        })
8422                    }
8423                    Value::Bool(false) => Err(RuntimeError::new(
8424                        "validation failed: predicate returned false",
8425                    )),
8426                    _ => Err(RuntimeError::new("validation predicate must return bool")),
8427                }
8428            }
8429
8430            PipeOp::Assume {
8431                reason,
8432                target_evidence,
8433            } => {
8434                // |assume!("reason") - explicitly assume evidence (with audit trail)
8435                let reason_str: Rc<String> = if let Some(r) = reason {
8436                    match self.evaluate(r)? {
8437                        Value::String(s) => s,
8438                        _ => Rc::new("<no reason>".to_string()),
8439                    }
8440                } else {
8441                    Rc::new("<no reason>".to_string())
8442                };
8443
8444                // Log the assumption for audit purposes
8445                #[cfg(debug_assertions)]
8446                eprintln!(
8447                    "[AUDIT] Evidence assumption: {} - reason: {}",
8448                    match target_evidence {
8449                        Evidentiality::Known => "!",
8450                        Evidentiality::Uncertain | Evidentiality::Predicted => "?",
8451                        Evidentiality::Reported => "~",
8452                        Evidentiality::Paradox => "‽",
8453                    },
8454                    reason_str
8455                );
8456
8457                let target_ev = match target_evidence {
8458                    Evidentiality::Known => Evidence::Known,
8459                    Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
8460                    Evidentiality::Reported => Evidence::Reported,
8461                    Evidentiality::Paradox => Evidence::Paradox,
8462                };
8463
8464                let inner = match value {
8465                    Value::Evidential { value: v, .. } => *v,
8466                    v => v,
8467                };
8468
8469                Ok(Value::Evidential {
8470                    value: Box::new(inner),
8471                    evidence: target_ev,
8472                })
8473            }
8474
8475            PipeOp::AssertEvidence(expected) => {
8476                // |assert_evidence!{!} - assert evidence level
8477                let actual_evidence = match &value {
8478                    Value::Evidential { evidence, .. } => evidence.clone(),
8479                    _ => Evidence::Known,
8480                };
8481
8482                let expected_ev = match expected {
8483                    Evidentiality::Known => Evidence::Known,
8484                    Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
8485                    Evidentiality::Reported => Evidence::Reported,
8486                    Evidentiality::Paradox => Evidence::Paradox,
8487                };
8488
8489                // Check if actual satisfies expected
8490                let satisfies = match (&actual_evidence, &expected_ev) {
8491                    (Evidence::Known, _) => true,
8492                    (
8493                        Evidence::Uncertain,
8494                        Evidence::Uncertain | Evidence::Reported | Evidence::Paradox,
8495                    ) => true,
8496                    (Evidence::Reported, Evidence::Reported | Evidence::Paradox) => true,
8497                    (Evidence::Paradox, Evidence::Paradox) => true,
8498                    _ => false,
8499                };
8500
8501                if satisfies {
8502                    Ok(value)
8503                } else {
8504                    Err(RuntimeError::new(format!(
8505                        "evidence assertion failed: expected {:?}, found {:?}",
8506                        expected_ev, actual_evidence
8507                    )))
8508                }
8509            }
8510
8511            // ==========================================
8512            // Scope Functions (Kotlin-inspired)
8513            // ==========================================
8514            PipeOp::Also(func) => {
8515                // |also{f} - execute side effect, return original value
8516                // Execute the function with the value for side effects
8517                match func.as_ref() {
8518                    Expr::Closure { params, body, .. } => {
8519                        if let Some(param) = params.first() {
8520                            let param_name = match &param.pattern {
8521                                Pattern::Ident { name, .. } => name.name.clone(),
8522                                _ => "it".to_string(),
8523                            };
8524                            self.environment
8525                                .borrow_mut()
8526                                .define(param_name, value.clone());
8527                        }
8528                        // Execute for side effects, ignore result
8529                        let _ = self.evaluate(body);
8530                    }
8531                    _ => {
8532                        // Call as function with value as argument
8533                        let _ = self.evaluate(func);
8534                    }
8535                }
8536                // Return original value unchanged
8537                Ok(value)
8538            }
8539
8540            PipeOp::Apply(func) => {
8541                // |apply{block} - mutate value in place, return modified value
8542                // The closure receives the value and can modify it
8543                match func.as_ref() {
8544                    Expr::Closure { params, body, .. } => {
8545                        if let Some(param) = params.first() {
8546                            let param_name = match &param.pattern {
8547                                Pattern::Ident { name, .. } => name.name.clone(),
8548                                _ => "it".to_string(),
8549                            };
8550                            self.environment
8551                                .borrow_mut()
8552                                .define(param_name, value.clone());
8553                        }
8554                        // Execute the body - mutations happen via the bound variable
8555                        let _ = self.evaluate(body);
8556                    }
8557                    _ => {
8558                        let _ = self.evaluate(func);
8559                    }
8560                }
8561                // Return the (potentially modified) value
8562                Ok(value)
8563            }
8564
8565            PipeOp::TakeIf(predicate) => {
8566                // |take_if{p} - return Some(value) if predicate true, None otherwise
8567                let predicate_result = match predicate.as_ref() {
8568                    Expr::Closure { params, body, .. } => {
8569                        if let Some(param) = params.first() {
8570                            let param_name = match &param.pattern {
8571                                Pattern::Ident { name, .. } => name.name.clone(),
8572                                _ => "it".to_string(),
8573                            };
8574                            self.environment
8575                                .borrow_mut()
8576                                .define(param_name, value.clone());
8577                        }
8578                        self.evaluate(body)?
8579                    }
8580                    _ => self.evaluate(predicate)?,
8581                };
8582
8583                match predicate_result {
8584                    Value::Bool(true) => Ok(Value::Variant {
8585                        enum_name: "Option".to_string(),
8586                        variant_name: "Some".to_string(),
8587                        fields: Some(Rc::new(vec![value])),
8588                    }),
8589                    Value::Bool(false) => Ok(Value::Variant {
8590                        enum_name: "Option".to_string(),
8591                        variant_name: "None".to_string(),
8592                        fields: None,
8593                    }),
8594                    _ => Err(RuntimeError::new("take_if predicate must return bool")),
8595                }
8596            }
8597
8598            PipeOp::TakeUnless(predicate) => {
8599                // |take_unless{p} - return Some(value) if predicate false, None otherwise
8600                let predicate_result = match predicate.as_ref() {
8601                    Expr::Closure { params, body, .. } => {
8602                        if let Some(param) = params.first() {
8603                            let param_name = match &param.pattern {
8604                                Pattern::Ident { name, .. } => name.name.clone(),
8605                                _ => "it".to_string(),
8606                            };
8607                            self.environment
8608                                .borrow_mut()
8609                                .define(param_name, value.clone());
8610                        }
8611                        self.evaluate(body)?
8612                    }
8613                    _ => self.evaluate(predicate)?,
8614                };
8615
8616                match predicate_result {
8617                    Value::Bool(false) => Ok(Value::Variant {
8618                        enum_name: "Option".to_string(),
8619                        variant_name: "Some".to_string(),
8620                        fields: Some(Rc::new(vec![value])),
8621                    }),
8622                    Value::Bool(true) => Ok(Value::Variant {
8623                        enum_name: "Option".to_string(),
8624                        variant_name: "None".to_string(),
8625                        fields: None,
8626                    }),
8627                    _ => Err(RuntimeError::new("take_unless predicate must return bool")),
8628                }
8629            }
8630
8631            PipeOp::Let(func) => {
8632                // |let{f} - transform value (alias for map/transform)
8633                match func.as_ref() {
8634                    Expr::Closure { params, body, .. } => {
8635                        if let Some(param) = params.first() {
8636                            let param_name = match &param.pattern {
8637                                Pattern::Ident { name, .. } => name.name.clone(),
8638                                _ => "it".to_string(),
8639                            };
8640                            self.environment
8641                                .borrow_mut()
8642                                .define(param_name, value.clone());
8643                        }
8644                        self.evaluate(body)
8645                    }
8646                    _ => self.evaluate(func),
8647                }
8648            }
8649
8650            // ==========================================
8651            // Mathematical & APL-Inspired Operations
8652            // ==========================================
8653            PipeOp::All(pred) => {
8654                // |∀{p} - check if ALL elements satisfy predicate
8655                match value {
8656                    Value::Array(arr) => {
8657                        for elem in arr.borrow().iter() {
8658                            self.environment
8659                                .borrow_mut()
8660                                .define("_".to_string(), elem.clone());
8661                            let result = self.evaluate(pred)?;
8662                            if !self.is_truthy(&result) {
8663                                return Ok(Value::Bool(false));
8664                            }
8665                        }
8666                        Ok(Value::Bool(true))
8667                    }
8668                    _ => Err(RuntimeError::new("All requires array")),
8669                }
8670            }
8671
8672            PipeOp::Any(pred) => {
8673                // |∃{p} - check if ANY element satisfies predicate
8674                match value {
8675                    Value::Array(arr) => {
8676                        for elem in arr.borrow().iter() {
8677                            self.environment
8678                                .borrow_mut()
8679                                .define("_".to_string(), elem.clone());
8680                            let result = self.evaluate(pred)?;
8681                            if self.is_truthy(&result) {
8682                                return Ok(Value::Bool(true));
8683                            }
8684                        }
8685                        Ok(Value::Bool(false))
8686                    }
8687                    _ => Err(RuntimeError::new("Any requires array")),
8688                }
8689            }
8690
8691            PipeOp::Compose(f) => {
8692                // |∘{f} - function composition / apply function
8693                self.environment.borrow_mut().define("_".to_string(), value);
8694                self.evaluate(f)
8695            }
8696
8697            PipeOp::Zip(other_expr) => {
8698                // |⋈{other} - zip with another collection
8699                let other = self.evaluate(other_expr)?;
8700                match (value, other) {
8701                    (Value::Array(arr1), Value::Array(arr2)) => {
8702                        let zipped: Vec<Value> = arr1
8703                            .borrow()
8704                            .iter()
8705                            .zip(arr2.borrow().iter())
8706                            .map(|(a, b)| Value::Tuple(Rc::new(vec![a.clone(), b.clone()])))
8707                            .collect();
8708                        Ok(Value::Array(Rc::new(RefCell::new(zipped))))
8709                    }
8710                    _ => Err(RuntimeError::new("Zip requires two arrays")),
8711                }
8712            }
8713
8714            PipeOp::Scan(f) => {
8715                // |∫{f} - cumulative fold (scan)
8716                match value {
8717                    Value::Array(arr) => {
8718                        let arr = arr.borrow();
8719                        if arr.is_empty() {
8720                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
8721                        }
8722                        let mut results = vec![arr[0].clone()];
8723                        let mut acc = arr[0].clone();
8724                        for elem in arr.iter().skip(1) {
8725                            self.environment
8726                                .borrow_mut()
8727                                .define("acc".to_string(), acc.clone());
8728                            self.environment
8729                                .borrow_mut()
8730                                .define("_".to_string(), elem.clone());
8731                            acc = self.evaluate(f)?;
8732                            results.push(acc.clone());
8733                        }
8734                        Ok(Value::Array(Rc::new(RefCell::new(results))))
8735                    }
8736                    _ => Err(RuntimeError::new("Scan requires array")),
8737                }
8738            }
8739
8740            PipeOp::Diff => {
8741                // |∂ - differences between adjacent elements
8742                match value {
8743                    Value::Array(arr) => {
8744                        let arr = arr.borrow();
8745                        if arr.len() < 2 {
8746                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
8747                        }
8748                        let mut diffs = Vec::new();
8749                        for i in 1..arr.len() {
8750                            let diff = self.subtract_values(&arr[i], &arr[i - 1])?;
8751                            diffs.push(diff);
8752                        }
8753                        Ok(Value::Array(Rc::new(RefCell::new(diffs))))
8754                    }
8755                    _ => Err(RuntimeError::new("Diff requires array")),
8756                }
8757            }
8758
8759            PipeOp::Gradient(var_expr) => {
8760                // |∇{var} - automatic differentiation
8761                // For now, just a placeholder - real autodiff requires tape recording
8762                let _ = var_expr;
8763                Ok(Value::Float(0.0)) // TODO: Implement real autodiff
8764            }
8765
8766            PipeOp::SortAsc => {
8767                // |⍋ - sort ascending
8768                match value {
8769                    Value::Array(arr) => {
8770                        let mut v = arr.borrow().clone();
8771                        v.sort_by(|a, b| self.compare_values(a, b, &None));
8772                        Ok(Value::Array(Rc::new(RefCell::new(v))))
8773                    }
8774                    _ => Err(RuntimeError::new("SortAsc requires array")),
8775                }
8776            }
8777
8778            PipeOp::SortDesc => {
8779                // |⍒ - sort descending
8780                match value {
8781                    Value::Array(arr) => {
8782                        let mut v = arr.borrow().clone();
8783                        v.sort_by(|a, b| self.compare_values(b, a, &None));
8784                        Ok(Value::Array(Rc::new(RefCell::new(v))))
8785                    }
8786                    _ => Err(RuntimeError::new("SortDesc requires array")),
8787                }
8788            }
8789
8790            PipeOp::Reverse => {
8791                // |⌽ - reverse collection
8792                match value {
8793                    Value::Array(arr) => {
8794                        let mut v = arr.borrow().clone();
8795                        v.reverse();
8796                        Ok(Value::Array(Rc::new(RefCell::new(v))))
8797                    }
8798                    _ => Err(RuntimeError::new("Reverse requires array")),
8799                }
8800            }
8801
8802            PipeOp::Cycle(n_expr) => {
8803                // |↻{n} - repeat collection n times
8804                match value {
8805                    Value::Array(arr) => {
8806                        let n_val = self.evaluate(n_expr)?;
8807                        let n = match n_val {
8808                            Value::Int(i) => i as usize,
8809                            _ => return Err(RuntimeError::new("Cycle count must be integer")),
8810                        };
8811                        let arr = arr.borrow();
8812                        let cycled: Vec<Value> =
8813                            arr.iter().cloned().cycle().take(arr.len() * n).collect();
8814                        Ok(Value::Array(Rc::new(RefCell::new(cycled))))
8815                    }
8816                    _ => Err(RuntimeError::new("Cycle requires array")),
8817                }
8818            }
8819
8820            PipeOp::Windows(n_expr) => {
8821                // |⌺{n} - sliding windows
8822                match value {
8823                    Value::Array(arr) => {
8824                        let n_val = self.evaluate(n_expr)?;
8825                        let n = match n_val {
8826                            Value::Int(i) => i as usize,
8827                            _ => return Err(RuntimeError::new("Window size must be integer")),
8828                        };
8829                        let arr = arr.borrow();
8830                        let windows: Vec<Value> = arr
8831                            .windows(n)
8832                            .map(|w| Value::Array(Rc::new(RefCell::new(w.to_vec()))))
8833                            .collect();
8834                        Ok(Value::Array(Rc::new(RefCell::new(windows))))
8835                    }
8836                    _ => Err(RuntimeError::new("Windows requires array")),
8837                }
8838            }
8839
8840            PipeOp::Chunks(n_expr) => {
8841                // |⊞{n} - split into chunks
8842                match value {
8843                    Value::Array(arr) => {
8844                        let n_val = self.evaluate(n_expr)?;
8845                        let n = match n_val {
8846                            Value::Int(i) => i as usize,
8847                            _ => return Err(RuntimeError::new("Chunk size must be integer")),
8848                        };
8849                        let arr = arr.borrow();
8850                        let chunks: Vec<Value> = arr
8851                            .chunks(n)
8852                            .map(|c| Value::Array(Rc::new(RefCell::new(c.to_vec()))))
8853                            .collect();
8854                        Ok(Value::Array(Rc::new(RefCell::new(chunks))))
8855                    }
8856                    _ => Err(RuntimeError::new("Chunks requires array")),
8857                }
8858            }
8859
8860            PipeOp::Flatten => {
8861                // |⋳ - flatten nested collection
8862                match value {
8863                    Value::Array(arr) => {
8864                        let mut flat = Vec::new();
8865                        for elem in arr.borrow().iter() {
8866                            match elem {
8867                                Value::Array(inner) => {
8868                                    flat.extend(inner.borrow().iter().cloned());
8869                                }
8870                                other => flat.push(other.clone()),
8871                            }
8872                        }
8873                        Ok(Value::Array(Rc::new(RefCell::new(flat))))
8874                    }
8875                    _ => Err(RuntimeError::new("Flatten requires array")),
8876                }
8877            }
8878
8879            PipeOp::Unique => {
8880                // |∪ - remove duplicates
8881                match value {
8882                    Value::Array(arr) => {
8883                        let mut seen = std::collections::HashSet::new();
8884                        let mut unique = Vec::new();
8885                        for elem in arr.borrow().iter() {
8886                            let key = format!("{:?}", elem);
8887                            if seen.insert(key) {
8888                                unique.push(elem.clone());
8889                            }
8890                        }
8891                        Ok(Value::Array(Rc::new(RefCell::new(unique))))
8892                    }
8893                    _ => Err(RuntimeError::new("Unique requires array")),
8894                }
8895            }
8896
8897            PipeOp::Enumerate => {
8898                // |⍳ - pair with indices
8899                match value {
8900                    Value::Array(arr) => {
8901                        let enumerated: Vec<Value> = arr
8902                            .borrow()
8903                            .iter()
8904                            .enumerate()
8905                            .map(|(i, v)| {
8906                                Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
8907                            })
8908                            .collect();
8909                        Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
8910                    }
8911                    _ => Err(RuntimeError::new("Enumerate requires array")),
8912                }
8913            }
8914        }
8915    }
8916
8917    // ==========================================
8918    // Protocol Helper Methods
8919    // ==========================================
8920
8921    /// Wrap a value in Reported evidentiality
8922    /// Network data is "hearsay" - it comes from external sources we can't verify
8923    fn wrap_reported(&self, value: Value) -> Value {
8924        Value::Evidential {
8925            value: Box::new(value),
8926            evidence: Evidence::Reported,
8927        }
8928    }
8929
8930    /// Send data over a protocol connection
8931    fn protocol_send(&mut self, connection: &Value, data: &Value) -> Result<Value, RuntimeError> {
8932        // Extract connection info and send data
8933        match connection {
8934            Value::Map(obj) => {
8935                let obj = obj.borrow();
8936                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
8937                    match protocol.as_str() {
8938                        "http" | "https" => {
8939                            // For HTTP, "send" means execute the request
8940                            // The data becomes the body
8941                            #[cfg(debug_assertions)]
8942                            eprintln!("[HTTP] Would send request with body: {:?}", data);
8943                            Ok(Value::Map(Rc::new(RefCell::new({
8944                                let mut response = HashMap::new();
8945                                response.insert("status".to_string(), Value::Int(200));
8946                                response.insert("body".to_string(), data.clone());
8947                                response.insert(
8948                                    "__protocol__".to_string(),
8949                                    Value::String(Rc::new("http_response".to_string())),
8950                                );
8951                                response
8952                            }))))
8953                        }
8954                        "ws" | "wss" => {
8955                            // For WebSocket, send a message
8956                            #[cfg(debug_assertions)]
8957                            eprintln!("[WebSocket] Would send message: {:?}", data);
8958                            Ok(Value::Bool(true)) // Message sent successfully
8959                        }
8960                        "grpc" => {
8961                            // For gRPC, send the request message
8962                            #[cfg(debug_assertions)]
8963                            eprintln!("[gRPC] Would send message: {:?}", data);
8964                            Ok(Value::Map(Rc::new(RefCell::new({
8965                                let mut response = HashMap::new();
8966                                response.insert("status".to_string(), Value::Int(0)); // OK
8967                                response.insert("message".to_string(), data.clone());
8968                                response.insert(
8969                                    "__protocol__".to_string(),
8970                                    Value::String(Rc::new("grpc_response".to_string())),
8971                                );
8972                                response
8973                            }))))
8974                        }
8975                        "kafka" => {
8976                            // For Kafka, produce a message
8977                            #[cfg(debug_assertions)]
8978                            eprintln!("[Kafka] Would produce message: {:?}", data);
8979                            Ok(Value::Map(Rc::new(RefCell::new({
8980                                let mut result = HashMap::new();
8981                                result.insert("partition".to_string(), Value::Int(0));
8982                                result.insert("offset".to_string(), Value::Int(42));
8983                                result
8984                            }))))
8985                        }
8986                        _ => Err(RuntimeError::new(format!("Unknown protocol: {}", protocol))),
8987                    }
8988                } else {
8989                    Err(RuntimeError::new(
8990                        "Connection object missing __protocol__ field",
8991                    ))
8992                }
8993            }
8994            _ => Err(RuntimeError::new("send requires a connection object")),
8995        }
8996    }
8997
8998    /// Receive data from a protocol connection
8999    fn protocol_recv(&mut self, connection: &Value) -> Result<Value, RuntimeError> {
9000        match connection {
9001            Value::Map(obj) => {
9002                let obj = obj.borrow();
9003                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
9004                    match protocol.as_str() {
9005                        "ws" | "wss" => {
9006                            // For WebSocket, receive a message
9007                            #[cfg(debug_assertions)]
9008                            eprintln!("[WebSocket] Would receive message");
9009                            Ok(Value::String(Rc::new("received message".to_string())))
9010                        }
9011                        "kafka" => {
9012                            // For Kafka, consume a message
9013                            #[cfg(debug_assertions)]
9014                            eprintln!("[Kafka] Would consume message");
9015                            Ok(Value::Map(Rc::new(RefCell::new({
9016                                let mut msg = HashMap::new();
9017                                msg.insert("key".to_string(), Value::Null);
9018                                msg.insert(
9019                                    "value".to_string(),
9020                                    Value::String(Rc::new("consumed message".to_string())),
9021                                );
9022                                msg.insert("partition".to_string(), Value::Int(0));
9023                                msg.insert("offset".to_string(), Value::Int(100));
9024                                msg
9025                            }))))
9026                        }
9027                        "grpc" => {
9028                            // For gRPC streaming, receive next message
9029                            #[cfg(debug_assertions)]
9030                            eprintln!("[gRPC] Would receive stream message");
9031                            Ok(Value::Map(Rc::new(RefCell::new({
9032                                let mut msg = HashMap::new();
9033                                msg.insert(
9034                                    "data".to_string(),
9035                                    Value::String(Rc::new("stream data".to_string())),
9036                                );
9037                                msg
9038                            }))))
9039                        }
9040                        _ => Err(RuntimeError::new(format!(
9041                            "recv not supported for protocol: {}",
9042                            protocol
9043                        ))),
9044                    }
9045                } else {
9046                    Err(RuntimeError::new(
9047                        "Connection object missing __protocol__ field",
9048                    ))
9049                }
9050            }
9051            _ => Err(RuntimeError::new("recv requires a connection object")),
9052        }
9053    }
9054
9055    /// Create a streaming iterator over protocol data
9056    fn protocol_stream(
9057        &mut self,
9058        connection: &Value,
9059        _handler: &Value,
9060    ) -> Result<Value, RuntimeError> {
9061        // Create a lazy stream that yields values with Reported evidentiality
9062        match connection {
9063            Value::Map(obj) => {
9064                let obj = obj.borrow();
9065                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
9066                    #[cfg(debug_assertions)]
9067                    eprintln!("[{}] Would create stream", protocol);
9068
9069                    // Return a stream object that can be iterated
9070                    Ok(Value::Map(Rc::new(RefCell::new({
9071                        let mut stream = HashMap::new();
9072                        stream.insert(
9073                            "__type__".to_string(),
9074                            Value::String(Rc::new("Stream".to_string())),
9075                        );
9076                        stream.insert("__protocol__".to_string(), Value::String(protocol.clone()));
9077                        stream.insert(
9078                            "__evidentiality__".to_string(),
9079                            Value::String(Rc::new("reported".to_string())),
9080                        );
9081                        stream
9082                    }))))
9083                } else {
9084                    Err(RuntimeError::new(
9085                        "Connection object missing __protocol__ field",
9086                    ))
9087                }
9088            }
9089            _ => Err(RuntimeError::new("stream requires a connection object")),
9090        }
9091    }
9092
9093    /// Establish a protocol connection
9094    fn protocol_connect(
9095        &mut self,
9096        target: &Value,
9097        _config: Option<&Value>,
9098    ) -> Result<Value, RuntimeError> {
9099        match target {
9100            Value::String(url) => {
9101                // Parse URL to determine protocol
9102                let protocol = if url.starts_with("wss://") || url.starts_with("ws://") {
9103                    if url.starts_with("wss://") {
9104                        "wss"
9105                    } else {
9106                        "ws"
9107                    }
9108                } else if url.starts_with("https://") || url.starts_with("http://") {
9109                    if url.starts_with("https://") {
9110                        "https"
9111                    } else {
9112                        "http"
9113                    }
9114                } else if url.starts_with("grpc://") || url.starts_with("grpcs://") {
9115                    "grpc"
9116                } else if url.starts_with("kafka://") {
9117                    "kafka"
9118                } else if url.starts_with("amqp://") || url.starts_with("amqps://") {
9119                    "amqp"
9120                } else {
9121                    "unknown"
9122                };
9123
9124                #[cfg(debug_assertions)]
9125                eprintln!("[{}] Would connect to: {}", protocol, url);
9126
9127                // Return a connection object
9128                Ok(Value::Map(Rc::new(RefCell::new({
9129                    let mut conn = HashMap::new();
9130                    conn.insert(
9131                        "__protocol__".to_string(),
9132                        Value::String(Rc::new(protocol.to_string())),
9133                    );
9134                    conn.insert("url".to_string(), Value::String(url.clone()));
9135                    conn.insert("connected".to_string(), Value::Bool(true));
9136                    conn
9137                }))))
9138            }
9139            Value::Map(obj) => {
9140                // Already a connection config object
9141                let mut conn = obj.borrow().clone();
9142                conn.insert("connected".to_string(), Value::Bool(true));
9143                Ok(Value::Map(Rc::new(RefCell::new(conn))))
9144            }
9145            _ => Err(RuntimeError::new(
9146                "connect requires URL string or config object",
9147            )),
9148        }
9149    }
9150
9151    /// Close a protocol connection
9152    fn protocol_close(&mut self, connection: &Value) -> Result<(), RuntimeError> {
9153        match connection {
9154            Value::Map(obj) => {
9155                let mut obj = obj.borrow_mut();
9156                if let Some(Value::String(protocol)) = obj.get("__protocol__").cloned() {
9157                    #[cfg(debug_assertions)]
9158                    eprintln!("[{}] Would close connection", protocol);
9159                    obj.insert("connected".to_string(), Value::Bool(false));
9160                    Ok(())
9161                } else {
9162                    Err(RuntimeError::new(
9163                        "Connection object missing __protocol__ field",
9164                    ))
9165                }
9166            }
9167            _ => Err(RuntimeError::new("close requires a connection object")),
9168        }
9169    }
9170
9171    /// Add a header to a protocol request
9172    fn protocol_add_header(
9173        &mut self,
9174        mut request: Value,
9175        name: &Value,
9176        header_value: &Value,
9177    ) -> Result<Value, RuntimeError> {
9178        let name_str = match name {
9179            Value::String(s) => (**s).clone(),
9180            _ => return Err(RuntimeError::new("Header name must be a string")),
9181        };
9182        let value_str = match header_value {
9183            Value::String(s) => (**s).clone(),
9184            Value::Int(i) => i.to_string(),
9185            _ => return Err(RuntimeError::new("Header value must be string or int")),
9186        };
9187
9188        match &mut request {
9189            Value::Map(obj) => {
9190                let mut obj = obj.borrow_mut();
9191
9192                // Get or create headers map
9193                let headers = obj
9194                    .entry("headers".to_string())
9195                    .or_insert_with(|| Value::Map(Rc::new(RefCell::new(HashMap::new()))));
9196
9197                if let Value::Map(headers_obj) = headers {
9198                    headers_obj
9199                        .borrow_mut()
9200                        .insert(name_str, Value::String(Rc::new(value_str)));
9201                }
9202                drop(obj);
9203                Ok(request)
9204            }
9205            _ => Err(RuntimeError::new("header requires a request object")),
9206        }
9207    }
9208
9209    /// Set the body of a protocol request
9210    fn protocol_set_body(
9211        &mut self,
9212        mut request: Value,
9213        body: &Value,
9214    ) -> Result<Value, RuntimeError> {
9215        match &mut request {
9216            Value::Map(obj) => {
9217                obj.borrow_mut().insert("body".to_string(), body.clone());
9218                Ok(request)
9219            }
9220            _ => Err(RuntimeError::new("body requires a request object")),
9221        }
9222    }
9223
9224    /// Set the timeout for a protocol operation
9225    fn protocol_set_timeout(
9226        &mut self,
9227        mut request: Value,
9228        ms: &Value,
9229    ) -> Result<Value, RuntimeError> {
9230        let timeout_ms = match ms {
9231            Value::Int(n) => *n,
9232            Value::Float(f) => *f as i64,
9233            _ => return Err(RuntimeError::new("Timeout must be a number (milliseconds)")),
9234        };
9235
9236        match &mut request {
9237            Value::Map(obj) => {
9238                obj.borrow_mut()
9239                    .insert("timeout_ms".to_string(), Value::Int(timeout_ms));
9240                Ok(request)
9241            }
9242            _ => Err(RuntimeError::new("timeout requires a request object")),
9243        }
9244    }
9245
9246    /// Set the retry policy for a protocol operation
9247    fn protocol_set_retry(
9248        &mut self,
9249        mut request: Value,
9250        count: &Value,
9251        strategy: Option<&Value>,
9252    ) -> Result<Value, RuntimeError> {
9253        let retry_count = match count {
9254            Value::Int(n) => *n,
9255            _ => return Err(RuntimeError::new("Retry count must be an integer")),
9256        };
9257
9258        match &mut request {
9259            Value::Map(obj) => {
9260                let mut obj = obj.borrow_mut();
9261                obj.insert("retry_count".to_string(), Value::Int(retry_count));
9262                if let Some(strat) = strategy {
9263                    obj.insert("retry_strategy".to_string(), strat.clone());
9264                }
9265                drop(obj);
9266                Ok(request)
9267            }
9268            _ => Err(RuntimeError::new("retry requires a request object")),
9269        }
9270    }
9271
9272    fn sum_values(&self, value: Value) -> Result<Value, RuntimeError> {
9273        match value {
9274            Value::Array(arr) => {
9275                let arr = arr.borrow();
9276                if arr.is_empty() {
9277                    return Ok(Value::Int(0));
9278                }
9279                let mut sum = match &arr[0] {
9280                    Value::Int(_) => Value::Int(0),
9281                    Value::Float(_) => Value::Float(0.0),
9282                    _ => return Err(RuntimeError::new("Cannot sum non-numeric array")),
9283                };
9284                for item in arr.iter() {
9285                    sum = match (&sum, item) {
9286                        (Value::Int(a), Value::Int(b)) => Value::Int(a + b),
9287                        (Value::Float(a), Value::Float(b)) => Value::Float(a + b),
9288                        (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 + b),
9289                        (Value::Float(a), Value::Int(b)) => Value::Float(a + *b as f64),
9290                        _ => return Err(RuntimeError::new("Cannot sum non-numeric values")),
9291                    };
9292                }
9293                Ok(sum)
9294            }
9295            _ => Err(RuntimeError::new("sum requires array")),
9296        }
9297    }
9298
9299    fn product_values(&self, value: Value) -> Result<Value, RuntimeError> {
9300        match value {
9301            Value::Array(arr) => {
9302                let arr = arr.borrow();
9303                if arr.is_empty() {
9304                    return Ok(Value::Int(1));
9305                }
9306                let mut prod = match &arr[0] {
9307                    Value::Int(_) => Value::Int(1),
9308                    Value::Float(_) => Value::Float(1.0),
9309                    _ => return Err(RuntimeError::new("Cannot multiply non-numeric array")),
9310                };
9311                for item in arr.iter() {
9312                    prod = match (&prod, item) {
9313                        (Value::Int(a), Value::Int(b)) => Value::Int(a * b),
9314                        (Value::Float(a), Value::Float(b)) => Value::Float(a * b),
9315                        (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 * b),
9316                        (Value::Float(a), Value::Int(b)) => Value::Float(a * *b as f64),
9317                        _ => return Err(RuntimeError::new("Cannot multiply non-numeric values")),
9318                    };
9319                }
9320                Ok(prod)
9321            }
9322            _ => Err(RuntimeError::new("product requires array")),
9323        }
9324    }
9325
9326    fn min_values(&self, value: Value) -> Result<Value, RuntimeError> {
9327        match value {
9328            Value::Array(arr) => {
9329                let arr = arr.borrow();
9330                if arr.is_empty() {
9331                    return Err(RuntimeError::new("Cannot find min of empty array"));
9332                }
9333                let mut min = arr[0].clone();
9334                for item in arr.iter().skip(1) {
9335                    min = match (&min, item) {
9336                        (Value::Int(a), Value::Int(b)) => {
9337                            if *b < *a {
9338                                Value::Int(*b)
9339                            } else {
9340                                Value::Int(*a)
9341                            }
9342                        }
9343                        (Value::Float(a), Value::Float(b)) => {
9344                            if *b < *a {
9345                                Value::Float(*b)
9346                            } else {
9347                                Value::Float(*a)
9348                            }
9349                        }
9350                        (Value::Int(a), Value::Float(b)) => {
9351                            let af = *a as f64;
9352                            if *b < af {
9353                                Value::Float(*b)
9354                            } else {
9355                                Value::Float(af)
9356                            }
9357                        }
9358                        (Value::Float(a), Value::Int(b)) => {
9359                            let bf = *b as f64;
9360                            if bf < *a {
9361                                Value::Float(bf)
9362                            } else {
9363                                Value::Float(*a)
9364                            }
9365                        }
9366                        _ => {
9367                            return Err(RuntimeError::new("Cannot find min of non-numeric values"))
9368                        }
9369                    };
9370                }
9371                Ok(min)
9372            }
9373            _ => Err(RuntimeError::new("min requires array")),
9374        }
9375    }
9376
9377    fn max_values(&self, value: Value) -> Result<Value, RuntimeError> {
9378        match value {
9379            Value::Array(arr) => {
9380                let arr = arr.borrow();
9381                if arr.is_empty() {
9382                    return Err(RuntimeError::new("Cannot find max of empty array"));
9383                }
9384                let mut max = arr[0].clone();
9385                for item in arr.iter().skip(1) {
9386                    max = match (&max, item) {
9387                        (Value::Int(a), Value::Int(b)) => {
9388                            if *b > *a {
9389                                Value::Int(*b)
9390                            } else {
9391                                Value::Int(*a)
9392                            }
9393                        }
9394                        (Value::Float(a), Value::Float(b)) => {
9395                            if *b > *a {
9396                                Value::Float(*b)
9397                            } else {
9398                                Value::Float(*a)
9399                            }
9400                        }
9401                        (Value::Int(a), Value::Float(b)) => {
9402                            let af = *a as f64;
9403                            if *b > af {
9404                                Value::Float(*b)
9405                            } else {
9406                                Value::Float(af)
9407                            }
9408                        }
9409                        (Value::Float(a), Value::Int(b)) => {
9410                            let bf = *b as f64;
9411                            if bf > *a {
9412                                Value::Float(bf)
9413                            } else {
9414                                Value::Float(*a)
9415                            }
9416                        }
9417                        _ => {
9418                            return Err(RuntimeError::new("Cannot find max of non-numeric values"))
9419                        }
9420                    };
9421                }
9422                Ok(max)
9423            }
9424            _ => Err(RuntimeError::new("max requires array")),
9425        }
9426    }
9427
9428    fn concat_values(&self, value: Value) -> Result<Value, RuntimeError> {
9429        match value {
9430            Value::Array(arr) => {
9431                let arr = arr.borrow();
9432                if arr.is_empty() {
9433                    return Ok(Value::String(Rc::new(String::new())));
9434                }
9435                // Determine if we're concatenating strings or arrays
9436                match &arr[0] {
9437                    Value::String(_) => {
9438                        let mut result = String::new();
9439                        for item in arr.iter() {
9440                            if let Value::String(s) = item {
9441                                result.push_str(s);
9442                            } else {
9443                                return Err(RuntimeError::new(
9444                                    "concat requires all elements to be strings",
9445                                ));
9446                            }
9447                        }
9448                        Ok(Value::String(Rc::new(result)))
9449                    }
9450                    Value::Array(_) => {
9451                        let mut result = Vec::new();
9452                        for item in arr.iter() {
9453                            if let Value::Array(inner) = item {
9454                                result.extend(inner.borrow().iter().cloned());
9455                            } else {
9456                                return Err(RuntimeError::new(
9457                                    "concat requires all elements to be arrays",
9458                                ));
9459                            }
9460                        }
9461                        Ok(Value::Array(Rc::new(RefCell::new(result))))
9462                    }
9463                    _ => Err(RuntimeError::new("concat requires strings or arrays")),
9464                }
9465            }
9466            _ => Err(RuntimeError::new("concat requires array")),
9467        }
9468    }
9469
9470    fn all_values(&self, value: Value) -> Result<Value, RuntimeError> {
9471        match value {
9472            Value::Array(arr) => {
9473                let arr = arr.borrow();
9474                for item in arr.iter() {
9475                    match item {
9476                        Value::Bool(b) => {
9477                            if !*b {
9478                                return Ok(Value::Bool(false));
9479                            }
9480                        }
9481                        _ => return Err(RuntimeError::new("all requires array of booleans")),
9482                    }
9483                }
9484                Ok(Value::Bool(true))
9485            }
9486            _ => Err(RuntimeError::new("all requires array")),
9487        }
9488    }
9489
9490    fn any_values(&self, value: Value) -> Result<Value, RuntimeError> {
9491        match value {
9492            Value::Array(arr) => {
9493                let arr = arr.borrow();
9494                for item in arr.iter() {
9495                    match item {
9496                        Value::Bool(b) => {
9497                            if *b {
9498                                return Ok(Value::Bool(true));
9499                            }
9500                        }
9501                        _ => return Err(RuntimeError::new("any requires array of booleans")),
9502                    }
9503                }
9504                Ok(Value::Bool(false))
9505            }
9506            _ => Err(RuntimeError::new("any requires array")),
9507        }
9508    }
9509
9510    fn compare_values(&self, a: &Value, b: &Value, _field: &Option<Ident>) -> std::cmp::Ordering {
9511        // Simple comparison for now
9512        match (a, b) {
9513            (Value::Int(a), Value::Int(b)) => a.cmp(b),
9514            (Value::Float(a), Value::Float(b)) => {
9515                a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)
9516            }
9517            (Value::String(a), Value::String(b)) => a.cmp(b),
9518            _ => std::cmp::Ordering::Equal,
9519        }
9520    }
9521
9522    /// Subtract two values (for diff operation)
9523    fn subtract_values(&self, a: &Value, b: &Value) -> Result<Value, RuntimeError> {
9524        match (a, b) {
9525            (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a - b)),
9526            (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a - b)),
9527            (Value::Int(a), Value::Float(b)) => Ok(Value::Float(*a as f64 - b)),
9528            (Value::Float(a), Value::Int(b)) => Ok(Value::Float(a - *b as f64)),
9529            _ => Err(RuntimeError::new(format!(
9530                "Cannot subtract {:?} from {:?}",
9531                b, a
9532            ))),
9533        }
9534    }
9535
9536    fn eval_closure(
9537        &mut self,
9538        params: &[ClosureParam],
9539        body: &Expr,
9540    ) -> Result<Value, RuntimeError> {
9541        let param_names: Vec<String> = params
9542            .iter()
9543            .map(|p| match &p.pattern {
9544                Pattern::Ident { name, .. } => name.name.clone(),
9545                _ => "_".to_string(),
9546            })
9547            .collect();
9548
9549        Ok(Value::Function(Rc::new(Function {
9550            name: None,
9551            params: param_names,
9552            body: body.clone(),
9553            closure: self.environment.clone(),
9554        })))
9555    }
9556
9557    fn eval_struct_literal(
9558        &mut self,
9559        path: &TypePath,
9560        fields: &[FieldInit],
9561        rest: &Option<Box<Expr>>,
9562    ) -> Result<Value, RuntimeError> {
9563        let raw_name = path
9564            .segments
9565            .iter()
9566            .map(|s| s.ident.name.as_str())
9567            .collect::<Vec<_>>()
9568            .join("::");
9569
9570        // Resolve "Self" to the actual type name if we're in an impl block
9571        let name = if raw_name == "Self" {
9572            if let Some(ref self_type) = self.current_self_type {
9573                self_type.clone()
9574            } else {
9575                // Fall back to trying to infer from field names
9576                raw_name
9577            }
9578        } else {
9579            raw_name
9580        };
9581
9582        let mut field_values = HashMap::new();
9583
9584        // If there's a rest expression (..expr), evaluate it first to get base fields
9585        if let Some(rest_expr) = rest {
9586            // Set current_self_type for the rest expression (e.g., Default::default())
9587            let prev_self_type = self.current_self_type.clone();
9588            self.current_self_type = Some(name.clone());
9589
9590            let rest_value = self.evaluate(rest_expr)?;
9591
9592            self.current_self_type = prev_self_type;
9593
9594            // Extract fields from the rest value
9595            if let Value::Struct { fields: rest_fields, .. } = rest_value {
9596                for (k, v) in rest_fields.borrow().iter() {
9597                    field_values.insert(k.clone(), v.clone());
9598                }
9599            }
9600        }
9601
9602        // Override with explicitly provided fields
9603        for field in fields {
9604            let value = match &field.value {
9605                Some(expr) => self.evaluate(expr)?,
9606                None => self
9607                    .environment
9608                    .borrow()
9609                    .get(&field.name.name)
9610                    .ok_or_else(|| {
9611                        RuntimeError::new(format!("Unknown variable: {}", field.name.name))
9612                    })?,
9613            };
9614            field_values.insert(field.name.name.clone(), value);
9615        }
9616
9617        Ok(Value::Struct {
9618            name,
9619            fields: Rc::new(RefCell::new(field_values)),
9620        })
9621    }
9622
9623    /// Extract evidentiality from a value (recursively unwraps Evidential wrapper)
9624    fn extract_evidence(value: &Value) -> Option<Evidence> {
9625        match value {
9626            Value::Evidential { evidence, .. } => Some(*evidence),
9627            _ => None,
9628        }
9629    }
9630
9631    /// Extract affect from a value
9632    fn extract_affect(value: &Value) -> Option<&RuntimeAffect> {
9633        match value {
9634            Value::Affective { affect, .. } => Some(affect),
9635            _ => None,
9636        }
9637    }
9638
9639    /// Derive evidence from affect markers.
9640    /// Sarcasm implies uncertainty (meaning is inverted).
9641    /// Confidence directly maps to evidence levels.
9642    fn affect_to_evidence(affect: &RuntimeAffect) -> Option<Evidence> {
9643        // Sarcasm indicates the literal meaning shouldn't be trusted
9644        if affect.sarcasm {
9645            return Some(Evidence::Uncertain);
9646        }
9647
9648        // Confidence maps directly to evidence
9649        match affect.confidence {
9650            Some(RuntimeConfidence::High) => Some(Evidence::Known),
9651            Some(RuntimeConfidence::Low) => Some(Evidence::Uncertain),
9652            Some(RuntimeConfidence::Medium) | None => None,
9653        }
9654    }
9655
9656    /// Combine two evidence levels, returning the "worst" (most uncertain) one.
9657    /// Order: Known < Uncertain < Reported < Paradox
9658    fn combine_evidence(a: Option<Evidence>, b: Option<Evidence>) -> Option<Evidence> {
9659        match (a, b) {
9660            (None, None) => None,
9661            (Some(e), None) | (None, Some(e)) => Some(e),
9662            (Some(a), Some(b)) => {
9663                let rank = |e: Evidence| match e {
9664                    Evidence::Known => 0,
9665                    Evidence::Uncertain => 1,
9666                    Evidence::Reported => 2,
9667                    Evidence::Paradox => 3,
9668                };
9669                if rank(a) >= rank(b) {
9670                    Some(a)
9671                } else {
9672                    Some(b)
9673                }
9674            }
9675        }
9676    }
9677
9678    /// Unwrap an evidential value to get the inner value for display
9679    fn unwrap_evidential(value: &Value) -> &Value {
9680        match value {
9681            Value::Evidential { value: inner, .. } => Self::unwrap_evidential(inner),
9682            _ => value,
9683        }
9684    }
9685
9686    /// Unwrap an affective value to get the inner value
9687    fn unwrap_affective(value: &Value) -> &Value {
9688        match value {
9689            Value::Affective { value: inner, .. } => Self::unwrap_affective(inner),
9690            _ => value,
9691        }
9692    }
9693
9694    /// Unwrap both evidential and affective wrappers
9695    fn unwrap_value(value: &Value) -> &Value {
9696        match value {
9697            Value::Evidential { value: inner, .. } => Self::unwrap_value(inner),
9698            Value::Affective { value: inner, .. } => Self::unwrap_value(inner),
9699            _ => value,
9700        }
9701    }
9702
9703    /// Unwrap all wrappers including Ref for deep value access
9704    fn unwrap_all(value: &Value) -> Value {
9705        match value {
9706            Value::Evidential { value: inner, .. } => Self::unwrap_all(inner),
9707            Value::Affective { value: inner, .. } => Self::unwrap_all(inner),
9708            Value::Ref(r) => Self::unwrap_all(&r.borrow()),
9709            _ => value.clone(),
9710        }
9711    }
9712
9713    fn eval_evidential(&mut self, expr: &Expr, ev: &Evidentiality) -> Result<Value, RuntimeError> {
9714        let value = self.evaluate(expr)?;
9715
9716        // For Known (!) evidentiality - this is an "unwrap" or "assert known" operation
9717        // If the value is null, return null (propagate nulls for graceful handling)
9718        // If the value is already evidential, unwrap it
9719        // Otherwise, return the value as-is (it's implicitly known)
9720        if *ev == Evidentiality::Known {
9721            return match value {
9722                Value::Null => Ok(Value::Null),  // Null propagates
9723                Value::Evidential { value: inner, .. } => Ok(*inner),  // Unwrap evidential
9724                other => Ok(other),  // Non-null, non-evidential returns as-is
9725            };
9726        }
9727
9728        let evidence = match ev {
9729            Evidentiality::Known => Evidence::Known,  // Won't reach here
9730            Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
9731            Evidentiality::Reported => Evidence::Reported,
9732            Evidentiality::Paradox => Evidence::Paradox,
9733        };
9734        Ok(Value::Evidential {
9735            value: Box::new(value),
9736            evidence,
9737        })
9738    }
9739
9740    /// Evaluate format! macro - parse format string and arguments
9741    fn eval_format_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
9742        // Token string looks like: "\"format string\" , arg1 , arg2"
9743        // We need to parse this properly
9744
9745        // Find the format string (first quoted string)
9746        let tokens = tokens.trim();
9747        if !tokens.starts_with('"') {
9748            // No format string - just return the tokens as-is
9749            return Ok(Value::String(Rc::new(tokens.to_string())));
9750        }
9751
9752        // Find the end of the format string
9753        let mut in_escape = false;
9754        let mut format_end = 1;
9755        for (i, c) in tokens[1..].char_indices() {
9756            if in_escape {
9757                in_escape = false;
9758            } else if c == '\\' {
9759                in_escape = true;
9760            } else if c == '"' {
9761                format_end = i + 2; // +1 for starting quote, +1 for this quote
9762                break;
9763            }
9764        }
9765
9766        let format_str = &tokens[1..format_end-1]; // Remove quotes
9767        crate::sigil_debug!("DEBUG format_str: '{}'", format_str);
9768        let args_str = if format_end < tokens.len() {
9769            tokens[format_end..].trim_start_matches(',').trim()
9770        } else {
9771            ""
9772        };
9773
9774        // Parse and evaluate arguments
9775        let mut arg_values: Vec<String> = Vec::new();
9776        if !args_str.is_empty() {
9777            // Split by comma, but respect parentheses/brackets
9778            let mut depth = 0;
9779            let mut current_arg = String::new();
9780            for c in args_str.chars() {
9781                match c {
9782                    '(' | '[' | '{' => {
9783                        depth += 1;
9784                        current_arg.push(c);
9785                    }
9786                    ')' | ']' | '}' => {
9787                        depth -= 1;
9788                        current_arg.push(c);
9789                    }
9790                    ',' if depth == 0 => {
9791                        let arg = current_arg.trim().to_string();
9792                        if !arg.is_empty() {
9793                            // Parse and evaluate the argument expression
9794                            let mut parser = crate::parser::Parser::new(&arg);
9795                            match parser.parse_expr() {
9796                                Ok(expr) => {
9797                                    match self.evaluate(&expr) {
9798                                        Ok(val) => arg_values.push(self.format_value(&val)),
9799                                        Err(_) => arg_values.push(arg),
9800                                    }
9801                                }
9802                                Err(_) => arg_values.push(arg),
9803                            }
9804                        }
9805                        current_arg.clear();
9806                    }
9807                    _ => current_arg.push(c),
9808                }
9809            }
9810            // Don't forget the last argument
9811            let arg = current_arg.trim().to_string();
9812            if !arg.is_empty() {
9813                let mut parser = crate::parser::Parser::new(&arg);
9814                match parser.parse_expr() {
9815                    Ok(expr) => {
9816                        match self.evaluate(&expr) {
9817                            Ok(val) => arg_values.push(self.format_value(&val)),
9818                            Err(_) => arg_values.push(arg),
9819                        }
9820                    }
9821                    Err(_) => arg_values.push(arg),
9822                }
9823            }
9824        }
9825
9826        // Format the string by replacing {} and {:?} with arguments
9827        let mut result = String::new();
9828        let mut arg_idx = 0;
9829        let mut chars = format_str.chars().peekable();
9830
9831        while let Some(c) = chars.next() {
9832            if c == '{' {
9833                if chars.peek() == Some(&'{') {
9834                    // Escaped {{ -> {
9835                    chars.next();
9836                    result.push('{');
9837                } else {
9838                    // Consume until }
9839                    let mut placeholder = String::new();
9840                    while let Some(pc) = chars.next() {
9841                        if pc == '}' {
9842                            break;
9843                        }
9844                        placeholder.push(pc);
9845                    }
9846                    // Insert argument value
9847                    if arg_idx < arg_values.len() {
9848                        result.push_str(&arg_values[arg_idx]);
9849                        arg_idx += 1;
9850                    } else {
9851                        result.push_str(&format!("{{{}}}", placeholder));
9852                    }
9853                }
9854            } else if c == '}' {
9855                if chars.peek() == Some(&'}') {
9856                    // Escaped }} -> }
9857                    chars.next();
9858                    result.push('}');
9859                } else {
9860                    result.push('}');
9861                }
9862            } else if c == '\\' {
9863                // Handle escape sequences
9864                if let Some(next) = chars.next() {
9865                    match next {
9866                        'n' => result.push('\n'),
9867                        't' => result.push('\t'),
9868                        'r' => result.push('\r'),
9869                        '\\' => result.push('\\'),
9870                        '"' => result.push('"'),
9871                        _ => {
9872                            result.push('\\');
9873                            result.push(next);
9874                        }
9875                    }
9876                }
9877            } else {
9878                result.push(c);
9879            }
9880        }
9881
9882        Ok(Value::String(Rc::new(result)))
9883    }
9884
9885    /// Format a value for display in format!
9886    fn format_value(&self, value: &Value) -> String {
9887        match value {
9888            Value::String(s) => s.to_string(),
9889            Value::Int(n) => n.to_string(),
9890            Value::Float(f) => f.to_string(),
9891            Value::Bool(b) => b.to_string(),
9892            Value::Char(c) => c.to_string(),
9893            Value::Null => "null".to_string(),
9894            Value::Array(arr) => {
9895                let items: Vec<String> = arr.borrow().iter().map(|v| self.format_value(v)).collect();
9896                format!("[{}]", items.join(", "))
9897            }
9898            Value::Tuple(items) => {
9899                let formatted: Vec<String> = items.iter().map(|v| self.format_value(v)).collect();
9900                format!("({})", formatted.join(", "))
9901            }
9902            Value::Struct { name, fields } => {
9903                let field_strs: Vec<String> = fields.borrow().iter()
9904                    .map(|(k, v)| format!("{}: {}", k, self.format_value(v)))
9905                    .collect();
9906                format!("{} {{ {} }}", name, field_strs.join(", "))
9907            }
9908            Value::Variant { enum_name, variant_name, fields } => {
9909                match fields {
9910                    Some(f) if !f.is_empty() => {
9911                        let formatted: Vec<String> = f.iter().map(|v| self.format_value(v)).collect();
9912                        format!("{}::{}({})", enum_name, variant_name, formatted.join(", "))
9913                    }
9914                    _ => format!("{}::{}", enum_name, variant_name),
9915                }
9916            }
9917            Value::Evidential { value: inner, evidence } => {
9918                format!("{:?}{}", evidence, self.format_value(inner))
9919            }
9920            Value::Ref(r) => self.format_value(&r.borrow()),
9921            _ => format!("{:?}", value),
9922        }
9923    }
9924
9925    /// Evaluate vec! macro
9926    fn eval_vec_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
9927        // Parse comma-separated elements
9928        let mut elements = Vec::new();
9929        let mut depth = 0;
9930        let mut current = String::new();
9931
9932        for c in tokens.chars() {
9933            match c {
9934                '(' | '[' | '{' => {
9935                    depth += 1;
9936                    current.push(c);
9937                }
9938                ')' | ']' | '}' => {
9939                    depth -= 1;
9940                    current.push(c);
9941                }
9942                ',' if depth == 0 => {
9943                    let elem = current.trim().to_string();
9944                    if !elem.is_empty() {
9945                        let mut parser = crate::parser::Parser::new(&elem);
9946                        if let Ok(expr) = parser.parse_expr() {
9947                            elements.push(self.evaluate(&expr)?);
9948                        }
9949                    }
9950                    current.clear();
9951                }
9952                _ => current.push(c),
9953            }
9954        }
9955
9956        // Last element
9957        let elem = current.trim().to_string();
9958        if !elem.is_empty() {
9959            let mut parser = crate::parser::Parser::new(&elem);
9960            if let Ok(expr) = parser.parse_expr() {
9961                elements.push(self.evaluate(&expr)?);
9962            }
9963        }
9964
9965        Ok(Value::Array(Rc::new(RefCell::new(elements))))
9966    }
9967
9968    fn eval_range(
9969        &mut self,
9970        start: &Option<Box<Expr>>,
9971        end: &Option<Box<Expr>>,
9972        inclusive: bool,
9973    ) -> Result<Value, RuntimeError> {
9974        let start_val = match start {
9975            Some(e) => match self.evaluate(e)? {
9976                Value::Int(n) => n,
9977                _ => return Err(RuntimeError::new("Range requires integer bounds")),
9978            },
9979            None => 0,
9980        };
9981
9982        let end_val = match end {
9983            Some(e) => match self.evaluate(e)? {
9984                Value::Int(n) => n,
9985                _ => return Err(RuntimeError::new("Range requires integer bounds")),
9986            },
9987            None => {
9988                // Open-ended range (like 1..) - return a tuple (start, None) marker
9989                // This can be used by slice operations to slice to end
9990                return Ok(Value::Tuple(Rc::new(vec![
9991                    Value::Int(start_val),
9992                    Value::Null,  // None marker for open end
9993                ])));
9994            }
9995        };
9996
9997        let values: Vec<Value> = if inclusive {
9998            (start_val..=end_val).map(Value::Int).collect()
9999        } else {
10000            (start_val..end_val).map(Value::Int).collect()
10001        };
10002
10003        Ok(Value::Array(Rc::new(RefCell::new(values))))
10004    }
10005
10006    fn is_truthy(&self, value: &Value) -> bool {
10007        match value {
10008            Value::Null => false,
10009            Value::Bool(b) => *b,
10010            Value::Int(n) => *n != 0,
10011            Value::Float(n) => *n != 0.0,
10012            Value::String(s) => !s.is_empty(),
10013            Value::Array(arr) => !arr.borrow().is_empty(),
10014            Value::Empty => false,
10015            Value::Evidential { value, .. } => self.is_truthy(value),
10016            _ => true,
10017        }
10018    }
10019}
10020
10021impl Default for Interpreter {
10022    fn default() -> Self {
10023        Self::new()
10024    }
10025}
10026
10027#[cfg(test)]
10028mod tests {
10029    use super::*;
10030    use crate::Parser;
10031
10032    fn run(source: &str) -> Result<Value, RuntimeError> {
10033        let mut parser = Parser::new(source);
10034        let file = parser
10035            .parse_file()
10036            .map_err(|e| RuntimeError::new(e.to_string()))?;
10037        let mut interp = Interpreter::new();
10038        interp.execute(&file)
10039    }
10040
10041    #[test]
10042    fn test_arithmetic() {
10043        assert!(matches!(
10044            run("fn main() { return 2 + 3; }"),
10045            Ok(Value::Int(5))
10046        ));
10047        assert!(matches!(
10048            run("fn main() { return 10 - 4; }"),
10049            Ok(Value::Int(6))
10050        ));
10051        assert!(matches!(
10052            run("fn main() { return 3 * 4; }"),
10053            Ok(Value::Int(12))
10054        ));
10055        assert!(matches!(
10056            run("fn main() { return 15 / 3; }"),
10057            Ok(Value::Int(5))
10058        ));
10059        assert!(matches!(
10060            run("fn main() { return 2 ** 10; }"),
10061            Ok(Value::Int(1024))
10062        ));
10063    }
10064
10065    #[test]
10066    fn test_variables() {
10067        assert!(matches!(
10068            run("fn main() { let x = 42; return x; }"),
10069            Ok(Value::Int(42))
10070        ));
10071    }
10072
10073    #[test]
10074    fn test_conditionals() {
10075        assert!(matches!(
10076            run("fn main() { if true { return 1; } else { return 2; } }"),
10077            Ok(Value::Int(1))
10078        ));
10079        assert!(matches!(
10080            run("fn main() { if false { return 1; } else { return 2; } }"),
10081            Ok(Value::Int(2))
10082        ));
10083    }
10084
10085    #[test]
10086    fn test_arrays() {
10087        assert!(matches!(
10088            run("fn main() { return [1, 2, 3][1]; }"),
10089            Ok(Value::Int(2))
10090        ));
10091    }
10092
10093    #[test]
10094    fn test_functions() {
10095        let result = run("
10096            fn double(x: i64) -> i64 { return x * 2; }
10097            fn main() { return double(21); }
10098        ");
10099        assert!(matches!(result, Ok(Value::Int(42))));
10100    }
10101
10102    #[test]
10103    fn test_pipe_transform() {
10104        let result = run("fn main() { return [1, 2, 3]|τ{_ * 2}|sum; }");
10105        assert!(matches!(result, Ok(Value::Int(12))));
10106    }
10107
10108    #[test]
10109    fn test_pipe_filter() {
10110        let result = run("fn main() { return [1, 2, 3, 4, 5]|φ{_ > 2}|sum; }");
10111        assert!(matches!(result, Ok(Value::Int(12)))); // 3 + 4 + 5
10112    }
10113
10114    #[test]
10115    fn test_interpolation_evidentiality_propagation() {
10116        // Test that evidentiality propagates through string interpolation
10117        // When an evidential value is interpolated, the result string should carry that evidentiality
10118        let result = run(r#"
10119            fn main() {
10120                let rep = reported(42);
10121
10122                // Interpolating a reported value should make the string reported
10123                let s = f"Value: {rep}";
10124                return s;
10125            }
10126        "#);
10127
10128        match result {
10129            Ok(Value::Evidential {
10130                evidence: Evidence::Reported,
10131                value,
10132            }) => {
10133                // The inner value should be a string
10134                assert!(matches!(*value, Value::String(_)));
10135            }
10136            Ok(other) => panic!("Expected Evidential Reported, got {:?}", other),
10137            Err(e) => panic!("Error: {:?}", e),
10138        }
10139    }
10140
10141    #[test]
10142    fn test_interpolation_worst_evidence_wins() {
10143        // When multiple evidential values are interpolated, the worst evidence level wins
10144        let result = run(r#"
10145            fn main() {
10146                let k = known(1);         // Known is best
10147                let u = uncertain(2);     // Uncertain is worse
10148
10149                // Combining known and uncertain should yield uncertain
10150                let s = f"{k} and {u}";
10151                return s;
10152            }
10153        "#);
10154
10155        match result {
10156            Ok(Value::Evidential {
10157                evidence: Evidence::Uncertain,
10158                ..
10159            }) => (),
10160            Ok(other) => panic!("Expected Evidential Uncertain, got {:?}", other),
10161            Err(e) => panic!("Error: {:?}", e),
10162        }
10163    }
10164
10165    #[test]
10166    fn test_interpolation_no_evidential_plain_string() {
10167        // When no evidential values are interpolated, the result is a plain string
10168        let result = run(r#"
10169            fn main() {
10170                let x = 42;
10171                let s = f"Value: {x}";
10172                return s;
10173            }
10174        "#);
10175
10176        match result {
10177            Ok(Value::String(s)) => {
10178                assert_eq!(*s, "Value: 42");
10179            }
10180            Ok(other) => panic!("Expected plain String, got {:?}", other),
10181            Err(e) => panic!("Error: {:?}", e),
10182        }
10183    }
10184}