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 {
392                enum_name,
393                variant_name,
394            } => {
395                write!(f, "<constructor {}::{}>", enum_name, variant_name)
396            }
397            Value::DefaultConstructor { type_name } => {
398                write!(f, "<default {}>", type_name)
399            }
400            Value::Range {
401                start,
402                end,
403                inclusive,
404            } => match (start, end) {
405                (Some(s), Some(e)) => {
406                    if *inclusive {
407                        write!(f, "{}..={}", s, e)
408                    } else {
409                        write!(f, "{}..{}", s, e)
410                    }
411                }
412                (Some(s), None) => write!(f, "{}..", s),
413                (None, Some(e)) => {
414                    if *inclusive {
415                        write!(f, "..={}", e)
416                    } else {
417                        write!(f, "..{}", e)
418                    }
419                }
420                (None, None) => write!(f, ".."),
421            },
422        }
423    }
424}
425
426impl fmt::Display for Value {
427    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428        match self {
429            Value::Null => write!(f, "null"),
430            Value::Bool(b) => write!(f, "{}", b),
431            Value::Int(n) => write!(f, "{}", n),
432            Value::Float(n) => write!(f, "{}", n),
433            Value::String(s) => write!(f, "{}", s),
434            Value::Char(c) => write!(f, "{}", c),
435            Value::Array(arr) => {
436                let arr = arr.borrow();
437                write!(f, "[")?;
438                for (i, v) in arr.iter().enumerate() {
439                    if i > 0 {
440                        write!(f, ", ")?;
441                    }
442                    write!(f, "{}", v)?;
443                }
444                write!(f, "]")
445            }
446            Value::Evidential { value, .. } => write!(f, "{}", value),
447            Value::Affective { value, affect } => {
448                // Display affect markers as suffix symbols
449                let mut suffix = String::new();
450                if let Some(sent) = &affect.sentiment {
451                    suffix.push(match sent {
452                        RuntimeSentiment::Positive => '⊕',
453                        RuntimeSentiment::Negative => '⊖',
454                        RuntimeSentiment::Neutral => '⊜',
455                    });
456                }
457                if affect.sarcasm {
458                    suffix.push('⸮');
459                }
460                if let Some(int) = &affect.intensity {
461                    suffix.push(match int {
462                        RuntimeIntensity::Up => '↑',
463                        RuntimeIntensity::Down => '↓',
464                        RuntimeIntensity::Max => '⇈',
465                    });
466                }
467                if let Some(form) = &affect.formality {
468                    suffix.push(match form {
469                        RuntimeFormality::Formal => '♔',
470                        RuntimeFormality::Informal => '♟',
471                    });
472                }
473                if let Some(emo) = &affect.emotion {
474                    suffix.push(match emo {
475                        RuntimeEmotion::Joy => '☺',
476                        RuntimeEmotion::Sadness => '☹',
477                        RuntimeEmotion::Anger => '⚡',
478                        RuntimeEmotion::Fear => '❄',
479                        RuntimeEmotion::Surprise => '✦',
480                        RuntimeEmotion::Love => '♡',
481                    });
482                }
483                if let Some(conf) = &affect.confidence {
484                    suffix.push(match conf {
485                        RuntimeConfidence::High => '◉',
486                        RuntimeConfidence::Medium => '◎',
487                        RuntimeConfidence::Low => '○',
488                    });
489                }
490                write!(f, "{}{}", value, suffix)
491            }
492            _ => write!(f, "{:?}", self),
493        }
494    }
495}
496
497/// Runtime error
498#[derive(Debug)]
499pub struct RuntimeError {
500    pub message: String,
501    pub span: Option<Span>,
502}
503
504impl RuntimeError {
505    pub fn new(message: impl Into<String>) -> Self {
506        Self {
507            message: message.into(),
508            span: None,
509        }
510    }
511
512    pub fn with_span(message: impl Into<String>, span: Span) -> Self {
513        Self {
514            message: message.into(),
515            span: Some(span),
516        }
517    }
518}
519
520impl fmt::Display for RuntimeError {
521    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522        write!(f, "Runtime error: {}", self.message)?;
523        if let Some(span) = self.span {
524            write!(f, " at {}", span)?;
525        }
526        Ok(())
527    }
528}
529
530/// Control flow signals for return/break/continue
531#[derive(Debug, Clone)]
532pub enum ControlFlow {
533    Return(Value),
534    Break(Option<Value>),
535    Continue,
536}
537
538impl From<ControlFlow> for RuntimeError {
539    fn from(cf: ControlFlow) -> Self {
540        match cf {
541            ControlFlow::Return(_) => RuntimeError::new("return outside function"),
542            ControlFlow::Break(_) => RuntimeError::new("break outside loop"),
543            ControlFlow::Continue => RuntimeError::new("continue outside loop"),
544        }
545    }
546}
547
548/// Result type that can contain control flow
549pub type EvalResult = Result<Value, EvalError>;
550
551/// Error type that includes control flow
552#[derive(Debug)]
553pub enum EvalError {
554    Runtime(RuntimeError),
555    Control(ControlFlow),
556}
557
558impl From<RuntimeError> for EvalError {
559    fn from(e: RuntimeError) -> Self {
560        EvalError::Runtime(e)
561    }
562}
563
564impl From<ControlFlow> for EvalError {
565    fn from(cf: ControlFlow) -> Self {
566        EvalError::Control(cf)
567    }
568}
569
570impl fmt::Display for EvalError {
571    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
572        match self {
573            EvalError::Runtime(e) => write!(f, "{}", e),
574            EvalError::Control(cf) => write!(f, "Unexpected control flow: {:?}", cf),
575        }
576    }
577}
578
579/// Environment for variable bindings
580#[derive(Clone)]
581pub struct Environment {
582    values: HashMap<String, Value>,
583    parent: Option<Rc<RefCell<Environment>>>,
584}
585
586impl Environment {
587    pub fn new() -> Self {
588        Self {
589            values: HashMap::new(),
590            parent: None,
591        }
592    }
593
594    pub fn with_parent(parent: Rc<RefCell<Environment>>) -> Self {
595        Self {
596            values: HashMap::new(),
597            parent: Some(parent),
598        }
599    }
600
601    pub fn define(&mut self, name: String, value: Value) {
602        self.values.insert(name, value);
603    }
604
605    pub fn get(&self, name: &str) -> Option<Value> {
606        if let Some(value) = self.values.get(name) {
607            Some(value.clone())
608        } else if let Some(ref parent) = self.parent {
609            parent.borrow().get(name)
610        } else {
611            None
612        }
613    }
614
615    pub fn set(&mut self, name: &str, value: Value) -> Result<(), RuntimeError> {
616        if self.values.contains_key(name) {
617            self.values.insert(name.to_string(), value);
618            Ok(())
619        } else if let Some(ref parent) = self.parent {
620            parent.borrow_mut().set(name, value)
621        } else {
622            Err(RuntimeError::new(format!("Undefined variable: {}", name)))
623        }
624    }
625}
626
627impl Default for Environment {
628    fn default() -> Self {
629        Self::new()
630    }
631}
632
633/// The Sigil interpreter
634pub struct Interpreter {
635    /// Global environment
636    pub globals: Rc<RefCell<Environment>>,
637    /// Current environment
638    pub environment: Rc<RefCell<Environment>>,
639    /// Type definitions
640    pub types: HashMap<String, TypeDef>,
641    /// Variant constructors: qualified_name -> (enum_name, variant_name, arity)
642    pub variant_constructors: HashMap<String, (String, String, usize)>,
643    /// Structs with #[derive(Default)]
644    pub default_structs: HashMap<String, StructDef>,
645    /// Output buffer (for testing)
646    pub output: Vec<String>,
647    /// Return value from the last return statement (control flow)
648    return_value: Option<Value>,
649    /// Program arguments (overrides env::args when set)
650    pub program_args: Option<Vec<String>>,
651    /// Current module prefix for registering definitions
652    pub current_module: Option<String>,
653    /// Current Self type (when inside an impl block)
654    pub current_self_type: Option<String>,
655    /// Current source directory for resolving relative module paths
656    pub current_source_dir: Option<String>,
657    /// Loaded crates registry (crate_name -> true if loaded)
658    pub loaded_crates: HashSet<String>,
659    /// Crates currently being loaded (for circular dependency detection)
660    pub loading_crates: HashSet<String>,
661    /// Project root directory (where Sigil.toml is located)
662    pub project_root: Option<PathBuf>,
663    /// Workspace members: crate_name -> relative path from project root
664    pub workspace_members: HashMap<String, PathBuf>,
665    /// Types that implement Drop trait - call drop() when they go out of scope
666    pub drop_types: HashSet<String>,
667}
668
669/// Type definition for structs/enums
670#[derive(Clone)]
671pub enum TypeDef {
672    Struct(StructDef),
673    Enum(EnumDef),
674}
675
676impl Interpreter {
677    pub fn new() -> Self {
678        let globals = Rc::new(RefCell::new(Environment::new()));
679        let environment = globals.clone();
680
681        let mut interp = Self {
682            globals: globals.clone(),
683            environment,
684            types: HashMap::new(),
685            variant_constructors: HashMap::new(),
686            default_structs: HashMap::new(),
687            return_value: None,
688            output: Vec::new(),
689            program_args: None,
690            current_module: None,
691            current_self_type: None,
692            current_source_dir: None,
693            loaded_crates: HashSet::new(),
694            loading_crates: HashSet::new(),
695            project_root: None,
696            workspace_members: HashMap::new(),
697            drop_types: HashSet::new(),
698        };
699
700        // Register built-in functions
701        interp.register_builtins();
702
703        interp
704    }
705
706    /// Set program arguments (overrides env::args for the running program)
707    pub fn set_program_args(&mut self, args: Vec<String>) {
708        self.program_args = Some(args);
709    }
710
711    /// Set current module for registering definitions (module name, not file stem)
712    pub fn set_current_module(&mut self, module: Option<String>) {
713        self.current_module = module;
714    }
715
716    /// Set current source directory for resolving relative module paths
717    pub fn set_current_source_dir(&mut self, dir: Option<String>) {
718        self.current_source_dir = dir;
719    }
720
721    /// Get program arguments (uses overridden args if set, otherwise env::args)
722    pub fn get_program_args(&self) -> Vec<String> {
723        self.program_args
724            .clone()
725            .unwrap_or_else(|| std::env::args().collect())
726    }
727
728    /// Find and parse Sigil.toml from a source directory, walking up parent directories
729    /// Looks for a workspace Sigil.toml (one with [workspace] section and members)
730    pub fn discover_project(&mut self, source_dir: &str) -> Result<(), RuntimeError> {
731        let mut current = PathBuf::from(source_dir);
732
733        // Walk up to find Sigil.toml with [workspace] section
734        loop {
735            let sigil_toml = current.join("Sigil.toml");
736            if sigil_toml.exists() {
737                if let Ok(result) = self.try_parse_workspace_toml(&sigil_toml) {
738                    if result {
739                        return Ok(());
740                    }
741                    // Not a workspace Sigil.toml, continue searching
742                }
743            }
744
745            // Also check for sigil.toml (lowercase)
746            let sigil_toml_lower = current.join("sigil.toml");
747            if sigil_toml_lower.exists() {
748                if let Ok(result) = self.try_parse_workspace_toml(&sigil_toml_lower) {
749                    if result {
750                        return Ok(());
751                    }
752                    // Not a workspace Sigil.toml, continue searching
753                }
754            }
755
756            if !current.pop() {
757                // No workspace Sigil.toml found
758                crate::sigil_debug!(
759                    "DEBUG discover_project: no workspace Sigil.toml found from {}",
760                    source_dir
761                );
762                return Ok(());
763            }
764        }
765    }
766
767    /// Try to parse a Sigil.toml as a workspace config. Returns Ok(true) if it's a workspace,
768    /// Ok(false) if it's a crate-level config, Err if parsing failed.
769    fn try_parse_workspace_toml(&mut self, path: &PathBuf) -> Result<bool, RuntimeError> {
770        let content = std::fs::read_to_string(path)
771            .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
772
773        let toml_value: toml::Value = content
774            .parse()
775            .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
776
777        // Check if this has a [workspace] section with members
778        if let Some(workspace) = toml_value.get("workspace") {
779            if workspace
780                .get("members")
781                .and_then(|m| m.as_array())
782                .is_some()
783            {
784                // This is a workspace Sigil.toml
785                return self.parse_sigil_toml(path).map(|_| true);
786            }
787        }
788
789        // Not a workspace config
790        crate::sigil_debug!(
791            "DEBUG try_parse_workspace_toml: {:?} is not a workspace config",
792            path
793        );
794        Ok(false)
795    }
796
797    /// Parse a Sigil.toml file and populate workspace_members
798    fn parse_sigil_toml(&mut self, path: &PathBuf) -> Result<(), RuntimeError> {
799        let content = std::fs::read_to_string(path)
800            .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
801
802        let toml_value: toml::Value = content
803            .parse()
804            .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
805
806        self.project_root = path.parent().map(|p| p.to_path_buf());
807
808        // Parse [workspace] members
809        if let Some(workspace) = toml_value.get("workspace") {
810            if let Some(members) = workspace.get("members").and_then(|m| m.as_array()) {
811                for member in members {
812                    if let Some(member_path) = member.as_str() {
813                        // Extract crate name from path (e.g., "crates/samael-analysis" -> "samael_analysis")
814                        let crate_name = std::path::Path::new(member_path)
815                            .file_name()
816                            .and_then(|n| n.to_str())
817                            .map(|n| n.replace("-", "_"))
818                            .unwrap_or_default();
819
820                        if !crate_name.is_empty() {
821                            crate::sigil_debug!(
822                                "DEBUG parse_sigil_toml: registered workspace member: {} -> {}",
823                                &crate_name,
824                                member_path
825                            );
826                            self.workspace_members
827                                .insert(crate_name, PathBuf::from(member_path));
828                        }
829                    }
830                }
831            }
832        }
833
834        crate::sigil_debug!(
835            "DEBUG parse_sigil_toml: loaded {} workspace members from {:?}",
836            self.workspace_members.len(),
837            path
838        );
839
840        Ok(())
841    }
842
843    /// Load an external crate by name
844    pub fn load_crate(&mut self, crate_name: &str) -> Result<bool, RuntimeError> {
845        // Check if already loaded
846        if self.loaded_crates.contains(crate_name) {
847            return Ok(true);
848        }
849
850        // Check for circular dependency
851        if self.loading_crates.contains(crate_name) {
852            return Err(RuntimeError::new(format!(
853                "Circular dependency detected: crate '{}' is already being loaded",
854                crate_name
855            )));
856        }
857
858        // Find crate path in workspace members
859        let crate_path = match self.workspace_members.get(crate_name) {
860            Some(p) => p.clone(),
861            None => {
862                crate::sigil_debug!(
863                    "DEBUG load_crate: crate '{}' not found in workspace members",
864                    crate_name
865                );
866                return Ok(false);
867            }
868        };
869
870        let project_root = match &self.project_root {
871            Some(r) => r.clone(),
872            None => {
873                crate::sigil_debug!("DEBUG load_crate: no project root set");
874                return Ok(false);
875            }
876        };
877
878        // Build path to lib.sigil
879        let lib_path = project_root.join(&crate_path).join("src").join("lib.sigil");
880
881        if !lib_path.exists() {
882            crate::sigil_debug!("DEBUG load_crate: lib.sigil not found at {:?}", lib_path);
883            return Ok(false);
884        }
885
886        // Mark as loading (for circular dependency detection)
887        self.loading_crates.insert(crate_name.to_string());
888
889        crate::sigil_debug!(
890            "DEBUG load_crate: loading crate '{}' from {:?}",
891            crate_name,
892            lib_path
893        );
894
895        // Read and parse the lib.sigil file
896        let source = std::fs::read_to_string(&lib_path)
897            .map_err(|e| RuntimeError::new(format!("Failed to read {:?}: {}", lib_path, e)))?;
898
899        // Save current state
900        let prev_module = self.current_module.clone();
901        let prev_source_dir = self.current_source_dir.clone();
902
903        // Set module context to crate name
904        self.current_module = Some(crate_name.to_string());
905        self.current_source_dir = lib_path.parent().map(|p| p.to_string_lossy().to_string());
906
907        // Parse the source
908        let mut parser = crate::Parser::new(&source);
909
910        match parser.parse_file() {
911            Ok(parsed_file) => {
912                // Execute all items to register types and functions
913                for item in &parsed_file.items {
914                    if let Err(e) = self.execute_item(&item.node) {
915                        crate::sigil_warn!("Warning: error loading crate '{}': {}", crate_name, e);
916                    }
917                }
918            }
919            Err(e) => {
920                crate::sigil_warn!("Warning: failed to parse crate '{}': {:?}", crate_name, e);
921            }
922        }
923
924        // Restore previous state
925        self.current_module = prev_module;
926        self.current_source_dir = prev_source_dir;
927
928        // Mark as loaded and no longer loading
929        self.loading_crates.remove(crate_name);
930        self.loaded_crates.insert(crate_name.to_string());
931
932        crate::sigil_debug!(
933            "DEBUG load_crate: successfully loaded crate '{}'",
934            crate_name
935        );
936
937        Ok(true)
938    }
939
940    fn register_builtins(&mut self) {
941        // PhantomData - zero-sized type marker
942        self.globals
943            .borrow_mut()
944            .define("PhantomData".to_string(), Value::Null);
945
946        // Print function
947        self.define_builtin("print", None, |interp, args| {
948            let output: Vec<String> = args.iter().map(|v| format!("{}", v)).collect();
949            let line = output.join(" ");
950            println!("{}", line);
951            interp.output.push(line);
952            Ok(Value::Null)
953        });
954
955        // Type checking
956        self.define_builtin("type_of", Some(1), |_, args| {
957            let type_name = match &args[0] {
958                Value::Null => "null",
959                Value::Bool(_) => "bool",
960                Value::Int(_) => "i64",
961                Value::Float(_) => "f64",
962                Value::String(_) => "str",
963                Value::Char(_) => "char",
964                Value::Array(_) => "array",
965                Value::Tuple(_) => "tuple",
966                Value::Struct { name, .. } => name,
967                Value::Variant { enum_name, .. } => enum_name,
968                Value::Function(_) => "fn",
969                Value::BuiltIn(_) => "builtin",
970                Value::Ref(_) => "ref",
971                Value::Infinity => "infinity",
972                Value::Empty => "empty",
973                Value::Evidential { .. } => "evidential",
974                Value::Affective { .. } => "affective",
975                Value::Map(_) => "map",
976                Value::Set(_) => "set",
977                Value::Channel(_) => "channel",
978                Value::ThreadHandle(_) => "thread",
979                Value::Actor(_) => "actor",
980                Value::Future(_) => "future",
981                Value::VariantConstructor { .. } => "variant_constructor",
982                Value::DefaultConstructor { .. } => "default_constructor",
983                Value::Range { .. } => "range",
984            };
985            Ok(Value::String(Rc::new(type_name.to_string())))
986        });
987
988        // Array operations
989        self.define_builtin("len", Some(1), |_, args| match &args[0] {
990            Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
991            Value::String(s) => Ok(Value::Int(s.len() as i64)),
992            Value::Tuple(t) => Ok(Value::Int(t.len() as i64)),
993            _ => Err(RuntimeError::new("len() requires array, string, or tuple")),
994        });
995
996        self.define_builtin("push", Some(2), |_, args| match &args[0] {
997            Value::Array(arr) => {
998                arr.borrow_mut().push(args[1].clone());
999                Ok(Value::Null)
1000            }
1001            _ => Err(RuntimeError::new("push() requires array")),
1002        });
1003
1004        self.define_builtin("pop", Some(1), |_, args| match &args[0] {
1005            Value::Array(arr) => arr
1006                .borrow_mut()
1007                .pop()
1008                .ok_or_else(|| RuntimeError::new("pop() on empty array")),
1009            _ => Err(RuntimeError::new("pop() requires array")),
1010        });
1011
1012        // Math functions
1013        self.define_builtin("abs", Some(1), |_, args| match &args[0] {
1014            Value::Int(n) => Ok(Value::Int(n.abs())),
1015            Value::Float(n) => Ok(Value::Float(n.abs())),
1016            _ => Err(RuntimeError::new("abs() requires number")),
1017        });
1018
1019        self.define_builtin("sqrt", Some(1), |_, args| match &args[0] {
1020            Value::Int(n) => Ok(Value::Float((*n as f64).sqrt())),
1021            Value::Float(n) => Ok(Value::Float(n.sqrt())),
1022            _ => Err(RuntimeError::new("sqrt() requires number")),
1023        });
1024
1025        self.define_builtin("sin", Some(1), |_, args| match &args[0] {
1026            Value::Int(n) => Ok(Value::Float((*n as f64).sin())),
1027            Value::Float(n) => Ok(Value::Float(n.sin())),
1028            _ => Err(RuntimeError::new("sin() requires number")),
1029        });
1030
1031        self.define_builtin("cos", Some(1), |_, args| match &args[0] {
1032            Value::Int(n) => Ok(Value::Float((*n as f64).cos())),
1033            Value::Float(n) => Ok(Value::Float(n.cos())),
1034            _ => Err(RuntimeError::new("cos() requires number")),
1035        });
1036
1037        // Evidence operations
1038        self.define_builtin("known", Some(1), |_, args| {
1039            Ok(Value::Evidential {
1040                value: Box::new(args[0].clone()),
1041                evidence: Evidence::Known,
1042            })
1043        });
1044
1045        self.define_builtin("uncertain", Some(1), |_, args| {
1046            Ok(Value::Evidential {
1047                value: Box::new(args[0].clone()),
1048                evidence: Evidence::Uncertain,
1049            })
1050        });
1051
1052        self.define_builtin("reported", Some(1), |_, args| {
1053            Ok(Value::Evidential {
1054                value: Box::new(args[0].clone()),
1055                evidence: Evidence::Reported,
1056            })
1057        });
1058
1059        // Box::new - just return the value (Sigil is GC'd)
1060        self.globals.borrow_mut().define(
1061            "Box·new".to_string(),
1062            Value::BuiltIn(Rc::new(BuiltInFn {
1063                name: "Box·new".to_string(),
1064                arity: Some(1),
1065                func: |_, args| Ok(args[0].clone()),
1066            })),
1067        );
1068
1069        // Map::new - create empty map
1070        self.globals.borrow_mut().define(
1071            "Map·new".to_string(),
1072            Value::BuiltIn(Rc::new(BuiltInFn {
1073                name: "Map·new".to_string(),
1074                arity: Some(0),
1075                func: |_, _| Ok(Value::Map(Rc::new(RefCell::new(HashMap::new())))),
1076            })),
1077        );
1078
1079        // Range function
1080        self.define_builtin("range", Some(2), |_, args| {
1081            let start = match &args[0] {
1082                Value::Int(n) => *n,
1083                _ => return Err(RuntimeError::new("range() requires integers")),
1084            };
1085            let end = match &args[1] {
1086                Value::Int(n) => *n,
1087                _ => return Err(RuntimeError::new("range() requires integers")),
1088            };
1089            let values: Vec<Value> = (start..end).map(Value::Int).collect();
1090            Ok(Value::Array(Rc::new(RefCell::new(values))))
1091        });
1092
1093        // ExitCode enum for process exit codes (like Rust's std::process::ExitCode)
1094        self.globals.borrow_mut().define(
1095            "ExitCode·SUCCESS".to_string(),
1096            Value::Variant {
1097                enum_name: "ExitCode".to_string(),
1098                variant_name: "SUCCESS".to_string(),
1099                fields: Some(Rc::new(vec![Value::Int(0)])),
1100            },
1101        );
1102        self.globals.borrow_mut().define(
1103            "ExitCode·FAILURE".to_string(),
1104            Value::Variant {
1105                enum_name: "ExitCode".to_string(),
1106                variant_name: "FAILURE".to_string(),
1107                fields: Some(Rc::new(vec![Value::Int(1)])),
1108            },
1109        );
1110
1111        // PathBuf::from - create a PathBuf from a string path
1112        self.define_builtin("PathBuf·from", Some(1), |_, args| {
1113            // Unwrap Ref types to get the actual value
1114            let arg = match &args[0] {
1115                Value::Ref(r) => r.borrow().clone(),
1116                other => other.clone(),
1117            };
1118            let path = match &arg {
1119                Value::String(s2) => s2.as_str().to_string(),
1120                _ => return Err(RuntimeError::new("PathBuf::from expects a string")),
1121            };
1122            // Represent PathBuf as a struct with a path field
1123            let mut fields = HashMap::new();
1124            fields.insert("path".to_string(), Value::String(Rc::new(path)));
1125            Ok(Value::Struct {
1126                name: "PathBuf".to_string(),
1127                fields: Rc::new(RefCell::new(fields)),
1128            })
1129        });
1130
1131        // Path::new - create a Path from a string (similar to PathBuf for our purposes)
1132        self.define_builtin("Path·new", Some(1), |_, args| {
1133            // Unwrap Ref types to get the actual value
1134            let arg = match &args[0] {
1135                Value::Ref(r) => r.borrow().clone(),
1136                other => other.clone(),
1137            };
1138            let path = match &arg {
1139                Value::String(s2) => s2.as_str().to_string(),
1140                _ => return Err(RuntimeError::new("Path::new expects a string")),
1141            };
1142            let mut fields = HashMap::new();
1143            fields.insert("path".to_string(), Value::String(Rc::new(path)));
1144            Ok(Value::Struct {
1145                name: "Path".to_string(),
1146                fields: Rc::new(RefCell::new(fields)),
1147            })
1148        });
1149
1150        // std::fs::read_to_string - read file contents as a string
1151        self.define_builtin("std·fs·read_to_string", Some(1), |interp, args| {
1152            // Recursively unwrap Ref types to get the actual value
1153            fn unwrap_refs(v: &Value) -> Value {
1154                match v {
1155                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1156                    other => other.clone(),
1157                }
1158            }
1159            let arg = unwrap_refs(&args[0]);
1160            crate::sigil_debug!("DEBUG read_to_string: arg = {:?}", arg);
1161            // Also dump the environment to see what 'path' is bound to
1162            crate::sigil_debug!(
1163                "DEBUG read_to_string: env has path = {:?}",
1164                interp.environment.borrow().get("path")
1165            );
1166            let path = match &arg {
1167                Value::String(s) => s.to_string(),
1168                // Handle PathBuf or Path structs
1169                Value::Struct { name, fields, .. } => {
1170                    crate::sigil_debug!("DEBUG read_to_string: struct name = {}", name);
1171                    fields
1172                        .borrow()
1173                        .get("path")
1174                        .and_then(|v| {
1175                            if let Value::String(s) = v {
1176                                Some(s.to_string())
1177                            } else {
1178                                None
1179                            }
1180                        })
1181                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1182                }
1183                // Handle Option::Some(String)
1184                Value::Variant {
1185                    enum_name,
1186                    variant_name,
1187                    fields,
1188                } if enum_name == "Option" && variant_name == "Some" => {
1189                    if let Some(fields) = fields {
1190                        if let Some(Value::String(s)) = fields.first() {
1191                            s.to_string()
1192                        } else {
1193                            return Err(RuntimeError::new(
1194                                "read_to_string: Option::Some does not contain a string",
1195                            ));
1196                        }
1197                    } else {
1198                        return Err(RuntimeError::new(
1199                            "read_to_string: Option::Some has no fields",
1200                        ));
1201                    }
1202                }
1203                _ => {
1204                    return Err(RuntimeError::new(&format!(
1205                        "read_to_string expects a path string or PathBuf, got {:?}",
1206                        arg
1207                    )))
1208                }
1209            };
1210            match std::fs::read_to_string(&path) {
1211                Ok(content) => Ok(Value::Variant {
1212                    enum_name: "Result".to_string(),
1213                    variant_name: "Ok".to_string(),
1214                    fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1215                }),
1216                Err(e) => Ok(Value::Variant {
1217                    enum_name: "Result".to_string(),
1218                    variant_name: "Err".to_string(),
1219                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1220                }),
1221            }
1222        });
1223
1224        // fs::read_to_string - alias without std prefix
1225        self.define_builtin("fs·read_to_string", Some(1), |_, args| {
1226            let arg = match &args[0] {
1227                Value::Ref(r) => r.borrow().clone(),
1228                other => other.clone(),
1229            };
1230            let path = match &arg {
1231                Value::String(s) => s.to_string(),
1232                Value::Struct { fields, .. } => fields
1233                    .borrow()
1234                    .get("path")
1235                    .and_then(|v| {
1236                        if let Value::String(s) = v {
1237                            Some(s.to_string())
1238                        } else {
1239                            None
1240                        }
1241                    })
1242                    .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?,
1243                _ => {
1244                    return Err(RuntimeError::new(
1245                        "read_to_string expects a path string or PathBuf",
1246                    ))
1247                }
1248            };
1249            match std::fs::read_to_string(&path) {
1250                Ok(content) => Ok(Value::Variant {
1251                    enum_name: "Result".to_string(),
1252                    variant_name: "Ok".to_string(),
1253                    fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1254                }),
1255                Err(e) => Ok(Value::Variant {
1256                    enum_name: "Result".to_string(),
1257                    variant_name: "Err".to_string(),
1258                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1259                }),
1260            }
1261        });
1262
1263        // std::fs::read_dir - read directory entries
1264        self.define_builtin("std·fs·read_dir", Some(1), |_, args| {
1265            fn unwrap_refs(v: &Value) -> Value {
1266                match v {
1267                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1268                    other => other.clone(),
1269                }
1270            }
1271            let arg = unwrap_refs(&args[0]);
1272            let path = match &arg {
1273                Value::String(s) => s.to_string(),
1274                Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => fields
1275                    .borrow()
1276                    .get("path")
1277                    .and_then(|v| {
1278                        if let Value::String(s) = v {
1279                            Some(s.to_string())
1280                        } else {
1281                            None
1282                        }
1283                    })
1284                    .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?,
1285                _ => {
1286                    return Err(RuntimeError::new(&format!(
1287                        "read_dir expects a path, got {:?}",
1288                        arg
1289                    )))
1290                }
1291            };
1292            match std::fs::read_dir(&path) {
1293                Ok(entries) => {
1294                    // Collect entries into a Vec of DirEntry structs wrapped in Result::Ok
1295                    let entry_values: Vec<Value> = entries
1296                        .filter_map(|e| e.ok())
1297                        .map(|e| {
1298                            let entry_path = e.path().to_string_lossy().to_string();
1299                            let mut fields = HashMap::new();
1300                            fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
1301                            // Each entry is wrapped in Result::Ok
1302                            Value::Variant {
1303                                enum_name: "Result".to_string(),
1304                                variant_name: "Ok".to_string(),
1305                                fields: Some(Rc::new(vec![Value::Struct {
1306                                    name: "DirEntry".to_string(),
1307                                    fields: Rc::new(RefCell::new(fields)),
1308                                }])),
1309                            }
1310                        })
1311                        .collect();
1312                    // The overall result is Ok(iterator/array)
1313                    Ok(Value::Variant {
1314                        enum_name: "Result".to_string(),
1315                        variant_name: "Ok".to_string(),
1316                        fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(
1317                            entry_values,
1318                        )))])),
1319                    })
1320                }
1321                Err(e) => Ok(Value::Variant {
1322                    enum_name: "Result".to_string(),
1323                    variant_name: "Err".to_string(),
1324                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1325                }),
1326            }
1327        });
1328
1329        // fs::read_dir - alias without std prefix
1330        self.define_builtin("fs·read_dir", Some(1), |_, args| {
1331            fn unwrap_refs(v: &Value) -> Value {
1332                match v {
1333                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1334                    other => other.clone(),
1335                }
1336            }
1337            let arg = unwrap_refs(&args[0]);
1338            let path = match &arg {
1339                Value::String(s) => s.to_string(),
1340                Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => fields
1341                    .borrow()
1342                    .get("path")
1343                    .and_then(|v| {
1344                        if let Value::String(s) = v {
1345                            Some(s.to_string())
1346                        } else {
1347                            None
1348                        }
1349                    })
1350                    .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?,
1351                _ => {
1352                    return Err(RuntimeError::new(&format!(
1353                        "read_dir expects a path, got {:?}",
1354                        arg
1355                    )))
1356                }
1357            };
1358            match std::fs::read_dir(&path) {
1359                Ok(entries) => {
1360                    let entry_values: Vec<Value> = entries
1361                        .filter_map(|e| e.ok())
1362                        .map(|e| {
1363                            let entry_path = e.path().to_string_lossy().to_string();
1364                            let mut fields = HashMap::new();
1365                            fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
1366                            Value::Variant {
1367                                enum_name: "Result".to_string(),
1368                                variant_name: "Ok".to_string(),
1369                                fields: Some(Rc::new(vec![Value::Struct {
1370                                    name: "DirEntry".to_string(),
1371                                    fields: Rc::new(RefCell::new(fields)),
1372                                }])),
1373                            }
1374                        })
1375                        .collect();
1376                    Ok(Value::Variant {
1377                        enum_name: "Result".to_string(),
1378                        variant_name: "Ok".to_string(),
1379                        fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(
1380                            entry_values,
1381                        )))])),
1382                    })
1383                }
1384                Err(e) => Ok(Value::Variant {
1385                    enum_name: "Result".to_string(),
1386                    variant_name: "Err".to_string(),
1387                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1388                }),
1389            }
1390        });
1391
1392        // std::env::var - get environment variable
1393        self.define_builtin("std·env·var", Some(1), |_, args| {
1394            fn unwrap_refs(v: &Value) -> Value {
1395                match v {
1396                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1397                    other => other.clone(),
1398                }
1399            }
1400            let arg = unwrap_refs(&args[0]);
1401            let var_name = match &arg {
1402                Value::String(s) => s.to_string(),
1403                _ => return Err(RuntimeError::new("env::var expects a string")),
1404            };
1405            match std::env::var(&var_name) {
1406                Ok(value) => Ok(Value::Variant {
1407                    enum_name: "Result".to_string(),
1408                    variant_name: "Ok".to_string(),
1409                    fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
1410                }),
1411                Err(_) => Ok(Value::Variant {
1412                    enum_name: "Result".to_string(),
1413                    variant_name: "Err".to_string(),
1414                    fields: Some(Rc::new(vec![Value::String(Rc::new(
1415                        "Environment variable not found".to_string(),
1416                    ))])),
1417                }),
1418            }
1419        });
1420
1421        // env::var - alias without std prefix
1422        self.define_builtin("env·var", Some(1), |_, args| {
1423            fn unwrap_refs(v: &Value) -> Value {
1424                match v {
1425                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1426                    other => other.clone(),
1427                }
1428            }
1429            let arg = unwrap_refs(&args[0]);
1430            let var_name = match &arg {
1431                Value::String(s) => s.to_string(),
1432                _ => return Err(RuntimeError::new("env::var expects a string")),
1433            };
1434            match std::env::var(&var_name) {
1435                Ok(value) => Ok(Value::Variant {
1436                    enum_name: "Result".to_string(),
1437                    variant_name: "Ok".to_string(),
1438                    fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
1439                }),
1440                Err(_) => Ok(Value::Variant {
1441                    enum_name: "Result".to_string(),
1442                    variant_name: "Err".to_string(),
1443                    fields: Some(Rc::new(vec![Value::String(Rc::new(
1444                        "Environment variable not found".to_string(),
1445                    ))])),
1446                }),
1447            }
1448        });
1449
1450        // std::env::args - get command line arguments
1451        // This is a special function that returns an iterator/array of strings
1452        self.define_builtin("std·env·args", Some(0), |interp, _| {
1453            let args = interp.get_program_args();
1454            let arg_values: Vec<Value> = args
1455                .iter()
1456                .map(|s| Value::String(Rc::new(s.clone())))
1457                .collect();
1458            Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
1459        });
1460
1461        // env::args - alias without std prefix
1462        self.define_builtin("env·args", Some(0), |interp, _| {
1463            let args = interp.get_program_args();
1464            let arg_values: Vec<Value> = args
1465                .iter()
1466                .map(|s| Value::String(Rc::new(s.clone())))
1467                .collect();
1468            Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
1469        });
1470
1471        // ============================================================
1472        // Filesystem built-ins for scanner (underscore naming)
1473        // ============================================================
1474
1475        // fs_read - read entire file as string
1476        self.define_builtin("fs_read", Some(1), |_, args| {
1477            let path = match &args[0] {
1478                Value::String(s) => s.to_string(),
1479                _ => return Err(RuntimeError::new("fs_read requires a string path")),
1480            };
1481            match std::fs::read_to_string(&path) {
1482                Ok(content) => Ok(Value::String(Rc::new(content))),
1483                Err(e) => {
1484                    crate::sigil_debug!("DEBUG fs_read error for '{}': {}", path, e);
1485                    Ok(Value::Null)
1486                }
1487            }
1488        });
1489
1490        // fs_list - list directory contents as array of strings
1491        self.define_builtin("fs_list", Some(1), |_, args| {
1492            let path = match &args[0] {
1493                Value::String(s) => s.to_string(),
1494                _ => return Err(RuntimeError::new("fs_list requires a string path")),
1495            };
1496            match std::fs::read_dir(&path) {
1497                Ok(entries) => {
1498                    let files: Vec<Value> = entries
1499                        .filter_map(|e| e.ok())
1500                        .map(|e| {
1501                            Value::String(Rc::new(e.file_name().to_string_lossy().to_string()))
1502                        })
1503                        .collect();
1504                    Ok(Value::Array(Rc::new(RefCell::new(files))))
1505                }
1506                Err(e) => {
1507                    crate::sigil_debug!("DEBUG fs_list error for '{}': {}", path, e);
1508                    Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))))
1509                }
1510            }
1511        });
1512
1513        // fs_is_dir - check if path is a directory
1514        self.define_builtin("fs_is_dir", Some(1), |_, args| {
1515            let path = match &args[0] {
1516                Value::String(s) => s.to_string(),
1517                _ => return Err(RuntimeError::new("fs_is_dir requires a string path")),
1518            };
1519            Ok(Value::Bool(std::path::Path::new(&path).is_dir()))
1520        });
1521
1522        // fs_is_file - check if path is a file
1523        self.define_builtin("fs_is_file", Some(1), |_, args| {
1524            let path = match &args[0] {
1525                Value::String(s) => s.to_string(),
1526                _ => return Err(RuntimeError::new("fs_is_file requires a string path")),
1527            };
1528            Ok(Value::Bool(std::path::Path::new(&path).is_file()))
1529        });
1530
1531        // fs_exists - check if path exists
1532        self.define_builtin("fs_exists", Some(1), |_, args| {
1533            let path = match &args[0] {
1534                Value::String(s) => s.to_string(),
1535                _ => return Err(RuntimeError::new("fs_exists requires a string path")),
1536            };
1537            Ok(Value::Bool(std::path::Path::new(&path).exists()))
1538        });
1539
1540        // path_extension - get file extension
1541        self.define_builtin("path_extension", Some(1), |_, args| {
1542            let path = match &args[0] {
1543                Value::String(s) => s.to_string(),
1544                _ => return Err(RuntimeError::new("path_extension requires a string path")),
1545            };
1546            let ext = std::path::Path::new(&path)
1547                .extension()
1548                .and_then(|e| e.to_str())
1549                .map(|s| s.to_string());
1550            match ext {
1551                Some(e) => Ok(Value::String(Rc::new(e))),
1552                None => Ok(Value::Null),
1553            }
1554        });
1555
1556        // path_join - join path components
1557        self.define_builtin("path_join", Some(2), |_, args| {
1558            let base = match &args[0] {
1559                Value::String(s) => s.to_string(),
1560                _ => return Err(RuntimeError::new("path_join requires string paths")),
1561            };
1562            let part = match &args[1] {
1563                Value::String(s) => s.to_string(),
1564                _ => return Err(RuntimeError::new("path_join requires string paths")),
1565            };
1566            let joined = std::path::Path::new(&base).join(&part);
1567            Ok(Value::String(Rc::new(joined.to_string_lossy().to_string())))
1568        });
1569
1570        // path_parent - get parent directory
1571        self.define_builtin("path_parent", Some(1), |_, args| {
1572            let path = match &args[0] {
1573                Value::String(s) => s.to_string(),
1574                _ => return Err(RuntimeError::new("path_parent requires a string path")),
1575            };
1576            match std::path::Path::new(&path).parent() {
1577                Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
1578                None => Ok(Value::Null),
1579            }
1580        });
1581
1582        // path_file_name - get file name without directory
1583        self.define_builtin("path_file_name", Some(1), |_, args| {
1584            let path = match &args[0] {
1585                Value::String(s) => s.to_string(),
1586                _ => return Err(RuntimeError::new("path_file_name requires a string path")),
1587            };
1588            match std::path::Path::new(&path).file_name() {
1589                Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
1590                None => Ok(Value::Null),
1591            }
1592        });
1593
1594        // ============================================================
1595        // Tree-sitter parsing built-ins
1596        // ============================================================
1597
1598        // TreeSitterParser::new - create a tree-sitter parser for a language
1599        self.define_builtin("TreeSitterParser·new", Some(1), |_, args| {
1600            use crate::tree_sitter_support::{TSLanguage, TSParser};
1601
1602            // Get the language from the argument
1603            let lang_str = match &args[0] {
1604                Value::String(s) => s.to_string(),
1605                Value::Variant {
1606                    enum_name,
1607                    variant_name,
1608                    ..
1609                } => {
1610                    // Handle Language::Rust style enums
1611                    format!("{}::{}", enum_name, variant_name)
1612                }
1613                other => format!("{:?}", other),
1614            };
1615
1616            // Try to create the parser
1617            let language = match TSLanguage::from_str(&lang_str) {
1618                Some(lang) => lang,
1619                None => {
1620                    return Ok(Value::Variant {
1621                        enum_name: "Result".to_string(),
1622                        variant_name: "Err".to_string(),
1623                        fields: Some(Rc::new(vec![Value::Struct {
1624                            name: "ParseError".to_string(),
1625                            fields: Rc::new(RefCell::new({
1626                                let mut f = HashMap::new();
1627                                f.insert(
1628                                    "kind".to_string(),
1629                                    Value::String(Rc::new("ParserNotFound".to_string())),
1630                                );
1631                                f.insert(
1632                                    "message".to_string(),
1633                                    Value::String(Rc::new(format!(
1634                                        "Unsupported language: {}",
1635                                        lang_str
1636                                    ))),
1637                                );
1638                                f
1639                            })),
1640                        }])),
1641                    });
1642                }
1643            };
1644
1645            // Create the parser and store the language
1646            match TSParser::new(language) {
1647                Ok(_) => {
1648                    // Return a TreeSitterParser struct
1649                    let mut fields = HashMap::new();
1650                    fields.insert("language".to_string(), Value::String(Rc::new(lang_str)));
1651                    fields.insert(
1652                        "_ts_language".to_string(),
1653                        Value::String(Rc::new(format!("{:?}", language))),
1654                    );
1655
1656                    Ok(Value::Variant {
1657                        enum_name: "Result".to_string(),
1658                        variant_name: "Ok".to_string(),
1659                        fields: Some(Rc::new(vec![Value::Struct {
1660                            name: "TreeSitterParser".to_string(),
1661                            fields: Rc::new(RefCell::new(fields)),
1662                        }])),
1663                    })
1664                }
1665                Err(e) => Ok(Value::Variant {
1666                    enum_name: "Result".to_string(),
1667                    variant_name: "Err".to_string(),
1668                    fields: Some(Rc::new(vec![Value::Struct {
1669                        name: "ParseError".to_string(),
1670                        fields: Rc::new(RefCell::new({
1671                            let mut f = HashMap::new();
1672                            f.insert(
1673                                "kind".to_string(),
1674                                Value::String(Rc::new("ParserNotFound".to_string())),
1675                            );
1676                            f.insert("message".to_string(), Value::String(Rc::new(e)));
1677                            f
1678                        })),
1679                    }])),
1680                }),
1681            }
1682        });
1683
1684        // tree_sitter_parse - parse source code with tree-sitter
1685        self.define_builtin("tree_sitter_parse", Some(2), |_, args| {
1686            use crate::tree_sitter_support::{node_to_value, parse_source};
1687
1688            // First arg is the language string, second is the source code
1689            let lang_str = match &args[0] {
1690                Value::String(s) => s.to_string(),
1691                Value::Variant {
1692                    enum_name,
1693                    variant_name,
1694                    ..
1695                } => {
1696                    format!("{}::{}", enum_name, variant_name)
1697                }
1698                other => format!("{:?}", other),
1699            };
1700
1701            let source = match &args[1] {
1702                Value::String(s) => s.to_string(),
1703                _ => {
1704                    return Err(RuntimeError::new(
1705                        "tree_sitter_parse expects source code string as second argument",
1706                    ))
1707                }
1708            };
1709
1710            // Parse the source
1711            match parse_source(&lang_str, &source) {
1712                Ok(tree) => {
1713                    // Convert to SyntaxNode value
1714                    let root = tree.root_node();
1715                    let root_fields = node_to_value(&root);
1716
1717                    // Create TSTree struct
1718                    let mut tree_fields = HashMap::new();
1719                    tree_fields.insert(
1720                        "root".to_string(),
1721                        Value::Struct {
1722                            name: "SyntaxNode".to_string(),
1723                            fields: Rc::new(RefCell::new(root_fields)),
1724                        },
1725                    );
1726                    tree_fields.insert("source".to_string(), Value::String(Rc::new(source)));
1727
1728                    Ok(Value::Variant {
1729                        enum_name: "Result".to_string(),
1730                        variant_name: "Ok".to_string(),
1731                        fields: Some(Rc::new(vec![Value::Struct {
1732                            name: "TSTree".to_string(),
1733                            fields: Rc::new(RefCell::new(tree_fields)),
1734                        }])),
1735                    })
1736                }
1737                Err(e) => Ok(Value::Variant {
1738                    enum_name: "Result".to_string(),
1739                    variant_name: "Err".to_string(),
1740                    fields: Some(Rc::new(vec![Value::Struct {
1741                        name: "ParseError".to_string(),
1742                        fields: Rc::new(RefCell::new({
1743                            let mut f = HashMap::new();
1744                            f.insert(
1745                                "kind".to_string(),
1746                                Value::String(Rc::new("SyntaxError".to_string())),
1747                            );
1748                            f.insert("message".to_string(), Value::String(Rc::new(e)));
1749                            f
1750                        })),
1751                    }])),
1752                }),
1753            }
1754        });
1755
1756        // tree_sitter_supported_languages - get list of supported languages
1757        self.define_builtin("tree_sitter_supported_languages", Some(0), |_, _| {
1758            use crate::tree_sitter_support::supported_languages;
1759
1760            let languages: Vec<Value> = supported_languages()
1761                .iter()
1762                .map(|s| Value::String(Rc::new(s.to_string())))
1763                .collect();
1764
1765            Ok(Value::Array(Rc::new(RefCell::new(languages))))
1766        });
1767
1768        // tree_sitter_node_text - extract text from a syntax node using the source
1769        self.define_builtin("tree_sitter_node_text", Some(2), |_, args| {
1770            // First arg is the node (with start_byte and end_byte), second is the source
1771            let (start_byte, end_byte) = match &args[0] {
1772                Value::Struct { fields, .. } => {
1773                    let fields = fields.borrow();
1774                    let start = match fields.get("start_byte") {
1775                        Some(Value::Int(n)) => *n as usize,
1776                        _ => return Err(RuntimeError::new("Node missing start_byte field")),
1777                    };
1778                    let end = match fields.get("end_byte") {
1779                        Some(Value::Int(n)) => *n as usize,
1780                        _ => return Err(RuntimeError::new("Node missing end_byte field")),
1781                    };
1782                    (start, end)
1783                }
1784                _ => {
1785                    return Err(RuntimeError::new(
1786                        "tree_sitter_node_text expects a SyntaxNode struct",
1787                    ))
1788                }
1789            };
1790
1791            let source = match &args[1] {
1792                Value::String(s) => s.to_string(),
1793                _ => {
1794                    return Err(RuntimeError::new(
1795                        "tree_sitter_node_text expects source string as second argument",
1796                    ))
1797                }
1798            };
1799
1800            if end_byte <= source.len() && start_byte <= end_byte {
1801                Ok(Value::String(Rc::new(
1802                    source[start_byte..end_byte].to_string(),
1803                )))
1804            } else {
1805                Err(RuntimeError::new("Byte range out of bounds"))
1806            }
1807        });
1808
1809        // Rc::new(value) - Reference counted smart pointer (simplified)
1810        let rc_new = Value::BuiltIn(Rc::new(BuiltInFn {
1811            name: "Rc·new".to_string(),
1812            arity: Some(1),
1813            func: |_, args| {
1814                let mut fields = HashMap::new();
1815                fields.insert("_value".to_string(), args[0].clone());
1816                Ok(Value::Struct {
1817                    name: "Rc".to_string(),
1818                    fields: std::rc::Rc::new(RefCell::new(fields)),
1819                })
1820            },
1821        }));
1822        self.globals
1823            .borrow_mut()
1824            .define("Rc·new".to_string(), rc_new);
1825
1826        // Cell::new(value) - Interior mutability
1827        let cell_new = Value::BuiltIn(Rc::new(BuiltInFn {
1828            name: "Cell·new".to_string(),
1829            arity: Some(1),
1830            func: |_, args| {
1831                let mut fields = HashMap::new();
1832                fields.insert("_value".to_string(), args[0].clone());
1833                Ok(Value::Struct {
1834                    name: "Cell".to_string(),
1835                    fields: std::rc::Rc::new(RefCell::new(fields)),
1836                })
1837            },
1838        }));
1839        self.globals
1840            .borrow_mut()
1841            .define("Cell·new".to_string(), cell_new);
1842    }
1843
1844    fn define_builtin(
1845        &mut self,
1846        name: &str,
1847        arity: Option<usize>,
1848        func: fn(&mut Interpreter, Vec<Value>) -> Result<Value, RuntimeError>,
1849    ) {
1850        let builtin = Value::BuiltIn(Rc::new(BuiltInFn {
1851            name: name.to_string(),
1852            arity,
1853            func,
1854        }));
1855        self.globals.borrow_mut().define(name.to_string(), builtin);
1856    }
1857
1858    /// Execute a source file
1859    pub fn execute(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
1860        let mut result = Value::Null;
1861
1862        for item in &file.items {
1863            result = self.execute_item(&item.node)?;
1864        }
1865
1866        // Look for main function and execute it (only if it takes no args)
1867        let main_fn = self.globals.borrow().get("main").and_then(|v| {
1868            if let Value::Function(f) = v {
1869                Some(f.clone())
1870            } else {
1871                None
1872            }
1873        });
1874        if let Some(f) = main_fn {
1875            // Only auto-call main if it takes no arguments
1876            // If main expects args, caller should call it explicitly via call_function_by_name
1877            if f.params.is_empty() {
1878                result = self.call_function(&f, vec![])?;
1879            }
1880        }
1881
1882        Ok(result)
1883    }
1884
1885    /// Execute a file but only register definitions, don't auto-call main.
1886    /// Use this when loading files as part of a multi-file workspace.
1887    pub fn execute_definitions(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
1888        let mut result = Value::Null;
1889
1890        for item in &file.items {
1891            result = self.execute_item(&item.node)?;
1892        }
1893
1894        Ok(result)
1895    }
1896
1897    fn execute_item(&mut self, item: &Item) -> Result<Value, RuntimeError> {
1898        match item {
1899            Item::Function(func) => {
1900                let fn_value = self.create_function(func)?;
1901                let fn_name = func.name.name.clone();
1902
1903                // Register with both simple name and module-qualified name
1904                self.globals
1905                    .borrow_mut()
1906                    .define(fn_name.clone(), fn_value.clone());
1907
1908                // Also register with module prefix if we're in a module context
1909                if let Some(ref module) = self.current_module {
1910                    let qualified_name = format!("{}·{}", module, fn_name);
1911                    self.globals.borrow_mut().define(qualified_name, fn_value);
1912                }
1913
1914                Ok(Value::Null)
1915            }
1916            Item::Struct(s) => {
1917                // Register with simple name
1918                self.types
1919                    .insert(s.name.name.clone(), TypeDef::Struct(s.clone()));
1920
1921                // Also register with module-qualified name if in a module context
1922                if let Some(ref module) = self.current_module {
1923                    let qualified_name = format!("{}·{}", module, s.name.name);
1924                    self.types
1925                        .insert(qualified_name, TypeDef::Struct(s.clone()));
1926                }
1927
1928                // For unit structs, register the struct name as a value (zero-sized type)
1929                if matches!(&s.fields, crate::ast::StructFields::Unit) {
1930                    let unit_value = Value::Struct {
1931                        name: s.name.name.clone(),
1932                        fields: Rc::new(RefCell::new(HashMap::new())),
1933                    };
1934                    self.globals
1935                        .borrow_mut()
1936                        .define(s.name.name.clone(), unit_value.clone());
1937
1938                    // Also register with module-qualified name
1939                    if let Some(ref module) = self.current_module {
1940                        let qualified_name = format!("{}·{}", module, s.name.name);
1941                        self.globals.borrow_mut().define(qualified_name, unit_value);
1942                    }
1943                }
1944
1945                // Check for #[derive(Default)] attribute and store for later lookup
1946                let has_default = s
1947                    .attrs
1948                    .derives
1949                    .iter()
1950                    .any(|d| matches!(d, DeriveTrait::Default));
1951                if has_default {
1952                    self.default_structs.insert(s.name.name.clone(), s.clone());
1953                    if let Some(ref module) = self.current_module {
1954                        let qualified_name = format!("{}·{}", module, s.name.name);
1955                        self.default_structs.insert(qualified_name, s.clone());
1956                    }
1957                }
1958
1959                Ok(Value::Null)
1960            }
1961            Item::Enum(e) => {
1962                // Register with simple name
1963                self.types
1964                    .insert(e.name.name.clone(), TypeDef::Enum(e.clone()));
1965
1966                // Also register with module-qualified name
1967                if let Some(ref module) = self.current_module {
1968                    let qualified_name = format!("{}·{}", module, e.name.name);
1969                    self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
1970                }
1971
1972                // Register variant constructors as EnumName·VariantName
1973                // Store them in a lookup table that the variant_constructor builtin can use
1974                let enum_name = e.name.name.clone();
1975                for variant in &e.variants {
1976                    let variant_name = variant.name.name.clone();
1977                    let qualified_name = format!("{}·{}", enum_name, variant_name);
1978
1979                    let arity = match &variant.fields {
1980                        crate::ast::StructFields::Unit => 0,
1981                        crate::ast::StructFields::Tuple(types) => types.len(),
1982                        crate::ast::StructFields::Named(fields) => fields.len(),
1983                    };
1984
1985                    // Store variant info for later lookup
1986                    self.variant_constructors.insert(
1987                        qualified_name.clone(),
1988                        (enum_name.clone(), variant_name.clone(), arity),
1989                    );
1990                }
1991                Ok(Value::Null)
1992            }
1993            Item::Const(c) => {
1994                let value = self.evaluate(&c.value)?;
1995                self.globals.borrow_mut().define(c.name.name.clone(), value);
1996                Ok(Value::Null)
1997            }
1998            Item::Static(s) => {
1999                let value = self.evaluate(&s.value)?;
2000                self.globals.borrow_mut().define(s.name.name.clone(), value);
2001                Ok(Value::Null)
2002            }
2003            Item::ExternBlock(extern_block) => {
2004                // Register extern functions as builtins
2005                for item in &extern_block.items {
2006                    if let ExternItem::Function(func) = item {
2007                        let name = func.name.name.clone();
2008                        // Register emulated FFI functions
2009                        match name.as_str() {
2010                            "sigil_read_file" => {
2011                                self.define_builtin("sigil_read_file", Some(2), |_, args| {
2012                                    // args[0] = path pointer (we'll use string), args[1] = len
2013                                    let path = match &args[0] {
2014                                        Value::String(s) => (**s).clone(),
2015                                        _ => {
2016                                            return Err(RuntimeError::new(
2017                                                "sigil_read_file expects string path",
2018                                            ))
2019                                        }
2020                                    };
2021                                    match std::fs::read_to_string(&path) {
2022                                        Ok(content) => {
2023                                            // Store content in a global for sigil_file_len to access
2024                                            Ok(Value::String(Rc::new(content)))
2025                                        }
2026                                        Err(_) => Ok(Value::Null),
2027                                    }
2028                                });
2029                            }
2030                            "sigil_file_len" => {
2031                                self.define_builtin("sigil_file_len", Some(0), |_, _| {
2032                                    // This is a placeholder - in real usage, would track last read
2033                                    Ok(Value::Int(0))
2034                                });
2035                            }
2036                            "sigil_write_file" => {
2037                                self.define_builtin("sigil_write_file", Some(4), |_, args| {
2038                                    let path = match &args[0] {
2039                                        Value::String(s) => (**s).clone(),
2040                                        _ => {
2041                                            return Err(RuntimeError::new(
2042                                                "sigil_write_file expects string path",
2043                                            ))
2044                                        }
2045                                    };
2046                                    let content = match &args[2] {
2047                                        Value::String(s) => (**s).clone(),
2048                                        _ => {
2049                                            return Err(RuntimeError::new(
2050                                                "sigil_write_file expects string content",
2051                                            ))
2052                                        }
2053                                    };
2054                                    match std::fs::write(&path, &content) {
2055                                        Ok(_) => Ok(Value::Bool(true)),
2056                                        Err(_) => Ok(Value::Bool(false)),
2057                                    }
2058                                });
2059                            }
2060                            "write" => {
2061                                self.define_builtin("write", Some(3), |_, args| {
2062                                    // write(fd, buf, count)
2063                                    let fd = match &args[0] {
2064                                        Value::Int(n) => *n,
2065                                        _ => 1,
2066                                    };
2067                                    let content = match &args[1] {
2068                                        Value::String(s) => (**s).clone(),
2069                                        _ => format!("{}", args[1]),
2070                                    };
2071                                    if fd == 1 {
2072                                        print!("{}", content);
2073                                    } else if fd == 2 {
2074                                        eprint!("{}", content);
2075                                    }
2076                                    Ok(Value::Int(content.len() as i64))
2077                                });
2078                            }
2079                            _ => {
2080                                // Unknown extern function - register a no-op
2081                            }
2082                        }
2083                    }
2084                }
2085                Ok(Value::Null)
2086            }
2087            Item::Impl(impl_block) => {
2088                // Extract type name from self_ty
2089                let type_name = match &impl_block.self_ty {
2090                    TypeExpr::Path(path) => path
2091                        .segments
2092                        .iter()
2093                        .map(|s| s.ident.name.as_str())
2094                        .collect::<Vec<_>>()
2095                        .join("::"),
2096                    _ => return Ok(Value::Null), // Can't handle complex types
2097                };
2098
2099                // Check if this is `impl Drop for X` - register for automatic drop calls
2100                if let Some(trait_path) = &impl_block.trait_ {
2101                    let trait_name = trait_path
2102                        .segments
2103                        .iter()
2104                        .map(|s| s.ident.name.as_str())
2105                        .collect::<Vec<_>>()
2106                        .join("::");
2107                    if trait_name == "Drop" {
2108                        self.drop_types.insert(type_name.clone());
2109                    }
2110                }
2111
2112                // Register each method with qualified name TypeName·method
2113                for impl_item in &impl_block.items {
2114                    if let ImplItem::Function(func) = impl_item {
2115                        let fn_value = self.create_function(func)?;
2116                        let qualified_name = format!("{}·{}", type_name, func.name.name);
2117                        // Debug: track Lexer method registration
2118                        if type_name == "Lexer" && func.name.name.contains("keyword") {
2119                            crate::sigil_debug!("DEBUG registering: {}", qualified_name);
2120                        }
2121                        self.globals
2122                            .borrow_mut()
2123                            .define(qualified_name.clone(), fn_value.clone());
2124
2125                        // Also register with module prefix if in a module context
2126                        if let Some(ref module) = self.current_module {
2127                            let fully_qualified = format!("{}·{}", module, qualified_name);
2128                            self.globals.borrow_mut().define(fully_qualified, fn_value);
2129                        }
2130                    }
2131                }
2132                Ok(Value::Null)
2133            }
2134            Item::Module(module) => {
2135                // Handle module definitions
2136                let module_name = &module.name.name;
2137
2138                if let Some(items) = &module.items {
2139                    // Inline module: mod foo { ... }
2140                    // Register items with qualified names: module_name·item_name
2141                    for item in items {
2142                        match &item.node {
2143                            Item::Const(c) => {
2144                                let value = self.evaluate(&c.value)?;
2145                                let qualified_name = format!("{}·{}", module_name, c.name.name);
2146                                self.globals.borrow_mut().define(qualified_name, value);
2147                            }
2148                            Item::Static(s) => {
2149                                let value = self.evaluate(&s.value)?;
2150                                let qualified_name = format!("{}·{}", module_name, s.name.name);
2151                                self.globals.borrow_mut().define(qualified_name, value);
2152                            }
2153                            Item::Function(func) => {
2154                                let fn_value = self.create_function(func)?;
2155                                let qualified_name = format!("{}·{}", module_name, func.name.name);
2156                                self.globals.borrow_mut().define(qualified_name, fn_value);
2157                            }
2158                            Item::Struct(s) => {
2159                                let qualified_name = format!("{}·{}", module_name, s.name.name);
2160                                self.types
2161                                    .insert(qualified_name, TypeDef::Struct(s.clone()));
2162                            }
2163                            Item::Enum(e) => {
2164                                let qualified_name = format!("{}·{}", module_name, e.name.name);
2165                                self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
2166                            }
2167                            _ => {} // Skip other nested items for now
2168                        }
2169                    }
2170                } else {
2171                    // External module: mod foo; - try to load foo.sigil from same directory
2172                    if let Some(ref source_dir) = self.current_source_dir {
2173                        let module_path =
2174                            std::path::Path::new(source_dir).join(format!("{}.sigil", module_name));
2175
2176                        if module_path.exists() {
2177                            crate::sigil_debug!(
2178                                "DEBUG Loading external module: {}",
2179                                module_path.display()
2180                            );
2181
2182                            match std::fs::read_to_string(&module_path) {
2183                                Ok(source) => {
2184                                    // Parse the module file
2185                                    let mut parser = crate::Parser::new(&source);
2186                                    match parser.parse_file() {
2187                                        Ok(parsed_file) => {
2188                                            // Save current module context
2189                                            let prev_module = self.current_module.clone();
2190
2191                                            // Set module context for registering definitions
2192                                            self.current_module = Some(module_name.clone());
2193
2194                                            // Execute module definitions
2195                                            for item in &parsed_file.items {
2196                                                if let Err(e) = self.execute_item(&item.node) {
2197                                                    crate::sigil_warn!(
2198                                                        "Warning: error in module {}: {}",
2199                                                        module_name,
2200                                                        e
2201                                                    );
2202                                                }
2203                                            }
2204
2205                                            // Restore previous module context
2206                                            self.current_module = prev_module;
2207                                        }
2208                                        Err(e) => {
2209                                            crate::sigil_warn!(
2210                                                "Warning: failed to parse module {}: {:?}",
2211                                                module_name,
2212                                                e
2213                                            );
2214                                        }
2215                                    }
2216                                }
2217                                Err(e) => {
2218                                    crate::sigil_warn!(
2219                                        "Warning: failed to read module file {}: {}",
2220                                        module_path.display(),
2221                                        e
2222                                    );
2223                                }
2224                            }
2225                        } else {
2226                            crate::sigil_debug!(
2227                                "DEBUG Module file not found: {} (source_dir={})",
2228                                module_path.display(),
2229                                source_dir
2230                            );
2231                        }
2232                    } else {
2233                        crate::sigil_debug!(
2234                            "DEBUG No source_dir set, cannot load external module: {}",
2235                            module_name
2236                        );
2237                    }
2238                }
2239                Ok(Value::Null)
2240            }
2241            Item::Use(use_decl) => {
2242                // Process use declarations to create type/function aliases
2243                self.process_use_tree(&use_decl.tree, &[])?;
2244                Ok(Value::Null)
2245            }
2246            _ => Ok(Value::Null), // Skip other items for now
2247        }
2248    }
2249
2250    /// Process a use tree to create type and function aliases
2251    fn process_use_tree(
2252        &mut self,
2253        tree: &crate::ast::UseTree,
2254        prefix: &[String],
2255    ) -> Result<(), RuntimeError> {
2256        use crate::ast::UseTree;
2257        match tree {
2258            UseTree::Path {
2259                prefix: path_prefix,
2260                suffix,
2261            } => {
2262                // Build path: prefix + this segment
2263                let mut new_prefix = prefix.to_vec();
2264                new_prefix.push(path_prefix.name.clone());
2265                self.process_use_tree(suffix, &new_prefix)
2266            }
2267            UseTree::Name(name) => {
2268                // use foo::bar::Baz -> import Baz from foo·bar·Baz
2269                let mut path = prefix.to_vec();
2270                path.push(name.name.clone());
2271                let qualified = path.join("·");
2272                let simple_name = name.name.clone();
2273
2274                // If the type/function isn't found, try loading the crate first
2275                // The crate name is the first segment of the path
2276                if !prefix.is_empty() {
2277                    let crate_name = &prefix[0];
2278                    if !self.types.contains_key(&qualified)
2279                        && self.globals.borrow().get(&qualified).is_none()
2280                        && !self.loaded_crates.contains(crate_name)
2281                    {
2282                        // Try to load the crate
2283                        if let Err(e) = self.load_crate(crate_name) {
2284                            crate::sigil_debug!(
2285                                "DEBUG process_use_tree: failed to load crate '{}': {}",
2286                                crate_name,
2287                                e
2288                            );
2289                        }
2290                    }
2291                }
2292
2293                // Create alias: simple_name -> qualified
2294                // For types: if foo·bar·Baz exists in types, also register as Baz
2295                if let Some(type_def) = self.types.get(&qualified).cloned() {
2296                    self.types.insert(simple_name.clone(), type_def);
2297                }
2298                // For functions: if foo·bar·Baz exists in globals, also register as Baz
2299                let func = self.globals.borrow().get(&qualified).map(|v| v.clone());
2300                if let Some(val) = func {
2301                    self.globals.borrow_mut().define(simple_name.clone(), val);
2302                }
2303
2304                // Also import impl methods for this type
2305                // e.g., when importing samael_analysis::AnalysisConfig,
2306                // also import samael_analysis·AnalysisConfig·default as AnalysisConfig·default
2307                let method_prefix = format!("{}·", qualified);
2308                let matching_methods: Vec<(String, Value)> = {
2309                    let globals = self.globals.borrow();
2310                    globals
2311                        .values
2312                        .iter()
2313                        .filter(|(k, _)| k.starts_with(&method_prefix))
2314                        .map(|(k, v)| {
2315                            // samael_analysis·AnalysisConfig·default -> AnalysisConfig·default
2316                            let method_suffix = k.strip_prefix(&method_prefix).unwrap();
2317                            let new_name = format!("{}·{}", simple_name, method_suffix);
2318                            (new_name, v.clone())
2319                        })
2320                        .collect()
2321                };
2322                for (name, val) in matching_methods {
2323                    self.globals.borrow_mut().define(name, val);
2324                }
2325                Ok(())
2326            }
2327            UseTree::Rename { name, alias } => {
2328                // use foo::bar::Baz as Qux
2329                let mut path = prefix.to_vec();
2330                path.push(name.name.clone());
2331                let qualified = path.join("·");
2332                let alias_name = alias.name.clone();
2333
2334                if let Some(type_def) = self.types.get(&qualified).cloned() {
2335                    self.types.insert(alias_name.clone(), type_def);
2336                }
2337                let func = self.globals.borrow().get(&qualified).map(|v| v.clone());
2338                if let Some(val) = func {
2339                    self.globals.borrow_mut().define(alias_name, val);
2340                }
2341                Ok(())
2342            }
2343            UseTree::Glob => {
2344                // use foo::bar::* - import all from foo·bar
2345                let path_prefix = prefix.join("·");
2346                // Find all types starting with this prefix
2347                let matching_types: Vec<(String, TypeDef)> = self
2348                    .types
2349                    .iter()
2350                    .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
2351                    .map(|(k, v)| {
2352                        let suffix = k
2353                            .strip_prefix(&path_prefix)
2354                            .unwrap()
2355                            .trim_start_matches('·');
2356                        (suffix.to_string(), v.clone())
2357                    })
2358                    .filter(|(k, _)| !k.contains('·')) // Only immediate children
2359                    .collect();
2360                for (name, def) in matching_types {
2361                    self.types.insert(name, def);
2362                }
2363                // Similar for functions
2364                let matching_funcs: Vec<(String, Value)> = {
2365                    let globals = self.globals.borrow();
2366                    globals
2367                        .values
2368                        .iter()
2369                        .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
2370                        .map(|(k, v)| {
2371                            let suffix = k
2372                                .strip_prefix(&path_prefix)
2373                                .unwrap()
2374                                .trim_start_matches('·');
2375                            (suffix.to_string(), v.clone())
2376                        })
2377                        .filter(|(k, _)| !k.contains('·'))
2378                        .collect()
2379                };
2380                for (name, val) in matching_funcs {
2381                    self.globals.borrow_mut().define(name, val);
2382                }
2383                Ok(())
2384            }
2385            UseTree::Group(trees) => {
2386                // use foo::{Bar, Baz}
2387                for tree in trees {
2388                    self.process_use_tree(tree, prefix)?;
2389                }
2390                Ok(())
2391            }
2392        }
2393    }
2394
2395    fn create_function(&self, func: &crate::ast::Function) -> Result<Value, RuntimeError> {
2396        let params: Vec<String> = func
2397            .params
2398            .iter()
2399            .map(|p| Self::extract_param_name(&p.pattern))
2400            .collect();
2401
2402        let body = func
2403            .body
2404            .as_ref()
2405            .map(|b| Expr::Block(b.clone()))
2406            .unwrap_or(Expr::Literal(Literal::Bool(false)));
2407
2408        Ok(Value::Function(Rc::new(Function {
2409            name: Some(func.name.name.clone()),
2410            params,
2411            body,
2412            closure: self.environment.clone(),
2413        })))
2414    }
2415
2416    /// Extract parameter name from a pattern, handling &self, mut self, etc.
2417    fn extract_param_name(pattern: &Pattern) -> String {
2418        match pattern {
2419            Pattern::Ident { name, .. } => name.name.clone(),
2420            // Handle &self and &mut self
2421            Pattern::Ref { pattern: inner, .. } => Self::extract_param_name(inner),
2422            // Handle ref self
2423            Pattern::RefBinding { name, .. } => name.name.clone(),
2424            _ => "_".to_string(),
2425        }
2426    }
2427
2428    /// Evaluate an expression
2429    pub fn evaluate(&mut self, expr: &Expr) -> Result<Value, RuntimeError> {
2430        match expr {
2431            Expr::Literal(lit) => self.eval_literal(lit),
2432            Expr::Path(path) => self.eval_path(path),
2433            Expr::Binary { left, op, right } => self.eval_binary(left, op, right),
2434            Expr::Unary { op, expr } => self.eval_unary(op, expr),
2435            Expr::Call { func, args } => self.eval_call(func, args),
2436            Expr::Array(elements) => self.eval_array(elements),
2437            Expr::Tuple(elements) => self.eval_tuple(elements),
2438            Expr::Block(block) => self.eval_block(block),
2439            Expr::If {
2440                condition,
2441                then_branch,
2442                else_branch,
2443            } => self.eval_if(condition, then_branch, else_branch),
2444            Expr::Match { expr, arms } => self.eval_match(expr, arms),
2445            Expr::For {
2446                pattern,
2447                iter,
2448                body,
2449                ..
2450            } => self.eval_for(pattern, iter, body),
2451            Expr::While {
2452                condition, body, ..
2453            } => self.eval_while(condition, body),
2454            Expr::Loop { body, .. } => self.eval_loop(body),
2455            Expr::Return(value) => self.eval_return(value),
2456            Expr::Break { value, .. } => self.eval_break(value),
2457            Expr::Continue { .. } => Err(RuntimeError::new("continue")),
2458            Expr::Index { expr, index } => self.eval_index(expr, index),
2459            Expr::Field { expr, field } => self.eval_field(expr, field),
2460            Expr::MethodCall {
2461                receiver,
2462                method,
2463                args,
2464                ..
2465            } => self.eval_method_call(receiver, method, args),
2466            // Polysynthetic incorporation: path·file·read·string
2467            // Each segment is a method/function that transforms the value
2468            Expr::Incorporation { segments } => self.eval_incorporation(segments),
2469            Expr::Pipe { expr, operations } => self.eval_pipe(expr, operations),
2470            Expr::Closure { params, body, .. } => self.eval_closure(params, body),
2471            Expr::Struct { path, fields, rest } => self.eval_struct_literal(path, fields, rest),
2472            Expr::Evidential {
2473                expr,
2474                evidentiality,
2475            } => self.eval_evidential(expr, evidentiality),
2476            Expr::Range {
2477                start,
2478                end,
2479                inclusive,
2480            } => {
2481                crate::sigil_debug!("DEBUG evaluate: Expr::Range being evaluated standalone");
2482                self.eval_range(start, end, *inclusive)
2483            }
2484            Expr::Assign { target, value } => self.eval_assign(target, value),
2485            Expr::Let { pattern, value } => {
2486                // Let expression (for if-let, while-let patterns)
2487                // Evaluate the value and check if pattern matches
2488                let val = self.evaluate(value)?;
2489                // Check if pattern matches - return true/false for if-let semantics
2490                if self.pattern_matches(pattern, &val)? {
2491                    // Pattern matches - bind variables and return true
2492                    self.bind_pattern(pattern, val)?;
2493                    Ok(Value::Bool(true))
2494                } else {
2495                    // Pattern doesn't match - return false without binding
2496                    Ok(Value::Bool(false))
2497                }
2498            }
2499            Expr::Await {
2500                expr: inner,
2501                evidentiality,
2502            } => {
2503                let value = self.evaluate(inner)?;
2504                let awaited = self.await_value(value)?;
2505                // Handle evidentiality marker semantics
2506                match evidentiality {
2507                    Some(Evidentiality::Uncertain) => {
2508                        // ⌛? - propagate error like Try
2509                        self.unwrap_result_or_option(awaited, true, false)
2510                    }
2511                    Some(Evidentiality::Known) => {
2512                        // ⌛! - expect success, panic on error
2513                        self.unwrap_result_or_option(awaited, true, true)
2514                    }
2515                    Some(Evidentiality::Reported)
2516                    | Some(Evidentiality::Paradox)
2517                    | Some(Evidentiality::Predicted) => {
2518                        // ⌛~ or ⌛‽ or ⌛◊ - mark as external/reported/predicted, unwrap if Result/Option
2519                        self.unwrap_result_or_option(awaited, false, false)
2520                    }
2521                    None => Ok(awaited),
2522                }
2523            }
2524            // Macro invocations: format!(...), println!(...), etc.
2525            Expr::Macro { path, tokens } => {
2526                let macro_name = path
2527                    .segments
2528                    .last()
2529                    .map(|s| s.ident.name.as_str())
2530                    .unwrap_or("");
2531                crate::sigil_debug!(
2532                    "DEBUG Expr::Macro: name='{}', tokens='{}'",
2533                    macro_name,
2534                    tokens
2535                );
2536
2537                match macro_name {
2538                    "format" => self.eval_format_macro(tokens),
2539                    "println" => {
2540                        let formatted = self.eval_format_macro(tokens)?;
2541                        if let Value::String(s) = formatted {
2542                            println!("{}", s);
2543                        }
2544                        Ok(Value::Null)
2545                    }
2546                    "eprintln" => {
2547                        let formatted = self.eval_format_macro(tokens)?;
2548                        if let Value::String(s) = formatted {
2549                            eprintln!("{}", s);
2550                        }
2551                        Ok(Value::Null)
2552                    }
2553                    "print" => {
2554                        let formatted = self.eval_format_macro(tokens)?;
2555                        if let Value::String(s) = formatted {
2556                            print!("{}", s);
2557                        }
2558                        Ok(Value::Null)
2559                    }
2560                    "eprint" => {
2561                        let formatted = self.eval_format_macro(tokens)?;
2562                        if let Value::String(s) = formatted {
2563                            eprint!("{}", s);
2564                        }
2565                        Ok(Value::Null)
2566                    }
2567                    "vec" => {
2568                        // vec![a, b, c] - parse elements and create array
2569                        self.eval_vec_macro(tokens)
2570                    }
2571                    "panic" => {
2572                        let formatted = self.eval_format_macro(tokens)?;
2573                        let msg = if let Value::String(s) = formatted {
2574                            s.to_string()
2575                        } else {
2576                            "panic!".to_string()
2577                        };
2578                        Err(RuntimeError::new(format!("panic: {}", msg)))
2579                    }
2580                    "assert" => {
2581                        // Simple assert - just evaluate the expression
2582                        let condition = self.eval_format_macro(tokens)?;
2583                        if self.is_truthy(&condition) {
2584                            Ok(Value::Null)
2585                        } else {
2586                            Err(RuntimeError::new("assertion failed"))
2587                        }
2588                    }
2589                    _ => {
2590                        // Unknown macro - return tokens as string for debugging
2591                        Ok(Value::String(Rc::new(tokens.clone())))
2592                    }
2593                }
2594            }
2595            // Unsafe block - just evaluate the block normally
2596            Expr::Unsafe(block) => self.eval_block(block),
2597            // Async block - evaluate the block (interpreter doesn't handle true async)
2598            Expr::Async { block, .. } => self.eval_block(block),
2599            // Try expression: expr?
2600            Expr::Try(inner) => {
2601                let value = self.evaluate(inner)?;
2602                // If Result::Err or None, propagate the error
2603                // If Result::Ok or Some, unwrap the value
2604                match &value {
2605                    Value::Variant {
2606                        enum_name,
2607                        variant_name,
2608                        fields,
2609                    } => {
2610                        match (enum_name.as_str(), variant_name.as_str()) {
2611                            ("Result", "Ok") => {
2612                                if let Some(f) = fields {
2613                                    Ok(f.first().cloned().unwrap_or(Value::Null))
2614                                } else {
2615                                    Ok(Value::Null)
2616                                }
2617                            }
2618                            ("Result", "Err") => {
2619                                crate::sigil_debug!(
2620                                    "DEBUG Try propagating Result::Err with fields: {:?}",
2621                                    fields
2622                                );
2623                                let err_msg = if let Some(f) = fields {
2624                                    let first = f.first().cloned().unwrap_or(Value::Null);
2625                                    crate::sigil_debug!("DEBUG Try error first value: {}", first);
2626                                    // Try to get more detail from the error
2627                                    match &first {
2628                                        Value::Struct { name, fields: sf } => {
2629                                            let field_str = sf
2630                                                .borrow()
2631                                                .iter()
2632                                                .map(|(k, v)| format!("{}: {}", k, v))
2633                                                .collect::<Vec<_>>()
2634                                                .join(", ");
2635                                            format!("{} {{ {} }}", name, field_str)
2636                                        }
2637                                        Value::Variant {
2638                                            enum_name: en,
2639                                            variant_name: vn,
2640                                            fields: vf,
2641                                        } => {
2642                                            let vf_str = vf
2643                                                .as_ref()
2644                                                .map(|vs| {
2645                                                    vs.iter()
2646                                                        .map(|v| format!("{}", v))
2647                                                        .collect::<Vec<_>>()
2648                                                        .join(", ")
2649                                                })
2650                                                .unwrap_or_default();
2651                                            format!("{}::{} {{ {} }}", en, vn, vf_str)
2652                                        }
2653                                        _ => format!("{}", first),
2654                                    }
2655                                } else {
2656                                    "error".to_string()
2657                                };
2658                                Err(RuntimeError::new(format!("try failed: {}", err_msg)))
2659                            }
2660                            ("Option", "Some") => {
2661                                if let Some(f) = fields {
2662                                    Ok(f.first().cloned().unwrap_or(Value::Null))
2663                                } else {
2664                                    Ok(Value::Null)
2665                                }
2666                            }
2667                            ("Option", "None") => Err(RuntimeError::new("try failed: None")),
2668                            _ => Ok(value), // Not a Result/Option, pass through
2669                        }
2670                    }
2671                    _ => Ok(value), // Not a variant, pass through
2672                }
2673            }
2674            // Cast expression: expr as Type
2675            Expr::Cast { expr, ty } => {
2676                let value = self.evaluate(expr)?;
2677                // Handle type casts
2678                let type_name = match ty {
2679                    TypeExpr::Path(path) => {
2680                        if !path.segments.is_empty() {
2681                            path.segments
2682                                .last()
2683                                .map(|s| s.ident.name.as_str())
2684                                .unwrap_or("")
2685                        } else {
2686                            ""
2687                        }
2688                    }
2689                    _ => "",
2690                };
2691                match (value, type_name) {
2692                    // Char to numeric
2693                    (Value::Char(c), "u8") => Ok(Value::Int(c as i64)),
2694                    (Value::Char(c), "u16") => Ok(Value::Int(c as i64)),
2695                    (Value::Char(c), "u32") => Ok(Value::Int(c as i64)),
2696                    (Value::Char(c), "u64") => Ok(Value::Int(c as i64)),
2697                    (Value::Char(c), "i8") => Ok(Value::Int(c as i64)),
2698                    (Value::Char(c), "i16") => Ok(Value::Int(c as i64)),
2699                    (Value::Char(c), "i32") => Ok(Value::Int(c as i64)),
2700                    (Value::Char(c), "i64") => Ok(Value::Int(c as i64)),
2701                    (Value::Char(c), "usize") => Ok(Value::Int(c as i64)),
2702                    (Value::Char(c), "isize") => Ok(Value::Int(c as i64)),
2703                    // Int to int (no-op in our runtime)
2704                    (Value::Int(i), "u8") => Ok(Value::Int(i)),
2705                    (Value::Int(i), "u16") => Ok(Value::Int(i)),
2706                    (Value::Int(i), "u32") => Ok(Value::Int(i)),
2707                    (Value::Int(i), "u64") => Ok(Value::Int(i)),
2708                    (Value::Int(i), "i8") => Ok(Value::Int(i)),
2709                    (Value::Int(i), "i16") => Ok(Value::Int(i)),
2710                    (Value::Int(i), "i32") => Ok(Value::Int(i)),
2711                    (Value::Int(i), "i64") => Ok(Value::Int(i)),
2712                    (Value::Int(i), "usize") => Ok(Value::Int(i)),
2713                    (Value::Int(i), "isize") => Ok(Value::Int(i)),
2714                    // Float to int
2715                    (Value::Float(f), "i32") => Ok(Value::Int(f as i64)),
2716                    (Value::Float(f), "i64") => Ok(Value::Int(f as i64)),
2717                    (Value::Float(f), "u32") => Ok(Value::Int(f as i64)),
2718                    (Value::Float(f), "u64") => Ok(Value::Int(f as i64)),
2719                    // Int to float
2720                    (Value::Int(i), "f32") => Ok(Value::Float(i as f64)),
2721                    (Value::Int(i), "f64") => Ok(Value::Float(i as f64)),
2722                    // Int to char
2723                    (Value::Int(i), "char") => {
2724                        if let Some(c) = char::from_u32(i as u32) {
2725                            Ok(Value::Char(c))
2726                        } else {
2727                            Err(RuntimeError::new(format!("invalid char code: {}", i)))
2728                        }
2729                    }
2730                    // Pass through for same type
2731                    (v, _) => Ok(v),
2732                }
2733            }
2734            _ => Err(RuntimeError::new(format!(
2735                "Unsupported expression: {:?}",
2736                expr
2737            ))),
2738        }
2739    }
2740
2741    fn eval_assign(&mut self, target: &Expr, value: &Expr) -> Result<Value, RuntimeError> {
2742        let val = self.evaluate(value)?;
2743
2744        match target {
2745            Expr::Path(path) if path.segments.len() == 1 => {
2746                let name = &path.segments[0].ident.name;
2747                self.environment.borrow_mut().set(name, val.clone())?;
2748                Ok(val)
2749            }
2750            Expr::Index { expr, index } => {
2751                // Array/map index assignment
2752                let idx = self.evaluate(index)?;
2753                let idx = match idx {
2754                    Value::Int(i) => i as usize,
2755                    _ => return Err(RuntimeError::new("Index must be an integer")),
2756                };
2757
2758                // Get the array and modify it
2759                if let Expr::Path(path) = expr.as_ref() {
2760                    if path.segments.len() == 1 {
2761                        let name = &path.segments[0].ident.name;
2762                        let current = self.environment.borrow().get(name).ok_or_else(|| {
2763                            RuntimeError::new(format!("Undefined variable: {}", name))
2764                        })?;
2765
2766                        if let Value::Array(arr) = current {
2767                            let borrowed = arr.borrow();
2768                            let mut new_arr = borrowed.clone();
2769                            drop(borrowed);
2770                            if idx < new_arr.len() {
2771                                new_arr[idx] = val.clone();
2772                                self.environment
2773                                    .borrow_mut()
2774                                    .set(name, Value::Array(Rc::new(RefCell::new(new_arr))))?;
2775                                return Ok(val);
2776                            }
2777                        }
2778                    }
2779                }
2780                Err(RuntimeError::new("Invalid index assignment target"))
2781            }
2782            Expr::Field { expr, field } => {
2783                // Field assignment: struct.field = value
2784                // Need to find the variable and update its field
2785                match expr.as_ref() {
2786                    Expr::Path(path) if path.segments.len() == 1 => {
2787                        let var_name = &path.segments[0].ident.name;
2788                        let current = self.environment.borrow().get(var_name).ok_or_else(|| {
2789                            RuntimeError::new(format!("Undefined variable: {}", var_name))
2790                        })?;
2791
2792                        match current {
2793                            Value::Struct { fields, .. } => {
2794                                fields.borrow_mut().insert(field.name.clone(), val.clone());
2795                                Ok(val)
2796                            }
2797                            Value::Ref(r) => {
2798                                let mut borrowed = r.borrow_mut();
2799                                if let Value::Struct { fields, .. } = &mut *borrowed {
2800                                    fields.borrow_mut().insert(field.name.clone(), val.clone());
2801                                    Ok(val)
2802                                } else {
2803                                    Err(RuntimeError::new("Cannot assign field on non-struct ref"))
2804                                }
2805                            }
2806                            _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
2807                        }
2808                    }
2809                    _ => {
2810                        // For now, just evaluate and try to update (won't persist for non-path exprs)
2811                        let struct_val = self.evaluate(expr)?;
2812                        match struct_val {
2813                            Value::Struct { fields, .. } => {
2814                                fields.borrow_mut().insert(field.name.clone(), val.clone());
2815                                Ok(val)
2816                            }
2817                            Value::Ref(r) => {
2818                                let mut borrowed = r.borrow_mut();
2819                                if let Value::Struct { fields, .. } = &mut *borrowed {
2820                                    fields.borrow_mut().insert(field.name.clone(), val.clone());
2821                                    Ok(val)
2822                                } else {
2823                                    Err(RuntimeError::new("Cannot assign field on non-struct"))
2824                                }
2825                            }
2826                            _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
2827                        }
2828                    }
2829                }
2830            }
2831            Expr::Unary {
2832                op: UnaryOp::Deref,
2833                expr: inner,
2834            } => {
2835                // Dereference assignment: *ptr = value (parsed as Unary)
2836                // Handle mutable references (&mut T)
2837                let ptr_val = self.evaluate(inner)?;
2838                match ptr_val {
2839                    Value::Ref(r) => {
2840                        *r.borrow_mut() = val.clone();
2841                        Ok(val)
2842                    }
2843                    _ => Err(RuntimeError::new(
2844                        "Cannot dereference assign to non-reference",
2845                    )),
2846                }
2847            }
2848            Expr::Deref(inner) => {
2849                // Dereference assignment: *ptr = value (parsed as Deref)
2850                // Handle mutable references (&mut T)
2851                let ptr_val = self.evaluate(inner)?;
2852                match ptr_val {
2853                    Value::Ref(r) => {
2854                        *r.borrow_mut() = val.clone();
2855                        Ok(val)
2856                    }
2857                    _ => Err(RuntimeError::new(
2858                        "Cannot dereference assign to non-reference",
2859                    )),
2860                }
2861            }
2862            _ => Err(RuntimeError::new("Invalid assignment target")),
2863        }
2864    }
2865
2866    fn eval_literal(&mut self, lit: &Literal) -> Result<Value, RuntimeError> {
2867        match lit {
2868            Literal::Int { value, base, .. } => {
2869                let n = self.parse_int(value, base)?;
2870                Ok(Value::Int(n))
2871            }
2872            Literal::Float { value, .. } => {
2873                let n: f64 = value
2874                    .parse()
2875                    .map_err(|_| RuntimeError::new(format!("Invalid float: {}", value)))?;
2876                Ok(Value::Float(n))
2877            }
2878            Literal::String(s) => Ok(Value::String(Rc::new(s.clone()))),
2879            Literal::MultiLineString(s) => Ok(Value::String(Rc::new(s.clone()))),
2880            Literal::RawString(s) => Ok(Value::String(Rc::new(s.clone()))),
2881            Literal::ByteString(bytes) => {
2882                // Convert byte array to an array of integers
2883                let arr: Vec<Value> = bytes.iter().map(|&b| Value::Int(b as i64)).collect();
2884                Ok(Value::Array(Rc::new(RefCell::new(arr))))
2885            }
2886            Literal::InterpolatedString { parts } => {
2887                // Evaluate each part and concatenate, tracking evidentiality
2888                let mut result = String::new();
2889                let mut combined_evidence: Option<Evidence> = None;
2890
2891                for part in parts {
2892                    match part {
2893                        InterpolationPart::Text(s) => result.push_str(s),
2894                        InterpolationPart::Expr(expr) => {
2895                            let value = self.evaluate(expr)?;
2896
2897                            // Track explicit evidentiality
2898                            combined_evidence = Self::combine_evidence(
2899                                combined_evidence,
2900                                Self::extract_evidence(&value),
2901                            );
2902
2903                            // Track affect-derived evidentiality (sarcasm, confidence)
2904                            if let Some(affect) = Self::extract_affect(&value) {
2905                                combined_evidence = Self::combine_evidence(
2906                                    combined_evidence,
2907                                    Self::affect_to_evidence(affect),
2908                                );
2909                            }
2910
2911                            // Use the fully unwrapped value for display
2912                            let display_value = Self::unwrap_value(&value);
2913                            result.push_str(&format!("{}", display_value));
2914                        }
2915                    }
2916                }
2917
2918                // Wrap result with evidentiality if any interpolated values were evidential
2919                let string_value = Value::String(Rc::new(result));
2920                match combined_evidence {
2921                    Some(evidence) => Ok(Value::Evidential {
2922                        value: Box::new(string_value),
2923                        evidence,
2924                    }),
2925                    None => Ok(string_value),
2926                }
2927            }
2928            Literal::SigilStringSql(s) => {
2929                // SQL sigil string - for now just return as string
2930                // Future: could add SQL validation or templating
2931                Ok(Value::String(Rc::new(s.clone())))
2932            }
2933            Literal::SigilStringRoute(s) => {
2934                // Route sigil string - for now just return as string
2935                // Future: could add route validation or templating
2936                Ok(Value::String(Rc::new(s.clone())))
2937            }
2938            Literal::Char(c) => Ok(Value::Char(*c)),
2939            Literal::ByteChar(b) => Ok(Value::Int(*b as i64)),
2940            Literal::Bool(b) => Ok(Value::Bool(*b)),
2941            Literal::Null => Ok(Value::Null),
2942            Literal::Empty => Ok(Value::Empty),
2943            Literal::Infinity => Ok(Value::Infinity),
2944            Literal::Circle => Ok(Value::Int(0)), // ◯ = zero
2945        }
2946    }
2947
2948    fn parse_int(&self, value: &str, base: &NumBase) -> Result<i64, RuntimeError> {
2949        let (radix, prefix_len) = match base {
2950            NumBase::Binary => (2, 2), // 0b
2951            NumBase::Octal => (8, 2),  // 0o
2952            NumBase::Decimal => (10, 0),
2953            NumBase::Hex => (16, 2),         // 0x
2954            NumBase::Vigesimal => (20, 2),   // 0v
2955            NumBase::Sexagesimal => (60, 2), // 0s
2956            NumBase::Duodecimal => (12, 2),  // 0z
2957            NumBase::Explicit(b) => (*b as u32, 0),
2958        };
2959
2960        let clean = value[prefix_len..].replace('_', "");
2961        i64::from_str_radix(&clean, radix)
2962            .map_err(|_| RuntimeError::new(format!("Invalid integer: {}", value)))
2963    }
2964
2965    fn eval_path(&self, path: &TypePath) -> Result<Value, RuntimeError> {
2966        if path.segments.len() == 1 {
2967            let name = &path.segments[0].ident.name;
2968            // Look up the variable in the environment
2969            // Note: "_" may be bound by pipe operations (τ, φ, etc.), so we must check
2970            // the environment first before treating it as a wildcard
2971            if let Some(val) = self.environment.borrow().get(name) {
2972                return Ok(val);
2973            }
2974            // Handle wildcard "_" - return Null if not bound
2975            if name == "_" {
2976                return Ok(Value::Null);
2977            }
2978            // Handle "Self" as unit struct constructor (for unit structs like `pub fn new() -> Self { Self }`)
2979            if name == "Self" {
2980                if let Some(ref self_type) = self.current_self_type {
2981                    // Check if the type is a unit struct
2982                    if let Some(TypeDef::Struct(struct_def)) = self.types.get(self_type) {
2983                        if matches!(struct_def.fields, crate::ast::StructFields::Unit) {
2984                            return Ok(Value::Struct {
2985                                name: self_type.clone(),
2986                                fields: Rc::new(RefCell::new(HashMap::new())),
2987                            });
2988                        }
2989                    }
2990                    // If not a unit struct, create empty struct (best effort)
2991                    return Ok(Value::Struct {
2992                        name: self_type.clone(),
2993                        fields: Rc::new(RefCell::new(HashMap::new())),
2994                    });
2995                }
2996            }
2997            if name.len() <= 2 {
2998                crate::sigil_debug!("DEBUG Undefined variable '{}' (len={})", name, name.len());
2999            }
3000            Err(RuntimeError::new(format!("Undefined variable: {}", name)))
3001        } else {
3002            // Multi-segment path (module::item or Type·method)
3003            // Try full qualified name first (joined with ·)
3004            let full_name = path
3005                .segments
3006                .iter()
3007                .map(|s| s.ident.name.as_str())
3008                .collect::<Vec<_>>()
3009                .join("·");
3010
3011            if let Some(val) = self.environment.borrow().get(&full_name) {
3012                return Ok(val);
3013            }
3014
3015            // Check globals for qualified name (for Type::method patterns)
3016            if let Some(val) = self.globals.borrow().get(&full_name) {
3017                return Ok(val);
3018            }
3019
3020            // If in a module context, try current_module·full_name for sibling modules
3021            // e.g., when in samael_cli, "analyze::execute" -> "samael_cli·analyze·execute"
3022            if let Some(ref current_mod) = self.current_module {
3023                // Extract crate name from current_module (e.g., "samael_cli" from "samael_cli·analyze")
3024                let crate_name = current_mod.split('·').next().unwrap_or(current_mod);
3025                let crate_qualified = format!("{}·{}", crate_name, full_name);
3026                if full_name.contains("execute") {
3027                    crate::sigil_debug!(
3028                        "DEBUG eval_path: Looking for '{}' with crate_qualified='{}'",
3029                        full_name,
3030                        crate_qualified
3031                    );
3032                }
3033                if let Some(val) = self.globals.borrow().get(&crate_qualified) {
3034                    crate::sigil_debug!(
3035                        "DEBUG eval_path: FOUND '{}' via crate_qualified",
3036                        crate_qualified
3037                    );
3038                    return Ok(val);
3039                }
3040            } else if full_name.contains("execute") {
3041                crate::sigil_debug!(
3042                    "DEBUG eval_path: current_module is None, can't resolve '{}'",
3043                    full_name
3044                );
3045            }
3046
3047            // DEBUG: Check if we're looking for a ::new call
3048            if full_name.ends_with("·new") {
3049                crate::sigil_debug!(
3050                    "DEBUG eval_path: Looking for '{}' - NOT FOUND in globals",
3051                    full_name
3052                );
3053            }
3054
3055            // Check for enum variant syntax FIRST (EnumName::Variant)
3056            // This must come before looking up just the last segment to avoid
3057            // returning a built-in function instead of the actual variant
3058            if path.segments.len() == 2 {
3059                let type_name = &path.segments[0].ident.name;
3060                let variant_name = &path.segments[1].ident.name;
3061
3062                // Check if this is an enum variant (direct type name match)
3063                if let Some(TypeDef::Enum(enum_def)) = self.types.get(type_name) {
3064                    for variant in &enum_def.variants {
3065                        if &variant.name.name == variant_name {
3066                            // Return a variant constructor or unit variant
3067                            if matches!(variant.fields, crate::ast::StructFields::Unit) {
3068                                return Ok(Value::Variant {
3069                                    enum_name: type_name.clone(),
3070                                    variant_name: variant_name.clone(),
3071                                    fields: None,
3072                                });
3073                            }
3074                        }
3075                    }
3076                }
3077
3078                // Fallback: type name might be an alias - search all enums for the variant
3079                for (actual_type_name, type_def) in &self.types {
3080                    if let TypeDef::Enum(enum_def) = type_def {
3081                        for variant in &enum_def.variants {
3082                            if &variant.name.name == variant_name {
3083                                if matches!(variant.fields, crate::ast::StructFields::Unit) {
3084                                    return Ok(Value::Variant {
3085                                        enum_name: actual_type_name.clone(),
3086                                        variant_name: variant_name.clone(),
3087                                        fields: None,
3088                                    });
3089                                }
3090                            }
3091                        }
3092                    }
3093                }
3094            }
3095
3096            // Try looking up the last segment (for Math·sqrt -> sqrt)
3097            let last_name = &path.segments.last().unwrap().ident.name;
3098            if let Some(val) = self.environment.borrow().get(last_name) {
3099                // DEBUG: Warn about fallback for new functions
3100                if last_name == "new" {
3101                    crate::sigil_debug!(
3102                        "DEBUG eval_path: FALLBACK from '{}' to '{}' - found in env",
3103                        full_name,
3104                        last_name
3105                    );
3106                }
3107                return Ok(val);
3108            }
3109
3110            // Handle Self::method - use current_self_type to get the specific type
3111            if path.segments.len() == 2 && path.segments[0].ident.name == "Self" {
3112                if let Some(ref self_type) = self.current_self_type {
3113                    // Look up the specific Type·method function
3114                    let qualified = format!("{}·{}", self_type, last_name);
3115                    if let Some(val) = self.globals.borrow().get(&qualified) {
3116                        return Ok(val);
3117                    }
3118                }
3119            }
3120
3121            // Check for variant constructor in variant_constructors table
3122            if let Some((enum_name, variant_name, arity)) =
3123                self.variant_constructors.get(&full_name).cloned()
3124            {
3125                // Return a special marker that eval_call can recognize
3126                // For unit variants, return the variant directly
3127                if arity == 0 {
3128                    return Ok(Value::Variant {
3129                        enum_name,
3130                        variant_name,
3131                        fields: None,
3132                    });
3133                }
3134                // For variants with fields, we need to return something callable
3135                // We'll use a special builtin-like marker
3136                // Actually, let's just let eval_call handle it via call_function_by_name
3137            }
3138
3139            // Fallback for unknown types from external crates:
3140            if path.segments.len() == 2 {
3141                let type_name = &path.segments[0].ident.name;
3142                let method_name = &path.segments[1].ident.name;
3143
3144                // Check if this looks like a constructor/method call (lowercase or snake_case)
3145                let is_method = method_name
3146                    .chars()
3147                    .next()
3148                    .map_or(false, |c| c.is_lowercase())
3149                    || method_name == "new"
3150                    || method_name == "default"
3151                    || method_name == "from"
3152                    || method_name == "try_from"
3153                    || method_name == "into"
3154                    || method_name == "with_capacity"
3155                    || method_name == "from_str";
3156
3157                if is_method {
3158                    // Return a special marker that eval_call will recognize
3159                    // Store the type name in a Struct value with a special marker name
3160                    return Ok(Value::Struct {
3161                        name: format!("__constructor__{}", type_name),
3162                        fields: Rc::new(RefCell::new(HashMap::new())),
3163                    });
3164                } else {
3165                    // Looks like an enum variant (PascalCase) - create unit variant
3166                    return Ok(Value::Variant {
3167                        enum_name: type_name.clone(),
3168                        variant_name: method_name.clone(),
3169                        fields: None,
3170                    });
3171                }
3172            }
3173
3174            Err(RuntimeError::new(format!(
3175                "Undefined: {} (tried {} and {})",
3176                full_name, full_name, last_name
3177            )))
3178        }
3179    }
3180
3181    fn eval_binary(
3182        &mut self,
3183        left: &Expr,
3184        op: &BinOp,
3185        right: &Expr,
3186    ) -> Result<Value, RuntimeError> {
3187        let lhs = self.evaluate(left)?;
3188
3189        // Short-circuit for && and ||
3190        match op {
3191            BinOp::And => {
3192                if !self.is_truthy(&lhs) {
3193                    return Ok(Value::Bool(false));
3194                }
3195                let rhs = self.evaluate(right)?;
3196                return Ok(Value::Bool(self.is_truthy(&rhs)));
3197            }
3198            BinOp::Or => {
3199                if self.is_truthy(&lhs) {
3200                    return Ok(Value::Bool(true));
3201                }
3202                let rhs = self.evaluate(right)?;
3203                return Ok(Value::Bool(self.is_truthy(&rhs)));
3204            }
3205            _ => {}
3206        }
3207
3208        let rhs = self.evaluate(right)?;
3209
3210        // Unwrap all wrappers (evidential/affective/ref) for binary operations
3211        let lhs = Self::unwrap_all(&lhs);
3212        let rhs = Self::unwrap_all(&rhs);
3213
3214        // Debug Mul operations involving potential null
3215        if matches!(op, BinOp::Mul)
3216            && (matches!(lhs, Value::Null)
3217                || matches!(rhs, Value::Null)
3218                || matches!(lhs, Value::Struct { .. })
3219                || matches!(rhs, Value::Struct { .. }))
3220        {
3221            crate::sigil_debug!("DEBUG eval_binary Mul: left={:?}, right={:?}", left, right);
3222            crate::sigil_debug!(
3223                "DEBUG eval_binary Mul: lhs={}, rhs={}",
3224                self.format_value(&lhs),
3225                self.format_value(&rhs)
3226            );
3227        }
3228
3229        match (lhs, rhs) {
3230            (Value::Int(a), Value::Int(b)) => self.int_binary_op(a, b, op),
3231            (Value::Float(a), Value::Float(b)) => self.float_binary_op(a, b, op),
3232            (Value::Int(a), Value::Float(b)) => self.float_binary_op(a as f64, b, op),
3233            (Value::Float(a), Value::Int(b)) => self.float_binary_op(a, b as f64, op),
3234            (Value::String(a), Value::String(b)) => match op {
3235                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
3236                BinOp::Eq => Ok(Value::Bool(*a == *b)),
3237                BinOp::Ne => Ok(Value::Bool(*a != *b)),
3238                _ => Err(RuntimeError::new("Invalid string operation")),
3239            },
3240            (Value::Bool(a), Value::Bool(b)) => match op {
3241                BinOp::Eq => Ok(Value::Bool(a == b)),
3242                BinOp::Ne => Ok(Value::Bool(a != b)),
3243                _ => Err(RuntimeError::new("Invalid boolean operation")),
3244            },
3245            (Value::Array(a), Value::Array(b)) => match op {
3246                BinOp::Concat => {
3247                    let mut result = a.borrow().clone();
3248                    result.extend(b.borrow().iter().cloned());
3249                    Ok(Value::Array(Rc::new(RefCell::new(result))))
3250                }
3251                BinOp::Eq => Ok(Value::Bool(Rc::ptr_eq(&a, &b))),
3252                BinOp::Ne => Ok(Value::Bool(!Rc::ptr_eq(&a, &b))),
3253                _ => Err(RuntimeError::new("Invalid array operation")),
3254            },
3255            // Null equality
3256            (Value::Null, Value::Null) => match op {
3257                BinOp::Eq => Ok(Value::Bool(true)),
3258                BinOp::Ne => Ok(Value::Bool(false)),
3259                _ => {
3260                    crate::sigil_debug!("DEBUG: null op {:?} on (Null, Null)", op);
3261                    Err(RuntimeError::new(format!(
3262                        "Invalid null operation: {:?} on (Null, Null)",
3263                        op
3264                    )))
3265                }
3266            },
3267            (Value::Null, other) | (other, Value::Null) => match op {
3268                BinOp::Eq => Ok(Value::Bool(false)),
3269                BinOp::Ne => Ok(Value::Bool(true)),
3270                _ => {
3271                    crate::sigil_debug!(
3272                        "DEBUG: null op {:?} with other={}",
3273                        op,
3274                        self.format_value(&other)
3275                    );
3276                    Err(RuntimeError::new(format!(
3277                        "Invalid null operation: {:?}",
3278                        op
3279                    )))
3280                }
3281            },
3282            // Char comparisons
3283            (Value::Char(a), Value::Char(b)) => match op {
3284                BinOp::Eq => Ok(Value::Bool(a == b)),
3285                BinOp::Ne => Ok(Value::Bool(a != b)),
3286                BinOp::Lt => Ok(Value::Bool(a < b)),
3287                BinOp::Le => Ok(Value::Bool(a <= b)),
3288                BinOp::Gt => Ok(Value::Bool(a > b)),
3289                BinOp::Ge => Ok(Value::Bool(a >= b)),
3290                _ => Err(RuntimeError::new("Invalid char operation")),
3291            },
3292            // String and char operations
3293            (Value::String(a), Value::Char(b)) => match op {
3294                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
3295                _ => Err(RuntimeError::new("Invalid string/char operation")),
3296            },
3297            (Value::Char(a), Value::String(b)) => match op {
3298                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
3299                _ => Err(RuntimeError::new("Invalid char/string operation")),
3300            },
3301            // Variant equality
3302            (
3303                Value::Variant {
3304                    enum_name: e1,
3305                    variant_name: v1,
3306                    fields: f1,
3307                },
3308                Value::Variant {
3309                    enum_name: e2,
3310                    variant_name: v2,
3311                    fields: f2,
3312                },
3313            ) => match op {
3314                BinOp::Eq => {
3315                    let eq = e1 == e2
3316                        && v1 == v2
3317                        && match (f1, f2) {
3318                            (None, None) => true,
3319                            (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
3320                            _ => false,
3321                        };
3322                    Ok(Value::Bool(eq))
3323                }
3324                BinOp::Ne => {
3325                    let eq = e1 == e2
3326                        && v1 == v2
3327                        && match (f1, f2) {
3328                            (None, None) => true,
3329                            (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
3330                            _ => false,
3331                        };
3332                    Ok(Value::Bool(!eq))
3333                }
3334                _ => Err(RuntimeError::new("Invalid variant operation")),
3335            },
3336            // Struct equality (by reference)
3337            (
3338                Value::Struct {
3339                    name: n1,
3340                    fields: f1,
3341                },
3342                Value::Struct {
3343                    name: n2,
3344                    fields: f2,
3345                },
3346            ) => match op {
3347                BinOp::Eq => Ok(Value::Bool(n1 == n2 && Rc::ptr_eq(&f1, &f2))),
3348                BinOp::Ne => Ok(Value::Bool(n1 != n2 || !Rc::ptr_eq(&f1, &f2))),
3349                _ => Err(RuntimeError::new("Invalid struct operation")),
3350            },
3351            (l, r) => Err(RuntimeError::new(format!(
3352                "Type mismatch in binary operation: {:?} {:?} {:?}",
3353                l, op, r
3354            ))),
3355        }
3356    }
3357
3358    fn int_binary_op(&self, a: i64, b: i64, op: &BinOp) -> Result<Value, RuntimeError> {
3359        Ok(match op {
3360            BinOp::Add => Value::Int(a + b),
3361            BinOp::Sub => Value::Int(a - b),
3362            BinOp::Mul => Value::Int(a * b),
3363            BinOp::Div => {
3364                if b == 0 {
3365                    return Err(RuntimeError::new("Division by zero"));
3366                }
3367                Value::Int(a / b)
3368            }
3369            BinOp::Rem => {
3370                if b == 0 {
3371                    return Err(RuntimeError::new("Division by zero"));
3372                }
3373                Value::Int(a % b)
3374            }
3375            BinOp::Pow => Value::Int(a.pow(b as u32)),
3376            BinOp::Eq => Value::Bool(a == b),
3377            BinOp::Ne => Value::Bool(a != b),
3378            BinOp::Lt => Value::Bool(a < b),
3379            BinOp::Le => Value::Bool(a <= b),
3380            BinOp::Gt => Value::Bool(a > b),
3381            BinOp::Ge => Value::Bool(a >= b),
3382            BinOp::BitAnd => Value::Int(a & b),
3383            BinOp::BitOr => Value::Int(a | b),
3384            BinOp::BitXor => Value::Int(a ^ b),
3385            BinOp::Shl => Value::Int(a << b),
3386            BinOp::Shr => Value::Int(a >> b),
3387            _ => return Err(RuntimeError::new("Invalid integer operation")),
3388        })
3389    }
3390
3391    fn float_binary_op(&self, a: f64, b: f64, op: &BinOp) -> Result<Value, RuntimeError> {
3392        Ok(match op {
3393            BinOp::Add => Value::Float(a + b),
3394            BinOp::Sub => Value::Float(a - b),
3395            BinOp::Mul => Value::Float(a * b),
3396            BinOp::Div => Value::Float(a / b),
3397            BinOp::Rem => Value::Float(a % b),
3398            BinOp::Pow => Value::Float(a.powf(b)),
3399            BinOp::Eq => Value::Bool((a - b).abs() < f64::EPSILON),
3400            BinOp::Ne => Value::Bool((a - b).abs() >= f64::EPSILON),
3401            BinOp::Lt => Value::Bool(a < b),
3402            BinOp::Le => Value::Bool(a <= b),
3403            BinOp::Gt => Value::Bool(a > b),
3404            BinOp::Ge => Value::Bool(a >= b),
3405            _ => return Err(RuntimeError::new("Invalid float operation")),
3406        })
3407    }
3408
3409    fn eval_unary(&mut self, op: &UnaryOp, expr: &Expr) -> Result<Value, RuntimeError> {
3410        let val = self.evaluate(expr)?;
3411        match (op, &val) {
3412            (UnaryOp::Neg, Value::Int(n)) => Ok(Value::Int(-n)),
3413            (UnaryOp::Neg, Value::Float(n)) => Ok(Value::Float(-n)),
3414            (UnaryOp::Not, Value::Bool(b)) => Ok(Value::Bool(!b)),
3415            (UnaryOp::Not, Value::Int(n)) => Ok(Value::Int(!n)),
3416            // Handle evidential values - unwrap, negate, rewrap
3417            (UnaryOp::Not, Value::Evidential { value, evidence }) => {
3418                // Negate the inner value
3419                match value.as_ref() {
3420                    Value::Bool(b) => Ok(Value::Evidential {
3421                        value: Box::new(Value::Bool(!b)),
3422                        evidence: evidence.clone(),
3423                    }),
3424                    other => {
3425                        let truthy = self.is_truthy(other);
3426                        Ok(Value::Evidential {
3427                            value: Box::new(Value::Bool(!truthy)),
3428                            evidence: evidence.clone(),
3429                        })
3430                    }
3431                }
3432            }
3433            // Handle string truthiness (non-empty = true)
3434            (UnaryOp::Not, Value::String(s)) => Ok(Value::Bool(s.is_empty())),
3435            // Handle array truthiness (non-empty = true)
3436            (UnaryOp::Not, Value::Array(arr)) => Ok(Value::Bool(arr.borrow().is_empty())),
3437            // Handle null - null is falsy
3438            (UnaryOp::Not, Value::Null) => Ok(Value::Bool(true)),
3439            (UnaryOp::Ref, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
3440            (UnaryOp::RefMut, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
3441            (UnaryOp::Deref, Value::Ref(r)) => Ok(r.borrow().clone()),
3442            (UnaryOp::Deref, Value::Struct { name, fields }) if name == "Rc" => {
3443                // Deref Rc to get inner value
3444                let borrowed = fields.borrow();
3445                if let Some(value) = borrowed.get("_value") {
3446                    Ok(value.clone())
3447                } else {
3448                    Err(RuntimeError::new("Rc has no value"))
3449                }
3450            }
3451            (UnaryOp::Deref, other) => {
3452                // Try to unwrap evidential/affective wrappers and deref
3453                let unwrapped = Self::unwrap_all(&val);
3454                if let Value::Ref(r) = &unwrapped {
3455                    return Ok(r.borrow().clone());
3456                }
3457                // For non-ref types in interpreted code, just return the value as-is
3458                // (dereferencing a copy type in Sigil is a no-op)
3459                Ok(unwrapped)
3460            }
3461            _ => Err(RuntimeError::new(format!(
3462                "Invalid unary {:?} on {:?}",
3463                op,
3464                std::mem::discriminant(&val)
3465            ))),
3466        }
3467    }
3468
3469    fn eval_call(&mut self, func_expr: &Expr, args: &[Expr]) -> Result<Value, RuntimeError> {
3470        // Check if func_expr is a path that might be a variant constructor or tuple struct
3471        if let Expr::Path(path) = func_expr {
3472            let qualified_name = path
3473                .segments
3474                .iter()
3475                .map(|s| s.ident.name.as_str())
3476                .collect::<Vec<_>>()
3477                .join("·");
3478
3479            // Handle Self(...) as tuple struct constructor
3480            if qualified_name == "Self" {
3481                if let Some(ref self_type) = self.current_self_type {
3482                    // Check if this type is a tuple struct - extract arity first to release borrow
3483                    let tuple_arity = if let Some(TypeDef::Struct(struct_def)) =
3484                        self.types.get(self_type)
3485                    {
3486                        if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
3487                            Some((self_type.clone(), field_types.len()))
3488                        } else {
3489                            None
3490                        }
3491                    } else {
3492                        None
3493                    };
3494
3495                    if let Some((type_name, expected_arity)) = tuple_arity {
3496                        // Now we can safely evaluate arguments
3497                        let arg_values: Vec<Value> = args
3498                            .iter()
3499                            .map(|a| self.evaluate(a))
3500                            .collect::<Result<_, _>>()?;
3501
3502                        if arg_values.len() != expected_arity {
3503                            return Err(RuntimeError::new(format!(
3504                                "Tuple struct {} expects {} fields, got {}",
3505                                type_name,
3506                                expected_arity,
3507                                arg_values.len()
3508                            )));
3509                        }
3510
3511                        // Create struct with numbered fields (0, 1, 2, ...)
3512                        let mut fields = HashMap::new();
3513                        for (i, value) in arg_values.into_iter().enumerate() {
3514                            fields.insert(i.to_string(), value);
3515                        }
3516                        return Ok(Value::Struct {
3517                            name: type_name,
3518                            fields: Rc::new(RefCell::new(fields)),
3519                        });
3520                    }
3521                }
3522            }
3523
3524            // Handle TypeName(...) as tuple struct constructor
3525            if path.segments.len() == 1 {
3526                let type_name = &path.segments[0].ident.name;
3527                // Extract arity first to release borrow
3528                let tuple_arity =
3529                    if let Some(TypeDef::Struct(struct_def)) = self.types.get(type_name) {
3530                        if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
3531                            Some((type_name.clone(), field_types.len()))
3532                        } else {
3533                            None
3534                        }
3535                    } else {
3536                        None
3537                    };
3538
3539                if let Some((struct_name, expected_arity)) = tuple_arity {
3540                    let arg_values: Vec<Value> = args
3541                        .iter()
3542                        .map(|a| self.evaluate(a))
3543                        .collect::<Result<_, _>>()?;
3544
3545                    if arg_values.len() != expected_arity {
3546                        return Err(RuntimeError::new(format!(
3547                            "Tuple struct {} expects {} fields, got {}",
3548                            struct_name,
3549                            expected_arity,
3550                            arg_values.len()
3551                        )));
3552                    }
3553
3554                    let mut fields = HashMap::new();
3555                    for (i, value) in arg_values.into_iter().enumerate() {
3556                        fields.insert(i.to_string(), value);
3557                    }
3558                    return Ok(Value::Struct {
3559                        name: struct_name,
3560                        fields: Rc::new(RefCell::new(fields)),
3561                    });
3562                }
3563            }
3564
3565            // Handle Default::default() when current_self_type is set
3566            // This allows ..Default::default() to work in struct literals
3567            if qualified_name == "Default·default" && args.is_empty() {
3568                if let Some(type_name) = self.current_self_type.clone() {
3569                    // First check if type has impl Default with explicit default fn
3570                    let default_fn_name = format!("{}·default", type_name);
3571                    crate::sigil_debug!(
3572                        "DEBUG Default::default() looking for '{}', self_type='{}'",
3573                        default_fn_name,
3574                        type_name
3575                    );
3576                    let func_clone = self
3577                        .globals
3578                        .borrow()
3579                        .get(&default_fn_name)
3580                        .map(|v| v.clone());
3581                    if let Some(Value::Function(f)) = func_clone {
3582                        crate::sigil_debug!(
3583                            "DEBUG Found function '{}', calling it",
3584                            default_fn_name
3585                        );
3586                        crate::sigil_debug!(
3587                            "DEBUG current_self_type before call: {:?}",
3588                            self.current_self_type
3589                        );
3590                        // Call the type's default implementation
3591                        let result = self.call_function(&f, vec![]);
3592                        crate::sigil_debug!(
3593                            "DEBUG Default call result: {:?}",
3594                            result
3595                                .as_ref()
3596                                .map(|v| self.format_value(v))
3597                                .unwrap_or_else(|e| format!("ERR: {:?}", e))
3598                        );
3599                        return result;
3600                    }
3601                    // Otherwise check for #[derive(Default)]
3602                    if let Some(struct_def) = self.default_structs.get(&type_name).cloned() {
3603                        let mut fields = HashMap::new();
3604                        if let StructFields::Named(field_defs) = &struct_def.fields {
3605                            for field in field_defs {
3606                                let default_val = if let Some(default_expr) = &field.default {
3607                                    self.evaluate(default_expr)?
3608                                } else {
3609                                    Value::Null
3610                                };
3611                                fields.insert(field.name.name.clone(), default_val);
3612                            }
3613                        }
3614                        return Ok(Value::Struct {
3615                            name: type_name,
3616                            fields: Rc::new(RefCell::new(fields)),
3617                        });
3618                    }
3619                }
3620            }
3621
3622            // Check for TypeName·default pattern
3623            if qualified_name.ends_with("·default") && args.is_empty() {
3624                let type_name = qualified_name.strip_suffix("·default").unwrap();
3625                // First check if type has impl Default with explicit default fn
3626                let default_fn_name = format!("{}·default", type_name);
3627                let func_clone = self
3628                    .globals
3629                    .borrow()
3630                    .get(&default_fn_name)
3631                    .map(|v| v.clone());
3632                if let Some(Value::Function(f)) = func_clone {
3633                    // Call the type's default implementation
3634                    return self.call_function(&f, vec![]);
3635                }
3636                // Otherwise check for #[derive(Default)]
3637                if let Some(struct_def) = self.default_structs.get(type_name).cloned() {
3638                    let mut fields = HashMap::new();
3639                    if let StructFields::Named(field_defs) = &struct_def.fields {
3640                        for field in field_defs {
3641                            let default_val = if let Some(default_expr) = &field.default {
3642                                self.evaluate(default_expr)?
3643                            } else {
3644                                // No default - use null for optional/uncertain types
3645                                Value::Null
3646                            };
3647                            fields.insert(field.name.name.clone(), default_val);
3648                        }
3649                    }
3650                    return Ok(Value::Struct {
3651                        name: type_name.to_string(),
3652                        fields: Rc::new(RefCell::new(fields)),
3653                    });
3654                }
3655            }
3656
3657            // Check variant constructors
3658            if let Some((enum_name, variant_name, arity)) =
3659                self.variant_constructors.get(&qualified_name).cloned()
3660            {
3661                let arg_values: Vec<Value> = args
3662                    .iter()
3663                    .map(|a| self.evaluate(a))
3664                    .collect::<Result<_, _>>()?;
3665
3666                if arg_values.len() != arity {
3667                    return Err(RuntimeError::new(format!(
3668                        "{} expects {} arguments, got {}",
3669                        qualified_name,
3670                        arity,
3671                        arg_values.len()
3672                    )));
3673                }
3674
3675                if arity == 0 {
3676                    return Ok(Value::Variant {
3677                        enum_name,
3678                        variant_name,
3679                        fields: None,
3680                    });
3681                } else {
3682                    if enum_name == "Item" {
3683                        crate::sigil_debug!(
3684                            "DEBUG creating Item::{} variant with {} fields",
3685                            variant_name,
3686                            arg_values.len()
3687                        );
3688                    }
3689                    return Ok(Value::Variant {
3690                        enum_name,
3691                        variant_name,
3692                        fields: Some(Rc::new(arg_values)),
3693                    });
3694                }
3695            }
3696
3697            // Check for built-in type constructors (Map::new, String::new, HashMap::new, etc.)
3698            let segments: Vec<&str> = path
3699                .segments
3700                .iter()
3701                .map(|s| s.ident.name.as_str())
3702                .collect();
3703            match segments.as_slice() {
3704                ["Map", "new"] | ["HashMap", "new"] => {
3705                    // Create a new empty Map (represented as a struct with HashMap fields)
3706                    return Ok(Value::Struct {
3707                        name: "Map".to_string(),
3708                        fields: Rc::new(RefCell::new(HashMap::new())),
3709                    });
3710                }
3711                ["String", "new"] => {
3712                    return Ok(Value::String(Rc::new(String::new())));
3713                }
3714                ["Vec", "new"] | ["Array", "new"] => {
3715                    return Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))));
3716                }
3717                ["Box", "new"] => {
3718                    // Box::new(value) - just return the value (no heap allocation in interpreter)
3719                    if args.len() == 1 {
3720                        return self.evaluate(&args[0]);
3721                    }
3722                    return Err(RuntimeError::new("Box::new expects 1 argument"));
3723                }
3724                ["char", "from_u32"] => {
3725                    // char::from_u32(u32) -> Option<char>
3726                    if args.len() == 1 {
3727                        let arg = self.evaluate(&args[0])?;
3728                        let code = match arg {
3729                            Value::Int(i) => i as u32,
3730                            _ => return Err(RuntimeError::new("char::from_u32 expects u32")),
3731                        };
3732                        if let Some(c) = char::from_u32(code) {
3733                            // Return Some(char)
3734                            return Ok(Value::Variant {
3735                                enum_name: "Option".to_string(),
3736                                variant_name: "Some".to_string(),
3737                                fields: Some(Rc::new(vec![Value::Char(c)])),
3738                            });
3739                        } else {
3740                            // Return None
3741                            return Ok(Value::Variant {
3742                                enum_name: "Option".to_string(),
3743                                variant_name: "None".to_string(),
3744                                fields: None,
3745                            });
3746                        }
3747                    }
3748                    return Err(RuntimeError::new("char::from_u32 expects 1 argument"));
3749                }
3750                // Mutex::new - create a mutex wrapper around a value
3751                ["parking_lot", "Mutex", "new"]
3752                | ["std", "sync", "Mutex", "new"]
3753                | ["Mutex", "new"] => {
3754                    if args.len() == 1 {
3755                        let inner = self.evaluate(&args[0])?;
3756                        return Ok(Value::Struct {
3757                            name: "Mutex".to_string(),
3758                            fields: Rc::new(RefCell::new(HashMap::from([(
3759                                "__inner__".to_string(),
3760                                inner,
3761                            )]))),
3762                        });
3763                    }
3764                    return Err(RuntimeError::new("Mutex::new expects 1 argument"));
3765                }
3766                // RwLock::new - same as Mutex for interpreter purposes
3767                ["parking_lot", "RwLock", "new"]
3768                | ["std", "sync", "RwLock", "new"]
3769                | ["RwLock", "new"] => {
3770                    if args.len() == 1 {
3771                        let inner = self.evaluate(&args[0])?;
3772                        return Ok(Value::Struct {
3773                            name: "RwLock".to_string(),
3774                            fields: Rc::new(RefCell::new(HashMap::from([(
3775                                "__inner__".to_string(),
3776                                inner,
3777                            )]))),
3778                        });
3779                    }
3780                    return Err(RuntimeError::new("RwLock::new expects 1 argument"));
3781                }
3782                // Arc::new - just wrap the value (no real reference counting in interpreter)
3783                ["std", "sync", "Arc", "new"] | ["Arc", "new"] => {
3784                    if args.len() == 1 {
3785                        let inner = self.evaluate(&args[0])?;
3786                        return Ok(Value::Ref(Rc::new(RefCell::new(inner))));
3787                    }
3788                    return Err(RuntimeError::new("Arc::new expects 1 argument"));
3789                }
3790                // AtomicU64::new and similar atomics
3791                ["std", "sync", "atomic", "AtomicU64", "new"] | ["AtomicU64", "new"] => {
3792                    if args.len() == 1 {
3793                        let inner = self.evaluate(&args[0])?;
3794                        return Ok(Value::Struct {
3795                            name: "AtomicU64".to_string(),
3796                            fields: Rc::new(RefCell::new(HashMap::from([(
3797                                "__value__".to_string(),
3798                                inner,
3799                            )]))),
3800                        });
3801                    }
3802                    return Err(RuntimeError::new("AtomicU64::new expects 1 argument"));
3803                }
3804                ["std", "sync", "atomic", "AtomicUsize", "new"] | ["AtomicUsize", "new"] => {
3805                    if args.len() == 1 {
3806                        let inner = self.evaluate(&args[0])?;
3807                        return Ok(Value::Struct {
3808                            name: "AtomicUsize".to_string(),
3809                            fields: Rc::new(RefCell::new(HashMap::from([(
3810                                "__value__".to_string(),
3811                                inner,
3812                            )]))),
3813                        });
3814                    }
3815                    return Err(RuntimeError::new("AtomicUsize::new expects 1 argument"));
3816                }
3817                ["std", "sync", "atomic", "AtomicBool", "new"] | ["AtomicBool", "new"] => {
3818                    if args.len() == 1 {
3819                        let inner = self.evaluate(&args[0])?;
3820                        return Ok(Value::Struct {
3821                            name: "AtomicBool".to_string(),
3822                            fields: Rc::new(RefCell::new(HashMap::from([(
3823                                "__value__".to_string(),
3824                                inner,
3825                            )]))),
3826                        });
3827                    }
3828                    return Err(RuntimeError::new("AtomicBool::new expects 1 argument"));
3829                }
3830                _ => {}
3831            }
3832        }
3833
3834        // If calling a qualified function (Type::method), set current_self_type
3835        let type_name_for_self = if let Expr::Path(path) = func_expr {
3836            if path.segments.len() >= 2 {
3837                // First segment is the type name
3838                let first = &path.segments[0].ident.name;
3839                // Check if it's a type name (exists in types registry)
3840                if self.types.contains_key(first) {
3841                    Some(first.clone())
3842                } else {
3843                    None
3844                }
3845            } else {
3846                None
3847            }
3848        } else {
3849            None
3850        };
3851
3852        let func = self.evaluate(func_expr)?;
3853
3854        // Track &mut path arguments for sync-back after function call
3855        // This enables proper mutable reference semantics where modifications persist
3856        let mut mut_ref_sync: Vec<(String, Rc<RefCell<Value>>)> = Vec::new();
3857
3858        let mut arg_values: Vec<Value> = Vec::new();
3859        for arg in args.iter() {
3860            let val = self.evaluate(arg)?;
3861
3862            // If this was a &mut path expression, track it for sync-back
3863            if let Expr::Unary {
3864                op: crate::ast::UnaryOp::RefMut,
3865                expr,
3866            } = arg
3867            {
3868                if let Expr::Path(path) = expr.as_ref() {
3869                    if path.segments.len() == 1 {
3870                        let var_name = path.segments[0].ident.name.clone();
3871                        if let Value::Ref(r) = &val {
3872                            mut_ref_sync.push((var_name, r.clone()));
3873                        }
3874                    }
3875                }
3876            }
3877
3878            arg_values.push(val);
3879        }
3880
3881        // Set Self type if we're calling a type-associated function
3882        // Use clone instead of take to preserve for nested calls that don't set a type
3883        let old_self_type = self.current_self_type.clone();
3884        if let Some(type_name) = type_name_for_self {
3885            self.current_self_type = Some(type_name);
3886        }
3887
3888        let result = match func {
3889            Value::Function(f) => self.call_function(&f, arg_values),
3890            Value::BuiltIn(b) => self.call_builtin(&b, arg_values),
3891            // Handle constructor markers for unknown external types
3892            Value::Struct { ref name, .. } if name.starts_with("__constructor__") => {
3893                let actual_type = name.strip_prefix("__constructor__").unwrap();
3894                // Create an empty struct for the unknown type
3895                Ok(Value::Struct {
3896                    name: actual_type.to_string(),
3897                    fields: Rc::new(RefCell::new(HashMap::new())),
3898                })
3899            }
3900            _ => {
3901                crate::sigil_debug!(
3902                    "DEBUG Cannot call non-function: {:?}, expr: {:?}",
3903                    func,
3904                    func_expr
3905                );
3906                Err(RuntimeError::new("Cannot call non-function"))
3907            }
3908        };
3909
3910        // Sync mutable references back to original variables
3911        // This is what makes `fn foo(x: &mut T)` actually modify the caller's variable
3912        for (var_name, ref_val) in mut_ref_sync {
3913            let current_value = ref_val.borrow().clone();
3914            let _ = self.environment.borrow_mut().set(&var_name, current_value);
3915        }
3916
3917        // Restore old Self type
3918        self.current_self_type = old_self_type;
3919
3920        result
3921    }
3922
3923    pub fn call_function(
3924        &mut self,
3925        func: &Function,
3926        args: Vec<Value>,
3927    ) -> Result<Value, RuntimeError> {
3928        // Debug trace for relevant functions
3929        if func.name.as_ref().map_or(false, |n| {
3930            n.contains("read_source")
3931                || n.contains("parse_file")
3932                || n.contains("load_from_file")
3933                || n.contains("read_to_string")
3934        }) {
3935            crate::sigil_debug!(
3936                "DEBUG call_function: name={:?}, params={:?}",
3937                func.name,
3938                func.params
3939            );
3940            for (i, arg) in args.iter().enumerate() {
3941                crate::sigil_debug!("  arg[{}] = {:?}", i, arg);
3942            }
3943        }
3944        if args.len() != func.params.len() {
3945            return Err(RuntimeError::new(format!(
3946                "Expected {} arguments, got {} (func={:?}, params={:?})",
3947                func.params.len(),
3948                args.len(),
3949                func.name,
3950                func.params
3951            )));
3952        }
3953
3954        // Debug: trace calls to keyword_or_ident
3955        if func.params.iter().any(|p| p == "name") {
3956            for arg in &args {
3957                let unwrapped = Self::unwrap_all(arg);
3958                if let Value::String(s) = &unwrapped {
3959                    if s.len() <= 10 {
3960                        crate::sigil_debug!("DEBUG call_function(name='{}')", s);
3961                    }
3962                }
3963            }
3964        }
3965
3966        // Create new environment for function
3967        let env = Rc::new(RefCell::new(Environment::with_parent(func.closure.clone())));
3968
3969        // Bind parameters
3970        for (param, value) in func.params.iter().zip(args) {
3971            // Debug: trace path parameter binding
3972            if param == "path" {
3973                crate::sigil_debug!(
3974                    "DEBUG call_function func={:?} binding param 'path' = {:?}",
3975                    func.name,
3976                    value
3977                );
3978            }
3979            env.borrow_mut().define(param.clone(), value);
3980        }
3981
3982        // Execute function body
3983        let prev_env = self.environment.clone();
3984        self.environment = env;
3985
3986        let result = match self.evaluate(&func.body) {
3987            Ok(val) => Ok(val),
3988            Err(e) if e.message == "return" => {
3989                // Extract return value from stored location
3990                Ok(self.return_value.take().unwrap_or(Value::Null))
3991            }
3992            Err(e) => Err(e),
3993        };
3994
3995        self.environment = prev_env;
3996        result
3997    }
3998
3999    fn call_builtin(
4000        &mut self,
4001        builtin: &BuiltInFn,
4002        args: Vec<Value>,
4003    ) -> Result<Value, RuntimeError> {
4004        if let Some(arity) = builtin.arity {
4005            if args.len() != arity {
4006                return Err(RuntimeError::new(format!(
4007                    "{}() expects {} arguments, got {}",
4008                    builtin.name,
4009                    arity,
4010                    args.len()
4011                )));
4012            }
4013        }
4014        (builtin.func)(self, args)
4015    }
4016
4017    /// Await a value - if it's a future, resolve it; otherwise return as-is
4018    pub fn await_value(&mut self, value: Value) -> Result<Value, RuntimeError> {
4019        match value {
4020            Value::Future(fut) => {
4021                let mut fut_inner = fut.borrow_mut();
4022                self.poll_future(&mut fut_inner)
4023            }
4024            // Non-futures return immediately
4025            other => Ok(other),
4026        }
4027    }
4028
4029    /// Unwrap a Result or Option value with configurable error handling
4030    /// - propagate_errors: if true, return error on Err/None; if false, just unwrap
4031    /// - panic_on_error: if true, panic instead of returning error
4032    fn unwrap_result_or_option(
4033        &self,
4034        value: Value,
4035        propagate_errors: bool,
4036        panic_on_error: bool,
4037    ) -> Result<Value, RuntimeError> {
4038        // First, determine what kind of value we have and extract any inner value
4039        let (is_ok_or_some, is_err, is_none, inner_val) = match &value {
4040            Value::Struct { name, fields } if name == "Ok" || name == "Some" => {
4041                let borrowed = fields.borrow();
4042                let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
4043                (true, false, false, inner)
4044            }
4045            Value::Struct { name, fields } if name == "Err" => {
4046                let borrowed = fields.borrow();
4047                let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
4048                (false, true, false, inner)
4049            }
4050            Value::Struct { name, .. } if name == "None" => (false, false, true, None),
4051            _ => return Ok(value),
4052        };
4053
4054        if is_ok_or_some {
4055            Ok(inner_val.unwrap_or(value))
4056        } else if is_err {
4057            let msg = format!("Error: {:?}", inner_val);
4058            if panic_on_error {
4059                panic!("{}", msg);
4060            } else if propagate_errors {
4061                Err(RuntimeError::new(msg))
4062            } else {
4063                Ok(inner_val.unwrap_or(value))
4064            }
4065        } else if is_none {
4066            if panic_on_error {
4067                panic!("Unwrapped None");
4068            } else if propagate_errors {
4069                Err(RuntimeError::new("Unwrapped None".to_string()))
4070            } else {
4071                Ok(value)
4072            }
4073        } else {
4074            Ok(value)
4075        }
4076    }
4077
4078    /// Poll a future to completion
4079    fn poll_future(&mut self, fut: &mut FutureInner) -> Result<Value, RuntimeError> {
4080        // Check if already resolved
4081        match &fut.state {
4082            FutureState::Ready(v) => return Ok((**v).clone()),
4083            FutureState::Failed(e) => return Err(RuntimeError::new(e.clone())),
4084            _ => {}
4085        }
4086
4087        // Check if it's a timer future
4088        if let Some(complete_at) = fut.complete_at {
4089            if std::time::Instant::now() >= complete_at {
4090                fut.state = FutureState::Ready(Box::new(Value::Null));
4091                return Ok(Value::Null);
4092            } else {
4093                // Timer not complete - in interpreter, we just sleep
4094                let remaining = complete_at - std::time::Instant::now();
4095                std::thread::sleep(remaining);
4096                fut.state = FutureState::Ready(Box::new(Value::Null));
4097                return Ok(Value::Null);
4098            }
4099        }
4100
4101        // Execute computation if pending
4102        if let Some(computation) = fut.computation.take() {
4103            fut.state = FutureState::Running;
4104
4105            match computation {
4106                FutureComputation::Immediate(v) => {
4107                    fut.state = FutureState::Ready(v.clone());
4108                    Ok((*v).clone())
4109                }
4110                FutureComputation::Timer(duration) => {
4111                    // Sleep for the duration
4112                    std::thread::sleep(duration);
4113                    fut.state = FutureState::Ready(Box::new(Value::Null));
4114                    Ok(Value::Null)
4115                }
4116                FutureComputation::Lazy { func, args } => {
4117                    // Execute the function
4118                    match self.call_function(&func, args) {
4119                        Ok(result) => {
4120                            fut.state = FutureState::Ready(Box::new(result.clone()));
4121                            Ok(result)
4122                        }
4123                        Err(e) => {
4124                            fut.state = FutureState::Failed(e.message.clone());
4125                            Err(e)
4126                        }
4127                    }
4128                }
4129                FutureComputation::Join(futures) => {
4130                    // Await all futures and collect results
4131                    let mut results = Vec::new();
4132                    for f in futures {
4133                        let mut f_inner = f.borrow_mut();
4134                        results.push(self.poll_future(&mut f_inner)?);
4135                    }
4136                    let result = Value::Array(Rc::new(RefCell::new(results)));
4137                    fut.state = FutureState::Ready(Box::new(result.clone()));
4138                    Ok(result)
4139                }
4140                FutureComputation::Race(futures) => {
4141                    // Return first completed future
4142                    // In interpreter, just poll in order
4143                    for f in futures {
4144                        let f_inner = f.borrow_mut();
4145                        if matches!(f_inner.state, FutureState::Ready(_)) {
4146                            if let FutureState::Ready(v) = &f_inner.state {
4147                                fut.state = FutureState::Ready(v.clone());
4148                                return Ok((**v).clone());
4149                            }
4150                        }
4151                    }
4152                    // None ready, poll first one
4153                    Err(RuntimeError::new("No futures ready in race"))
4154                }
4155            }
4156        } else {
4157            // No computation - return current state
4158            match &fut.state {
4159                FutureState::Ready(v) => Ok((**v).clone()),
4160                FutureState::Failed(e) => Err(RuntimeError::new(e.clone())),
4161                _ => Err(RuntimeError::new("Future has no computation")),
4162            }
4163        }
4164    }
4165
4166    /// Create a new future from a value
4167    pub fn make_future_immediate(&self, value: Value) -> Value {
4168        Value::Future(Rc::new(RefCell::new(FutureInner {
4169            state: FutureState::Ready(Box::new(value)),
4170            computation: None,
4171            complete_at: None,
4172        })))
4173    }
4174
4175    /// Create a pending future with lazy computation
4176    pub fn make_future_lazy(&self, func: Rc<Function>, args: Vec<Value>) -> Value {
4177        Value::Future(Rc::new(RefCell::new(FutureInner {
4178            state: FutureState::Pending,
4179            computation: Some(FutureComputation::Lazy { func, args }),
4180            complete_at: None,
4181        })))
4182    }
4183
4184    /// Create a timer future
4185    pub fn make_future_timer(&self, duration: std::time::Duration) -> Value {
4186        Value::Future(Rc::new(RefCell::new(FutureInner {
4187            state: FutureState::Pending,
4188            computation: Some(FutureComputation::Timer(duration)),
4189            complete_at: Some(std::time::Instant::now() + duration),
4190        })))
4191    }
4192
4193    fn eval_array(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
4194        let values: Vec<Value> = elements
4195            .iter()
4196            .map(|e| self.evaluate(e))
4197            .collect::<Result<_, _>>()?;
4198        Ok(Value::Array(Rc::new(RefCell::new(values))))
4199    }
4200
4201    fn eval_tuple(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
4202        let values: Vec<Value> = elements
4203            .iter()
4204            .map(|e| self.evaluate(e))
4205            .collect::<Result<_, _>>()?;
4206        Ok(Value::Tuple(Rc::new(values)))
4207    }
4208
4209    fn eval_block(&mut self, block: &Block) -> Result<Value, RuntimeError> {
4210        let env = Rc::new(RefCell::new(Environment::with_parent(
4211            self.environment.clone(),
4212        )));
4213        let prev_env = self.environment.clone();
4214        self.environment = env;
4215
4216        let mut result = Value::Null;
4217
4218        for stmt in &block.stmts {
4219            match stmt {
4220                Stmt::Let { pattern, init, .. } => {
4221                    let value = match init {
4222                        Some(expr) => self.evaluate(expr)?,
4223                        None => Value::Null,
4224                    };
4225                    self.bind_pattern(pattern, value)?;
4226                }
4227                Stmt::LetElse {
4228                    pattern,
4229                    init,
4230                    else_branch,
4231                    ..
4232                } => {
4233                    let value = self.evaluate(init)?;
4234                    // Try to bind pattern, if it fails, execute else branch
4235                    if self.bind_pattern(pattern, value.clone()).is_err() {
4236                        return self.evaluate(else_branch);
4237                    }
4238                }
4239                Stmt::Expr(expr) => {
4240                    result = self.evaluate(expr)?;
4241                }
4242                Stmt::Semi(expr) => {
4243                    self.evaluate(expr)?;
4244                    result = Value::Null;
4245                }
4246                Stmt::Item(item) => {
4247                    self.execute_item(item)?;
4248                }
4249            }
4250        }
4251
4252        if let Some(expr) = &block.expr {
4253            result = self.evaluate(expr)?;
4254        }
4255
4256        // RAII: Call Drop::drop() on values going out of scope
4257        // Collect values to drop (avoid borrowing self during iteration)
4258        let values_to_drop: Vec<(String, Value)> = self
4259            .environment
4260            .borrow()
4261            .values
4262            .iter()
4263            .filter_map(|(name, value)| {
4264                if let Value::Struct {
4265                    name: struct_name, ..
4266                } = value
4267                {
4268                    if self.drop_types.contains(struct_name) {
4269                        return Some((name.clone(), value.clone()));
4270                    }
4271                }
4272                None
4273            })
4274            .collect();
4275
4276        // Call drop on each value
4277        for (_var_name, value) in values_to_drop {
4278            if let Value::Struct {
4279                name: struct_name, ..
4280            } = &value
4281            {
4282                let drop_fn_name = format!("{}·drop", struct_name);
4283                // Clone the function out of globals to avoid borrow issues
4284                let drop_fn = self.globals.borrow().get(&drop_fn_name).map(|v| v.clone());
4285                if let Some(Value::Function(f)) = drop_fn {
4286                    // Call drop(self) - the value is passed as self
4287                    let _ = self.call_function(&f, vec![value.clone()]);
4288                }
4289            }
4290        }
4291
4292        self.environment = prev_env;
4293        Ok(result)
4294    }
4295
4296    fn bind_pattern(&mut self, pattern: &Pattern, value: Value) -> Result<(), RuntimeError> {
4297        match pattern {
4298            Pattern::Ident { name, .. } => {
4299                // Don't bind "_" - it's a wildcard in identifier form
4300                if name.name != "_" {
4301                    // Debug: trace path binding
4302                    if name.name == "path" {
4303                        crate::sigil_debug!("DEBUG bind_pattern: binding 'path' = {:?}", value);
4304                    }
4305                    self.environment
4306                        .borrow_mut()
4307                        .define(name.name.clone(), value);
4308                }
4309                Ok(())
4310            }
4311            Pattern::Tuple(patterns) => {
4312                // Unwrap evidential wrappers first
4313                let unwrapped = Self::unwrap_all(&value);
4314                crate::sigil_debug!(
4315                    "DEBUG bind_pattern Tuple: patterns.len()={}, value type={:?}",
4316                    patterns.len(),
4317                    std::mem::discriminant(&unwrapped)
4318                );
4319                match unwrapped {
4320                    Value::Tuple(values) => {
4321                        if patterns.len() != values.len() {
4322                            return Err(RuntimeError::new("Tuple pattern size mismatch"));
4323                        }
4324                        for (i, (p, v)) in patterns.iter().zip(values.iter()).enumerate() {
4325                            crate::sigil_debug!(
4326                                "DEBUG   binding tuple element {}: {:?} = {}",
4327                                i,
4328                                p,
4329                                self.format_value(v)
4330                            );
4331                            self.bind_pattern(p, v.clone())?;
4332                        }
4333                        Ok(())
4334                    }
4335                    Value::Null => {
4336                        // Null value during iteration - treat as end of iteration (no binding)
4337                        Ok(())
4338                    }
4339                    Value::Array(arr) if arr.borrow().len() == patterns.len() => {
4340                        // Allow array to be destructured as tuple
4341                        let vals = arr.borrow();
4342                        for (p, v) in patterns.iter().zip(vals.iter()) {
4343                            self.bind_pattern(p, v.clone())?;
4344                        }
4345                        Ok(())
4346                    }
4347                    _ => Err(RuntimeError::new("Expected tuple")),
4348                }
4349            }
4350            Pattern::Wildcard => Ok(()),
4351            Pattern::Struct { path, fields, .. } => {
4352                // Unwrap any wrappers first
4353                let unwrapped = Self::unwrap_all(&value);
4354                // Bind each field from the struct or variant
4355                match &unwrapped {
4356                    Value::Struct {
4357                        fields: struct_fields,
4358                        ..
4359                    } => {
4360                        for field_pat in fields {
4361                            let field_name = &field_pat.name.name;
4362                            // Get field value or default to Null for missing optional fields
4363                            let field_val = struct_fields
4364                                .borrow()
4365                                .get(field_name)
4366                                .cloned()
4367                                .unwrap_or(Value::Null);
4368                            if let Some(pat) = &field_pat.pattern {
4369                                self.bind_pattern(pat, field_val)?;
4370                            } else {
4371                                // Shorthand: foo: foo - bind to same name
4372                                self.environment
4373                                    .borrow_mut()
4374                                    .define(field_name.clone(), field_val);
4375                            }
4376                        }
4377                        Ok(())
4378                    }
4379                    Value::Variant {
4380                        enum_name,
4381                        variant_name,
4382                        fields: variant_fields,
4383                    } => {
4384                        // Handle struct-like enum variants (e.g., IrPattern::Ident { name, .. })
4385                        let pattern_variant = path
4386                            .segments
4387                            .last()
4388                            .map(|s| s.ident.name.as_str())
4389                            .unwrap_or("");
4390                        if pattern_variant == variant_name
4391                            || path.segments.iter().any(|s| s.ident.name == *variant_name)
4392                        {
4393                            // Variant fields are stored as a Vec, but we need to map by name
4394                            // For struct-like variants, the fields should be a Struct value with field names
4395                            if let Some(inner_fields) = variant_fields {
4396                                if inner_fields.len() == 1 {
4397                                    // Single wrapped struct with named fields
4398                                    if let Value::Struct {
4399                                        fields: inner_struct,
4400                                        ..
4401                                    } = &inner_fields[0]
4402                                    {
4403                                        for field_pat in fields {
4404                                            let field_name = &field_pat.name.name;
4405                                            // Default to Null for missing optional fields
4406                                            let field_val = inner_struct
4407                                                .borrow()
4408                                                .get(field_name)
4409                                                .cloned()
4410                                                .unwrap_or(Value::Null);
4411                                            if let Some(pat) = &field_pat.pattern {
4412                                                self.bind_pattern(pat, field_val)?;
4413                                            } else {
4414                                                self.environment
4415                                                    .borrow_mut()
4416                                                    .define(field_name.clone(), field_val);
4417                                            }
4418                                        }
4419                                        return Ok(());
4420                                    }
4421                                }
4422                                // Named field lookup from variant's field map
4423                                // Variants store struct fields as named HashMap inside the variant
4424                                for field_pat in fields {
4425                                    let field_name = &field_pat.name.name;
4426                                    // Look for a field with matching name in variant fields
4427                                    // Variant fields might be stored in order or as a struct
4428                                    // For now, search by name if we can find it
4429                                    let field_val = inner_fields.iter().find_map(|f| {
4430                                        if let Value::Struct { fields: fs, .. } = f {
4431                                            fs.borrow().get(field_name).cloned()
4432                                        } else {
4433                                            None
4434                                        }
4435                                    });
4436                                    if let Some(val) = field_val {
4437                                        if let Some(pat) = &field_pat.pattern {
4438                                            self.bind_pattern(pat, val)?;
4439                                        } else {
4440                                            self.environment
4441                                                .borrow_mut()
4442                                                .define(field_name.clone(), val);
4443                                        }
4444                                    }
4445                                }
4446                            }
4447                            Ok(())
4448                        } else {
4449                            crate::sigil_debug!(
4450                                "DEBUG variant name mismatch: pattern={}, actual={}",
4451                                pattern_variant,
4452                                variant_name
4453                            );
4454                            Err(RuntimeError::new(format!(
4455                                "Variant name mismatch: expected {} but got {}::{}",
4456                                pattern_variant, enum_name, variant_name
4457                            )))
4458                        }
4459                    }
4460                    _ => {
4461                        crate::sigil_debug!(
4462                            "DEBUG struct pattern bind: expected struct/variant but got {:?}",
4463                            std::mem::discriminant(&unwrapped)
4464                        );
4465                        Err(RuntimeError::new(
4466                            "Expected struct or variant value for struct pattern",
4467                        ))
4468                    }
4469                }
4470            }
4471            Pattern::Path(_path) => {
4472                // Path patterns like Result::Ok - unit variant patterns
4473                // Don't bind anything
4474                Ok(())
4475            }
4476            Pattern::TupleStruct { path, fields } => {
4477                // Enum variant with fields: Result::Ok(value)
4478                // Unwrap any refs first
4479                let unwrapped = Self::unwrap_all(&value);
4480                let path_str = path
4481                    .segments
4482                    .iter()
4483                    .map(|s| s.ident.name.as_str())
4484                    .collect::<Vec<_>>()
4485                    .join("::");
4486                crate::sigil_debug!(
4487                    "DEBUG bind_pattern TupleStruct: path={}, value type={:?}",
4488                    path_str,
4489                    std::mem::discriminant(&unwrapped)
4490                );
4491                if let Value::Variant {
4492                    variant_name,
4493                    fields: variant_fields,
4494                    enum_name,
4495                } = &unwrapped
4496                {
4497                    crate::sigil_debug!(
4498                        "DEBUG   Variant {}::{}, fields={}",
4499                        enum_name,
4500                        variant_name,
4501                        if variant_fields.is_some() {
4502                            format!("Some(len={})", variant_fields.as_ref().unwrap().len())
4503                        } else {
4504                            "None".to_string()
4505                        }
4506                    );
4507                    let pattern_variant = path
4508                        .segments
4509                        .last()
4510                        .map(|s| s.ident.name.as_str())
4511                        .unwrap_or("");
4512                    if pattern_variant == variant_name {
4513                        // Unwrap fields and bind
4514                        if let Some(inner_fields) = variant_fields {
4515                            if fields.len() == 1 && inner_fields.len() == 1 {
4516                                self.bind_pattern(&fields[0], inner_fields[0].clone())?;
4517                            } else {
4518                                for (pat, val) in fields.iter().zip(inner_fields.iter()) {
4519                                    self.bind_pattern(pat, val.clone())?;
4520                                }
4521                            }
4522                        } else if !fields.is_empty() {
4523                            // Pattern expects fields but variant has none
4524                            crate::sigil_debug!(
4525                                "DEBUG TupleStruct: pattern expects {} fields but variant has none",
4526                                fields.len()
4527                            );
4528                        }
4529                    }
4530                    Ok(())
4531                } else {
4532                    // Maybe it's a regular tuple being matched
4533                    if let Value::Tuple(tuple_vals) = &value {
4534                        for (pat, val) in fields.iter().zip(tuple_vals.iter()) {
4535                            self.bind_pattern(pat, val.clone())?;
4536                        }
4537                        Ok(())
4538                    } else {
4539                        Err(RuntimeError::new(
4540                            "Expected variant or tuple for tuple struct pattern",
4541                        ))
4542                    }
4543                }
4544            }
4545            Pattern::Literal(_) => {
4546                // Literal patterns don't bind anything, just match
4547                Ok(())
4548            }
4549            Pattern::Rest => {
4550                // Rest pattern .. - just ignores rest of values
4551                Ok(())
4552            }
4553            Pattern::Range { .. } => {
4554                // Range patterns like 'a'..='z' don't bind anything
4555                Ok(())
4556            }
4557            Pattern::Or(patterns) => {
4558                // Or patterns - find the matching pattern and bind its variables
4559                for p in patterns {
4560                    if self.pattern_matches(p, &value)? {
4561                        return self.bind_pattern(p, value.clone());
4562                    }
4563                }
4564                // No pattern matched - this shouldn't happen if pattern_matches returned true earlier
4565                Err(RuntimeError::new("Or pattern didn't match any alternative"))
4566            }
4567            _ => Err(RuntimeError::new(format!(
4568                "Unsupported pattern: {:?}",
4569                pattern
4570            ))),
4571        }
4572    }
4573
4574    fn eval_if(
4575        &mut self,
4576        condition: &Expr,
4577        then_branch: &Block,
4578        else_branch: &Option<Box<Expr>>,
4579    ) -> Result<Value, RuntimeError> {
4580        let cond = self.evaluate(condition)?;
4581        if self.is_truthy(&cond) {
4582            self.eval_block(then_branch)
4583        } else if let Some(else_expr) = else_branch {
4584            self.evaluate(else_expr)
4585        } else {
4586            Ok(Value::Null)
4587        }
4588    }
4589
4590    fn eval_match(&mut self, expr: &Expr, arms: &[MatchArm]) -> Result<Value, RuntimeError> {
4591        let value = self.evaluate(expr)?;
4592
4593        // Debug all string matches to find keyword_or_ident
4594        let unwrapped = Self::unwrap_all(&value);
4595        if let Value::String(s) = &unwrapped {
4596            if s.len() <= 10 {
4597                crate::sigil_debug!("DEBUG eval_match: string='{}', arms={}", s, arms.len());
4598            }
4599        }
4600
4601        for arm in arms {
4602            if self.pattern_matches(&arm.pattern, &value)? {
4603                // Create new environment for pattern bindings
4604                let env = Rc::new(RefCell::new(Environment::with_parent(
4605                    self.environment.clone(),
4606                )));
4607                let prev_env = self.environment.clone();
4608                self.environment = env;
4609
4610                // Bind pattern variables FIRST (before evaluating guard)
4611                // This is necessary for guards like `?fields if !fields.is_empty()`
4612                if let Err(e) = self.bind_pattern(&arm.pattern, value.clone()) {
4613                    self.environment = prev_env;
4614                    return Err(e);
4615                }
4616
4617                // Check guard if present (pattern vars are now in scope)
4618                if let Some(guard) = &arm.guard {
4619                    let guard_val = self.evaluate(guard)?;
4620                    if !self.is_truthy(&guard_val) {
4621                        // Guard failed - restore environment and try next arm
4622                        self.environment = prev_env;
4623                        continue;
4624                    }
4625                }
4626
4627                // Pattern matched and guard passed - evaluate body
4628                let result = self.evaluate(&arm.body);
4629
4630                self.environment = prev_env;
4631                return result;
4632            }
4633        }
4634
4635        // Debug: show what value we're trying to match with discriminant
4636        crate::sigil_debug!(
4637            "DEBUG No matching pattern for value: {} (discriminant: {:?})",
4638            self.format_value(&value),
4639            std::mem::discriminant(&value)
4640        );
4641        // Also show the arms
4642        for (i, arm) in arms.iter().enumerate() {
4643            crate::sigil_debug!("DEBUG   arm {}: {:?}", i, arm.pattern);
4644        }
4645        Err(RuntimeError::new(format!(
4646            "No matching pattern for {}",
4647            self.format_value(&value)
4648        )))
4649    }
4650
4651    fn pattern_matches(&mut self, pattern: &Pattern, value: &Value) -> Result<bool, RuntimeError> {
4652        // Unwrap evidential/affective/ref wrappers from value
4653        let value = Self::unwrap_all(value);
4654
4655        // Debug string pattern matching
4656        if let Value::String(s) = &value {
4657            if **s == "fn" {
4658                crate::sigil_debug!("DEBUG pattern_matches: value='fn', pattern={:?}", pattern);
4659            }
4660        }
4661
4662        match (pattern, &value) {
4663            (Pattern::Wildcard, _) => Ok(true),
4664            // Pattern::Ident with evidentiality - ?g matches Some/non-null, !g matches Known values
4665            (
4666                Pattern::Ident {
4667                    evidentiality: Some(Evidentiality::Uncertain),
4668                    name,
4669                    ..
4670                },
4671                val,
4672            ) => {
4673                // ?g pattern should match non-null values (i.e., Option::Some)
4674                let matches = match val {
4675                    Value::Null => false,
4676                    Value::Variant { variant_name, .. } if variant_name == "None" => false,
4677                    _ => true,
4678                };
4679                crate::sigil_debug!(
4680                    "DEBUG pattern_matches ?{}: value={} => {}",
4681                    name.name,
4682                    self.format_value(val),
4683                    matches
4684                );
4685                Ok(matches)
4686            }
4687            (Pattern::Ident { .. }, _) => Ok(true),
4688            (Pattern::Literal(lit), val) => {
4689                let lit_val = self.eval_literal(lit)?;
4690                let result = self.values_equal(&lit_val, val);
4691                // Debug null pattern matching specifically
4692                if matches!(lit, Literal::Null) || matches!(val, Value::Null) {
4693                    crate::sigil_debug!(
4694                        "DEBUG literal pattern: lit={:?}, lit_val={}, val={}, result={}",
4695                        lit,
4696                        self.format_value(&lit_val),
4697                        self.format_value(val),
4698                        result
4699                    );
4700                }
4701                Ok(result)
4702            }
4703            (Pattern::Tuple(patterns), Value::Tuple(values)) => {
4704                if patterns.len() != values.len() {
4705                    return Ok(false);
4706                }
4707                for (p, v) in patterns.iter().zip(values.iter()) {
4708                    if !self.pattern_matches(p, v)? {
4709                        return Ok(false);
4710                    }
4711                }
4712                Ok(true)
4713            }
4714            // Path pattern - matches unit enum variants like CompileMode::Compile
4715            (
4716                Pattern::Path(path),
4717                Value::Variant {
4718                    variant_name,
4719                    fields,
4720                    ..
4721                },
4722            ) => {
4723                let pattern_variant = path
4724                    .segments
4725                    .last()
4726                    .map(|s| s.ident.name.as_str())
4727                    .unwrap_or("");
4728                // Match if variant name matches and has no fields
4729                Ok(pattern_variant == variant_name && fields.is_none())
4730            }
4731            // TupleStruct pattern - matches enum variants with data like Result::Ok(x)
4732            (
4733                Pattern::TupleStruct {
4734                    path,
4735                    fields: pat_fields,
4736                },
4737                Value::Variant {
4738                    variant_name,
4739                    fields,
4740                    ..
4741                },
4742            ) => {
4743                let pattern_variant = path
4744                    .segments
4745                    .last()
4746                    .map(|s| s.ident.name.as_str())
4747                    .unwrap_or("");
4748                if pattern_variant != variant_name {
4749                    return Ok(false);
4750                }
4751                // Match field patterns
4752                if let Some(variant_fields) = fields {
4753                    if pat_fields.len() != variant_fields.len() {
4754                        return Ok(false);
4755                    }
4756                    for (p, v) in pat_fields.iter().zip(variant_fields.iter()) {
4757                        if !self.pattern_matches(p, v)? {
4758                            return Ok(false);
4759                        }
4760                    }
4761                    Ok(true)
4762                } else {
4763                    // Variant has no fields but pattern expects some
4764                    Ok(pat_fields.is_empty())
4765                }
4766            }
4767            // Struct pattern - matches struct values
4768            (
4769                Pattern::Struct {
4770                    path,
4771                    fields: pat_fields,
4772                    rest,
4773                },
4774                Value::Struct {
4775                    name: struct_name,
4776                    fields: struct_fields,
4777                },
4778            ) => {
4779                let pattern_name = path
4780                    .segments
4781                    .iter()
4782                    .map(|s| s.ident.name.as_str())
4783                    .collect::<Vec<_>>()
4784                    .join("::");
4785                if pattern_name != *struct_name {
4786                    return Ok(false);
4787                }
4788                // Check each field in the pattern
4789                let borrowed = struct_fields.borrow();
4790                for field_pat in pat_fields {
4791                    let field_name = &field_pat.name.name;
4792                    if let Some(field_val) = borrowed.get(field_name) {
4793                        if let Some(sub_pat) = &field_pat.pattern {
4794                            if !self.pattern_matches(sub_pat, field_val)? {
4795                                return Ok(false);
4796                            }
4797                        }
4798                        // If no sub-pattern, any value matches
4799                    } else if !rest {
4800                        // Field not found and no rest pattern
4801                        return Ok(false);
4802                    }
4803                }
4804                Ok(true)
4805            }
4806            // Struct pattern - matches struct-like enum variants (e.g., TypeExpr::Evidential { inner, ... })
4807            (
4808                Pattern::Struct {
4809                    path,
4810                    fields: pat_fields,
4811                    rest,
4812                },
4813                Value::Variant {
4814                    variant_name,
4815                    fields: variant_fields,
4816                    ..
4817                },
4818            ) => {
4819                let pattern_variant = path
4820                    .segments
4821                    .last()
4822                    .map(|s| s.ident.name.as_str())
4823                    .unwrap_or("");
4824                if pattern_variant != variant_name {
4825                    return Ok(false);
4826                }
4827                // Struct-like variants store fields as a single wrapped Struct value
4828                if let Some(inner_fields) = variant_fields {
4829                    if inner_fields.len() == 1 {
4830                        if let Value::Struct {
4831                            fields: inner_struct,
4832                            ..
4833                        } = &inner_fields[0]
4834                        {
4835                            let borrowed = inner_struct.borrow();
4836                            for field_pat in pat_fields {
4837                                let field_name = &field_pat.name.name;
4838                                if let Some(field_val) = borrowed.get(field_name) {
4839                                    if let Some(sub_pat) = &field_pat.pattern {
4840                                        if !self.pattern_matches(sub_pat, field_val)? {
4841                                            return Ok(false);
4842                                        }
4843                                    }
4844                                } else if !rest {
4845                                    return Ok(false);
4846                                }
4847                            }
4848                            return Ok(true);
4849                        }
4850                    }
4851                }
4852                // No fields or structure doesn't match
4853                Ok(pat_fields.is_empty() || *rest)
4854            }
4855            // Or pattern - match if any sub-pattern matches
4856            (Pattern::Or(patterns), val) => {
4857                for p in patterns {
4858                    if self.pattern_matches(p, val)? {
4859                        return Ok(true);
4860                    }
4861                }
4862                Ok(false)
4863            }
4864            // Rest pattern always matches
4865            (Pattern::Rest, _) => Ok(true),
4866            // Range pattern: 'a'..='z' or 0..=9
4867            (
4868                Pattern::Range {
4869                    start,
4870                    end,
4871                    inclusive,
4872                },
4873                val,
4874            ) => {
4875                // Helper to extract char from pattern
4876                let extract_char = |pat: &Option<Box<Pattern>>| -> Option<char> {
4877                    match pat {
4878                        Some(p) => match p.as_ref() {
4879                            Pattern::Literal(Literal::Char(c)) => Some(*c),
4880                            _ => None,
4881                        },
4882                        None => None,
4883                    }
4884                };
4885                // Helper to extract int from pattern
4886                let extract_int = |pat: &Option<Box<Pattern>>| -> Option<i64> {
4887                    match pat {
4888                        Some(p) => match p.as_ref() {
4889                            Pattern::Literal(Literal::Int { value, .. }) => value.parse().ok(),
4890                            _ => None,
4891                        },
4892                        None => None,
4893                    }
4894                };
4895
4896                match val {
4897                    Value::Char(c) => {
4898                        let start_val = extract_char(start);
4899                        let end_val = extract_char(end);
4900                        let in_range = match (start_val, end_val, *inclusive) {
4901                            (Some(s), Some(e), true) => *c >= s && *c <= e,
4902                            (Some(s), Some(e), false) => *c >= s && *c < e,
4903                            (Some(s), None, _) => *c >= s,
4904                            (None, Some(e), true) => *c <= e,
4905                            (None, Some(e), false) => *c < e,
4906                            (None, None, _) => true,
4907                        };
4908                        Ok(in_range)
4909                    }
4910                    Value::Int(i) => {
4911                        let start_val = extract_int(start);
4912                        let end_val = extract_int(end);
4913                        let in_range = match (start_val, end_val, *inclusive) {
4914                            (Some(s), Some(e), true) => *i >= s && *i <= e,
4915                            (Some(s), Some(e), false) => *i >= s && *i < e,
4916                            (Some(s), None, _) => *i >= s,
4917                            (None, Some(e), true) => *i <= e,
4918                            (None, Some(e), false) => *i < e,
4919                            (None, None, _) => true,
4920                        };
4921                        Ok(in_range)
4922                    }
4923                    _ => Ok(false),
4924                }
4925            }
4926            // Literal matching against string or char
4927            (Pattern::Literal(Literal::String(s)), Value::String(vs)) => Ok(s == vs.as_str()),
4928            (Pattern::Literal(Literal::Char(c)), Value::Char(vc)) => Ok(c == vc),
4929            _ => Ok(false),
4930        }
4931    }
4932
4933    fn values_equal(&self, a: &Value, b: &Value) -> bool {
4934        // Unwrap any Ref wrappers before comparison
4935        let a_unwrapped = match a {
4936            Value::Ref(r) => r.borrow().clone(),
4937            _ => a.clone(),
4938        };
4939        let b_unwrapped = match b {
4940            Value::Ref(r) => r.borrow().clone(),
4941            _ => b.clone(),
4942        };
4943        match (&a_unwrapped, &b_unwrapped) {
4944            (Value::Null, Value::Null) => true,
4945            (Value::Bool(a), Value::Bool(b)) => a == b,
4946            (Value::Int(a), Value::Int(b)) => a == b,
4947            (Value::Float(a), Value::Float(b)) => (a - b).abs() < f64::EPSILON,
4948            (Value::String(a), Value::String(b)) => {
4949                let result = **a == **b;
4950                // Debug ALL short string comparisons
4951                if a.len() <= 5 && b.len() <= 5 {
4952                    crate::sigil_debug!("DEBUG values_equal: '{}' == '{}' -> {}", a, b, result);
4953                }
4954                result
4955            }
4956            (Value::Char(a), Value::Char(b)) => a == b,
4957            _ => false,
4958        }
4959    }
4960
4961    fn eval_for(
4962        &mut self,
4963        pattern: &Pattern,
4964        iter: &Expr,
4965        body: &Block,
4966    ) -> Result<Value, RuntimeError> {
4967        let iterable_raw = self.evaluate(iter)?;
4968        let iterable = Self::unwrap_all(&iterable_raw);
4969        let items = match iterable {
4970            Value::Array(arr) => arr.borrow().clone(),
4971            Value::Tuple(t) => (*t).clone(),
4972            Value::String(s) => s.chars().map(Value::Char).collect(),
4973            Value::Map(m) => {
4974                // Iterate over key-value pairs as tuples
4975                m.borrow()
4976                    .iter()
4977                    .map(|(k, v)| {
4978                        Value::Tuple(Rc::new(vec![Value::String(Rc::new(k.clone())), v.clone()]))
4979                    })
4980                    .collect()
4981            }
4982            Value::Variant {
4983                fields: Some(f), ..
4984            } => (*f).clone(),
4985            _ => {
4986                return Err(RuntimeError::new(format!(
4987                    "Cannot iterate over non-iterable: {:?}",
4988                    iterable_raw
4989                )))
4990            }
4991        };
4992
4993        let mut result = Value::Null;
4994        for item in items {
4995            let env = Rc::new(RefCell::new(Environment::with_parent(
4996                self.environment.clone(),
4997            )));
4998            let prev_env = self.environment.clone();
4999            self.environment = env;
5000
5001            self.bind_pattern(pattern, item)?;
5002
5003            match self.eval_block(body) {
5004                Ok(val) => result = val,
5005                Err(e) if e.message == "break" => {
5006                    self.environment = prev_env;
5007                    break;
5008                }
5009                Err(e) if e.message == "continue" => {
5010                    self.environment = prev_env;
5011                    continue;
5012                }
5013                Err(e) => {
5014                    self.environment = prev_env;
5015                    return Err(e);
5016                }
5017            }
5018
5019            self.environment = prev_env;
5020        }
5021
5022        Ok(result)
5023    }
5024
5025    fn eval_while(&mut self, condition: &Expr, body: &Block) -> Result<Value, RuntimeError> {
5026        let mut result = Value::Null;
5027        loop {
5028            let cond = self.evaluate(condition)?;
5029            if !self.is_truthy(&cond) {
5030                break;
5031            }
5032
5033            match self.eval_block(body) {
5034                Ok(val) => result = val,
5035                Err(e) if e.message == "break" => break,
5036                Err(e) if e.message == "continue" => continue,
5037                Err(e) => return Err(e),
5038            }
5039        }
5040        Ok(result)
5041    }
5042
5043    fn eval_loop(&mut self, body: &Block) -> Result<Value, RuntimeError> {
5044        loop {
5045            match self.eval_block(body) {
5046                Ok(_) => {}
5047                Err(e) if e.message == "break" => break,
5048                Err(e) if e.message == "continue" => continue,
5049                Err(e) => return Err(e),
5050            }
5051        }
5052        Ok(Value::Null)
5053    }
5054
5055    fn eval_return(&mut self, value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
5056        let val = match value {
5057            Some(expr) => self.evaluate(expr)?,
5058            None => Value::Null,
5059        };
5060        // Store return value for call_function to retrieve
5061        self.return_value = Some(val);
5062        Err(RuntimeError::new("return"))
5063    }
5064
5065    fn eval_break(&mut self, _value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
5066        // TODO: break with value for loop expressions
5067        Err(RuntimeError::new("break"))
5068    }
5069
5070    fn eval_index(&mut self, expr: &Expr, index: &Expr) -> Result<Value, RuntimeError> {
5071        let collection = self.evaluate(expr)?;
5072
5073        // Dereference Ref values to get the underlying collection
5074        let collection = match collection {
5075            Value::Ref(r) => r.borrow().clone(),
5076            other => other,
5077        };
5078
5079        // Handle range slicing before evaluating the index
5080        if let Expr::Range {
5081            start,
5082            end,
5083            inclusive,
5084        } = index
5085        {
5086            let start_val = match start {
5087                Some(e) => match self.evaluate(e)? {
5088                    Value::Int(n) => n as usize,
5089                    _ => return Err(RuntimeError::new("Slice start must be an integer")),
5090                },
5091                None => 0,
5092            };
5093
5094            return match &collection {
5095                Value::Array(arr) => {
5096                    let arr = arr.borrow();
5097                    let len = arr.len();
5098                    let end_val = match end {
5099                        Some(e) => match self.evaluate(e)? {
5100                            Value::Int(n) => {
5101                                let n = n as usize;
5102                                if *inclusive {
5103                                    n + 1
5104                                } else {
5105                                    n
5106                                }
5107                            }
5108                            _ => return Err(RuntimeError::new("Slice end must be an integer")),
5109                        },
5110                        None => len, // Open-ended range: slice to end
5111                    };
5112                    let end_val = end_val.min(len);
5113                    let start_val = start_val.min(len);
5114                    let sliced: Vec<Value> = arr[start_val..end_val].to_vec();
5115                    Ok(Value::Array(Rc::new(RefCell::new(sliced))))
5116                }
5117                Value::String(s) => {
5118                    let len = s.len();
5119                    let end_val = match end {
5120                        Some(e) => match self.evaluate(e)? {
5121                            Value::Int(n) => {
5122                                let n = n as usize;
5123                                if *inclusive {
5124                                    n + 1
5125                                } else {
5126                                    n
5127                                }
5128                            }
5129                            _ => return Err(RuntimeError::new("Slice end must be an integer")),
5130                        },
5131                        None => len, // Open-ended range: slice to end
5132                    };
5133                    let end_val = end_val.min(len);
5134                    let start_val = start_val.min(len);
5135                    // Use byte slicing for consistency with char_at
5136                    let sliced = &s[start_val..end_val];
5137                    Ok(Value::String(Rc::new(sliced.to_string())))
5138                }
5139                _ => Err(RuntimeError::new("Cannot slice this type")),
5140            };
5141        }
5142
5143        let idx = self.evaluate(index)?;
5144
5145        match (collection, idx) {
5146            (Value::Array(arr), Value::Int(i)) => {
5147                let arr = arr.borrow();
5148                let i = if i < 0 { arr.len() as i64 + i } else { i } as usize;
5149                let result = arr
5150                    .get(i)
5151                    .cloned()
5152                    .ok_or_else(|| RuntimeError::new("Index out of bounds"));
5153                if let Ok(ref v) = result {
5154                    crate::sigil_debug!(
5155                        "DEBUG eval_index: arr[{}] = {:?}",
5156                        i,
5157                        std::mem::discriminant(v)
5158                    );
5159                }
5160                result
5161            }
5162            (Value::Tuple(t), Value::Int(i)) => {
5163                let i = if i < 0 { t.len() as i64 + i } else { i } as usize;
5164                t.get(i)
5165                    .cloned()
5166                    .ok_or_else(|| RuntimeError::new("Index out of bounds"))
5167            }
5168            (Value::String(s), Value::Int(i)) => {
5169                let i = if i < 0 { s.len() as i64 + i } else { i } as usize;
5170                s.chars()
5171                    .nth(i)
5172                    .map(Value::Char)
5173                    .ok_or_else(|| RuntimeError::new("Index out of bounds"))
5174            }
5175            // Handle open-ended range slicing (from eval_range returning tuple)
5176            (Value::Array(arr), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
5177                let arr = arr.borrow();
5178                let start = match &range_tuple[0] {
5179                    Value::Int(n) => *n as usize,
5180                    _ => return Err(RuntimeError::new("Range start must be integer")),
5181                };
5182                let end = match &range_tuple[1] {
5183                    Value::Null => arr.len(), // Open end - slice to end
5184                    Value::Int(n) => *n as usize,
5185                    _ => return Err(RuntimeError::new("Range end must be integer or None")),
5186                };
5187                let start = start.min(arr.len());
5188                let end = end.min(arr.len());
5189                let sliced: Vec<Value> = arr[start..end].to_vec();
5190                Ok(Value::Array(Rc::new(RefCell::new(sliced))))
5191            }
5192            (Value::String(s), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
5193                let start = match &range_tuple[0] {
5194                    Value::Int(n) => *n as usize,
5195                    _ => return Err(RuntimeError::new("Range start must be integer")),
5196                };
5197                let end = match &range_tuple[1] {
5198                    Value::Null => s.len(), // Open end - slice to end
5199                    Value::Int(n) => *n as usize,
5200                    _ => return Err(RuntimeError::new("Range end must be integer or None")),
5201                };
5202                let start = start.min(s.len());
5203                let end = end.min(s.len());
5204                let sliced = &s[start..end];
5205                Ok(Value::String(Rc::new(sliced.to_string())))
5206            }
5207            (coll, idx) => {
5208                crate::sigil_debug!(
5209                    "DEBUG Cannot index: collection={:?}, index={:?}",
5210                    std::mem::discriminant(&coll),
5211                    std::mem::discriminant(&idx)
5212                );
5213                Err(RuntimeError::new("Cannot index"))
5214            }
5215        }
5216    }
5217
5218    fn eval_field(&mut self, expr: &Expr, field: &Ident) -> Result<Value, RuntimeError> {
5219        if field.name == "items" {
5220            crate::sigil_debug!("DEBUG eval_field: accessing .items on expr={:?}", expr);
5221        }
5222        // Debug evidence field access
5223        if field.name == "evidence" {
5224            crate::sigil_debug!("DEBUG eval_field: accessing .evidence");
5225        }
5226        let value = self.evaluate(expr)?;
5227        if field.name == "items" {
5228            crate::sigil_debug!(
5229                "DEBUG eval_field: .items receiver value={:?}",
5230                std::mem::discriminant(&value)
5231            );
5232        }
5233        if field.name == "evidence" {
5234            crate::sigil_debug!(
5235                "DEBUG eval_field: .evidence receiver value type={:?}",
5236                std::mem::discriminant(&value)
5237            );
5238        }
5239        // Helper to get field from a value
5240        fn get_field(val: &Value, field_name: &str) -> Result<Value, RuntimeError> {
5241            // Debug all field access on IrPattern
5242            if field_name == "evidence" {
5243                crate::sigil_debug!(
5244                    "DEBUG get_field 'evidence' on value type: {:?}",
5245                    std::mem::discriminant(val)
5246                );
5247            }
5248            match val {
5249                Value::Struct { name, fields } => {
5250                    let field_val = fields.borrow().get(field_name).cloned();
5251                    if field_val.is_none() && field_name == "path" {
5252                        crate::sigil_debug!(
5253                            "DEBUG Unknown field 'path': struct={}, available={:?}",
5254                            name,
5255                            fields.borrow().keys().collect::<Vec<_>>()
5256                        );
5257                    }
5258                    // Debug evidence field access
5259                    if field_name == "evidence" || name.contains("IrPattern") {
5260                        crate::sigil_debug!("DEBUG get_field on Struct: name={}, field={}, available={:?}, found={}",
5261                            name, field_name, fields.borrow().keys().collect::<Vec<_>>(), field_val.is_some());
5262                    }
5263                    // Fallback for unknown fields on external types: return null
5264                    match field_val {
5265                        Some(v) => Ok(v),
5266                        None => {
5267                            crate::sigil_warn!(
5268                                "WARN: Unknown field '{}' on '{}' - returning null",
5269                                field_name,
5270                                name
5271                            );
5272                            Ok(Value::Null)
5273                        }
5274                    }
5275                }
5276                Value::Tuple(t) => {
5277                    // Tuple field access like .0, .1
5278                    let idx: usize = field_name
5279                        .parse()
5280                        .map_err(|_| RuntimeError::new("Invalid tuple index"))?;
5281                    t.get(idx)
5282                        .cloned()
5283                        .ok_or_else(|| RuntimeError::new("Tuple index out of bounds"))
5284                }
5285                Value::Ref(r) => {
5286                    // Dereference and access field on inner value
5287                    get_field(&r.borrow(), field_name)
5288                }
5289                Value::Evidential { value, .. } => {
5290                    // Unwrap evidential wrapper and access field
5291                    get_field(value, field_name)
5292                }
5293                Value::Affective { value, .. } => {
5294                    // Unwrap affective wrapper and access field
5295                    get_field(value, field_name)
5296                }
5297                Value::Variant {
5298                    fields: variant_fields,
5299                    ..
5300                } => {
5301                    // Handle struct-like enum variants (e.g., IrPattern::Ident { name, evidence, .. })
5302                    // Variant fields may be stored as a Struct value or as positional values
5303                    if let Some(inner_fields) = variant_fields {
5304                        // Try to find a Struct value that contains the field
5305                        for f in inner_fields.iter() {
5306                            if let Value::Struct {
5307                                fields: struct_fields,
5308                                ..
5309                            } = f
5310                            {
5311                                if let Some(field_val) =
5312                                    struct_fields.borrow().get(field_name).cloned()
5313                                {
5314                                    return Ok(field_val);
5315                                }
5316                            }
5317                        }
5318                        // Field not found in any struct - return Null for optional fields
5319                        Ok(Value::Null)
5320                    } else {
5321                        // No fields in variant
5322                        Ok(Value::Null)
5323                    }
5324                }
5325                other => {
5326                    // Fallback for field access on non-struct types: return null
5327                    crate::sigil_warn!(
5328                        "WARN: Cannot access field '{}' on non-struct - returning null",
5329                        field_name
5330                    );
5331                    Ok(Value::Null)
5332                }
5333            }
5334        }
5335        get_field(&value, &field.name)
5336    }
5337
5338    // Helper: Extract the root variable name from a method chain
5339    fn extract_root_var(expr: &Expr) -> Option<String> {
5340        match expr {
5341            Expr::Path(path) if path.segments.len() == 1 => {
5342                Some(path.segments[0].ident.name.clone())
5343            }
5344            Expr::MethodCall { receiver, .. } => Self::extract_root_var(receiver),
5345            _ => None,
5346        }
5347    }
5348
5349    fn eval_method_call(
5350        &mut self,
5351        receiver: &Expr,
5352        method: &Ident,
5353        args: &[Expr],
5354    ) -> Result<Value, RuntimeError> {
5355        // Special handling for String::push/push_str - needs to mutate the variable
5356        if (method.name == "push" || method.name == "push_str") && args.len() == 1 {
5357            let recv_val = self.evaluate(receiver)?;
5358            let recv_unwrapped = Self::unwrap_all(&recv_val);
5359            if let Value::String(s) = &recv_unwrapped {
5360                let arg = self.evaluate(&args[0])?;
5361                let arg_unwrapped = Self::unwrap_all(&arg);
5362                let new_s = match arg_unwrapped {
5363                    Value::Char(c) => {
5364                        let mut new_str = (**s).clone();
5365                        new_str.push(c);
5366                        new_str
5367                    }
5368                    Value::String(ref add_s) => {
5369                        let mut new_str = (**s).clone();
5370                        new_str.push_str(add_s);
5371                        new_str
5372                    }
5373                    _ => return Err(RuntimeError::new("push expects char or string argument")),
5374                };
5375                let new_val = Value::String(Rc::new(new_s));
5376
5377                // Try to extract root variable from chain and mutate it
5378                if let Some(root_var) = Self::extract_root_var(receiver) {
5379                    self.environment
5380                        .borrow_mut()
5381                        .set(&root_var, new_val.clone())?;
5382                    // Return the new value for method chaining
5383                    return Ok(new_val);
5384                }
5385
5386                // Handle field access like self.output.push(c)
5387                if let Expr::Field {
5388                    expr: base_expr,
5389                    field: field_ident,
5390                } = receiver
5391                {
5392                    let base = self.evaluate(base_expr)?;
5393                    if let Value::Struct { fields, .. } = base {
5394                        fields
5395                            .borrow_mut()
5396                            .insert(field_ident.name.clone(), new_val.clone());
5397                        // Return the new value for method chaining
5398                        return Ok(new_val);
5399                    }
5400                }
5401                // Fallback: can't mutate, just return the new string
5402                return Ok(new_val);
5403            }
5404        }
5405
5406        let recv_raw = self.evaluate(receiver)?;
5407        // Unwrap evidential/affective wrappers for method dispatch
5408        let recv = Self::unwrap_value(&recv_raw).clone();
5409
5410        // Debug: trace ALL method calls to find Lexer
5411        static METHOD_COUNT: std::sync::atomic::AtomicUsize =
5412            std::sync::atomic::AtomicUsize::new(0);
5413        let count = METHOD_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
5414        if count < 500 {
5415            let recv_type = match &recv {
5416                Value::Struct { name, .. } => format!("Struct({})", name),
5417                Value::String(s) => format!(
5418                    "String('{}')",
5419                    if s.len() <= 20 { s.as_str() } else { "<long>" }
5420                ),
5421                Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
5422                other => format!("{:?}", std::mem::discriminant(other)),
5423            };
5424            if recv_type.contains("Lexer")
5425                || method.name.contains("keyword")
5426                || method.name.contains("lex")
5427            {
5428                crate::sigil_debug!("DEBUG method #{}: {}.{}()", count, recv_type, method.name);
5429            }
5430        }
5431        let arg_values: Vec<Value> = args
5432            .iter()
5433            .map(|a| self.evaluate(a))
5434            .collect::<Result<_, _>>()?;
5435
5436        // Debug: Trace cloned/clone method calls
5437        if method.name == "cloned" || method.name == "clone" {
5438            let recv_type = match &recv {
5439                Value::Struct { name, .. } => format!("Struct({})", name),
5440                Value::Variant {
5441                    enum_name,
5442                    variant_name,
5443                    ..
5444                } => format!("Variant({}::{})", enum_name, variant_name),
5445                Value::String(_) => "String".to_string(),
5446                Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
5447                Value::Null => "Null".to_string(),
5448                other => format!("{:?}", std::mem::discriminant(other)),
5449            };
5450            crate::sigil_debug!("DEBUG {}: recv_type={}", method.name, recv_type);
5451        }
5452
5453        // Debug: Trace ALL as_str calls
5454        if method.name == "as_str" {
5455            let recv_unwrapped = Self::unwrap_all(&recv);
5456            if let Value::String(s) = &recv_unwrapped {
5457                crate::sigil_debug!("DEBUG as_str CALL: recv='{}' len={}", s, s.len());
5458            } else {
5459                crate::sigil_debug!("DEBUG as_str CALL: recv={:?} (not string)", recv_unwrapped);
5460            }
5461        }
5462
5463        // Debug: trace keyword_or_ident method calls
5464        if method.name == "keyword_or_ident" {
5465            let recv_type = match &recv {
5466                Value::Struct { name, .. } => format!("Struct({})", name),
5467                Value::String(_) => "String".to_string(),
5468                Value::Ref(r) => format!(
5469                    "Ref({})",
5470                    match &*r.borrow() {
5471                        Value::Struct { name, .. } => format!("Struct({})", name),
5472                        other => format!("{:?}", std::mem::discriminant(other)),
5473                    }
5474                ),
5475                other => format!("{:?}", std::mem::discriminant(other)),
5476            };
5477            crate::sigil_debug!("DEBUG keyword_or_ident: recv_type={}", recv_type);
5478        }
5479
5480        // Debug: Find "fn" as method argument
5481        for arg in &arg_values {
5482            let unwrapped = Self::unwrap_all(arg);
5483            if let Value::String(s) = &unwrapped {
5484                if **s == "fn" {
5485                    let recv_type = match &recv {
5486                        Value::Struct { name, .. } => format!("Struct({})", name),
5487                        Value::String(_) => "String".to_string(),
5488                        Value::Ref(_) => "Ref".to_string(),
5489                        other => format!("{:?}", std::mem::discriminant(other)),
5490                    };
5491                    crate::sigil_debug!(
5492                        "DEBUG method call with 'fn': method={}, recv_type={}",
5493                        method.name,
5494                        recv_type
5495                    );
5496                }
5497            }
5498        }
5499
5500        // Built-in methods
5501        match (&recv, method.name.as_str()) {
5502            (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
5503            (Value::Array(arr), "push") => {
5504                if arg_values.len() != 1 {
5505                    return Err(RuntimeError::new("push expects 1 argument"));
5506                }
5507                arr.borrow_mut().push(arg_values[0].clone());
5508                Ok(Value::Null)
5509            }
5510            (Value::Array(arr), "pop") => arr
5511                .borrow_mut()
5512                .pop()
5513                .ok_or_else(|| RuntimeError::new("pop on empty array")),
5514            (Value::Array(arr), "extend") => {
5515                if arg_values.len() != 1 {
5516                    return Err(RuntimeError::new("extend expects 1 argument"));
5517                }
5518                match &arg_values[0] {
5519                    Value::Array(other) => {
5520                        arr.borrow_mut().extend(other.borrow().iter().cloned());
5521                        Ok(Value::Null)
5522                    }
5523                    _ => Err(RuntimeError::new("extend expects array argument")),
5524                }
5525            }
5526            (Value::Array(arr), "reverse") => {
5527                let mut v = arr.borrow().clone();
5528                v.reverse();
5529                Ok(Value::Array(Rc::new(RefCell::new(v))))
5530            }
5531            (Value::Array(arr), "skip") => {
5532                let n = match arg_values.first() {
5533                    Some(Value::Int(i)) => *i as usize,
5534                    _ => 1,
5535                };
5536                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
5537                Ok(Value::Array(Rc::new(RefCell::new(v))))
5538            }
5539            (Value::Array(arr), "take") => {
5540                let n = match arg_values.first() {
5541                    Some(Value::Int(i)) => *i as usize,
5542                    _ => 1,
5543                };
5544                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
5545                Ok(Value::Array(Rc::new(RefCell::new(v))))
5546            }
5547            (Value::Array(arr), "step_by") => {
5548                let n = match arg_values.first() {
5549                    Some(Value::Int(i)) if *i > 0 => *i as usize,
5550                    _ => 1,
5551                };
5552                let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
5553                Ok(Value::Array(Rc::new(RefCell::new(v))))
5554            }
5555            (Value::Array(arr), "contains") => {
5556                if arg_values.len() != 1 {
5557                    return Err(RuntimeError::new("contains expects 1 argument"));
5558                }
5559                let target = &arg_values[0];
5560                let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
5561                Ok(Value::Bool(found))
5562            }
5563            // Tuple methods
5564            (Value::Tuple(t), "to_string") | (Value::Tuple(t), "string") => {
5565                let s: Vec<String> = t.iter().map(|v| format!("{}", v)).collect();
5566                Ok(Value::String(Rc::new(format!("({})", s.join(", ")))))
5567            }
5568            (Value::Tuple(t), "len") => Ok(Value::Int(t.len() as i64)),
5569            (Value::Tuple(t), "first") => t
5570                .first()
5571                .cloned()
5572                .ok_or_else(|| RuntimeError::new("empty tuple")),
5573            (Value::Tuple(t), "last") => t
5574                .last()
5575                .cloned()
5576                .ok_or_else(|| RuntimeError::new("empty tuple")),
5577            (Value::Tuple(t), "get") => {
5578                let idx = match arg_values.first() {
5579                    Some(Value::Int(i)) => *i as usize,
5580                    _ => return Err(RuntimeError::new("get expects integer index")),
5581                };
5582                t.get(idx)
5583                    .cloned()
5584                    .ok_or_else(|| RuntimeError::new("tuple index out of bounds"))
5585            }
5586            (Value::Array(arr), "first") | (Value::Array(arr), "next") => {
5587                Ok(arr.borrow().first().cloned().unwrap_or(Value::Null))
5588            }
5589            (Value::Array(arr), "last") => arr
5590                .borrow()
5591                .last()
5592                .cloned()
5593                .ok_or_else(|| RuntimeError::new("empty array")),
5594            (Value::Array(arr), "iter") | (Value::Array(arr), "into_iter") => {
5595                // iter()/into_iter() on an array just returns the array - iteration happens in for loops
5596                Ok(Value::Array(arr.clone()))
5597            }
5598            (Value::Array(arr), "map") => {
5599                // map(closure) applies closure to each element
5600                if arg_values.len() != 1 {
5601                    return Err(RuntimeError::new("map expects 1 argument (closure)"));
5602                }
5603                match &arg_values[0] {
5604                    Value::Function(f) => {
5605                        let mut results = Vec::new();
5606                        for val in arr.borrow().iter() {
5607                            let result = self.call_function(f, vec![val.clone()])?;
5608                            results.push(result);
5609                        }
5610                        Ok(Value::Array(Rc::new(RefCell::new(results))))
5611                    }
5612                    _ => Err(RuntimeError::new("map expects closure argument")),
5613                }
5614            }
5615            (Value::Array(arr), "filter") => {
5616                // filter(predicate) keeps elements where predicate returns true
5617                if arg_values.len() != 1 {
5618                    return Err(RuntimeError::new("filter expects 1 argument (closure)"));
5619                }
5620                match &arg_values[0] {
5621                    Value::Function(f) => {
5622                        let mut results = Vec::new();
5623                        for val in arr.borrow().iter() {
5624                            let keep = self.call_function(f, vec![val.clone()])?;
5625                            if matches!(keep, Value::Bool(true)) {
5626                                results.push(val.clone());
5627                            }
5628                        }
5629                        Ok(Value::Array(Rc::new(RefCell::new(results))))
5630                    }
5631                    _ => Err(RuntimeError::new("filter expects closure argument")),
5632                }
5633            }
5634            (Value::Array(arr), "any") => {
5635                // any(predicate) returns true if any element satisfies predicate
5636                if arg_values.len() != 1 {
5637                    return Err(RuntimeError::new("any expects 1 argument (closure)"));
5638                }
5639                match &arg_values[0] {
5640                    Value::Function(f) => {
5641                        for val in arr.borrow().iter() {
5642                            let result = self.call_function(f, vec![val.clone()])?;
5643                            if matches!(result, Value::Bool(true)) {
5644                                return Ok(Value::Bool(true));
5645                            }
5646                        }
5647                        Ok(Value::Bool(false))
5648                    }
5649                    _ => Err(RuntimeError::new("any expects closure argument")),
5650                }
5651            }
5652            (Value::Array(arr), "all") => {
5653                // all(predicate) returns true if all elements satisfy predicate
5654                if arg_values.len() != 1 {
5655                    return Err(RuntimeError::new("all expects 1 argument (closure)"));
5656                }
5657                match &arg_values[0] {
5658                    Value::Function(f) => {
5659                        for val in arr.borrow().iter() {
5660                            let result = self.call_function(f, vec![val.clone()])?;
5661                            if !matches!(result, Value::Bool(true)) {
5662                                return Ok(Value::Bool(false));
5663                            }
5664                        }
5665                        Ok(Value::Bool(true))
5666                    }
5667                    _ => Err(RuntimeError::new("all expects closure argument")),
5668                }
5669            }
5670            (Value::Array(arr), "find") => {
5671                // find(predicate) returns first element satisfying predicate, or None
5672                if arg_values.len() != 1 {
5673                    return Err(RuntimeError::new("find expects 1 argument (closure)"));
5674                }
5675                match &arg_values[0] {
5676                    Value::Function(f) => {
5677                        for val in arr.borrow().iter() {
5678                            let result = self.call_function(f, vec![val.clone()])?;
5679                            if matches!(result, Value::Bool(true)) {
5680                                return Ok(Value::Variant {
5681                                    enum_name: "Option".to_string(),
5682                                    variant_name: "Some".to_string(),
5683                                    fields: Some(Rc::new(vec![val.clone()])),
5684                                });
5685                            }
5686                        }
5687                        Ok(Value::Variant {
5688                            enum_name: "Option".to_string(),
5689                            variant_name: "None".to_string(),
5690                            fields: None,
5691                        })
5692                    }
5693                    _ => Err(RuntimeError::new("find expects closure argument")),
5694                }
5695            }
5696            (Value::Array(arr), "enumerate") => {
5697                // enumerate() returns array of (index, value) tuples
5698                let enumerated: Vec<Value> = arr
5699                    .borrow()
5700                    .iter()
5701                    .enumerate()
5702                    .map(|(i, v)| Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()])))
5703                    .collect();
5704                Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
5705            }
5706            (Value::Array(arr), "zip") => {
5707                // zip with another array to create array of tuples
5708                if arg_values.len() != 1 {
5709                    return Err(RuntimeError::new("zip expects 1 argument"));
5710                }
5711                match &arg_values[0] {
5712                    Value::Array(other) => {
5713                        let a = arr.borrow();
5714                        let b = other.borrow();
5715                        let zipped: Vec<Value> = a
5716                            .iter()
5717                            .zip(b.iter())
5718                            .map(|(x, y)| Value::Tuple(Rc::new(vec![x.clone(), y.clone()])))
5719                            .collect();
5720                        Ok(Value::Array(Rc::new(RefCell::new(zipped))))
5721                    }
5722                    _ => Err(RuntimeError::new("zip expects array argument")),
5723                }
5724            }
5725            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
5726            (Value::String(s), "chars") => {
5727                let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5728                Ok(Value::Array(Rc::new(RefCell::new(chars))))
5729            }
5730            (Value::String(s), "contains") => {
5731                if arg_values.len() != 1 {
5732                    return Err(RuntimeError::new("contains expects 1 argument"));
5733                }
5734                match &arg_values[0] {
5735                    Value::String(sub) => Ok(Value::Bool(s.contains(sub.as_str()))),
5736                    Value::Char(c) => Ok(Value::Bool(s.contains(*c))),
5737                    Value::Ref(inner) => {
5738                        if let Value::String(sub) = &*inner.borrow() {
5739                            Ok(Value::Bool(s.contains(sub.as_str())))
5740                        } else {
5741                            Err(RuntimeError::new("contains expects string or char"))
5742                        }
5743                    }
5744                    _ => Err(RuntimeError::new("contains expects string or char")),
5745                }
5746            }
5747            (Value::String(s), "as_str") => {
5748                if s.len() <= 10 {
5749                    crate::sigil_debug!("DEBUG as_str: '{}'", s);
5750                }
5751                Ok(Value::String(s.clone()))
5752            }
5753            (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
5754            (Value::String(s), "into") => Ok(Value::String(s.clone())), // into() for String just returns String
5755            (Value::String(s), "starts_with") => {
5756                if arg_values.len() != 1 {
5757                    return Err(RuntimeError::new("starts_with expects 1 argument"));
5758                }
5759                match &arg_values[0] {
5760                    Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
5761                    _ => Err(RuntimeError::new("starts_with expects string")),
5762                }
5763            }
5764            (Value::String(s), "ends_with") => {
5765                if arg_values.len() != 1 {
5766                    return Err(RuntimeError::new("ends_with expects 1 argument"));
5767                }
5768                match &arg_values[0] {
5769                    Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
5770                    _ => Err(RuntimeError::new("ends_with expects string")),
5771                }
5772            }
5773            (Value::String(s), "strip_prefix") => {
5774                if arg_values.len() != 1 {
5775                    return Err(RuntimeError::new("strip_prefix expects 1 argument"));
5776                }
5777                match &arg_values[0] {
5778                    Value::String(prefix) => match s.strip_prefix(prefix.as_str()) {
5779                        Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
5780                        None => Ok(Value::Null),
5781                    },
5782                    _ => Err(RuntimeError::new("strip_prefix expects string")),
5783                }
5784            }
5785            (Value::String(s), "strip_suffix") => {
5786                if arg_values.len() != 1 {
5787                    return Err(RuntimeError::new("strip_suffix expects 1 argument"));
5788                }
5789                match &arg_values[0] {
5790                    Value::String(suffix) => match s.strip_suffix(suffix.as_str()) {
5791                        Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
5792                        None => Ok(Value::Null),
5793                    },
5794                    _ => Err(RuntimeError::new("strip_suffix expects string")),
5795                }
5796            }
5797            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
5798            (Value::String(s), "find") => {
5799                if arg_values.len() != 1 {
5800                    return Err(RuntimeError::new("find expects 1 argument"));
5801                }
5802                match &arg_values[0] {
5803                    Value::Char(c) => match s.find(*c) {
5804                        Some(idx) => Ok(Value::Variant {
5805                            enum_name: "Option".to_string(),
5806                            variant_name: "Some".to_string(),
5807                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5808                        }),
5809                        None => Ok(Value::Variant {
5810                            enum_name: "Option".to_string(),
5811                            variant_name: "None".to_string(),
5812                            fields: None,
5813                        }),
5814                    },
5815                    Value::String(pattern) => match s.find(pattern.as_str()) {
5816                        Some(idx) => Ok(Value::Variant {
5817                            enum_name: "Option".to_string(),
5818                            variant_name: "Some".to_string(),
5819                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5820                        }),
5821                        None => Ok(Value::Variant {
5822                            enum_name: "Option".to_string(),
5823                            variant_name: "None".to_string(),
5824                            fields: None,
5825                        }),
5826                    },
5827                    Value::Function(f) => {
5828                        for (idx, c) in s.chars().enumerate() {
5829                            let result = self.call_function(f, vec![Value::Char(c)])?;
5830                            if let Value::Bool(true) = result {
5831                                return Ok(Value::Variant {
5832                                    enum_name: "Option".to_string(),
5833                                    variant_name: "Some".to_string(),
5834                                    fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5835                                });
5836                            }
5837                        }
5838                        Ok(Value::Variant {
5839                            enum_name: "Option".to_string(),
5840                            variant_name: "None".to_string(),
5841                            fields: None,
5842                        })
5843                    }
5844                    _ => Err(RuntimeError::new("find expects a char, string, or closure")),
5845                }
5846            }
5847            (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
5848            (Value::String(s), "concat") => {
5849                if arg_values.len() != 1 {
5850                    return Err(RuntimeError::new("concat expects 1 argument"));
5851                }
5852                match &arg_values[0] {
5853                    Value::String(other) => {
5854                        let mut result = (**s).clone();
5855                        result.push_str(other);
5856                        Ok(Value::String(Rc::new(result)))
5857                    }
5858                    _ => Err(RuntimeError::new("concat expects string argument")),
5859                }
5860            }
5861            (Value::String(s), "as_ptr") => {
5862                // Return the string itself - FFI emulation doesn't need real pointers
5863                Ok(Value::String(s.clone()))
5864            }
5865            (Value::String(_), "is_null") => Ok(Value::Bool(false)),
5866            (Value::Null, "is_null") => Ok(Value::Bool(true)),
5867            (Value::String(s), "char_at") => {
5868                if arg_values.len() != 1 {
5869                    return Err(RuntimeError::new("char_at expects 1 argument"));
5870                }
5871                let idx = match &arg_values[0] {
5872                    Value::Int(i) => *i as usize,
5873                    _ => return Err(RuntimeError::new("char_at expects integer index")),
5874                };
5875                // Use byte-based indexing to match the self-hosted lexer's pos tracking
5876                // which increments by c.len_utf8() (byte count, not character count)
5877                if idx < s.len() {
5878                    // Get the character starting at byte position idx
5879                    let remaining = &s[idx..];
5880                    match remaining.chars().next() {
5881                        Some(c) => Ok(Value::Char(c)),
5882                        None => Ok(Value::Null),
5883                    }
5884                } else {
5885                    Ok(Value::Null) // Out of bounds
5886                }
5887            }
5888            (Value::String(s), "chars") => {
5889                let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5890                Ok(Value::Array(Rc::new(RefCell::new(chars))))
5891            }
5892            (Value::String(s), "bytes") => {
5893                let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
5894                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
5895            }
5896            (Value::String(s), "split") => {
5897                if arg_values.len() != 1 {
5898                    return Err(RuntimeError::new("split expects 1 argument"));
5899                }
5900                match &arg_values[0] {
5901                    Value::String(sep) => {
5902                        let parts: Vec<Value> = s
5903                            .split(sep.as_str())
5904                            .map(|p| Value::String(Rc::new(p.to_string())))
5905                            .collect();
5906                        Ok(Value::Array(Rc::new(RefCell::new(parts))))
5907                    }
5908                    Value::Char(sep) => {
5909                        let parts: Vec<Value> = s
5910                            .split(*sep)
5911                            .map(|p| Value::String(Rc::new(p.to_string())))
5912                            .collect();
5913                        Ok(Value::Array(Rc::new(RefCell::new(parts))))
5914                    }
5915                    _ => Err(RuntimeError::new("split expects string or char separator")),
5916                }
5917            }
5918            // Char methods
5919            (Value::Char(c), "len_utf8") => Ok(Value::Int(c.len_utf8() as i64)),
5920            (Value::Char(c), "is_alphabetic") => Ok(Value::Bool(c.is_alphabetic())),
5921            (Value::Char(c), "is_alphanumeric") => Ok(Value::Bool(c.is_alphanumeric())),
5922            (Value::Char(c), "is_ascii_alphanumeric") => Ok(Value::Bool(c.is_ascii_alphanumeric())),
5923            (Value::Char(c), "is_ascii_alphabetic") => Ok(Value::Bool(c.is_ascii_alphabetic())),
5924            (Value::Char(c), "is_ascii_digit") => Ok(Value::Bool(c.is_ascii_digit())),
5925            (Value::Char(c), "is_ascii_hexdigit") => Ok(Value::Bool(c.is_ascii_hexdigit())),
5926            (Value::Char(c), "is_ascii") => Ok(Value::Bool(c.is_ascii())),
5927            (Value::Char(c), "is_digit") => {
5928                let radix = if arg_values.is_empty() {
5929                    10
5930                } else {
5931                    match &arg_values[0] {
5932                        Value::Int(n) => *n as u32,
5933                        _ => 10,
5934                    }
5935                };
5936                Ok(Value::Bool(c.is_digit(radix)))
5937            }
5938            (Value::Char(c), "is_numeric") => Ok(Value::Bool(c.is_numeric())),
5939            (Value::Char(c), "is_whitespace") => Ok(Value::Bool(c.is_whitespace())),
5940            (Value::Char(c), "is_uppercase") => Ok(Value::Bool(c.is_uppercase())),
5941            (Value::Char(c), "is_lowercase") => Ok(Value::Bool(c.is_lowercase())),
5942            (Value::Char(c), "to_uppercase") => {
5943                let upper: String = c.to_uppercase().collect();
5944                Ok(Value::String(Rc::new(upper)))
5945            }
5946            (Value::Char(c), "to_lowercase") => {
5947                let lower: String = c.to_lowercase().collect();
5948                Ok(Value::String(Rc::new(lower)))
5949            }
5950            (Value::Char(c), "to_string") => Ok(Value::String(Rc::new(c.to_string()))),
5951            (Value::Char(c), "to_digit") => {
5952                let radix = if arg_values.is_empty() {
5953                    10
5954                } else {
5955                    match &arg_values[0] {
5956                        Value::Int(n) => *n as u32,
5957                        _ => 10,
5958                    }
5959                };
5960                match c.to_digit(radix) {
5961                    Some(d) => Ok(Value::Int(d as i64)),
5962                    None => Ok(Value::Null),
5963                }
5964            }
5965            (Value::Char(c), "to_ascii_uppercase") => Ok(Value::Char(c.to_ascii_uppercase())),
5966            (Value::Char(c), "to_ascii_lowercase") => Ok(Value::Char(c.to_ascii_lowercase())),
5967            (Value::Char(c), "clone") => Ok(Value::Char(*c)),
5968            (Value::String(s), "upper")
5969            | (Value::String(s), "uppercase")
5970            | (Value::String(s), "to_uppercase") => Ok(Value::String(Rc::new(s.to_uppercase()))),
5971            (Value::String(s), "lower")
5972            | (Value::String(s), "lowercase")
5973            | (Value::String(s), "to_lowercase") => Ok(Value::String(Rc::new(s.to_lowercase()))),
5974            (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
5975            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
5976            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
5977            // Path-like methods for strings (treat string as file path)
5978            (Value::String(s), "exists") => {
5979                Ok(Value::Bool(std::path::Path::new(s.as_str()).exists()))
5980            }
5981            (Value::String(s), "is_dir") => {
5982                Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir()))
5983            }
5984            (Value::String(s), "is_file") => {
5985                Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file()))
5986            }
5987            (Value::String(s), "join") => {
5988                // Path join: "dir".join("file") => "dir/file"
5989                if arg_values.len() != 1 {
5990                    return Err(RuntimeError::new(&format!(
5991                        "join expects 1 argument, got {}",
5992                        arg_values.len()
5993                    )));
5994                }
5995                let other = match &arg_values[0] {
5996                    Value::String(s2) => s2.as_str().to_string(),
5997                    other => {
5998                        return Err(RuntimeError::new(&format!(
5999                            "join expects String argument, got {:?}",
6000                            other
6001                        )))
6002                    }
6003                };
6004                let path = std::path::Path::new(s.as_str()).join(&other);
6005                Ok(Value::String(Rc::new(path.to_string_lossy().to_string())))
6006            }
6007            (Value::String(s), "parent") => {
6008                // Get parent directory
6009                let path = std::path::Path::new(s.as_str());
6010                match path.parent() {
6011                    Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
6012                    None => Ok(Value::Null),
6013                }
6014            }
6015            (Value::String(s), "file_name") => {
6016                // Get file name component
6017                let path = std::path::Path::new(s.as_str());
6018                match path.file_name() {
6019                    Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
6020                    None => Ok(Value::Null),
6021                }
6022            }
6023            (Value::String(s), "extension") => {
6024                // Get file extension
6025                let path = std::path::Path::new(s.as_str());
6026                match path.extension() {
6027                    Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
6028                    None => Ok(Value::Null),
6029                }
6030            }
6031            // Result-like chaining for strings (used when string represents a Result-like value)
6032            (Value::String(_), "and_then") | (Value::String(_), "or_else") => {
6033                // Just pass through - these are no-ops for plain strings
6034                Ok(recv.clone())
6035            }
6036            (Value::String(s), "first") => s
6037                .chars()
6038                .next()
6039                .map(Value::Char)
6040                .ok_or_else(|| RuntimeError::new("empty string")),
6041            (Value::String(s), "last") => s
6042                .chars()
6043                .last()
6044                .map(Value::Char)
6045                .ok_or_else(|| RuntimeError::new("empty string")),
6046            (Value::Array(arr), "is_empty") => Ok(Value::Bool(arr.borrow().is_empty())),
6047            (Value::Array(arr), "clone") => {
6048                Ok(Value::Array(Rc::new(RefCell::new(arr.borrow().clone()))))
6049            }
6050            (Value::Array(arr), "collect") => {
6051                // collect() on array just returns the array itself
6052                // It's the terminal operation that materializes pipeline results
6053                Ok(Value::Array(arr.clone()))
6054            }
6055            (Value::Array(arr), "join") => {
6056                let separator = if arg_values.is_empty() {
6057                    String::new()
6058                } else {
6059                    match &arg_values[0] {
6060                        Value::String(s) => (**s).clone(),
6061                        _ => return Err(RuntimeError::new("join separator must be string")),
6062                    }
6063                };
6064                let parts: Vec<String> =
6065                    arr.borrow().iter().map(|v| self.format_value(v)).collect();
6066                Ok(Value::String(Rc::new(parts.join(&separator))))
6067            }
6068            // Map methods
6069            (Value::Map(m), "insert") => {
6070                if arg_values.len() != 2 {
6071                    return Err(RuntimeError::new("insert expects 2 arguments"));
6072                }
6073                let key = match &arg_values[0] {
6074                    Value::String(s) => (**s).clone(),
6075                    _ => format!("{}", arg_values[0]),
6076                };
6077                m.borrow_mut().insert(key, arg_values[1].clone());
6078                Ok(Value::Null)
6079            }
6080            (Value::Map(m), "get") => {
6081                if arg_values.len() != 1 {
6082                    return Err(RuntimeError::new("get expects 1 argument"));
6083                }
6084                let key = match &arg_values[0] {
6085                    Value::String(s) => (**s).clone(),
6086                    _ => format!("{}", arg_values[0]),
6087                };
6088                Ok(m.borrow().get(&key).cloned().unwrap_or(Value::Null))
6089            }
6090            (Value::Map(m), "contains_key") => {
6091                if arg_values.len() != 1 {
6092                    return Err(RuntimeError::new("contains_key expects 1 argument"));
6093                }
6094                let key = match &arg_values[0] {
6095                    Value::String(s) => (**s).clone(),
6096                    _ => format!("{}", arg_values[0]),
6097                };
6098                Ok(Value::Bool(m.borrow().contains_key(&key)))
6099            }
6100            (Value::Map(m), "len") => Ok(Value::Int(m.borrow().len() as i64)),
6101            (Value::Map(m), "is_empty") => Ok(Value::Bool(m.borrow().is_empty())),
6102            (Value::Map(m), "keys") => {
6103                let keys: Vec<Value> = m
6104                    .borrow()
6105                    .keys()
6106                    .map(|k| Value::String(Rc::new(k.clone())))
6107                    .collect();
6108                Ok(Value::Array(Rc::new(RefCell::new(keys))))
6109            }
6110            (Value::Map(m), "values") => {
6111                let values: Vec<Value> = m.borrow().values().cloned().collect();
6112                Ok(Value::Array(Rc::new(RefCell::new(values))))
6113            }
6114            // Ref methods
6115            (Value::Ref(r), "cloned") => {
6116                // Clone the inner value
6117                Ok(r.borrow().clone())
6118            }
6119            (Value::Ref(r), "borrow") => {
6120                // Return a reference to the inner value
6121                Ok(recv.clone())
6122            }
6123            (Value::Ref(r), "borrow_mut") => {
6124                // Return a reference to the inner value (mutable in place)
6125                Ok(recv.clone())
6126            }
6127            // Forward method calls on Ref to inner value (struct method lookup)
6128            (Value::Ref(r), _) => {
6129                // Dereference and look up method on inner struct
6130                let inner = r.borrow().clone();
6131                if let Value::Struct { name, fields } = &inner {
6132                    // Try struct method lookup with the inner struct
6133                    let qualified_name = format!("{}·{}", name, method.name);
6134                    let func = self
6135                        .globals
6136                        .borrow()
6137                        .get(&qualified_name)
6138                        .map(|v| v.clone());
6139                    if let Some(func) = func {
6140                        if let Value::Function(f) = func {
6141                            // Set current Self type for Self { ... } resolution
6142                            let old_self_type = self.current_self_type.take();
6143                            self.current_self_type = Some(name.clone());
6144
6145                            // Pass the Ref as the receiver (for &mut self methods)
6146                            let mut all_args = vec![recv.clone()];
6147                            all_args.extend(arg_values.clone());
6148                            let result = self.call_function(&f, all_args);
6149
6150                            // Restore old Self type
6151                            self.current_self_type = old_self_type;
6152                            return result;
6153                        } else if let Value::BuiltIn(b) = func {
6154                            let mut all_args = vec![recv.clone()];
6155                            all_args.extend(arg_values.clone());
6156                            return (b.func)(self, all_args);
6157                        }
6158                    }
6159
6160                    // If struct name is "Self", search by matching field names
6161                    if name == "Self" {
6162                        let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
6163
6164                        // Search through registered types to find a matching struct
6165                        for (type_name, type_def) in &self.types {
6166                            if let TypeDef::Struct(struct_def) = type_def {
6167                                let def_fields: Vec<String> = match &struct_def.fields {
6168                                    crate::ast::StructFields::Named(fs) => {
6169                                        fs.iter().map(|f| f.name.name.clone()).collect()
6170                                    }
6171                                    _ => continue,
6172                                };
6173
6174                                // Match if our fields exist in the definition
6175                                let matches = field_names.iter().all(|f| def_fields.contains(f));
6176                                if matches {
6177                                    let qualified_name = format!("{}·{}", type_name, method.name);
6178                                    let func = self
6179                                        .globals
6180                                        .borrow()
6181                                        .get(&qualified_name)
6182                                        .map(|v| v.clone());
6183                                    if let Some(func) = func {
6184                                        if let Value::Function(f) = func {
6185                                            // Set current Self type for Self { ... } resolution
6186                                            let old_self_type = self.current_self_type.take();
6187                                            self.current_self_type = Some(type_name.clone());
6188
6189                                            let mut all_args = vec![recv.clone()];
6190                                            all_args.extend(arg_values.clone());
6191                                            let result = self.call_function(&f, all_args);
6192
6193                                            // Restore old Self type
6194                                            self.current_self_type = old_self_type;
6195                                            return result;
6196                                        } else if let Value::BuiltIn(b) = func {
6197                                            let mut all_args = vec![recv.clone()];
6198                                            all_args.extend(arg_values.clone());
6199                                            return (b.func)(self, all_args);
6200                                        }
6201                                    }
6202                                }
6203                            }
6204                        }
6205                    }
6206
6207                    // Built-in methods for PathBuf struct
6208                    if name == "PathBuf" || name == "Path" {
6209                        if let Some(Value::String(path)) = fields.borrow().get("path").cloned() {
6210                            match method.name.as_str() {
6211                                "exists" => {
6212                                    return Ok(Value::Bool(
6213                                        std::path::Path::new(path.as_str()).exists(),
6214                                    ))
6215                                }
6216                                "is_dir" => {
6217                                    return Ok(Value::Bool(
6218                                        std::path::Path::new(path.as_str()).is_dir(),
6219                                    ))
6220                                }
6221                                "is_file" => {
6222                                    return Ok(Value::Bool(
6223                                        std::path::Path::new(path.as_str()).is_file(),
6224                                    ))
6225                                }
6226                                "join" => {
6227                                    if let Some(Value::String(other)) = arg_values.first() {
6228                                        let new_path = std::path::Path::new(path.as_str())
6229                                            .join(other.as_str());
6230                                        let mut new_fields = std::collections::HashMap::new();
6231                                        new_fields.insert(
6232                                            "path".to_string(),
6233                                            Value::String(Rc::new(
6234                                                new_path.to_string_lossy().to_string(),
6235                                            )),
6236                                        );
6237                                        return Ok(Value::Struct {
6238                                            name: "PathBuf".to_string(),
6239                                            fields: Rc::new(RefCell::new(new_fields)),
6240                                        });
6241                                    }
6242                                    return Err(RuntimeError::new("join requires string argument"));
6243                                }
6244                                "parent" => {
6245                                    let p = std::path::Path::new(path.as_str());
6246                                    return match p.parent() {
6247                                        Some(par) => {
6248                                            let mut new_fields = std::collections::HashMap::new();
6249                                            new_fields.insert(
6250                                                "path".to_string(),
6251                                                Value::String(Rc::new(
6252                                                    par.to_string_lossy().to_string(),
6253                                                )),
6254                                            );
6255                                            Ok(Value::Struct {
6256                                                name: "PathBuf".to_string(),
6257                                                fields: Rc::new(RefCell::new(new_fields)),
6258                                            })
6259                                        }
6260                                        None => Ok(Value::Null),
6261                                    };
6262                                }
6263                                "file_name" => {
6264                                    let p = std::path::Path::new(path.as_str());
6265                                    return match p.file_name() {
6266                                        Some(n) => Ok(Value::String(Rc::new(
6267                                            n.to_string_lossy().to_string(),
6268                                        ))),
6269                                        None => Ok(Value::Null),
6270                                    };
6271                                }
6272                                "extension" => {
6273                                    let p = std::path::Path::new(path.as_str());
6274                                    return match p.extension() {
6275                                        Some(e) => Ok(Value::String(Rc::new(
6276                                            e.to_string_lossy().to_string(),
6277                                        ))),
6278                                        None => Ok(Value::Null),
6279                                    };
6280                                }
6281                                "to_string" | "display" | "to_str" => {
6282                                    return Ok(Value::String(path.clone()));
6283                                }
6284                                _ => {}
6285                            }
6286                        }
6287                    }
6288
6289                    // Fallback for unknown methods on external type references: return null
6290                    crate::sigil_warn!(
6291                        "WARN: Unknown method '{}' on '&{}' - returning null",
6292                        method.name,
6293                        name
6294                    );
6295                    return Ok(Value::Null);
6296                }
6297                // For non-struct refs (like &str), auto-deref and call method on inner value
6298                // Handle common methods on &str (reference to String)
6299                if let Value::String(s) = &inner {
6300                    match method.name.as_str() {
6301                        "to_string" => return Ok(Value::String(s.clone())),
6302                        "len" => return Ok(Value::Int(s.len() as i64)),
6303                        "is_empty" => return Ok(Value::Bool(s.is_empty())),
6304                        "as_str" => return Ok(Value::String(s.clone())),
6305                        "starts_with" => {
6306                            let prefix = match arg_values.first() {
6307                                Some(Value::String(p)) => p.as_str(),
6308                                Some(Value::Char(c)) => return Ok(Value::Bool(s.starts_with(*c))),
6309                                _ => {
6310                                    return Err(RuntimeError::new(
6311                                        "starts_with expects string or char",
6312                                    ))
6313                                }
6314                            };
6315                            return Ok(Value::Bool(s.starts_with(prefix)));
6316                        }
6317                        "ends_with" => {
6318                            let suffix = match arg_values.first() {
6319                                Some(Value::String(p)) => p.as_str(),
6320                                Some(Value::Char(c)) => return Ok(Value::Bool(s.ends_with(*c))),
6321                                _ => {
6322                                    return Err(RuntimeError::new(
6323                                        "ends_with expects string or char",
6324                                    ))
6325                                }
6326                            };
6327                            return Ok(Value::Bool(s.ends_with(suffix)));
6328                        }
6329                        "contains" => {
6330                            let substr = match arg_values.first() {
6331                                Some(Value::String(p)) => p.as_str(),
6332                                Some(Value::Char(c)) => return Ok(Value::Bool(s.contains(*c))),
6333                                _ => {
6334                                    return Err(RuntimeError::new(
6335                                        "contains expects string or char",
6336                                    ))
6337                                }
6338                            };
6339                            return Ok(Value::Bool(s.contains(substr)));
6340                        }
6341                        "trim" => return Ok(Value::String(Rc::new(s.trim().to_string()))),
6342                        "to_lowercase" => return Ok(Value::String(Rc::new(s.to_lowercase()))),
6343                        "to_uppercase" => return Ok(Value::String(Rc::new(s.to_uppercase()))),
6344                        "chars" => {
6345                            let chars: Vec<Value> = s.chars().map(Value::Char).collect();
6346                            return Ok(Value::Array(Rc::new(RefCell::new(chars))));
6347                        }
6348                        "split" => {
6349                            let delim = match arg_values.first() {
6350                                Some(Value::String(d)) => d.as_str().to_string(),
6351                                Some(Value::Char(c)) => c.to_string(),
6352                                _ => " ".to_string(),
6353                            };
6354                            let parts: Vec<Value> = s
6355                                .split(&delim)
6356                                .map(|p| Value::String(Rc::new(p.to_string())))
6357                                .collect();
6358                            return Ok(Value::Array(Rc::new(RefCell::new(parts))));
6359                        }
6360                        "replace" => {
6361                            if arg_values.len() != 2 {
6362                                return Err(RuntimeError::new("replace expects 2 arguments"));
6363                            }
6364                            let from = match &arg_values[0] {
6365                                Value::String(f) => f.as_str().to_string(),
6366                                Value::Char(c) => c.to_string(),
6367                                _ => return Err(RuntimeError::new("replace expects strings")),
6368                            };
6369                            let to = match &arg_values[1] {
6370                                Value::String(t) => t.as_str().to_string(),
6371                                Value::Char(c) => c.to_string(),
6372                                _ => return Err(RuntimeError::new("replace expects strings")),
6373                            };
6374                            return Ok(Value::String(Rc::new(s.replace(&from, &to))));
6375                        }
6376                        _ => {}
6377                    }
6378                }
6379                // Handle methods on &[T] and &mut [T] (references to arrays/slices)
6380                if let Value::Array(arr) = &inner {
6381                    match method.name.as_str() {
6382                        "len" => return Ok(Value::Int(arr.borrow().len() as i64)),
6383                        "is_empty" => return Ok(Value::Bool(arr.borrow().is_empty())),
6384                        "push" => {
6385                            if arg_values.len() != 1 {
6386                                return Err(RuntimeError::new("push expects 1 argument"));
6387                            }
6388                            arr.borrow_mut().push(arg_values[0].clone());
6389                            return Ok(Value::Null);
6390                        }
6391                        "pop" => {
6392                            return arr
6393                                .borrow_mut()
6394                                .pop()
6395                                .ok_or_else(|| RuntimeError::new("pop on empty array"));
6396                        }
6397                        "contains" => {
6398                            if arg_values.len() != 1 {
6399                                return Err(RuntimeError::new("contains expects 1 argument"));
6400                            }
6401                            let target = &arg_values[0];
6402                            let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
6403                            return Ok(Value::Bool(found));
6404                        }
6405                        "first" | "next" => {
6406                            return Ok(arr.borrow().first().cloned().unwrap_or(Value::Null));
6407                        }
6408                        "last" => {
6409                            return arr
6410                                .borrow()
6411                                .last()
6412                                .cloned()
6413                                .ok_or_else(|| RuntimeError::new("empty array"));
6414                        }
6415                        "iter" | "into_iter" => {
6416                            return Ok(Value::Array(arr.clone()));
6417                        }
6418                        "reverse" => {
6419                            let mut v = arr.borrow().clone();
6420                            v.reverse();
6421                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
6422                        }
6423                        "skip" => {
6424                            let n = match arg_values.first() {
6425                                Some(Value::Int(i)) => *i as usize,
6426                                _ => 1,
6427                            };
6428                            let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
6429                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
6430                        }
6431                        "take" => {
6432                            let n = match arg_values.first() {
6433                                Some(Value::Int(i)) => *i as usize,
6434                                _ => 1,
6435                            };
6436                            let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
6437                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
6438                        }
6439                        "get" => {
6440                            let idx = match arg_values.first() {
6441                                Some(Value::Int(i)) => *i as usize,
6442                                _ => return Err(RuntimeError::new("get expects integer index")),
6443                            };
6444                            return Ok(arr.borrow().get(idx).cloned().unwrap_or(Value::Null));
6445                        }
6446                        _ => {}
6447                    }
6448                }
6449                // Handle clone on any Ref value - clone the inner value
6450                if method.name == "clone" {
6451                    crate::sigil_debug!(
6452                        "DEBUG clone: recv_type=Ref({:?})",
6453                        std::mem::discriminant(&inner)
6454                    );
6455                    return Ok(inner.clone());
6456                }
6457                // Handle into on Ref value - convert to owned value
6458                if method.name == "into" {
6459                    return Ok(inner.clone());
6460                }
6461                // Handle to_string on Ref value
6462                if method.name == "to_string" {
6463                    return Ok(Value::String(Rc::new(format!("{}", inner))));
6464                }
6465                // Path methods for Ref containing PathBuf struct
6466                if let Value::Struct { name, fields, .. } = &inner {
6467                    if name == "PathBuf" || name == "Path" {
6468                        let borrowed = fields.borrow();
6469                        if let Some(Value::String(path)) = borrowed.get("path") {
6470                            match method.name.as_str() {
6471                                "exists" => {
6472                                    return Ok(Value::Bool(
6473                                        std::path::Path::new(path.as_str()).exists(),
6474                                    ))
6475                                }
6476                                "is_dir" => {
6477                                    return Ok(Value::Bool(
6478                                        std::path::Path::new(path.as_str()).is_dir(),
6479                                    ))
6480                                }
6481                                "is_file" => {
6482                                    return Ok(Value::Bool(
6483                                        std::path::Path::new(path.as_str()).is_file(),
6484                                    ))
6485                                }
6486                                "join" => {
6487                                    if let Some(Value::String(other)) = arg_values.first() {
6488                                        let new_path = std::path::Path::new(path.as_str())
6489                                            .join(other.as_str());
6490                                        let mut new_fields = std::collections::HashMap::new();
6491                                        new_fields.insert(
6492                                            "path".to_string(),
6493                                            Value::String(Rc::new(
6494                                                new_path.to_string_lossy().to_string(),
6495                                            )),
6496                                        );
6497                                        return Ok(Value::Struct {
6498                                            name: "PathBuf".to_string(),
6499                                            fields: Rc::new(RefCell::new(new_fields)),
6500                                        });
6501                                    }
6502                                    return Err(RuntimeError::new("join requires string argument"));
6503                                }
6504                                "parent" => {
6505                                    let p = std::path::Path::new(path.as_str());
6506                                    return match p.parent() {
6507                                        Some(par) => {
6508                                            let mut new_fields = std::collections::HashMap::new();
6509                                            new_fields.insert(
6510                                                "path".to_string(),
6511                                                Value::String(Rc::new(
6512                                                    par.to_string_lossy().to_string(),
6513                                                )),
6514                                            );
6515                                            Ok(Value::Struct {
6516                                                name: "PathBuf".to_string(),
6517                                                fields: Rc::new(RefCell::new(new_fields)),
6518                                            })
6519                                        }
6520                                        None => Ok(Value::Null),
6521                                    };
6522                                }
6523                                "file_name" => {
6524                                    let p = std::path::Path::new(path.as_str());
6525                                    return match p.file_name() {
6526                                        Some(n) => Ok(Value::String(Rc::new(
6527                                            n.to_string_lossy().to_string(),
6528                                        ))),
6529                                        None => Ok(Value::Null),
6530                                    };
6531                                }
6532                                "extension" => {
6533                                    let p = std::path::Path::new(path.as_str());
6534                                    return match p.extension() {
6535                                        Some(e) => Ok(Value::String(Rc::new(
6536                                            e.to_string_lossy().to_string(),
6537                                        ))),
6538                                        None => Ok(Value::Null),
6539                                    };
6540                                }
6541                                "to_string" | "display" => {
6542                                    return Ok(Value::String(path.clone()));
6543                                }
6544                                _ => {}
6545                            }
6546                        }
6547                    }
6548                }
6549                // Path methods for Ref containing String (PathBuf behavior)
6550                if let Value::String(s) = &inner {
6551                    match method.name.as_str() {
6552                        "exists" => {
6553                            return Ok(Value::Bool(std::path::Path::new(s.as_str()).exists()))
6554                        }
6555                        "is_dir" => {
6556                            return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir()))
6557                        }
6558                        "is_file" => {
6559                            return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file()))
6560                        }
6561                        "join" => {
6562                            if let Some(Value::String(other)) = arg_values.first() {
6563                                let path = std::path::Path::new(s.as_str()).join(other.as_str());
6564                                return Ok(Value::String(Rc::new(
6565                                    path.to_string_lossy().to_string(),
6566                                )));
6567                            }
6568                            return Err(RuntimeError::new("join requires string argument"));
6569                        }
6570                        "parent" => {
6571                            let path = std::path::Path::new(s.as_str());
6572                            return match path.parent() {
6573                                Some(p) => {
6574                                    Ok(Value::String(Rc::new(p.to_string_lossy().to_string())))
6575                                }
6576                                None => Ok(Value::Null),
6577                            };
6578                        }
6579                        "file_name" => {
6580                            let path = std::path::Path::new(s.as_str());
6581                            return match path.file_name() {
6582                                Some(n) => {
6583                                    Ok(Value::String(Rc::new(n.to_string_lossy().to_string())))
6584                                }
6585                                None => Ok(Value::Null),
6586                            };
6587                        }
6588                        "extension" => {
6589                            let path = std::path::Path::new(s.as_str());
6590                            return match path.extension() {
6591                                Some(e) => {
6592                                    Ok(Value::String(Rc::new(e.to_string_lossy().to_string())))
6593                                }
6594                                None => Ok(Value::Null),
6595                            };
6596                        }
6597                        _ => {}
6598                    }
6599                }
6600                // If the inner value is a string, recursively call method dispatch
6601                // This handles cases like &s[..].find(...) where we have a Ref to a String slice
6602                if let Value::String(_) = inner {
6603                    // Recursively dispatch method call on the inner string
6604                    // Create a temporary receiver with the unwrapped string
6605                    let recv_unwrapped = inner.clone();
6606                    match (&recv_unwrapped, method.name.as_str()) {
6607                        (Value::String(s), "find") => {
6608                            if arg_values.len() != 1 {
6609                                return Err(RuntimeError::new("find expects 1 argument"));
6610                            }
6611                            match &arg_values[0] {
6612                                Value::Char(c) => {
6613                                    return match s.find(*c) {
6614                                        Some(idx) => Ok(Value::Variant {
6615                                            enum_name: "Option".to_string(),
6616                                            variant_name: "Some".to_string(),
6617                                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
6618                                        }),
6619                                        None => Ok(Value::Variant {
6620                                            enum_name: "Option".to_string(),
6621                                            variant_name: "None".to_string(),
6622                                            fields: None,
6623                                        }),
6624                                    }
6625                                }
6626                                Value::String(pattern) => {
6627                                    return match s.find(pattern.as_str()) {
6628                                        Some(idx) => Ok(Value::Variant {
6629                                            enum_name: "Option".to_string(),
6630                                            variant_name: "Some".to_string(),
6631                                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
6632                                        }),
6633                                        None => Ok(Value::Variant {
6634                                            enum_name: "Option".to_string(),
6635                                            variant_name: "None".to_string(),
6636                                            fields: None,
6637                                        }),
6638                                    }
6639                                }
6640                                Value::Function(f) => {
6641                                    for (idx, c) in s.chars().enumerate() {
6642                                        let result = self.call_function(f, vec![Value::Char(c)])?;
6643                                        if let Value::Bool(true) = result {
6644                                            return Ok(Value::Variant {
6645                                                enum_name: "Option".to_string(),
6646                                                variant_name: "Some".to_string(),
6647                                                fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
6648                                            });
6649                                        }
6650                                    }
6651                                    return Ok(Value::Variant {
6652                                        enum_name: "Option".to_string(),
6653                                        variant_name: "None".to_string(),
6654                                        fields: None,
6655                                    });
6656                                }
6657                                _ => {
6658                                    return Err(RuntimeError::new(
6659                                        "find expects a char, string, or closure",
6660                                    ))
6661                                }
6662                            }
6663                        }
6664                        (Value::String(s), "trim") => {
6665                            return Ok(Value::String(Rc::new(s.trim().to_string())))
6666                        }
6667                        (Value::String(s), "is_empty") => return Ok(Value::Bool(s.is_empty())),
6668                        (Value::String(s), "len") => return Ok(Value::Int(s.len() as i64)),
6669                        (Value::String(s), "to_string") => return Ok(Value::String(s.clone())),
6670                        (Value::String(s), "chars") => {
6671                            let chars: Vec<Value> = s.chars().map(Value::Char).collect();
6672                            return Ok(Value::Array(Rc::new(RefCell::new(chars))));
6673                        }
6674                        (Value::String(s), "starts_with") => {
6675                            if let Some(Value::String(prefix)) = arg_values.first() {
6676                                return Ok(Value::Bool(s.starts_with(prefix.as_str())));
6677                            }
6678                            return Err(RuntimeError::new("starts_with expects string argument"));
6679                        }
6680                        _ => {}
6681                    }
6682                }
6683                Err(RuntimeError::new(format!(
6684                    "Cannot call method {} on Ref to non-struct",
6685                    method.name
6686                )))
6687            }
6688            // Try struct method lookup: StructName·method
6689            (Value::Struct { name, fields }, _) => {
6690                // Built-in struct methods
6691                if method.name == "clone" {
6692                    // Clone the struct value
6693                    return Ok(recv.clone());
6694                }
6695                // PathBuf struct methods
6696                if name == "PathBuf" || name == "Path" {
6697                    let borrowed = fields.borrow();
6698                    if let Some(Value::String(path)) = borrowed.get("path") {
6699                        match method.name.as_str() {
6700                            "exists" => {
6701                                return Ok(Value::Bool(
6702                                    std::path::Path::new(path.as_str()).exists(),
6703                                ))
6704                            }
6705                            "is_dir" => {
6706                                return Ok(Value::Bool(
6707                                    std::path::Path::new(path.as_str()).is_dir(),
6708                                ))
6709                            }
6710                            "is_file" => {
6711                                return Ok(Value::Bool(
6712                                    std::path::Path::new(path.as_str()).is_file(),
6713                                ))
6714                            }
6715                            "join" => {
6716                                if let Some(Value::String(other)) = arg_values.first() {
6717                                    let new_path =
6718                                        std::path::Path::new(path.as_str()).join(other.as_str());
6719                                    let mut new_fields = std::collections::HashMap::new();
6720                                    new_fields.insert(
6721                                        "path".to_string(),
6722                                        Value::String(Rc::new(
6723                                            new_path.to_string_lossy().to_string(),
6724                                        )),
6725                                    );
6726                                    return Ok(Value::Struct {
6727                                        name: "PathBuf".to_string(),
6728                                        fields: Rc::new(RefCell::new(new_fields)),
6729                                    });
6730                                }
6731                                return Err(RuntimeError::new("join requires string argument"));
6732                            }
6733                            "parent" => {
6734                                let p = std::path::Path::new(path.as_str());
6735                                return match p.parent() {
6736                                    Some(par) => {
6737                                        let mut new_fields = std::collections::HashMap::new();
6738                                        new_fields.insert(
6739                                            "path".to_string(),
6740                                            Value::String(Rc::new(
6741                                                par.to_string_lossy().to_string(),
6742                                            )),
6743                                        );
6744                                        Ok(Value::Struct {
6745                                            name: "PathBuf".to_string(),
6746                                            fields: Rc::new(RefCell::new(new_fields)),
6747                                        })
6748                                    }
6749                                    None => Ok(Value::Null),
6750                                };
6751                            }
6752                            "file_name" => {
6753                                let p = std::path::Path::new(path.as_str());
6754                                return match p.file_name() {
6755                                    Some(n) => {
6756                                        Ok(Value::String(Rc::new(n.to_string_lossy().to_string())))
6757                                    }
6758                                    None => Ok(Value::Null),
6759                                };
6760                            }
6761                            "extension" => {
6762                                let p = std::path::Path::new(path.as_str());
6763                                return match p.extension() {
6764                                    Some(e) => {
6765                                        Ok(Value::String(Rc::new(e.to_string_lossy().to_string())))
6766                                    }
6767                                    None => Ok(Value::Null),
6768                                };
6769                            }
6770                            "to_string" | "display" => {
6771                                return Ok(Value::String(path.clone()));
6772                            }
6773                            _ => {}
6774                        }
6775                    }
6776                }
6777                // Rc struct methods
6778                if name == "Rc" {
6779                    let borrowed = fields.borrow();
6780                    if let Some(value) = borrowed.get("_value") {
6781                        match method.name.as_str() {
6782                            "clone" => {
6783                                // Return a new Rc with same value
6784                                let mut new_fields = HashMap::new();
6785                                new_fields.insert("_value".to_string(), value.clone());
6786                                return Ok(Value::Struct {
6787                                    name: "Rc".to_string(),
6788                                    fields: Rc::new(RefCell::new(new_fields)),
6789                                });
6790                            }
6791                            _ => {}
6792                        }
6793                    }
6794                }
6795                // Cell struct methods
6796                if name == "Cell" {
6797                    match method.name.as_str() {
6798                        "get" => {
6799                            let borrowed = fields.borrow();
6800                            if let Some(value) = borrowed.get("_value") {
6801                                return Ok(value.clone());
6802                            }
6803                            return Err(RuntimeError::new("Cell has no value"));
6804                        }
6805                        "set" => {
6806                            if arg_values.len() != 1 {
6807                                return Err(RuntimeError::new("set expects 1 argument"));
6808                            }
6809                            fields
6810                                .borrow_mut()
6811                                .insert("_value".to_string(), arg_values[0].clone());
6812                            return Ok(Value::Null);
6813                        }
6814                        _ => {}
6815                    }
6816                }
6817                // Duration struct methods
6818                if name == "Duration" {
6819                    let borrowed = fields.borrow();
6820                    let secs = match borrowed.get("secs") {
6821                        Some(Value::Int(s)) => *s,
6822                        _ => 0,
6823                    };
6824                    let nanos = match borrowed.get("nanos") {
6825                        Some(Value::Int(n)) => *n,
6826                        _ => 0,
6827                    };
6828                    match method.name.as_str() {
6829                        "as_secs" => return Ok(Value::Int(secs)),
6830                        "as_millis" => return Ok(Value::Int(secs * 1000 + nanos / 1_000_000)),
6831                        "as_micros" => return Ok(Value::Int(secs * 1_000_000 + nanos / 1000)),
6832                        "as_nanos" => return Ok(Value::Int(secs * 1_000_000_000 + nanos)),
6833                        "subsec_nanos" => return Ok(Value::Int(nanos)),
6834                        "subsec_millis" => return Ok(Value::Int(nanos / 1_000_000)),
6835                        "is_zero" => return Ok(Value::Bool(secs == 0 && nanos == 0)),
6836                        _ => {}
6837                    }
6838                }
6839                // Mutex methods - lock() returns a Ref to the inner value
6840                if name == "Mutex" {
6841                    match method.name.as_str() {
6842                        "lock" => {
6843                            // lock() returns a guard that provides access to inner value
6844                            // In the interpreter, we just return a Ref to the inner value
6845                            let borrowed = fields.borrow();
6846                            if let Some(inner) = borrowed.get("__inner__") {
6847                                // Return a Ref wrapping the inner value for mutation
6848                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6849                            }
6850                            return Err(RuntimeError::new("Mutex has no inner value"));
6851                        }
6852                        "try_lock" => {
6853                            // try_lock() returns Some(guard) - in interpreter always succeeds
6854                            let borrowed = fields.borrow();
6855                            if let Some(inner) = borrowed.get("__inner__") {
6856                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6857                                return Ok(Value::Variant {
6858                                    enum_name: "Option".to_string(),
6859                                    variant_name: "Some".to_string(),
6860                                    fields: Some(Rc::new(vec![guard])),
6861                                });
6862                            }
6863                            return Ok(Value::Variant {
6864                                enum_name: "Option".to_string(),
6865                                variant_name: "None".to_string(),
6866                                fields: None,
6867                            });
6868                        }
6869                        "into_inner" => {
6870                            // into_inner() consumes the mutex and returns the inner value
6871                            let borrowed = fields.borrow();
6872                            if let Some(inner) = borrowed.get("__inner__") {
6873                                return Ok(inner.clone());
6874                            }
6875                            return Err(RuntimeError::new("Mutex has no inner value"));
6876                        }
6877                        "get_mut" => {
6878                            // get_mut() returns &mut T when we have exclusive access
6879                            let borrowed = fields.borrow();
6880                            if let Some(inner) = borrowed.get("__inner__") {
6881                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6882                            }
6883                            return Err(RuntimeError::new("Mutex has no inner value"));
6884                        }
6885                        _ => {}
6886                    }
6887                }
6888                // RwLock methods - read() and write() return guards
6889                if name == "RwLock" {
6890                    match method.name.as_str() {
6891                        "read" => {
6892                            // read() returns a read guard
6893                            let borrowed = fields.borrow();
6894                            if let Some(inner) = borrowed.get("__inner__") {
6895                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6896                            }
6897                            return Err(RuntimeError::new("RwLock has no inner value"));
6898                        }
6899                        "write" => {
6900                            // write() returns a write guard
6901                            let borrowed = fields.borrow();
6902                            if let Some(inner) = borrowed.get("__inner__") {
6903                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6904                            }
6905                            return Err(RuntimeError::new("RwLock has no inner value"));
6906                        }
6907                        "try_read" => {
6908                            let borrowed = fields.borrow();
6909                            if let Some(inner) = borrowed.get("__inner__") {
6910                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6911                                return Ok(Value::Variant {
6912                                    enum_name: "Option".to_string(),
6913                                    variant_name: "Some".to_string(),
6914                                    fields: Some(Rc::new(vec![guard])),
6915                                });
6916                            }
6917                            return Ok(Value::Variant {
6918                                enum_name: "Option".to_string(),
6919                                variant_name: "None".to_string(),
6920                                fields: None,
6921                            });
6922                        }
6923                        "try_write" => {
6924                            let borrowed = fields.borrow();
6925                            if let Some(inner) = borrowed.get("__inner__") {
6926                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6927                                return Ok(Value::Variant {
6928                                    enum_name: "Option".to_string(),
6929                                    variant_name: "Some".to_string(),
6930                                    fields: Some(Rc::new(vec![guard])),
6931                                });
6932                            }
6933                            return Ok(Value::Variant {
6934                                enum_name: "Option".to_string(),
6935                                variant_name: "None".to_string(),
6936                                fields: None,
6937                            });
6938                        }
6939                        "into_inner" => {
6940                            let borrowed = fields.borrow();
6941                            if let Some(inner) = borrowed.get("__inner__") {
6942                                return Ok(inner.clone());
6943                            }
6944                            return Err(RuntimeError::new("RwLock has no inner value"));
6945                        }
6946                        _ => {}
6947                    }
6948                }
6949                // Atomic methods - load/store/fetch_add etc.
6950                if name == "AtomicU64"
6951                    || name == "AtomicUsize"
6952                    || name == "AtomicI64"
6953                    || name == "AtomicIsize"
6954                {
6955                    match method.name.as_str() {
6956                        "load" => {
6957                            // load() returns the current value
6958                            let borrowed = fields.borrow();
6959                            if let Some(val) = borrowed.get("__value__") {
6960                                return Ok(val.clone());
6961                            }
6962                            return Ok(Value::Int(0));
6963                        }
6964                        "store" => {
6965                            // store(value) sets the value
6966                            if let Some(new_val) = arg_values.first() {
6967                                fields
6968                                    .borrow_mut()
6969                                    .insert("__value__".to_string(), new_val.clone());
6970                                return Ok(Value::Null);
6971                            }
6972                            return Err(RuntimeError::new("store requires a value"));
6973                        }
6974                        "fetch_add" => {
6975                            // fetch_add(n) adds n and returns old value
6976                            if let Some(Value::Int(n)) = arg_values.first() {
6977                                let mut borrowed = fields.borrow_mut();
6978                                let old = match borrowed.get("__value__") {
6979                                    Some(Value::Int(v)) => *v,
6980                                    _ => 0,
6981                                };
6982                                borrowed.insert("__value__".to_string(), Value::Int(old + n));
6983                                return Ok(Value::Int(old));
6984                            }
6985                            return Err(RuntimeError::new("fetch_add requires integer"));
6986                        }
6987                        "fetch_sub" => {
6988                            if let Some(Value::Int(n)) = arg_values.first() {
6989                                let mut borrowed = fields.borrow_mut();
6990                                let old = match borrowed.get("__value__") {
6991                                    Some(Value::Int(v)) => *v,
6992                                    _ => 0,
6993                                };
6994                                borrowed.insert("__value__".to_string(), Value::Int(old - n));
6995                                return Ok(Value::Int(old));
6996                            }
6997                            return Err(RuntimeError::new("fetch_sub requires integer"));
6998                        }
6999                        "swap" => {
7000                            if let Some(new_val) = arg_values.first() {
7001                                let mut borrowed = fields.borrow_mut();
7002                                let old =
7003                                    borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
7004                                borrowed.insert("__value__".to_string(), new_val.clone());
7005                                return Ok(old);
7006                            }
7007                            return Err(RuntimeError::new("swap requires a value"));
7008                        }
7009                        "compare_exchange" | "compare_and_swap" => {
7010                            // compare_exchange(current, new) - if value == current, set to new
7011                            if arg_values.len() >= 2 {
7012                                let current = &arg_values[0];
7013                                let new_val = &arg_values[1];
7014                                let mut borrowed = fields.borrow_mut();
7015                                let actual =
7016                                    borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
7017                                if self.values_equal(&actual, current) {
7018                                    borrowed.insert("__value__".to_string(), new_val.clone());
7019                                    return Ok(Value::Variant {
7020                                        enum_name: "Result".to_string(),
7021                                        variant_name: "Ok".to_string(),
7022                                        fields: Some(Rc::new(vec![actual])),
7023                                    });
7024                                } else {
7025                                    return Ok(Value::Variant {
7026                                        enum_name: "Result".to_string(),
7027                                        variant_name: "Err".to_string(),
7028                                        fields: Some(Rc::new(vec![actual])),
7029                                    });
7030                                }
7031                            }
7032                            return Err(RuntimeError::new(
7033                                "compare_exchange requires two arguments",
7034                            ));
7035                        }
7036                        _ => {}
7037                    }
7038                }
7039                // AtomicBool methods
7040                if name == "AtomicBool" {
7041                    match method.name.as_str() {
7042                        "load" => {
7043                            let borrowed = fields.borrow();
7044                            if let Some(val) = borrowed.get("__value__") {
7045                                return Ok(val.clone());
7046                            }
7047                            return Ok(Value::Bool(false));
7048                        }
7049                        "store" => {
7050                            if let Some(new_val) = arg_values.first() {
7051                                fields
7052                                    .borrow_mut()
7053                                    .insert("__value__".to_string(), new_val.clone());
7054                                return Ok(Value::Null);
7055                            }
7056                            return Err(RuntimeError::new("store requires a value"));
7057                        }
7058                        "swap" => {
7059                            if let Some(new_val) = arg_values.first() {
7060                                let mut borrowed = fields.borrow_mut();
7061                                let old = borrowed
7062                                    .get("__value__")
7063                                    .cloned()
7064                                    .unwrap_or(Value::Bool(false));
7065                                borrowed.insert("__value__".to_string(), new_val.clone());
7066                                return Ok(old);
7067                            }
7068                            return Err(RuntimeError::new("swap requires a value"));
7069                        }
7070                        "fetch_and" => {
7071                            if let Some(Value::Bool(b)) = arg_values.first() {
7072                                let mut borrowed = fields.borrow_mut();
7073                                let old = match borrowed.get("__value__") {
7074                                    Some(Value::Bool(v)) => *v,
7075                                    _ => false,
7076                                };
7077                                borrowed.insert("__value__".to_string(), Value::Bool(old && *b));
7078                                return Ok(Value::Bool(old));
7079                            }
7080                            return Err(RuntimeError::new("fetch_and requires boolean"));
7081                        }
7082                        "fetch_or" => {
7083                            if let Some(Value::Bool(b)) = arg_values.first() {
7084                                let mut borrowed = fields.borrow_mut();
7085                                let old = match borrowed.get("__value__") {
7086                                    Some(Value::Bool(v)) => *v,
7087                                    _ => false,
7088                                };
7089                                borrowed.insert("__value__".to_string(), Value::Bool(old || *b));
7090                                return Ok(Value::Bool(old));
7091                            }
7092                            return Err(RuntimeError::new("fetch_or requires boolean"));
7093                        }
7094                        _ => {}
7095                    }
7096                }
7097                if method.name == "to_string" {
7098                    // Generic to_string for structs - returns a debug representation
7099                    let field_str = fields
7100                        .borrow()
7101                        .iter()
7102                        .map(|(k, v)| format!("{}: {}", k, v))
7103                        .collect::<Vec<_>>()
7104                        .join(", ");
7105                    return Ok(Value::String(Rc::new(format!(
7106                        "{} {{ {} }}",
7107                        name, field_str
7108                    ))));
7109                }
7110
7111                // Pattern methods - for AST patterns stored as structs (Pattern::Ident, Pattern::Tuple, etc.)
7112                if name.starts_with("Pattern::") {
7113                    match method.name.as_str() {
7114                        "evidentiality" => {
7115                            // Return the evidentiality field from the pattern struct
7116                            if let Some(ev) = fields.borrow().get("evidentiality") {
7117                                return Ok(ev.clone());
7118                            }
7119                            return Ok(Value::Null);
7120                        }
7121                        "name" | "binding_name" => {
7122                            // Return the name field from the pattern struct (for binding purposes)
7123                            if let Some(n) = fields.borrow().get("name") {
7124                                // The name field might be an Ident struct with a nested "name" field
7125                                // Extract the inner string if that's the case
7126                                let result = match &n {
7127                                    Value::Struct {
7128                                        fields: inner_fields,
7129                                        ..
7130                                    } => {
7131                                        if let Some(inner_name) = inner_fields.borrow().get("name")
7132                                        {
7133                                            crate::sigil_debug!("DEBUG binding_name: returning inner name {} from {}", inner_name, name);
7134                                            inner_name.clone()
7135                                        } else {
7136                                            crate::sigil_debug!(
7137                                                "DEBUG binding_name: returning struct {} from {}",
7138                                                n,
7139                                                name
7140                                            );
7141                                            n.clone()
7142                                        }
7143                                    }
7144                                    _ => {
7145                                        crate::sigil_debug!(
7146                                            "DEBUG binding_name: returning {} from {}",
7147                                            n,
7148                                            name
7149                                        );
7150                                        n.clone()
7151                                    }
7152                                };
7153                                return Ok(result);
7154                            }
7155                            crate::sigil_debug!(
7156                                "DEBUG binding_name: 'name' field not found in {}, fields: {:?}",
7157                                name,
7158                                fields.borrow().keys().collect::<Vec<_>>()
7159                            );
7160                            // For Pattern::Ident, name is the binding name
7161                            return Ok(Value::Null);
7162                        }
7163                        "mutable" => {
7164                            // Return the mutable field from the pattern struct
7165                            if let Some(m) = fields.borrow().get("mutable") {
7166                                return Ok(m.clone());
7167                            }
7168                            return Ok(Value::Bool(false));
7169                        }
7170                        "is_ident" => {
7171                            return Ok(Value::Bool(name == "Pattern::Ident"));
7172                        }
7173                        "is_wildcard" => {
7174                            return Ok(Value::Bool(name == "Pattern::Wildcard"));
7175                        }
7176                        "clone" => {
7177                            return Ok(recv.clone());
7178                        }
7179                        _ => {}
7180                    }
7181                }
7182
7183                // PathBuf methods
7184                if name == "PathBuf" || name == "Path" {
7185                    match method.name.as_str() {
7186                        "exists" => {
7187                            // Check if path exists
7188                            let path = match fields.borrow().get("path") {
7189                                Some(Value::String(s)) => s.to_string(),
7190                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7191                            };
7192                            return Ok(Value::Bool(std::path::Path::new(&path).exists()));
7193                        }
7194                        "is_dir" => {
7195                            let path = match fields.borrow().get("path") {
7196                                Some(Value::String(s)) => s.to_string(),
7197                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7198                            };
7199                            return Ok(Value::Bool(std::path::Path::new(&path).is_dir()));
7200                        }
7201                        "is_file" => {
7202                            let path = match fields.borrow().get("path") {
7203                                Some(Value::String(s)) => s.to_string(),
7204                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7205                            };
7206                            return Ok(Value::Bool(std::path::Path::new(&path).is_file()));
7207                        }
7208                        "extension" => {
7209                            let path = match fields.borrow().get("path") {
7210                                Some(Value::String(s)) => s.to_string(),
7211                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7212                            };
7213                            match std::path::Path::new(&path).extension() {
7214                                Some(ext) => {
7215                                    // Return Option::Some with an OsStr-like struct
7216                                    let ext_str = ext.to_string_lossy().to_string();
7217                                    let mut ext_fields = HashMap::new();
7218                                    ext_fields.insert(
7219                                        "value".to_string(),
7220                                        Value::String(Rc::new(ext_str)),
7221                                    );
7222                                    return Ok(Value::Variant {
7223                                        enum_name: "Option".to_string(),
7224                                        variant_name: "Some".to_string(),
7225                                        fields: Some(Rc::new(vec![Value::Struct {
7226                                            name: "OsStr".to_string(),
7227                                            fields: Rc::new(RefCell::new(ext_fields)),
7228                                        }])),
7229                                    });
7230                                }
7231                                None => {
7232                                    return Ok(Value::Variant {
7233                                        enum_name: "Option".to_string(),
7234                                        variant_name: "None".to_string(),
7235                                        fields: None,
7236                                    });
7237                                }
7238                            }
7239                        }
7240                        "file_name" => {
7241                            let path = match fields.borrow().get("path") {
7242                                Some(Value::String(s)) => s.to_string(),
7243                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7244                            };
7245                            match std::path::Path::new(&path).file_name() {
7246                                Some(fname) => {
7247                                    let fname_str = fname.to_string_lossy().to_string();
7248                                    let mut fname_fields = HashMap::new();
7249                                    fname_fields.insert(
7250                                        "value".to_string(),
7251                                        Value::String(Rc::new(fname_str)),
7252                                    );
7253                                    return Ok(Value::Variant {
7254                                        enum_name: "Option".to_string(),
7255                                        variant_name: "Some".to_string(),
7256                                        fields: Some(Rc::new(vec![Value::Struct {
7257                                            name: "OsStr".to_string(),
7258                                            fields: Rc::new(RefCell::new(fname_fields)),
7259                                        }])),
7260                                    });
7261                                }
7262                                None => {
7263                                    return Ok(Value::Variant {
7264                                        enum_name: "Option".to_string(),
7265                                        variant_name: "None".to_string(),
7266                                        fields: None,
7267                                    });
7268                                }
7269                            }
7270                        }
7271                        "parent" => {
7272                            let path = match fields.borrow().get("path") {
7273                                Some(Value::String(s)) => s.to_string(),
7274                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7275                            };
7276                            match std::path::Path::new(&path).parent() {
7277                                Some(parent) => {
7278                                    let mut parent_fields = HashMap::new();
7279                                    parent_fields.insert(
7280                                        "path".to_string(),
7281                                        Value::String(Rc::new(
7282                                            parent.to_string_lossy().to_string(),
7283                                        )),
7284                                    );
7285                                    return Ok(Value::Variant {
7286                                        enum_name: "Option".to_string(),
7287                                        variant_name: "Some".to_string(),
7288                                        fields: Some(Rc::new(vec![Value::Struct {
7289                                            name: "Path".to_string(),
7290                                            fields: Rc::new(RefCell::new(parent_fields)),
7291                                        }])),
7292                                    });
7293                                }
7294                                None => {
7295                                    return Ok(Value::Variant {
7296                                        enum_name: "Option".to_string(),
7297                                        variant_name: "None".to_string(),
7298                                        fields: None,
7299                                    });
7300                                }
7301                            }
7302                        }
7303                        "to_str" => {
7304                            // Convert to string (returns Option<&str>, we just return the string)
7305                            let path = match fields.borrow().get("path") {
7306                                Some(Value::String(s)) => s.clone(),
7307                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7308                            };
7309                            // Wrap in Some for unwrap() compatibility
7310                            return Ok(Value::Variant {
7311                                enum_name: "Option".to_string(),
7312                                variant_name: "Some".to_string(),
7313                                fields: Some(Rc::new(vec![Value::String(path)])),
7314                            });
7315                        }
7316                        "to_string_lossy" => {
7317                            let path = match fields.borrow().get("path") {
7318                                Some(Value::String(s)) => s.clone(),
7319                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7320                            };
7321                            return Ok(Value::String(path));
7322                        }
7323                        "join" => {
7324                            // Join path with another component
7325                            if arg_values.is_empty() {
7326                                return Err(RuntimeError::new("join expects 1 argument"));
7327                            }
7328                            let base = match fields.borrow().get("path") {
7329                                Some(Value::String(s)) => s.to_string(),
7330                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7331                            };
7332                            let component = match &arg_values[0] {
7333                                Value::String(s) => s.to_string(),
7334                                Value::Struct { name: n, fields: f }
7335                                    if n == "PathBuf" || n == "Path" =>
7336                                {
7337                                    match f.borrow().get("path") {
7338                                        Some(Value::String(s)) => s.to_string(),
7339                                        _ => {
7340                                            return Err(RuntimeError::new(
7341                                                "PathBuf has no path field",
7342                                            ))
7343                                        }
7344                                    }
7345                                }
7346                                _ => {
7347                                    return Err(RuntimeError::new("join expects string or PathBuf"))
7348                                }
7349                            };
7350                            let joined = std::path::Path::new(&base).join(&component);
7351                            let mut new_fields = HashMap::new();
7352                            new_fields.insert(
7353                                "path".to_string(),
7354                                Value::String(Rc::new(joined.to_string_lossy().to_string())),
7355                            );
7356                            return Ok(Value::Struct {
7357                                name: "PathBuf".to_string(),
7358                                fields: Rc::new(RefCell::new(new_fields)),
7359                            });
7360                        }
7361                        "display" => {
7362                            let path = match fields.borrow().get("path") {
7363                                Some(Value::String(s)) => s.clone(),
7364                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
7365                            };
7366                            return Ok(Value::String(path));
7367                        }
7368                        "to_path_buf" => {
7369                            // Path -> PathBuf (just return a copy)
7370                            return Ok(recv.clone());
7371                        }
7372                        _ => {}
7373                    }
7374                }
7375
7376                // OsStr methods
7377                if name == "OsStr" {
7378                    match method.name.as_str() {
7379                        "to_str" => {
7380                            let val = match fields.borrow().get("value") {
7381                                Some(Value::String(s)) => s.clone(),
7382                                _ => return Err(RuntimeError::new("OsStr has no value field")),
7383                            };
7384                            return Ok(Value::Variant {
7385                                enum_name: "Option".to_string(),
7386                                variant_name: "Some".to_string(),
7387                                fields: Some(Rc::new(vec![Value::String(val)])),
7388                            });
7389                        }
7390                        "to_string_lossy" => {
7391                            let val = match fields.borrow().get("value") {
7392                                Some(Value::String(s)) => s.clone(),
7393                                _ => return Err(RuntimeError::new("OsStr has no value field")),
7394                            };
7395                            return Ok(Value::String(val));
7396                        }
7397                        "to_lowercase" => {
7398                            let val = match fields.borrow().get("value") {
7399                                Some(Value::String(s)) => s.to_lowercase(),
7400                                _ => return Err(RuntimeError::new("OsStr has no value field")),
7401                            };
7402                            return Ok(Value::String(Rc::new(val)));
7403                        }
7404                        "as_str" => {
7405                            let val = match fields.borrow().get("value") {
7406                                Some(Value::String(s)) => s.clone(),
7407                                _ => return Err(RuntimeError::new("OsStr has no value field")),
7408                            };
7409                            return Ok(Value::String(val));
7410                        }
7411                        _ => {}
7412                    }
7413                }
7414
7415                // DirEntry methods
7416                if name == "DirEntry" {
7417                    match method.name.as_str() {
7418                        "path" => {
7419                            let path = match fields.borrow().get("path") {
7420                                Some(Value::String(s)) => s.clone(),
7421                                _ => return Err(RuntimeError::new("DirEntry has no path field")),
7422                            };
7423                            let mut path_fields = HashMap::new();
7424                            path_fields.insert("path".to_string(), Value::String(path));
7425                            return Ok(Value::Struct {
7426                                name: "PathBuf".to_string(),
7427                                fields: Rc::new(RefCell::new(path_fields)),
7428                            });
7429                        }
7430                        "file_name" => {
7431                            let path = match fields.borrow().get("path") {
7432                                Some(Value::String(s)) => s.to_string(),
7433                                _ => return Err(RuntimeError::new("DirEntry has no path field")),
7434                            };
7435                            let fname = std::path::Path::new(&path)
7436                                .file_name()
7437                                .map(|f| f.to_string_lossy().to_string())
7438                                .unwrap_or_default();
7439                            let mut fname_fields = HashMap::new();
7440                            fname_fields.insert("value".to_string(), Value::String(Rc::new(fname)));
7441                            return Ok(Value::Struct {
7442                                name: "OsStr".to_string(),
7443                                fields: Rc::new(RefCell::new(fname_fields)),
7444                            });
7445                        }
7446                        _ => {}
7447                    }
7448                }
7449
7450                // Map methods - for built-in hash map operations
7451                if name == "Map" {
7452                    match method.name.as_str() {
7453                        "get" => {
7454                            // map.get(key) -> ?value
7455                            if arg_values.len() != 1 {
7456                                return Err(RuntimeError::new("Map.get expects 1 argument"));
7457                            }
7458                            let key = match &arg_values[0] {
7459                                Value::String(s) => s.to_string(),
7460                                Value::Int(n) => n.to_string(),
7461                                other => format!("{:?}", other),
7462                            };
7463                            if let Some(val) = fields.borrow().get(&key) {
7464                                return Ok(val.clone());
7465                            }
7466                            return Ok(Value::Null);
7467                        }
7468                        "insert" => {
7469                            // map.insert(key, value)
7470                            if arg_values.len() != 2 {
7471                                return Err(RuntimeError::new("Map.insert expects 2 arguments"));
7472                            }
7473                            let key = match &arg_values[0] {
7474                                Value::String(s) => s.to_string(),
7475                                Value::Int(n) => n.to_string(),
7476                                other => format!("{:?}", other),
7477                            };
7478                            crate::sigil_debug!(
7479                                "DEBUG Map.insert: key='{}', value={}",
7480                                key,
7481                                arg_values[1]
7482                            );
7483                            fields.borrow_mut().insert(key, arg_values[1].clone());
7484                            return Ok(Value::Null);
7485                        }
7486                        "contains_key" => {
7487                            if arg_values.len() != 1 {
7488                                return Err(RuntimeError::new(
7489                                    "Map.contains_key expects 1 argument",
7490                                ));
7491                            }
7492                            let key = match &arg_values[0] {
7493                                Value::String(s) => s.to_string(),
7494                                Value::Int(n) => n.to_string(),
7495                                other => format!("{:?}", other),
7496                            };
7497                            return Ok(Value::Bool(fields.borrow().contains_key(&key)));
7498                        }
7499                        "len" => {
7500                            return Ok(Value::Int(fields.borrow().len() as i64));
7501                        }
7502                        "is_empty" => {
7503                            return Ok(Value::Bool(fields.borrow().is_empty()));
7504                        }
7505                        "keys" => {
7506                            let keys: Vec<Value> = fields
7507                                .borrow()
7508                                .keys()
7509                                .map(|k| Value::String(Rc::new(k.clone())))
7510                                .collect();
7511                            return Ok(Value::Array(Rc::new(RefCell::new(keys))));
7512                        }
7513                        "values" => {
7514                            let vals: Vec<Value> = fields.borrow().values().cloned().collect();
7515                            return Ok(Value::Array(Rc::new(RefCell::new(vals))));
7516                        }
7517                        "clone" => {
7518                            return Ok(recv.clone());
7519                        }
7520                        _ => {}
7521                    }
7522                }
7523
7524                let qualified_name = format!("{}·{}", name, method.name);
7525
7526                // Debug: track Parser method calls
7527                if name == "Parser" && (method.name == "parse_file" || method.name == "read_source")
7528                {
7529                    crate::sigil_debug!("DEBUG Parser method call: {}", qualified_name);
7530                    for (i, arg) in arg_values.iter().enumerate() {
7531                        crate::sigil_debug!("  arg_value[{}] = {:?}", i, arg);
7532                    }
7533                }
7534
7535                // Debug: track Lexer method calls
7536                if name == "Lexer" {
7537                    // Print all args for lex_ident_or_keyword
7538                    if method.name == "lex_ident_or_keyword" {
7539                        for (i, arg) in arg_values.iter().enumerate() {
7540                            let unwrapped = Self::unwrap_all(arg);
7541                            if let Value::Char(c) = &unwrapped {
7542                                crate::sigil_debug!(
7543                                    "DEBUG Lexer·lex_ident_or_keyword arg[{}]='{}'",
7544                                    i,
7545                                    c
7546                                );
7547                            }
7548                        }
7549                    }
7550                    crate::sigil_debug!("DEBUG Lexer method call: {}", qualified_name);
7551                }
7552                // Check if arg is "fn" string
7553                for arg in &arg_values {
7554                    let unwrapped = Self::unwrap_all(arg);
7555                    if let Value::String(s) = &unwrapped {
7556                        if **s == "fn" {
7557                            crate::sigil_debug!(
7558                                "DEBUG struct method with 'fn': {} recv_name={}",
7559                                method.name,
7560                                name
7561                            );
7562                        }
7563                    }
7564                }
7565
7566                let func = self
7567                    .globals
7568                    .borrow()
7569                    .get(&qualified_name)
7570                    .map(|v| v.clone());
7571                if let Some(func) = func {
7572                    if let Value::Function(f) = func {
7573                        // Set current Self type for Self { ... } resolution
7574                        let old_self_type = self.current_self_type.take();
7575                        self.current_self_type = Some(name.clone());
7576
7577                        // Call with self as first argument
7578                        let mut all_args = vec![recv.clone()];
7579                        all_args.extend(arg_values.clone());
7580                        let result = self.call_function(&f, all_args);
7581
7582                        // Restore old Self type
7583                        self.current_self_type = old_self_type;
7584                        return result;
7585                    } else if let Value::BuiltIn(b) = func {
7586                        let mut all_args = vec![recv.clone()];
7587                        all_args.extend(arg_values.clone());
7588                        return (b.func)(self, all_args);
7589                    }
7590                }
7591
7592                // If struct name is "Self", try to find the method by searching all types
7593                if name == "Self" {
7594                    // Get field names to match struct type
7595                    let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
7596
7597                    // Search through registered types to find a matching struct
7598                    for (type_name, type_def) in &self.types {
7599                        if let TypeDef::Struct(struct_def) = type_def {
7600                            // Check if field names match
7601                            let def_fields: Vec<String> = match &struct_def.fields {
7602                                crate::ast::StructFields::Named(fs) => {
7603                                    fs.iter().map(|f| f.name.name.clone()).collect()
7604                                }
7605                                _ => continue,
7606                            };
7607
7608                            // Rough match - if we have fields that exist in the definition
7609                            let matches = field_names.iter().all(|f| def_fields.contains(f));
7610                            if matches {
7611                                let qualified_name = format!("{}·{}", type_name, method.name);
7612                                let func = self
7613                                    .globals
7614                                    .borrow()
7615                                    .get(&qualified_name)
7616                                    .map(|v| v.clone());
7617                                if let Some(func) = func {
7618                                    if let Value::Function(f) = func {
7619                                        // Set current Self type for Self { ... } resolution
7620                                        let old_self_type = self.current_self_type.take();
7621                                        self.current_self_type = Some(type_name.clone());
7622
7623                                        let mut all_args = vec![recv.clone()];
7624                                        all_args.extend(arg_values.clone());
7625                                        let result = self.call_function(&f, all_args);
7626
7627                                        // Restore old Self type
7628                                        self.current_self_type = old_self_type;
7629                                        return result;
7630                                    } else if let Value::BuiltIn(b) = func {
7631                                        let mut all_args = vec![recv.clone()];
7632                                        all_args.extend(arg_values.clone());
7633                                        return (b.func)(self, all_args);
7634                                    }
7635                                }
7636                            }
7637                        }
7638                    }
7639                }
7640
7641                // Fallback for unknown methods on external types: return null
7642                // This allows code using external crate types to run without full loading
7643                crate::sigil_warn!(
7644                    "WARN: Unknown method '{}' on '{}' - returning null",
7645                    method.name,
7646                    name
7647                );
7648                Ok(Value::Null)
7649            }
7650            // Try variant method lookup: EnumName·method
7651            (
7652                Value::Variant {
7653                    enum_name,
7654                    variant_name,
7655                    fields,
7656                },
7657                _,
7658            ) => {
7659                // Built-in Option methods
7660                if enum_name == "Option" {
7661                    match method.name.as_str() {
7662                        "cloned" => {
7663                            // cloned() on Option<&T> returns Option<T>
7664                            // In our interpreter, just clone the value
7665                            return Ok(recv.clone());
7666                        }
7667                        "is_some" => {
7668                            return Ok(Value::Bool(variant_name == "Some"));
7669                        }
7670                        "is_none" => {
7671                            return Ok(Value::Bool(variant_name == "None"));
7672                        }
7673                        "unwrap" => {
7674                            crate::sigil_debug!(
7675                                "DEBUG Option.unwrap: variant={}, fields={:?}",
7676                                variant_name,
7677                                fields
7678                            );
7679                            if variant_name == "Some" {
7680                                if let Some(f) = fields {
7681                                    let result = f.first().cloned().unwrap_or(Value::Null);
7682                                    crate::sigil_debug!(
7683                                        "DEBUG Option.unwrap: returning {:?}",
7684                                        result
7685                                    );
7686                                    return Ok(result);
7687                                }
7688                            }
7689                            return Err(RuntimeError::new("unwrap on None"));
7690                        }
7691                        "unwrap_or" => {
7692                            if variant_name == "Some" {
7693                                if let Some(f) = fields {
7694                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
7695                                }
7696                            }
7697                            return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
7698                        }
7699                        "map" => {
7700                            // Option::map takes a closure
7701                            if variant_name == "Some" {
7702                                if let Some(f) = fields {
7703                                    if let Some(inner) = f.first() {
7704                                        if let Some(Value::Function(func)) = arg_values.first() {
7705                                            let result =
7706                                                self.call_function(func, vec![inner.clone()])?;
7707                                            return Ok(Value::Variant {
7708                                                enum_name: "Option".to_string(),
7709                                                variant_name: "Some".to_string(),
7710                                                fields: Some(Rc::new(vec![result])),
7711                                            });
7712                                        }
7713                                    }
7714                                }
7715                            }
7716                            return Ok(Value::Variant {
7717                                enum_name: "Option".to_string(),
7718                                variant_name: "None".to_string(),
7719                                fields: None,
7720                            });
7721                        }
7722                        "and_then" => {
7723                            // Option::and_then takes a closure that returns Option<U>
7724                            crate::sigil_debug!(
7725                                "DEBUG and_then: variant={}, has_fields={}, arg_count={}",
7726                                variant_name,
7727                                fields.is_some(),
7728                                arg_values.len()
7729                            );
7730                            if let Some(arg) = arg_values.first() {
7731                                crate::sigil_debug!(
7732                                    "DEBUG and_then: arg type = {:?}",
7733                                    std::mem::discriminant(arg)
7734                                );
7735                            }
7736                            if variant_name == "Some" {
7737                                if let Some(f) = fields {
7738                                    if let Some(inner) = f.first() {
7739                                        crate::sigil_debug!("DEBUG and_then: inner = {:?}", inner);
7740                                        if let Some(Value::Function(func)) = arg_values.first() {
7741                                            let result =
7742                                                self.call_function(func, vec![inner.clone()])?;
7743                                            crate::sigil_debug!(
7744                                                "DEBUG and_then: result = {:?}",
7745                                                result
7746                                            );
7747                                            // The closure should return an Option, return it directly
7748                                            return Ok(result);
7749                                        } else {
7750                                            crate::sigil_debug!(
7751                                                "DEBUG and_then: arg is not a Function!"
7752                                            );
7753                                        }
7754                                    }
7755                                }
7756                            }
7757                            // None case - return None
7758                            return Ok(Value::Variant {
7759                                enum_name: "Option".to_string(),
7760                                variant_name: "None".to_string(),
7761                                fields: None,
7762                            });
7763                        }
7764                        "or_else" => {
7765                            // Option::or_else takes a closure that returns Option<T>
7766                            if variant_name == "Some" {
7767                                // Some case - return self
7768                                return Ok(recv.clone());
7769                            }
7770                            // None case - call the closure
7771                            if let Some(Value::Function(func)) = arg_values.first() {
7772                                return self.call_function(func, vec![]);
7773                            }
7774                            return Ok(recv.clone());
7775                        }
7776                        "ok_or" | "ok_or_else" => {
7777                            // Convert Option to Result
7778                            if variant_name == "Some" {
7779                                if let Some(f) = fields {
7780                                    if let Some(inner) = f.first() {
7781                                        return Ok(Value::Variant {
7782                                            enum_name: "Result".to_string(),
7783                                            variant_name: "Ok".to_string(),
7784                                            fields: Some(Rc::new(vec![inner.clone()])),
7785                                        });
7786                                    }
7787                                }
7788                            }
7789                            // None case - return Err with the provided value
7790                            let err_val = arg_values
7791                                .first()
7792                                .cloned()
7793                                .unwrap_or(Value::String(Rc::new("None".to_string())));
7794                            return Ok(Value::Variant {
7795                                enum_name: "Result".to_string(),
7796                                variant_name: "Err".to_string(),
7797                                fields: Some(Rc::new(vec![err_val])),
7798                            });
7799                        }
7800                        _ => {}
7801                    }
7802                }
7803                // Built-in Result methods
7804                if enum_name == "Result" {
7805                    match method.name.as_str() {
7806                        "is_ok" => {
7807                            return Ok(Value::Bool(variant_name == "Ok"));
7808                        }
7809                        "is_err" => {
7810                            return Ok(Value::Bool(variant_name == "Err"));
7811                        }
7812                        "ok" => {
7813                            // Convert Result<T, E> to Option<T>
7814                            // Ok(val) -> Some(val), Err(_) -> None
7815                            if variant_name == "Ok" {
7816                                let inner = fields
7817                                    .as_ref()
7818                                    .and_then(|f| f.first().cloned())
7819                                    .unwrap_or(Value::Null);
7820                                return Ok(Value::Variant {
7821                                    enum_name: "Option".to_string(),
7822                                    variant_name: "Some".to_string(),
7823                                    fields: Some(Rc::new(vec![inner])),
7824                                });
7825                            }
7826                            return Ok(Value::Variant {
7827                                enum_name: "Option".to_string(),
7828                                variant_name: "None".to_string(),
7829                                fields: None,
7830                            });
7831                        }
7832                        "err" => {
7833                            // Convert Result<T, E> to Option<E>
7834                            // Ok(_) -> None, Err(e) -> Some(e)
7835                            if variant_name == "Err" {
7836                                let inner = fields
7837                                    .as_ref()
7838                                    .and_then(|f| f.first().cloned())
7839                                    .unwrap_or(Value::Null);
7840                                return Ok(Value::Variant {
7841                                    enum_name: "Option".to_string(),
7842                                    variant_name: "Some".to_string(),
7843                                    fields: Some(Rc::new(vec![inner])),
7844                                });
7845                            }
7846                            return Ok(Value::Variant {
7847                                enum_name: "Option".to_string(),
7848                                variant_name: "None".to_string(),
7849                                fields: None,
7850                            });
7851                        }
7852                        "unwrap" => {
7853                            if variant_name == "Ok" {
7854                                if let Some(f) = fields {
7855                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
7856                                }
7857                            }
7858                            return Err(RuntimeError::new("unwrap on Err"));
7859                        }
7860                        "unwrap_or" => {
7861                            if variant_name == "Ok" {
7862                                if let Some(f) = fields {
7863                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
7864                                }
7865                            }
7866                            return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
7867                        }
7868                        "map" => {
7869                            // map(fn) - apply fn to Ok value, leave Err unchanged
7870                            if variant_name == "Ok" {
7871                                if let Some(Value::Function(f)) = arg_values.first() {
7872                                    let inner = fields
7873                                        .as_ref()
7874                                        .and_then(|f| f.first().cloned())
7875                                        .unwrap_or(Value::Null);
7876                                    let result = self.call_function(f, vec![inner])?;
7877                                    return Ok(Value::Variant {
7878                                        enum_name: "Result".to_string(),
7879                                        variant_name: "Ok".to_string(),
7880                                        fields: Some(Rc::new(vec![result])),
7881                                    });
7882                                }
7883                            }
7884                            // For Err variant, return unchanged
7885                            return Ok(recv.clone());
7886                        }
7887                        "map_err" => {
7888                            // map_err(fn) - apply fn to Err value, leave Ok unchanged
7889                            if variant_name == "Err" {
7890                                if let Some(Value::Function(f)) = arg_values.first() {
7891                                    let inner = fields
7892                                        .as_ref()
7893                                        .and_then(|f| f.first().cloned())
7894                                        .unwrap_or(Value::Null);
7895                                    let result = self.call_function(f, vec![inner])?;
7896                                    return Ok(Value::Variant {
7897                                        enum_name: "Result".to_string(),
7898                                        variant_name: "Err".to_string(),
7899                                        fields: Some(Rc::new(vec![result])),
7900                                    });
7901                                }
7902                            }
7903                            // For Ok variant, return unchanged
7904                            return Ok(recv.clone());
7905                        }
7906                        "and_then" => {
7907                            // and_then(fn) - chain Result-returning functions
7908                            if variant_name == "Ok" {
7909                                if let Some(Value::Function(f)) = arg_values.first() {
7910                                    let inner = fields
7911                                        .as_ref()
7912                                        .and_then(|f| f.first().cloned())
7913                                        .unwrap_or(Value::Null);
7914                                    return self.call_function(f, vec![inner]);
7915                                }
7916                            }
7917                            // For Err variant, return unchanged
7918                            return Ok(recv.clone());
7919                        }
7920                        _ => {}
7921                    }
7922                }
7923                // Pattern methods - for AST pattern access
7924                crate::sigil_debug!(
7925                    "DEBUG variant method call: enum_name={}, variant_name={}, method={}",
7926                    enum_name,
7927                    variant_name,
7928                    method.name
7929                );
7930
7931                // Type methods
7932                if enum_name == "Type" {
7933                    match method.name.as_str() {
7934                        "is_never" => {
7935                            // Type::Never is the never type, all others are not
7936                            return Ok(Value::Bool(variant_name == "Never"));
7937                        }
7938                        "to_string" => {
7939                            // Convert type to string representation
7940                            let type_str = match variant_name.as_str() {
7941                                "Bool" => "bool".to_string(),
7942                                "Int" => "i64".to_string(),
7943                                "Float" => "f64".to_string(),
7944                                "Str" => "str".to_string(),
7945                                "Char" => "char".to_string(),
7946                                "Unit" => "()".to_string(),
7947                                "Never" => "!".to_string(),
7948                                "Error" => "<error>".to_string(),
7949                                other => format!("Type::{}", other),
7950                            };
7951                            return Ok(Value::String(Rc::new(type_str)));
7952                        }
7953                        _ => {}
7954                    }
7955                }
7956
7957                if enum_name == "Pattern" {
7958                    match method.name.as_str() {
7959                        "evidentiality" => {
7960                            // Pattern::Ident { name, mutable, evidentiality } - return the evidentiality field
7961                            if variant_name == "Ident" {
7962                                if let Some(f) = fields {
7963                                    // Fields are stored as a struct or in order
7964                                    // Try to find evidentiality field
7965                                    for field_val in f.iter() {
7966                                        if let Value::Struct { fields: inner, .. } = field_val {
7967                                            if let Some(ev) = inner.borrow().get("evidentiality") {
7968                                                return Ok(ev.clone());
7969                                            }
7970                                        }
7971                                    }
7972                                    // If fields are stored in order: name, mutable, evidentiality (index 2)
7973                                    if f.len() > 2 {
7974                                        return Ok(f[2].clone());
7975                                    }
7976                                }
7977                            }
7978                            // No evidentiality for other pattern types
7979                            return Ok(Value::Null);
7980                        }
7981                        "name" => {
7982                            // Get the name from Pattern::Ident
7983                            if variant_name == "Ident" {
7984                                if let Some(f) = fields {
7985                                    for field_val in f.iter() {
7986                                        if let Value::Struct { fields: inner, .. } = field_val {
7987                                            if let Some(n) = inner.borrow().get("name") {
7988                                                return Ok(n.clone());
7989                                            }
7990                                        }
7991                                    }
7992                                    // First field is name
7993                                    if let Some(n) = f.first() {
7994                                        return Ok(n.clone());
7995                                    }
7996                                }
7997                            }
7998                            return Ok(Value::Null);
7999                        }
8000                        "mutable" => {
8001                            // Get mutable flag from Pattern::Ident
8002                            if variant_name == "Ident" {
8003                                if let Some(f) = fields {
8004                                    for field_val in f.iter() {
8005                                        if let Value::Struct { fields: inner, .. } = field_val {
8006                                            if let Some(m) = inner.borrow().get("mutable") {
8007                                                return Ok(m.clone());
8008                                            }
8009                                        }
8010                                    }
8011                                    // Second field is mutable
8012                                    if f.len() > 1 {
8013                                        return Ok(f[1].clone());
8014                                    }
8015                                }
8016                            }
8017                            return Ok(Value::Bool(false));
8018                        }
8019                        _ => {}
8020                    }
8021                }
8022                // Built-in clone method for all variants
8023                if method.name == "clone" {
8024                    return Ok(recv.clone());
8025                }
8026
8027                let qualified_name = format!("{}·{}", enum_name, method.name);
8028                let func = self
8029                    .globals
8030                    .borrow()
8031                    .get(&qualified_name)
8032                    .map(|v| v.clone());
8033                if let Some(func) = func {
8034                    if let Value::Function(f) = func {
8035                        let mut all_args = vec![recv.clone()];
8036                        all_args.extend(arg_values.clone());
8037                        return self.call_function(&f, all_args);
8038                    } else if let Value::BuiltIn(b) = func {
8039                        let mut all_args = vec![recv.clone()];
8040                        all_args.extend(arg_values.clone());
8041                        return (b.func)(self, all_args);
8042                    }
8043                }
8044                // Fallback for unknown methods on external enum types: return null
8045                crate::sigil_warn!(
8046                    "WARN: Unknown method '{}' on enum '{}' - returning null",
8047                    method.name,
8048                    enum_name
8049                );
8050                Ok(Value::Null)
8051            }
8052            // Null-safe method handlers - methods called on null return sensible defaults
8053            (Value::Null, "len_utf8") => Ok(Value::Int(0)),
8054            (Value::Null, "is_ascii") => Ok(Value::Bool(false)),
8055            (Value::Null, "is_alphabetic") => Ok(Value::Bool(false)),
8056            (Value::Null, "is_alphanumeric") => Ok(Value::Bool(false)),
8057            (Value::Null, "is_numeric") | (Value::Null, "is_digit") => Ok(Value::Bool(false)),
8058            (Value::Null, "is_whitespace") => Ok(Value::Bool(false)),
8059            (Value::Null, "is_uppercase") => Ok(Value::Bool(false)),
8060            (Value::Null, "is_lowercase") => Ok(Value::Bool(false)),
8061            (Value::Null, "len") => Ok(Value::Int(0)),
8062            (Value::Null, "is_empty") => Ok(Value::Bool(true)),
8063            (Value::Null, "to_string") => Ok(Value::String(Rc::new("".to_string()))),
8064            (Value::Null, "clone") => Ok(Value::Null),
8065            (Value::Null, "is_some") => Ok(Value::Bool(false)),
8066            (Value::Null, "is_none") => Ok(Value::Bool(true)),
8067            (Value::Null, "unwrap_or") => {
8068                if arg_values.is_empty() {
8069                    Ok(Value::Null)
8070                } else {
8071                    Ok(arg_values[0].clone())
8072                }
8073            }
8074            // unwrap_or for non-null values returns the value itself
8075            (Value::Char(c), "unwrap_or") => Ok(Value::Char(*c)),
8076            (Value::Int(n), "unwrap_or") => Ok(Value::Int(*n)),
8077            (Value::Float(n), "unwrap_or") => Ok(Value::Float(*n)),
8078            (Value::String(s), "unwrap_or") => Ok(Value::String(s.clone())),
8079            (Value::Bool(b), "unwrap_or") => Ok(Value::Bool(*b)),
8080            // Int methods
8081            (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
8082                Ok(Value::String(Rc::new(n.to_string())))
8083            }
8084            (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
8085            (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
8086            (Value::Int(n), "duration_since") => {
8087                // Treat Int as nanoseconds since some epoch
8088                // Return a Duration struct
8089                let other_ns = match arg_values.first() {
8090                    Some(Value::Int(i)) => *i,
8091                    Some(Value::Struct { fields, .. }) => {
8092                        let borrowed = fields.borrow();
8093                        let secs = match borrowed.get("secs") {
8094                            Some(Value::Int(s)) => *s,
8095                            _ => 0,
8096                        };
8097                        let nanos = match borrowed.get("nanos") {
8098                            Some(Value::Int(n)) => *n,
8099                            _ => 0,
8100                        };
8101                        secs * 1_000_000_000 + nanos
8102                    }
8103                    _ => 0,
8104                };
8105                let diff_ns = n - other_ns;
8106                let mut fields = std::collections::HashMap::new();
8107                fields.insert("secs".to_string(), Value::Int(diff_ns / 1_000_000_000));
8108                fields.insert("nanos".to_string(), Value::Int(diff_ns % 1_000_000_000));
8109                Ok(Value::Variant {
8110                    enum_name: "Result".to_string(),
8111                    variant_name: "Ok".to_string(),
8112                    fields: Some(Rc::new(vec![Value::Struct {
8113                        name: "Duration".to_string(),
8114                        fields: Rc::new(RefCell::new(fields)),
8115                    }])),
8116                })
8117            }
8118            // Float methods
8119            (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
8120                Ok(Value::String(Rc::new(n.to_string())))
8121            }
8122            (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
8123            (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
8124            // Bool methods
8125            (Value::Bool(b), "to_string") | (Value::Bool(b), "string") => {
8126                Ok(Value::String(Rc::new(b.to_string())))
8127            }
8128            // Char methods
8129            (Value::Char(c), "to_string") | (Value::Char(c), "string") => {
8130                Ok(Value::String(Rc::new(c.to_string())))
8131            }
8132            _ => {
8133                // Debug: what type is failing method lookup
8134                let recv_type = match &recv {
8135                    Value::String(s) => format!("String(len={})", s.len()),
8136                    Value::Array(arr) => format!("Array(len={})", arr.borrow().len()),
8137                    Value::Struct { name, .. } => format!("Struct({})", name),
8138                    Value::Variant {
8139                        enum_name,
8140                        variant_name,
8141                        ..
8142                    } => format!("Variant({}::{})", enum_name, variant_name),
8143                    Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
8144                    Value::Null => "Null".to_string(),
8145                    other => format!("{:?}", std::mem::discriminant(other)),
8146                };
8147                crate::sigil_warn!(
8148                    "WARN: Unknown method '{}' on recv_type={} - returning null",
8149                    method.name,
8150                    recv_type
8151                );
8152                // Fallback for unknown methods: return null to allow external crate types
8153                Ok(Value::Null)
8154            }
8155        }
8156    }
8157
8158    /// Evaluate polysynthetic incorporation: path·file·read·string
8159    /// The first segment provides the initial value, subsequent segments are method-like transformations
8160    fn eval_incorporation(
8161        &mut self,
8162        segments: &[IncorporationSegment],
8163    ) -> Result<Value, RuntimeError> {
8164        if segments.is_empty() {
8165            return Err(RuntimeError::new("empty incorporation chain"));
8166        }
8167
8168        // First segment: get initial value (variable lookup or function call)
8169        let first = &segments[0];
8170        let mut value = if let Some(args) = &first.args {
8171            // First segment is a function call: func(args)·next·...
8172            let arg_values: Vec<Value> = args
8173                .iter()
8174                .map(|a| self.evaluate(a))
8175                .collect::<Result<_, _>>()?;
8176            self.call_function_by_name(&first.name.name, arg_values)?
8177        } else {
8178            // First segment is a variable: var·next·...
8179            self.environment
8180                .borrow()
8181                .get(&first.name.name)
8182                .ok_or_else(|| RuntimeError::new(format!("undefined: {}", first.name.name)))?
8183        };
8184
8185        // Process remaining segments as method-like calls
8186        for segment in segments.iter().skip(1) {
8187            let arg_values: Vec<Value> = segment
8188                .args
8189                .as_ref()
8190                .map(|args| {
8191                    args.iter()
8192                        .map(|a| self.evaluate(a))
8193                        .collect::<Result<Vec<_>, _>>()
8194                })
8195                .transpose()?
8196                .unwrap_or_default();
8197
8198            // Try to call as a method on the value
8199            value = self.call_incorporation_method(&value, &segment.name.name, arg_values)?;
8200        }
8201
8202        Ok(value)
8203    }
8204
8205    /// Call a method in an incorporation chain
8206    /// This looks up the segment name as a method or stdlib function
8207    fn call_incorporation_method(
8208        &mut self,
8209        receiver: &Value,
8210        method_name: &str,
8211        args: Vec<Value>,
8212    ) -> Result<Value, RuntimeError> {
8213        // First try as a method on the receiver value
8214        match (receiver, method_name) {
8215            // String methods
8216            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
8217            (Value::String(s), "upper")
8218            | (Value::String(s), "uppercase")
8219            | (Value::String(s), "to_uppercase") => Ok(Value::String(Rc::new(s.to_uppercase()))),
8220            (Value::String(s), "lower")
8221            | (Value::String(s), "lowercase")
8222            | (Value::String(s), "to_lowercase") => Ok(Value::String(Rc::new(s.to_lowercase()))),
8223            (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
8224            (Value::String(s), "chars") => {
8225                let chars: Vec<Value> = s
8226                    .chars()
8227                    .map(|c| Value::String(Rc::new(c.to_string())))
8228                    .collect();
8229                Ok(Value::Array(Rc::new(RefCell::new(chars))))
8230            }
8231            (Value::String(s), "lines") => {
8232                let lines: Vec<Value> = s
8233                    .lines()
8234                    .map(|l| Value::String(Rc::new(l.to_string())))
8235                    .collect();
8236                Ok(Value::Array(Rc::new(RefCell::new(lines))))
8237            }
8238            (Value::String(s), "bytes") => {
8239                let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
8240                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
8241            }
8242            (Value::String(s), "parse_int") | (Value::String(s), "to_int") => s
8243                .parse::<i64>()
8244                .map(Value::Int)
8245                .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as int", s))),
8246            (Value::String(s), "parse_float") | (Value::String(s), "to_float") => s
8247                .parse::<f64>()
8248                .map(Value::Float)
8249                .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as float", s))),
8250            (Value::String(s), "as_str") => {
8251                if s.len() <= 10 {
8252                    crate::sigil_debug!("DEBUG as_str: '{}'", s);
8253                }
8254                Ok(Value::String(s.clone()))
8255            }
8256            (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
8257            (Value::String(s), "starts_with") => {
8258                if args.len() != 1 {
8259                    return Err(RuntimeError::new("starts_with expects 1 argument"));
8260                }
8261                match &args[0] {
8262                    Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
8263                    _ => Err(RuntimeError::new("starts_with expects string")),
8264                }
8265            }
8266            (Value::String(s), "ends_with") => {
8267                if args.len() != 1 {
8268                    return Err(RuntimeError::new("ends_with expects 1 argument"));
8269                }
8270                match &args[0] {
8271                    Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
8272                    _ => Err(RuntimeError::new("ends_with expects string")),
8273                }
8274            }
8275            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
8276            (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
8277            (Value::String(s), "first") => s
8278                .chars()
8279                .next()
8280                .map(Value::Char)
8281                .ok_or_else(|| RuntimeError::new("empty string")),
8282            (Value::String(s), "last") => s
8283                .chars()
8284                .last()
8285                .map(Value::Char)
8286                .ok_or_else(|| RuntimeError::new("empty string")),
8287
8288            // Array methods
8289            (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
8290            (Value::Array(arr), "first") | (Value::Array(arr), "next") => {
8291                Ok(arr.borrow().first().cloned().unwrap_or(Value::Null))
8292            }
8293            (Value::Array(arr), "last") => arr
8294                .borrow()
8295                .last()
8296                .cloned()
8297                .ok_or_else(|| RuntimeError::new("empty array")),
8298            (Value::Array(arr), "reverse") | (Value::Array(arr), "rev") => {
8299                let mut v = arr.borrow().clone();
8300                v.reverse();
8301                Ok(Value::Array(Rc::new(RefCell::new(v))))
8302            }
8303            (Value::Array(arr), "join") => {
8304                let sep = args
8305                    .first()
8306                    .map(|v| match v {
8307                        Value::String(s) => s.to_string(),
8308                        _ => "".to_string(),
8309                    })
8310                    .unwrap_or_default();
8311                let joined = arr
8312                    .borrow()
8313                    .iter()
8314                    .map(|v| format!("{}", v))
8315                    .collect::<Vec<_>>()
8316                    .join(&sep);
8317                Ok(Value::String(Rc::new(joined)))
8318            }
8319            (Value::Array(arr), "sum") => {
8320                let mut sum = 0i64;
8321                for v in arr.borrow().iter() {
8322                    match v {
8323                        Value::Int(i) => sum += i,
8324                        Value::Float(f) => return Ok(Value::Float(sum as f64 + f)),
8325                        _ => {}
8326                    }
8327                }
8328                Ok(Value::Int(sum))
8329            }
8330            (Value::Array(arr), "skip") => {
8331                let n = match args.first() {
8332                    Some(Value::Int(i)) => *i as usize,
8333                    _ => 1,
8334                };
8335                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
8336                Ok(Value::Array(Rc::new(RefCell::new(v))))
8337            }
8338            (Value::Array(arr), "take") => {
8339                let n = match args.first() {
8340                    Some(Value::Int(i)) => *i as usize,
8341                    _ => 1,
8342                };
8343                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
8344                Ok(Value::Array(Rc::new(RefCell::new(v))))
8345            }
8346            (Value::Array(arr), "step_by") => {
8347                let n = match args.first() {
8348                    Some(Value::Int(i)) if *i > 0 => *i as usize,
8349                    _ => 1,
8350                };
8351                let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
8352                Ok(Value::Array(Rc::new(RefCell::new(v))))
8353            }
8354
8355            // Number methods
8356            (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
8357            (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
8358            (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
8359                Ok(Value::String(Rc::new(n.to_string())))
8360            }
8361            (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
8362                Ok(Value::String(Rc::new(n.to_string())))
8363            }
8364            (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
8365            (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
8366
8367            // Map/Struct field access
8368            (Value::Map(map), field) => map
8369                .borrow()
8370                .get(field)
8371                .cloned()
8372                .ok_or_else(|| RuntimeError::new(format!("no field '{}' in map", field))),
8373            (Value::Struct { fields, .. }, field) => fields
8374                .borrow()
8375                .get(field)
8376                .cloned()
8377                .ok_or_else(|| RuntimeError::new(format!("no field '{}' in struct", field))),
8378
8379            // Try stdlib function with receiver as first arg
8380            _ => {
8381                let mut all_args = vec![receiver.clone()];
8382                all_args.extend(args);
8383                self.call_function_by_name(method_name, all_args)
8384            }
8385        }
8386    }
8387
8388    /// Call a function by name from the environment
8389    pub fn call_function_by_name(
8390        &mut self,
8391        name: &str,
8392        args: Vec<Value>,
8393    ) -> Result<Value, RuntimeError> {
8394        // Get the function value from environment (clone to avoid borrow issues)
8395        let func_value = self.environment.borrow().get(name);
8396
8397        match func_value {
8398            Some(Value::Function(f)) => self.call_function(&f, args),
8399            Some(Value::BuiltIn(b)) => self.call_builtin(&b, args),
8400            Some(_) => Err(RuntimeError::new(format!("{} is not a function", name))),
8401            None => {
8402                // Check for variant constructor
8403                if let Some((enum_name, variant_name, arity)) =
8404                    self.variant_constructors.get(name).cloned()
8405                {
8406                    if arity == 0 && args.is_empty() {
8407                        return Ok(Value::Variant {
8408                            enum_name,
8409                            variant_name,
8410                            fields: None,
8411                        });
8412                    } else if args.len() == arity {
8413                        return Ok(Value::Variant {
8414                            enum_name,
8415                            variant_name,
8416                            fields: Some(Rc::new(args)),
8417                        });
8418                    } else {
8419                        return Err(RuntimeError::new(format!(
8420                            "{} expects {} arguments, got {}",
8421                            name,
8422                            arity,
8423                            args.len()
8424                        )));
8425                    }
8426                }
8427                Err(RuntimeError::new(format!("undefined function: {}", name)))
8428            }
8429        }
8430    }
8431
8432    fn eval_pipe(&mut self, expr: &Expr, operations: &[PipeOp]) -> Result<Value, RuntimeError> {
8433        let mut value = self.evaluate(expr)?;
8434
8435        for op in operations {
8436            value = self.apply_pipe_op(value, op)?;
8437        }
8438
8439        Ok(value)
8440    }
8441
8442    fn apply_pipe_op(&mut self, value: Value, op: &PipeOp) -> Result<Value, RuntimeError> {
8443        // Unwrap evidential/affective wrappers for pipe operations
8444        let value = Self::unwrap_all(&value);
8445
8446        match op {
8447            PipeOp::Transform(body) => {
8448                // τ{f} - map over collection or apply to single value
8449                // Extract closure parameter pattern and body
8450                let (param_pattern, inner_body) = match body.as_ref() {
8451                    Expr::Closure { params, body, .. } => {
8452                        let pattern = params.first().map(|p| p.pattern.clone());
8453                        (pattern, body.as_ref())
8454                    }
8455                    _ => (None, body.as_ref()),
8456                };
8457
8458                match value {
8459                    Value::Array(arr) => {
8460                        let results: Vec<Value> = arr
8461                            .borrow()
8462                            .iter()
8463                            .map(|item| {
8464                                // Bind the item to the pattern (supports tuple destructuring)
8465                                if let Some(ref pattern) = param_pattern {
8466                                    self.bind_pattern(pattern, item.clone())?;
8467                                } else {
8468                                    self.environment
8469                                        .borrow_mut()
8470                                        .define("_".to_string(), item.clone());
8471                                }
8472                                self.evaluate(inner_body)
8473                            })
8474                            .collect::<Result<_, _>>()?;
8475                        Ok(Value::Array(Rc::new(RefCell::new(results))))
8476                    }
8477                    single => {
8478                        if let Some(ref pattern) = param_pattern {
8479                            self.bind_pattern(pattern, single)?;
8480                        } else {
8481                            self.environment
8482                                .borrow_mut()
8483                                .define("_".to_string(), single);
8484                        }
8485                        self.evaluate(inner_body)
8486                    }
8487                }
8488            }
8489            PipeOp::Filter(predicate) => {
8490                // φ{p} - filter collection
8491                // Extract closure parameter pattern and body
8492                let (param_pattern, inner_pred) = match predicate.as_ref() {
8493                    Expr::Closure { params, body, .. } => {
8494                        let pattern = params.first().map(|p| p.pattern.clone());
8495                        (pattern, body.as_ref())
8496                    }
8497                    _ => (None, predicate.as_ref()),
8498                };
8499
8500                match value {
8501                    Value::Array(arr) => {
8502                        let results: Vec<Value> = arr
8503                            .borrow()
8504                            .iter()
8505                            .filter_map(|item| {
8506                                // Bind the item to the pattern (supports tuple destructuring)
8507                                if let Some(ref pattern) = param_pattern {
8508                                    if let Err(e) = self.bind_pattern(pattern, item.clone()) {
8509                                        return Some(Err(e));
8510                                    }
8511                                } else {
8512                                    self.environment
8513                                        .borrow_mut()
8514                                        .define("_".to_string(), item.clone());
8515                                }
8516                                match self.evaluate(inner_pred) {
8517                                    Ok(v) if self.is_truthy(&v) => Some(Ok(item.clone())),
8518                                    Ok(_) => None,
8519                                    Err(e) => Some(Err(e)),
8520                                }
8521                            })
8522                            .collect::<Result<_, _>>()?;
8523                        Ok(Value::Array(Rc::new(RefCell::new(results))))
8524                    }
8525                    _ => Err(RuntimeError::new("Filter requires array")),
8526                }
8527            }
8528            PipeOp::Sort(field) => {
8529                // σ - sort collection
8530                match value {
8531                    Value::Array(arr) => {
8532                        let mut v = arr.borrow().clone();
8533                        v.sort_by(|a, b| self.compare_values(a, b, field));
8534                        Ok(Value::Array(Rc::new(RefCell::new(v))))
8535                    }
8536                    _ => Err(RuntimeError::new("Sort requires array")),
8537                }
8538            }
8539            PipeOp::Reduce(body) => {
8540                // ρ{f} - reduce collection
8541                match value {
8542                    Value::Array(arr) => {
8543                        let arr = arr.borrow();
8544                        if arr.is_empty() {
8545                            return Err(RuntimeError::new("Cannot reduce empty array"));
8546                        }
8547                        let mut acc = arr[0].clone();
8548                        for item in arr.iter().skip(1) {
8549                            self.environment.borrow_mut().define("acc".to_string(), acc);
8550                            self.environment
8551                                .borrow_mut()
8552                                .define("_".to_string(), item.clone());
8553                            acc = self.evaluate(body)?;
8554                        }
8555                        Ok(acc)
8556                    }
8557                    _ => Err(RuntimeError::new("Reduce requires array")),
8558                }
8559            }
8560            PipeOp::ReduceSum => {
8561                // ρ+ or ρ_sum - sum all elements
8562                self.sum_values(value)
8563            }
8564            PipeOp::ReduceProd => {
8565                // ρ* or ρ_prod - multiply all elements
8566                self.product_values(value)
8567            }
8568            PipeOp::ReduceMin => {
8569                // ρ_min - find minimum element
8570                self.min_values(value)
8571            }
8572            PipeOp::ReduceMax => {
8573                // ρ_max - find maximum element
8574                self.max_values(value)
8575            }
8576            PipeOp::ReduceConcat => {
8577                // ρ++ or ρ_cat - concatenate strings/arrays
8578                self.concat_values(value)
8579            }
8580            PipeOp::ReduceAll => {
8581                // ρ& or ρ_all - logical AND (all true)
8582                self.all_values(value)
8583            }
8584            PipeOp::ReduceAny => {
8585                // ρ| or ρ_any - logical OR (any true)
8586                self.any_values(value)
8587            }
8588            PipeOp::Match(arms) => {
8589                // |match{ Pattern => expr, ... } - pattern matching in pipe
8590                for arm in arms {
8591                    if self.pattern_matches(&arm.pattern, &value)? {
8592                        // Create new scope for pattern bindings
8593                        let prev_env = self.environment.clone();
8594                        self.environment =
8595                            Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
8596
8597                        // Bind pattern variables
8598                        self.bind_pattern(&arm.pattern, value.clone())?;
8599
8600                        // Also bind _ to the piped value for convenient access
8601                        self.environment
8602                            .borrow_mut()
8603                            .define("_".to_string(), value.clone());
8604
8605                        // Check guard if present
8606                        let guard_passes = if let Some(guard) = &arm.guard {
8607                            matches!(self.evaluate(guard)?, Value::Bool(true))
8608                        } else {
8609                            true
8610                        };
8611
8612                        if guard_passes {
8613                            let result = self.evaluate(&arm.body)?;
8614                            self.environment = prev_env;
8615                            return Ok(result);
8616                        }
8617
8618                        // Guard failed, restore environment and try next arm
8619                        self.environment = prev_env;
8620                    }
8621                }
8622                Err(RuntimeError::new("No pattern matched in pipe match"))
8623            }
8624            PipeOp::TryMap(mapper) => {
8625                // |? or |?{mapper} - unwrap Result/Option or transform error
8626                match &value {
8627                    // Handle Result-like values (struct with ok/err fields)
8628                    Value::Struct { name, fields } if name == "Ok" || name.ends_with("::Ok") => {
8629                        // Extract the inner value from Ok
8630                        let fields = fields.borrow();
8631                        fields
8632                            .get("0")
8633                            .or_else(|| fields.get("value"))
8634                            .cloned()
8635                            .ok_or_else(|| RuntimeError::new("Ok variant has no value"))
8636                    }
8637                    Value::Struct { name, fields } if name == "Err" || name.ends_with("::Err") => {
8638                        // Transform error if mapper provided, otherwise propagate
8639                        let fields = fields.borrow();
8640                        let err_val = fields
8641                            .get("0")
8642                            .or_else(|| fields.get("error"))
8643                            .cloned()
8644                            .unwrap_or(Value::Null);
8645                        if let Some(mapper_expr) = mapper {
8646                            // Apply mapper to error
8647                            let prev_env = self.environment.clone();
8648                            self.environment =
8649                                Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
8650                            self.environment
8651                                .borrow_mut()
8652                                .define("_".to_string(), err_val);
8653                            let mapped = self.evaluate(mapper_expr)?;
8654                            self.environment = prev_env;
8655                            Err(RuntimeError::new(format!("Error: {:?}", mapped)))
8656                        } else {
8657                            Err(RuntimeError::new(format!("Error: {:?}", err_val)))
8658                        }
8659                    }
8660                    // Handle Option-like values
8661                    Value::Struct { name, fields }
8662                        if name == "Some" || name.ends_with("::Some") =>
8663                    {
8664                        let fields = fields.borrow();
8665                        fields
8666                            .get("0")
8667                            .or_else(|| fields.get("value"))
8668                            .cloned()
8669                            .ok_or_else(|| RuntimeError::new("Some variant has no value"))
8670                    }
8671                    Value::Struct { name, .. } if name == "None" || name.ends_with("::None") => {
8672                        Err(RuntimeError::new("Unwrapped None value"))
8673                    }
8674                    Value::Null => Err(RuntimeError::new("Unwrapped null value")),
8675                    // Pass through non-Result/Option values unchanged
8676                    _ => Ok(value),
8677                }
8678            }
8679            PipeOp::Call(callee) => {
8680                // |expr - call an arbitrary expression (like self.layer) with piped value
8681                let callee_val = self.evaluate(callee)?;
8682                match callee_val {
8683                    Value::Function(f) => {
8684                        // Call the function with the piped value as argument
8685                        self.call_function(&f, vec![value])
8686                    }
8687                    Value::BuiltIn(b) => {
8688                        // Call built-in with the piped value
8689                        self.call_builtin(&b, vec![value])
8690                    }
8691                    Value::Struct { .. } => {
8692                        // Structs that implement __call__ can be called as functions
8693                        // For now, just return the value (ML layers would override)
8694                        Ok(value)
8695                    }
8696                    _ => Err(RuntimeError::new(format!(
8697                        "Cannot call non-function value in pipe: {:?}",
8698                        callee_val
8699                    ))),
8700                }
8701            }
8702            PipeOp::Method {
8703                name,
8704                type_args: _,
8705                args,
8706            } => {
8707                let arg_values: Vec<Value> = args
8708                    .iter()
8709                    .map(|a| self.evaluate(a))
8710                    .collect::<Result<_, _>>()?;
8711
8712                // Check for built-in pipe methods
8713                match name.name.as_str() {
8714                    "collect" => Ok(value), // Already collected
8715                    "sum" | "Σ" => self.sum_values(value),
8716                    "product" | "Π" => self.product_values(value),
8717                    "len" => match &value {
8718                        Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
8719                        Value::String(s) => Ok(Value::Int(s.len() as i64)),
8720                        _ => Err(RuntimeError::new("len requires array or string")),
8721                    },
8722                    "reverse" => match value {
8723                        Value::Array(arr) => {
8724                            let mut v = arr.borrow().clone();
8725                            v.reverse();
8726                            Ok(Value::Array(Rc::new(RefCell::new(v))))
8727                        }
8728                        _ => Err(RuntimeError::new("reverse requires array")),
8729                    },
8730                    "iter" | "into_iter" => {
8731                        // iter()/into_iter() returns the array for iteration (identity operation)
8732                        Ok(value)
8733                    }
8734                    "enumerate" => {
8735                        // enumerate() returns array of (index, value) tuples
8736                        match &value {
8737                            Value::Array(arr) => {
8738                                let enumerated: Vec<Value> = arr
8739                                    .borrow()
8740                                    .iter()
8741                                    .enumerate()
8742                                    .map(|(i, v)| {
8743                                        Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
8744                                    })
8745                                    .collect();
8746                                Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
8747                            }
8748                            _ => Err(RuntimeError::new("enumerate requires array")),
8749                        }
8750                    }
8751                    "first" => match &value {
8752                        Value::Array(arr) => arr
8753                            .borrow()
8754                            .first()
8755                            .cloned()
8756                            .ok_or_else(|| RuntimeError::new("first on empty array")),
8757                        _ => Err(RuntimeError::new("first requires array")),
8758                    },
8759                    "last" => match &value {
8760                        Value::Array(arr) => arr
8761                            .borrow()
8762                            .last()
8763                            .cloned()
8764                            .ok_or_else(|| RuntimeError::new("last on empty array")),
8765                        _ => Err(RuntimeError::new("last requires array")),
8766                    },
8767                    "take" => {
8768                        if arg_values.len() != 1 {
8769                            return Err(RuntimeError::new("take requires 1 argument"));
8770                        }
8771                        let n = match &arg_values[0] {
8772                            Value::Int(n) => *n as usize,
8773                            _ => return Err(RuntimeError::new("take requires integer")),
8774                        };
8775                        match value {
8776                            Value::Array(arr) => {
8777                                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
8778                                Ok(Value::Array(Rc::new(RefCell::new(v))))
8779                            }
8780                            _ => Err(RuntimeError::new("take requires array")),
8781                        }
8782                    }
8783                    "skip" => {
8784                        if arg_values.len() != 1 {
8785                            return Err(RuntimeError::new("skip requires 1 argument"));
8786                        }
8787                        let n = match &arg_values[0] {
8788                            Value::Int(n) => *n as usize,
8789                            _ => return Err(RuntimeError::new("skip requires integer")),
8790                        };
8791                        match value {
8792                            Value::Array(arr) => {
8793                                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
8794                                Ok(Value::Array(Rc::new(RefCell::new(v))))
8795                            }
8796                            _ => Err(RuntimeError::new("skip requires array")),
8797                        }
8798                    }
8799                    "join" => {
8800                        // Join array elements with a separator string
8801                        let separator = if arg_values.is_empty() {
8802                            String::new()
8803                        } else {
8804                            match &arg_values[0] {
8805                                Value::String(s) => (**s).clone(),
8806                                _ => {
8807                                    return Err(RuntimeError::new("join separator must be string"))
8808                                }
8809                            }
8810                        };
8811                        match value {
8812                            Value::Array(arr) => {
8813                                let parts: Vec<String> = arr
8814                                    .borrow()
8815                                    .iter()
8816                                    .map(|v| format!("{}", Self::unwrap_all(v)))
8817                                    .collect();
8818                                Ok(Value::String(Rc::new(parts.join(&separator))))
8819                            }
8820                            _ => Err(RuntimeError::new("join requires array")),
8821                        }
8822                    }
8823                    "all" => {
8824                        // Check if all elements are truthy (no predicate in Method variant)
8825                        match value {
8826                            Value::Array(arr) => {
8827                                for item in arr.borrow().iter() {
8828                                    if !self.is_truthy(item) {
8829                                        return Ok(Value::Bool(false));
8830                                    }
8831                                }
8832                                Ok(Value::Bool(true))
8833                            }
8834                            _ => Err(RuntimeError::new("all requires array")),
8835                        }
8836                    }
8837                    "any" => {
8838                        // Check if any element is truthy
8839                        match value {
8840                            Value::Array(arr) => {
8841                                for item in arr.borrow().iter() {
8842                                    if self.is_truthy(item) {
8843                                        return Ok(Value::Bool(true));
8844                                    }
8845                                }
8846                                Ok(Value::Bool(false))
8847                            }
8848                            _ => Err(RuntimeError::new("any requires array")),
8849                        }
8850                    }
8851                    "map" => {
8852                        // map(closure) applies closure to each element
8853                        if arg_values.len() != 1 {
8854                            return Err(RuntimeError::new("map expects 1 argument (closure)"));
8855                        }
8856                        match (&value, &arg_values[0]) {
8857                            (Value::Array(arr), Value::Function(f)) => {
8858                                let mut results = Vec::new();
8859                                for val in arr.borrow().iter() {
8860                                    let result = self.call_function(f, vec![val.clone()])?;
8861                                    results.push(result);
8862                                }
8863                                Ok(Value::Array(Rc::new(RefCell::new(results))))
8864                            }
8865                            (Value::Array(_), _) => {
8866                                Err(RuntimeError::new("map expects closure argument"))
8867                            }
8868                            _ => Err(RuntimeError::new("map requires array")),
8869                        }
8870                    }
8871                    "filter" => {
8872                        // filter(predicate) keeps elements where predicate returns true
8873                        if arg_values.len() != 1 {
8874                            return Err(RuntimeError::new("filter expects 1 argument (closure)"));
8875                        }
8876                        match (&value, &arg_values[0]) {
8877                            (Value::Array(arr), Value::Function(f)) => {
8878                                let mut results = Vec::new();
8879                                for val in arr.borrow().iter() {
8880                                    let keep = self.call_function(f, vec![val.clone()])?;
8881                                    if matches!(keep, Value::Bool(true)) {
8882                                        results.push(val.clone());
8883                                    }
8884                                }
8885                                Ok(Value::Array(Rc::new(RefCell::new(results))))
8886                            }
8887                            (Value::Array(_), _) => {
8888                                Err(RuntimeError::new("filter expects closure argument"))
8889                            }
8890                            _ => Err(RuntimeError::new("filter requires array")),
8891                        }
8892                    }
8893                    "fold" => {
8894                        // fold(init, closure) reduces array to single value
8895                        if arg_values.len() != 2 {
8896                            return Err(RuntimeError::new(
8897                                "fold expects 2 arguments (init, closure)",
8898                            ));
8899                        }
8900                        match (&value, &arg_values[1]) {
8901                            (Value::Array(arr), Value::Function(f)) => {
8902                                let mut acc = arg_values[0].clone();
8903                                for val in arr.borrow().iter() {
8904                                    acc = self.call_function(f, vec![acc, val.clone()])?;
8905                                }
8906                                Ok(acc)
8907                            }
8908                            (Value::Array(_), _) => {
8909                                Err(RuntimeError::new("fold expects closure as second argument"))
8910                            }
8911                            _ => Err(RuntimeError::new("fold requires array")),
8912                        }
8913                    }
8914                    _ => Err(RuntimeError::new(format!(
8915                        "Unknown pipe method: {}",
8916                        name.name
8917                    ))),
8918                }
8919            }
8920            PipeOp::Await => {
8921                // Await a future - resolve it to a value
8922                self.await_value(value)
8923            }
8924            // New access morphemes
8925            PipeOp::First => {
8926                // α - first element
8927                match &value {
8928                    Value::Array(arr) => arr
8929                        .borrow()
8930                        .first()
8931                        .cloned()
8932                        .ok_or_else(|| RuntimeError::new("first (α) on empty array")),
8933                    Value::Tuple(t) => t
8934                        .first()
8935                        .cloned()
8936                        .ok_or_else(|| RuntimeError::new("first (α) on empty tuple")),
8937                    _ => Err(RuntimeError::new("first (α) requires array or tuple")),
8938                }
8939            }
8940            PipeOp::Last => {
8941                // ω - last element
8942                match &value {
8943                    Value::Array(arr) => arr
8944                        .borrow()
8945                        .last()
8946                        .cloned()
8947                        .ok_or_else(|| RuntimeError::new("last (ω) on empty array")),
8948                    Value::Tuple(t) => t
8949                        .last()
8950                        .cloned()
8951                        .ok_or_else(|| RuntimeError::new("last (ω) on empty tuple")),
8952                    _ => Err(RuntimeError::new("last (ω) requires array or tuple")),
8953                }
8954            }
8955            PipeOp::Middle => {
8956                // μ - middle/median element
8957                match &value {
8958                    Value::Array(arr) => {
8959                        let arr = arr.borrow();
8960                        if arr.is_empty() {
8961                            return Err(RuntimeError::new("middle (μ) on empty array"));
8962                        }
8963                        let mid = arr.len() / 2;
8964                        Ok(arr[mid].clone())
8965                    }
8966                    Value::Tuple(t) => {
8967                        if t.is_empty() {
8968                            return Err(RuntimeError::new("middle (μ) on empty tuple"));
8969                        }
8970                        let mid = t.len() / 2;
8971                        Ok(t[mid].clone())
8972                    }
8973                    _ => Err(RuntimeError::new("middle (μ) requires array or tuple")),
8974                }
8975            }
8976            PipeOp::Choice => {
8977                // χ - random element
8978                use std::time::{SystemTime, UNIX_EPOCH};
8979                match &value {
8980                    Value::Array(arr) => {
8981                        let arr = arr.borrow();
8982                        if arr.is_empty() {
8983                            return Err(RuntimeError::new("choice (χ) on empty array"));
8984                        }
8985                        let seed = SystemTime::now()
8986                            .duration_since(UNIX_EPOCH)
8987                            .unwrap_or(std::time::Duration::ZERO)
8988                            .as_nanos() as u64;
8989                        let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
8990                            as usize
8991                            % arr.len();
8992                        Ok(arr[idx].clone())
8993                    }
8994                    Value::Tuple(t) => {
8995                        if t.is_empty() {
8996                            return Err(RuntimeError::new("choice (χ) on empty tuple"));
8997                        }
8998                        let seed = SystemTime::now()
8999                            .duration_since(UNIX_EPOCH)
9000                            .unwrap_or(std::time::Duration::ZERO)
9001                            .as_nanos() as u64;
9002                        let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
9003                            as usize
9004                            % t.len();
9005                        Ok(t[idx].clone())
9006                    }
9007                    _ => Err(RuntimeError::new("choice (χ) requires array or tuple")),
9008                }
9009            }
9010            PipeOp::Nth(index_expr) => {
9011                // ν{n} - nth element
9012                let index = match self.evaluate(index_expr)? {
9013                    Value::Int(n) => n,
9014                    _ => return Err(RuntimeError::new("nth (ν) index must be integer")),
9015                };
9016                match &value {
9017                    Value::Array(arr) => {
9018                        let arr = arr.borrow();
9019                        if index < 0 || index as usize >= arr.len() {
9020                            return Err(RuntimeError::new("nth (ν) index out of bounds"));
9021                        }
9022                        Ok(arr[index as usize].clone())
9023                    }
9024                    Value::Tuple(t) => {
9025                        if index < 0 || index as usize >= t.len() {
9026                            return Err(RuntimeError::new("nth (ν) index out of bounds"));
9027                        }
9028                        Ok(t[index as usize].clone())
9029                    }
9030                    _ => Err(RuntimeError::new("nth (ν) requires array or tuple")),
9031                }
9032            }
9033            PipeOp::Next => {
9034                // ξ - next element (for iterators, currently just returns first)
9035                // In a full implementation, this would advance an iterator
9036                match &value {
9037                    Value::Array(arr) => arr
9038                        .borrow()
9039                        .first()
9040                        .cloned()
9041                        .ok_or_else(|| RuntimeError::new("next (ξ) on empty array")),
9042                    Value::Tuple(t) => t
9043                        .first()
9044                        .cloned()
9045                        .ok_or_else(|| RuntimeError::new("next (ξ) on empty tuple")),
9046                    _ => Err(RuntimeError::new("next (ξ) requires array or tuple")),
9047                }
9048            }
9049            PipeOp::Named { prefix, body } => {
9050                // Named morpheme like ·map{f}
9051                let method_name = prefix
9052                    .iter()
9053                    .map(|i| i.name.as_str())
9054                    .collect::<Vec<_>>()
9055                    .join("·");
9056                match method_name.as_str() {
9057                    "map" => {
9058                        if let Some(body) = body {
9059                            match value {
9060                                Value::Array(arr) => {
9061                                    let results: Vec<Value> = arr
9062                                        .borrow()
9063                                        .iter()
9064                                        .map(|item| {
9065                                            self.environment
9066                                                .borrow_mut()
9067                                                .define("_".to_string(), item.clone());
9068                                            self.evaluate(body)
9069                                        })
9070                                        .collect::<Result<_, _>>()?;
9071                                    Ok(Value::Array(Rc::new(RefCell::new(results))))
9072                                }
9073                                _ => Err(RuntimeError::new("map requires array")),
9074                            }
9075                        } else {
9076                            Ok(value)
9077                        }
9078                    }
9079                    "filter" => {
9080                        if let Some(body) = body {
9081                            match value {
9082                                Value::Array(arr) => {
9083                                    let results: Vec<Value> = arr
9084                                        .borrow()
9085                                        .iter()
9086                                        .filter_map(|item| {
9087                                            self.environment
9088                                                .borrow_mut()
9089                                                .define("_".to_string(), item.clone());
9090                                            match self.evaluate(body) {
9091                                                Ok(v) if self.is_truthy(&v) => {
9092                                                    Some(Ok(item.clone()))
9093                                                }
9094                                                Ok(_) => None,
9095                                                Err(e) => Some(Err(e)),
9096                                            }
9097                                        })
9098                                        .collect::<Result<_, _>>()?;
9099                                    Ok(Value::Array(Rc::new(RefCell::new(results))))
9100                                }
9101                                _ => Err(RuntimeError::new("filter requires array")),
9102                            }
9103                        } else {
9104                            Ok(value)
9105                        }
9106                    }
9107                    "all" => {
9108                        if let Some(body) = body {
9109                            match value {
9110                                Value::Array(arr) => {
9111                                    for item in arr.borrow().iter() {
9112                                        self.environment
9113                                            .borrow_mut()
9114                                            .define("_".to_string(), item.clone());
9115                                        let result = self.evaluate(body)?;
9116                                        if !self.is_truthy(&result) {
9117                                            return Ok(Value::Bool(false));
9118                                        }
9119                                    }
9120                                    Ok(Value::Bool(true))
9121                                }
9122                                _ => Err(RuntimeError::new("all requires array")),
9123                            }
9124                        } else {
9125                            // Without body, check if all elements are truthy
9126                            match value {
9127                                Value::Array(arr) => {
9128                                    for item in arr.borrow().iter() {
9129                                        if !self.is_truthy(item) {
9130                                            return Ok(Value::Bool(false));
9131                                        }
9132                                    }
9133                                    Ok(Value::Bool(true))
9134                                }
9135                                _ => Err(RuntimeError::new("all requires array")),
9136                            }
9137                        }
9138                    }
9139                    "any" => {
9140                        if let Some(body) = body {
9141                            match value {
9142                                Value::Array(arr) => {
9143                                    for item in arr.borrow().iter() {
9144                                        self.environment
9145                                            .borrow_mut()
9146                                            .define("_".to_string(), item.clone());
9147                                        let result = self.evaluate(body)?;
9148                                        if self.is_truthy(&result) {
9149                                            return Ok(Value::Bool(true));
9150                                        }
9151                                    }
9152                                    Ok(Value::Bool(false))
9153                                }
9154                                _ => Err(RuntimeError::new("any requires array")),
9155                            }
9156                        } else {
9157                            // Without body, check if any elements are truthy
9158                            match value {
9159                                Value::Array(arr) => {
9160                                    for item in arr.borrow().iter() {
9161                                        if self.is_truthy(item) {
9162                                            return Ok(Value::Bool(true));
9163                                        }
9164                                    }
9165                                    Ok(Value::Bool(false))
9166                                }
9167                                _ => Err(RuntimeError::new("any requires array")),
9168                            }
9169                        }
9170                    }
9171                    _ => Err(RuntimeError::new(format!(
9172                        "Unknown named morpheme: {}",
9173                        method_name
9174                    ))),
9175                }
9176            }
9177            PipeOp::Parallel(inner_op) => {
9178                // ∥ - parallel execution of the inner operation
9179                // For arrays, execute the operation in parallel using threads
9180                match value {
9181                    Value::Array(arr) => {
9182                        use std::sync::{Arc, Mutex};
9183
9184                        let arr_ref = arr.borrow();
9185                        let len = arr_ref.len();
9186                        if len == 0 {
9187                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
9188                        }
9189
9190                        // For Transform operations, parallelize across elements
9191                        match inner_op.as_ref() {
9192                            PipeOp::Transform(body) => {
9193                                // Determine number of threads (use available parallelism)
9194                                let num_threads = std::thread::available_parallelism()
9195                                    .map(|p| p.get())
9196                                    .unwrap_or(4)
9197                                    .min(len);
9198
9199                                // For future parallel implementation
9200                                let _chunk_size = (len + num_threads - 1) / num_threads;
9201                                let _results = Arc::new(Mutex::new(vec![Value::Null; len]));
9202                                let items: Vec<Value> = arr_ref.clone();
9203                                drop(arr_ref);
9204
9205                                // Clone the body expression for each thread (for future use)
9206                                let _body_str = format!("{:?}", body);
9207
9208                                // For now, fall back to sequential since full parallelization
9209                                // requires thread-safe evaluation context
9210                                // In production, this would use Rayon or a work-stealing scheduler
9211                                let mut result_vec = Vec::with_capacity(len);
9212                                for item in items.iter() {
9213                                    self.environment
9214                                        .borrow_mut()
9215                                        .define("_".to_string(), item.clone());
9216                                    result_vec.push(self.evaluate(body)?);
9217                                }
9218                                Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
9219                            }
9220                            PipeOp::Filter(predicate) => {
9221                                // Parallel filter - evaluate predicate in parallel
9222                                let items: Vec<Value> = arr_ref.clone();
9223                                drop(arr_ref);
9224
9225                                let mut result_vec = Vec::new();
9226                                for item in items.iter() {
9227                                    self.environment
9228                                        .borrow_mut()
9229                                        .define("_".to_string(), item.clone());
9230                                    let pred_result = self.evaluate(predicate)?;
9231                                    if self.is_truthy(&pred_result) {
9232                                        result_vec.push(item.clone());
9233                                    }
9234                                }
9235                                Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
9236                            }
9237                            _ => {
9238                                // For other operations, just apply them normally
9239                                drop(arr_ref);
9240                                self.apply_pipe_op(Value::Array(arr), inner_op)
9241                            }
9242                        }
9243                    }
9244                    _ => {
9245                        // For non-arrays, just apply the inner operation
9246                        self.apply_pipe_op(value, inner_op)
9247                    }
9248                }
9249            }
9250            PipeOp::Gpu(inner_op) => {
9251                // ⊛ - GPU compute shader execution
9252                // This is a placeholder that falls back to CPU execution
9253                // In production, this would:
9254                // 1. Generate SPIR-V/WGSL compute shader
9255                // 2. Submit to GPU via wgpu/vulkan
9256                // 3. Read back results
9257                match value {
9258                    Value::Array(arr) => {
9259                        // For now, emit a hint that GPU execution would occur
9260                        // and fall back to CPU
9261                        #[cfg(debug_assertions)]
9262                        eprintln!(
9263                            "[GPU] Would execute {:?} on GPU, falling back to CPU",
9264                            inner_op
9265                        );
9266
9267                        self.apply_pipe_op(Value::Array(arr), inner_op)
9268                    }
9269                    _ => self.apply_pipe_op(value, inner_op),
9270                }
9271            }
9272
9273            // ==========================================
9274            // Protocol Operations - Sigil-native networking
9275            // All protocol results are wrapped with Reported evidentiality
9276            // since network data comes from external sources ("hearsay")
9277            // ==========================================
9278            PipeOp::Send(data_expr) => {
9279                // |send{data} or |⇒{data} - Send data over a connection
9280                // The value should be a connection object
9281                let data = self.evaluate(data_expr)?;
9282
9283                // Create a protocol response with Reported evidentiality
9284                // In production, this would actually send data over the network
9285                let response = self.protocol_send(&value, &data)?;
9286
9287                // Wrap in Reported evidentiality - network responses are hearsay
9288                Ok(self.wrap_reported(response))
9289            }
9290
9291            PipeOp::Recv => {
9292                // |recv or |⇐ - Receive data from a connection
9293                // The value should be a connection object
9294
9295                // In production, this would actually receive data from the network
9296                let response = self.protocol_recv(&value)?;
9297
9298                // Wrap in Reported evidentiality - network data is hearsay
9299                Ok(self.wrap_reported(response))
9300            }
9301
9302            PipeOp::Stream(handler_expr) => {
9303                // |stream{handler} or |≋{handler} - Stream data with a handler
9304                let handler = self.evaluate(handler_expr)?;
9305
9306                // Create a streaming iterator over network data
9307                // Each element will be wrapped in Reported evidentiality
9308                let stream = self.protocol_stream(&value, &handler)?;
9309                Ok(stream)
9310            }
9311
9312            PipeOp::Connect(config_expr) => {
9313                // |connect or |connect{config} or |⊸{config} - Establish connection
9314                let config = match config_expr {
9315                    Some(expr) => Some(self.evaluate(expr)?),
9316                    None => None,
9317                };
9318
9319                // Create a connection object
9320                let connection = self.protocol_connect(&value, config.as_ref())?;
9321                Ok(connection)
9322            }
9323
9324            PipeOp::Close => {
9325                // |close or |⊗ - Close connection gracefully
9326                self.protocol_close(&value)?;
9327                Ok(Value::Null)
9328            }
9329
9330            PipeOp::Header {
9331                name,
9332                value: value_expr,
9333            } => {
9334                // |header{name, value} - Add/set header on request
9335                let header_name = self.evaluate(name)?;
9336                let header_value = self.evaluate(value_expr)?;
9337
9338                // Add header to the request builder
9339                self.protocol_add_header(value, &header_name, &header_value)
9340            }
9341
9342            PipeOp::Body(data_expr) => {
9343                // |body{data} - Set request body
9344                let body_data = self.evaluate(data_expr)?;
9345
9346                // Set body on the request builder
9347                self.protocol_set_body(value, &body_data)
9348            }
9349
9350            PipeOp::Timeout(ms_expr) => {
9351                // |timeout{ms} or |⏱{ms} - Set operation timeout
9352                let ms = self.evaluate(ms_expr)?;
9353
9354                // Set timeout on the request/connection
9355                self.protocol_set_timeout(value, &ms)
9356            }
9357
9358            PipeOp::Retry { count, strategy } => {
9359                // |retry{count} or |retry{count, strategy} - Set retry policy
9360                let retry_count = self.evaluate(count)?;
9361                let retry_strategy = match strategy {
9362                    Some(s) => Some(self.evaluate(s)?),
9363                    None => None,
9364                };
9365
9366                // Set retry policy on the request
9367                self.protocol_set_retry(value, &retry_count, retry_strategy.as_ref())
9368            }
9369
9370            // ==========================================
9371            // Evidence Promotion Operations
9372            // ==========================================
9373            PipeOp::Validate {
9374                predicate,
9375                target_evidence,
9376            } => {
9377                // |validate!{predicate} - validate and promote evidence
9378                // Execute the predicate with the current value
9379                let predicate_result = match predicate.as_ref() {
9380                    Expr::Closure { params, body, .. } => {
9381                        if let Some(param) = params.first() {
9382                            let param_name = match &param.pattern {
9383                                Pattern::Ident { name, .. } => name.name.clone(),
9384                                _ => "it".to_string(),
9385                            };
9386                            self.environment
9387                                .borrow_mut()
9388                                .define(param_name, value.clone());
9389                        }
9390                        self.evaluate(body)?
9391                    }
9392                    _ => self.evaluate(predicate)?,
9393                };
9394
9395                // Check if validation passed
9396                match predicate_result {
9397                    Value::Bool(true) => {
9398                        // Validation passed: promote evidence
9399                        let target_ev = match target_evidence {
9400                            Evidentiality::Known => Evidence::Known,
9401                            Evidentiality::Uncertain | Evidentiality::Predicted => {
9402                                Evidence::Uncertain
9403                            }
9404                            Evidentiality::Reported => Evidence::Reported,
9405                            Evidentiality::Paradox => Evidence::Paradox,
9406                        };
9407                        let inner = match value {
9408                            Value::Evidential { value: v, .. } => *v,
9409                            v => v,
9410                        };
9411                        Ok(Value::Evidential {
9412                            value: Box::new(inner),
9413                            evidence: target_ev,
9414                        })
9415                    }
9416                    Value::Bool(false) => Err(RuntimeError::new(
9417                        "validation failed: predicate returned false",
9418                    )),
9419                    _ => Err(RuntimeError::new("validation predicate must return bool")),
9420                }
9421            }
9422
9423            PipeOp::Assume {
9424                reason,
9425                target_evidence,
9426            } => {
9427                // |assume!("reason") - explicitly assume evidence (with audit trail)
9428                let reason_str: Rc<String> = if let Some(r) = reason {
9429                    match self.evaluate(r)? {
9430                        Value::String(s) => s,
9431                        _ => Rc::new("<no reason>".to_string()),
9432                    }
9433                } else {
9434                    Rc::new("<no reason>".to_string())
9435                };
9436
9437                // Log the assumption for audit purposes
9438                #[cfg(debug_assertions)]
9439                eprintln!(
9440                    "[AUDIT] Evidence assumption: {} - reason: {}",
9441                    match target_evidence {
9442                        Evidentiality::Known => "!",
9443                        Evidentiality::Uncertain | Evidentiality::Predicted => "?",
9444                        Evidentiality::Reported => "~",
9445                        Evidentiality::Paradox => "‽",
9446                    },
9447                    reason_str
9448                );
9449
9450                let target_ev = match target_evidence {
9451                    Evidentiality::Known => Evidence::Known,
9452                    Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
9453                    Evidentiality::Reported => Evidence::Reported,
9454                    Evidentiality::Paradox => Evidence::Paradox,
9455                };
9456
9457                let inner = match value {
9458                    Value::Evidential { value: v, .. } => *v,
9459                    v => v,
9460                };
9461
9462                Ok(Value::Evidential {
9463                    value: Box::new(inner),
9464                    evidence: target_ev,
9465                })
9466            }
9467
9468            PipeOp::AssertEvidence(expected) => {
9469                // |assert_evidence!{!} - assert evidence level
9470                let actual_evidence = match &value {
9471                    Value::Evidential { evidence, .. } => evidence.clone(),
9472                    _ => Evidence::Known,
9473                };
9474
9475                let expected_ev = match expected {
9476                    Evidentiality::Known => Evidence::Known,
9477                    Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
9478                    Evidentiality::Reported => Evidence::Reported,
9479                    Evidentiality::Paradox => Evidence::Paradox,
9480                };
9481
9482                // Check if actual satisfies expected
9483                let satisfies = match (&actual_evidence, &expected_ev) {
9484                    (Evidence::Known, _) => true,
9485                    (
9486                        Evidence::Uncertain,
9487                        Evidence::Uncertain | Evidence::Reported | Evidence::Paradox,
9488                    ) => true,
9489                    (Evidence::Reported, Evidence::Reported | Evidence::Paradox) => true,
9490                    (Evidence::Paradox, Evidence::Paradox) => true,
9491                    _ => false,
9492                };
9493
9494                if satisfies {
9495                    Ok(value)
9496                } else {
9497                    Err(RuntimeError::new(format!(
9498                        "evidence assertion failed: expected {:?}, found {:?}",
9499                        expected_ev, actual_evidence
9500                    )))
9501                }
9502            }
9503
9504            // ==========================================
9505            // Scope Functions (Kotlin-inspired)
9506            // ==========================================
9507            PipeOp::Also(func) => {
9508                // |also{f} - execute side effect, return original value
9509                // Execute the function with the value for side effects
9510                match func.as_ref() {
9511                    Expr::Closure { params, body, .. } => {
9512                        if let Some(param) = params.first() {
9513                            let param_name = match &param.pattern {
9514                                Pattern::Ident { name, .. } => name.name.clone(),
9515                                _ => "it".to_string(),
9516                            };
9517                            self.environment
9518                                .borrow_mut()
9519                                .define(param_name, value.clone());
9520                        }
9521                        // Execute for side effects, ignore result
9522                        let _ = self.evaluate(body);
9523                    }
9524                    _ => {
9525                        // Call as function with value as argument
9526                        let _ = self.evaluate(func);
9527                    }
9528                }
9529                // Return original value unchanged
9530                Ok(value)
9531            }
9532
9533            PipeOp::Apply(func) => {
9534                // |apply{block} - mutate value in place, return modified value
9535                // The closure receives the value and can modify it
9536                match func.as_ref() {
9537                    Expr::Closure { params, body, .. } => {
9538                        if let Some(param) = params.first() {
9539                            let param_name = match &param.pattern {
9540                                Pattern::Ident { name, .. } => name.name.clone(),
9541                                _ => "it".to_string(),
9542                            };
9543                            self.environment
9544                                .borrow_mut()
9545                                .define(param_name, value.clone());
9546                        }
9547                        // Execute the body - mutations happen via the bound variable
9548                        let _ = self.evaluate(body);
9549                    }
9550                    _ => {
9551                        let _ = self.evaluate(func);
9552                    }
9553                }
9554                // Return the (potentially modified) value
9555                Ok(value)
9556            }
9557
9558            PipeOp::TakeIf(predicate) => {
9559                // |take_if{p} - return Some(value) if predicate true, None otherwise
9560                let predicate_result = match predicate.as_ref() {
9561                    Expr::Closure { params, body, .. } => {
9562                        if let Some(param) = params.first() {
9563                            let param_name = match &param.pattern {
9564                                Pattern::Ident { name, .. } => name.name.clone(),
9565                                _ => "it".to_string(),
9566                            };
9567                            self.environment
9568                                .borrow_mut()
9569                                .define(param_name, value.clone());
9570                        }
9571                        self.evaluate(body)?
9572                    }
9573                    _ => self.evaluate(predicate)?,
9574                };
9575
9576                match predicate_result {
9577                    Value::Bool(true) => Ok(Value::Variant {
9578                        enum_name: "Option".to_string(),
9579                        variant_name: "Some".to_string(),
9580                        fields: Some(Rc::new(vec![value])),
9581                    }),
9582                    Value::Bool(false) => Ok(Value::Variant {
9583                        enum_name: "Option".to_string(),
9584                        variant_name: "None".to_string(),
9585                        fields: None,
9586                    }),
9587                    _ => Err(RuntimeError::new("take_if predicate must return bool")),
9588                }
9589            }
9590
9591            PipeOp::TakeUnless(predicate) => {
9592                // |take_unless{p} - return Some(value) if predicate false, None otherwise
9593                let predicate_result = match predicate.as_ref() {
9594                    Expr::Closure { params, body, .. } => {
9595                        if let Some(param) = params.first() {
9596                            let param_name = match &param.pattern {
9597                                Pattern::Ident { name, .. } => name.name.clone(),
9598                                _ => "it".to_string(),
9599                            };
9600                            self.environment
9601                                .borrow_mut()
9602                                .define(param_name, value.clone());
9603                        }
9604                        self.evaluate(body)?
9605                    }
9606                    _ => self.evaluate(predicate)?,
9607                };
9608
9609                match predicate_result {
9610                    Value::Bool(false) => Ok(Value::Variant {
9611                        enum_name: "Option".to_string(),
9612                        variant_name: "Some".to_string(),
9613                        fields: Some(Rc::new(vec![value])),
9614                    }),
9615                    Value::Bool(true) => Ok(Value::Variant {
9616                        enum_name: "Option".to_string(),
9617                        variant_name: "None".to_string(),
9618                        fields: None,
9619                    }),
9620                    _ => Err(RuntimeError::new("take_unless predicate must return bool")),
9621                }
9622            }
9623
9624            PipeOp::Let(func) => {
9625                // |let{f} - transform value (alias for map/transform)
9626                match func.as_ref() {
9627                    Expr::Closure { params, body, .. } => {
9628                        if let Some(param) = params.first() {
9629                            let param_name = match &param.pattern {
9630                                Pattern::Ident { name, .. } => name.name.clone(),
9631                                _ => "it".to_string(),
9632                            };
9633                            self.environment
9634                                .borrow_mut()
9635                                .define(param_name, value.clone());
9636                        }
9637                        self.evaluate(body)
9638                    }
9639                    _ => self.evaluate(func),
9640                }
9641            }
9642
9643            // ==========================================
9644            // Mathematical & APL-Inspired Operations
9645            // ==========================================
9646            PipeOp::All(pred) => {
9647                // |∀{p} - check if ALL elements satisfy predicate
9648                match value {
9649                    Value::Array(arr) => {
9650                        for elem in arr.borrow().iter() {
9651                            self.environment
9652                                .borrow_mut()
9653                                .define("_".to_string(), elem.clone());
9654                            let result = self.evaluate(pred)?;
9655                            if !self.is_truthy(&result) {
9656                                return Ok(Value::Bool(false));
9657                            }
9658                        }
9659                        Ok(Value::Bool(true))
9660                    }
9661                    _ => Err(RuntimeError::new("All requires array")),
9662                }
9663            }
9664
9665            PipeOp::Any(pred) => {
9666                // |∃{p} - check if ANY element satisfies predicate
9667                match value {
9668                    Value::Array(arr) => {
9669                        for elem in arr.borrow().iter() {
9670                            self.environment
9671                                .borrow_mut()
9672                                .define("_".to_string(), elem.clone());
9673                            let result = self.evaluate(pred)?;
9674                            if self.is_truthy(&result) {
9675                                return Ok(Value::Bool(true));
9676                            }
9677                        }
9678                        Ok(Value::Bool(false))
9679                    }
9680                    _ => Err(RuntimeError::new("Any requires array")),
9681                }
9682            }
9683
9684            PipeOp::Compose(f) => {
9685                // |∘{f} - function composition / apply function
9686                self.environment.borrow_mut().define("_".to_string(), value);
9687                self.evaluate(f)
9688            }
9689
9690            PipeOp::Zip(other_expr) => {
9691                // |⋈{other} - zip with another collection
9692                let other = self.evaluate(other_expr)?;
9693                match (value, other) {
9694                    (Value::Array(arr1), Value::Array(arr2)) => {
9695                        let zipped: Vec<Value> = arr1
9696                            .borrow()
9697                            .iter()
9698                            .zip(arr2.borrow().iter())
9699                            .map(|(a, b)| Value::Tuple(Rc::new(vec![a.clone(), b.clone()])))
9700                            .collect();
9701                        Ok(Value::Array(Rc::new(RefCell::new(zipped))))
9702                    }
9703                    _ => Err(RuntimeError::new("Zip requires two arrays")),
9704                }
9705            }
9706
9707            PipeOp::Scan(f) => {
9708                // |∫{f} - cumulative fold (scan)
9709                match value {
9710                    Value::Array(arr) => {
9711                        let arr = arr.borrow();
9712                        if arr.is_empty() {
9713                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
9714                        }
9715                        let mut results = vec![arr[0].clone()];
9716                        let mut acc = arr[0].clone();
9717                        for elem in arr.iter().skip(1) {
9718                            self.environment
9719                                .borrow_mut()
9720                                .define("acc".to_string(), acc.clone());
9721                            self.environment
9722                                .borrow_mut()
9723                                .define("_".to_string(), elem.clone());
9724                            acc = self.evaluate(f)?;
9725                            results.push(acc.clone());
9726                        }
9727                        Ok(Value::Array(Rc::new(RefCell::new(results))))
9728                    }
9729                    _ => Err(RuntimeError::new("Scan requires array")),
9730                }
9731            }
9732
9733            PipeOp::Diff => {
9734                // |∂ - differences between adjacent elements
9735                match value {
9736                    Value::Array(arr) => {
9737                        let arr = arr.borrow();
9738                        if arr.len() < 2 {
9739                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
9740                        }
9741                        let mut diffs = Vec::new();
9742                        for i in 1..arr.len() {
9743                            let diff = self.subtract_values(&arr[i], &arr[i - 1])?;
9744                            diffs.push(diff);
9745                        }
9746                        Ok(Value::Array(Rc::new(RefCell::new(diffs))))
9747                    }
9748                    _ => Err(RuntimeError::new("Diff requires array")),
9749                }
9750            }
9751
9752            PipeOp::Gradient(var_expr) => {
9753                // |∇{var} - automatic differentiation
9754                // For now, just a placeholder - real autodiff requires tape recording
9755                let _ = var_expr;
9756                Ok(Value::Float(0.0)) // TODO: Implement real autodiff
9757            }
9758
9759            PipeOp::SortAsc => {
9760                // |⍋ - sort ascending
9761                match value {
9762                    Value::Array(arr) => {
9763                        let mut v = arr.borrow().clone();
9764                        v.sort_by(|a, b| self.compare_values(a, b, &None));
9765                        Ok(Value::Array(Rc::new(RefCell::new(v))))
9766                    }
9767                    _ => Err(RuntimeError::new("SortAsc requires array")),
9768                }
9769            }
9770
9771            PipeOp::SortDesc => {
9772                // |⍒ - sort descending
9773                match value {
9774                    Value::Array(arr) => {
9775                        let mut v = arr.borrow().clone();
9776                        v.sort_by(|a, b| self.compare_values(b, a, &None));
9777                        Ok(Value::Array(Rc::new(RefCell::new(v))))
9778                    }
9779                    _ => Err(RuntimeError::new("SortDesc requires array")),
9780                }
9781            }
9782
9783            PipeOp::Reverse => {
9784                // |⌽ - reverse collection
9785                match value {
9786                    Value::Array(arr) => {
9787                        let mut v = arr.borrow().clone();
9788                        v.reverse();
9789                        Ok(Value::Array(Rc::new(RefCell::new(v))))
9790                    }
9791                    _ => Err(RuntimeError::new("Reverse requires array")),
9792                }
9793            }
9794
9795            PipeOp::Cycle(n_expr) => {
9796                // |↻{n} - repeat collection n times
9797                match value {
9798                    Value::Array(arr) => {
9799                        let n_val = self.evaluate(n_expr)?;
9800                        let n = match n_val {
9801                            Value::Int(i) => i as usize,
9802                            _ => return Err(RuntimeError::new("Cycle count must be integer")),
9803                        };
9804                        let arr = arr.borrow();
9805                        let cycled: Vec<Value> =
9806                            arr.iter().cloned().cycle().take(arr.len() * n).collect();
9807                        Ok(Value::Array(Rc::new(RefCell::new(cycled))))
9808                    }
9809                    _ => Err(RuntimeError::new("Cycle requires array")),
9810                }
9811            }
9812
9813            PipeOp::Windows(n_expr) => {
9814                // |⌺{n} - sliding windows
9815                match value {
9816                    Value::Array(arr) => {
9817                        let n_val = self.evaluate(n_expr)?;
9818                        let n = match n_val {
9819                            Value::Int(i) => i as usize,
9820                            _ => return Err(RuntimeError::new("Window size must be integer")),
9821                        };
9822                        let arr = arr.borrow();
9823                        let windows: Vec<Value> = arr
9824                            .windows(n)
9825                            .map(|w| Value::Array(Rc::new(RefCell::new(w.to_vec()))))
9826                            .collect();
9827                        Ok(Value::Array(Rc::new(RefCell::new(windows))))
9828                    }
9829                    _ => Err(RuntimeError::new("Windows requires array")),
9830                }
9831            }
9832
9833            PipeOp::Chunks(n_expr) => {
9834                // |⊞{n} - split into chunks
9835                match value {
9836                    Value::Array(arr) => {
9837                        let n_val = self.evaluate(n_expr)?;
9838                        let n = match n_val {
9839                            Value::Int(i) => i as usize,
9840                            _ => return Err(RuntimeError::new("Chunk size must be integer")),
9841                        };
9842                        let arr = arr.borrow();
9843                        let chunks: Vec<Value> = arr
9844                            .chunks(n)
9845                            .map(|c| Value::Array(Rc::new(RefCell::new(c.to_vec()))))
9846                            .collect();
9847                        Ok(Value::Array(Rc::new(RefCell::new(chunks))))
9848                    }
9849                    _ => Err(RuntimeError::new("Chunks requires array")),
9850                }
9851            }
9852
9853            PipeOp::Flatten => {
9854                // |⋳ - flatten nested collection
9855                match value {
9856                    Value::Array(arr) => {
9857                        let mut flat = Vec::new();
9858                        for elem in arr.borrow().iter() {
9859                            match elem {
9860                                Value::Array(inner) => {
9861                                    flat.extend(inner.borrow().iter().cloned());
9862                                }
9863                                other => flat.push(other.clone()),
9864                            }
9865                        }
9866                        Ok(Value::Array(Rc::new(RefCell::new(flat))))
9867                    }
9868                    _ => Err(RuntimeError::new("Flatten requires array")),
9869                }
9870            }
9871
9872            PipeOp::Unique => {
9873                // |∪ - remove duplicates
9874                match value {
9875                    Value::Array(arr) => {
9876                        let mut seen = std::collections::HashSet::new();
9877                        let mut unique = Vec::new();
9878                        for elem in arr.borrow().iter() {
9879                            let key = format!("{:?}", elem);
9880                            if seen.insert(key) {
9881                                unique.push(elem.clone());
9882                            }
9883                        }
9884                        Ok(Value::Array(Rc::new(RefCell::new(unique))))
9885                    }
9886                    _ => Err(RuntimeError::new("Unique requires array")),
9887                }
9888            }
9889
9890            PipeOp::Enumerate => {
9891                // |⍳ - pair with indices
9892                match value {
9893                    Value::Array(arr) => {
9894                        let enumerated: Vec<Value> = arr
9895                            .borrow()
9896                            .iter()
9897                            .enumerate()
9898                            .map(|(i, v)| {
9899                                Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
9900                            })
9901                            .collect();
9902                        Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
9903                    }
9904                    _ => Err(RuntimeError::new("Enumerate requires array")),
9905                }
9906            }
9907        }
9908    }
9909
9910    // ==========================================
9911    // Protocol Helper Methods
9912    // ==========================================
9913
9914    /// Wrap a value in Reported evidentiality
9915    /// Network data is "hearsay" - it comes from external sources we can't verify
9916    fn wrap_reported(&self, value: Value) -> Value {
9917        Value::Evidential {
9918            value: Box::new(value),
9919            evidence: Evidence::Reported,
9920        }
9921    }
9922
9923    /// Send data over a protocol connection
9924    fn protocol_send(&mut self, connection: &Value, data: &Value) -> Result<Value, RuntimeError> {
9925        // Extract connection info and send data
9926        match connection {
9927            Value::Map(obj) => {
9928                let obj = obj.borrow();
9929                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
9930                    match protocol.as_str() {
9931                        "http" | "https" => {
9932                            // For HTTP, "send" means execute the request
9933                            // The data becomes the body
9934                            #[cfg(debug_assertions)]
9935                            eprintln!("[HTTP] Would send request with body: {:?}", data);
9936                            Ok(Value::Map(Rc::new(RefCell::new({
9937                                let mut response = HashMap::new();
9938                                response.insert("status".to_string(), Value::Int(200));
9939                                response.insert("body".to_string(), data.clone());
9940                                response.insert(
9941                                    "__protocol__".to_string(),
9942                                    Value::String(Rc::new("http_response".to_string())),
9943                                );
9944                                response
9945                            }))))
9946                        }
9947                        "ws" | "wss" => {
9948                            // For WebSocket, send a message
9949                            #[cfg(debug_assertions)]
9950                            eprintln!("[WebSocket] Would send message: {:?}", data);
9951                            Ok(Value::Bool(true)) // Message sent successfully
9952                        }
9953                        "grpc" => {
9954                            // For gRPC, send the request message
9955                            #[cfg(debug_assertions)]
9956                            eprintln!("[gRPC] Would send message: {:?}", data);
9957                            Ok(Value::Map(Rc::new(RefCell::new({
9958                                let mut response = HashMap::new();
9959                                response.insert("status".to_string(), Value::Int(0)); // OK
9960                                response.insert("message".to_string(), data.clone());
9961                                response.insert(
9962                                    "__protocol__".to_string(),
9963                                    Value::String(Rc::new("grpc_response".to_string())),
9964                                );
9965                                response
9966                            }))))
9967                        }
9968                        "kafka" => {
9969                            // For Kafka, produce a message
9970                            #[cfg(debug_assertions)]
9971                            eprintln!("[Kafka] Would produce message: {:?}", data);
9972                            Ok(Value::Map(Rc::new(RefCell::new({
9973                                let mut result = HashMap::new();
9974                                result.insert("partition".to_string(), Value::Int(0));
9975                                result.insert("offset".to_string(), Value::Int(42));
9976                                result
9977                            }))))
9978                        }
9979                        _ => Err(RuntimeError::new(format!("Unknown protocol: {}", protocol))),
9980                    }
9981                } else {
9982                    Err(RuntimeError::new(
9983                        "Connection object missing __protocol__ field",
9984                    ))
9985                }
9986            }
9987            _ => Err(RuntimeError::new("send requires a connection object")),
9988        }
9989    }
9990
9991    /// Receive data from a protocol connection
9992    fn protocol_recv(&mut self, connection: &Value) -> Result<Value, RuntimeError> {
9993        match connection {
9994            Value::Map(obj) => {
9995                let obj = obj.borrow();
9996                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
9997                    match protocol.as_str() {
9998                        "ws" | "wss" => {
9999                            // For WebSocket, receive a message
10000                            #[cfg(debug_assertions)]
10001                            eprintln!("[WebSocket] Would receive message");
10002                            Ok(Value::String(Rc::new("received message".to_string())))
10003                        }
10004                        "kafka" => {
10005                            // For Kafka, consume a message
10006                            #[cfg(debug_assertions)]
10007                            eprintln!("[Kafka] Would consume message");
10008                            Ok(Value::Map(Rc::new(RefCell::new({
10009                                let mut msg = HashMap::new();
10010                                msg.insert("key".to_string(), Value::Null);
10011                                msg.insert(
10012                                    "value".to_string(),
10013                                    Value::String(Rc::new("consumed message".to_string())),
10014                                );
10015                                msg.insert("partition".to_string(), Value::Int(0));
10016                                msg.insert("offset".to_string(), Value::Int(100));
10017                                msg
10018                            }))))
10019                        }
10020                        "grpc" => {
10021                            // For gRPC streaming, receive next message
10022                            #[cfg(debug_assertions)]
10023                            eprintln!("[gRPC] Would receive stream message");
10024                            Ok(Value::Map(Rc::new(RefCell::new({
10025                                let mut msg = HashMap::new();
10026                                msg.insert(
10027                                    "data".to_string(),
10028                                    Value::String(Rc::new("stream data".to_string())),
10029                                );
10030                                msg
10031                            }))))
10032                        }
10033                        _ => Err(RuntimeError::new(format!(
10034                            "recv not supported for protocol: {}",
10035                            protocol
10036                        ))),
10037                    }
10038                } else {
10039                    Err(RuntimeError::new(
10040                        "Connection object missing __protocol__ field",
10041                    ))
10042                }
10043            }
10044            _ => Err(RuntimeError::new("recv requires a connection object")),
10045        }
10046    }
10047
10048    /// Create a streaming iterator over protocol data
10049    fn protocol_stream(
10050        &mut self,
10051        connection: &Value,
10052        _handler: &Value,
10053    ) -> Result<Value, RuntimeError> {
10054        // Create a lazy stream that yields values with Reported evidentiality
10055        match connection {
10056            Value::Map(obj) => {
10057                let obj = obj.borrow();
10058                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
10059                    #[cfg(debug_assertions)]
10060                    eprintln!("[{}] Would create stream", protocol);
10061
10062                    // Return a stream object that can be iterated
10063                    Ok(Value::Map(Rc::new(RefCell::new({
10064                        let mut stream = HashMap::new();
10065                        stream.insert(
10066                            "__type__".to_string(),
10067                            Value::String(Rc::new("Stream".to_string())),
10068                        );
10069                        stream.insert("__protocol__".to_string(), Value::String(protocol.clone()));
10070                        stream.insert(
10071                            "__evidentiality__".to_string(),
10072                            Value::String(Rc::new("reported".to_string())),
10073                        );
10074                        stream
10075                    }))))
10076                } else {
10077                    Err(RuntimeError::new(
10078                        "Connection object missing __protocol__ field",
10079                    ))
10080                }
10081            }
10082            _ => Err(RuntimeError::new("stream requires a connection object")),
10083        }
10084    }
10085
10086    /// Establish a protocol connection
10087    fn protocol_connect(
10088        &mut self,
10089        target: &Value,
10090        _config: Option<&Value>,
10091    ) -> Result<Value, RuntimeError> {
10092        match target {
10093            Value::String(url) => {
10094                // Parse URL to determine protocol
10095                let protocol = if url.starts_with("wss://") || url.starts_with("ws://") {
10096                    if url.starts_with("wss://") {
10097                        "wss"
10098                    } else {
10099                        "ws"
10100                    }
10101                } else if url.starts_with("https://") || url.starts_with("http://") {
10102                    if url.starts_with("https://") {
10103                        "https"
10104                    } else {
10105                        "http"
10106                    }
10107                } else if url.starts_with("grpc://") || url.starts_with("grpcs://") {
10108                    "grpc"
10109                } else if url.starts_with("kafka://") {
10110                    "kafka"
10111                } else if url.starts_with("amqp://") || url.starts_with("amqps://") {
10112                    "amqp"
10113                } else {
10114                    "unknown"
10115                };
10116
10117                #[cfg(debug_assertions)]
10118                eprintln!("[{}] Would connect to: {}", protocol, url);
10119
10120                // Return a connection object
10121                Ok(Value::Map(Rc::new(RefCell::new({
10122                    let mut conn = HashMap::new();
10123                    conn.insert(
10124                        "__protocol__".to_string(),
10125                        Value::String(Rc::new(protocol.to_string())),
10126                    );
10127                    conn.insert("url".to_string(), Value::String(url.clone()));
10128                    conn.insert("connected".to_string(), Value::Bool(true));
10129                    conn
10130                }))))
10131            }
10132            Value::Map(obj) => {
10133                // Already a connection config object
10134                let mut conn = obj.borrow().clone();
10135                conn.insert("connected".to_string(), Value::Bool(true));
10136                Ok(Value::Map(Rc::new(RefCell::new(conn))))
10137            }
10138            _ => Err(RuntimeError::new(
10139                "connect requires URL string or config object",
10140            )),
10141        }
10142    }
10143
10144    /// Close a protocol connection
10145    fn protocol_close(&mut self, connection: &Value) -> Result<(), RuntimeError> {
10146        match connection {
10147            Value::Map(obj) => {
10148                let mut obj = obj.borrow_mut();
10149                if let Some(Value::String(protocol)) = obj.get("__protocol__").cloned() {
10150                    #[cfg(debug_assertions)]
10151                    eprintln!("[{}] Would close connection", protocol);
10152                    obj.insert("connected".to_string(), Value::Bool(false));
10153                    Ok(())
10154                } else {
10155                    Err(RuntimeError::new(
10156                        "Connection object missing __protocol__ field",
10157                    ))
10158                }
10159            }
10160            _ => Err(RuntimeError::new("close requires a connection object")),
10161        }
10162    }
10163
10164    /// Add a header to a protocol request
10165    fn protocol_add_header(
10166        &mut self,
10167        mut request: Value,
10168        name: &Value,
10169        header_value: &Value,
10170    ) -> Result<Value, RuntimeError> {
10171        let name_str = match name {
10172            Value::String(s) => (**s).clone(),
10173            _ => return Err(RuntimeError::new("Header name must be a string")),
10174        };
10175        let value_str = match header_value {
10176            Value::String(s) => (**s).clone(),
10177            Value::Int(i) => i.to_string(),
10178            _ => return Err(RuntimeError::new("Header value must be string or int")),
10179        };
10180
10181        match &mut request {
10182            Value::Map(obj) => {
10183                let mut obj = obj.borrow_mut();
10184
10185                // Get or create headers map
10186                let headers = obj
10187                    .entry("headers".to_string())
10188                    .or_insert_with(|| Value::Map(Rc::new(RefCell::new(HashMap::new()))));
10189
10190                if let Value::Map(headers_obj) = headers {
10191                    headers_obj
10192                        .borrow_mut()
10193                        .insert(name_str, Value::String(Rc::new(value_str)));
10194                }
10195                drop(obj);
10196                Ok(request)
10197            }
10198            _ => Err(RuntimeError::new("header requires a request object")),
10199        }
10200    }
10201
10202    /// Set the body of a protocol request
10203    fn protocol_set_body(
10204        &mut self,
10205        mut request: Value,
10206        body: &Value,
10207    ) -> Result<Value, RuntimeError> {
10208        match &mut request {
10209            Value::Map(obj) => {
10210                obj.borrow_mut().insert("body".to_string(), body.clone());
10211                Ok(request)
10212            }
10213            _ => Err(RuntimeError::new("body requires a request object")),
10214        }
10215    }
10216
10217    /// Set the timeout for a protocol operation
10218    fn protocol_set_timeout(
10219        &mut self,
10220        mut request: Value,
10221        ms: &Value,
10222    ) -> Result<Value, RuntimeError> {
10223        let timeout_ms = match ms {
10224            Value::Int(n) => *n,
10225            Value::Float(f) => *f as i64,
10226            _ => return Err(RuntimeError::new("Timeout must be a number (milliseconds)")),
10227        };
10228
10229        match &mut request {
10230            Value::Map(obj) => {
10231                obj.borrow_mut()
10232                    .insert("timeout_ms".to_string(), Value::Int(timeout_ms));
10233                Ok(request)
10234            }
10235            _ => Err(RuntimeError::new("timeout requires a request object")),
10236        }
10237    }
10238
10239    /// Set the retry policy for a protocol operation
10240    fn protocol_set_retry(
10241        &mut self,
10242        mut request: Value,
10243        count: &Value,
10244        strategy: Option<&Value>,
10245    ) -> Result<Value, RuntimeError> {
10246        let retry_count = match count {
10247            Value::Int(n) => *n,
10248            _ => return Err(RuntimeError::new("Retry count must be an integer")),
10249        };
10250
10251        match &mut request {
10252            Value::Map(obj) => {
10253                let mut obj = obj.borrow_mut();
10254                obj.insert("retry_count".to_string(), Value::Int(retry_count));
10255                if let Some(strat) = strategy {
10256                    obj.insert("retry_strategy".to_string(), strat.clone());
10257                }
10258                drop(obj);
10259                Ok(request)
10260            }
10261            _ => Err(RuntimeError::new("retry requires a request object")),
10262        }
10263    }
10264
10265    fn sum_values(&self, value: Value) -> Result<Value, RuntimeError> {
10266        match value {
10267            Value::Array(arr) => {
10268                let arr = arr.borrow();
10269                if arr.is_empty() {
10270                    return Ok(Value::Int(0));
10271                }
10272                let mut sum = match &arr[0] {
10273                    Value::Int(_) => Value::Int(0),
10274                    Value::Float(_) => Value::Float(0.0),
10275                    _ => return Err(RuntimeError::new("Cannot sum non-numeric array")),
10276                };
10277                for item in arr.iter() {
10278                    sum = match (&sum, item) {
10279                        (Value::Int(a), Value::Int(b)) => Value::Int(a + b),
10280                        (Value::Float(a), Value::Float(b)) => Value::Float(a + b),
10281                        (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 + b),
10282                        (Value::Float(a), Value::Int(b)) => Value::Float(a + *b as f64),
10283                        _ => return Err(RuntimeError::new("Cannot sum non-numeric values")),
10284                    };
10285                }
10286                Ok(sum)
10287            }
10288            _ => Err(RuntimeError::new("sum requires array")),
10289        }
10290    }
10291
10292    fn product_values(&self, value: Value) -> Result<Value, RuntimeError> {
10293        match value {
10294            Value::Array(arr) => {
10295                let arr = arr.borrow();
10296                if arr.is_empty() {
10297                    return Ok(Value::Int(1));
10298                }
10299                let mut prod = match &arr[0] {
10300                    Value::Int(_) => Value::Int(1),
10301                    Value::Float(_) => Value::Float(1.0),
10302                    _ => return Err(RuntimeError::new("Cannot multiply non-numeric array")),
10303                };
10304                for item in arr.iter() {
10305                    prod = match (&prod, item) {
10306                        (Value::Int(a), Value::Int(b)) => Value::Int(a * b),
10307                        (Value::Float(a), Value::Float(b)) => Value::Float(a * b),
10308                        (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 * b),
10309                        (Value::Float(a), Value::Int(b)) => Value::Float(a * *b as f64),
10310                        _ => return Err(RuntimeError::new("Cannot multiply non-numeric values")),
10311                    };
10312                }
10313                Ok(prod)
10314            }
10315            _ => Err(RuntimeError::new("product requires array")),
10316        }
10317    }
10318
10319    fn min_values(&self, value: Value) -> Result<Value, RuntimeError> {
10320        match value {
10321            Value::Array(arr) => {
10322                let arr = arr.borrow();
10323                if arr.is_empty() {
10324                    return Err(RuntimeError::new("Cannot find min of empty array"));
10325                }
10326                let mut min = arr[0].clone();
10327                for item in arr.iter().skip(1) {
10328                    min = match (&min, item) {
10329                        (Value::Int(a), Value::Int(b)) => {
10330                            if *b < *a {
10331                                Value::Int(*b)
10332                            } else {
10333                                Value::Int(*a)
10334                            }
10335                        }
10336                        (Value::Float(a), Value::Float(b)) => {
10337                            if *b < *a {
10338                                Value::Float(*b)
10339                            } else {
10340                                Value::Float(*a)
10341                            }
10342                        }
10343                        (Value::Int(a), Value::Float(b)) => {
10344                            let af = *a as f64;
10345                            if *b < af {
10346                                Value::Float(*b)
10347                            } else {
10348                                Value::Float(af)
10349                            }
10350                        }
10351                        (Value::Float(a), Value::Int(b)) => {
10352                            let bf = *b as f64;
10353                            if bf < *a {
10354                                Value::Float(bf)
10355                            } else {
10356                                Value::Float(*a)
10357                            }
10358                        }
10359                        _ => {
10360                            return Err(RuntimeError::new("Cannot find min of non-numeric values"))
10361                        }
10362                    };
10363                }
10364                Ok(min)
10365            }
10366            _ => Err(RuntimeError::new("min requires array")),
10367        }
10368    }
10369
10370    fn max_values(&self, value: Value) -> Result<Value, RuntimeError> {
10371        match value {
10372            Value::Array(arr) => {
10373                let arr = arr.borrow();
10374                if arr.is_empty() {
10375                    return Err(RuntimeError::new("Cannot find max of empty array"));
10376                }
10377                let mut max = arr[0].clone();
10378                for item in arr.iter().skip(1) {
10379                    max = match (&max, item) {
10380                        (Value::Int(a), Value::Int(b)) => {
10381                            if *b > *a {
10382                                Value::Int(*b)
10383                            } else {
10384                                Value::Int(*a)
10385                            }
10386                        }
10387                        (Value::Float(a), Value::Float(b)) => {
10388                            if *b > *a {
10389                                Value::Float(*b)
10390                            } else {
10391                                Value::Float(*a)
10392                            }
10393                        }
10394                        (Value::Int(a), Value::Float(b)) => {
10395                            let af = *a as f64;
10396                            if *b > af {
10397                                Value::Float(*b)
10398                            } else {
10399                                Value::Float(af)
10400                            }
10401                        }
10402                        (Value::Float(a), Value::Int(b)) => {
10403                            let bf = *b as f64;
10404                            if bf > *a {
10405                                Value::Float(bf)
10406                            } else {
10407                                Value::Float(*a)
10408                            }
10409                        }
10410                        _ => {
10411                            return Err(RuntimeError::new("Cannot find max of non-numeric values"))
10412                        }
10413                    };
10414                }
10415                Ok(max)
10416            }
10417            _ => Err(RuntimeError::new("max requires array")),
10418        }
10419    }
10420
10421    fn concat_values(&self, value: Value) -> Result<Value, RuntimeError> {
10422        match value {
10423            Value::Array(arr) => {
10424                let arr = arr.borrow();
10425                if arr.is_empty() {
10426                    return Ok(Value::String(Rc::new(String::new())));
10427                }
10428                // Determine if we're concatenating strings or arrays
10429                match &arr[0] {
10430                    Value::String(_) => {
10431                        let mut result = String::new();
10432                        for item in arr.iter() {
10433                            if let Value::String(s) = item {
10434                                result.push_str(s);
10435                            } else {
10436                                return Err(RuntimeError::new(
10437                                    "concat requires all elements to be strings",
10438                                ));
10439                            }
10440                        }
10441                        Ok(Value::String(Rc::new(result)))
10442                    }
10443                    Value::Array(_) => {
10444                        let mut result = Vec::new();
10445                        for item in arr.iter() {
10446                            if let Value::Array(inner) = item {
10447                                result.extend(inner.borrow().iter().cloned());
10448                            } else {
10449                                return Err(RuntimeError::new(
10450                                    "concat requires all elements to be arrays",
10451                                ));
10452                            }
10453                        }
10454                        Ok(Value::Array(Rc::new(RefCell::new(result))))
10455                    }
10456                    _ => Err(RuntimeError::new("concat requires strings or arrays")),
10457                }
10458            }
10459            _ => Err(RuntimeError::new("concat requires array")),
10460        }
10461    }
10462
10463    fn all_values(&self, value: Value) -> Result<Value, RuntimeError> {
10464        match value {
10465            Value::Array(arr) => {
10466                let arr = arr.borrow();
10467                for item in arr.iter() {
10468                    match item {
10469                        Value::Bool(b) => {
10470                            if !*b {
10471                                return Ok(Value::Bool(false));
10472                            }
10473                        }
10474                        _ => return Err(RuntimeError::new("all requires array of booleans")),
10475                    }
10476                }
10477                Ok(Value::Bool(true))
10478            }
10479            _ => Err(RuntimeError::new("all requires array")),
10480        }
10481    }
10482
10483    fn any_values(&self, value: Value) -> Result<Value, RuntimeError> {
10484        match value {
10485            Value::Array(arr) => {
10486                let arr = arr.borrow();
10487                for item in arr.iter() {
10488                    match item {
10489                        Value::Bool(b) => {
10490                            if *b {
10491                                return Ok(Value::Bool(true));
10492                            }
10493                        }
10494                        _ => return Err(RuntimeError::new("any requires array of booleans")),
10495                    }
10496                }
10497                Ok(Value::Bool(false))
10498            }
10499            _ => Err(RuntimeError::new("any requires array")),
10500        }
10501    }
10502
10503    fn compare_values(&self, a: &Value, b: &Value, _field: &Option<Ident>) -> std::cmp::Ordering {
10504        // Simple comparison for now
10505        match (a, b) {
10506            (Value::Int(a), Value::Int(b)) => a.cmp(b),
10507            (Value::Float(a), Value::Float(b)) => {
10508                a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)
10509            }
10510            (Value::String(a), Value::String(b)) => a.cmp(b),
10511            _ => std::cmp::Ordering::Equal,
10512        }
10513    }
10514
10515    /// Subtract two values (for diff operation)
10516    fn subtract_values(&self, a: &Value, b: &Value) -> Result<Value, RuntimeError> {
10517        match (a, b) {
10518            (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a - b)),
10519            (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a - b)),
10520            (Value::Int(a), Value::Float(b)) => Ok(Value::Float(*a as f64 - b)),
10521            (Value::Float(a), Value::Int(b)) => Ok(Value::Float(a - *b as f64)),
10522            _ => Err(RuntimeError::new(format!(
10523                "Cannot subtract {:?} from {:?}",
10524                b, a
10525            ))),
10526        }
10527    }
10528
10529    fn eval_closure(
10530        &mut self,
10531        params: &[ClosureParam],
10532        body: &Expr,
10533    ) -> Result<Value, RuntimeError> {
10534        let param_names: Vec<String> = params
10535            .iter()
10536            .map(|p| match &p.pattern {
10537                Pattern::Ident { name, .. } => name.name.clone(),
10538                _ => "_".to_string(),
10539            })
10540            .collect();
10541
10542        Ok(Value::Function(Rc::new(Function {
10543            name: None,
10544            params: param_names,
10545            body: body.clone(),
10546            closure: self.environment.clone(),
10547        })))
10548    }
10549
10550    fn eval_struct_literal(
10551        &mut self,
10552        path: &TypePath,
10553        fields: &[FieldInit],
10554        rest: &Option<Box<Expr>>,
10555    ) -> Result<Value, RuntimeError> {
10556        let raw_name = path
10557            .segments
10558            .iter()
10559            .map(|s| s.ident.name.as_str())
10560            .collect::<Vec<_>>()
10561            .join("::");
10562
10563        // Resolve "Self" to the actual type name if we're in an impl block
10564        let name = if raw_name == "Self" {
10565            if let Some(ref self_type) = self.current_self_type {
10566                self_type.clone()
10567            } else {
10568                // Fall back to trying to infer from field names
10569                raw_name
10570            }
10571        } else {
10572            raw_name
10573        };
10574
10575        let mut field_values = HashMap::new();
10576
10577        // If there's a rest expression (..expr), evaluate it first to get base fields
10578        if let Some(rest_expr) = rest {
10579            // Set current_self_type for the rest expression (e.g., Default::default())
10580            let prev_self_type = self.current_self_type.clone();
10581            self.current_self_type = Some(name.clone());
10582
10583            let rest_value = self.evaluate(rest_expr)?;
10584
10585            self.current_self_type = prev_self_type;
10586
10587            // Extract fields from the rest value
10588            if let Value::Struct {
10589                fields: rest_fields,
10590                ..
10591            } = rest_value
10592            {
10593                for (k, v) in rest_fields.borrow().iter() {
10594                    field_values.insert(k.clone(), v.clone());
10595                }
10596            }
10597        }
10598
10599        // Override with explicitly provided fields
10600        for field in fields {
10601            let value = match &field.value {
10602                Some(expr) => self.evaluate(expr)?,
10603                None => self
10604                    .environment
10605                    .borrow()
10606                    .get(&field.name.name)
10607                    .ok_or_else(|| {
10608                        RuntimeError::new(format!("Unknown variable: {}", field.name.name))
10609                    })?,
10610            };
10611            field_values.insert(field.name.name.clone(), value);
10612        }
10613
10614        Ok(Value::Struct {
10615            name,
10616            fields: Rc::new(RefCell::new(field_values)),
10617        })
10618    }
10619
10620    /// Extract evidentiality from a value (recursively unwraps Evidential wrapper)
10621    fn extract_evidence(value: &Value) -> Option<Evidence> {
10622        match value {
10623            Value::Evidential { evidence, .. } => Some(*evidence),
10624            _ => None,
10625        }
10626    }
10627
10628    /// Extract affect from a value
10629    fn extract_affect(value: &Value) -> Option<&RuntimeAffect> {
10630        match value {
10631            Value::Affective { affect, .. } => Some(affect),
10632            _ => None,
10633        }
10634    }
10635
10636    /// Derive evidence from affect markers.
10637    /// Sarcasm implies uncertainty (meaning is inverted).
10638    /// Confidence directly maps to evidence levels.
10639    fn affect_to_evidence(affect: &RuntimeAffect) -> Option<Evidence> {
10640        // Sarcasm indicates the literal meaning shouldn't be trusted
10641        if affect.sarcasm {
10642            return Some(Evidence::Uncertain);
10643        }
10644
10645        // Confidence maps directly to evidence
10646        match affect.confidence {
10647            Some(RuntimeConfidence::High) => Some(Evidence::Known),
10648            Some(RuntimeConfidence::Low) => Some(Evidence::Uncertain),
10649            Some(RuntimeConfidence::Medium) | None => None,
10650        }
10651    }
10652
10653    /// Combine two evidence levels, returning the "worst" (most uncertain) one.
10654    /// Order: Known < Uncertain < Reported < Paradox
10655    fn combine_evidence(a: Option<Evidence>, b: Option<Evidence>) -> Option<Evidence> {
10656        match (a, b) {
10657            (None, None) => None,
10658            (Some(e), None) | (None, Some(e)) => Some(e),
10659            (Some(a), Some(b)) => {
10660                let rank = |e: Evidence| match e {
10661                    Evidence::Known => 0,
10662                    Evidence::Uncertain => 1,
10663                    Evidence::Reported => 2,
10664                    Evidence::Paradox => 3,
10665                };
10666                if rank(a) >= rank(b) {
10667                    Some(a)
10668                } else {
10669                    Some(b)
10670                }
10671            }
10672        }
10673    }
10674
10675    /// Unwrap an evidential value to get the inner value for display
10676    fn unwrap_evidential(value: &Value) -> &Value {
10677        match value {
10678            Value::Evidential { value: inner, .. } => Self::unwrap_evidential(inner),
10679            _ => value,
10680        }
10681    }
10682
10683    /// Unwrap an affective value to get the inner value
10684    fn unwrap_affective(value: &Value) -> &Value {
10685        match value {
10686            Value::Affective { value: inner, .. } => Self::unwrap_affective(inner),
10687            _ => value,
10688        }
10689    }
10690
10691    /// Unwrap both evidential and affective wrappers
10692    fn unwrap_value(value: &Value) -> &Value {
10693        match value {
10694            Value::Evidential { value: inner, .. } => Self::unwrap_value(inner),
10695            Value::Affective { value: inner, .. } => Self::unwrap_value(inner),
10696            _ => value,
10697        }
10698    }
10699
10700    /// Unwrap all wrappers including Ref for deep value access
10701    fn unwrap_all(value: &Value) -> Value {
10702        match value {
10703            Value::Evidential { value: inner, .. } => Self::unwrap_all(inner),
10704            Value::Affective { value: inner, .. } => Self::unwrap_all(inner),
10705            Value::Ref(r) => Self::unwrap_all(&r.borrow()),
10706            _ => value.clone(),
10707        }
10708    }
10709
10710    fn eval_evidential(&mut self, expr: &Expr, ev: &Evidentiality) -> Result<Value, RuntimeError> {
10711        let value = self.evaluate(expr)?;
10712
10713        // For Known (!) evidentiality - this is an "unwrap" or "assert known" operation
10714        // If the value is null, return null (propagate nulls for graceful handling)
10715        // If the value is already evidential, unwrap it
10716        // Otherwise, return the value as-is (it's implicitly known)
10717        if *ev == Evidentiality::Known {
10718            return match value {
10719                Value::Null => Ok(Value::Null), // Null propagates
10720                Value::Evidential { value: inner, .. } => Ok(*inner), // Unwrap evidential
10721                other => Ok(other),             // Non-null, non-evidential returns as-is
10722            };
10723        }
10724
10725        let evidence = match ev {
10726            Evidentiality::Known => Evidence::Known, // Won't reach here
10727            Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
10728            Evidentiality::Reported => Evidence::Reported,
10729            Evidentiality::Paradox => Evidence::Paradox,
10730        };
10731        Ok(Value::Evidential {
10732            value: Box::new(value),
10733            evidence,
10734        })
10735    }
10736
10737    /// Evaluate format! macro - parse format string and arguments
10738    fn eval_format_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
10739        // Token string looks like: "\"format string\" , arg1 , arg2"
10740        // We need to parse this properly
10741
10742        // Find the format string (first quoted string)
10743        let tokens = tokens.trim();
10744        if !tokens.starts_with('"') {
10745            // No format string - just return the tokens as-is
10746            return Ok(Value::String(Rc::new(tokens.to_string())));
10747        }
10748
10749        // Find the end of the format string
10750        let mut in_escape = false;
10751        let mut format_end = 1;
10752        for (i, c) in tokens[1..].char_indices() {
10753            if in_escape {
10754                in_escape = false;
10755            } else if c == '\\' {
10756                in_escape = true;
10757            } else if c == '"' {
10758                format_end = i + 2; // +1 for starting quote, +1 for this quote
10759                break;
10760            }
10761        }
10762
10763        let format_str = &tokens[1..format_end - 1]; // Remove quotes
10764        crate::sigil_debug!("DEBUG format_str: '{}'", format_str);
10765        let args_str = if format_end < tokens.len() {
10766            tokens[format_end..].trim_start_matches(',').trim()
10767        } else {
10768            ""
10769        };
10770
10771        // Parse and evaluate arguments
10772        let mut arg_values: Vec<String> = Vec::new();
10773        if !args_str.is_empty() {
10774            // Split by comma, but respect parentheses/brackets
10775            let mut depth = 0;
10776            let mut current_arg = String::new();
10777            for c in args_str.chars() {
10778                match c {
10779                    '(' | '[' | '{' => {
10780                        depth += 1;
10781                        current_arg.push(c);
10782                    }
10783                    ')' | ']' | '}' => {
10784                        depth -= 1;
10785                        current_arg.push(c);
10786                    }
10787                    ',' if depth == 0 => {
10788                        let arg = current_arg.trim().to_string();
10789                        if !arg.is_empty() {
10790                            // Parse and evaluate the argument expression
10791                            let mut parser = crate::parser::Parser::new(&arg);
10792                            match parser.parse_expr() {
10793                                Ok(expr) => match self.evaluate(&expr) {
10794                                    Ok(val) => arg_values.push(self.format_value(&val)),
10795                                    Err(_) => arg_values.push(arg),
10796                                },
10797                                Err(_) => arg_values.push(arg),
10798                            }
10799                        }
10800                        current_arg.clear();
10801                    }
10802                    _ => current_arg.push(c),
10803                }
10804            }
10805            // Don't forget the last argument
10806            let arg = current_arg.trim().to_string();
10807            if !arg.is_empty() {
10808                let mut parser = crate::parser::Parser::new(&arg);
10809                match parser.parse_expr() {
10810                    Ok(expr) => match self.evaluate(&expr) {
10811                        Ok(val) => arg_values.push(self.format_value(&val)),
10812                        Err(_) => arg_values.push(arg),
10813                    },
10814                    Err(_) => arg_values.push(arg),
10815                }
10816            }
10817        }
10818
10819        // Format the string by replacing {} and {:?} with arguments
10820        let mut result = String::new();
10821        let mut arg_idx = 0;
10822        let mut chars = format_str.chars().peekable();
10823
10824        while let Some(c) = chars.next() {
10825            if c == '{' {
10826                if chars.peek() == Some(&'{') {
10827                    // Escaped {{ -> {
10828                    chars.next();
10829                    result.push('{');
10830                } else {
10831                    // Consume until }
10832                    let mut placeholder = String::new();
10833                    while let Some(pc) = chars.next() {
10834                        if pc == '}' {
10835                            break;
10836                        }
10837                        placeholder.push(pc);
10838                    }
10839                    // Insert argument value
10840                    if arg_idx < arg_values.len() {
10841                        result.push_str(&arg_values[arg_idx]);
10842                        arg_idx += 1;
10843                    } else {
10844                        result.push_str(&format!("{{{}}}", placeholder));
10845                    }
10846                }
10847            } else if c == '}' {
10848                if chars.peek() == Some(&'}') {
10849                    // Escaped }} -> }
10850                    chars.next();
10851                    result.push('}');
10852                } else {
10853                    result.push('}');
10854                }
10855            } else if c == '\\' {
10856                // Handle escape sequences
10857                if let Some(next) = chars.next() {
10858                    match next {
10859                        'n' => result.push('\n'),
10860                        't' => result.push('\t'),
10861                        'r' => result.push('\r'),
10862                        '\\' => result.push('\\'),
10863                        '"' => result.push('"'),
10864                        _ => {
10865                            result.push('\\');
10866                            result.push(next);
10867                        }
10868                    }
10869                }
10870            } else {
10871                result.push(c);
10872            }
10873        }
10874
10875        Ok(Value::String(Rc::new(result)))
10876    }
10877
10878    /// Format a value for display in format!
10879    fn format_value(&self, value: &Value) -> String {
10880        match value {
10881            Value::String(s) => s.to_string(),
10882            Value::Int(n) => n.to_string(),
10883            Value::Float(f) => f.to_string(),
10884            Value::Bool(b) => b.to_string(),
10885            Value::Char(c) => c.to_string(),
10886            Value::Null => "null".to_string(),
10887            Value::Array(arr) => {
10888                let items: Vec<String> =
10889                    arr.borrow().iter().map(|v| self.format_value(v)).collect();
10890                format!("[{}]", items.join(", "))
10891            }
10892            Value::Tuple(items) => {
10893                let formatted: Vec<String> = items.iter().map(|v| self.format_value(v)).collect();
10894                format!("({})", formatted.join(", "))
10895            }
10896            Value::Struct { name, fields } => {
10897                let field_strs: Vec<String> = fields
10898                    .borrow()
10899                    .iter()
10900                    .map(|(k, v)| format!("{}: {}", k, self.format_value(v)))
10901                    .collect();
10902                format!("{} {{ {} }}", name, field_strs.join(", "))
10903            }
10904            Value::Variant {
10905                enum_name,
10906                variant_name,
10907                fields,
10908            } => match fields {
10909                Some(f) if !f.is_empty() => {
10910                    let formatted: Vec<String> = f.iter().map(|v| self.format_value(v)).collect();
10911                    format!("{}::{}({})", enum_name, variant_name, formatted.join(", "))
10912                }
10913                _ => format!("{}::{}", enum_name, variant_name),
10914            },
10915            Value::Evidential {
10916                value: inner,
10917                evidence,
10918            } => {
10919                format!("{:?}{}", evidence, self.format_value(inner))
10920            }
10921            Value::Ref(r) => self.format_value(&r.borrow()),
10922            _ => format!("{:?}", value),
10923        }
10924    }
10925
10926    /// Evaluate vec! macro
10927    fn eval_vec_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
10928        // Parse comma-separated elements
10929        let mut elements = Vec::new();
10930        let mut depth = 0;
10931        let mut current = String::new();
10932
10933        for c in tokens.chars() {
10934            match c {
10935                '(' | '[' | '{' => {
10936                    depth += 1;
10937                    current.push(c);
10938                }
10939                ')' | ']' | '}' => {
10940                    depth -= 1;
10941                    current.push(c);
10942                }
10943                ',' if depth == 0 => {
10944                    let elem = current.trim().to_string();
10945                    if !elem.is_empty() {
10946                        let mut parser = crate::parser::Parser::new(&elem);
10947                        if let Ok(expr) = parser.parse_expr() {
10948                            elements.push(self.evaluate(&expr)?);
10949                        }
10950                    }
10951                    current.clear();
10952                }
10953                _ => current.push(c),
10954            }
10955        }
10956
10957        // Last element
10958        let elem = current.trim().to_string();
10959        if !elem.is_empty() {
10960            let mut parser = crate::parser::Parser::new(&elem);
10961            if let Ok(expr) = parser.parse_expr() {
10962                elements.push(self.evaluate(&expr)?);
10963            }
10964        }
10965
10966        Ok(Value::Array(Rc::new(RefCell::new(elements))))
10967    }
10968
10969    fn eval_range(
10970        &mut self,
10971        start: &Option<Box<Expr>>,
10972        end: &Option<Box<Expr>>,
10973        inclusive: bool,
10974    ) -> Result<Value, RuntimeError> {
10975        let start_val = match start {
10976            Some(e) => match self.evaluate(e)? {
10977                Value::Int(n) => n,
10978                _ => return Err(RuntimeError::new("Range requires integer bounds")),
10979            },
10980            None => 0,
10981        };
10982
10983        let end_val = match end {
10984            Some(e) => match self.evaluate(e)? {
10985                Value::Int(n) => n,
10986                _ => return Err(RuntimeError::new("Range requires integer bounds")),
10987            },
10988            None => {
10989                // Open-ended range (like 1..) - return a tuple (start, None) marker
10990                // This can be used by slice operations to slice to end
10991                return Ok(Value::Tuple(Rc::new(vec![
10992                    Value::Int(start_val),
10993                    Value::Null, // None marker for open end
10994                ])));
10995            }
10996        };
10997
10998        let values: Vec<Value> = if inclusive {
10999            (start_val..=end_val).map(Value::Int).collect()
11000        } else {
11001            (start_val..end_val).map(Value::Int).collect()
11002        };
11003
11004        Ok(Value::Array(Rc::new(RefCell::new(values))))
11005    }
11006
11007    fn is_truthy(&self, value: &Value) -> bool {
11008        match value {
11009            Value::Null => false,
11010            Value::Bool(b) => *b,
11011            Value::Int(n) => *n != 0,
11012            Value::Float(n) => *n != 0.0,
11013            Value::String(s) => !s.is_empty(),
11014            Value::Array(arr) => !arr.borrow().is_empty(),
11015            Value::Empty => false,
11016            Value::Evidential { value, .. } => self.is_truthy(value),
11017            _ => true,
11018        }
11019    }
11020}
11021
11022impl Default for Interpreter {
11023    fn default() -> Self {
11024        Self::new()
11025    }
11026}
11027
11028#[cfg(test)]
11029mod tests {
11030    use super::*;
11031    use crate::Parser;
11032
11033    fn run(source: &str) -> Result<Value, RuntimeError> {
11034        let mut parser = Parser::new(source);
11035        let file = parser
11036            .parse_file()
11037            .map_err(|e| RuntimeError::new(e.to_string()))?;
11038        let mut interp = Interpreter::new();
11039        interp.execute(&file)
11040    }
11041
11042    #[test]
11043    fn test_arithmetic() {
11044        assert!(matches!(
11045            run("fn main() { return 2 + 3; }"),
11046            Ok(Value::Int(5))
11047        ));
11048        assert!(matches!(
11049            run("fn main() { return 10 - 4; }"),
11050            Ok(Value::Int(6))
11051        ));
11052        assert!(matches!(
11053            run("fn main() { return 3 * 4; }"),
11054            Ok(Value::Int(12))
11055        ));
11056        assert!(matches!(
11057            run("fn main() { return 15 / 3; }"),
11058            Ok(Value::Int(5))
11059        ));
11060        assert!(matches!(
11061            run("fn main() { return 2 ** 10; }"),
11062            Ok(Value::Int(1024))
11063        ));
11064    }
11065
11066    #[test]
11067    fn test_variables() {
11068        assert!(matches!(
11069            run("fn main() { let x = 42; return x; }"),
11070            Ok(Value::Int(42))
11071        ));
11072    }
11073
11074    #[test]
11075    fn test_conditionals() {
11076        assert!(matches!(
11077            run("fn main() { if true { return 1; } else { return 2; } }"),
11078            Ok(Value::Int(1))
11079        ));
11080        assert!(matches!(
11081            run("fn main() { if false { return 1; } else { return 2; } }"),
11082            Ok(Value::Int(2))
11083        ));
11084    }
11085
11086    #[test]
11087    fn test_arrays() {
11088        assert!(matches!(
11089            run("fn main() { return [1, 2, 3][1]; }"),
11090            Ok(Value::Int(2))
11091        ));
11092    }
11093
11094    #[test]
11095    fn test_functions() {
11096        let result = run("
11097            fn double(x: i64) -> i64 { return x * 2; }
11098            fn main() { return double(21); }
11099        ");
11100        assert!(matches!(result, Ok(Value::Int(42))));
11101    }
11102
11103    #[test]
11104    fn test_pipe_transform() {
11105        let result = run("fn main() { return [1, 2, 3]|τ{_ * 2}|sum; }");
11106        assert!(matches!(result, Ok(Value::Int(12))));
11107    }
11108
11109    #[test]
11110    fn test_pipe_filter() {
11111        let result = run("fn main() { return [1, 2, 3, 4, 5]|φ{_ > 2}|sum; }");
11112        assert!(matches!(result, Ok(Value::Int(12)))); // 3 + 4 + 5
11113    }
11114
11115    #[test]
11116    fn test_interpolation_evidentiality_propagation() {
11117        // Test that evidentiality propagates through string interpolation
11118        // When an evidential value is interpolated, the result string should carry that evidentiality
11119        let result = run(r#"
11120            fn main() {
11121                let rep = reported(42);
11122
11123                // Interpolating a reported value should make the string reported
11124                let s = f"Value: {rep}";
11125                return s;
11126            }
11127        "#);
11128
11129        match result {
11130            Ok(Value::Evidential {
11131                evidence: Evidence::Reported,
11132                value,
11133            }) => {
11134                // The inner value should be a string
11135                assert!(matches!(*value, Value::String(_)));
11136            }
11137            Ok(other) => panic!("Expected Evidential Reported, got {:?}", other),
11138            Err(e) => panic!("Error: {:?}", e),
11139        }
11140    }
11141
11142    #[test]
11143    fn test_interpolation_worst_evidence_wins() {
11144        // When multiple evidential values are interpolated, the worst evidence level wins
11145        let result = run(r#"
11146            fn main() {
11147                let k = known(1);         // Known is best
11148                let u = uncertain(2);     // Uncertain is worse
11149
11150                // Combining known and uncertain should yield uncertain
11151                let s = f"{k} and {u}";
11152                return s;
11153            }
11154        "#);
11155
11156        match result {
11157            Ok(Value::Evidential {
11158                evidence: Evidence::Uncertain,
11159                ..
11160            }) => (),
11161            Ok(other) => panic!("Expected Evidential Uncertain, got {:?}", other),
11162            Err(e) => panic!("Error: {:?}", e),
11163        }
11164    }
11165
11166    #[test]
11167    fn test_interpolation_no_evidential_plain_string() {
11168        // When no evidential values are interpolated, the result is a plain string
11169        let result = run(r#"
11170            fn main() {
11171                let x = 42;
11172                let s = f"Value: {x}";
11173                return s;
11174            }
11175        "#);
11176
11177        match result {
11178            Ok(Value::String(s)) => {
11179                assert_eq!(*s, "Value: 42");
11180            }
11181            Ok(other) => panic!("Expected plain String, got {:?}", other),
11182            Err(e) => panic!("Error: {:?}", e),
11183        }
11184    }
11185}