Skip to main content

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// WebSocket support (feature-gated, native implementation)
16#[cfg(feature = "websocket")]
17use crate::websocket;
18
19/// Runtime value in Sigil.
20#[derive(Clone)]
21pub enum Value {
22    /// Null/void
23    Null,
24    /// Boolean
25    Bool(bool),
26    /// Integer (64-bit)
27    Int(i64),
28    /// Float (64-bit)
29    Float(f64),
30    /// String
31    String(Rc<String>),
32    /// Character
33    Char(char),
34    /// Array/list
35    Array(Rc<RefCell<Vec<Value>>>),
36    /// Tuple
37    Tuple(Rc<Vec<Value>>),
38    /// Struct instance
39    Struct {
40        name: String,
41        fields: Rc<RefCell<HashMap<String, Value>>>,
42    },
43    /// Enum variant
44    Variant {
45        enum_name: String,
46        variant_name: String,
47        fields: Option<Rc<Vec<Value>>>,
48    },
49    /// Function/closure
50    Function(Rc<Function>),
51    /// Built-in function
52    BuiltIn(Rc<BuiltInFn>),
53    /// Reference to another value
54    Ref(Rc<RefCell<Value>>),
55    /// Special mathematical values
56    Infinity,
57    Empty,
58    /// Evidence-wrapped value
59    Evidential {
60        value: Box<Value>,
61        evidence: Evidence,
62    },
63    /// Affect-wrapped value (sentiment, emotion, sarcasm, etc.)
64    Affective {
65        value: Box<Value>,
66        affect: RuntimeAffect,
67    },
68    /// HashMap
69    Map(Rc<RefCell<HashMap<String, Value>>>),
70    /// HashSet (stores keys only, values are unit)
71    Set(Rc<RefCell<std::collections::HashSet<String>>>),
72    /// Channel for message passing (sender, receiver)
73    Channel(Arc<ChannelInner>),
74    /// Thread handle
75    ThreadHandle(Arc<Mutex<Option<JoinHandle<Value>>>>),
76    /// Actor (mailbox + state)
77    Actor(Arc<ActorInner>),
78    /// Future - represents an async computation
79    Future(Rc<RefCell<FutureInner>>),
80    /// Variant constructor (for creating enum variants)
81    VariantConstructor {
82        enum_name: String,
83        variant_name: String,
84    },
85    /// Default constructor (for default trait)
86    DefaultConstructor {
87        type_name: String,
88    },
89    /// Range value (start..end or start..=end)
90    Range {
91        start: Option<i64>,
92        end: Option<i64>,
93        inclusive: bool,
94    },
95}
96
97/// Future state for async computations
98#[derive(Clone)]
99pub enum FutureState {
100    /// Not yet started
101    Pending,
102    /// Currently executing
103    Running,
104    /// Completed with value
105    Ready(Box<Value>),
106    /// Failed with error
107    Failed(String),
108}
109
110/// Inner future representation
111pub struct FutureInner {
112    /// Current state
113    pub state: FutureState,
114    /// The computation to run (if pending)
115    pub computation: Option<FutureComputation>,
116    /// Completion time for timer futures
117    pub complete_at: Option<std::time::Instant>,
118}
119
120impl Clone for FutureInner {
121    fn clone(&self) -> Self {
122        FutureInner {
123            state: self.state.clone(),
124            computation: self.computation.clone(),
125            complete_at: self.complete_at,
126        }
127    }
128}
129
130/// Types of future computations
131#[derive(Clone)]
132pub enum FutureComputation {
133    /// Immediate value (already resolved)
134    Immediate(Box<Value>),
135    /// Timer - completes after duration
136    Timer(std::time::Duration),
137    /// Lazy computation - function + captured args
138    Lazy {
139        func: Rc<Function>,
140        args: Vec<Value>,
141    },
142    /// Join multiple futures
143    Join(Vec<Rc<RefCell<FutureInner>>>),
144    /// Race multiple futures (first to complete wins)
145    Race(Vec<Rc<RefCell<FutureInner>>>),
146}
147
148/// Inner channel state - wraps mpsc channel
149pub struct ChannelInner {
150    pub sender: Mutex<mpsc::Sender<Value>>,
151    pub receiver: Mutex<mpsc::Receiver<Value>>,
152}
153
154impl Clone for ChannelInner {
155    fn clone(&self) -> Self {
156        // Channels can't really be cloned - create a dummy
157        // This is for the Clone requirement on Value
158        panic!("Channels cannot be cloned directly - use channel_clone()")
159    }
160}
161
162/// Inner actor state - single-threaded for interpreter (Value contains Rc)
163/// For true async actors, use the JIT backend
164pub struct ActorInner {
165    pub name: String,
166    pub message_queue: Mutex<Vec<(String, String)>>, // (msg_type, serialized_data)
167    pub message_count: std::sync::atomic::AtomicUsize,
168}
169
170/// Evidence level at runtime
171#[derive(Debug, Clone, Copy, PartialEq, Eq)]
172pub enum Evidence {
173    Known,     // !
174    Uncertain, // ?
175    Reported,  // ~
176    Predicted, // ◊
177    Paradox,   // ‽
178}
179
180/// Runtime affect markers for sentiment and emotion tracking
181#[derive(Debug, Clone, PartialEq)]
182pub struct RuntimeAffect {
183    pub sentiment: Option<RuntimeSentiment>,
184    pub sarcasm: bool, // ⸮
185    pub intensity: Option<RuntimeIntensity>,
186    pub formality: Option<RuntimeFormality>,
187    pub emotion: Option<RuntimeEmotion>,
188    pub confidence: Option<RuntimeConfidence>,
189}
190
191#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192pub enum RuntimeSentiment {
193    Positive, // ⊕
194    Negative, // ⊖
195    Neutral,  // ⊜
196}
197
198#[derive(Debug, Clone, Copy, PartialEq, Eq)]
199pub enum RuntimeIntensity {
200    Up,   // ↑
201    Down, // ↓
202    Max,  // ⇈
203}
204
205#[derive(Debug, Clone, Copy, PartialEq, Eq)]
206pub enum RuntimeFormality {
207    Formal,   // ♔
208    Informal, // ♟
209}
210
211#[derive(Debug, Clone, Copy, PartialEq, Eq)]
212pub enum RuntimeEmotion {
213    Joy,      // ☺
214    Sadness,  // ☹
215    Anger,    // ⚡
216    Fear,     // ❄
217    Surprise, // ✦
218    Love,     // ♡
219}
220
221#[derive(Debug, Clone, Copy, PartialEq, Eq)]
222pub enum RuntimeConfidence {
223    High,   // ◉
224    Medium, // ◎
225    Low,    // ○
226}
227
228/// A Sigil function
229pub struct Function {
230    pub name: Option<String>,
231    pub params: Vec<String>,
232    pub body: Expr,
233    pub closure: Rc<RefCell<Environment>>,
234    /// Generic type parameter names (e.g., ["T", "U"] for fn foo<T, U>())
235    pub generic_params: Vec<String>,
236}
237
238/// Built-in function type
239pub struct BuiltInFn {
240    pub name: String,
241    pub arity: Option<usize>, // None = variadic
242    pub func: fn(&mut Interpreter, Vec<Value>) -> Result<Value, RuntimeError>,
243}
244
245impl fmt::Debug for Value {
246    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247        match self {
248            Value::Null => write!(f, "null"),
249            Value::Bool(b) => write!(f, "{}", b),
250            Value::Int(n) => write!(f, "{}", n),
251            Value::Float(n) => write!(f, "{}", n),
252            Value::String(s) => write!(f, "\"{}\"", s),
253            Value::Char(c) => write!(f, "'{}'", c),
254            Value::Array(arr) => {
255                let arr = arr.borrow();
256                write!(f, "[")?;
257                for (i, v) in arr.iter().enumerate() {
258                    if i > 0 {
259                        write!(f, ", ")?;
260                    }
261                    write!(f, "{:?}", v)?;
262                }
263                write!(f, "]")
264            }
265            Value::Tuple(vals) => {
266                write!(f, "(")?;
267                for (i, v) in vals.iter().enumerate() {
268                    if i > 0 {
269                        write!(f, ", ")?;
270                    }
271                    write!(f, "{:?}", v)?;
272                }
273                write!(f, ")")
274            }
275            Value::Struct { name, fields } => {
276                write!(f, "{} {{ ", name)?;
277                let fields = fields.borrow();
278                for (i, (k, v)) in fields.iter().enumerate() {
279                    if i > 0 {
280                        write!(f, ", ")?;
281                    }
282                    write!(f, "{}: {:?}", k, v)?;
283                }
284                write!(f, " }}")
285            }
286            Value::Variant {
287                enum_name,
288                variant_name,
289                fields,
290            } => {
291                write!(f, "{}::{}", enum_name, variant_name)?;
292                if let Some(fields) = fields {
293                    write!(f, "(")?;
294                    for (i, v) in fields.iter().enumerate() {
295                        if i > 0 {
296                            write!(f, ", ")?;
297                        }
298                        write!(f, "{:?}", v)?;
299                    }
300                    write!(f, ")")?;
301                }
302                Ok(())
303            }
304            Value::Function(func) => {
305                write!(f, "<fn {}>", func.name.as_deref().unwrap_or("anonymous"))
306            }
307            Value::BuiltIn(b) => write!(f, "<builtin {}>", b.name),
308            Value::Ref(r) => write!(f, "&{:?}", r.borrow()),
309            Value::Infinity => write!(f, "∞"),
310            Value::Empty => write!(f, "∅"),
311            Value::Evidential { value, evidence } => {
312                write!(f, "{:?}", value)?;
313                match evidence {
314                    Evidence::Known => write!(f, "!"),
315                    Evidence::Uncertain => write!(f, "?"),
316                    Evidence::Reported => write!(f, "~"),
317                    Evidence::Predicted => write!(f, "◊"),
318                    Evidence::Paradox => write!(f, "‽"),
319                }
320            }
321            Value::Map(map) => {
322                let map = map.borrow();
323                write!(f, "{{")?;
324                for (i, (k, v)) in map.iter().enumerate() {
325                    if i > 0 {
326                        write!(f, ", ")?;
327                    }
328                    write!(f, "{:?}: {:?}", k, v)?;
329                }
330                write!(f, "}}")
331            }
332            Value::Set(set) => {
333                let set = set.borrow();
334                write!(f, "Set{{")?;
335                for (i, k) in set.iter().enumerate() {
336                    if i > 0 {
337                        write!(f, ", ")?;
338                    }
339                    write!(f, "{:?}", k)?;
340                }
341                write!(f, "}}")
342            }
343            Value::Channel(_) => write!(f, "<channel>"),
344            Value::ThreadHandle(_) => write!(f, "<thread>"),
345            Value::Actor(actor) => write!(f, "<actor {}>", actor.name),
346            Value::Future(fut) => {
347                let fut = fut.borrow();
348                match &fut.state {
349                    FutureState::Pending => write!(f, "<future pending>"),
350                    FutureState::Running => write!(f, "<future running>"),
351                    FutureState::Ready(v) => write!(f, "<future ready: {:?}>", v),
352                    FutureState::Failed(e) => write!(f, "<future failed: {}>", e),
353                }
354            }
355            Value::Affective { value, affect } => {
356                write!(f, "{:?}", value)?;
357                if let Some(s) = &affect.sentiment {
358                    match s {
359                        RuntimeSentiment::Positive => write!(f, "⊕")?,
360                        RuntimeSentiment::Negative => write!(f, "⊖")?,
361                        RuntimeSentiment::Neutral => write!(f, "⊜")?,
362                    }
363                }
364                if affect.sarcasm {
365                    write!(f, "⸮")?;
366                }
367                if let Some(i) = &affect.intensity {
368                    match i {
369                        RuntimeIntensity::Up => write!(f, "↑")?,
370                        RuntimeIntensity::Down => write!(f, "↓")?,
371                        RuntimeIntensity::Max => write!(f, "⇈")?,
372                    }
373                }
374                if let Some(fo) = &affect.formality {
375                    match fo {
376                        RuntimeFormality::Formal => write!(f, "♔")?,
377                        RuntimeFormality::Informal => write!(f, "♟")?,
378                    }
379                }
380                if let Some(e) = &affect.emotion {
381                    match e {
382                        RuntimeEmotion::Joy => write!(f, "☺")?,
383                        RuntimeEmotion::Sadness => write!(f, "☹")?,
384                        RuntimeEmotion::Anger => write!(f, "⚡")?,
385                        RuntimeEmotion::Fear => write!(f, "❄")?,
386                        RuntimeEmotion::Surprise => write!(f, "✦")?,
387                        RuntimeEmotion::Love => write!(f, "♡")?,
388                    }
389                }
390                if let Some(c) = &affect.confidence {
391                    match c {
392                        RuntimeConfidence::High => write!(f, "◉")?,
393                        RuntimeConfidence::Medium => write!(f, "◎")?,
394                        RuntimeConfidence::Low => write!(f, "○")?,
395                    }
396                }
397                Ok(())
398            }
399            Value::VariantConstructor {
400                enum_name,
401                variant_name,
402            } => {
403                write!(f, "<constructor {}::{}>", enum_name, variant_name)
404            }
405            Value::DefaultConstructor { type_name } => {
406                write!(f, "<default {}>", type_name)
407            }
408            Value::Range {
409                start,
410                end,
411                inclusive,
412            } => match (start, end) {
413                (Some(s), Some(e)) => {
414                    if *inclusive {
415                        write!(f, "{}..={}", s, e)
416                    } else {
417                        write!(f, "{}..{}", s, e)
418                    }
419                }
420                (Some(s), None) => write!(f, "{}..", s),
421                (None, Some(e)) => {
422                    if *inclusive {
423                        write!(f, "..={}", e)
424                    } else {
425                        write!(f, "..{}", e)
426                    }
427                }
428                (None, None) => write!(f, ".."),
429            },
430        }
431    }
432}
433
434impl fmt::Display for Value {
435    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
436        match self {
437            Value::Null => write!(f, "null"),
438            Value::Bool(b) => write!(f, "{}", b),
439            Value::Int(n) => write!(f, "{}", n),
440            Value::Float(n) => {
441                // Print whole numbers without decimal point (e.g., 6.0 -> "6")
442                // This matches the 100% test pass behavior
443                if n.fract() == 0.0 && n.is_finite() {
444                    write!(f, "{}", *n as i64)
445                } else {
446                    write!(f, "{}", n)
447                }
448            }
449            Value::String(s) => write!(f, "{}", s),
450            Value::Char(c) => write!(f, "{}", c),
451            Value::Array(arr) => {
452                let arr = arr.borrow();
453                write!(f, "[")?;
454                for (i, v) in arr.iter().enumerate() {
455                    if i > 0 {
456                        write!(f, ", ")?;
457                    }
458                    write!(f, "{}", v)?;
459                }
460                write!(f, "]")
461            }
462            Value::Evidential { value, .. } => write!(f, "{}", value),
463            Value::Affective { value, affect } => {
464                // Display affect markers as suffix symbols
465                let mut suffix = String::new();
466                if let Some(sent) = &affect.sentiment {
467                    suffix.push(match sent {
468                        RuntimeSentiment::Positive => '⊕',
469                        RuntimeSentiment::Negative => '⊖',
470                        RuntimeSentiment::Neutral => '⊜',
471                    });
472                }
473                if affect.sarcasm {
474                    suffix.push('⸮');
475                }
476                if let Some(int) = &affect.intensity {
477                    suffix.push(match int {
478                        RuntimeIntensity::Up => '↑',
479                        RuntimeIntensity::Down => '↓',
480                        RuntimeIntensity::Max => '⇈',
481                    });
482                }
483                if let Some(form) = &affect.formality {
484                    suffix.push(match form {
485                        RuntimeFormality::Formal => '♔',
486                        RuntimeFormality::Informal => '♟',
487                    });
488                }
489                if let Some(emo) = &affect.emotion {
490                    suffix.push(match emo {
491                        RuntimeEmotion::Joy => '☺',
492                        RuntimeEmotion::Sadness => '☹',
493                        RuntimeEmotion::Anger => '⚡',
494                        RuntimeEmotion::Fear => '❄',
495                        RuntimeEmotion::Surprise => '✦',
496                        RuntimeEmotion::Love => '♡',
497                    });
498                }
499                if let Some(conf) = &affect.confidence {
500                    suffix.push(match conf {
501                        RuntimeConfidence::High => '◉',
502                        RuntimeConfidence::Medium => '◎',
503                        RuntimeConfidence::Low => '○',
504                    });
505                }
506                write!(f, "{}{}", value, suffix)
507            }
508            // Special Display for quantum types
509            Value::Struct { name, fields } if name == "Cbit" => {
510                let fields = fields.borrow();
511                match fields.get("__value__") {
512                    Some(Value::Bool(true)) => write!(f, "1"),
513                    Some(Value::Bool(false)) => write!(f, "0"),
514                    _ => write!(f, "Cbit(invalid)"),
515                }
516            }
517            Value::Struct { name, fields } if name == "Qubit" => {
518                // Show qubit state in Dirac notation
519                let fields = fields.borrow();
520                if let Some(Value::Float(alpha)) = fields.get("__alpha_real__") {
521                    if *alpha >= 0.999 {
522                        write!(f, "|0⟩")
523                    } else if let Some(Value::Float(beta)) = fields.get("__beta_real__") {
524                        if *beta >= 0.999 {
525                            write!(f, "|1⟩")
526                        } else {
527                            write!(f, "|ψ⟩")
528                        }
529                    } else {
530                        write!(f, "|ψ⟩")
531                    }
532                } else {
533                    write!(f, "|ψ⟩")
534                }
535            }
536            Value::Struct { name, fields } if name == "Tensor" => {
537                // Show tensor data or shape
538                let fields = fields.borrow();
539                if let Some(Value::Array(data)) = fields.get("data") {
540                    let data = data.borrow();
541                    if data.len() <= 10 {
542                        write!(f, "Tensor([")?;
543                        for (i, v) in data.iter().enumerate() {
544                            if i > 0 { write!(f, ", ")?; }
545                            write!(f, "{}", v)?;
546                        }
547                        write!(f, "])")
548                    } else {
549                        write!(f, "Tensor([{} elements])", data.len())
550                    }
551                } else if let Some(Value::Float(val)) = fields.get("_value") {
552                    write!(f, "Tensor({})", val)
553                } else {
554                    write!(f, "Tensor(...)")
555                }
556            }
557            _ => write!(f, "{:?}", self),
558        }
559    }
560}
561
562impl Value {
563    /// Extract a scalar f64 from a Tensor struct value.
564    /// Looks for `_value` field first, then `data[0]`.
565    /// Returns None if the value is not a Tensor or has no numeric data.
566    pub fn as_tensor_scalar(&self) -> Option<f64> {
567        match self {
568            Value::Struct { name, fields } if name == "Tensor" => {
569                tensor_scalar_from_fields(&fields.borrow())
570            }
571            Value::Float(f) => Some(*f),
572            Value::Int(n) => Some(*n as f64),
573            _ => None,
574        }
575    }
576
577    /// Extract a Vec<f64> of data from a Tensor struct.
578    /// Returns None if the value is not a Tensor or has no data field.
579    pub fn as_tensor_data(&self) -> Option<Vec<f64>> {
580        match self {
581            Value::Struct { name, fields } if name == "Tensor" => {
582                tensor_data_from_fields(&fields.borrow())
583            }
584            _ => None,
585        }
586    }
587
588    /// Extract the shape as Vec<usize> from a Tensor struct.
589    /// Returns None if the value is not a Tensor or has no shape field.
590    pub fn as_tensor_shape(&self) -> Option<Vec<usize>> {
591        match self {
592            Value::Struct { name, fields } if name == "Tensor" => {
593                tensor_shape_from_fields(&fields.borrow())
594            }
595            _ => None,
596        }
597    }
598}
599
600// ============================================================================
601// TENSOR FIELD HELPERS
602// ============================================================================
603//
604// These functions extract tensor data directly from a fields HashMap,
605// avoiding the need to reconstruct Value::Struct in binary operations.
606
607/// Extract a scalar f64 from tensor fields.
608/// Checks `_value` first, then `data[0]`.
609fn tensor_scalar_from_fields(fields: &HashMap<String, Value>) -> Option<f64> {
610    // Try _value field first (for scalar tensors)
611    if let Some(val) = fields.get("_value") {
612        match val {
613            Value::Float(f) => return Some(*f),
614            Value::Int(n) => return Some(*n as f64),
615            _ => {}
616        }
617    }
618    // Fall back to __data__[0] or data[0]
619    let data_field = fields.get("__data__").or_else(|| fields.get("data"));
620    if let Some(Value::Array(arr)) = data_field {
621        if let Some(first) = arr.borrow().first() {
622            match first {
623                Value::Float(f) => return Some(*f),
624                Value::Int(n) => return Some(*n as f64),
625                _ => {}
626            }
627        }
628    }
629    None
630}
631
632/// Extract data as Vec<f64> from tensor fields.
633/// Checks __data__ first (stdlib convention), then data (fallback).
634fn tensor_data_from_fields(fields: &HashMap<String, Value>) -> Option<Vec<f64>> {
635    let arr = fields.get("__data__").or_else(|| fields.get("data"));
636    if let Some(Value::Array(arr)) = arr {
637        Some(
638            arr.borrow()
639                .iter()
640                .map(|v| match v {
641                    Value::Float(f) => *f,
642                    Value::Int(n) => *n as f64,
643                    _ => 0.0,
644                })
645                .collect(),
646        )
647    } else {
648        None
649    }
650}
651
652/// Extract shape as Vec<usize> from tensor fields.
653/// Checks __shape__ first (stdlib convention), then shape (fallback).
654fn tensor_shape_from_fields(fields: &HashMap<String, Value>) -> Option<Vec<usize>> {
655    let arr = fields.get("__shape__").or_else(|| fields.get("shape"));
656    if let Some(Value::Array(arr)) = arr {
657        Some(
658            arr.borrow()
659                .iter()
660                .map(|v| match v {
661                    Value::Int(n) => *n as usize,
662                    _ => 0,
663                })
664                .collect(),
665        )
666    } else {
667        None
668    }
669}
670
671// ============================================================================
672// AST to Value conversion for sigil_parse (Option D - self-parsing)
673// ============================================================================
674
675use crate::ast::{Item, SourceFile, StructFields, Visibility as AstVisibility};
676use crate::span::Spanned;
677
678/// Convert a SourceFile AST to an inspectable Value
679fn ast_to_value_source_file(sf: &SourceFile) -> Value {
680    let mut fields = HashMap::new();
681
682    // Convert items
683    let items: Vec<Value> = sf
684        .items
685        .iter()
686        .map(|item| ast_to_value_item(item))
687        .collect();
688    fields.insert(
689        "items".to_string(),
690        Value::Array(Rc::new(RefCell::new(items))),
691    );
692    fields.insert("item_count".to_string(), Value::Int(sf.items.len() as i64));
693
694    // Wrap in Result::Ok
695    Value::Variant {
696        enum_name: "Result".to_string(),
697        variant_name: "Ok".to_string(),
698        fields: Some(Rc::new(vec![Value::Struct {
699            name: "SourceFile".to_string(),
700            fields: Rc::new(RefCell::new(fields)),
701        }])),
702    }
703}
704
705/// Convert a Spanned<Item> to a Value
706fn ast_to_value_item(item: &Spanned<Item>) -> Value {
707    let mut fields = HashMap::new();
708
709    // Add span info
710    fields.insert("start".to_string(), Value::Int(item.span.start as i64));
711    fields.insert("end".to_string(), Value::Int(item.span.end as i64));
712
713    // Add item-specific info
714    match &item.node {
715        Item::Function(f) => {
716            fields.insert(
717                "kind".to_string(),
718                Value::String(Rc::new("Function".to_string())),
719            );
720            fields.insert(
721                "name".to_string(),
722                Value::String(Rc::new(f.name.name.clone())),
723            );
724            fields.insert(
725                "visibility".to_string(),
726                Value::String(Rc::new(visibility_to_string(&f.visibility))),
727            );
728            fields.insert("is_async".to_string(), Value::Bool(f.is_async));
729            fields.insert("param_count".to_string(), Value::Int(f.params.len() as i64));
730            fields.insert(
731                "has_return_type".to_string(),
732                Value::Bool(f.return_type.is_some()),
733            );
734
735            // Parameter info (simplified - just count)
736            let params: Vec<Value> = f
737                .params
738                .iter()
739                .map(|p| {
740                    let mut pf = HashMap::new();
741                    pf.insert(
742                        "type".to_string(),
743                        Value::String(Rc::new(format!("{:?}", p.ty))),
744                    );
745                    Value::Struct {
746                        name: "Param".to_string(),
747                        fields: Rc::new(RefCell::new(pf)),
748                    }
749                })
750                .collect();
751            fields.insert(
752                "params".to_string(),
753                Value::Array(Rc::new(RefCell::new(params))),
754            );
755        }
756        Item::Struct(s) => {
757            fields.insert(
758                "kind".to_string(),
759                Value::String(Rc::new("Struct".to_string())),
760            );
761            fields.insert(
762                "name".to_string(),
763                Value::String(Rc::new(s.name.name.clone())),
764            );
765            fields.insert(
766                "visibility".to_string(),
767                Value::String(Rc::new(visibility_to_string(&s.visibility))),
768            );
769
770            // Handle StructFields enum
771            let (field_count, field_names) = match &s.fields {
772                StructFields::Named(fields_vec) => {
773                    let names: Vec<Value> = fields_vec
774                        .iter()
775                        .map(|f| Value::String(Rc::new(f.name.name.clone())))
776                        .collect();
777                    (fields_vec.len() as i64, names)
778                }
779                StructFields::Tuple(types) => (types.len() as i64, vec![]),
780                StructFields::Unit => (0, vec![]),
781            };
782            fields.insert("field_count".to_string(), Value::Int(field_count));
783            fields.insert(
784                "fields".to_string(),
785                Value::Array(Rc::new(RefCell::new(field_names))),
786            );
787        }
788        Item::Enum(e) => {
789            fields.insert(
790                "kind".to_string(),
791                Value::String(Rc::new("Enum".to_string())),
792            );
793            fields.insert(
794                "name".to_string(),
795                Value::String(Rc::new(e.name.name.clone())),
796            );
797            fields.insert(
798                "visibility".to_string(),
799                Value::String(Rc::new(visibility_to_string(&e.visibility))),
800            );
801            fields.insert(
802                "variant_count".to_string(),
803                Value::Int(e.variants.len() as i64),
804            );
805
806            // Variant names
807            let variants: Vec<Value> = e
808                .variants
809                .iter()
810                .map(|v| Value::String(Rc::new(v.name.name.clone())))
811                .collect();
812            fields.insert(
813                "variants".to_string(),
814                Value::Array(Rc::new(RefCell::new(variants))),
815            );
816        }
817        Item::Trait(t) => {
818            fields.insert(
819                "kind".to_string(),
820                Value::String(Rc::new("Trait".to_string())),
821            );
822            fields.insert(
823                "name".to_string(),
824                Value::String(Rc::new(t.name.name.clone())),
825            );
826            fields.insert(
827                "visibility".to_string(),
828                Value::String(Rc::new(visibility_to_string(&t.visibility))),
829            );
830            fields.insert("method_count".to_string(), Value::Int(t.items.len() as i64));
831        }
832        Item::Impl(i) => {
833            fields.insert(
834                "kind".to_string(),
835                Value::String(Rc::new("Impl".to_string())),
836            );
837            if let Some(trait_path) = &i.trait_ {
838                fields.insert(
839                    "trait_name".to_string(),
840                    Value::String(Rc::new(format!("{:?}", trait_path))),
841                );
842            }
843            fields.insert("method_count".to_string(), Value::Int(i.items.len() as i64));
844        }
845        Item::TypeAlias(t) => {
846            fields.insert(
847                "kind".to_string(),
848                Value::String(Rc::new("TypeAlias".to_string())),
849            );
850            fields.insert(
851                "name".to_string(),
852                Value::String(Rc::new(t.name.name.clone())),
853            );
854        }
855        Item::Module(m) => {
856            fields.insert(
857                "kind".to_string(),
858                Value::String(Rc::new("Module".to_string())),
859            );
860            fields.insert(
861                "name".to_string(),
862                Value::String(Rc::new(m.name.name.clone())),
863            );
864        }
865        Item::Use(u) => {
866            fields.insert(
867                "kind".to_string(),
868                Value::String(Rc::new("Use".to_string())),
869            );
870            fields.insert(
871                "path".to_string(),
872                Value::String(Rc::new(format!("{:?}", u.tree))),
873            );
874        }
875        Item::Const(c) => {
876            fields.insert(
877                "kind".to_string(),
878                Value::String(Rc::new("Const".to_string())),
879            );
880            fields.insert(
881                "name".to_string(),
882                Value::String(Rc::new(c.name.name.clone())),
883            );
884        }
885        Item::Static(s) => {
886            fields.insert(
887                "kind".to_string(),
888                Value::String(Rc::new("Static".to_string())),
889            );
890            fields.insert(
891                "name".to_string(),
892                Value::String(Rc::new(s.name.name.clone())),
893            );
894        }
895        Item::Actor(a) => {
896            fields.insert(
897                "kind".to_string(),
898                Value::String(Rc::new("Actor".to_string())),
899            );
900            fields.insert(
901                "name".to_string(),
902                Value::String(Rc::new(a.name.name.clone())),
903            );
904        }
905        Item::ExternBlock(_) => {
906            fields.insert(
907                "kind".to_string(),
908                Value::String(Rc::new("ExternBlock".to_string())),
909            );
910        }
911        Item::Macro(m) => {
912            fields.insert(
913                "kind".to_string(),
914                Value::String(Rc::new("Macro".to_string())),
915            );
916            fields.insert(
917                "name".to_string(),
918                Value::String(Rc::new(m.name.name.clone())),
919            );
920        }
921        Item::MacroInvocation(m) => {
922            fields.insert(
923                "kind".to_string(),
924                Value::String(Rc::new("MacroInvocation".to_string())),
925            );
926            fields.insert(
927                "path".to_string(),
928                Value::String(Rc::new(format!("{:?}", m.path))),
929            );
930        }
931        Item::Plurality(_) => {
932            fields.insert(
933                "kind".to_string(),
934                Value::String(Rc::new("Plurality".to_string())),
935            );
936        }
937    }
938
939    Value::Struct {
940        name: "Item".to_string(),
941        fields: Rc::new(RefCell::new(fields)),
942    }
943}
944
945/// Convert Visibility to string
946fn visibility_to_string(vis: &AstVisibility) -> String {
947    match vis {
948        AstVisibility::Private => "private".to_string(),
949        AstVisibility::Public => "public".to_string(),
950        AstVisibility::Crate => "crate".to_string(),
951        AstVisibility::Super => "super".to_string(),
952    }
953}
954
955/// Runtime error codes for structured diagnostics
956#[derive(Debug, Clone, Copy, PartialEq, Eq)]
957pub enum RuntimeErrorCode {
958    /// R0001: Division by zero
959    DivisionByZero,
960    /// R0002: Index out of bounds
961    IndexOutOfBounds,
962    /// R0003: Undefined variable
963    UndefinedVariable,
964    /// R0004: Type error at runtime
965    TypeError,
966    /// R0005: Invalid operation
967    InvalidOperation,
968    /// R0006: Assertion failed
969    AssertionFailed,
970    /// R0007: Overflow error
971    Overflow,
972    /// R0008: Stack overflow
973    StackOverflow,
974    /// R0009: Control flow error (return/break/continue in wrong context)
975    ControlFlowError,
976    /// R0010: Linear type violation (no-cloning theorem)
977    LinearTypeViolation,
978    /// R0000: Generic runtime error
979    Generic,
980}
981
982impl RuntimeErrorCode {
983    pub fn code(&self) -> &'static str {
984        match self {
985            RuntimeErrorCode::DivisionByZero => "R0001",
986            RuntimeErrorCode::IndexOutOfBounds => "R0002",
987            RuntimeErrorCode::UndefinedVariable => "R0003",
988            RuntimeErrorCode::TypeError => "R0004",
989            RuntimeErrorCode::InvalidOperation => "R0005",
990            RuntimeErrorCode::AssertionFailed => "R0006",
991            RuntimeErrorCode::Overflow => "R0007",
992            RuntimeErrorCode::StackOverflow => "R0008",
993            RuntimeErrorCode::ControlFlowError => "R0009",
994            RuntimeErrorCode::LinearTypeViolation => "R0010",
995            RuntimeErrorCode::Generic => "R0000",
996        }
997    }
998}
999
1000/// Runtime error
1001#[derive(Debug)]
1002pub struct RuntimeError {
1003    pub message: String,
1004    pub span: Option<Span>,
1005    pub code: RuntimeErrorCode,
1006}
1007
1008impl RuntimeError {
1009    pub fn new(message: impl Into<String>) -> Self {
1010        Self {
1011            message: message.into(),
1012            span: None,
1013            code: RuntimeErrorCode::Generic,
1014        }
1015    }
1016
1017    pub fn with_span(message: impl Into<String>, span: Span) -> Self {
1018        Self {
1019            message: message.into(),
1020            span: Some(span),
1021            code: RuntimeErrorCode::Generic,
1022        }
1023    }
1024
1025    pub fn with_code(mut self, code: RuntimeErrorCode) -> Self {
1026        self.code = code;
1027        self
1028    }
1029
1030    // Convenience constructors for common runtime errors
1031
1032    /// Division by zero error
1033    pub fn division_by_zero() -> Self {
1034        Self::new("division by zero").with_code(RuntimeErrorCode::DivisionByZero)
1035    }
1036
1037    /// Linear type violation (no-cloning theorem)
1038    pub fn linear_type_violation(var_name: &str) -> Self {
1039        Self::new(format!(
1040            "linear value '{}' used twice (no-cloning theorem violation)",
1041            var_name
1042        ))
1043        .with_code(RuntimeErrorCode::LinearTypeViolation)
1044    }
1045
1046    /// Index out of bounds error
1047    pub fn index_out_of_bounds(index: i64, len: usize) -> Self {
1048        Self::new(format!("index {} out of bounds for length {}", index, len))
1049            .with_code(RuntimeErrorCode::IndexOutOfBounds)
1050    }
1051
1052    /// Undefined variable error
1053    pub fn undefined_variable(name: &str) -> Self {
1054        Self::new(format!("undefined variable: `{}`", name))
1055            .with_code(RuntimeErrorCode::UndefinedVariable)
1056    }
1057
1058    /// Type error at runtime
1059    pub fn type_error(expected: &str, found: &str) -> Self {
1060        Self::new(format!("expected {}, found {}", expected, found))
1061            .with_code(RuntimeErrorCode::TypeError)
1062    }
1063
1064    /// Invalid operation error
1065    pub fn invalid_operation(op: &str, context: &str) -> Self {
1066        Self::new(format!("{} is not valid for {}", op, context))
1067            .with_code(RuntimeErrorCode::InvalidOperation)
1068    }
1069
1070    /// Assertion failed error
1071    pub fn assertion_failed(msg: Option<&str>) -> Self {
1072        let message = match msg {
1073            Some(m) => format!("assertion failed: {}", m),
1074            None => "assertion failed".to_string(),
1075        };
1076        Self::new(message).with_code(RuntimeErrorCode::AssertionFailed)
1077    }
1078}
1079
1080impl fmt::Display for RuntimeError {
1081    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1082        write!(f, "[{}] Runtime error: {}", self.code.code(), self.message)?;
1083        if let Some(span) = self.span {
1084            write!(f, " at {}", span)?;
1085        }
1086        Ok(())
1087    }
1088}
1089
1090/// Control flow signals for return/break/continue
1091#[derive(Debug, Clone)]
1092pub enum ControlFlow {
1093    Return(Value),
1094    Break(Option<Value>),
1095    Continue,
1096}
1097
1098impl From<ControlFlow> for RuntimeError {
1099    fn from(cf: ControlFlow) -> Self {
1100        match cf {
1101            ControlFlow::Return(_) => RuntimeError::new("return outside function")
1102                .with_code(RuntimeErrorCode::ControlFlowError),
1103            ControlFlow::Break(_) => RuntimeError::new("break outside loop")
1104                .with_code(RuntimeErrorCode::ControlFlowError),
1105            ControlFlow::Continue => RuntimeError::new("continue outside loop")
1106                .with_code(RuntimeErrorCode::ControlFlowError),
1107        }
1108    }
1109}
1110
1111/// Result type that can contain control flow
1112pub type EvalResult = Result<Value, EvalError>;
1113
1114/// Error type that includes control flow
1115#[derive(Debug)]
1116pub enum EvalError {
1117    Runtime(RuntimeError),
1118    Control(ControlFlow),
1119}
1120
1121impl From<RuntimeError> for EvalError {
1122    fn from(e: RuntimeError) -> Self {
1123        EvalError::Runtime(e)
1124    }
1125}
1126
1127impl From<ControlFlow> for EvalError {
1128    fn from(cf: ControlFlow) -> Self {
1129        EvalError::Control(cf)
1130    }
1131}
1132
1133impl fmt::Display for EvalError {
1134    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1135        match self {
1136            EvalError::Runtime(e) => write!(f, "{}", e),
1137            EvalError::Control(cf) => write!(f, "Unexpected control flow: {:?}", cf),
1138        }
1139    }
1140}
1141
1142/// Environment for variable bindings
1143#[derive(Clone)]
1144pub struct Environment {
1145    values: HashMap<String, Value>,
1146    parent: Option<Rc<RefCell<Environment>>>,
1147}
1148
1149impl Environment {
1150    pub fn new() -> Self {
1151        Self {
1152            values: HashMap::new(),
1153            parent: None,
1154        }
1155    }
1156
1157    pub fn with_parent(parent: Rc<RefCell<Environment>>) -> Self {
1158        Self {
1159            values: HashMap::new(),
1160            parent: Some(parent),
1161        }
1162    }
1163
1164    pub fn define(&mut self, name: String, value: Value) {
1165        self.values.insert(name, value);
1166    }
1167
1168    pub fn get(&self, name: &str) -> Option<Value> {
1169        if let Some(value) = self.values.get(name) {
1170            Some(value.clone())
1171        } else if let Some(ref parent) = self.parent {
1172            parent.borrow().get(name)
1173        } else {
1174            None
1175        }
1176    }
1177
1178    pub fn set(&mut self, name: &str, value: Value) -> Result<(), RuntimeError> {
1179        if self.values.contains_key(name) {
1180            self.values.insert(name.to_string(), value);
1181            Ok(())
1182        } else if let Some(ref parent) = self.parent {
1183            parent.borrow_mut().set(name, value)
1184        } else {
1185            Err(RuntimeError::undefined_variable(name))
1186        }
1187    }
1188
1189    /// Iterate over all values in this environment (not including parent scopes)
1190    /// Used by autograd and IR export for introspection
1191    pub fn iter_values(&self) -> impl Iterator<Item = (&String, &Value)> {
1192        self.values.iter()
1193    }
1194
1195    /// Collect all values in this environment and parent scopes
1196    pub fn all_values(&self) -> Vec<(String, Value)> {
1197        let mut values: Vec<(String, Value)> = self.values
1198            .iter()
1199            .map(|(k, v)| (k.clone(), v.clone()))
1200            .collect();
1201        if let Some(ref parent) = self.parent {
1202            values.extend(parent.borrow().all_values());
1203        }
1204        values
1205    }
1206}
1207
1208impl Default for Environment {
1209    fn default() -> Self {
1210        Self::new()
1211    }
1212}
1213
1214/// State for tracking linear type consumption (no-cloning theorem enforcement)
1215#[derive(Default)]
1216pub struct LinearTypeState {
1217    /// Linear values that have been consumed (variable name -> true)
1218    pub consumed: RefCell<HashSet<String>>,
1219    /// Variables declared with linear type annotation
1220    pub vars: RefCell<HashSet<String>>,
1221}
1222
1223/// Context for type-directed value construction
1224#[derive(Default)]
1225pub struct TypeConstructionContext {
1226    /// Expected tensor shape from type annotation (e.g., Tensor<[3, 4]>)
1227    pub tensor_shape: RefCell<Option<Vec<i64>>>,
1228    /// Expected struct type with const generics (e.g., Linear<784, 256>)
1229    pub struct_generics: RefCell<Option<(String, Vec<i64>)>>,
1230}
1231
1232/// The Sigil interpreter
1233pub struct Interpreter {
1234    /// Global environment
1235    pub globals: Rc<RefCell<Environment>>,
1236    /// Current environment
1237    pub environment: Rc<RefCell<Environment>>,
1238    /// Type definitions
1239    pub types: HashMap<String, TypeDef>,
1240    /// Variant constructors: qualified_name -> (enum_name, variant_name, arity)
1241    pub variant_constructors: HashMap<String, (String, String, usize)>,
1242    /// Structs with #[derive(Default)]
1243    pub default_structs: HashMap<String, StructDef>,
1244    /// Output buffer (for testing)
1245    pub output: Vec<String>,
1246    /// Return value from the last return statement (control flow)
1247    return_value: Option<Value>,
1248    /// Program arguments (overrides env::args when set)
1249    pub program_args: Option<Vec<String>>,
1250    /// Current module prefix for registering definitions
1251    pub current_module: Option<String>,
1252    /// Current Self type (when inside an impl block)
1253    pub current_self_type: Option<String>,
1254    /// Generic type parameter bindings (e.g., T -> "F16" during dtype_info·<F16>() call)
1255    pub generic_type_bindings: HashMap<String, String>,
1256    /// Current source directory for resolving relative module paths
1257    pub current_source_dir: Option<String>,
1258    /// Loaded crates registry (crate_name -> true if loaded)
1259    pub loaded_crates: HashSet<String>,
1260    /// Crates currently being loaded (for circular dependency detection)
1261    pub loading_crates: HashSet<String>,
1262    /// Project root directory (where Sigil.toml is located)
1263    pub project_root: Option<PathBuf>,
1264    /// Workspace members: crate_name -> relative path from project root
1265    pub workspace_members: HashMap<String, PathBuf>,
1266    /// Types that implement Drop trait - call drop() when they go out of scope
1267    pub drop_types: HashSet<String>,
1268    /// Linear type tracking state (for no-cloning theorem enforcement)
1269    pub linear_state: LinearTypeState,
1270    /// Variables declared as mutable (let mut)
1271    pub mutable_vars: RefCell<HashSet<String>>,
1272    /// Variable type annotations (for generic type checking on Vec<T>, etc.)
1273    pub var_types: RefCell<HashMap<String, (String, Vec<String>)>>,
1274    /// Type-directed construction context (for Tensor<shape>, Linear<N, M>, etc.)
1275    pub type_context: TypeConstructionContext,
1276    // === IR Reflection Registries ===
1277    /// Function definitions for IR export (with span info)
1278    pub ir_functions: RefCell<Vec<Value>>,
1279    /// Trait definitions for IR export (trait_name -> TraitDef)
1280    pub ir_traits: RefCell<Vec<Value>>,
1281    /// Module definitions for IR export
1282    pub ir_modules: RefCell<Vec<Value>>,
1283    /// Constant definitions for IR export
1284    pub ir_constants: RefCell<Vec<Value>>,
1285    /// Impl block definitions for IR export
1286    pub ir_impls: RefCell<Vec<Value>>,
1287    /// Source code for span-to-line conversion
1288    pub source_code: RefCell<String>,
1289    /// User-defined macro registry: name -> (params, body_tokens)
1290    /// params is a Vec<String> of parameter names (e.g., ["n"] for macro foo($n) {...})
1291    /// body_tokens is the raw body string to be parsed and evaluated
1292    /// field_map maps struct field names to param names for named patterns (e.g., { key: $param:expr })
1293    pub user_macros: RefCell<HashMap<String, (Vec<String>, String, HashMap<String, String>)>>,
1294    // === AI IR Export Fields (Phase 8) ===
1295    /// Source text for span-to-line conversion (used by __export_ir)
1296    pub source_text: Option<String>,
1297    /// Function spans for IR export (function_name -> span)
1298    pub function_spans: HashMap<String, crate::span::Span>,
1299    /// Raw trait definitions for IR export
1300    pub trait_defs: Vec<crate::ast::TraitDef>,
1301    /// Raw impl blocks for IR export
1302    pub impl_blocks: Vec<crate::ast::ImplBlock>,
1303    /// Constant definitions for IR export (const_name, span)
1304    pub const_defs: Vec<(String, crate::span::Span)>,
1305    /// Modules in current crate for IR export
1306    pub crate_modules: HashSet<String>,
1307    /// Current crate name for module resolution
1308    pub crate_name: Option<String>,
1309    /// Alias for current crate (e.g., "tome" for tome commands)
1310    pub crate_alias: Option<String>,
1311    /// Maps type name → const generic parameter names
1312    /// e.g., "Shape1" → ["N"], "Shape2" → ["M", "N"]
1313    pub const_generic_params: HashMap<String, Vec<String>>,
1314    /// Deferred associated constants for const-generic impl blocks
1315    /// Maps "TypeName·ConstName" → unevaluated AST expression
1316    pub const_generic_deferred_consts: HashMap<String, crate::ast::Expr>,
1317}
1318
1319/// Type definition for structs/enums
1320#[derive(Clone)]
1321pub enum TypeDef {
1322    Struct(StructDef),
1323    Enum(EnumDef),
1324}
1325
1326impl Interpreter {
1327    pub fn new() -> Self {
1328        let globals = Rc::new(RefCell::new(Environment::new()));
1329        let environment = globals.clone();
1330
1331        let mut interp = Self {
1332            globals: globals.clone(),
1333            environment,
1334            types: HashMap::new(),
1335            variant_constructors: HashMap::new(),
1336            default_structs: HashMap::new(),
1337            return_value: None,
1338            output: Vec::new(),
1339            program_args: None,
1340            current_module: None,
1341            current_self_type: None,
1342            generic_type_bindings: HashMap::new(),
1343            current_source_dir: None,
1344            loaded_crates: HashSet::new(),
1345            loading_crates: HashSet::new(),
1346            project_root: None,
1347            workspace_members: HashMap::new(),
1348            drop_types: HashSet::new(),
1349            linear_state: LinearTypeState::default(),
1350            mutable_vars: RefCell::new(HashSet::new()),
1351            var_types: RefCell::new(HashMap::new()),
1352            type_context: TypeConstructionContext::default(),
1353            ir_functions: RefCell::new(Vec::new()),
1354            ir_traits: RefCell::new(Vec::new()),
1355            ir_modules: RefCell::new(Vec::new()),
1356            ir_constants: RefCell::new(Vec::new()),
1357            ir_impls: RefCell::new(Vec::new()),
1358            source_code: RefCell::new(String::new()),
1359            user_macros: RefCell::new(HashMap::new()),
1360            // Phase 8: AI IR Export fields
1361            source_text: None,
1362            function_spans: HashMap::new(),
1363            trait_defs: Vec::new(),
1364            impl_blocks: Vec::new(),
1365            const_defs: Vec::new(),
1366            crate_modules: HashSet::new(),
1367            crate_name: None,
1368            crate_alias: None,
1369            const_generic_params: HashMap::new(),
1370            const_generic_deferred_consts: HashMap::new(),
1371        };
1372
1373        // Register built-in functions
1374        interp.register_builtins();
1375
1376        interp
1377    }
1378
1379    /// Set program arguments (overrides env::args for the running program)
1380    pub fn set_program_args(&mut self, args: Vec<String>) {
1381        self.program_args = Some(args);
1382    }
1383
1384    /// Set current module for registering definitions (module name, not file stem)
1385    pub fn set_current_module(&mut self, module: Option<String>) {
1386        self.current_module = module;
1387    }
1388
1389    /// Set current source directory for resolving relative module paths
1390    pub fn set_current_source_dir(&mut self, dir: Option<String>) {
1391        self.current_source_dir = dir;
1392    }
1393
1394    /// Set source directory for the current program (for module resolution)
1395    /// This is the directory containing the entry point file
1396    pub fn set_source_dir(&mut self, dir: String) {
1397        self.current_source_dir = Some(dir);
1398    }
1399
1400    /// Set the current crate name (for module prefixing)
1401    pub fn set_crate_name(&mut self, name: String) {
1402        self.crate_name = Some(name);
1403    }
1404
1405    /// Set an alias for the current crate (e.g., "tome" for tome commands)
1406    pub fn set_crate_alias(&mut self, alias: String) {
1407        self.crate_alias = Some(alias);
1408    }
1409
1410    /// Register a module in the current crate for IR export
1411    pub fn register_module(&mut self, name: String) {
1412        self.crate_modules.insert(name);
1413    }
1414
1415    /// Get program arguments (uses overridden args if set, otherwise env::args)
1416    pub fn get_program_args(&self) -> Vec<String> {
1417        self.program_args
1418            .clone()
1419            .unwrap_or_else(|| std::env::args().collect())
1420    }
1421
1422    /// Find and parse Sigil.toml/Grimoire.toml from a source directory, walking up parent directories
1423    /// Looks for a workspace config (one with [workspace] section and members)
1424    pub fn discover_project(&mut self, source_dir: &str) -> Result<(), RuntimeError> {
1425        let mut current = PathBuf::from(source_dir);
1426        // Canonicalize for correct path resolution
1427        if let Ok(canonical) = current.canonicalize() {
1428            current = canonical;
1429        }
1430
1431        // Walk up to find Sigil.toml or Grimoire.toml with [workspace] section
1432        loop {
1433            // Check Sigil.toml variants
1434            for name in &["Sigil.toml", "sigil.toml", "Grimoire.toml", "grimoire.toml"] {
1435                let manifest = current.join(name);
1436                if manifest.exists() {
1437                    if let Ok(result) = self.try_parse_workspace_toml(&manifest) {
1438                        if result {
1439                            return Ok(());
1440                        }
1441                        // Not a workspace config, continue searching
1442                    }
1443                }
1444            }
1445
1446            if !current.pop() {
1447                // No workspace config found
1448                crate::sigil_debug!(
1449                    "DEBUG discover_project: no workspace config found from {}",
1450                    source_dir
1451                );
1452                return Ok(());
1453            }
1454        }
1455    }
1456
1457    /// Try to parse a Sigil.toml as a workspace config. Returns Ok(true) if it's a workspace,
1458    /// Ok(false) if it's a crate-level config, Err if parsing failed.
1459    fn try_parse_workspace_toml(&mut self, path: &PathBuf) -> Result<bool, RuntimeError> {
1460        let content = std::fs::read_to_string(path)
1461            .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
1462
1463        let toml_value: toml::Value = content
1464            .parse()
1465            .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
1466
1467        // Check if this has a [workspace] section with members
1468        if let Some(workspace) = toml_value.get("workspace") {
1469            if workspace
1470                .get("members")
1471                .and_then(|m| m.as_array())
1472                .is_some()
1473            {
1474                // This is a workspace Sigil.toml
1475                return self.parse_sigil_toml(path).map(|_| true);
1476            }
1477        }
1478
1479        // Not a workspace config
1480        crate::sigil_debug!(
1481            "DEBUG try_parse_workspace_toml: {:?} is not a workspace config",
1482            path
1483        );
1484        Ok(false)
1485    }
1486
1487    /// Parse a Sigil.toml file and populate workspace_members
1488    fn parse_sigil_toml(&mut self, path: &PathBuf) -> Result<(), RuntimeError> {
1489        let content = std::fs::read_to_string(path)
1490            .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
1491
1492        let toml_value: toml::Value = content
1493            .parse()
1494            .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
1495
1496        self.project_root = path.parent().map(|p| p.to_path_buf());
1497
1498        // Parse [workspace] members
1499        if let Some(workspace) = toml_value.get("workspace") {
1500            if let Some(members) = workspace.get("members").and_then(|m| m.as_array()) {
1501                for member in members {
1502                    if let Some(member_path) = member.as_str() {
1503                        // Extract crate name from path (e.g., "crates/samael-analysis" -> "samael_analysis")
1504                        let crate_name = std::path::Path::new(member_path)
1505                            .file_name()
1506                            .and_then(|n| n.to_str())
1507                            .map(|n| n.replace("-", "_"))
1508                            .unwrap_or_default();
1509
1510                        if !crate_name.is_empty() {
1511                            crate::sigil_debug!(
1512                                "DEBUG parse_sigil_toml: registered workspace member: {} -> {}",
1513                                &crate_name,
1514                                member_path
1515                            );
1516                            self.workspace_members
1517                                .insert(crate_name, PathBuf::from(member_path));
1518                        }
1519                    }
1520                }
1521            }
1522        }
1523
1524        crate::sigil_debug!(
1525            "DEBUG parse_sigil_toml: loaded {} workspace members from {:?}",
1526            self.workspace_members.len(),
1527            path
1528        );
1529
1530        Ok(())
1531    }
1532
1533    /// Load an external crate by name
1534    pub fn load_crate(&mut self, crate_name: &str) -> Result<bool, RuntimeError> {
1535        // Check if already loaded
1536        if self.loaded_crates.contains(crate_name) {
1537            return Ok(true);
1538        }
1539
1540        // Check for circular dependency
1541        if self.loading_crates.contains(crate_name) {
1542            return Err(RuntimeError::new(format!(
1543                "Circular dependency detected: crate '{}' is already being loaded",
1544                crate_name
1545            )));
1546        }
1547
1548        // Find crate path in workspace members
1549        let crate_path = match self.workspace_members.get(crate_name) {
1550            Some(p) => p.clone(),
1551            None => {
1552                crate::sigil_debug!(
1553                    "DEBUG load_crate: crate '{}' not found in workspace members",
1554                    crate_name
1555                );
1556                return Ok(false);
1557            }
1558        };
1559
1560        let project_root = match &self.project_root {
1561            Some(r) => r.clone(),
1562            None => {
1563                crate::sigil_debug!("DEBUG load_crate: no project root set");
1564                return Ok(false);
1565            }
1566        };
1567
1568        // Build path to lib.sigil
1569        let lib_path = project_root.join(&crate_path).join("src").join("lib.sigil");
1570
1571        if !lib_path.exists() {
1572            crate::sigil_debug!("DEBUG load_crate: lib.sigil not found at {:?}", lib_path);
1573            return Ok(false);
1574        }
1575
1576        // Mark as loading (for circular dependency detection)
1577        self.loading_crates.insert(crate_name.to_string());
1578
1579        crate::sigil_debug!(
1580            "DEBUG load_crate: loading crate '{}' from {:?}",
1581            crate_name,
1582            lib_path
1583        );
1584
1585        // Read and parse the lib.sigil file
1586        let source = std::fs::read_to_string(&lib_path)
1587            .map_err(|e| RuntimeError::new(format!("Failed to read {:?}: {}", lib_path, e)))?;
1588
1589        // Save current state
1590        let prev_module = self.current_module.clone();
1591        let prev_source_dir = self.current_source_dir.clone();
1592
1593        // Set module context to crate name
1594        self.current_module = Some(crate_name.to_string());
1595        self.current_source_dir = lib_path.parent().map(|p| p.to_string_lossy().to_string());
1596
1597        // Parse the source
1598        let mut parser = crate::Parser::new(&source);
1599
1600        match parser.parse_file() {
1601            Ok(parsed_file) => {
1602                // Execute all items to register types and functions
1603                for item in &parsed_file.items {
1604                    if let Err(e) = self.execute_item(&item.node) {
1605                        crate::sigil_warn!("Warning: error loading crate '{}': {}", crate_name, e);
1606                    }
1607                }
1608            }
1609            Err(e) => {
1610                crate::sigil_warn!("Warning: failed to parse crate '{}': {:?}", crate_name, e);
1611            }
1612        }
1613
1614        // Restore previous state
1615        self.current_module = prev_module;
1616        self.current_source_dir = prev_source_dir;
1617
1618        // Mark as loaded and no longer loading
1619        self.loading_crates.remove(crate_name);
1620        self.loaded_crates.insert(crate_name.to_string());
1621
1622        crate::sigil_debug!(
1623            "DEBUG load_crate: successfully loaded crate '{}'",
1624            crate_name
1625        );
1626
1627        Ok(true)
1628    }
1629
1630    fn register_builtins(&mut self) {
1631        // PhantomData - zero-sized type marker
1632        self.globals
1633            .borrow_mut()
1634            .define("PhantomData".to_string(), Value::Null);
1635
1636        // Print function
1637        self.define_builtin("print", None, |interp, args| {
1638            let output: Vec<String> = args.iter().map(|v| format!("{}", v)).collect();
1639            let line = output.join(" ");
1640            println!("{}", line);
1641            interp.output.push(line);
1642            Ok(Value::Null)
1643        });
1644
1645        // Type checking
1646        self.define_builtin("type_of", Some(1), |_, args| {
1647            let type_name = match &args[0] {
1648                Value::Null => "null",
1649                Value::Bool(_) => "bool",
1650                Value::Int(_) => "i64",
1651                Value::Float(_) => "f64",
1652                Value::String(_) => "str",
1653                Value::Char(_) => "char",
1654                Value::Array(_) => "array",
1655                Value::Tuple(_) => "tuple",
1656                Value::Struct { name, .. } => name,
1657                Value::Variant { enum_name, .. } => enum_name,
1658                Value::Function(_) => "fn",
1659                Value::BuiltIn(_) => "builtin",
1660                Value::Ref(_) => "ref",
1661                Value::Infinity => "infinity",
1662                Value::Empty => "empty",
1663                Value::Evidential { .. } => "evidential",
1664                Value::Affective { .. } => "affective",
1665                Value::Map(_) => "map",
1666                Value::Set(_) => "set",
1667                Value::Channel(_) => "channel",
1668                Value::ThreadHandle(_) => "thread",
1669                Value::Actor(_) => "actor",
1670                Value::Future(_) => "future",
1671                Value::VariantConstructor { .. } => "variant_constructor",
1672                Value::DefaultConstructor { .. } => "default_constructor",
1673                Value::Range { .. } => "range",
1674            };
1675            Ok(Value::String(Rc::new(type_name.to_string())))
1676        });
1677
1678        // Array operations
1679        self.define_builtin("len", Some(1), |_, args| match &args[0] {
1680            Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
1681            Value::String(s) => Ok(Value::Int(s.len() as i64)),
1682            Value::Tuple(t) => Ok(Value::Int(t.len() as i64)),
1683            _ => Err(RuntimeError::new("len() requires array, string, or tuple")),
1684        });
1685
1686        self.define_builtin("push", Some(2), |_, args| match &args[0] {
1687            Value::Array(arr) => {
1688                arr.borrow_mut().push(args[1].clone());
1689                Ok(Value::Null)
1690            }
1691            _ => Err(RuntimeError::new("push() requires array")),
1692        });
1693
1694        self.define_builtin("pop", Some(1), |_, args| match &args[0] {
1695            Value::Array(arr) => arr
1696                .borrow_mut()
1697                .pop()
1698                .ok_or_else(|| RuntimeError::new("pop() on empty array")),
1699            _ => Err(RuntimeError::new("pop() requires array")),
1700        });
1701
1702        // Math functions
1703        self.define_builtin("abs", Some(1), |_, args| match &args[0] {
1704            Value::Int(n) => Ok(Value::Int(n.abs())),
1705            Value::Float(n) => Ok(Value::Float(n.abs())),
1706            _ => Err(RuntimeError::new("abs() requires number")),
1707        });
1708
1709        self.define_builtin("sqrt", Some(1), |_, args| match &args[0] {
1710            Value::Int(n) => Ok(Value::Float((*n as f64).sqrt())),
1711            Value::Float(n) => Ok(Value::Float(n.sqrt())),
1712            _ => Err(RuntimeError::new("sqrt() requires number")),
1713        });
1714
1715        self.define_builtin("sin", Some(1), |_, args| match &args[0] {
1716            Value::Int(n) => Ok(Value::Float((*n as f64).sin())),
1717            Value::Float(n) => Ok(Value::Float(n.sin())),
1718            _ => Err(RuntimeError::new("sin() requires number")),
1719        });
1720
1721        self.define_builtin("cos", Some(1), |_, args| match &args[0] {
1722            Value::Int(n) => Ok(Value::Float((*n as f64).cos())),
1723            Value::Float(n) => Ok(Value::Float(n.cos())),
1724            _ => Err(RuntimeError::new("cos() requires number")),
1725        });
1726
1727        // Evidence operations
1728        self.define_builtin("known", Some(1), |_, args| {
1729            Ok(Value::Evidential {
1730                value: Box::new(args[0].clone()),
1731                evidence: Evidence::Known,
1732            })
1733        });
1734
1735        self.define_builtin("uncertain", Some(1), |_, args| {
1736            Ok(Value::Evidential {
1737                value: Box::new(args[0].clone()),
1738                evidence: Evidence::Uncertain,
1739            })
1740        });
1741
1742        self.define_builtin("reported", Some(1), |_, args| {
1743            Ok(Value::Evidential {
1744                value: Box::new(args[0].clone()),
1745                evidence: Evidence::Reported,
1746            })
1747        });
1748
1749        // Box::new - just return the value (Sigil is GC'd)
1750        self.globals.borrow_mut().define(
1751            "Box·new".to_string(),
1752            Value::BuiltIn(Rc::new(BuiltInFn {
1753                name: "Box·new".to_string(),
1754                arity: Some(1),
1755                func: |_, args| Ok(args[0].clone()),
1756            })),
1757        );
1758
1759        // Map::new - create empty map
1760        self.globals.borrow_mut().define(
1761            "Map·new".to_string(),
1762            Value::BuiltIn(Rc::new(BuiltInFn {
1763                name: "Map·new".to_string(),
1764                arity: Some(0),
1765                func: |_, _| Ok(Value::Map(Rc::new(RefCell::new(HashMap::new())))),
1766            })),
1767        );
1768
1769        // Range function
1770        self.define_builtin("range", Some(2), |_, args| {
1771            let start = match &args[0] {
1772                Value::Int(n) => *n,
1773                _ => return Err(RuntimeError::new("range() requires integers")),
1774            };
1775            let end = match &args[1] {
1776                Value::Int(n) => *n,
1777                _ => return Err(RuntimeError::new("range() requires integers")),
1778            };
1779            let values: Vec<Value> = (start..end).map(Value::Int).collect();
1780            Ok(Value::Array(Rc::new(RefCell::new(values))))
1781        });
1782
1783        // ExitCode enum for process exit codes (like Rust's std::process::ExitCode)
1784        self.globals.borrow_mut().define(
1785            "ExitCode·SUCCESS".to_string(),
1786            Value::Variant {
1787                enum_name: "ExitCode".to_string(),
1788                variant_name: "SUCCESS".to_string(),
1789                fields: Some(Rc::new(vec![Value::Int(0)])),
1790            },
1791        );
1792        self.globals.borrow_mut().define(
1793            "ExitCode·FAILURE".to_string(),
1794            Value::Variant {
1795                enum_name: "ExitCode".to_string(),
1796                variant_name: "FAILURE".to_string(),
1797                fields: Some(Rc::new(vec![Value::Int(1)])),
1798            },
1799        );
1800
1801        // PathBuf::from - create a PathBuf from a string path
1802        self.define_builtin("PathBuf·from", Some(1), |_, args| {
1803            // Unwrap Ref types to get the actual value
1804            let arg = match &args[0] {
1805                Value::Ref(r) => r.borrow().clone(),
1806                other => other.clone(),
1807            };
1808            let path = match &arg {
1809                Value::String(s2) => s2.as_str().to_string(),
1810                _ => return Err(RuntimeError::new("PathBuf::from expects a string")),
1811            };
1812            // Represent PathBuf as a struct with a path field
1813            let mut fields = HashMap::new();
1814            fields.insert("path".to_string(), Value::String(Rc::new(path)));
1815            Ok(Value::Struct {
1816                name: "PathBuf".to_string(),
1817                fields: Rc::new(RefCell::new(fields)),
1818            })
1819        });
1820
1821        // Path::new - create a Path from a string (similar to PathBuf for our purposes)
1822        self.define_builtin("Path·new", Some(1), |_, args| {
1823            // Unwrap Ref types to get the actual value
1824            let arg = match &args[0] {
1825                Value::Ref(r) => r.borrow().clone(),
1826                other => other.clone(),
1827            };
1828            let path = match &arg {
1829                Value::String(s2) => s2.as_str().to_string(),
1830                _ => return Err(RuntimeError::new("Path::new expects a string")),
1831            };
1832            let mut fields = HashMap::new();
1833            fields.insert("path".to_string(), Value::String(Rc::new(path)));
1834            Ok(Value::Struct {
1835                name: "Path".to_string(),
1836                fields: Rc::new(RefCell::new(fields)),
1837            })
1838        });
1839
1840        // std::fs::read_to_string - read file contents as a string
1841        self.define_builtin("std·fs·read_to_string", Some(1), |interp, args| {
1842            // Recursively unwrap Ref types to get the actual value
1843            fn unwrap_refs(v: &Value) -> Value {
1844                match v {
1845                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1846                    other => other.clone(),
1847                }
1848            }
1849            let arg = unwrap_refs(&args[0]);
1850            crate::sigil_debug!("DEBUG read_to_string: arg = {:?}", arg);
1851            // Also dump the environment to see what 'path' is bound to
1852            crate::sigil_debug!(
1853                "DEBUG read_to_string: env has path = {:?}",
1854                interp.environment.borrow().get("path")
1855            );
1856            let path = match &arg {
1857                Value::String(s) => s.to_string(),
1858                // Handle PathBuf or Path structs
1859                Value::Struct { name, fields, .. } => {
1860                    crate::sigil_debug!("DEBUG read_to_string: struct name = {}", name);
1861                    fields
1862                        .borrow()
1863                        .get("path")
1864                        .and_then(|v| {
1865                            if let Value::String(s) = v {
1866                                Some(s.to_string())
1867                            } else {
1868                                None
1869                            }
1870                        })
1871                        .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1872                }
1873                // Handle Option::Some(String)
1874                Value::Variant {
1875                    enum_name,
1876                    variant_name,
1877                    fields,
1878                } if enum_name == "Option" && variant_name == "Some" => {
1879                    if let Some(fields) = fields {
1880                        if let Some(Value::String(s)) = fields.first() {
1881                            s.to_string()
1882                        } else {
1883                            return Err(RuntimeError::new(
1884                                "read_to_string: Option::Some does not contain a string",
1885                            ));
1886                        }
1887                    } else {
1888                        return Err(RuntimeError::new(
1889                            "read_to_string: Option::Some has no fields",
1890                        ));
1891                    }
1892                }
1893                _ => {
1894                    return Err(RuntimeError::new(&format!(
1895                        "read_to_string expects a path string or PathBuf, got {:?}",
1896                        arg
1897                    )))
1898                }
1899            };
1900            match std::fs::read_to_string(&path) {
1901                Ok(content) => Ok(Value::Variant {
1902                    enum_name: "Result".to_string(),
1903                    variant_name: "Ok".to_string(),
1904                    fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1905                }),
1906                Err(e) => Ok(Value::Variant {
1907                    enum_name: "Result".to_string(),
1908                    variant_name: "Err".to_string(),
1909                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1910                }),
1911            }
1912        });
1913
1914        // fs::read_to_string - alias without std prefix
1915        self.define_builtin("fs·read_to_string", Some(1), |_, args| {
1916            let arg = match &args[0] {
1917                Value::Ref(r) => r.borrow().clone(),
1918                other => other.clone(),
1919            };
1920            let path = match &arg {
1921                Value::String(s) => s.to_string(),
1922                Value::Struct { fields, .. } => fields
1923                    .borrow()
1924                    .get("path")
1925                    .and_then(|v| {
1926                        if let Value::String(s) = v {
1927                            Some(s.to_string())
1928                        } else {
1929                            None
1930                        }
1931                    })
1932                    .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?,
1933                _ => {
1934                    return Err(RuntimeError::new(
1935                        "read_to_string expects a path string or PathBuf",
1936                    ))
1937                }
1938            };
1939            match std::fs::read_to_string(&path) {
1940                Ok(content) => Ok(Value::Variant {
1941                    enum_name: "Result".to_string(),
1942                    variant_name: "Ok".to_string(),
1943                    fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1944                }),
1945                Err(e) => Ok(Value::Variant {
1946                    enum_name: "Result".to_string(),
1947                    variant_name: "Err".to_string(),
1948                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1949                }),
1950            }
1951        });
1952
1953        // std::fs::read_dir - read directory entries
1954        self.define_builtin("std·fs·read_dir", Some(1), |_, args| {
1955            fn unwrap_refs(v: &Value) -> Value {
1956                match v {
1957                    Value::Ref(r) => unwrap_refs(&r.borrow()),
1958                    other => other.clone(),
1959                }
1960            }
1961            let arg = unwrap_refs(&args[0]);
1962            let path = match &arg {
1963                Value::String(s) => s.to_string(),
1964                Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => fields
1965                    .borrow()
1966                    .get("path")
1967                    .and_then(|v| {
1968                        if let Value::String(s) = v {
1969                            Some(s.to_string())
1970                        } else {
1971                            None
1972                        }
1973                    })
1974                    .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?,
1975                _ => {
1976                    return Err(RuntimeError::new(&format!(
1977                        "read_dir expects a path, got {:?}",
1978                        arg
1979                    )))
1980                }
1981            };
1982            match std::fs::read_dir(&path) {
1983                Ok(entries) => {
1984                    // Collect entries into a Vec of DirEntry structs wrapped in Result::Ok
1985                    let entry_values: Vec<Value> = entries
1986                        .filter_map(|e| e.ok())
1987                        .map(|e| {
1988                            let entry_path = e.path().to_string_lossy().to_string();
1989                            let mut fields = HashMap::new();
1990                            fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
1991                            // Each entry is wrapped in Result::Ok
1992                            Value::Variant {
1993                                enum_name: "Result".to_string(),
1994                                variant_name: "Ok".to_string(),
1995                                fields: Some(Rc::new(vec![Value::Struct {
1996                                    name: "DirEntry".to_string(),
1997                                    fields: Rc::new(RefCell::new(fields)),
1998                                }])),
1999                            }
2000                        })
2001                        .collect();
2002                    // The overall result is Ok(iterator/array)
2003                    Ok(Value::Variant {
2004                        enum_name: "Result".to_string(),
2005                        variant_name: "Ok".to_string(),
2006                        fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(
2007                            entry_values,
2008                        )))])),
2009                    })
2010                }
2011                Err(e) => Ok(Value::Variant {
2012                    enum_name: "Result".to_string(),
2013                    variant_name: "Err".to_string(),
2014                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
2015                }),
2016            }
2017        });
2018
2019        // fs::read_dir - alias without std prefix
2020        self.define_builtin("fs·read_dir", Some(1), |_, args| {
2021            fn unwrap_refs(v: &Value) -> Value {
2022                match v {
2023                    Value::Ref(r) => unwrap_refs(&r.borrow()),
2024                    other => other.clone(),
2025                }
2026            }
2027            let arg = unwrap_refs(&args[0]);
2028            let path = match &arg {
2029                Value::String(s) => s.to_string(),
2030                Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => fields
2031                    .borrow()
2032                    .get("path")
2033                    .and_then(|v| {
2034                        if let Value::String(s) = v {
2035                            Some(s.to_string())
2036                        } else {
2037                            None
2038                        }
2039                    })
2040                    .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?,
2041                _ => {
2042                    return Err(RuntimeError::new(&format!(
2043                        "read_dir expects a path, got {:?}",
2044                        arg
2045                    )))
2046                }
2047            };
2048            match std::fs::read_dir(&path) {
2049                Ok(entries) => {
2050                    let entry_values: Vec<Value> = entries
2051                        .filter_map(|e| e.ok())
2052                        .map(|e| {
2053                            let entry_path = e.path().to_string_lossy().to_string();
2054                            let mut fields = HashMap::new();
2055                            fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
2056                            Value::Variant {
2057                                enum_name: "Result".to_string(),
2058                                variant_name: "Ok".to_string(),
2059                                fields: Some(Rc::new(vec![Value::Struct {
2060                                    name: "DirEntry".to_string(),
2061                                    fields: Rc::new(RefCell::new(fields)),
2062                                }])),
2063                            }
2064                        })
2065                        .collect();
2066                    Ok(Value::Variant {
2067                        enum_name: "Result".to_string(),
2068                        variant_name: "Ok".to_string(),
2069                        fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(
2070                            entry_values,
2071                        )))])),
2072                    })
2073                }
2074                Err(e) => Ok(Value::Variant {
2075                    enum_name: "Result".to_string(),
2076                    variant_name: "Err".to_string(),
2077                    fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
2078                }),
2079            }
2080        });
2081
2082        // std::env::var - get environment variable
2083        self.define_builtin("std·env·var", Some(1), |_, args| {
2084            fn unwrap_refs(v: &Value) -> Value {
2085                match v {
2086                    Value::Ref(r) => unwrap_refs(&r.borrow()),
2087                    other => other.clone(),
2088                }
2089            }
2090            let arg = unwrap_refs(&args[0]);
2091            let var_name = match &arg {
2092                Value::String(s) => s.to_string(),
2093                _ => return Err(RuntimeError::new("env::var expects a string")),
2094            };
2095            match std::env::var(&var_name) {
2096                Ok(value) => Ok(Value::Variant {
2097                    enum_name: "Result".to_string(),
2098                    variant_name: "Ok".to_string(),
2099                    fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
2100                }),
2101                Err(_) => Ok(Value::Variant {
2102                    enum_name: "Result".to_string(),
2103                    variant_name: "Err".to_string(),
2104                    fields: Some(Rc::new(vec![Value::String(Rc::new(
2105                        "Environment variable not found".to_string(),
2106                    ))])),
2107                }),
2108            }
2109        });
2110
2111        // env::var - alias without std prefix
2112        self.define_builtin("env·var", Some(1), |_, args| {
2113            fn unwrap_refs(v: &Value) -> Value {
2114                match v {
2115                    Value::Ref(r) => unwrap_refs(&r.borrow()),
2116                    other => other.clone(),
2117                }
2118            }
2119            let arg = unwrap_refs(&args[0]);
2120            let var_name = match &arg {
2121                Value::String(s) => s.to_string(),
2122                _ => return Err(RuntimeError::new("env::var expects a string")),
2123            };
2124            match std::env::var(&var_name) {
2125                Ok(value) => Ok(Value::Variant {
2126                    enum_name: "Result".to_string(),
2127                    variant_name: "Ok".to_string(),
2128                    fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
2129                }),
2130                Err(_) => Ok(Value::Variant {
2131                    enum_name: "Result".to_string(),
2132                    variant_name: "Err".to_string(),
2133                    fields: Some(Rc::new(vec![Value::String(Rc::new(
2134                        "Environment variable not found".to_string(),
2135                    ))])),
2136                }),
2137            }
2138        });
2139
2140        // std::env::args - get command line arguments
2141        // This is a special function that returns an iterator/array of strings
2142        self.define_builtin("std·env·args", Some(0), |interp, _| {
2143            let args = interp.get_program_args();
2144            let arg_values: Vec<Value> = args
2145                .iter()
2146                .map(|s| Value::String(Rc::new(s.clone())))
2147                .collect();
2148            Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
2149        });
2150
2151        // env::args - alias without std prefix
2152        self.define_builtin("env·args", Some(0), |interp, _| {
2153            let args = interp.get_program_args();
2154            let arg_values: Vec<Value> = args
2155                .iter()
2156                .map(|s| Value::String(Rc::new(s.clone())))
2157                .collect();
2158            Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
2159        });
2160
2161        // ============================================================
2162        // Filesystem built-ins for scanner (underscore naming)
2163        // ============================================================
2164
2165        // fs_read - read entire file as string
2166        self.define_builtin("fs_read", Some(1), |_, args| {
2167            let path = match &args[0] {
2168                Value::String(s) => s.to_string(),
2169                _ => return Err(RuntimeError::new("fs_read requires a string path")),
2170            };
2171            match std::fs::read_to_string(&path) {
2172                Ok(content) => Ok(Value::String(Rc::new(content))),
2173                Err(e) => {
2174                    crate::sigil_debug!("DEBUG fs_read error for '{}': {}", path, e);
2175                    Ok(Value::Null)
2176                }
2177            }
2178        });
2179
2180        // fs_list - list directory contents as array of strings
2181        self.define_builtin("fs_list", Some(1), |_, args| {
2182            let path = match &args[0] {
2183                Value::String(s) => s.to_string(),
2184                _ => return Err(RuntimeError::new("fs_list requires a string path")),
2185            };
2186            match std::fs::read_dir(&path) {
2187                Ok(entries) => {
2188                    let files: Vec<Value> = entries
2189                        .filter_map(|e| e.ok())
2190                        .map(|e| {
2191                            Value::String(Rc::new(e.file_name().to_string_lossy().to_string()))
2192                        })
2193                        .collect();
2194                    Ok(Value::Array(Rc::new(RefCell::new(files))))
2195                }
2196                Err(e) => {
2197                    crate::sigil_debug!("DEBUG fs_list error for '{}': {}", path, e);
2198                    Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))))
2199                }
2200            }
2201        });
2202
2203        // fs_is_dir - check if path is a directory
2204        self.define_builtin("fs_is_dir", Some(1), |_, args| {
2205            let path = match &args[0] {
2206                Value::String(s) => s.to_string(),
2207                _ => return Err(RuntimeError::new("fs_is_dir requires a string path")),
2208            };
2209            Ok(Value::Bool(std::path::Path::new(&path).is_dir()))
2210        });
2211
2212        // fs_is_file - check if path is a file
2213        self.define_builtin("fs_is_file", Some(1), |_, args| {
2214            let path = match &args[0] {
2215                Value::String(s) => s.to_string(),
2216                _ => return Err(RuntimeError::new("fs_is_file requires a string path")),
2217            };
2218            Ok(Value::Bool(std::path::Path::new(&path).is_file()))
2219        });
2220
2221        // fs_exists - check if path exists
2222        self.define_builtin("fs_exists", Some(1), |_, args| {
2223            let path = match &args[0] {
2224                Value::String(s) => s.to_string(),
2225                _ => return Err(RuntimeError::new("fs_exists requires a string path")),
2226            };
2227            Ok(Value::Bool(std::path::Path::new(&path).exists()))
2228        });
2229
2230        // path_extension - get file extension
2231        self.define_builtin("path_extension", Some(1), |_, args| {
2232            let path = match &args[0] {
2233                Value::String(s) => s.to_string(),
2234                _ => return Err(RuntimeError::new("path_extension requires a string path")),
2235            };
2236            let ext = std::path::Path::new(&path)
2237                .extension()
2238                .and_then(|e| e.to_str())
2239                .map(|s| s.to_string());
2240            match ext {
2241                Some(e) => Ok(Value::String(Rc::new(e))),
2242                None => Ok(Value::Null),
2243            }
2244        });
2245
2246        // path_join - join path components
2247        self.define_builtin("path_join", Some(2), |_, args| {
2248            let base = match &args[0] {
2249                Value::String(s) => s.to_string(),
2250                _ => return Err(RuntimeError::new("path_join requires string paths")),
2251            };
2252            let part = match &args[1] {
2253                Value::String(s) => s.to_string(),
2254                _ => return Err(RuntimeError::new("path_join requires string paths")),
2255            };
2256            let joined = std::path::Path::new(&base).join(&part);
2257            Ok(Value::String(Rc::new(joined.to_string_lossy().to_string())))
2258        });
2259
2260        // path_parent - get parent directory
2261        self.define_builtin("path_parent", Some(1), |_, args| {
2262            let path = match &args[0] {
2263                Value::String(s) => s.to_string(),
2264                _ => return Err(RuntimeError::new("path_parent requires a string path")),
2265            };
2266            match std::path::Path::new(&path).parent() {
2267                Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
2268                None => Ok(Value::Null),
2269            }
2270        });
2271
2272        // path_file_name - get file name without directory
2273        self.define_builtin("path_file_name", Some(1), |_, args| {
2274            let path = match &args[0] {
2275                Value::String(s) => s.to_string(),
2276                _ => return Err(RuntimeError::new("path_file_name requires a string path")),
2277            };
2278            match std::path::Path::new(&path).file_name() {
2279                Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
2280                None => Ok(Value::Null),
2281            }
2282        });
2283
2284        // ============================================================
2285        // Tree-sitter parsing built-ins (native-only: requires tree-sitter C FFI)
2286        // ============================================================
2287
2288        #[cfg(feature = "native")]
2289        {
2290        // TreeSitterParser::new - create a tree-sitter parser for a language
2291        self.define_builtin("TreeSitterParser·new", Some(1), |_, args| {
2292            use crate::tree_sitter_support::{TSLanguage, TSParser};
2293
2294            // Get the language from the argument
2295            let lang_str = match &args[0] {
2296                Value::String(s) => s.to_string(),
2297                Value::Variant {
2298                    enum_name,
2299                    variant_name,
2300                    ..
2301                } => {
2302                    // Handle Language::Rust style enums
2303                    format!("{}::{}", enum_name, variant_name)
2304                }
2305                other => format!("{:?}", other),
2306            };
2307
2308            // Try to create the parser
2309            let language = match TSLanguage::from_str(&lang_str) {
2310                Some(lang) => lang,
2311                None => {
2312                    return Ok(Value::Variant {
2313                        enum_name: "Result".to_string(),
2314                        variant_name: "Err".to_string(),
2315                        fields: Some(Rc::new(vec![Value::Struct {
2316                            name: "ParseError".to_string(),
2317                            fields: Rc::new(RefCell::new({
2318                                let mut f = HashMap::new();
2319                                f.insert(
2320                                    "kind".to_string(),
2321                                    Value::String(Rc::new("ParserNotFound".to_string())),
2322                                );
2323                                f.insert(
2324                                    "message".to_string(),
2325                                    Value::String(Rc::new(format!(
2326                                        "Unsupported language: {}",
2327                                        lang_str
2328                                    ))),
2329                                );
2330                                f
2331                            })),
2332                        }])),
2333                    });
2334                }
2335            };
2336
2337            // Create the parser and store the language
2338            match TSParser::new(language) {
2339                Ok(_) => {
2340                    // Return a TreeSitterParser struct
2341                    let mut fields = HashMap::new();
2342                    fields.insert("language".to_string(), Value::String(Rc::new(lang_str)));
2343                    fields.insert(
2344                        "_ts_language".to_string(),
2345                        Value::String(Rc::new(format!("{:?}", language))),
2346                    );
2347
2348                    Ok(Value::Variant {
2349                        enum_name: "Result".to_string(),
2350                        variant_name: "Ok".to_string(),
2351                        fields: Some(Rc::new(vec![Value::Struct {
2352                            name: "TreeSitterParser".to_string(),
2353                            fields: Rc::new(RefCell::new(fields)),
2354                        }])),
2355                    })
2356                }
2357                Err(e) => Ok(Value::Variant {
2358                    enum_name: "Result".to_string(),
2359                    variant_name: "Err".to_string(),
2360                    fields: Some(Rc::new(vec![Value::Struct {
2361                        name: "ParseError".to_string(),
2362                        fields: Rc::new(RefCell::new({
2363                            let mut f = HashMap::new();
2364                            f.insert(
2365                                "kind".to_string(),
2366                                Value::String(Rc::new("ParserNotFound".to_string())),
2367                            );
2368                            f.insert("message".to_string(), Value::String(Rc::new(e)));
2369                            f
2370                        })),
2371                    }])),
2372                }),
2373            }
2374        });
2375
2376        // tree_sitter_parse - parse source code with tree-sitter
2377        self.define_builtin("tree_sitter_parse", Some(2), |_, args| {
2378            use crate::tree_sitter_support::{node_to_value, parse_source};
2379
2380            // First arg is the language string, second is the source code
2381            let lang_str = match &args[0] {
2382                Value::String(s) => s.to_string(),
2383                Value::Variant {
2384                    enum_name,
2385                    variant_name,
2386                    ..
2387                } => {
2388                    format!("{}::{}", enum_name, variant_name)
2389                }
2390                other => format!("{:?}", other),
2391            };
2392
2393            let source = match &args[1] {
2394                Value::String(s) => s.to_string(),
2395                _ => {
2396                    return Err(RuntimeError::new(
2397                        "tree_sitter_parse expects source code string as second argument",
2398                    ))
2399                }
2400            };
2401
2402            // Parse the source
2403            match parse_source(&lang_str, &source) {
2404                Ok(tree) => {
2405                    // Convert to SyntaxNode value
2406                    let root = tree.root_node();
2407                    let root_fields = node_to_value(&root);
2408
2409                    // Create TSTree struct
2410                    let mut tree_fields = HashMap::new();
2411                    tree_fields.insert(
2412                        "root".to_string(),
2413                        Value::Struct {
2414                            name: "SyntaxNode".to_string(),
2415                            fields: Rc::new(RefCell::new(root_fields)),
2416                        },
2417                    );
2418                    tree_fields.insert("source".to_string(), Value::String(Rc::new(source)));
2419
2420                    Ok(Value::Variant {
2421                        enum_name: "Result".to_string(),
2422                        variant_name: "Ok".to_string(),
2423                        fields: Some(Rc::new(vec![Value::Struct {
2424                            name: "TSTree".to_string(),
2425                            fields: Rc::new(RefCell::new(tree_fields)),
2426                        }])),
2427                    })
2428                }
2429                Err(e) => Ok(Value::Variant {
2430                    enum_name: "Result".to_string(),
2431                    variant_name: "Err".to_string(),
2432                    fields: Some(Rc::new(vec![Value::Struct {
2433                        name: "ParseError".to_string(),
2434                        fields: Rc::new(RefCell::new({
2435                            let mut f = HashMap::new();
2436                            f.insert(
2437                                "kind".to_string(),
2438                                Value::String(Rc::new("SyntaxError".to_string())),
2439                            );
2440                            f.insert("message".to_string(), Value::String(Rc::new(e)));
2441                            f
2442                        })),
2443                    }])),
2444                }),
2445            }
2446        });
2447
2448        // tree_sitter_supported_languages - get list of supported languages
2449        self.define_builtin("tree_sitter_supported_languages", Some(0), |_, _| {
2450            use crate::tree_sitter_support::supported_languages;
2451
2452            let languages: Vec<Value> = supported_languages()
2453                .iter()
2454                .map(|s| Value::String(Rc::new(s.to_string())))
2455                .collect();
2456
2457            Ok(Value::Array(Rc::new(RefCell::new(languages))))
2458        });
2459        } // end #[cfg(feature = "native")] tree-sitter block
2460
2461        // tree_sitter_node_text - extract text from a syntax node using the source
2462        self.define_builtin("tree_sitter_node_text", Some(2), |_, args| {
2463            // First arg is the node (with start_byte and end_byte), second is the source
2464            let (start_byte, end_byte) = match &args[0] {
2465                Value::Struct { fields, .. } => {
2466                    let fields = fields.borrow();
2467                    let start = match fields.get("start_byte") {
2468                        Some(Value::Int(n)) => *n as usize,
2469                        _ => return Err(RuntimeError::new("Node missing start_byte field")),
2470                    };
2471                    let end = match fields.get("end_byte") {
2472                        Some(Value::Int(n)) => *n as usize,
2473                        _ => return Err(RuntimeError::new("Node missing end_byte field")),
2474                    };
2475                    (start, end)
2476                }
2477                _ => {
2478                    return Err(RuntimeError::new(
2479                        "tree_sitter_node_text expects a SyntaxNode struct",
2480                    ))
2481                }
2482            };
2483
2484            let source = match &args[1] {
2485                Value::String(s) => s.to_string(),
2486                _ => {
2487                    return Err(RuntimeError::new(
2488                        "tree_sitter_node_text expects source string as second argument",
2489                    ))
2490                }
2491            };
2492
2493            if end_byte <= source.len() && start_byte <= end_byte {
2494                Ok(Value::String(Rc::new(
2495                    source[start_byte..end_byte].to_string(),
2496                )))
2497            } else {
2498                Err(RuntimeError::new("Byte range out of bounds"))
2499            }
2500        });
2501
2502        // ============================================================
2503        // Sigil self-parsing built-ins (Option D - eat your own dogfood)
2504        // ============================================================
2505
2506        // sigil_parse - parse Sigil source code and return AST as inspectable Value
2507        self.define_builtin("sigil_parse", Some(1), |_, args| {
2508            let source = match &args[0] {
2509                Value::String(s) => s.to_string(),
2510                Value::Ref(r) => {
2511                    if let Value::String(s) = &*r.borrow() {
2512                        s.to_string()
2513                    } else {
2514                        return Err(RuntimeError::new("sigil_parse expects string source"));
2515                    }
2516                }
2517                _ => return Err(RuntimeError::new("sigil_parse expects string source")),
2518            };
2519
2520            // Parse using Sigil's own parser
2521            let mut parser = crate::Parser::new(&source);
2522            match parser.parse_file() {
2523                Ok(source_file) => {
2524                    // Convert AST to inspectable Value
2525                    Ok(ast_to_value_source_file(&source_file))
2526                }
2527                Err(e) => {
2528                    // Return error as Result::Err variant
2529                    let mut fields = HashMap::new();
2530                    fields.insert(
2531                        "message".to_string(),
2532                        Value::String(Rc::new(format!("{}", e))),
2533                    );
2534                    Ok(Value::Variant {
2535                        enum_name: "Result".to_string(),
2536                        variant_name: "Err".to_string(),
2537                        fields: Some(Rc::new(vec![Value::Struct {
2538                            name: "ParseError".to_string(),
2539                            fields: Rc::new(RefCell::new(fields)),
2540                        }])),
2541                    })
2542                }
2543            }
2544        });
2545
2546        // sigil_parse_file - read and parse a Sigil file
2547        self.define_builtin("sigil_parse_file", Some(1), |_, args| {
2548            let path = match &args[0] {
2549                Value::String(s) => s.to_string(),
2550                Value::Ref(r) => {
2551                    if let Value::String(s) = &*r.borrow() {
2552                        s.to_string()
2553                    } else {
2554                        return Err(RuntimeError::new("sigil_parse_file expects string path"));
2555                    }
2556                }
2557                _ => return Err(RuntimeError::new("sigil_parse_file expects string path")),
2558            };
2559
2560            // Read file
2561            let source = match std::fs::read_to_string(&path) {
2562                Ok(s) => s,
2563                Err(e) => {
2564                    let mut fields = HashMap::new();
2565                    fields.insert(
2566                        "message".to_string(),
2567                        Value::String(Rc::new(format!("IO error: {}", e))),
2568                    );
2569                    return Ok(Value::Variant {
2570                        enum_name: "Result".to_string(),
2571                        variant_name: "Err".to_string(),
2572                        fields: Some(Rc::new(vec![Value::Struct {
2573                            name: "ParseError".to_string(),
2574                            fields: Rc::new(RefCell::new(fields)),
2575                        }])),
2576                    });
2577                }
2578            };
2579
2580            // Parse using Sigil's own parser
2581            let mut parser = crate::Parser::new(&source);
2582            match parser.parse_file() {
2583                Ok(source_file) => Ok(ast_to_value_source_file(&source_file)),
2584                Err(e) => {
2585                    let mut fields = HashMap::new();
2586                    fields.insert(
2587                        "message".to_string(),
2588                        Value::String(Rc::new(format!("{}", e))),
2589                    );
2590                    Ok(Value::Variant {
2591                        enum_name: "Result".to_string(),
2592                        variant_name: "Err".to_string(),
2593                        fields: Some(Rc::new(vec![Value::Struct {
2594                            name: "ParseError".to_string(),
2595                            fields: Rc::new(RefCell::new(fields)),
2596                        }])),
2597                    })
2598                }
2599            }
2600        });
2601
2602        // Rc::new(value) - Reference counted smart pointer (simplified)
2603        let rc_new = Value::BuiltIn(Rc::new(BuiltInFn {
2604            name: "Rc·new".to_string(),
2605            arity: Some(1),
2606            func: |_, args| {
2607                let mut fields = HashMap::new();
2608                fields.insert("_value".to_string(), args[0].clone());
2609                Ok(Value::Struct {
2610                    name: "Rc".to_string(),
2611                    fields: std::rc::Rc::new(RefCell::new(fields)),
2612                })
2613            },
2614        }));
2615        self.globals
2616            .borrow_mut()
2617            .define("Rc·new".to_string(), rc_new);
2618
2619        // Cell::new(value) - Interior mutability
2620        let cell_new = Value::BuiltIn(Rc::new(BuiltInFn {
2621            name: "Cell·new".to_string(),
2622            arity: Some(1),
2623            func: |_, args| {
2624                let mut fields = HashMap::new();
2625                fields.insert("_value".to_string(), args[0].clone());
2626                Ok(Value::Struct {
2627                    name: "Cell".to_string(),
2628                    fields: std::rc::Rc::new(RefCell::new(fields)),
2629                })
2630            },
2631        }));
2632        self.globals
2633            .borrow_mut()
2634            .define("Cell·new".to_string(), cell_new);
2635    }
2636
2637    fn define_builtin(
2638        &mut self,
2639        name: &str,
2640        arity: Option<usize>,
2641        func: fn(&mut Interpreter, Vec<Value>) -> Result<Value, RuntimeError>,
2642    ) {
2643        let builtin = Value::BuiltIn(Rc::new(BuiltInFn {
2644            name: name.to_string(),
2645            arity,
2646            func,
2647        }));
2648        self.globals.borrow_mut().define(name.to_string(), builtin);
2649    }
2650
2651    /// Set the source code for span-to-line conversion
2652    pub fn set_source_code(&mut self, source: String) {
2653        *self.source_code.borrow_mut() = source;
2654    }
2655
2656    /// Convert a byte offset to a line number (1-indexed)
2657    fn offset_to_line(&self, offset: usize) -> i64 {
2658        let source = self.source_code.borrow();
2659        if source.is_empty() || offset >= source.len() {
2660            return 1; // Default if no source or out of bounds
2661        }
2662        // Snap to nearest char boundary to avoid panicking on multi-byte UTF-8
2663        let mut safe_offset = offset;
2664        while safe_offset > 0 && !source.is_char_boundary(safe_offset) {
2665            safe_offset -= 1;
2666        }
2667        // Count newlines up to offset
2668        let line_count = source[..safe_offset].matches('\n').count() + 1;
2669        line_count as i64
2670    }
2671
2672    /// Execute a source file
2673    pub fn execute(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
2674        let mut result = Value::Null;
2675
2676        for item in &file.items {
2677            result = self.execute_item(&item.node)?;
2678        }
2679
2680        // Look for main function and execute it (only if it takes no args)
2681        let main_fn = self.globals.borrow().get("main").and_then(|v| {
2682            if let Value::Function(f) = v {
2683                Some(f.clone())
2684            } else {
2685                None
2686            }
2687        });
2688        if let Some(f) = main_fn {
2689            // Only auto-call main if it takes no arguments
2690            // If main expects args, caller should call it explicitly via call_function_by_name
2691            if f.params.is_empty() {
2692                result = self.call_function(&f, vec![])?;
2693            }
2694        }
2695
2696        Ok(result)
2697    }
2698
2699    /// Execute a file but only register definitions, don't auto-call main.
2700    /// Use this when loading files as part of a multi-file workspace.
2701    pub fn execute_definitions(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
2702        let mut result = Value::Null;
2703
2704        for item in &file.items {
2705            result = self.execute_item(&item.node)?;
2706        }
2707
2708        Ok(result)
2709    }
2710
2711    fn execute_item(&mut self, item: &Item) -> Result<Value, RuntimeError> {
2712        match item {
2713            Item::Function(func) => {
2714                let fn_value = self.create_function(func)?;
2715                let fn_name = func.name.name.clone();
2716
2717                // Register with both simple name and module-qualified name
2718                self.globals
2719                    .borrow_mut()
2720                    .define(fn_name.clone(), fn_value.clone());
2721
2722                // Also register with module prefix if we're in a module context
2723                if let Some(ref module) = self.current_module {
2724                    let qualified_name = format!("{}·{}", module, fn_name);
2725                    self.globals.borrow_mut().define(qualified_name, fn_value);
2726                }
2727
2728                // Track function span for IR export (raw span for __export_ir)
2729                self.function_spans.insert(fn_name.clone(), func.name.span.clone());
2730
2731                // Track function for IR export with span info
2732                let span = &func.name.span;
2733                let start_line = self.offset_to_line(span.start);
2734                let end_line = self.offset_to_line(span.end);
2735
2736                let mut start_fields = HashMap::new();
2737                start_fields.insert("line".to_string(), Value::Int(start_line));
2738                start_fields.insert("column".to_string(), Value::Int(1));
2739                let start = Value::Struct {
2740                    name: "SpanPos".to_string(),
2741                    fields: Rc::new(RefCell::new(start_fields)),
2742                };
2743
2744                let mut end_fields = HashMap::new();
2745                end_fields.insert("line".to_string(), Value::Int(end_line));
2746                end_fields.insert("column".to_string(), Value::Int(1));
2747                let end = Value::Struct {
2748                    name: "SpanPos".to_string(),
2749                    fields: Rc::new(RefCell::new(end_fields)),
2750                };
2751
2752                let mut span_fields = HashMap::new();
2753                span_fields.insert("start".to_string(), start);
2754                span_fields.insert("end".to_string(), end);
2755                let span_value = Value::Struct {
2756                    name: "Span".to_string(),
2757                    fields: Rc::new(RefCell::new(span_fields)),
2758                };
2759
2760                let mut func_fields = HashMap::new();
2761                func_fields.insert("name".to_string(), Value::String(Rc::new(fn_name)));
2762                func_fields.insert("span".to_string(), span_value);
2763                self.ir_functions.borrow_mut().push(Value::Struct {
2764                    name: "FunctionIR".to_string(),
2765                    fields: Rc::new(RefCell::new(func_fields)),
2766                });
2767
2768                Ok(Value::Null)
2769            }
2770            Item::Struct(s) => {
2771                // Register with simple name
2772                self.types
2773                    .insert(s.name.name.clone(), TypeDef::Struct(s.clone()));
2774
2775                // Also register with module-qualified name if in a module context
2776                if let Some(ref module) = self.current_module {
2777                    let qualified_name = format!("{}·{}", module, s.name.name);
2778                    self.types
2779                        .insert(qualified_name, TypeDef::Struct(s.clone()));
2780                }
2781
2782                // For unit structs, register the struct name as a value (zero-sized type)
2783                if matches!(&s.fields, crate::ast::StructFields::Unit) {
2784                    let unit_value = Value::Struct {
2785                        name: s.name.name.clone(),
2786                        fields: Rc::new(RefCell::new(HashMap::new())),
2787                    };
2788                    self.globals
2789                        .borrow_mut()
2790                        .define(s.name.name.clone(), unit_value.clone());
2791
2792                    // Also register with module-qualified name
2793                    if let Some(ref module) = self.current_module {
2794                        let qualified_name = format!("{}·{}", module, s.name.name);
2795                        self.globals.borrow_mut().define(qualified_name, unit_value);
2796                    }
2797                }
2798
2799                // Check for #[derive(Default)] attribute and store for later lookup
2800                let has_default = s
2801                    .attrs
2802                    .derives
2803                    .iter()
2804                    .any(|d| matches!(d, DeriveTrait::Default));
2805                if has_default {
2806                    self.default_structs.insert(s.name.name.clone(), s.clone());
2807                    if let Some(ref module) = self.current_module {
2808                        let qualified_name = format!("{}·{}", module, s.name.name);
2809                        self.default_structs.insert(qualified_name, s.clone());
2810                    }
2811                }
2812
2813                Ok(Value::Null)
2814            }
2815            Item::Enum(e) => {
2816                // Register with simple name
2817                self.types
2818                    .insert(e.name.name.clone(), TypeDef::Enum(e.clone()));
2819
2820                // Also register with module-qualified name
2821                if let Some(ref module) = self.current_module {
2822                    let qualified_name = format!("{}·{}", module, e.name.name);
2823                    self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
2824                }
2825
2826                // Register variant constructors as EnumName·VariantName
2827                // Store them in a lookup table that the variant_constructor builtin can use
2828                let enum_name = e.name.name.clone();
2829                for variant in &e.variants {
2830                    let variant_name = variant.name.name.clone();
2831                    let qualified_name = format!("{}·{}", enum_name, variant_name);
2832
2833                    let arity = match &variant.fields {
2834                        crate::ast::StructFields::Unit => 0,
2835                        crate::ast::StructFields::Tuple(types) => types.len(),
2836                        crate::ast::StructFields::Named(fields) => fields.len(),
2837                    };
2838
2839                    // Store variant info for later lookup
2840                    self.variant_constructors.insert(
2841                        qualified_name.clone(),
2842                        (enum_name.clone(), variant_name.clone(), arity),
2843                    );
2844                }
2845                Ok(Value::Null)
2846            }
2847            Item::Const(c) => {
2848                // Track constant for IR export (raw name + span for __export_ir)
2849                self.const_defs.push((c.name.name.clone(), c.name.span.clone()));
2850
2851                let value = self.evaluate(&c.value)?;
2852                self.globals.borrow_mut().define(c.name.name.clone(), value.clone());
2853
2854                // Track constant for IR export
2855                let mut const_fields = HashMap::new();
2856                const_fields.insert("name".to_string(), Value::String(Rc::new(c.name.name.clone())));
2857                const_fields.insert("value".to_string(), value);
2858                self.ir_constants.borrow_mut().push(Value::Struct {
2859                    name: "ConstDef".to_string(),
2860                    fields: Rc::new(RefCell::new(const_fields)),
2861                });
2862
2863                Ok(Value::Null)
2864            }
2865            Item::Static(s) => {
2866                let value = self.evaluate(&s.value)?;
2867                self.globals.borrow_mut().define(s.name.name.clone(), value);
2868                // If static is mutable (static Δ), track it as a mutable variable
2869                if s.mutable {
2870                    self.mutable_vars.borrow_mut().insert(s.name.name.clone());
2871                }
2872                Ok(Value::Null)
2873            }
2874            Item::ExternBlock(extern_block) => {
2875                // Register extern functions as builtins
2876                for item in &extern_block.items {
2877                    if let ExternItem::Function(func) = item {
2878                        let name = func.name.name.clone();
2879                        // Register emulated FFI functions
2880                        match name.as_str() {
2881                            "sigil_read_file" => {
2882                                self.define_builtin("sigil_read_file", Some(2), |_, args| {
2883                                    // args[0] = path pointer (we'll use string), args[1] = len
2884                                    let path = match &args[0] {
2885                                        Value::String(s) => (**s).clone(),
2886                                        _ => {
2887                                            return Err(RuntimeError::new(
2888                                                "sigil_read_file expects string path",
2889                                            ))
2890                                        }
2891                                    };
2892                                    match std::fs::read_to_string(&path) {
2893                                        Ok(content) => {
2894                                            // Store content in a global for sigil_file_len to access
2895                                            Ok(Value::String(Rc::new(content)))
2896                                        }
2897                                        Err(_) => Ok(Value::Null),
2898                                    }
2899                                });
2900                            }
2901                            "sigil_file_len" => {
2902                                self.define_builtin("sigil_file_len", Some(0), |_, _| {
2903                                    // This is a placeholder - in real usage, would track last read
2904                                    Ok(Value::Int(0))
2905                                });
2906                            }
2907                            "sigil_write_file" => {
2908                                self.define_builtin("sigil_write_file", Some(4), |_, args| {
2909                                    let path = match &args[0] {
2910                                        Value::String(s) => (**s).clone(),
2911                                        _ => {
2912                                            return Err(RuntimeError::new(
2913                                                "sigil_write_file expects string path",
2914                                            ))
2915                                        }
2916                                    };
2917                                    let content = match &args[2] {
2918                                        Value::String(s) => (**s).clone(),
2919                                        _ => {
2920                                            return Err(RuntimeError::new(
2921                                                "sigil_write_file expects string content",
2922                                            ))
2923                                        }
2924                                    };
2925                                    match std::fs::write(&path, &content) {
2926                                        Ok(_) => Ok(Value::Bool(true)),
2927                                        Err(_) => Ok(Value::Bool(false)),
2928                                    }
2929                                });
2930                            }
2931                            "write" => {
2932                                self.define_builtin("write", Some(3), |_, args| {
2933                                    // write(fd, buf, count)
2934                                    let fd = match &args[0] {
2935                                        Value::Int(n) => *n,
2936                                        _ => 1,
2937                                    };
2938                                    let content = match &args[1] {
2939                                        Value::String(s) => (**s).clone(),
2940                                        _ => format!("{}", args[1]),
2941                                    };
2942                                    if fd == 1 {
2943                                        print!("{}", content);
2944                                    } else if fd == 2 {
2945                                        eprint!("{}", content);
2946                                    }
2947                                    Ok(Value::Int(content.len() as i64))
2948                                });
2949                            }
2950                            _ => {
2951                                // Unknown extern function - register a no-op
2952                            }
2953                        }
2954                    }
2955                }
2956                Ok(Value::Null)
2957            }
2958            Item::Impl(impl_block) => {
2959                // Track impl block for IR export (raw AST for __export_ir)
2960                self.impl_blocks.push(impl_block.clone());
2961
2962                // Extract type name from self_ty
2963                let type_name = match &impl_block.self_ty {
2964                    TypeExpr::Path(path) => path
2965                        .segments
2966                        .iter()
2967                        .map(|s| s.ident.name.as_str())
2968                        .collect::<Vec<_>>()
2969                        .join("·"),
2970                    _ => return Ok(Value::Null), // Can't handle complex types
2971                };
2972
2973                // Extract const generic param names from impl block generics
2974                let const_params: Vec<String> = impl_block.generics.as_ref()
2975                    .map(|g| g.params.iter().filter_map(|p| match p {
2976                        crate::ast::GenericParam::Const { name, .. } => Some(name.name.clone()),
2977                        _ => None,
2978                    }).collect())
2979                    .unwrap_or_default();
2980
2981                if !const_params.is_empty() {
2982                    self.const_generic_params.insert(type_name.clone(), const_params.clone());
2983                }
2984
2985                // Check if this is `impl Drop for X` - register for automatic drop calls
2986                if let Some(trait_path) = &impl_block.trait_ {
2987                    let trait_name = trait_path
2988                        .segments
2989                        .iter()
2990                        .map(|s| s.ident.name.as_str())
2991                        .collect::<Vec<_>>()
2992                        .join("·");
2993                    if trait_name == "Drop" {
2994                        self.drop_types.insert(type_name.clone());
2995                    }
2996                }
2997
2998                // Register each method/const with qualified name TypeName·method
2999                for impl_item in &impl_block.items {
3000                    match impl_item {
3001                        ImplItem::Function(func) => {
3002                            let fn_value = self.create_function(func)?;
3003                            let qualified_name = format!("{}·{}", type_name, func.name.name);
3004                            // Debug: track Lexer method registration
3005                            if type_name == "Lexer" && func.name.name.contains("keyword") {
3006                                crate::sigil_debug!("DEBUG registering: {}", qualified_name);
3007                            }
3008                            self.globals
3009                                .borrow_mut()
3010                                .define(qualified_name.clone(), fn_value.clone());
3011
3012                            // Also register with module prefix if in a module context
3013                            if let Some(ref module) = self.current_module {
3014                                let fully_qualified = format!("{}·{}", module, qualified_name);
3015                                self.globals.borrow_mut().define(fully_qualified, fn_value);
3016                            }
3017                        }
3018                        ImplItem::Const(c) => {
3019                            if const_params.is_empty() {
3020                                // No const generics: evaluate normally
3021                                let value = self.evaluate(&c.value)?;
3022                                let qualified_name = format!("{}·{}", type_name, c.name.name);
3023                                self.globals.borrow_mut().define(qualified_name.clone(), value.clone());
3024
3025                                if let Some(ref module) = self.current_module {
3026                                    let fully_qualified = format!("{}·{}", module, qualified_name);
3027                                    self.globals.borrow_mut().define(fully_qualified, value);
3028                                }
3029                            } else {
3030                                // Try to evaluate; defer if it references a const param
3031                                match self.evaluate(&c.value) {
3032                                    Ok(value) => {
3033                                        let qualified_name = format!("{}·{}", type_name, c.name.name);
3034                                        self.globals.borrow_mut().define(qualified_name.clone(), value.clone());
3035
3036                                        if let Some(ref module) = self.current_module {
3037                                            let fully_qualified = format!("{}·{}", module, qualified_name);
3038                                            self.globals.borrow_mut().define(fully_qualified, value);
3039                                        }
3040                                    }
3041                                    Err(e) if const_params.iter().any(|p| e.message.contains(p)) => {
3042                                        // Deferred: depends on const generic params
3043                                        let key = format!("{}·{}", type_name, c.name.name);
3044                                        self.const_generic_deferred_consts.insert(key, c.value.clone());
3045                                    }
3046                                    Err(e) => return Err(e),
3047                                }
3048                            }
3049                        }
3050                        _ => {}
3051                    }
3052                }
3053
3054                // If this is a trait impl, register default methods from the trait
3055                // that aren't overridden by the impl block (e.g., `size()` from `DType`)
3056                if let Some(trait_path) = &impl_block.trait_ {
3057                    let t_name = trait_path
3058                        .segments
3059                        .iter()
3060                        .map(|s| s.ident.name.as_str())
3061                        .collect::<Vec<_>>()
3062                        .join("·");
3063
3064                    // Collect names of methods explicitly provided in the impl block
3065                    let impl_method_names: std::collections::HashSet<String> = impl_block
3066                        .items
3067                        .iter()
3068                        .filter_map(|item| match item {
3069                            ImplItem::Function(f) => Some(f.name.name.clone()),
3070                            _ => None,
3071                        })
3072                        .collect();
3073
3074                    // Find the trait definition and register unoverridden default methods
3075                    if let Some(trait_def) = self.trait_defs.iter().find(|td| td.name.name == t_name).cloned() {
3076                        for trait_item in &trait_def.items {
3077                            if let crate::ast::TraitItem::Function(f) = trait_item {
3078                                if f.body.is_some() && !impl_method_names.contains(&f.name.name) {
3079                                    let fn_value = self.create_function(f)?;
3080                                    let qualified_name = format!("{}·{}", type_name, f.name.name);
3081                                    self.globals
3082                                        .borrow_mut()
3083                                        .define(qualified_name.clone(), fn_value.clone());
3084
3085                                    if let Some(ref module) = self.current_module {
3086                                        let fully_qualified = format!("{}·{}", module, qualified_name);
3087                                        self.globals.borrow_mut().define(fully_qualified, fn_value);
3088                                    }
3089                                }
3090                            }
3091                        }
3092                    }
3093                }
3094
3095                // Track impl for IR export
3096                let trait_name = impl_block.trait_.as_ref().map(|t| {
3097                    t.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("·")
3098                });
3099                let mut impl_fields = HashMap::new();
3100                impl_fields.insert("type_name".to_string(), Value::String(Rc::new(type_name.clone())));
3101                impl_fields.insert("trait_name".to_string(), match trait_name {
3102                    Some(t) => Value::String(Rc::new(t)),
3103                    None => Value::Null,
3104                });
3105                impl_fields.insert("method_count".to_string(), Value::Int(impl_block.items.len() as i64));
3106                self.ir_impls.borrow_mut().push(Value::Struct {
3107                    name: "ImplDef".to_string(),
3108                    fields: Rc::new(RefCell::new(impl_fields)),
3109                });
3110
3111                Ok(Value::Null)
3112            }
3113            Item::Module(module) => {
3114                // Handle module definitions
3115                let module_name = &module.name.name;
3116
3117                // Track module for IR export
3118                self.crate_modules.insert(module_name.clone());
3119
3120                if let Some(items) = &module.items {
3121                    // Inline module: mod foo { ... }
3122                    // Register items with qualified names: module_name·item_name
3123                    for item in items {
3124                        match &item.node {
3125                            Item::Const(c) => {
3126                                let value = self.evaluate(&c.value)?;
3127                                let qualified_name = format!("{}·{}", module_name, c.name.name);
3128                                self.globals.borrow_mut().define(qualified_name, value);
3129                            }
3130                            Item::Static(s) => {
3131                                let value = self.evaluate(&s.value)?;
3132                                let qualified_name = format!("{}·{}", module_name, s.name.name);
3133                                self.globals.borrow_mut().define(qualified_name, value);
3134                            }
3135                            Item::Function(func) => {
3136                                let fn_value = self.create_function(func)?;
3137                                let qualified_name = format!("{}·{}", module_name, func.name.name);
3138                                self.globals.borrow_mut().define(qualified_name, fn_value);
3139                            }
3140                            Item::Struct(s) => {
3141                                let qualified_name = format!("{}·{}", module_name, s.name.name);
3142                                self.types
3143                                    .insert(qualified_name, TypeDef::Struct(s.clone()));
3144                            }
3145                            Item::Enum(e) => {
3146                                let qualified_name = format!("{}·{}", module_name, e.name.name);
3147                                self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
3148                            }
3149                            Item::Impl(impl_block) => {
3150                                // Handle impl blocks inside modules
3151                                // Extract the type name and qualify it with the module name
3152                                let type_name = match &impl_block.self_ty {
3153                                    TypeExpr::Path(path) => path
3154                                        .segments
3155                                        .iter()
3156                                        .map(|s| s.ident.name.as_str())
3157                                        .collect::<Vec<_>>()
3158                                        .join("·"),
3159                                    _ => continue, // Skip complex types
3160                                };
3161
3162                                // Check if type name is already qualified (has ·)
3163                                // If not, prefix with module name
3164                                let qualified_type = if type_name.contains("·") {
3165                                    type_name.clone()
3166                                } else {
3167                                    format!("{}·{}", module_name, type_name)
3168                                };
3169
3170                                // Check for Drop trait impl
3171                                if let Some(trait_path) = &impl_block.trait_ {
3172                                    let trait_name = trait_path
3173                                        .segments
3174                                        .iter()
3175                                        .map(|s| s.ident.name.as_str())
3176                                        .collect::<Vec<_>>()
3177                                        .join("·");
3178                                    if trait_name == "Drop" {
3179                                        self.drop_types.insert(qualified_type.clone());
3180                                    }
3181                                }
3182
3183                                // Register each method with module-qualified name
3184                                for impl_item in &impl_block.items {
3185                                    if let ImplItem::Function(func) = impl_item {
3186                                        let fn_value = self.create_function(func)?;
3187                                        // Register as module·Type·method
3188                                        let qualified_name =
3189                                            format!("{}·{}", qualified_type, func.name.name);
3190                                        self.globals
3191                                            .borrow_mut()
3192                                            .define(qualified_name.clone(), fn_value.clone());
3193
3194                                        // Also register without module prefix for local access
3195                                        // (Type·method for when type is accessed without module prefix)
3196                                        let local_name =
3197                                            format!("{}·{}", type_name, func.name.name);
3198                                        if local_name != qualified_name {
3199                                            self.globals
3200                                                .borrow_mut()
3201                                                .define(local_name, fn_value.clone());
3202                                        }
3203                                    }
3204                                }
3205                            }
3206                            Item::Module(nested_mod) => {
3207                                // Handle nested modules recursively
3208                                let nested_name =
3209                                    format!("{}·{}", module_name, nested_mod.name.name);
3210
3211                                // Track nested module for IR export
3212                                self.crate_modules.insert(nested_name.clone());
3213
3214                                if let Some(nested_items) = &nested_mod.items {
3215                                    // Create a temporary module item with qualified name
3216                                    // and process it recursively
3217                                    let prev_module = self.current_module.clone();
3218                                    self.current_module = Some(nested_name.clone());
3219                                    for nested_item in nested_items {
3220                                        if let Err(e) = self.execute_item(&nested_item.node) {
3221                                            crate::sigil_warn!(
3222                                                "Warning: error in nested module {}: {}",
3223                                                nested_name,
3224                                                e
3225                                            );
3226                                        }
3227                                    }
3228                                    self.current_module = prev_module;
3229                                }
3230                            }
3231                            _ => {} // Skip other nested items for now
3232                        }
3233                    }
3234                } else {
3235                    // External module: mod foo; - try to load foo.sigil from same directory
3236                    if let Some(ref source_dir) = self.current_source_dir {
3237                        let module_path =
3238                            std::path::Path::new(source_dir).join(format!("{}.sigil", module_name));
3239
3240                        if module_path.exists() {
3241                            crate::sigil_debug!(
3242                                "DEBUG Loading external module: {}",
3243                                module_path.display()
3244                            );
3245
3246                            match std::fs::read_to_string(&module_path) {
3247                                Ok(source) => {
3248                                    // Parse the module file
3249                                    let mut parser = crate::Parser::new(&source);
3250                                    match parser.parse_file() {
3251                                        Ok(parsed_file) => {
3252                                            // Save current module context
3253                                            let prev_module = self.current_module.clone();
3254
3255                                            // Set module context for registering definitions
3256                                            self.current_module = Some(module_name.clone());
3257
3258                                            // Execute module definitions
3259                                            for item in &parsed_file.items {
3260                                                if let Err(e) = self.execute_item(&item.node) {
3261                                                    crate::sigil_warn!(
3262                                                        "Warning: error in module {}: {}",
3263                                                        module_name,
3264                                                        e
3265                                                    );
3266                                                }
3267                                            }
3268
3269                                            // Restore previous module context
3270                                            self.current_module = prev_module;
3271                                        }
3272                                        Err(e) => {
3273                                            crate::sigil_warn!(
3274                                                "Warning: failed to parse module {}: {:?}",
3275                                                module_name,
3276                                                e
3277                                            );
3278                                        }
3279                                    }
3280                                }
3281                                Err(e) => {
3282                                    crate::sigil_warn!(
3283                                        "Warning: failed to read module file {}: {}",
3284                                        module_path.display(),
3285                                        e
3286                                    );
3287                                }
3288                            }
3289                        } else {
3290                            crate::sigil_debug!(
3291                                "DEBUG Module file not found: {} (source_dir={})",
3292                                module_path.display(),
3293                                source_dir
3294                            );
3295                        }
3296                    } else {
3297                        crate::sigil_debug!(
3298                            "DEBUG No source_dir set, cannot load external module: {}",
3299                            module_name
3300                        );
3301                    }
3302                }
3303
3304                // Track module for IR export
3305                let mut module_fields = HashMap::new();
3306                module_fields.insert("name".to_string(), Value::String(Rc::new(module_name.clone())));
3307                module_fields.insert("is_inline".to_string(), Value::Bool(module.items.is_some()));
3308                self.ir_modules.borrow_mut().push(Value::Struct {
3309                    name: "ModuleDef".to_string(),
3310                    fields: Rc::new(RefCell::new(module_fields)),
3311                });
3312
3313                Ok(Value::Null)
3314            }
3315            Item::Use(use_decl) => {
3316                // Process use declarations to create type/function aliases
3317                self.process_use_tree(&use_decl.tree, &[])?;
3318                Ok(Value::Null)
3319            }
3320            Item::Trait(trait_def) => {
3321                // Track trait for IR export (raw AST for __export_ir)
3322                self.trait_defs.push(trait_def.clone());
3323
3324                // Also track as Value for legacy ir_traits
3325                let method_names: Vec<Value> = trait_def.items.iter().filter_map(|item| {
3326                    match item {
3327                        crate::ast::TraitItem::Function(f) => Some(Value::String(Rc::new(f.name.name.clone()))),
3328                        _ => None,
3329                    }
3330                }).collect();
3331
3332                let mut trait_fields = HashMap::new();
3333                trait_fields.insert("name".to_string(), Value::String(Rc::new(trait_def.name.name.clone())));
3334                trait_fields.insert("method_count".to_string(), Value::Int(trait_def.items.len() as i64));
3335                trait_fields.insert("methods".to_string(), Value::Array(Rc::new(RefCell::new(method_names))));
3336                self.ir_traits.borrow_mut().push(Value::Struct {
3337                    name: "TraitDef".to_string(),
3338                    fields: Rc::new(RefCell::new(trait_fields)),
3339                });
3340
3341                Ok(Value::Null)
3342            }
3343            Item::Macro(m) => {
3344                // Parse macro definition and register in user_macros
3345                // Format: "($param1, $param2) { body }" or "{ body }" for parameterless macros
3346                // Also supports rune-style: "{ (...) => { body } }" or "{ ({ key: $val:expr }) => { body } }"
3347                let rules = m.rules.trim();
3348
3349                // Helper: strip outer braces if present
3350                let inner = if rules.starts_with('{') && rules.ends_with('}') {
3351                    rules[1..rules.len() - 1].trim()
3352                } else {
3353                    rules
3354                };
3355
3356                // Check for rune-style pattern with => separator
3357                // Look for ") =>" which indicates rune-style pattern matching
3358                let (params, body, field_map) = if let Some(arrow_pos) = inner.find("=>") {
3359                    // Check if there's a pattern before =>
3360                    let pattern_part = inner[..arrow_pos].trim();
3361                    let body_part = inner[arrow_pos + 2..].trim();
3362
3363                    // Extract params from pattern: ($n:expr) → ["n"]
3364                    // Pattern can be (), ($n:expr), ({ key: $val:expr, ... })
3365                    let mut field_map: HashMap<String, String> = HashMap::new();
3366                    let params = if pattern_part.starts_with('(') {
3367                        let inner_pat = if pattern_part.ends_with(')') {
3368                            &pattern_part[1..pattern_part.len()-1]
3369                        } else {
3370                            &pattern_part[1..]
3371                        };
3372                        // Find $param patterns (possibly with :expr/:ty suffixes)
3373                        let mut extracted = Vec::new();
3374                        let mut i = 0;
3375                        let chars: Vec<char> = inner_pat.chars().collect();
3376                        while i < chars.len() {
3377                            if chars[i] == '$' {
3378                                let dollar_pos = i;
3379                                i += 1;
3380                                // Collect param name until : or , or ) or space or }
3381                                let mut name = String::new();
3382                                while i < chars.len() && chars[i].is_alphanumeric() || (i < chars.len() && chars[i] == '_') {
3383                                    name.push(chars[i]);
3384                                    i += 1;
3385                                }
3386                                // Skip :expr, :ty, etc.
3387                                if i < chars.len() && chars[i] == ':' {
3388                                    while i < chars.len() && !matches!(chars[i], ',' | ')' | '}') {
3389                                        i += 1;
3390                                    }
3391                                }
3392                                if !name.is_empty() {
3393                                    // Look backwards from $ for a field name: "field_name: $param"
3394                                    // Skip whitespace, then expect ':', then skip whitespace, then read field name
3395                                    let mut j = dollar_pos;
3396                                    // Skip whitespace before $
3397                                    while j > 0 && chars[j - 1] == ' ' {
3398                                        j -= 1;
3399                                    }
3400                                    // Check for colon
3401                                    if j > 0 && chars[j - 1] == ':' {
3402                                        j -= 1;
3403                                        // Skip whitespace before colon
3404                                        while j > 0 && chars[j - 1] == ' ' {
3405                                            j -= 1;
3406                                        }
3407                                        // Read field name backwards
3408                                        let field_end = j;
3409                                        while j > 0 && (chars[j - 1].is_alphanumeric() || chars[j - 1] == '_') {
3410                                            j -= 1;
3411                                        }
3412                                        if field_end > j {
3413                                            let field_name: String = chars[j..field_end].iter().collect();
3414                                            field_map.insert(field_name, name.clone());
3415                                        }
3416                                    }
3417                                    extracted.push(name);
3418                                }
3419                            } else {
3420                                i += 1;
3421                            }
3422                        }
3423                        extracted
3424                    } else {
3425                        Vec::new()
3426                    };
3427
3428                    // Extract body: strip outer braces if present
3429                    let body = if body_part.starts_with('{') && body_part.ends_with('}') {
3430                        body_part[1..body_part.len()-1].trim().to_string()
3431                    } else {
3432                        body_part.to_string()
3433                    };
3434
3435                    (params, body, field_map)
3436                } else if inner.starts_with('(') {
3437                    // Original format: ($param1, $param2) { body }
3438                    let mut depth = 0;
3439                    let mut paren_end = 0;
3440                    for (i, c) in inner.chars().enumerate() {
3441                        match c {
3442                            '(' => depth += 1,
3443                            ')' => {
3444                                depth -= 1;
3445                                if depth == 0 {
3446                                    paren_end = i;
3447                                    break;
3448                                }
3449                            }
3450                            _ => {}
3451                        }
3452                    }
3453
3454                    let param_str = &inner[1..paren_end];
3455                    let params: Vec<String> = param_str
3456                        .split(',')
3457                        .map(|p| p.trim().trim_start_matches('$').to_string())
3458                        .filter(|p| !p.is_empty())
3459                        .collect();
3460
3461                    let rest = inner[paren_end + 1..].trim();
3462                    let body = if rest.starts_with('{') && rest.ends_with('}') {
3463                        rest[1..rest.len() - 1].trim().to_string()
3464                    } else {
3465                        rest.to_string()
3466                    };
3467
3468                    (params, body, HashMap::new())
3469                } else {
3470                    // Fallback: treat entire inner as body
3471                    (Vec::new(), inner.to_string(), HashMap::new())
3472                };
3473
3474                // Register the macro
3475                self.user_macros
3476                    .borrow_mut()
3477                    .insert(m.name.name.clone(), (params, body, field_map));
3478
3479                Ok(Value::Null)
3480            }
3481            _ => Ok(Value::Null), // Skip other items for now
3482        }
3483    }
3484
3485    /// Process a use tree to create type and function aliases
3486    fn process_use_tree(
3487        &mut self,
3488        tree: &crate::ast::UseTree,
3489        prefix: &[String],
3490    ) -> Result<(), RuntimeError> {
3491        use crate::ast::UseTree;
3492        match tree {
3493            UseTree::Path {
3494                prefix: path_prefix,
3495                suffix,
3496            } => {
3497                // Build path: prefix + this segment
3498                let mut new_prefix = prefix.to_vec();
3499                new_prefix.push(path_prefix.name.clone());
3500                self.process_use_tree(suffix, &new_prefix)
3501            }
3502            UseTree::Name(name) => {
3503                // use foo::bar::Baz -> import Baz from foo·bar·Baz
3504                let mut path = prefix.to_vec();
3505                path.push(name.name.clone());
3506                let qualified = path.join("·");
3507                let simple_name = name.name.clone();
3508
3509                // If the type/function isn't found, try loading the crate first
3510                // The crate name is the first segment of the path
3511                if !prefix.is_empty() {
3512                    let crate_name = &prefix[0];
3513
3514                    // Handle "crate", "tome", or "above" as self-reference to current crate
3515                    // e.g., "invoke crate·output·Output" loads from ./output.sigil
3516                    if crate_name == "crate" || crate_name == "tome" || crate_name == "above" {
3517                        if !self.types.contains_key(&qualified)
3518                            && self.globals.borrow().get(&qualified).is_none()
3519                        {
3520                            // Load from current source directory
3521                            if let Some(source_dir) = &self.current_source_dir.clone() {
3522                                // Determine module name:
3523                                // - invoke tome·module·Item -> prefix=["tome","module"], name=Item -> module_name = prefix[1]
3524                                // - invoke tome·module -> prefix=["tome"], name=module -> module_name = name (simple_name)
3525                                let module_name = if prefix.len() >= 2 {
3526                                    prefix[1].clone()
3527                                } else {
3528                                    // `invoke tome·analyze;` case: prefix=["tome"], simple_name="analyze"
3529                                    simple_name.clone()
3530                                };
3531                                let module_file = format!("{}/{}.sigil", source_dir, module_name);
3532                                crate::sigil_debug!(
3533                                    "DEBUG process_use_tree: loading tome module '{}' from {}",
3534                                    module_name,
3535                                    module_file
3536                                );
3537                                // Skip if already loaded (prevent infinite recursion)
3538                                if self.loaded_crates.contains(&module_file) {
3539                                    // Already loaded, skip
3540                                } else if std::path::Path::new(&module_file).exists() {
3541                                    // Mark as loaded before processing (handle circular deps)
3542                                    self.loaded_crates.insert(module_file.clone());
3543
3544                                    // Read and parse the module file
3545                                    if let Ok(source) = std::fs::read_to_string(&module_file) {
3546                                        // Save current module context
3547                                        let prev_module = self.current_module.clone();
3548
3549                                        // Set module context for the tome module
3550                                        // This ensures impl methods are registered correctly
3551                                        self.current_module = Some(module_name.clone());
3552
3553                                        let mut parser = crate::Parser::new(&source);
3554                                        if let Ok(parsed_file) = parser.parse_file() {
3555                                            for item in &parsed_file.items {
3556                                                let _ = self.execute_item(&item.node);
3557                                            }
3558                                        }
3559
3560                                        // Restore previous module context
3561                                        self.current_module = prev_module;
3562                                    }
3563                                }
3564                            }
3565                        }
3566                    } else if !self.types.contains_key(&qualified)
3567                        && self.globals.borrow().get(&qualified).is_none()
3568                        && !self.loaded_crates.contains(crate_name)
3569                    {
3570                        // Try to load the crate
3571                        if let Err(e) = self.load_crate(crate_name) {
3572                            crate::sigil_debug!(
3573                                "DEBUG process_use_tree: failed to load crate '{}': {}",
3574                                crate_name,
3575                                e
3576                            );
3577                        }
3578                    }
3579                }
3580
3581                // Create alias: simple_name -> qualified
3582                // For types: if foo·bar·Baz exists in types, also register as Baz
3583                // Special handling for "crate·"/"tome·" self-reference: look up just the final name
3584                let lookup_name = if !prefix.is_empty()
3585                    && (prefix[0] == "crate" || prefix[0] == "tome" || prefix[0] == "above")
3586                {
3587                    // For tome·output·Output, look up just "Output"
3588                    simple_name.clone()
3589                } else {
3590                    qualified.clone()
3591                };
3592
3593                if let Some(type_def) = self.types.get(&lookup_name).cloned() {
3594                    if lookup_name != simple_name {
3595                        self.types.insert(simple_name.clone(), type_def.clone());
3596                    }
3597                    // Also register with the qualified name for consistency
3598                    self.types.insert(qualified.clone(), type_def);
3599                }
3600                // For functions: if foo·bar·Baz exists in globals, also register as Baz
3601                let func = self.globals.borrow().get(&lookup_name).map(|v| v.clone());
3602                if let Some(val) = func {
3603                    self.globals
3604                        .borrow_mut()
3605                        .define(simple_name.clone(), val.clone());
3606                    if lookup_name != qualified {
3607                        self.globals.borrow_mut().define(qualified.clone(), val);
3608                    }
3609                }
3610
3611                // Also import impl methods for this type
3612                // e.g., when importing samael_analysis::AnalysisConfig,
3613                // also import samael_analysis·AnalysisConfig·default as AnalysisConfig·default
3614                let method_prefix = format!("{}·", qualified);
3615                let matching_methods: Vec<(String, Value)> = {
3616                    let globals = self.globals.borrow();
3617                    globals
3618                        .values
3619                        .iter()
3620                        .filter(|(k, _)| k.starts_with(&method_prefix))
3621                        .map(|(k, v)| {
3622                            // samael_analysis·AnalysisConfig·default -> AnalysisConfig·default
3623                            let method_suffix = k.strip_prefix(&method_prefix).unwrap();
3624                            let new_name = format!("{}·{}", simple_name, method_suffix);
3625                            (new_name, v.clone())
3626                        })
3627                        .collect()
3628                };
3629                for (name, val) in matching_methods {
3630                    self.globals.borrow_mut().define(name, val);
3631                }
3632                Ok(())
3633            }
3634            UseTree::Rename { name, alias } => {
3635                // use foo::bar::Baz as Qux
3636                let mut path = prefix.to_vec();
3637                path.push(name.name.clone());
3638                let qualified = path.join("·");
3639                let alias_name = alias.name.clone();
3640
3641                if let Some(type_def) = self.types.get(&qualified).cloned() {
3642                    self.types.insert(alias_name.clone(), type_def);
3643                }
3644                let func = self.globals.borrow().get(&qualified).map(|v| v.clone());
3645                if let Some(val) = func {
3646                    self.globals.borrow_mut().define(alias_name, val);
3647                }
3648                Ok(())
3649            }
3650            UseTree::Glob => {
3651                // use foo::bar::* - import all from foo·bar
3652                let path_prefix = prefix.join("·");
3653                // Find all types starting with this prefix
3654                let matching_types: Vec<(String, TypeDef)> = self
3655                    .types
3656                    .iter()
3657                    .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
3658                    .map(|(k, v)| {
3659                        let suffix = k
3660                            .strip_prefix(&path_prefix)
3661                            .unwrap()
3662                            .trim_start_matches('·');
3663                        (suffix.to_string(), v.clone())
3664                    })
3665                    .filter(|(k, _)| !k.contains('·')) // Only immediate children
3666                    .collect();
3667                for (name, def) in matching_types {
3668                    self.types.insert(name, def);
3669                }
3670                // Similar for functions
3671                let matching_funcs: Vec<(String, Value)> = {
3672                    let globals = self.globals.borrow();
3673                    globals
3674                        .values
3675                        .iter()
3676                        .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
3677                        .map(|(k, v)| {
3678                            let suffix = k
3679                                .strip_prefix(&path_prefix)
3680                                .unwrap()
3681                                .trim_start_matches('·');
3682                            (suffix.to_string(), v.clone())
3683                        })
3684                        .filter(|(k, _)| !k.contains('·'))
3685                        .collect()
3686                };
3687                for (name, val) in matching_funcs {
3688                    self.globals.borrow_mut().define(name, val);
3689                }
3690                Ok(())
3691            }
3692            UseTree::Group(trees) => {
3693                // use foo::{Bar, Baz}
3694                for tree in trees {
3695                    self.process_use_tree(tree, prefix)?;
3696                }
3697                Ok(())
3698            }
3699        }
3700    }
3701
3702    fn create_function(&self, func: &crate::ast::Function) -> Result<Value, RuntimeError> {
3703        let params: Vec<String> = func
3704            .params
3705            .iter()
3706            .map(|p| Self::extract_param_name(&p.pattern))
3707            .collect();
3708
3709        let body = func
3710            .body
3711            .as_ref()
3712            .map(|b| Expr::Block(b.clone()))
3713            .unwrap_or(Expr::Literal(Literal::Bool(false)));
3714
3715        // Extract generic type parameter names (e.g., T, U from fn foo<T: Trait, U>())
3716        let generic_params = func
3717            .generics
3718            .as_ref()
3719            .map(|g| {
3720                g.params
3721                    .iter()
3722                    .filter_map(|p| match p {
3723                        crate::ast::GenericParam::Type { name, .. } => Some(name.name.clone()),
3724                        _ => None,
3725                    })
3726                    .collect()
3727            })
3728            .unwrap_or_default();
3729
3730        Ok(Value::Function(Rc::new(Function {
3731            name: Some(func.name.name.clone()),
3732            params,
3733            body,
3734            closure: self.environment.clone(),
3735            generic_params,
3736        })))
3737    }
3738
3739    /// Extract parameter name from a pattern, handling &self, mut self, etc.
3740    fn extract_param_name(pattern: &Pattern) -> String {
3741        match pattern {
3742            Pattern::Ident { name, .. } => name.name.clone(),
3743            // Handle &self and &mut self
3744            Pattern::Ref { pattern: inner, .. } => Self::extract_param_name(inner),
3745            // Handle ref self
3746            Pattern::RefBinding { name, .. } => name.name.clone(),
3747            _ => "_".to_string(),
3748        }
3749    }
3750
3751    /// Evaluate an expression
3752    pub fn evaluate(&mut self, expr: &Expr) -> Result<Value, RuntimeError> {
3753        match expr {
3754            Expr::Literal(lit) => self.eval_literal(lit),
3755            Expr::Path(path) => self.eval_path(path),
3756            Expr::Binary { left, op, right } => self.eval_binary(left, op, right),
3757            Expr::Unary { op, expr } => self.eval_unary(op, expr),
3758            Expr::Call { func, args } => self.eval_call(func, args),
3759            Expr::Array(elements) => self.eval_array(elements),
3760            Expr::Tuple(elements) => self.eval_tuple(elements),
3761            Expr::Block(block) => self.eval_block(block),
3762            Expr::If {
3763                condition,
3764                then_branch,
3765                else_branch,
3766            } => self.eval_if(condition, then_branch, else_branch),
3767            Expr::Match { expr, arms } => self.eval_match(expr, arms),
3768            Expr::For {
3769                pattern,
3770                iter,
3771                body,
3772                ..
3773            } => self.eval_for(pattern, iter, body),
3774            Expr::While {
3775                condition, body, ..
3776            } => self.eval_while(condition, body),
3777            Expr::Loop { body, .. } => self.eval_loop(body),
3778            Expr::Return(value) => self.eval_return(value),
3779            Expr::Break { value, .. } => self.eval_break(value),
3780            Expr::Continue { .. } => Err(RuntimeError::new("continue")),
3781            Expr::Index { expr, index } => self.eval_index(expr, index),
3782            Expr::Field { expr, field } => self.eval_field(expr, field),
3783            Expr::MethodCall {
3784                receiver,
3785                method,
3786                args,
3787                ..
3788            } => self.eval_method_call(receiver, method, args),
3789            // Polysynthetic incorporation: path·file·read·string
3790            // Each segment is a method/function that transforms the value
3791            Expr::Incorporation { segments } => self.eval_incorporation(segments),
3792            Expr::Pipe { expr, operations } => self.eval_pipe(expr, operations),
3793            Expr::Closure { params, body, .. } => self.eval_closure(params, body),
3794            Expr::Struct { path, fields, rest } => self.eval_struct_literal(path, fields, rest),
3795            Expr::Evidential {
3796                expr,
3797                evidentiality,
3798            } => self.eval_evidential(expr, evidentiality),
3799            Expr::Range {
3800                start,
3801                end,
3802                inclusive,
3803            } => {
3804                crate::sigil_debug!("DEBUG evaluate: Expr::Range being evaluated standalone");
3805                self.eval_range(start, end, *inclusive)
3806            }
3807            Expr::Assign { target, value } => self.eval_assign(target, value),
3808            Expr::Let { pattern, value } => {
3809                // Let expression (for if-let, while-let patterns)
3810                // Evaluate the value and check if pattern matches
3811                let val = self.evaluate(value)?;
3812                // Check if pattern matches - return true/false for if-let semantics
3813                if self.pattern_matches(pattern, &val)? {
3814                    // Pattern matches - bind variables and return true
3815                    self.bind_pattern(pattern, val)?;
3816                    Ok(Value::Bool(true))
3817                } else {
3818                    // Pattern doesn't match - return false without binding
3819                    Ok(Value::Bool(false))
3820                }
3821            }
3822            Expr::Await {
3823                expr: inner,
3824                evidentiality,
3825            } => {
3826                let value = self.evaluate(inner)?;
3827                let awaited = self.await_value(value)?;
3828                // Handle evidentiality marker semantics
3829                match evidentiality {
3830                    Some(Evidentiality::Uncertain) => {
3831                        // ⌛? - propagate error like Try
3832                        self.unwrap_result_or_option(awaited, true, false)
3833                    }
3834                    Some(Evidentiality::Known) => {
3835                        // ⌛! - expect success, panic on error
3836                        self.unwrap_result_or_option(awaited, true, true)
3837                    }
3838                    Some(Evidentiality::Reported)
3839                    | Some(Evidentiality::Paradox)
3840                    | Some(Evidentiality::Predicted) => {
3841                        // ⌛~ or ⌛‽ or ⌛◊ - mark as external/reported/predicted, unwrap if Result/Option
3842                        self.unwrap_result_or_option(awaited, false, false)
3843                    }
3844                    None => Ok(awaited),
3845                }
3846            }
3847            // Macro invocations: format!(...), println!(...), etc.
3848            Expr::Macro { path, tokens } => {
3849                let macro_name = path
3850                    .segments
3851                    .last()
3852                    .map(|s| s.ident.name.as_str())
3853                    .unwrap_or("");
3854                crate::sigil_debug!(
3855                    "DEBUG Expr::Macro: name='{}', tokens='{}'",
3856                    macro_name,
3857                    tokens
3858                );
3859
3860                match macro_name {
3861                    "format" => self.eval_format_macro(tokens),
3862                    "println" => {
3863                        let formatted = self.eval_format_macro(tokens)?;
3864                        if let Value::String(s) = formatted {
3865                            println!("{}", s);
3866                        }
3867                        Ok(Value::Null)
3868                    }
3869                    "eprintln" => {
3870                        let formatted = self.eval_format_macro(tokens)?;
3871                        if let Value::String(s) = formatted {
3872                            eprintln!("{}", s);
3873                        }
3874                        Ok(Value::Null)
3875                    }
3876                    "print" => {
3877                        let formatted = self.eval_format_macro(tokens)?;
3878                        if let Value::String(s) = formatted {
3879                            print!("{}", s);
3880                        }
3881                        Ok(Value::Null)
3882                    }
3883                    "eprint" => {
3884                        let formatted = self.eval_format_macro(tokens)?;
3885                        if let Value::String(s) = formatted {
3886                            eprint!("{}", s);
3887                        }
3888                        Ok(Value::Null)
3889                    }
3890                    "vec" => {
3891                        // vec![a, b, c] - parse elements and create array
3892                        self.eval_vec_macro(tokens)
3893                    }
3894                    "panic" => {
3895                        let formatted = self.eval_format_macro(tokens)?;
3896                        let msg = if let Value::String(s) = formatted {
3897                            s.to_string()
3898                        } else {
3899                            "panic!".to_string()
3900                        };
3901                        Err(RuntimeError::new(format!("panic: {}", msg)))
3902                    }
3903                    "assert" => {
3904                        // Parse and evaluate the expression in tokens
3905                        let trimmed = tokens.trim();
3906                        let mut parser = crate::parser::Parser::new(trimmed);
3907                        match parser.parse_expr() {
3908                            Ok(expr) => {
3909                                let condition = self.evaluate(&expr)?;
3910                                if self.is_truthy(&condition) {
3911                                    Ok(Value::Null)
3912                                } else {
3913                                    Err(RuntimeError::new(format!(
3914                                        "assertion failed: `{}`",
3915                                        trimmed
3916                                    )))
3917                                }
3918                            }
3919                            Err(_) => Err(RuntimeError::new(format!(
3920                                "assert!: failed to parse expression: {}",
3921                                trimmed
3922                            ))),
3923                        }
3924                    }
3925                    "assert_eq" => {
3926                        // Parse two comma-separated expressions and compare
3927                        let trimmed = tokens.trim();
3928                        // Split by top-level comma
3929                        let mut depth = 0;
3930                        let mut split_pos = None;
3931                        for (i, c) in trimmed.char_indices() {
3932                            match c {
3933                                '(' | '[' | '{' => depth += 1,
3934                                ')' | ']' | '}' => depth -= 1,
3935                                ',' if depth == 0 => {
3936                                    split_pos = Some(i);
3937                                    break;
3938                                }
3939                                _ => {}
3940                            }
3941                        }
3942                        if let Some(pos) = split_pos {
3943                            let left_str = trimmed[..pos].trim();
3944                            let right_str = trimmed[pos + 1..].trim();
3945                            let mut p1 = crate::parser::Parser::new(left_str);
3946                            let mut p2 = crate::parser::Parser::new(right_str);
3947                            match (p1.parse_expr(), p2.parse_expr()) {
3948                                (Ok(left_expr), Ok(right_expr)) => {
3949                                    let left = self.evaluate(&left_expr)?;
3950                                    let right = self.evaluate(&right_expr)?;
3951                                    if self.values_equal(&left, &right) {
3952                                        Ok(Value::Null)
3953                                    } else {
3954                                        Err(RuntimeError::new(format!(
3955                                            "assertion failed: `assert_eq!({}, {})` - left: {:?}, right: {:?}",
3956                                            left_str, right_str, left, right
3957                                        )))
3958                                    }
3959                                }
3960                                _ => Err(RuntimeError::new(format!(
3961                                    "assert_eq!: failed to parse expressions: {}",
3962                                    trimmed
3963                                ))),
3964                            }
3965                        } else {
3966                            Err(RuntimeError::new(format!(
3967                                "assert_eq! requires two arguments separated by comma: {}",
3968                                trimmed
3969                            )))
3970                        }
3971                    }
3972                    _ => {
3973                        // Check for user-defined macro
3974                        // Clone the macro definition out of the borrow to avoid lifetime issues
3975                        let macro_def = self.user_macros.borrow().get(macro_name).cloned();
3976                        if let Some((params, body, field_map)) = macro_def {
3977                            // Expand user-defined macro
3978                            self.expand_user_macro(&params, &body, tokens, None, &field_map)
3979                        } else {
3980                            // Unknown macro - return tokens as string for debugging
3981                            Ok(Value::String(Rc::new(tokens.clone())))
3982                        }
3983                    }
3984                }
3985            }
3986            // Unsafe block - just evaluate the block normally
3987            Expr::Unsafe(block) => self.eval_block(block),
3988            // Async block - evaluate the block (interpreter doesn't handle true async)
3989            Expr::Async { block, .. } => self.eval_block(block),
3990            // Try expression: expr?
3991            Expr::Try(inner) => {
3992                let value = self.evaluate(inner)?;
3993                // If Result::Err or None, propagate the error
3994                // If Result::Ok or Some, unwrap the value
3995                match &value {
3996                    Value::Variant {
3997                        enum_name,
3998                        variant_name,
3999                        fields,
4000                    } => {
4001                        match (enum_name.as_str(), variant_name.as_str()) {
4002                            ("Result", "Ok") => {
4003                                if let Some(f) = fields {
4004                                    Ok(f.first().cloned().unwrap_or(Value::Null))
4005                                } else {
4006                                    Ok(Value::Null)
4007                                }
4008                            }
4009                            ("Result", "Err") => {
4010                                crate::sigil_debug!(
4011                                    "DEBUG Try propagating Result::Err with fields: {:?}",
4012                                    fields
4013                                );
4014                                let err_msg = if let Some(f) = fields {
4015                                    let first = f.first().cloned().unwrap_or(Value::Null);
4016                                    crate::sigil_debug!("DEBUG Try error first value: {}", first);
4017                                    // Try to get more detail from the error
4018                                    match &first {
4019                                        Value::Struct { name, fields: sf } => {
4020                                            let field_str = sf
4021                                                .borrow()
4022                                                .iter()
4023                                                .map(|(k, v)| format!("{}: {}", k, v))
4024                                                .collect::<Vec<_>>()
4025                                                .join(", ");
4026                                            format!("{} {{ {} }}", name, field_str)
4027                                        }
4028                                        Value::Variant {
4029                                            enum_name: en,
4030                                            variant_name: vn,
4031                                            fields: vf,
4032                                        } => {
4033                                            let vf_str = vf
4034                                                .as_ref()
4035                                                .map(|vs| {
4036                                                    vs.iter()
4037                                                        .map(|v| format!("{}", v))
4038                                                        .collect::<Vec<_>>()
4039                                                        .join(", ")
4040                                                })
4041                                                .unwrap_or_default();
4042                                            format!("{}::{} {{ {} }}", en, vn, vf_str)
4043                                        }
4044                                        _ => format!("{}", first),
4045                                    }
4046                                } else {
4047                                    "error".to_string()
4048                                };
4049                                Err(RuntimeError::new(format!("try failed: {}", err_msg)))
4050                            }
4051                            ("Option", "Some") => {
4052                                if let Some(f) = fields {
4053                                    Ok(f.first().cloned().unwrap_or(Value::Null))
4054                                } else {
4055                                    Ok(Value::Null)
4056                                }
4057                            }
4058                            ("Option", "None") => Err(RuntimeError::new("try failed: None")),
4059                            _ => Ok(value), // Not a Result/Option, pass through
4060                        }
4061                    }
4062                    _ => Ok(value), // Not a variant, pass through
4063                }
4064            }
4065            // Cast expression: expr as Type
4066            Expr::Cast { expr, ty } => {
4067                let value = self.evaluate(expr)?;
4068                // Handle type casts
4069                let type_name = match ty {
4070                    TypeExpr::Path(path) => {
4071                        if !path.segments.is_empty() {
4072                            path.segments
4073                                .last()
4074                                .map(|s| s.ident.name.as_str())
4075                                .unwrap_or("")
4076                        } else {
4077                            ""
4078                        }
4079                    }
4080                    _ => "",
4081                };
4082                match (value, type_name) {
4083                    // Char to numeric
4084                    (Value::Char(c), "u8") => Ok(Value::Int(c as i64)),
4085                    (Value::Char(c), "u16") => Ok(Value::Int(c as i64)),
4086                    (Value::Char(c), "u32") => Ok(Value::Int(c as i64)),
4087                    (Value::Char(c), "u64") => Ok(Value::Int(c as i64)),
4088                    (Value::Char(c), "i8") => Ok(Value::Int(c as i64)),
4089                    (Value::Char(c), "i16") => Ok(Value::Int(c as i64)),
4090                    (Value::Char(c), "i32") => Ok(Value::Int(c as i64)),
4091                    (Value::Char(c), "i64") => Ok(Value::Int(c as i64)),
4092                    (Value::Char(c), "usize") => Ok(Value::Int(c as i64)),
4093                    (Value::Char(c), "isize") => Ok(Value::Int(c as i64)),
4094                    // Int to int (no-op in our runtime)
4095                    (Value::Int(i), "u8") => Ok(Value::Int(i)),
4096                    (Value::Int(i), "u16") => Ok(Value::Int(i)),
4097                    (Value::Int(i), "u32") => Ok(Value::Int(i)),
4098                    (Value::Int(i), "u64") => Ok(Value::Int(i)),
4099                    (Value::Int(i), "i8") => Ok(Value::Int(i)),
4100                    (Value::Int(i), "i16") => Ok(Value::Int(i)),
4101                    (Value::Int(i), "i32") => Ok(Value::Int(i)),
4102                    (Value::Int(i), "i64") => Ok(Value::Int(i)),
4103                    (Value::Int(i), "usize") => Ok(Value::Int(i)),
4104                    (Value::Int(i), "isize") => Ok(Value::Int(i)),
4105                    // Float to int
4106                    (Value::Float(f), "i32") => Ok(Value::Int(f as i64)),
4107                    (Value::Float(f), "i64") => Ok(Value::Int(f as i64)),
4108                    (Value::Float(f), "u32") => Ok(Value::Int(f as i64)),
4109                    (Value::Float(f), "u64") => Ok(Value::Int(f as i64)),
4110                    // Int to float
4111                    (Value::Int(i), "f32") => Ok(Value::Float(i as f64)),
4112                    (Value::Int(i), "f64") => Ok(Value::Float(i as f64)),
4113                    // Int to char
4114                    (Value::Int(i), "char") => {
4115                        if let Some(c) = char::from_u32(i as u32) {
4116                            Ok(Value::Char(c))
4117                        } else {
4118                            Err(RuntimeError::new(format!("invalid char code: {}", i)))
4119                        }
4120                    }
4121                    // Pass through for same type
4122                    (v, _) => Ok(v),
4123                }
4124            }
4125            // Named argument: evaluate the value (name is used by caller for reordering)
4126            Expr::NamedArg { value, .. } => self.evaluate(value),
4127            _ => Err(RuntimeError::new(format!(
4128                "Unsupported expression: {:?}",
4129                expr
4130            ))),
4131        }
4132    }
4133
4134    fn eval_assign(&mut self, target: &Expr, value: &Expr) -> Result<Value, RuntimeError> {
4135        let val = self.evaluate(value)?;
4136
4137        match target {
4138            Expr::Path(path) if path.segments.len() == 1 => {
4139                let name = &path.segments[0].ident.name;
4140                // Check if variable is mutable before allowing assignment
4141                let in_env = self.environment.borrow().get(name).is_some();
4142                let in_globals = self.globals.borrow().get(name).is_some();
4143
4144                if !self.mutable_vars.borrow().contains(name) {
4145                    // Check if variable exists (to distinguish from first assignment vs reassignment)
4146                    if in_env || in_globals {
4147                        return Err(RuntimeError::new(format!(
4148                            "cannot assign to immutable variable '{}'. \
4149                            Hint: Use `≔ Δ {} = ...` or `vary {} = ...` to declare mutable variables",
4150                            name, name, name
4151                        )));
4152                    }
4153                }
4154
4155                // If it's a global (static), update globals; otherwise update environment
4156                if in_globals && !in_env {
4157                    self.globals.borrow_mut().set(name, val.clone())?;
4158                } else {
4159                    self.environment.borrow_mut().set(name, val.clone())?;
4160                }
4161                Ok(val)
4162            }
4163            Expr::Index { expr, index } => {
4164                // Array/map index assignment
4165                let idx = self.evaluate(index)?;
4166                let idx = match idx {
4167                    Value::Int(i) => i as usize,
4168                    _ => return Err(RuntimeError::new("Index must be an integer")),
4169                };
4170
4171                // Get the array and modify it
4172                if let Expr::Path(path) = expr.as_ref() {
4173                    if path.segments.len() == 1 {
4174                        let name = &path.segments[0].ident.name;
4175                        let current = self.environment.borrow().get(name).ok_or_else(|| {
4176                            RuntimeError::new(format!("Undefined variable: {}", name))
4177                        })?;
4178
4179                        if let Value::Array(arr) = current {
4180                            let borrowed = arr.borrow();
4181                            let mut new_arr = borrowed.clone();
4182                            drop(borrowed);
4183                            if idx < new_arr.len() {
4184                                new_arr[idx] = val.clone();
4185                                self.environment
4186                                    .borrow_mut()
4187                                    .set(name, Value::Array(Rc::new(RefCell::new(new_arr))))?;
4188                                return Ok(val);
4189                            }
4190                        }
4191                    }
4192                }
4193
4194                // Handle complex index targets (e.g., self.data[idx], x.field[idx])
4195                // Evaluate the expression to get the array value. Since Value::Array
4196                // uses Rc<RefCell<Vec<Value>>>, modifying through the shared reference
4197                // updates the original struct field in place.
4198                let target = self.evaluate(expr)?;
4199                // Unwrap Ref if needed to get the inner array
4200                let target = match &target {
4201                    Value::Ref(r) => r.borrow().clone(),
4202                    other => other.clone(),
4203                };
4204                match target {
4205                    Value::Array(arr) => {
4206                        let mut borrowed = arr.borrow_mut();
4207                        if idx < borrowed.len() {
4208                            borrowed[idx] = val.clone();
4209                            return Ok(val);
4210                        }
4211                        Err(RuntimeError::new(format!(
4212                            "Index {} out of bounds for array of length {}",
4213                            idx,
4214                            borrowed.len()
4215                        )))
4216                    }
4217                    _ => Err(RuntimeError::new("Invalid index assignment target")),
4218                }
4219            }
4220            Expr::Field { expr, field } => {
4221                // Field assignment: struct.field = value
4222                // Need to find the variable and update its field
4223                match expr.as_ref() {
4224                    Expr::Path(path) if path.segments.len() == 1 => {
4225                        let var_name = &path.segments[0].ident.name;
4226                        let current = self.environment.borrow().get(var_name).ok_or_else(|| {
4227                            RuntimeError::new(format!("Undefined variable: {}", var_name))
4228                        })?;
4229
4230                        match current {
4231                            Value::Struct { fields, .. } => {
4232                                fields.borrow_mut().insert(field.name.clone(), val.clone());
4233                                Ok(val)
4234                            }
4235                            Value::Ref(r) => {
4236                                let mut borrowed = r.borrow_mut();
4237                                if let Value::Struct { fields, .. } = &mut *borrowed {
4238                                    fields.borrow_mut().insert(field.name.clone(), val.clone());
4239                                    Ok(val)
4240                                } else {
4241                                    Err(RuntimeError::new("Cannot assign field on non-struct ref"))
4242                                }
4243                            }
4244                            _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
4245                        }
4246                    }
4247                    _ => {
4248                        // For now, just evaluate and try to update (won't persist for non-path exprs)
4249                        let struct_val = self.evaluate(expr)?;
4250                        match struct_val {
4251                            Value::Struct { fields, .. } => {
4252                                fields.borrow_mut().insert(field.name.clone(), val.clone());
4253                                Ok(val)
4254                            }
4255                            Value::Ref(r) => {
4256                                let mut borrowed = r.borrow_mut();
4257                                if let Value::Struct { fields, .. } = &mut *borrowed {
4258                                    fields.borrow_mut().insert(field.name.clone(), val.clone());
4259                                    Ok(val)
4260                                } else {
4261                                    Err(RuntimeError::new("Cannot assign field on non-struct"))
4262                                }
4263                            }
4264                            _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
4265                        }
4266                    }
4267                }
4268            }
4269            Expr::Unary {
4270                op: UnaryOp::Deref,
4271                expr: inner,
4272            } => {
4273                // Dereference assignment: *ptr = value (parsed as Unary)
4274                // Handle mutable references (&mut T)
4275                let ptr_val = self.evaluate(inner)?;
4276                match ptr_val {
4277                    Value::Ref(r) => {
4278                        *r.borrow_mut() = val.clone();
4279                        Ok(val)
4280                    }
4281                    _ => Err(RuntimeError::new(
4282                        "Cannot dereference assign to non-reference",
4283                    )),
4284                }
4285            }
4286            Expr::Deref(inner) => {
4287                // Dereference assignment: *ptr = value (parsed as Deref)
4288                // Handle mutable references (&mut T)
4289                let ptr_val = self.evaluate(inner)?;
4290                match ptr_val {
4291                    Value::Ref(r) => {
4292                        *r.borrow_mut() = val.clone();
4293                        Ok(val)
4294                    }
4295                    _ => Err(RuntimeError::new(
4296                        "Cannot dereference assign to non-reference",
4297                    )),
4298                }
4299            }
4300            _ => Err(RuntimeError::new("Invalid assignment target")),
4301        }
4302    }
4303
4304    fn eval_literal(&mut self, lit: &Literal) -> Result<Value, RuntimeError> {
4305        match lit {
4306            Literal::Int { value, base, .. } => {
4307                let n = self.parse_int(value, base)?;
4308                Ok(Value::Int(n))
4309            }
4310            Literal::Float { value, .. } => {
4311                let n: f64 = value
4312                    .parse()
4313                    .map_err(|_| RuntimeError::new(format!("Invalid float: {}", value)))?;
4314                Ok(Value::Float(n))
4315            }
4316            Literal::String(s) => Ok(Value::String(Rc::new(s.clone()))),
4317            Literal::MultiLineString(s) => Ok(Value::String(Rc::new(s.clone()))),
4318            Literal::RawString(s) => Ok(Value::String(Rc::new(s.clone()))),
4319            Literal::ByteString(bytes) => {
4320                // Convert byte array to an array of integers
4321                let arr: Vec<Value> = bytes.iter().map(|&b| Value::Int(b as i64)).collect();
4322                Ok(Value::Array(Rc::new(RefCell::new(arr))))
4323            }
4324            Literal::InterpolatedString { parts } => {
4325                // Evaluate each part and concatenate, tracking evidentiality
4326                let mut result = String::new();
4327                let mut combined_evidence: Option<Evidence> = None;
4328
4329                for part in parts {
4330                    match part {
4331                        InterpolationPart::Text(s) => result.push_str(s),
4332                        InterpolationPart::Expr(expr) => {
4333                            let value = self.evaluate(expr)?;
4334
4335                            // Track explicit evidentiality
4336                            combined_evidence = Self::combine_evidence(
4337                                combined_evidence,
4338                                Self::extract_evidence(&value),
4339                            );
4340
4341                            // Track affect-derived evidentiality (sarcasm, confidence)
4342                            if let Some(affect) = Self::extract_affect(&value) {
4343                                combined_evidence = Self::combine_evidence(
4344                                    combined_evidence,
4345                                    Self::affect_to_evidence(affect),
4346                                );
4347                            }
4348
4349                            // Use the fully unwrapped value for display
4350                            let display_value = Self::unwrap_value(&value);
4351                            result.push_str(&format!("{}", display_value));
4352                        }
4353                    }
4354                }
4355
4356                // Wrap result with evidentiality if any interpolated values were evidential
4357                let string_value = Value::String(Rc::new(result));
4358                match combined_evidence {
4359                    Some(evidence) => Ok(Value::Evidential {
4360                        value: Box::new(string_value),
4361                        evidence,
4362                    }),
4363                    None => Ok(string_value),
4364                }
4365            }
4366            Literal::SigilStringSql(s) => {
4367                // SQL sigil string - for now just return as string
4368                // Future: could add SQL validation or templating
4369                Ok(Value::String(Rc::new(s.clone())))
4370            }
4371            Literal::SigilStringRoute(s) => {
4372                // Route sigil string - for now just return as string
4373                // Future: could add route validation or templating
4374                Ok(Value::String(Rc::new(s.clone())))
4375            }
4376            Literal::Char(c) => Ok(Value::Char(*c)),
4377            Literal::ByteChar(b) => Ok(Value::Int(*b as i64)),
4378            Literal::Bool(b) => Ok(Value::Bool(*b)),
4379            Literal::Null => Ok(Value::Null),
4380            Literal::Empty => Ok(Value::Empty),
4381            Literal::Infinity => Ok(Value::Infinity),
4382            Literal::Circle => Ok(Value::Int(0)), // ◯ = zero
4383        }
4384    }
4385
4386    fn parse_int(&self, value: &str, base: &NumBase) -> Result<i64, RuntimeError> {
4387        let (radix, prefix_len) = match base {
4388            NumBase::Binary => (2, 2), // 0b
4389            NumBase::Octal => (8, 2),  // 0o
4390            NumBase::Decimal => (10, 0),
4391            NumBase::Hex => (16, 2),         // 0x
4392            NumBase::Vigesimal => (20, 2),   // 0v
4393            NumBase::Sexagesimal => (60, 2), // 0s
4394            NumBase::Duodecimal => (12, 2),  // 0z
4395            NumBase::Explicit(b) => (*b as u32, 0),
4396        };
4397
4398        let clean = value[prefix_len..].replace('_', "");
4399        i64::from_str_radix(&clean, radix)
4400            .map_err(|_| RuntimeError::new(format!("Invalid integer: {}", value)))
4401    }
4402
4403    fn eval_path(&self, path: &TypePath) -> Result<Value, RuntimeError> {
4404        if path.segments.len() == 1 {
4405            let name = &path.segments[0].ident.name;
4406            // Look up the variable in the environment
4407            // Note: "_" may be bound by pipe operations (τ, φ, etc.), so we must check
4408            // the environment first before treating it as a wildcard
4409            if let Some(val) = self.environment.borrow().get(name) {
4410                // Check if this is a linear variable
4411                if self.linear_state.vars.borrow().contains(name) {
4412                    // Check if already consumed
4413                    if self.linear_state.consumed.borrow().contains(name) {
4414                        return Err(RuntimeError::linear_type_violation(name));
4415                    }
4416                    // Mark as consumed
4417                    self.linear_state.consumed.borrow_mut().insert(name.clone());
4418                }
4419                return Ok(val);
4420            }
4421            // Handle wildcard "_" - return Null if not bound
4422            if name == "_" {
4423                return Ok(Value::Null);
4424            }
4425            // Handle "Self" as unit struct constructor (for unit structs like `pub fn new() -> Self { Self }`)
4426            if name == "Self" {
4427                if let Some(ref self_type) = self.current_self_type {
4428                    // Check if the type is a unit struct
4429                    if let Some(TypeDef::Struct(struct_def)) = self.types.get(self_type) {
4430                        if matches!(struct_def.fields, crate::ast::StructFields::Unit) {
4431                            return Ok(Value::Struct {
4432                                name: self_type.clone(),
4433                                fields: Rc::new(RefCell::new(HashMap::new())),
4434                            });
4435                        }
4436                    }
4437                    // If not a unit struct, create empty struct (best effort)
4438                    return Ok(Value::Struct {
4439                        name: self_type.clone(),
4440                        fields: Rc::new(RefCell::new(HashMap::new())),
4441                    });
4442                }
4443            }
4444            if name.len() <= 2 {
4445                crate::sigil_debug!("DEBUG Undefined variable '{}' (len={})", name, name.len());
4446            }
4447            Err(RuntimeError::undefined_variable(name))
4448        } else {
4449            // Multi-segment path (module::item or Type·method)
4450            // Try full qualified name first (joined with ·)
4451            let full_name = path
4452                .segments
4453                .iter()
4454                .map(|s| {
4455                    // Resolve Self to concrete type name inside trait/impl methods
4456                    if s.ident.name == "Self" {
4457                        if let Some(ref self_type) = self.current_self_type {
4458                            return self_type.clone();
4459                        }
4460                    }
4461                    // Resolve generic type parameters (e.g., T -> F16 during dtype_info·<F16>())
4462                    if let Some(concrete) = self.generic_type_bindings.get(&s.ident.name) {
4463                        return concrete.clone();
4464                    }
4465                    s.ident.name.clone()
4466                })
4467                .collect::<Vec<_>>()
4468                .join("·");
4469
4470            if let Some(val) = self.environment.borrow().get(&full_name) {
4471                return Ok(val);
4472            }
4473
4474            // Check globals for qualified name (for Type::method patterns)
4475            if let Some(val) = self.globals.borrow().get(&full_name) {
4476                return Ok(val);
4477            }
4478
4479            // If in a module context, try current_module·full_name for sibling modules
4480            // e.g., when in samael_cli, "analyze::execute" -> "samael_cli·analyze·execute"
4481            if let Some(ref current_mod) = self.current_module {
4482                // Extract crate name from current_module (e.g., "samael_cli" from "samael_cli·analyze")
4483                let crate_name = current_mod.split('·').next().unwrap_or(current_mod);
4484                let crate_qualified = format!("{}·{}", crate_name, full_name);
4485                if full_name.contains("execute") {
4486                    crate::sigil_debug!(
4487                        "DEBUG eval_path: Looking for '{}' with crate_qualified='{}'",
4488                        full_name,
4489                        crate_qualified
4490                    );
4491                }
4492                if let Some(val) = self.globals.borrow().get(&crate_qualified) {
4493                    crate::sigil_debug!(
4494                        "DEBUG eval_path: FOUND '{}' via crate_qualified",
4495                        crate_qualified
4496                    );
4497                    return Ok(val);
4498                }
4499            } else if full_name.contains("execute") {
4500                crate::sigil_debug!(
4501                    "DEBUG eval_path: current_module is None, can't resolve '{}'",
4502                    full_name
4503                );
4504            }
4505
4506            // DEBUG: Check if we're looking for a ::new call
4507            if full_name.ends_with("·new") {
4508                crate::sigil_debug!(
4509                    "DEBUG eval_path: Looking for '{}' - NOT FOUND in globals",
4510                    full_name
4511                );
4512            }
4513
4514            // Check for enum variant syntax (EnumName::Variant or module::EnumName::Variant)
4515            // This must come before looking up just the last segment to avoid
4516            // returning a built-in function instead of the actual variant
4517            if path.segments.len() >= 2 {
4518                let variant_name = &path.segments.last().unwrap().ident.name;
4519
4520                // Build possible type names from the path (all segments except the last)
4521                let type_segments: Vec<&str> = path.segments[..path.segments.len() - 1]
4522                    .iter()
4523                    .map(|s| s.ident.name.as_str())
4524                    .collect();
4525
4526                // Try different type name formats:
4527                // 1. Direct name (e.g., "DType" for DType::F32)
4528                // 2. Module-qualified with · (e.g., "dtype·DType" for dtype::DType::F32)
4529                // 3. Module-qualified with :: converted (e.g., "dtype·DType")
4530                let type_name_direct = type_segments.join("::");
4531                let type_name_qualified = type_segments.join("·");
4532
4533                // Try direct type name first
4534                let enum_def_and_name = self
4535                    .types
4536                    .get(&type_name_direct)
4537                    .map(|td| (td, type_name_direct.clone()))
4538                    .or_else(|| {
4539                        self.types
4540                            .get(&type_name_qualified)
4541                            .map(|td| (td, type_name_qualified.clone()))
4542                    });
4543
4544                if let Some((TypeDef::Enum(enum_def), actual_enum_name)) = enum_def_and_name {
4545                    for variant in &enum_def.variants {
4546                        if &variant.name.name == variant_name {
4547                            // Return a variant constructor or unit variant
4548                            if matches!(variant.fields, crate::ast::StructFields::Unit) {
4549                                return Ok(Value::Variant {
4550                                    enum_name: actual_enum_name,
4551                                    variant_name: variant_name.clone(),
4552                                    fields: None,
4553                                });
4554                            }
4555                        }
4556                    }
4557                }
4558
4559                // Fallback: search all enums for matching type name suffix and variant
4560                for (actual_type_name, type_def) in &self.types {
4561                    if let TypeDef::Enum(enum_def) = type_def {
4562                        // Check if this enum name ends with our type name
4563                        // (handles module·DType matching DType)
4564                        let matches = actual_type_name == &type_name_direct
4565                            || actual_type_name == &type_name_qualified
4566                            || actual_type_name.ends_with(&format!("·{}", type_name_direct));
4567
4568                        if matches {
4569                            for variant in &enum_def.variants {
4570                                if &variant.name.name == variant_name {
4571                                    if matches!(variant.fields, crate::ast::StructFields::Unit) {
4572                                        return Ok(Value::Variant {
4573                                            enum_name: actual_type_name.clone(),
4574                                            variant_name: variant_name.clone(),
4575                                            fields: None,
4576                                        });
4577                                    }
4578                                }
4579                            }
4580                        }
4581                    }
4582                }
4583            }
4584
4585            // Try looking up the last segment (for Math·sqrt -> sqrt)
4586            let last_name = &path.segments.last().unwrap().ident.name;
4587            if let Some(val) = self.environment.borrow().get(last_name) {
4588                // DEBUG: Warn about fallback for new functions
4589                if last_name == "new" {
4590                    crate::sigil_debug!(
4591                        "DEBUG eval_path: FALLBACK from '{}' to '{}' - found in env",
4592                        full_name,
4593                        last_name
4594                    );
4595                }
4596                return Ok(val);
4597            }
4598
4599            // Handle Self::method - use current_self_type to get the specific type
4600            if path.segments.len() == 2 && path.segments[0].ident.name == "Self" {
4601                if let Some(ref self_type) = self.current_self_type {
4602                    // Look up the specific Type·method function
4603                    let qualified = format!("{}·{}", self_type, last_name);
4604                    if let Some(val) = self.globals.borrow().get(&qualified) {
4605                        return Ok(val);
4606                    }
4607                }
4608            }
4609
4610            // Check for variant constructor in variant_constructors table
4611            if let Some((enum_name, variant_name, arity)) =
4612                self.variant_constructors.get(&full_name).cloned()
4613            {
4614                // Return a special marker that eval_call can recognize
4615                // For unit variants, return the variant directly
4616                if arity == 0 {
4617                    return Ok(Value::Variant {
4618                        enum_name,
4619                        variant_name,
4620                        fields: None,
4621                    });
4622                }
4623                // For variants with fields, we need to return something callable
4624                // We'll use a special builtin-like marker
4625                // Actually, let's just let eval_call handle it via call_function_by_name
4626            }
4627
4628            // Try module·function lookup - first try the direct qualified name (e.g., "analyze·execute")
4629            // This handles module function calls like `analyze·execute(...)` when module was imported via `invoke tome·analyze`
4630            if path.segments.len() == 2 {
4631                // Try direct lookup (module was registered with just module name prefix)
4632                if let Some(val) = self.globals.borrow().get(&full_name) {
4633                    return Ok(val);
4634                }
4635                // Also try with current_module crate prefix
4636                if let Some(ref current_mod) = self.current_module {
4637                    let crate_name = current_mod.split('·').next().unwrap_or(current_mod);
4638                    let module_qualified = format!("{}·{}", crate_name, full_name);
4639                    if let Some(val) = self.globals.borrow().get(&module_qualified) {
4640                        return Ok(val);
4641                    }
4642                }
4643            }
4644
4645            // Fallback for unknown types from external crates:
4646            if path.segments.len() == 2 {
4647                let type_name = &path.segments[0].ident.name;
4648                let method_name = &path.segments[1].ident.name;
4649
4650                // Check if this looks like a constructor/method call (lowercase or snake_case)
4651                let is_method = method_name
4652                    .chars()
4653                    .next()
4654                    .map_or(false, |c| c.is_lowercase())
4655                    || method_name == "new"
4656                    || method_name == "default"
4657                    || method_name == "from"
4658                    || method_name == "try_from"
4659                    || method_name == "into"
4660                    || method_name == "with_capacity"
4661                    || method_name == "from_str";
4662
4663                if is_method {
4664                    // Return a special marker that eval_call will recognize
4665                    // Store the type name in a Struct value with a special marker name
4666                    return Ok(Value::Struct {
4667                        name: format!("__constructor__{}", type_name),
4668                        fields: Rc::new(RefCell::new(HashMap::new())),
4669                    });
4670                } else {
4671                    // Looks like an enum variant (PascalCase) - check if it exists
4672                    if let Some(TypeDef::Enum(enum_def)) = self.types.get(type_name) {
4673                        // Check if variant exists
4674                        let variant_exists = enum_def
4675                            .variants
4676                            .iter()
4677                            .any(|v| v.name.name == *method_name);
4678                        if !variant_exists {
4679                            return Err(RuntimeError::new(format!(
4680                                "no variant '{}' on enum '{}'",
4681                                method_name, type_name
4682                            )));
4683                        }
4684                    }
4685                    // Create unit variant (for external types or verified variants)
4686                    return Ok(Value::Variant {
4687                        enum_name: type_name.clone(),
4688                        variant_name: method_name.clone(),
4689                        fields: None,
4690                    });
4691                }
4692            }
4693
4694            Err(RuntimeError::new(format!(
4695                "Undefined: {} (tried {} and {})",
4696                full_name, full_name, last_name
4697            )))
4698        }
4699    }
4700
4701    fn eval_binary(
4702        &mut self,
4703        left: &Expr,
4704        op: &BinOp,
4705        right: &Expr,
4706    ) -> Result<Value, RuntimeError> {
4707        let lhs = self.evaluate(left)?;
4708
4709        // Short-circuit for && and ||
4710        match op {
4711            BinOp::And => {
4712                if !self.is_truthy(&lhs) {
4713                    return Ok(Value::Bool(false));
4714                }
4715                let rhs = self.evaluate(right)?;
4716                return Ok(Value::Bool(self.is_truthy(&rhs)));
4717            }
4718            BinOp::Or => {
4719                if self.is_truthy(&lhs) {
4720                    return Ok(Value::Bool(true));
4721                }
4722                let rhs = self.evaluate(right)?;
4723                return Ok(Value::Bool(self.is_truthy(&rhs)));
4724            }
4725            _ => {}
4726        }
4727
4728        let rhs = self.evaluate(right)?;
4729
4730        // Unwrap all wrappers (evidential/affective/ref) for binary operations
4731        let lhs = Self::unwrap_all(&lhs);
4732        let rhs = Self::unwrap_all(&rhs);
4733
4734        // Auto-resolve zero-arg BuiltIn constants (PI, E, TAU, PHI) in binary context
4735        let lhs = self.resolve_constant(lhs);
4736        let rhs = self.resolve_constant(rhs);
4737
4738        // Debug Mul operations involving potential null
4739        if matches!(op, BinOp::Mul)
4740            && (matches!(lhs, Value::Null)
4741                || matches!(rhs, Value::Null)
4742                || matches!(lhs, Value::Struct { .. })
4743                || matches!(rhs, Value::Struct { .. }))
4744        {
4745            crate::sigil_debug!("DEBUG eval_binary Mul: left={:?}, right={:?}", left, right);
4746            crate::sigil_debug!(
4747                "DEBUG eval_binary Mul: lhs={}, rhs={}",
4748                self.format_value(&lhs),
4749                self.format_value(&rhs)
4750            );
4751        }
4752
4753        match (lhs, rhs) {
4754            (Value::Int(a), Value::Int(b)) => self.int_binary_op(a, b, op),
4755            (Value::Float(a), Value::Float(b)) => self.float_binary_op(a, b, op),
4756            (Value::Int(a), Value::Float(b)) => self.float_binary_op(a as f64, b, op),
4757            (Value::Float(a), Value::Int(b)) => self.float_binary_op(a, b as f64, op),
4758            (Value::String(a), Value::String(b)) => match op {
4759                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
4760                BinOp::Eq => Ok(Value::Bool(*a == *b)),
4761                BinOp::Ne => Ok(Value::Bool(*a != *b)),
4762                _ => Err(RuntimeError::new("Invalid string operation")),
4763            },
4764            (Value::Bool(a), Value::Bool(b)) => match op {
4765                BinOp::Eq => Ok(Value::Bool(a == b)),
4766                BinOp::Ne => Ok(Value::Bool(a != b)),
4767                _ => Err(RuntimeError::new("Invalid boolean operation")),
4768            },
4769            (Value::Array(a), Value::Array(b)) => match op {
4770                BinOp::Concat => {
4771                    let mut result = a.borrow().clone();
4772                    result.extend(b.borrow().iter().cloned());
4773                    Ok(Value::Array(Rc::new(RefCell::new(result))))
4774                }
4775                BinOp::Convolve => {
4776                    // Convolution/merge of two arrays
4777                    // Per spec 11-HOLOGRAPHIC.md § 2.4:
4778                    // For Shard arrays: deduplicate by index field
4779                    // For other arrays: concatenate
4780
4781                    let arr_a = a.borrow();
4782                    let arr_b = b.borrow();
4783
4784                    // Check if this is an array of Shard structs
4785                    let is_shard_array = arr_a.first().map_or(
4786                        false,
4787                        |v| matches!(v, Value::Struct { name, .. } if name == "Shard"),
4788                    );
4789
4790                    if is_shard_array {
4791                        // Deduplicate by index field
4792                        let mut seen_indices: std::collections::HashSet<i64> =
4793                            std::collections::HashSet::new();
4794                        let mut result = Vec::new();
4795
4796                        // Add shards from first array, tracking indices
4797                        for shard in arr_a.iter() {
4798                            if let Value::Struct { fields, .. } = shard {
4799                                if let Some(Value::Int(idx)) = fields.borrow().get("index") {
4800                                    if seen_indices.insert(*idx) {
4801                                        result.push(shard.clone());
4802                                    }
4803                                } else {
4804                                    // No index field or non-int, just add it
4805                                    result.push(shard.clone());
4806                                }
4807                            } else {
4808                                result.push(shard.clone());
4809                            }
4810                        }
4811
4812                        // Add shards from second array, skipping duplicates
4813                        for shard in arr_b.iter() {
4814                            if let Value::Struct { fields, .. } = shard {
4815                                if let Some(Value::Int(idx)) = fields.borrow().get("index") {
4816                                    if seen_indices.insert(*idx) {
4817                                        result.push(shard.clone());
4818                                    }
4819                                    // Skip if index already seen (duplicate)
4820                                } else {
4821                                    // No index field, add it
4822                                    result.push(shard.clone());
4823                                }
4824                            } else {
4825                                result.push(shard.clone());
4826                            }
4827                        }
4828
4829                        Ok(Value::Array(Rc::new(RefCell::new(result))))
4830                    } else {
4831                        // Non-shard arrays: simple concatenation
4832                        let mut result = arr_a.clone();
4833                        result.extend(arr_b.iter().cloned());
4834                        Ok(Value::Array(Rc::new(RefCell::new(result))))
4835                    }
4836                }
4837                BinOp::Eq => {
4838                    let arr_a = a.borrow();
4839                    let arr_b = b.borrow();
4840                    let equal = arr_a.len() == arr_b.len()
4841                        && arr_a.iter().zip(arr_b.iter()).all(|(x, y)| {
4842                            self.values_equal(x, y)
4843                        });
4844                    Ok(Value::Bool(equal))
4845                }
4846                BinOp::Ne => {
4847                    let arr_a = a.borrow();
4848                    let arr_b = b.borrow();
4849                    let equal = arr_a.len() == arr_b.len()
4850                        && arr_a.iter().zip(arr_b.iter()).all(|(x, y)| {
4851                            self.values_equal(x, y)
4852                        });
4853                    Ok(Value::Bool(!equal))
4854                }
4855                _ => Err(RuntimeError::new("Invalid array operation")),
4856            },
4857            // Null equality
4858            (Value::Null, Value::Null) => match op {
4859                BinOp::Eq => Ok(Value::Bool(true)),
4860                BinOp::Ne => Ok(Value::Bool(false)),
4861                _ => {
4862                    crate::sigil_debug!("DEBUG: null op {:?} on (Null, Null)", op);
4863                    Err(RuntimeError::new(format!(
4864                        "Invalid null operation: {:?} on (Null, Null)",
4865                        op
4866                    )))
4867                }
4868            },
4869            (Value::Null, other) | (other, Value::Null) => match op {
4870                BinOp::Eq => Ok(Value::Bool(false)),
4871                BinOp::Ne => Ok(Value::Bool(true)),
4872                _ => {
4873                    crate::sigil_debug!(
4874                        "DEBUG: null op {:?} with other={}",
4875                        op,
4876                        self.format_value(&other)
4877                    );
4878                    Err(RuntimeError::new(format!(
4879                        "Invalid null operation: {:?}",
4880                        op
4881                    )))
4882                }
4883            },
4884            // Char comparisons
4885            (Value::Char(a), Value::Char(b)) => match op {
4886                BinOp::Eq => Ok(Value::Bool(a == b)),
4887                BinOp::Ne => Ok(Value::Bool(a != b)),
4888                BinOp::Lt => Ok(Value::Bool(a < b)),
4889                BinOp::Le => Ok(Value::Bool(a <= b)),
4890                BinOp::Gt => Ok(Value::Bool(a > b)),
4891                BinOp::Ge => Ok(Value::Bool(a >= b)),
4892                _ => Err(RuntimeError::new("Invalid char operation")),
4893            },
4894            // String and char operations
4895            (Value::String(a), Value::Char(b)) => match op {
4896                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
4897                _ => Err(RuntimeError::new("Invalid string/char operation")),
4898            },
4899            (Value::Char(a), Value::String(b)) => match op {
4900                BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
4901                _ => Err(RuntimeError::new("Invalid char/string operation")),
4902            },
4903            // Variant equality
4904            (
4905                Value::Variant {
4906                    enum_name: e1,
4907                    variant_name: v1,
4908                    fields: f1,
4909                },
4910                Value::Variant {
4911                    enum_name: e2,
4912                    variant_name: v2,
4913                    fields: f2,
4914                },
4915            ) => match op {
4916                BinOp::Eq => {
4917                    let eq = e1 == e2
4918                        && v1 == v2
4919                        && match (f1, f2) {
4920                            (None, None) => true,
4921                            (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
4922                            _ => false,
4923                        };
4924                    Ok(Value::Bool(eq))
4925                }
4926                BinOp::Ne => {
4927                    let eq = e1 == e2
4928                        && v1 == v2
4929                        && match (f1, f2) {
4930                            (None, None) => true,
4931                            (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
4932                            _ => false,
4933                        };
4934                    Ok(Value::Bool(!eq))
4935                }
4936                _ => Err(RuntimeError::new("Invalid variant operation")),
4937            },
4938            // Struct equality (by value for Cbit, by reference for others) and Tensor operations
4939            (
4940                Value::Struct {
4941                    name: n1,
4942                    fields: f1,
4943                },
4944                Value::Struct {
4945                    name: n2,
4946                    fields: f2,
4947                },
4948            ) => match op {
4949                BinOp::Eq => {
4950                    // For Cbit, compare by value (the __value__ field)
4951                    if n1 == "Cbit" && n2 == "Cbit" {
4952                        let v1 = f1.borrow().get("__value__").cloned();
4953                        let v2 = f2.borrow().get("__value__").cloned();
4954                        let eq = match (v1, v2) {
4955                            (Some(Value::Bool(a)), Some(Value::Bool(b))) => a == b,
4956                            (Some(Value::Int(a)), Some(Value::Int(b))) => a == b,
4957                            _ => Rc::ptr_eq(&f1, &f2),
4958                        };
4959                        Ok(Value::Bool(eq))
4960                    } else {
4961                        Ok(Value::Bool(n1 == n2 && Rc::ptr_eq(&f1, &f2)))
4962                    }
4963                }
4964                BinOp::Ne => {
4965                    // For Cbit, compare by value (the __value__ field)
4966                    if n1 == "Cbit" && n2 == "Cbit" {
4967                        let v1 = f1.borrow().get("__value__").cloned();
4968                        let v2 = f2.borrow().get("__value__").cloned();
4969                        let neq = match (v1, v2) {
4970                            (Some(Value::Bool(a)), Some(Value::Bool(b))) => a != b,
4971                            (Some(Value::Int(a)), Some(Value::Int(b))) => a != b,
4972                            _ => !Rc::ptr_eq(&f1, &f2),
4973                        };
4974                        Ok(Value::Bool(neq))
4975                    } else {
4976                        Ok(Value::Bool(n1 != n2 || !Rc::ptr_eq(&f1, &f2)))
4977                    }
4978                }
4979                // Tensor multiplication (element-wise for scalars)
4980                BinOp::Mul if n1 == "Tensor" && n2 == "Tensor" => {
4981                    // Get scalar values from both tensors using field helpers (no allocation)
4982                    let val1 = tensor_scalar_from_fields(&f1.borrow())
4983                        .ok_or_else(|| RuntimeError::new("left tensor has no scalar data"))?;
4984                    let val2 = tensor_scalar_from_fields(&f2.borrow())
4985                        .ok_or_else(|| RuntimeError::new("right tensor has no scalar data"))?;
4986                    // Result is a new Tensor with the product
4987                    let result = val1 * val2;
4988                    let mut fields = std::collections::HashMap::new();
4989                    fields.insert(
4990                        "shape".to_string(),
4991                        Value::Array(Rc::new(RefCell::new(vec![]))),
4992                    );
4993                    fields.insert(
4994                        "data".to_string(),
4995                        Value::Array(Rc::new(RefCell::new(vec![Value::Float(result)]))),
4996                    );
4997                    fields.insert("requires_grad".to_string(), Value::Bool(false));
4998                    fields.insert("_value".to_string(), Value::Float(result));
4999                    // Track computation for autodiff
5000                    fields.insert("_op".to_string(), Value::String(Rc::new("mul".to_string())));
5001                    fields.insert("_operand1".to_string(), Value::Float(val1));
5002                    fields.insert("_operand2".to_string(), Value::Float(val2));
5003                    Ok(Value::Struct {
5004                        name: "Tensor".to_string(),
5005                        fields: Rc::new(RefCell::new(fields)),
5006                    })
5007                }
5008                // Matrix multiplication (@)
5009                BinOp::MatMul if n1 == "Tensor" && n2 == "Tensor" => {
5010                    // Get shape and data from both tensors using field helpers (no allocation)
5011                    let f1_ref = f1.borrow();
5012                    let f2_ref = f2.borrow();
5013                    let shape1 = tensor_shape_from_fields(&f1_ref)
5014                        .ok_or_else(|| RuntimeError::new("left tensor has no shape"))?;
5015                    let shape2 = tensor_shape_from_fields(&f2_ref)
5016                        .ok_or_else(|| RuntimeError::new("right tensor has no shape"))?;
5017                    let data1 = tensor_data_from_fields(&f1_ref)
5018                        .ok_or_else(|| RuntimeError::new("left tensor has no data"))?;
5019                    let data2 = tensor_data_from_fields(&f2_ref)
5020                        .ok_or_else(|| RuntimeError::new("right tensor has no data"))?;
5021                    drop(f1_ref);
5022                    drop(f2_ref);
5023
5024                    // Matrix multiply: [m,n] @ [n,p] = [m,p]
5025                    let m = if shape1.len() >= 2 { shape1[0] } else { 1 };
5026                    let n1_dim = if shape1.len() >= 2 {
5027                        shape1[1]
5028                    } else if !shape1.is_empty() {
5029                        shape1[0]
5030                    } else {
5031                        1
5032                    };
5033                    let p = if shape2.len() >= 2 { shape2[1] } else { 1 };
5034
5035                    // Perform matrix multiplication
5036                    let mut result_data = vec![0.0; m * p];
5037                    for i in 0..m {
5038                        for j in 0..p {
5039                            let mut sum = 0.0;
5040                            for k in 0..n1_dim {
5041                                let a_idx = i * n1_dim + k;
5042                                let b_idx = k * p + j;
5043                                if a_idx < data1.len() && b_idx < data2.len() {
5044                                    sum += data1[a_idx] * data2[b_idx];
5045                                }
5046                            }
5047                            result_data[i * p + j] = sum;
5048                        }
5049                    }
5050
5051                    // Check if either operand requires grad
5052                    let left_requires_grad =
5053                        matches!(f1.borrow().get("requires_grad"), Some(Value::Bool(true)));
5054                    let right_requires_grad =
5055                        matches!(f2.borrow().get("requires_grad"), Some(Value::Bool(true)));
5056
5057                    // Build result tensor with __field__ naming convention
5058                    let mut fields = std::collections::HashMap::new();
5059                    let shape_arr = Value::Array(Rc::new(RefCell::new(vec![
5060                        Value::Int(m as i64),
5061                        Value::Int(p as i64),
5062                    ])));
5063                    let data_arr = Value::Array(Rc::new(RefCell::new(
5064                        result_data.into_iter().map(Value::Float).collect(),
5065                    )));
5066                    fields.insert("__shape__".to_string(), shape_arr.clone());
5067                    fields.insert("__data__".to_string(), data_arr.clone());
5068                    fields.insert("shape".to_string(), shape_arr);
5069                    fields.insert("data".to_string(), data_arr);
5070                    fields.insert(
5071                        "__requires_grad__".to_string(),
5072                        Value::Bool(left_requires_grad || right_requires_grad),
5073                    );
5074                    fields.insert(
5075                        "requires_grad".to_string(),
5076                        Value::Bool(left_requires_grad || right_requires_grad),
5077                    );
5078
5079                    // Store references to operands for backward pass (autograd)
5080                    if left_requires_grad {
5081                        // Store the left operand's fields Rc for gradient computation
5082                        fields.insert(
5083                            "_grad_left".to_string(),
5084                            Value::Struct {
5085                                name: "Tensor".to_string(),
5086                                fields: f1.clone(),
5087                            },
5088                        );
5089                    }
5090                    if right_requires_grad {
5091                        fields.insert(
5092                            "_grad_right".to_string(),
5093                            Value::Struct {
5094                                name: "Tensor".to_string(),
5095                                fields: f2.clone(),
5096                            },
5097                        );
5098                    }
5099                    fields.insert(
5100                        "_op".to_string(),
5101                        Value::String(Rc::new("matmul".to_string())),
5102                    );
5103
5104                    Ok(Value::Struct {
5105                        name: "Tensor".to_string(),
5106                        fields: Rc::new(RefCell::new(fields)),
5107                    })
5108                }
5109                // Hadamard (element-wise) product (⊙)
5110                BinOp::Hadamard if n1 == "Tensor" && n2 == "Tensor" => {
5111                    // Get shape and data from both tensors using field helpers (no allocation)
5112                    let f1_ref = f1.borrow();
5113                    let f2_ref = f2.borrow();
5114                    // Keep shape as Vec<Value> for result construction
5115                    let shape1 = match f1_ref.get("shape") {
5116                        Some(Value::Array(arr)) => arr.borrow().clone(),
5117                        _ => return Err(RuntimeError::new("left tensor has no shape")),
5118                    };
5119                    let data1 = tensor_data_from_fields(&f1_ref)
5120                        .ok_or_else(|| RuntimeError::new("left tensor has no data"))?;
5121                    let data2 = tensor_data_from_fields(&f2_ref)
5122                        .ok_or_else(|| RuntimeError::new("right tensor has no data"))?;
5123                    drop(f1_ref);
5124                    drop(f2_ref);
5125
5126                    // Element-wise multiplication
5127                    let result_data: Vec<Value> = data1
5128                        .iter()
5129                        .zip(data2.iter())
5130                        .map(|(a, b)| Value::Float(a * b))
5131                        .collect();
5132
5133                    let mut fields = std::collections::HashMap::new();
5134                    fields.insert(
5135                        "shape".to_string(),
5136                        Value::Array(Rc::new(RefCell::new(shape1))),
5137                    );
5138                    fields.insert(
5139                        "data".to_string(),
5140                        Value::Array(Rc::new(RefCell::new(result_data))),
5141                    );
5142                    fields.insert("requires_grad".to_string(), Value::Bool(false));
5143                    Ok(Value::Struct {
5144                        name: "Tensor".to_string(),
5145                        fields: Rc::new(RefCell::new(fields)),
5146                    })
5147                }
5148                // Tensor addition with broadcasting
5149                BinOp::Add if n1 == "Tensor" && n2 == "Tensor" => {
5150                    // Get shape and data from both tensors using field helpers (no allocation)
5151                    let f1_ref = f1.borrow();
5152                    let f2_ref = f2.borrow();
5153                    // Shape as i64 for size calculations
5154                    let shape1: Vec<i64> = tensor_shape_from_fields(&f1_ref)
5155                        .ok_or_else(|| RuntimeError::new("left tensor has no shape"))?
5156                        .iter()
5157                        .map(|&x| x as i64)
5158                        .collect();
5159                    let shape2: Vec<i64> = tensor_shape_from_fields(&f2_ref)
5160                        .ok_or_else(|| RuntimeError::new("right tensor has no shape"))?
5161                        .iter()
5162                        .map(|&x| x as i64)
5163                        .collect();
5164                    let data1 = tensor_data_from_fields(&f1_ref)
5165                        .ok_or_else(|| RuntimeError::new("left tensor has no data"))?;
5166                    let data2 = tensor_data_from_fields(&f2_ref)
5167                        .ok_or_else(|| RuntimeError::new("right tensor has no data"))?;
5168                    drop(f1_ref);
5169                    drop(f2_ref);
5170
5171                    // Broadcasting support: [2,1] + [2] or [2] + [2,1] etc.
5172                    let result_data: Vec<f64>;
5173                    let result_shape: Vec<Value>;
5174
5175                    // Get total elements in each tensor
5176                    let size1: i64 = shape1.iter().product();
5177                    let size2: i64 = shape2.iter().product();
5178
5179                    if size1 == size2 {
5180                        // Same size - element-wise addition
5181                        result_data = data1.iter().zip(data2.iter()).map(|(a, b)| a + b).collect();
5182                        result_shape = shape1.into_iter().map(Value::Int).collect();
5183                    } else if size1 > size2 && size1 % size2 == 0 {
5184                        // Broadcast data2 to match data1
5185                        result_data = data1
5186                            .iter()
5187                            .enumerate()
5188                            .map(|(i, a)| a + data2[i % data2.len()])
5189                            .collect();
5190                        result_shape = shape1.into_iter().map(Value::Int).collect();
5191                    } else if size2 > size1 && size2 % size1 == 0 {
5192                        // Broadcast data1 to match data2
5193                        result_data = data2
5194                            .iter()
5195                            .enumerate()
5196                            .map(|(i, b)| data1[i % data1.len()] + b)
5197                            .collect();
5198                        result_shape = shape2.into_iter().map(Value::Int).collect();
5199                    } else {
5200                        // Fallback: zip what we can
5201                        result_data = data1.iter().zip(data2.iter()).map(|(a, b)| a + b).collect();
5202                        result_shape = shape1.into_iter().map(Value::Int).collect();
5203                    }
5204
5205                    let mut fields = std::collections::HashMap::new();
5206                    fields.insert(
5207                        "shape".to_string(),
5208                        Value::Array(Rc::new(RefCell::new(result_shape))),
5209                    );
5210                    fields.insert(
5211                        "data".to_string(),
5212                        Value::Array(Rc::new(RefCell::new(
5213                            result_data.into_iter().map(Value::Float).collect(),
5214                        ))),
5215                    );
5216                    fields.insert("requires_grad".to_string(), Value::Bool(false));
5217                    Ok(Value::Struct {
5218                        name: "Tensor".to_string(),
5219                        fields: Rc::new(RefCell::new(fields)),
5220                    })
5221                }
5222                // Tensor product (⊗) for qubits
5223                BinOp::TensorProd if n1 == "Qubit" && n2 == "Qubit" => {
5224                    // |ψ₁⟩ ⊗ |ψ₂⟩ creates a 2-qubit register
5225                    // Get qubit states and merge them
5226                    let get_state = |f: &Rc<RefCell<HashMap<String, Value>>>| -> (u64, usize) {
5227                        let fields = f.borrow();
5228                        let state_id = match fields.get("__state_id__") {
5229                            Some(Value::Int(v)) => *v as u64,
5230                            _ => 0,
5231                        };
5232                        let idx = match fields.get("__qubit_idx__") {
5233                            Some(Value::Int(v)) => *v as usize,
5234                            _ => 0,
5235                        };
5236                        (state_id, idx)
5237                    };
5238
5239                    let (state_id1, _idx1) = get_state(&f1);
5240                    let (state_id2, _idx2) = get_state(&f2);
5241
5242                    // Use stdlib to merge states and create register
5243                    use crate::stdlib::{get_quantum_state, store_quantum_state, create_qregister_value};
5244
5245                    let state1 = get_quantum_state(state_id1);
5246                    let state2 = get_quantum_state(state_id2);
5247
5248                    let n_qubits = match (&state1, &state2) {
5249                        (Some(s1), Some(s2)) => {
5250                            // Compute tensor product of states
5251                            let combined = s1.tensor_product(s2);
5252                            let total = combined.num_qubits();
5253                            let new_id = store_quantum_state(combined);
5254                            return Ok(create_qregister_value(new_id, total));
5255                        }
5256                        _ => 2, // fallback to 2 qubits if states not found
5257                    };
5258
5259                    // Fallback: create a simple 2-qubit register
5260                    Ok(create_qregister_value(0, n_qubits))
5261                }
5262                _ => Err(RuntimeError::new("Invalid struct operation")),
5263            },
5264            (l, r) => Err(RuntimeError::new(format!(
5265                "Type mismatch in binary operation: {:?} {:?} {:?}",
5266                l, op, r
5267            ))),
5268        }
5269    }
5270
5271    fn int_binary_op(&self, a: i64, b: i64, op: &BinOp) -> Result<Value, RuntimeError> {
5272        Ok(match op {
5273            BinOp::Add => Value::Int(a + b),
5274            BinOp::Sub => Value::Int(a - b),
5275            BinOp::Mul => Value::Int(a * b),
5276            BinOp::Div => {
5277                if b == 0 {
5278                    return Err(RuntimeError::division_by_zero());
5279                }
5280                Value::Int(a / b)
5281            }
5282            BinOp::Rem => {
5283                if b == 0 {
5284                    return Err(RuntimeError::division_by_zero());
5285                }
5286                Value::Int(a % b)
5287            }
5288            BinOp::Pow => Value::Int(a.pow(b as u32)),
5289            BinOp::Eq => Value::Bool(a == b),
5290            BinOp::Ne => Value::Bool(a != b),
5291            BinOp::Lt => Value::Bool(a < b),
5292            BinOp::Le => Value::Bool(a <= b),
5293            BinOp::Gt => Value::Bool(a > b),
5294            BinOp::Ge => Value::Bool(a >= b),
5295            BinOp::BitAnd => Value::Int(a & b),
5296            BinOp::BitOr => Value::Int(a | b),
5297            BinOp::BitXor => Value::Int(a ^ b),
5298            BinOp::Shl => Value::Int(a << b),
5299            BinOp::Shr => Value::Int(a >> b),
5300            _ => return Err(RuntimeError::new("Invalid integer operation")),
5301        })
5302    }
5303
5304    fn float_binary_op(&self, a: f64, b: f64, op: &BinOp) -> Result<Value, RuntimeError> {
5305        Ok(match op {
5306            BinOp::Add => Value::Float(a + b),
5307            BinOp::Sub => Value::Float(a - b),
5308            BinOp::Mul => Value::Float(a * b),
5309            BinOp::Div => Value::Float(a / b),
5310            BinOp::Rem => Value::Float(a % b),
5311            BinOp::Pow => Value::Float(a.powf(b)),
5312            BinOp::Eq => Value::Bool(a == b),
5313            BinOp::Ne => Value::Bool(a != b),
5314            BinOp::Lt => Value::Bool(a < b),
5315            BinOp::Le => Value::Bool(a <= b),
5316            BinOp::Gt => Value::Bool(a > b),
5317            BinOp::Ge => Value::Bool(a >= b),
5318            _ => return Err(RuntimeError::new("Invalid float operation")),
5319        })
5320    }
5321
5322    fn eval_unary(&mut self, op: &UnaryOp, expr: &Expr) -> Result<Value, RuntimeError> {
5323        let val = self.evaluate(expr)?;
5324        // Auto-resolve zero-arg BuiltIn constants (PI, E, TAU, PHI) for unary ops
5325        let val = self.resolve_constant(val);
5326        match (op, &val) {
5327            (UnaryOp::Neg, Value::Int(n)) => Ok(Value::Int(-n)),
5328            (UnaryOp::Neg, Value::Float(n)) => Ok(Value::Float(-n)),
5329            (UnaryOp::Not, Value::Bool(b)) => Ok(Value::Bool(!b)),
5330            (UnaryOp::Not, Value::Int(n)) => Ok(Value::Int(!n)),
5331            // Handle evidential values - unwrap, negate, rewrap
5332            (UnaryOp::Not, Value::Evidential { value, evidence }) => {
5333                // Negate the inner value
5334                match value.as_ref() {
5335                    Value::Bool(b) => Ok(Value::Evidential {
5336                        value: Box::new(Value::Bool(!b)),
5337                        evidence: evidence.clone(),
5338                    }),
5339                    other => {
5340                        let truthy = self.is_truthy(other);
5341                        Ok(Value::Evidential {
5342                            value: Box::new(Value::Bool(!truthy)),
5343                            evidence: evidence.clone(),
5344                        })
5345                    }
5346                }
5347            }
5348            // Handle string truthiness (non-empty = true)
5349            (UnaryOp::Not, Value::String(s)) => Ok(Value::Bool(s.is_empty())),
5350            // Handle array truthiness (non-empty = true)
5351            (UnaryOp::Not, Value::Array(arr)) => Ok(Value::Bool(arr.borrow().is_empty())),
5352            // Handle null - null is falsy
5353            (UnaryOp::Not, Value::Null) => Ok(Value::Bool(true)),
5354            (UnaryOp::Ref, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
5355            (UnaryOp::RefMut, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
5356            (UnaryOp::Deref, Value::Ref(r)) => Ok(r.borrow().clone()),
5357            (UnaryOp::Deref, Value::Struct { name, fields }) if name == "Rc" => {
5358                // Deref Rc to get inner value
5359                let borrowed = fields.borrow();
5360                if let Some(value) = borrowed.get("_value") {
5361                    Ok(value.clone())
5362                } else {
5363                    Err(RuntimeError::new("Rc has no value"))
5364                }
5365            }
5366            (UnaryOp::Deref, other) => {
5367                // Try to unwrap evidential/affective wrappers and deref
5368                let unwrapped = Self::unwrap_all(&val);
5369                if let Value::Ref(r) = &unwrapped {
5370                    return Ok(r.borrow().clone());
5371                }
5372                // For non-ref types in interpreted code, just return the value as-is
5373                // (dereferencing a copy type in Sigil is a no-op)
5374                Ok(unwrapped)
5375            }
5376            _ => Err(RuntimeError::new(format!(
5377                "Invalid unary {:?} on {:?}",
5378                op,
5379                std::mem::discriminant(&val)
5380            ))),
5381        }
5382    }
5383
5384    fn eval_call(&mut self, func_expr: &Expr, args: &[Expr]) -> Result<Value, RuntimeError> {
5385        // Check if func_expr is a path that might be a variant constructor or tuple struct
5386        if let Expr::Path(path) = func_expr {
5387            let qualified_name = path
5388                .segments
5389                .iter()
5390                .map(|s| s.ident.name.as_str())
5391                .collect::<Vec<_>>()
5392                .join("·");
5393
5394            // Handle Self(...) as tuple struct constructor
5395            if qualified_name == "Self" {
5396                if let Some(ref self_type) = self.current_self_type {
5397                    // Check if this type is a tuple struct - extract arity first to release borrow
5398                    let tuple_arity = if let Some(TypeDef::Struct(struct_def)) =
5399                        self.types.get(self_type)
5400                    {
5401                        if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
5402                            Some((self_type.clone(), field_types.len()))
5403                        } else {
5404                            None
5405                        }
5406                    } else {
5407                        None
5408                    };
5409
5410                    if let Some((type_name, expected_arity)) = tuple_arity {
5411                        // Now we can safely evaluate arguments
5412                        let arg_values: Vec<Value> = args
5413                            .iter()
5414                            .map(|a| self.evaluate(a))
5415                            .collect::<Result<_, _>>()?;
5416
5417                        if arg_values.len() != expected_arity {
5418                            return Err(RuntimeError::new(format!(
5419                                "Tuple struct {} expects {} fields, got {}",
5420                                type_name,
5421                                expected_arity,
5422                                arg_values.len()
5423                            )));
5424                        }
5425
5426                        // Create struct with numbered fields (0, 1, 2, ...)
5427                        let mut fields = HashMap::new();
5428                        for (i, value) in arg_values.into_iter().enumerate() {
5429                            fields.insert(i.to_string(), value);
5430                        }
5431                        return Ok(Value::Struct {
5432                            name: type_name,
5433                            fields: Rc::new(RefCell::new(fields)),
5434                        });
5435                    }
5436                }
5437            }
5438
5439            // Handle TypeName(...) as tuple struct constructor
5440            if path.segments.len() == 1 {
5441                let type_name = &path.segments[0].ident.name;
5442                // Extract arity first to release borrow
5443                let tuple_arity =
5444                    if let Some(TypeDef::Struct(struct_def)) = self.types.get(type_name) {
5445                        if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
5446                            Some((type_name.clone(), field_types.len()))
5447                        } else {
5448                            None
5449                        }
5450                    } else {
5451                        None
5452                    };
5453
5454                if let Some((struct_name, expected_arity)) = tuple_arity {
5455                    let arg_values: Vec<Value> = args
5456                        .iter()
5457                        .map(|a| self.evaluate(a))
5458                        .collect::<Result<_, _>>()?;
5459
5460                    if arg_values.len() != expected_arity {
5461                        return Err(RuntimeError::new(format!(
5462                            "Tuple struct {} expects {} fields, got {}",
5463                            struct_name,
5464                            expected_arity,
5465                            arg_values.len()
5466                        )));
5467                    }
5468
5469                    let mut fields = HashMap::new();
5470                    for (i, value) in arg_values.into_iter().enumerate() {
5471                        fields.insert(i.to_string(), value);
5472                    }
5473                    return Ok(Value::Struct {
5474                        name: struct_name,
5475                        fields: Rc::new(RefCell::new(fields)),
5476                    });
5477                }
5478            }
5479
5480            // Handle Default::default() when current_self_type is set
5481            // This allows ..Default::default() to work in struct literals
5482            if qualified_name == "Default·default" && args.is_empty() {
5483                if let Some(type_name) = self.current_self_type.clone() {
5484                    // First check if type has impl Default with explicit default fn
5485                    let default_fn_name = format!("{}·default", type_name);
5486                    crate::sigil_debug!(
5487                        "DEBUG Default::default() looking for '{}', self_type='{}'",
5488                        default_fn_name,
5489                        type_name
5490                    );
5491                    let func_clone = self
5492                        .globals
5493                        .borrow()
5494                        .get(&default_fn_name)
5495                        .map(|v| v.clone());
5496                    if let Some(Value::Function(f)) = func_clone {
5497                        crate::sigil_debug!(
5498                            "DEBUG Found function '{}', calling it",
5499                            default_fn_name
5500                        );
5501                        crate::sigil_debug!(
5502                            "DEBUG current_self_type before call: {:?}",
5503                            self.current_self_type
5504                        );
5505                        // Call the type's default implementation
5506                        let result = self.call_function(&f, vec![]);
5507                        crate::sigil_debug!(
5508                            "DEBUG Default call result: {:?}",
5509                            result
5510                                .as_ref()
5511                                .map(|v| self.format_value(v))
5512                                .unwrap_or_else(|e| format!("ERR: {:?}", e))
5513                        );
5514                        return result;
5515                    }
5516                    // Otherwise check for #[derive(Default)]
5517                    if let Some(struct_def) = self.default_structs.get(&type_name).cloned() {
5518                        let mut fields = HashMap::new();
5519                        if let StructFields::Named(field_defs) = &struct_def.fields {
5520                            for field in field_defs {
5521                                let default_val = if let Some(default_expr) = &field.default {
5522                                    self.evaluate(default_expr)?
5523                                } else {
5524                                    Value::Null
5525                                };
5526                                fields.insert(field.name.name.clone(), default_val);
5527                            }
5528                        }
5529                        return Ok(Value::Struct {
5530                            name: type_name,
5531                            fields: Rc::new(RefCell::new(fields)),
5532                        });
5533                    }
5534                }
5535            }
5536
5537            // Check for TypeName·default pattern
5538            if qualified_name.ends_with("·default") && args.is_empty() {
5539                let type_name = qualified_name.strip_suffix("·default").unwrap();
5540                // First check if type has impl Default with explicit default fn
5541                let default_fn_name = format!("{}·default", type_name);
5542                let func_clone = self
5543                    .globals
5544                    .borrow()
5545                    .get(&default_fn_name)
5546                    .map(|v| v.clone());
5547                if let Some(Value::Function(f)) = func_clone {
5548                    // Set current_self_type so This resolves to the correct type
5549                    let old_self_type = self.current_self_type.clone();
5550                    self.current_self_type = Some(type_name.to_string());
5551
5552                    // Call the type's default implementation
5553                    let result = self.call_function(&f, vec![]);
5554
5555                    // Restore old self type
5556                    self.current_self_type = old_self_type;
5557                    return result;
5558                }
5559                // Otherwise check for #[derive(Default)]
5560                if let Some(struct_def) = self.default_structs.get(type_name).cloned() {
5561                    let mut fields = HashMap::new();
5562                    if let StructFields::Named(field_defs) = &struct_def.fields {
5563                        for field in field_defs {
5564                            let default_val = if let Some(default_expr) = &field.default {
5565                                self.evaluate(default_expr)?
5566                            } else {
5567                                // No default - use null for optional/uncertain types
5568                                Value::Null
5569                            };
5570                            fields.insert(field.name.name.clone(), default_val);
5571                        }
5572                    }
5573                    return Ok(Value::Struct {
5574                        name: type_name.to_string(),
5575                        fields: Rc::new(RefCell::new(fields)),
5576                    });
5577                }
5578            }
5579
5580            // Check variant constructors
5581            // Debug: trace variant lookup for Command
5582            if qualified_name.contains("Command") || qualified_name.contains("Analyze") {
5583                eprintln!("DEBUG variant lookup: qualified_name='{}'", qualified_name);
5584                eprintln!(
5585                    "  found in variant_constructors: {}",
5586                    self.variant_constructors.contains_key(&qualified_name)
5587                );
5588                // Show registered variants with Command in name
5589                for (k, v) in &self.variant_constructors {
5590                    if k.contains("Command") {
5591                        eprintln!("  registered: '{}' -> {:?}", k, v);
5592                    }
5593                }
5594            }
5595            if let Some((enum_name, variant_name, arity)) =
5596                self.variant_constructors.get(&qualified_name).cloned()
5597            {
5598                let arg_values: Vec<Value> = args
5599                    .iter()
5600                    .map(|a| self.evaluate(a))
5601                    .collect::<Result<_, _>>()?;
5602
5603                if arg_values.len() != arity {
5604                    return Err(RuntimeError::new(format!(
5605                        "{} expects {} arguments, got {}",
5606                        qualified_name,
5607                        arity,
5608                        arg_values.len()
5609                    )));
5610                }
5611
5612                if arity == 0 {
5613                    return Ok(Value::Variant {
5614                        enum_name,
5615                        variant_name,
5616                        fields: None,
5617                    });
5618                } else {
5619                    // Debug: trace variant creation for Result and Command
5620                    if enum_name == "Command" || enum_name == "Result" {
5621                        eprintln!(
5622                            "DEBUG creating {}::{} variant with {} args",
5623                            enum_name,
5624                            variant_name,
5625                            arg_values.len()
5626                        );
5627                        for (i, v) in arg_values.iter().enumerate() {
5628                            eprintln!("  arg[{}]: {}", i, self.format_value(v));
5629                        }
5630                    }
5631                    return Ok(Value::Variant {
5632                        enum_name,
5633                        variant_name,
5634                        fields: Some(Rc::new(arg_values)),
5635                    });
5636                }
5637            }
5638
5639            // Check for built-in type constructors (Map::new, String::new, HashMap::new, etc.)
5640            let segments: Vec<&str> = path
5641                .segments
5642                .iter()
5643                .map(|s| s.ident.name.as_str())
5644                .collect();
5645            match segments.as_slice() {
5646                ["Map", "new"] | ["HashMap", "new"] => {
5647                    // Create a new empty Map (represented as a struct with HashMap fields)
5648                    return Ok(Value::Struct {
5649                        name: "Map".to_string(),
5650                        fields: Rc::new(RefCell::new(HashMap::new())),
5651                    });
5652                }
5653                ["String", "new"] => {
5654                    return Ok(Value::String(Rc::new(String::new())));
5655                }
5656                ["Vec", "new"] | ["Array", "new"] => {
5657                    return Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))));
5658                }
5659                ["Box", "new"] => {
5660                    // Box::new(value) - just return the value (no heap allocation in interpreter)
5661                    if args.len() == 1 {
5662                        return self.evaluate(&args[0]);
5663                    }
5664                    return Err(RuntimeError::new("Box::new expects 1 argument"));
5665                }
5666                ["char", "from_u32"] => {
5667                    // char::from_u32(u32) -> Option<char>
5668                    if args.len() == 1 {
5669                        let arg = self.evaluate(&args[0])?;
5670                        let code = match arg {
5671                            Value::Int(i) => i as u32,
5672                            _ => return Err(RuntimeError::new("char::from_u32 expects u32")),
5673                        };
5674                        if let Some(c) = char::from_u32(code) {
5675                            // Return Some(char)
5676                            return Ok(Value::Variant {
5677                                enum_name: "Option".to_string(),
5678                                variant_name: "Some".to_string(),
5679                                fields: Some(Rc::new(vec![Value::Char(c)])),
5680                            });
5681                        } else {
5682                            // Return None
5683                            return Ok(Value::Variant {
5684                                enum_name: "Option".to_string(),
5685                                variant_name: "None".to_string(),
5686                                fields: None,
5687                            });
5688                        }
5689                    }
5690                    return Err(RuntimeError::new("char::from_u32 expects 1 argument"));
5691                }
5692                // Mutex::new - create a mutex wrapper around a value
5693                ["parking_lot", "Mutex", "new"]
5694                | ["std", "sync", "Mutex", "new"]
5695                | ["Mutex", "new"] => {
5696                    if args.len() == 1 {
5697                        let inner = self.evaluate(&args[0])?;
5698                        return Ok(Value::Struct {
5699                            name: "Mutex".to_string(),
5700                            fields: Rc::new(RefCell::new(HashMap::from([(
5701                                "__inner__".to_string(),
5702                                inner,
5703                            )]))),
5704                        });
5705                    }
5706                    return Err(RuntimeError::new("Mutex::new expects 1 argument"));
5707                }
5708                // RwLock::new - same as Mutex for interpreter purposes
5709                ["parking_lot", "RwLock", "new"]
5710                | ["std", "sync", "RwLock", "new"]
5711                | ["RwLock", "new"] => {
5712                    if args.len() == 1 {
5713                        let inner = self.evaluate(&args[0])?;
5714                        return Ok(Value::Struct {
5715                            name: "RwLock".to_string(),
5716                            fields: Rc::new(RefCell::new(HashMap::from([(
5717                                "__inner__".to_string(),
5718                                inner,
5719                            )]))),
5720                        });
5721                    }
5722                    return Err(RuntimeError::new("RwLock::new expects 1 argument"));
5723                }
5724                // Barrier::new - create a barrier synchronization primitive
5725                ["std", "sync", "Barrier", "new"] | ["Barrier", "new"] => {
5726                    if args.len() == 1 {
5727                        let count = self.evaluate(&args[0])?;
5728                        return Ok(Value::Struct {
5729                            name: "Barrier".to_string(),
5730                            fields: Rc::new(RefCell::new(HashMap::from([(
5731                                "__count__".to_string(),
5732                                count,
5733                            )]))),
5734                        });
5735                    }
5736                    return Err(RuntimeError::new("Barrier::new expects 1 argument"));
5737                }
5738                // Arc::new - just wrap the value (no real reference counting in interpreter)
5739                ["std", "sync", "Arc", "new"] | ["Arc", "new"] => {
5740                    if args.len() == 1 {
5741                        let inner = self.evaluate(&args[0])?;
5742                        return Ok(Value::Ref(Rc::new(RefCell::new(inner))));
5743                    }
5744                    return Err(RuntimeError::new("Arc::new expects 1 argument"));
5745                }
5746                // AtomicU64::new and similar atomics
5747                ["std", "sync", "atomic", "AtomicU64", "new"] | ["AtomicU64", "new"] => {
5748                    if args.len() == 1 {
5749                        let inner = self.evaluate(&args[0])?;
5750                        return Ok(Value::Struct {
5751                            name: "AtomicU64".to_string(),
5752                            fields: Rc::new(RefCell::new(HashMap::from([(
5753                                "__value__".to_string(),
5754                                inner,
5755                            )]))),
5756                        });
5757                    }
5758                    return Err(RuntimeError::new("AtomicU64::new expects 1 argument"));
5759                }
5760                ["std", "sync", "atomic", "AtomicUsize", "new"] | ["AtomicUsize", "new"] => {
5761                    if args.len() == 1 {
5762                        let inner = self.evaluate(&args[0])?;
5763                        return Ok(Value::Struct {
5764                            name: "AtomicUsize".to_string(),
5765                            fields: Rc::new(RefCell::new(HashMap::from([(
5766                                "__value__".to_string(),
5767                                inner,
5768                            )]))),
5769                        });
5770                    }
5771                    return Err(RuntimeError::new("AtomicUsize::new expects 1 argument"));
5772                }
5773                ["std", "sync", "atomic", "AtomicBool", "new"] | ["AtomicBool", "new"] => {
5774                    if args.len() == 1 {
5775                        let inner = self.evaluate(&args[0])?;
5776                        return Ok(Value::Struct {
5777                            name: "AtomicBool".to_string(),
5778                            fields: Rc::new(RefCell::new(HashMap::from([(
5779                                "__value__".to_string(),
5780                                inner,
5781                            )]))),
5782                        });
5783                    }
5784                    return Err(RuntimeError::new("AtomicBool::new expects 1 argument"));
5785                }
5786                // Linear::new() - neural network layer constructor
5787                ["Linear", "new"] => {
5788                    if args.is_empty() {
5789                        // First try to extract generics from turbofish syntax: Linear::<784, 256>::new()
5790                        let turbofish_generics: Option<(i64, i64)> =
5791                            if let Some(seg) = path.segments.first() {
5792                                if let Some(generics) = &seg.generics {
5793                                    let mut const_values: Vec<i64> = Vec::new();
5794                                    for generic in generics {
5795                                        if let crate::ast::TypeExpr::ConstExpr(expr) = generic {
5796                                            if let crate::ast::Expr::Literal(
5797                                                crate::ast::Literal::Int { value, .. },
5798                                            ) = expr.as_ref()
5799                                            {
5800                                                if let Ok(n) = value.parse::<i64>() {
5801                                                    const_values.push(n);
5802                                                }
5803                                            }
5804                                        }
5805                                        if let crate::ast::TypeExpr::Path(inner_path) = generic {
5806                                            if let Some(inner_seg) = inner_path.segments.first() {
5807                                                if let Ok(n) = inner_seg.ident.name.parse::<i64>() {
5808                                                    const_values.push(n);
5809                                                }
5810                                            }
5811                                        }
5812                                    }
5813                                    if const_values.len() >= 2 {
5814                                        Some((const_values[0], const_values[1]))
5815                                    } else {
5816                                        None
5817                                    }
5818                                } else {
5819                                    None
5820                                }
5821                            } else {
5822                                None
5823                            };
5824
5825                        // Use turbofish generics, or fall back to type annotation generics
5826                        let (in_features, out_features) = if let Some((i, o)) = turbofish_generics {
5827                            (i, o)
5828                        } else if let Some((name, generics)) =
5829                            self.type_context.struct_generics.borrow().clone()
5830                        {
5831                            if name == "Linear" && generics.len() >= 2 {
5832                                (generics[0], generics[1])
5833                            } else {
5834                                return Err(RuntimeError::new(
5835                                    "Linear::new requires type annotation like Linear<IN, OUT>",
5836                                ));
5837                            }
5838                        } else {
5839                            return Err(RuntimeError::new(
5840                                "Linear::new requires type annotation like Linear<IN, OUT>",
5841                            ));
5842                        };
5843
5844                        // Create weight tensor [OUT, IN] with random values
5845                        let weight_data: Vec<Value> = (0..(out_features * in_features))
5846                            .map(|_| Value::Float(rand::random::<f64>() * 2.0 - 1.0))
5847                            .collect();
5848                        let weight_shape = vec![Value::Int(out_features), Value::Int(in_features)];
5849                        let mut weight_fields = HashMap::new();
5850                        weight_fields.insert(
5851                            "data".to_string(),
5852                            Value::Array(Rc::new(RefCell::new(weight_data))),
5853                        );
5854                        weight_fields.insert(
5855                            "shape".to_string(),
5856                            Value::Array(Rc::new(RefCell::new(weight_shape))),
5857                        );
5858                        weight_fields.insert("requires_grad".to_string(), Value::Bool(true));
5859                        weight_fields.insert(
5860                            "grad".to_string(),
5861                            Value::Variant {
5862                                enum_name: "Option".to_string(),
5863                                variant_name: "None".to_string(),
5864                                fields: None,
5865                            },
5866                        );
5867
5868                        // Create bias tensor [OUT] with random values
5869                        let bias_data: Vec<Value> = (0..out_features)
5870                            .map(|_| Value::Float(rand::random::<f64>() * 2.0 - 1.0))
5871                            .collect();
5872                        let bias_shape = vec![Value::Int(out_features)];
5873                        let mut bias_fields = HashMap::new();
5874                        bias_fields.insert(
5875                            "data".to_string(),
5876                            Value::Array(Rc::new(RefCell::new(bias_data))),
5877                        );
5878                        bias_fields.insert(
5879                            "shape".to_string(),
5880                            Value::Array(Rc::new(RefCell::new(bias_shape))),
5881                        );
5882                        bias_fields.insert("requires_grad".to_string(), Value::Bool(true));
5883                        bias_fields.insert(
5884                            "grad".to_string(),
5885                            Value::Variant {
5886                                enum_name: "Option".to_string(),
5887                                variant_name: "None".to_string(),
5888                                fields: None,
5889                            },
5890                        );
5891
5892                        // Create Linear struct with weight and bias
5893                        let mut linear_fields = HashMap::new();
5894                        linear_fields.insert(
5895                            "weight".to_string(),
5896                            Value::Struct {
5897                                name: "Tensor".to_string(),
5898                                fields: Rc::new(RefCell::new(weight_fields)),
5899                            },
5900                        );
5901                        linear_fields.insert(
5902                            "bias".to_string(),
5903                            Value::Struct {
5904                                name: "Tensor".to_string(),
5905                                fields: Rc::new(RefCell::new(bias_fields)),
5906                            },
5907                        );
5908
5909                        return Ok(Value::Struct {
5910                            name: "Linear".to_string(),
5911                            fields: Rc::new(RefCell::new(linear_fields)),
5912                        });
5913                    }
5914                    return Err(RuntimeError::new("Linear::new takes no arguments"));
5915                }
5916                // ReLU::new() - activation layer constructor
5917                ["ReLU", "new"] => {
5918                    if args.is_empty() {
5919                        return Ok(Value::Struct {
5920                            name: "ReLU".to_string(),
5921                            fields: Rc::new(RefCell::new(HashMap::new())),
5922                        });
5923                    }
5924                    return Err(RuntimeError::new("ReLU::new takes no arguments"));
5925                }
5926                // Sequential::new([layers]) - container for layers
5927                ["Sequential", "new"] => {
5928                    // Check for user-defined Sequential·new first
5929                    let user_ctor = self.globals.borrow().get("Sequential·new").map(|v| v.clone());
5930                    if let Some(Value::Function(func)) = user_ctor {
5931                        let mut evaluated_args = Vec::new();
5932                        for arg in args {
5933                            evaluated_args.push(self.evaluate(arg)?);
5934                        }
5935                        return self.call_function(&func, evaluated_args);
5936                    }
5937                    if args.len() == 1 {
5938                        let layers = self.evaluate(&args[0])?;
5939                        let mut fields = HashMap::new();
5940                        fields.insert("layers".to_string(), layers);
5941                        return Ok(Value::Struct {
5942                            name: "Sequential".to_string(),
5943                            fields: Rc::new(RefCell::new(fields)),
5944                        });
5945                    }
5946                    return Err(RuntimeError::new(
5947                        "Sequential::new expects an array of layers",
5948                    ));
5949                }
5950                _ => {}
5951            }
5952        }
5953
5954        // If calling a qualified function (Type::method), set current_self_type
5955        let type_name_for_self = if let Expr::Path(path) = func_expr {
5956            if path.segments.len() >= 2 {
5957                // First segment is the type name
5958                let first = &path.segments[0].ident.name;
5959                // Check if it's a type name (exists in types registry)
5960                if self.types.contains_key(first) {
5961                    Some(first.clone())
5962                } else {
5963                    None
5964                }
5965            } else {
5966                None
5967            }
5968        } else {
5969            None
5970        };
5971
5972        // Debug: trace function lookup for Result
5973        if let Expr::Path(path) = func_expr {
5974            let path_str = path
5975                .segments
5976                .iter()
5977                .map(|s| s.ident.name.as_str())
5978                .collect::<Vec<_>>()
5979                .join("·");
5980            if path_str.contains("Result") {
5981                eprintln!(
5982                    "DEBUG func lookup: path='{}', looking up in globals...",
5983                    path_str
5984                );
5985            }
5986        }
5987        let func = self.evaluate(func_expr)?;
5988        // Debug: trace what we got
5989        if let Expr::Path(path) = func_expr {
5990            let path_str = path
5991                .segments
5992                .iter()
5993                .map(|s| s.ident.name.as_str())
5994                .collect::<Vec<_>>()
5995                .join("·");
5996            if path_str.contains("Result") {
5997                eprintln!(
5998                    "DEBUG func lookup result: path='{}', value={}",
5999                    path_str,
6000                    self.format_value(&func)
6001                );
6002            }
6003        }
6004
6005        // Track &mut path arguments for sync-back after function call
6006        // This enables proper mutable reference semantics where modifications persist
6007        let mut mut_ref_sync: Vec<(String, Rc<RefCell<Value>>)> = Vec::new();
6008
6009        // Track named arguments for reordering: (name, value) pairs
6010        // Positional args have None as name
6011        let mut arg_entries: Vec<(Option<String>, Value)> = Vec::new();
6012        for arg in args.iter() {
6013            // Check if this is a named argument
6014            let (arg_name, inner_arg) = if let Expr::NamedArg { name, value } = arg {
6015                (Some(name.name.clone()), value.as_ref())
6016            } else {
6017                (None, arg)
6018            };
6019
6020            let val = self.evaluate(inner_arg)?;
6021
6022            // If this was a &mut path expression, track it for sync-back
6023            if let Expr::Unary {
6024                op: crate::ast::UnaryOp::RefMut,
6025                expr,
6026            } = inner_arg
6027            {
6028                if let Expr::Path(path) = expr.as_ref() {
6029                    if path.segments.len() == 1 {
6030                        let var_name = path.segments[0].ident.name.clone();
6031                        if let Value::Ref(r) = &val {
6032                            mut_ref_sync.push((var_name, r.clone()));
6033                        }
6034                    }
6035                }
6036            }
6037
6038            arg_entries.push((arg_name, val));
6039        }
6040
6041        // Set Self type if we're calling a type-associated function
6042        // Use clone instead of take to preserve for nested calls that don't set a type
6043        let old_self_type = self.current_self_type.clone();
6044        if let Some(type_name) = type_name_for_self {
6045            self.current_self_type = Some(type_name);
6046        }
6047
6048        // Extract turbofish type arguments from the call expression's path segments
6049        // e.g., dtype_info·<F16>() → type_args = ["F16"]
6050        let turbofish_type_args: Vec<String> = if let Expr::Path(path) = func_expr {
6051            path.segments
6052                .iter()
6053                .filter_map(|seg| seg.generics.as_ref())
6054                .flat_map(|generics| {
6055                    generics.iter().filter_map(|ty| {
6056                        if let crate::ast::TypeExpr::Path(tp) = ty {
6057                            Some(
6058                                tp.segments
6059                                    .iter()
6060                                    .map(|s| s.ident.name.as_str())
6061                                    .collect::<Vec<_>>()
6062                                    .join("·"),
6063                            )
6064                        } else {
6065                            None
6066                        }
6067                    })
6068                })
6069                .collect()
6070        } else {
6071            Vec::new()
6072        };
6073
6074        // Extract turbofish CONST generic values from the call expression's path segments
6075        // e.g., FixedVec·<5>·new() → const_args = [("N", 5)] using const_generic_params
6076        let turbofish_const_bindings: Vec<(String, Value)> = if let Expr::Path(path) = func_expr {
6077            let mut bindings = Vec::new();
6078            for seg in &path.segments {
6079                if let Some(generics) = &seg.generics {
6080                    if let Some(param_names) = self.const_generic_params.get(seg.ident.name.as_str()).cloned() {
6081                        let mut idx = 0;
6082                        for generic in generics {
6083                            if idx >= param_names.len() { break; }
6084                            let val = match generic {
6085                                crate::ast::TypeExpr::ConstExpr(expr) => {
6086                                    if let crate::ast::Expr::Literal(crate::ast::Literal::Int { value, .. }) = expr.as_ref() {
6087                                        value.parse::<i64>().ok()
6088                                    } else { None }
6089                                }
6090                                crate::ast::TypeExpr::Path(inner_path) => {
6091                                    if let Some(inner_seg) = inner_path.segments.first() {
6092                                        inner_seg.ident.name.parse::<i64>().ok()
6093                                    } else { None }
6094                                }
6095                                _ => None,
6096                            };
6097                            if let Some(v) = val {
6098                                bindings.push((param_names[idx].clone(), Value::Int(v)));
6099                                idx += 1;
6100                            }
6101                        }
6102                    }
6103                }
6104            }
6105            bindings
6106        } else {
6107            Vec::new()
6108        };
6109
6110        // Save and bind generic type parameters from turbofish (restore after call)
6111        let old_generic_bindings = self.generic_type_bindings.clone();
6112        if !turbofish_type_args.is_empty() {
6113            if let Value::Function(ref f) = func {
6114                for (param_name, concrete_type) in
6115                    f.generic_params.iter().zip(turbofish_type_args.iter())
6116                {
6117                    self.generic_type_bindings
6118                        .insert(param_name.clone(), concrete_type.clone());
6119                }
6120            }
6121        }
6122
6123        // If turbofish has const generic bindings, also set type_context.struct_generics
6124        // so that struct literals inside constructors (e.g., FixedVec { data: v }) get
6125        // the const generic hidden fields injected
6126        let prev_struct_generics = self.type_context.struct_generics.borrow().clone();
6127        if !turbofish_const_bindings.is_empty() {
6128            if let Expr::Path(path) = func_expr {
6129                if let Some(seg) = path.segments.first() {
6130                    let type_name = seg.ident.name.clone();
6131                    let const_values: Vec<i64> = turbofish_const_bindings.iter()
6132                        .filter_map(|(_, v)| if let Value::Int(n) = v { Some(*n) } else { None })
6133                        .collect();
6134                    if !const_values.is_empty() {
6135                        *self.type_context.struct_generics.borrow_mut() = Some((type_name, const_values));
6136                    }
6137                }
6138            }
6139        }
6140
6141        let result = match func {
6142            Value::Function(f) => {
6143                // Wrap with const generic bindings from turbofish if present
6144                let f = if turbofish_const_bindings.is_empty() {
6145                    f
6146                } else {
6147                    let wrapper_env = Rc::new(RefCell::new(
6148                        Environment::with_parent(f.closure.clone())
6149                    ));
6150                    for (name, value) in &turbofish_const_bindings {
6151                        wrapper_env.borrow_mut().define(name.clone(), value.clone());
6152                    }
6153                    Rc::new(Function {
6154                        name: f.name.clone(),
6155                        params: f.params.clone(),
6156                        body: f.body.clone(),
6157                        closure: wrapper_env,
6158                        generic_params: f.generic_params.clone(),
6159                    })
6160                };
6161                // Reorder arguments based on named parameters
6162                let arg_values = Self::reorder_named_args(&f.params, arg_entries)?;
6163                self.call_function(&f, arg_values)
6164            }
6165            Value::BuiltIn(b) => {
6166                // Built-ins don't support named params yet, just extract values
6167                let arg_values: Vec<Value> = arg_entries.into_iter().map(|(_, v)| v).collect();
6168                self.call_builtin(&b, arg_values)
6169            }
6170            // Handle constructor markers for unknown external types
6171            Value::Struct { ref name, .. } if name.starts_with("__constructor__") => {
6172                let actual_type = name.strip_prefix("__constructor__").unwrap();
6173                // Create an empty struct for the unknown type
6174                Ok(Value::Struct {
6175                    name: actual_type.to_string(),
6176                    fields: Rc::new(RefCell::new(HashMap::new())),
6177                })
6178            }
6179            // Auto-deref Value::Ref wrapping a function/closure (e.g., &rite(f64)->f64)
6180            Value::Ref(r) => {
6181                let inner = r.borrow().clone();
6182                match inner {
6183                    Value::Function(f) => {
6184                        let arg_values = Self::reorder_named_args(&f.params, arg_entries)?;
6185                        self.call_function(&f, arg_values)
6186                    }
6187                    Value::BuiltIn(b) => {
6188                        let arg_values: Vec<Value> = arg_entries.into_iter().map(|(_, v)| v).collect();
6189                        self.call_builtin(&b, arg_values)
6190                    }
6191                    _ => {
6192                        crate::sigil_debug!(
6193                            "DEBUG Cannot call non-function (deref'd Ref): {:?}",
6194                            inner
6195                        );
6196                        Err(RuntimeError::new("Cannot call non-function"))
6197                    }
6198                }
6199            }
6200            _ => {
6201                crate::sigil_debug!(
6202                    "DEBUG Cannot call non-function: {:?}, expr: {:?}",
6203                    func,
6204                    func_expr
6205                );
6206                Err(RuntimeError::new("Cannot call non-function"))
6207            }
6208        };
6209
6210        // Sync mutable references back to original variables
6211        // This is what makes `fn foo(x: &mut T)` actually modify the caller's variable
6212        for (var_name, ref_val) in mut_ref_sync {
6213            let current_value = ref_val.borrow().clone();
6214            let _ = self.environment.borrow_mut().set(&var_name, current_value);
6215        }
6216
6217        // Restore old Self type, generic type bindings, and struct generics context
6218        self.current_self_type = old_self_type;
6219        self.generic_type_bindings = old_generic_bindings;
6220        *self.type_context.struct_generics.borrow_mut() = prev_struct_generics;
6221
6222        result
6223    }
6224
6225    pub fn call_function(
6226        &mut self,
6227        func: &Function,
6228        args: Vec<Value>,
6229    ) -> Result<Value, RuntimeError> {
6230        // Debug trace for relevant functions
6231        if func.name.as_ref().map_or(false, |n| {
6232            n.contains("read_source")
6233                || n.contains("parse_file")
6234                || n.contains("load_from_file")
6235                || n.contains("read_to_string")
6236        }) {
6237            crate::sigil_debug!(
6238                "DEBUG call_function: name={:?}, params={:?}",
6239                func.name,
6240                func.params
6241            );
6242            for (i, arg) in args.iter().enumerate() {
6243                crate::sigil_debug!("  arg[{}] = {:?}", i, arg);
6244            }
6245        }
6246        if args.len() != func.params.len() {
6247            return Err(RuntimeError::new(format!(
6248                "Expected {} arguments, got {} (func={:?}, params={:?})",
6249                func.params.len(),
6250                args.len(),
6251                func.name,
6252                func.params
6253            )));
6254        }
6255
6256        // Debug: trace calls to keyword_or_ident
6257        if func.params.iter().any(|p| p == "name") {
6258            for arg in &args {
6259                let unwrapped = Self::unwrap_all(arg);
6260                if let Value::String(s) = &unwrapped {
6261                    if s.len() <= 10 {
6262                        crate::sigil_debug!("DEBUG call_function(name='{}')", s);
6263                    }
6264                }
6265            }
6266        }
6267
6268        // Create new environment for function
6269        let env = Rc::new(RefCell::new(Environment::with_parent(func.closure.clone())));
6270
6271        // Bind parameters, auto-resolving zero-arg BuiltIn constants
6272        for (param, value) in func.params.iter().zip(args) {
6273            let value = self.resolve_constant(value);
6274            // Debug: trace path parameter binding
6275            if param == "path" {
6276                crate::sigil_debug!(
6277                    "DEBUG call_function func={:?} binding param 'path' = {:?}",
6278                    func.name,
6279                    value
6280                );
6281            }
6282            env.borrow_mut().define(param.clone(), value);
6283        }
6284
6285        // Execute function body
6286        let prev_env = self.environment.clone();
6287        self.environment = env;
6288
6289        // Save and reset linear state for this function scope
6290        // Linear type tracking should be per-function, not global
6291        let prev_linear_consumed = std::mem::take(&mut *self.linear_state.consumed.borrow_mut());
6292        let prev_linear_vars = std::mem::take(&mut *self.linear_state.vars.borrow_mut());
6293
6294        let result = match self.evaluate(&func.body) {
6295            Ok(val) => Ok(val),
6296            Err(e) if e.message == "return" => {
6297                // Extract return value from stored location
6298                Ok(self.return_value.take().unwrap_or(Value::Null))
6299            }
6300            Err(e) => Err(e),
6301        };
6302
6303        // Check for unused linear variables before restoring state
6304        if result.is_ok() {
6305            let unused_var = {
6306                let vars = self.linear_state.vars.borrow();
6307                let consumed = self.linear_state.consumed.borrow();
6308                vars.iter()
6309                    .find(|v| !consumed.contains(*v))
6310                    .cloned()
6311            };
6312            if let Some(var_name) = unused_var {
6313                *self.linear_state.consumed.borrow_mut() = prev_linear_consumed;
6314                *self.linear_state.vars.borrow_mut() = prev_linear_vars;
6315                self.environment = prev_env;
6316                return Err(RuntimeError::new(format!(
6317                    "linear variable '{}' was declared but never used (linear types must be consumed exactly once)",
6318                    var_name
6319                )));
6320            }
6321        }
6322
6323        // Restore previous linear state
6324        *self.linear_state.consumed.borrow_mut() = prev_linear_consumed;
6325        *self.linear_state.vars.borrow_mut() = prev_linear_vars;
6326
6327        self.environment = prev_env;
6328        result
6329    }
6330
6331    fn call_builtin(
6332        &mut self,
6333        builtin: &BuiltInFn,
6334        args: Vec<Value>,
6335    ) -> Result<Value, RuntimeError> {
6336        if let Some(arity) = builtin.arity {
6337            if args.len() != arity {
6338                return Err(RuntimeError::new(format!(
6339                    "{}() expects {} arguments, got {}",
6340                    builtin.name,
6341                    arity,
6342                    args.len()
6343                )));
6344            }
6345        }
6346        // Auto-resolve zero-arg BuiltIn constants (PI, E, TAU, PHI) passed as arguments
6347        let args: Vec<Value> = args.into_iter().map(|v| self.resolve_constant(v)).collect();
6348        (builtin.func)(self, args)
6349    }
6350
6351    /// Auto-call zero-arg BuiltIn functions to resolve them to their constant values.
6352    /// This allows PI, E, TAU, PHI to work as bare values in any context.
6353    fn resolve_constant(&mut self, val: Value) -> Value {
6354        match &val {
6355            Value::BuiltIn(b) if b.arity == Some(0) => {
6356                (b.func)(self, vec![]).unwrap_or(val)
6357            }
6358            _ => val,
6359        }
6360    }
6361
6362    /// Reorder arguments based on named parameters to match function signature
6363    /// Positional args (None names) fill slots in order, named args go to their designated slots
6364    fn reorder_named_args(
6365        params: &[String],
6366        arg_entries: Vec<(Option<String>, Value)>,
6367    ) -> Result<Vec<Value>, RuntimeError> {
6368        // If no named args, just return values in order
6369        if arg_entries.iter().all(|(name, _)| name.is_none()) {
6370            return Ok(arg_entries.into_iter().map(|(_, v)| v).collect());
6371        }
6372
6373        // Build result array with slots for each parameter
6374        let mut result: Vec<Option<Value>> = vec![None; params.len()];
6375        let mut positional_idx = 0;
6376
6377        for (arg_name, value) in arg_entries {
6378            if let Some(name) = arg_name {
6379                // Named arg: find the parameter position
6380                if let Some(pos) = params.iter().position(|p| p == &name) {
6381                    if result[pos].is_some() {
6382                        return Err(RuntimeError::new(format!(
6383                            "argument '{}' specified multiple times",
6384                            name
6385                        )));
6386                    }
6387                    result[pos] = Some(value);
6388                } else {
6389                    return Err(RuntimeError::new(format!(
6390                        "unknown parameter name: '{}'",
6391                        name
6392                    )));
6393                }
6394            } else {
6395                // Positional arg: fill next available slot
6396                while positional_idx < result.len() && result[positional_idx].is_some() {
6397                    positional_idx += 1;
6398                }
6399                if positional_idx >= result.len() {
6400                    return Err(RuntimeError::new("too many positional arguments"));
6401                }
6402                result[positional_idx] = Some(value);
6403                positional_idx += 1;
6404            }
6405        }
6406
6407        // Check all parameters are filled
6408        for (i, slot) in result.iter().enumerate() {
6409            if slot.is_none() {
6410                return Err(RuntimeError::new(format!(
6411                    "missing argument for parameter '{}'",
6412                    params[i]
6413                )));
6414            }
6415        }
6416
6417        Ok(result.into_iter().map(|v| v.unwrap()).collect())
6418    }
6419
6420    /// Await a value - if it's a future, resolve it; otherwise return as-is
6421    pub fn await_value(&mut self, value: Value) -> Result<Value, RuntimeError> {
6422        match value {
6423            Value::Future(fut) => {
6424                let mut fut_inner = fut.borrow_mut();
6425                self.poll_future(&mut fut_inner)
6426            }
6427            // Non-futures return immediately
6428            other => Ok(other),
6429        }
6430    }
6431
6432    /// Unwrap a Result or Option value with configurable error handling
6433    /// - propagate_errors: if true, return error on Err/None; if false, just unwrap
6434    /// - panic_on_error: if true, panic instead of returning error
6435    fn unwrap_result_or_option(
6436        &self,
6437        value: Value,
6438        propagate_errors: bool,
6439        panic_on_error: bool,
6440    ) -> Result<Value, RuntimeError> {
6441        // First, determine what kind of value we have and extract any inner value
6442        let (is_ok_or_some, is_err, is_none, inner_val) = match &value {
6443            Value::Struct { name, fields } if name == "Ok" || name == "Some" => {
6444                let borrowed = fields.borrow();
6445                let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
6446                (true, false, false, inner)
6447            }
6448            Value::Struct { name, fields } if name == "Err" => {
6449                let borrowed = fields.borrow();
6450                let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
6451                (false, true, false, inner)
6452            }
6453            Value::Struct { name, .. } if name == "None" => (false, false, true, None),
6454            _ => return Ok(value),
6455        };
6456
6457        if is_ok_or_some {
6458            Ok(inner_val.unwrap_or(value))
6459        } else if is_err {
6460            let msg = format!("Error: {:?}", inner_val);
6461            if panic_on_error {
6462                panic!("{}", msg);
6463            } else if propagate_errors {
6464                Err(RuntimeError::new(msg))
6465            } else {
6466                Ok(inner_val.unwrap_or(value))
6467            }
6468        } else if is_none {
6469            if panic_on_error {
6470                panic!("Unwrapped None");
6471            } else if propagate_errors {
6472                Err(RuntimeError::new("Unwrapped None".to_string()))
6473            } else {
6474                Ok(value)
6475            }
6476        } else {
6477            Ok(value)
6478        }
6479    }
6480
6481    /// Poll a future to completion
6482    fn poll_future(&mut self, fut: &mut FutureInner) -> Result<Value, RuntimeError> {
6483        // Check if already resolved
6484        match &fut.state {
6485            FutureState::Ready(v) => return Ok((**v).clone()),
6486            FutureState::Failed(e) => return Err(RuntimeError::new(e.clone())),
6487            _ => {}
6488        }
6489
6490        // Check if it's a timer future
6491        if let Some(complete_at) = fut.complete_at {
6492            if std::time::Instant::now() >= complete_at {
6493                fut.state = FutureState::Ready(Box::new(Value::Null));
6494                return Ok(Value::Null);
6495            } else {
6496                // Timer not complete - in interpreter, we just sleep
6497                let remaining = complete_at - std::time::Instant::now();
6498                std::thread::sleep(remaining);
6499                fut.state = FutureState::Ready(Box::new(Value::Null));
6500                return Ok(Value::Null);
6501            }
6502        }
6503
6504        // Execute computation if pending
6505        if let Some(computation) = fut.computation.take() {
6506            fut.state = FutureState::Running;
6507
6508            match computation {
6509                FutureComputation::Immediate(v) => {
6510                    fut.state = FutureState::Ready(v.clone());
6511                    Ok((*v).clone())
6512                }
6513                FutureComputation::Timer(duration) => {
6514                    // Sleep for the duration
6515                    std::thread::sleep(duration);
6516                    fut.state = FutureState::Ready(Box::new(Value::Null));
6517                    Ok(Value::Null)
6518                }
6519                FutureComputation::Lazy { func, args } => {
6520                    // Execute the function
6521                    match self.call_function(&func, args) {
6522                        Ok(result) => {
6523                            fut.state = FutureState::Ready(Box::new(result.clone()));
6524                            Ok(result)
6525                        }
6526                        Err(e) => {
6527                            fut.state = FutureState::Failed(e.message.clone());
6528                            Err(e)
6529                        }
6530                    }
6531                }
6532                FutureComputation::Join(futures) => {
6533                    // Await all futures and collect results
6534                    let mut results = Vec::new();
6535                    for f in futures {
6536                        let mut f_inner = f.borrow_mut();
6537                        results.push(self.poll_future(&mut f_inner)?);
6538                    }
6539                    let result = Value::Array(Rc::new(RefCell::new(results)));
6540                    fut.state = FutureState::Ready(Box::new(result.clone()));
6541                    Ok(result)
6542                }
6543                FutureComputation::Race(futures) => {
6544                    // Return first completed future
6545                    // In interpreter, just poll in order
6546                    for f in futures {
6547                        let f_inner = f.borrow_mut();
6548                        if matches!(f_inner.state, FutureState::Ready(_)) {
6549                            if let FutureState::Ready(v) = &f_inner.state {
6550                                fut.state = FutureState::Ready(v.clone());
6551                                return Ok((**v).clone());
6552                            }
6553                        }
6554                    }
6555                    // None ready, poll first one
6556                    Err(RuntimeError::new("No futures ready in race"))
6557                }
6558            }
6559        } else {
6560            // No computation - return current state
6561            match &fut.state {
6562                FutureState::Ready(v) => Ok((**v).clone()),
6563                FutureState::Failed(e) => Err(RuntimeError::new(e.clone())),
6564                _ => Err(RuntimeError::new("Future has no computation")),
6565            }
6566        }
6567    }
6568
6569    /// Create a new future from a value
6570    pub fn make_future_immediate(&self, value: Value) -> Value {
6571        Value::Future(Rc::new(RefCell::new(FutureInner {
6572            state: FutureState::Ready(Box::new(value)),
6573            computation: None,
6574            complete_at: None,
6575        })))
6576    }
6577
6578    /// Create a pending future with lazy computation
6579    pub fn make_future_lazy(&self, func: Rc<Function>, args: Vec<Value>) -> Value {
6580        Value::Future(Rc::new(RefCell::new(FutureInner {
6581            state: FutureState::Pending,
6582            computation: Some(FutureComputation::Lazy { func, args }),
6583            complete_at: None,
6584        })))
6585    }
6586
6587    /// Create a timer future
6588    pub fn make_future_timer(&self, duration: std::time::Duration) -> Value {
6589        Value::Future(Rc::new(RefCell::new(FutureInner {
6590            state: FutureState::Pending,
6591            computation: Some(FutureComputation::Timer(duration)),
6592            complete_at: Some(std::time::Instant::now() + duration),
6593        })))
6594    }
6595
6596    fn eval_array(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
6597        let values: Vec<Value> = elements
6598            .iter()
6599            .map(|e| self.evaluate(e))
6600            .collect::<Result<_, _>>()?;
6601        Ok(Value::Array(Rc::new(RefCell::new(values))))
6602    }
6603
6604    fn eval_tuple(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
6605        let values: Vec<Value> = elements
6606            .iter()
6607            .map(|e| self.evaluate(e))
6608            .collect::<Result<_, _>>()?;
6609        Ok(Value::Tuple(Rc::new(values)))
6610    }
6611
6612    fn eval_block(&mut self, block: &Block) -> Result<Value, RuntimeError> {
6613        let env = Rc::new(RefCell::new(Environment::with_parent(
6614            self.environment.clone(),
6615        )));
6616        let prev_env = self.environment.clone();
6617        self.environment = env;
6618
6619        let mut result = Value::Null;
6620
6621        for stmt in &block.stmts {
6622            match stmt {
6623                Stmt::Let { pattern, ty, init } => {
6624                    // Extract tensor shape from type annotation for type-directed construction
6625                    if let Some(type_expr) = ty {
6626                        if let Some(shape) = self.extract_tensor_shape(type_expr) {
6627                            *self.type_context.tensor_shape.borrow_mut() = Some(shape);
6628                        }
6629                        // Extract struct generics for type-directed construction like Linear<3, 2>::new()
6630                        if let Some((name, generics)) = self.extract_struct_generics(type_expr) {
6631                            *self.type_context.struct_generics.borrow_mut() =
6632                                Some((name, generics));
6633                        }
6634                    }
6635                    let value = match init {
6636                        Some(expr) => self.evaluate(expr)?,
6637                        None => Value::Null,
6638                    };
6639                    // Clear expected tensor shape and struct generics after evaluation
6640                    *self.type_context.tensor_shape.borrow_mut() = None;
6641                    *self.type_context.struct_generics.borrow_mut() = None;
6642                    // Check if this is a linear type annotation
6643                    if let Some(type_expr) = ty {
6644                        if matches!(type_expr, crate::ast::TypeExpr::Linear(_)) {
6645                            // Track the variable name as linear
6646                            if let Pattern::Ident { name, .. } = pattern {
6647                                self.linear_state
6648                                    .vars
6649                                    .borrow_mut()
6650                                    .insert(name.name.clone());
6651                            }
6652                        }
6653                    }
6654                    // Check generic type parameter match for Option<T>/Result<T,E>
6655                    if let Some(type_expr) = ty {
6656                        if let Some((type_name, type_params)) = self.extract_type_params(type_expr)
6657                        {
6658                            self.check_generic_type_match(&type_name, &type_params, &value)?;
6659                            // Store Vec<T> type info for push type checking
6660                            if type_name == "Vec" && !type_params.is_empty() {
6661                                if let Pattern::Ident { name, .. } = pattern {
6662                                    self.var_types.borrow_mut().insert(
6663                                        name.name.clone(),
6664                                        (type_name.clone(), type_params.clone()),
6665                                    );
6666                                }
6667                            }
6668                        }
6669                    }
6670                    self.bind_pattern(pattern, value)?;
6671                }
6672                Stmt::LetElse {
6673                    pattern,
6674                    init,
6675                    else_branch,
6676                    ..
6677                } => {
6678                    let value = self.evaluate(init)?;
6679                    // Try to bind pattern, if it fails, execute else branch
6680                    if self.bind_pattern(pattern, value.clone()).is_err() {
6681                        return self.evaluate(else_branch);
6682                    }
6683                }
6684                Stmt::Expr(expr) => {
6685                    result = self.evaluate(expr)?;
6686                }
6687                Stmt::Semi(expr) => {
6688                    self.evaluate(expr)?;
6689                    result = Value::Null;
6690                }
6691                Stmt::Item(item) => {
6692                    self.execute_item(item)?;
6693                }
6694            }
6695        }
6696
6697        if let Some(expr) = &block.expr {
6698            result = self.evaluate(expr)?;
6699        }
6700
6701        // RAII: Call Drop::drop() on values going out of scope
6702        // Collect values to drop (avoid borrowing self during iteration)
6703        let values_to_drop: Vec<(String, Value)> = self
6704            .environment
6705            .borrow()
6706            .values
6707            .iter()
6708            .filter_map(|(name, value)| {
6709                if let Value::Struct {
6710                    name: struct_name, ..
6711                } = value
6712                {
6713                    if self.drop_types.contains(struct_name) {
6714                        return Some((name.clone(), value.clone()));
6715                    }
6716                }
6717                None
6718            })
6719            .collect();
6720
6721        // Call drop on each value
6722        for (_var_name, value) in values_to_drop {
6723            if let Value::Struct {
6724                name: struct_name, ..
6725            } = &value
6726            {
6727                let drop_fn_name = format!("{}·drop", struct_name);
6728                // Clone the function out of globals to avoid borrow issues
6729                let drop_fn = self.globals.borrow().get(&drop_fn_name).map(|v| v.clone());
6730                if let Some(Value::Function(f)) = drop_fn {
6731                    // Call drop(self) - the value is passed as self
6732                    let _ = self.call_function(&f, vec![value.clone()]);
6733                }
6734            }
6735        }
6736
6737        self.environment = prev_env;
6738        Ok(result)
6739    }
6740
6741    /// Extract tensor shape from a type annotation like Tensor<[2, 3]>
6742    fn extract_tensor_shape(&self, type_expr: &crate::ast::TypeExpr) -> Option<Vec<i64>> {
6743        use crate::ast::TypeExpr;
6744
6745        match type_expr {
6746            TypeExpr::Path(path) => {
6747                // Check if this is a Tensor type
6748                if let Some(segment) = path.segments.first() {
6749                    if segment.ident.name == "Tensor" {
6750                        // Get the generic parameter which should be an array type [dims...]
6751                        if let Some(generics) = &segment.generics {
6752                            if let Some(first_generic) = generics.first() {
6753                                return self.extract_shape_from_type(first_generic);
6754                            }
6755                        }
6756                    }
6757                }
6758                None
6759            }
6760            TypeExpr::Linear(inner) => {
6761                // Handle linear Tensor types
6762                self.extract_tensor_shape(inner)
6763            }
6764            _ => None,
6765        }
6766    }
6767
6768    /// Extract shape dimensions from array type like [2, 3] or [2, 3, 4]
6769    fn extract_shape_from_type(&self, type_expr: &crate::ast::TypeExpr) -> Option<Vec<i64>> {
6770        use crate::ast::{Expr, Literal, TypeExpr};
6771
6772        match type_expr {
6773            // Handle ConstExpr(Array([...])) - the most common case for Tensor<[2, 3]>
6774            TypeExpr::ConstExpr(expr) => {
6775                if let Expr::Array(elements) = expr.as_ref() {
6776                    let mut dims = Vec::new();
6777                    for elem in elements {
6778                        match elem {
6779                            Expr::Literal(Literal::Int { value, .. }) => {
6780                                if let Ok(n) = value.parse::<i64>() {
6781                                    dims.push(n);
6782                                }
6783                            }
6784                            _ => {}
6785                        }
6786                    }
6787                    if dims.is_empty() {
6788                        None
6789                    } else {
6790                        Some(dims)
6791                    }
6792                } else {
6793                    None
6794                }
6795            }
6796            // Handle [T; N] array type syntax (single dimension)
6797            TypeExpr::Array { size, element: _ } => {
6798                if let Expr::Literal(Literal::Int { value, .. }) = size.as_ref() {
6799                    if let Ok(n) = value.parse::<i64>() {
6800                        Some(vec![n])
6801                    } else {
6802                        None
6803                    }
6804                } else {
6805                    None
6806                }
6807            }
6808            // Handle Slice type - used for Tensor<[3]> (single dimension)
6809            TypeExpr::Slice(inner) => {
6810                // The inner is the element type, which for shape annotations is a ConstExpr
6811                // For Tensor<[3]>, this comes as Slice(ConstExpr(Int(3)))
6812                if let TypeExpr::ConstExpr(expr) = inner.as_ref() {
6813                    if let Expr::Literal(Literal::Int { value, .. }) = expr.as_ref() {
6814                        if let Ok(n) = value.parse::<i64>() {
6815                            return Some(vec![n]);
6816                        }
6817                    }
6818                }
6819                None
6820            }
6821            // Handle tuple type syntax (multiple dimensions) like Tensor<(2, 3)>
6822            TypeExpr::Tuple(dims) => {
6823                let mut shape = Vec::new();
6824                for dim in dims {
6825                    if let TypeExpr::Path(path) = dim {
6826                        if let Some(seg) = path.segments.first() {
6827                            if let Ok(n) = seg.ident.name.parse::<i64>() {
6828                                shape.push(n);
6829                            }
6830                        }
6831                    }
6832                }
6833                if shape.is_empty() {
6834                    None
6835                } else {
6836                    Some(shape)
6837                }
6838            }
6839            // Handle Tensor<[2, 3]> where [2, 3] is parsed as a path segment
6840            TypeExpr::Path(path) => {
6841                // This might be parsed as a special array literal in generic position
6842                // The shape [2, 3] might come through as a special segment
6843                if let Some(seg) = path.segments.first() {
6844                    // Try to parse the identifier as a shape
6845                    let name = &seg.ident.name;
6846                    // Check if it looks like "[2, 3]" or similar
6847                    if name.starts_with('[') && name.ends_with(']') {
6848                        let inner = &name[1..name.len() - 1];
6849                        let dims: Vec<i64> = inner
6850                            .split(',')
6851                            .filter_map(|s| s.trim().parse().ok())
6852                            .collect();
6853                        if !dims.is_empty() {
6854                            return Some(dims);
6855                        }
6856                    }
6857                }
6858                None
6859            }
6860            _ => None,
6861        }
6862    }
6863
6864    /// Extract struct name and const generics from type annotation like Linear<3, 2>
6865    fn extract_struct_generics(
6866        &self,
6867        type_expr: &crate::ast::TypeExpr,
6868    ) -> Option<(String, Vec<i64>)> {
6869        use crate::ast::{Expr, Literal, TypeExpr};
6870
6871        // Handle linear type wrapper: linear QRegister<3> -> QRegister<3>
6872        let inner_type = if let TypeExpr::Linear(inner) = type_expr {
6873            inner.as_ref()
6874        } else {
6875            type_expr
6876        };
6877
6878        if let TypeExpr::Path(path) = inner_type {
6879            if let Some(segment) = path.segments.first() {
6880                let struct_name = segment.ident.name.clone();
6881                if let Some(generics) = &segment.generics {
6882                    let mut const_values: Vec<i64> = Vec::new();
6883                    // Generics in PathSegment are Vec<TypeExpr>
6884                    for generic in generics {
6885                        // Handle ConstExpr variant for const generics like Linear<3, 2>
6886                        if let TypeExpr::ConstExpr(expr) = generic {
6887                            if let Expr::Literal(Literal::Int { value, .. }) = expr.as_ref() {
6888                                if let Ok(n) = value.parse::<i64>() {
6889                                    const_values.push(n);
6890                                }
6891                            }
6892                        }
6893                        // Also handle type arguments that are integers (e.g., from parsing "3" as a type)
6894                        if let TypeExpr::Path(inner_path) = generic {
6895                            if let Some(inner_seg) = inner_path.segments.first() {
6896                                if let Ok(n) = inner_seg.ident.name.parse::<i64>() {
6897                                    const_values.push(n);
6898                                }
6899                            }
6900                        }
6901                    }
6902                    if !const_values.is_empty() {
6903                        return Some((struct_name, const_values));
6904                    }
6905                }
6906            }
6907        }
6908        None
6909    }
6910
6911    /// Create a wrapper Function with const generic values pre-bound in its closure.
6912    /// Extracts `__const_X__` hidden fields from struct fields and injects them into
6913    /// a new closure environment that wraps the original function's closure.
6914    fn wrap_with_const_generics(
6915        func: &Rc<Function>,
6916        fields: &Rc<RefCell<HashMap<String, Value>>>,
6917    ) -> Rc<Function> {
6918        let const_bindings: Vec<(String, Value)> = fields.borrow()
6919            .iter()
6920            .filter_map(|(k, v)| {
6921                if k.starts_with("__const_") && k.ends_with("__") {
6922                    let param_name = k.strip_prefix("__const_")
6923                        .and_then(|s| s.strip_suffix("__"));
6924                    param_name.map(|name| (name.to_string(), v.clone()))
6925                } else {
6926                    None
6927                }
6928            })
6929            .collect();
6930
6931        if const_bindings.is_empty() {
6932            return func.clone();
6933        }
6934
6935        // Create wrapper with const generics pre-bound in closure
6936        let wrapper_env = Rc::new(RefCell::new(
6937            Environment::with_parent(func.closure.clone())
6938        ));
6939        for (name, value) in &const_bindings {
6940            wrapper_env.borrow_mut().define(name.clone(), value.clone());
6941        }
6942        Rc::new(Function {
6943            name: func.name.clone(),
6944            params: func.params.clone(),
6945            body: func.body.clone(),
6946            closure: wrapper_env,
6947            generic_params: func.generic_params.clone(),
6948        })
6949    }
6950
6951    fn bind_pattern(&mut self, pattern: &Pattern, value: Value) -> Result<(), RuntimeError> {
6952        match pattern {
6953            Pattern::Ident { name, mutable, evidentiality } => {
6954                // Don't bind "_" - it's a wildcard in identifier form
6955                if name.name != "_" {
6956                    // Debug: trace path binding
6957                    if name.name == "path" {
6958                        crate::sigil_debug!("DEBUG bind_pattern: binding 'path' = {:?}", value);
6959                    }
6960                    // Track if variable is declared as mutable
6961                    if *mutable {
6962                        self.mutable_vars.borrow_mut().insert(name.name.clone());
6963                    }
6964                    // If pattern has evidentiality, bind the inner value (evidence already matched)
6965                    let bound_value = if evidentiality.is_some() {
6966                        match value {
6967                            Value::Evidential { value: inner, .. } => *inner,
6968                            other => other,
6969                        }
6970                    } else {
6971                        value
6972                    };
6973                    self.environment
6974                        .borrow_mut()
6975                        .define(name.name.clone(), bound_value);
6976                }
6977                Ok(())
6978            }
6979            Pattern::Tuple(patterns) => {
6980                // Unwrap evidential wrappers first
6981                let unwrapped = Self::unwrap_all(&value);
6982                crate::sigil_debug!(
6983                    "DEBUG bind_pattern Tuple: patterns.len()={}, value type={:?}",
6984                    patterns.len(),
6985                    std::mem::discriminant(&unwrapped)
6986                );
6987                match unwrapped {
6988                    Value::Tuple(values) => {
6989                        if patterns.len() != values.len() {
6990                            return Err(RuntimeError::new("Tuple pattern size mismatch"));
6991                        }
6992                        for (i, (p, v)) in patterns.iter().zip(values.iter()).enumerate() {
6993                            crate::sigil_debug!(
6994                                "DEBUG   binding tuple element {}: {:?} = {}",
6995                                i,
6996                                p,
6997                                self.format_value(v)
6998                            );
6999                            self.bind_pattern(p, v.clone())?;
7000                        }
7001                        Ok(())
7002                    }
7003                    Value::Null => {
7004                        // Null value during iteration - treat as end of iteration (no binding)
7005                        Ok(())
7006                    }
7007                    Value::Array(arr) if arr.borrow().len() == patterns.len() => {
7008                        // Allow array to be destructured as tuple
7009                        let vals = arr.borrow();
7010                        for (p, v) in patterns.iter().zip(vals.iter()) {
7011                            self.bind_pattern(p, v.clone())?;
7012                        }
7013                        Ok(())
7014                    }
7015                    _ => Err(RuntimeError::new("Expected tuple")),
7016                }
7017            }
7018            Pattern::Wildcard => Ok(()),
7019            Pattern::Struct { path, fields, .. } => {
7020                // Unwrap any wrappers first
7021                let unwrapped = Self::unwrap_all(&value);
7022                // Bind each field from the struct or variant
7023                match &unwrapped {
7024                    Value::Struct {
7025                        fields: struct_fields,
7026                        ..
7027                    } => {
7028                        for field_pat in fields {
7029                            let field_name = &field_pat.name.name;
7030                            // Get field value or default to Null for missing optional fields
7031                            let field_val = struct_fields
7032                                .borrow()
7033                                .get(field_name)
7034                                .cloned()
7035                                .unwrap_or(Value::Null);
7036                            if let Some(pat) = &field_pat.pattern {
7037                                self.bind_pattern(pat, field_val)?;
7038                            } else {
7039                                // Shorthand: foo: foo - bind to same name
7040                                self.environment
7041                                    .borrow_mut()
7042                                    .define(field_name.clone(), field_val);
7043                            }
7044                        }
7045                        Ok(())
7046                    }
7047                    Value::Variant {
7048                        enum_name,
7049                        variant_name,
7050                        fields: variant_fields,
7051                    } => {
7052                        // Handle struct-like enum variants (e.g., IrPattern::Ident { name, .. })
7053                        let pattern_variant = path
7054                            .segments
7055                            .last()
7056                            .map(|s| s.ident.name.as_str())
7057                            .unwrap_or("");
7058                        if pattern_variant == variant_name
7059                            || path.segments.iter().any(|s| s.ident.name == *variant_name)
7060                        {
7061                            // Variant fields are stored as a Vec, but we need to map by name
7062                            // For struct-like variants, the fields should be a Struct value with field names
7063                            if let Some(inner_fields) = variant_fields {
7064                                if inner_fields.len() == 1 {
7065                                    // Single wrapped struct with named fields
7066                                    if let Value::Struct {
7067                                        fields: inner_struct,
7068                                        ..
7069                                    } = &inner_fields[0]
7070                                    {
7071                                        for field_pat in fields {
7072                                            let field_name = &field_pat.name.name;
7073                                            // Default to Null for missing optional fields
7074                                            let field_val = inner_struct
7075                                                .borrow()
7076                                                .get(field_name)
7077                                                .cloned()
7078                                                .unwrap_or(Value::Null);
7079                                            if let Some(pat) = &field_pat.pattern {
7080                                                self.bind_pattern(pat, field_val)?;
7081                                            } else {
7082                                                self.environment
7083                                                    .borrow_mut()
7084                                                    .define(field_name.clone(), field_val);
7085                                            }
7086                                        }
7087                                        return Ok(());
7088                                    }
7089                                }
7090                                // Named field lookup from variant's field map
7091                                // Variants store struct fields as named HashMap inside the variant
7092                                for field_pat in fields {
7093                                    let field_name = &field_pat.name.name;
7094                                    // Look for a field with matching name in variant fields
7095                                    // Variant fields might be stored in order or as a struct
7096                                    // For now, search by name if we can find it
7097                                    let field_val = inner_fields.iter().find_map(|f| {
7098                                        if let Value::Struct { fields: fs, .. } = f {
7099                                            fs.borrow().get(field_name).cloned()
7100                                        } else {
7101                                            None
7102                                        }
7103                                    });
7104                                    if let Some(val) = field_val {
7105                                        if let Some(pat) = &field_pat.pattern {
7106                                            self.bind_pattern(pat, val)?;
7107                                        } else {
7108                                            self.environment
7109                                                .borrow_mut()
7110                                                .define(field_name.clone(), val);
7111                                        }
7112                                    }
7113                                }
7114                            }
7115                            Ok(())
7116                        } else {
7117                            crate::sigil_debug!(
7118                                "DEBUG variant name mismatch: pattern={}, actual={}",
7119                                pattern_variant,
7120                                variant_name
7121                            );
7122                            Err(RuntimeError::new(format!(
7123                                "Variant name mismatch: expected {} but got {}::{}",
7124                                pattern_variant, enum_name, variant_name
7125                            )))
7126                        }
7127                    }
7128                    _ => {
7129                        crate::sigil_debug!(
7130                            "DEBUG struct pattern bind: expected struct/variant but got {:?}",
7131                            std::mem::discriminant(&unwrapped)
7132                        );
7133                        Err(RuntimeError::new(
7134                            "Expected struct or variant value for struct pattern",
7135                        ))
7136                    }
7137                }
7138            }
7139            Pattern::Path(_path) => {
7140                // Path patterns like Result::Ok - unit variant patterns
7141                // Don't bind anything
7142                Ok(())
7143            }
7144            Pattern::TupleStruct { path, fields } => {
7145                // Enum variant with fields: Result::Ok(value)
7146                // Unwrap any refs first
7147                let unwrapped = Self::unwrap_all(&value);
7148                let path_str = path
7149                    .segments
7150                    .iter()
7151                    .map(|s| s.ident.name.as_str())
7152                    .collect::<Vec<_>>()
7153                    .join("::");
7154                crate::sigil_debug!(
7155                    "DEBUG bind_pattern TupleStruct: path={}, value type={:?}",
7156                    path_str,
7157                    std::mem::discriminant(&unwrapped)
7158                );
7159                if let Value::Variant {
7160                    variant_name,
7161                    fields: variant_fields,
7162                    enum_name,
7163                } = &unwrapped
7164                {
7165                    crate::sigil_debug!(
7166                        "DEBUG   Variant {}::{}, fields={}",
7167                        enum_name,
7168                        variant_name,
7169                        if variant_fields.is_some() {
7170                            format!("Some(len={})", variant_fields.as_ref().unwrap().len())
7171                        } else {
7172                            "None".to_string()
7173                        }
7174                    );
7175                    let pattern_variant = path
7176                        .segments
7177                        .last()
7178                        .map(|s| s.ident.name.as_str())
7179                        .unwrap_or("");
7180                    if pattern_variant == variant_name {
7181                        // Unwrap fields and bind
7182                        if let Some(inner_fields) = variant_fields {
7183                            if fields.len() == 1 && inner_fields.len() == 1 {
7184                                self.bind_pattern(&fields[0], inner_fields[0].clone())?;
7185                            } else {
7186                                for (pat, val) in fields.iter().zip(inner_fields.iter()) {
7187                                    self.bind_pattern(pat, val.clone())?;
7188                                }
7189                            }
7190                        } else if !fields.is_empty() {
7191                            // Pattern expects fields but variant has none
7192                            crate::sigil_debug!(
7193                                "DEBUG TupleStruct: pattern expects {} fields but variant has none",
7194                                fields.len()
7195                            );
7196                        }
7197                    }
7198                    Ok(())
7199                } else {
7200                    // Maybe it's a regular tuple being matched
7201                    if let Value::Tuple(tuple_vals) = &value {
7202                        for (pat, val) in fields.iter().zip(tuple_vals.iter()) {
7203                            self.bind_pattern(pat, val.clone())?;
7204                        }
7205                        Ok(())
7206                    } else {
7207                        Err(RuntimeError::new(
7208                            "Expected variant or tuple for tuple struct pattern",
7209                        ))
7210                    }
7211                }
7212            }
7213            Pattern::Literal(_) => {
7214                // Literal patterns don't bind anything, just match
7215                Ok(())
7216            }
7217            Pattern::Rest => {
7218                // Rest pattern .. - just ignores rest of values
7219                Ok(())
7220            }
7221            Pattern::Range { .. } => {
7222                // Range patterns like 'a'..='z' don't bind anything
7223                Ok(())
7224            }
7225            Pattern::Or(patterns) => {
7226                // Or patterns - find the matching pattern and bind its variables
7227                for p in patterns {
7228                    if self.pattern_matches(p, &value)? {
7229                        return self.bind_pattern(p, value.clone());
7230                    }
7231                }
7232                // No pattern matched - this shouldn't happen if pattern_matches returned true earlier
7233                Err(RuntimeError::new("Or pattern didn't match any alternative"))
7234            }
7235            Pattern::RefBinding { name, .. } => {
7236                // Rust's `ref` pattern is not supported in Sigil
7237                Err(RuntimeError::new(format!(
7238                    "Rust's `ref {}` pattern is not supported in Sigil. \
7239                    Variables bind by value. Use `≔ {} = &expr` for explicit references",
7240                    name.name, name.name
7241                )))
7242            }
7243            Pattern::Ref { pattern: inner, .. } => {
7244                // &var pattern: strip one level of reference and bind the inner pattern
7245                let unwrapped = match &value {
7246                    Value::Ref(r) => r.borrow().clone(),
7247                    other => other.clone(),
7248                };
7249                self.bind_pattern(inner, unwrapped)
7250            }
7251            _ => Err(RuntimeError::new(format!(
7252                "Unsupported pattern: {:?}",
7253                pattern
7254            ))),
7255        }
7256    }
7257
7258    fn eval_if(
7259        &mut self,
7260        condition: &Expr,
7261        then_branch: &Block,
7262        else_branch: &Option<Box<Expr>>,
7263    ) -> Result<Value, RuntimeError> {
7264        let cond = self.evaluate(condition)?;
7265        if self.is_truthy(&cond) {
7266            self.eval_block(then_branch)
7267        } else if let Some(else_expr) = else_branch {
7268            self.evaluate(else_expr)
7269        } else {
7270            Ok(Value::Null)
7271        }
7272    }
7273
7274    fn eval_match(&mut self, expr: &Expr, arms: &[MatchArm]) -> Result<Value, RuntimeError> {
7275        // Type check: verify all arms return the same type
7276        if arms.len() >= 2 {
7277            let mut first_type: Option<String> = None;
7278            for arm in arms {
7279                if let Some(arm_type) = self.infer_expr_type(&arm.body) {
7280                    if let Some(ref expected) = first_type {
7281                        if &arm_type != expected {
7282                            return Err(RuntimeError::new(format!(
7283                                "match arms have incompatible types: expected '{}', found '{}'",
7284                                expected, arm_type
7285                            )));
7286                        }
7287                    } else {
7288                        first_type = Some(arm_type);
7289                    }
7290                }
7291            }
7292        }
7293
7294        let value = self.evaluate(expr)?;
7295
7296        // Debug all string matches to find keyword_or_ident
7297        let unwrapped = Self::unwrap_all(&value);
7298        if let Value::String(s) = &unwrapped {
7299            if s.len() <= 10 {
7300                crate::sigil_debug!("DEBUG eval_match: string='{}', arms={}", s, arms.len());
7301            }
7302        }
7303
7304        for arm in arms {
7305            if self.pattern_matches(&arm.pattern, &value)? {
7306                // Create new environment for pattern bindings
7307                let env = Rc::new(RefCell::new(Environment::with_parent(
7308                    self.environment.clone(),
7309                )));
7310                let prev_env = self.environment.clone();
7311                self.environment = env;
7312
7313                // Bind pattern variables FIRST (before evaluating guard)
7314                // This is necessary for guards like `?fields if !fields.is_empty()`
7315                if let Err(e) = self.bind_pattern(&arm.pattern, value.clone()) {
7316                    self.environment = prev_env;
7317                    return Err(e);
7318                }
7319
7320                // Check guard if present (pattern vars are now in scope)
7321                if let Some(guard) = &arm.guard {
7322                    let guard_val = self.evaluate(guard)?;
7323                    if !self.is_truthy(&guard_val) {
7324                        // Guard failed - restore environment and try next arm
7325                        self.environment = prev_env;
7326                        continue;
7327                    }
7328                }
7329
7330                // Pattern matched and guard passed - evaluate body
7331                let result = self.evaluate(&arm.body);
7332
7333                self.environment = prev_env;
7334                return result;
7335            }
7336        }
7337
7338        // Debug: show what value we're trying to match with discriminant
7339        eprintln!(
7340            "DEBUG No matching pattern for value: {} (discriminant: {:?})",
7341            self.format_value(&value),
7342            std::mem::discriminant(&value)
7343        );
7344        // Show more details if it's a Struct or Variant
7345        match &value {
7346            Value::Struct { name, fields } => {
7347                eprintln!(
7348                    "  Struct: name='{}', fields={:?}",
7349                    name,
7350                    fields.borrow().keys().collect::<Vec<_>>()
7351                );
7352            }
7353            Value::Variant {
7354                enum_name,
7355                variant_name,
7356                fields,
7357            } => {
7358                eprintln!(
7359                    "  Variant: {}::{}, fields={:?}",
7360                    enum_name, variant_name, fields
7361                );
7362            }
7363            _ => {}
7364        }
7365        // Also show the arms
7366        for (i, arm) in arms.iter().enumerate() {
7367            eprintln!("DEBUG   arm {}: {:?}", i, arm.pattern);
7368        }
7369        Err(RuntimeError::new(format!(
7370            "No matching pattern for {}",
7371            self.format_value(&value)
7372        )))
7373    }
7374
7375    fn pattern_matches(&mut self, pattern: &Pattern, value: &Value) -> Result<bool, RuntimeError> {
7376        // Evidence-level pattern matching: dispatch on evidence before unwrapping
7377        if let Pattern::Ident { evidentiality: Some(ev), .. } = pattern {
7378            return match (ev, value) {
7379                // Evidential value — check level matches
7380                (Evidentiality::Known, Value::Evidential { evidence: Evidence::Known, .. }) => Ok(true),
7381                (Evidentiality::Uncertain, Value::Evidential { evidence: Evidence::Uncertain, .. }) => Ok(true),
7382                (Evidentiality::Reported, Value::Evidential { evidence: Evidence::Reported, .. }) => Ok(true),
7383                (Evidentiality::Predicted, Value::Evidential { evidence: Evidence::Predicted, .. }) => Ok(true),
7384                (Evidentiality::Paradox, Value::Evidential { evidence: Evidence::Paradox, .. }) => Ok(true),
7385                // Known pattern also matches bare (non-evidential) values — bare values are implicitly known
7386                (Evidentiality::Known, v) if !matches!(v, Value::Evidential { .. } | Value::Null) => Ok(true),
7387                // Uncertain pattern (?v) matches any non-null value (bare or evidential with compatible level)
7388                // This handles the case: ≔ x: i32? = 42; ⌥ x { ?v => ..., null => ... }
7389                (Evidentiality::Uncertain, v) if !matches!(v, Value::Null) => Ok(true),
7390                _ => Ok(false),
7391            };
7392        }
7393
7394        // Non-evidence patterns: unwrap evidential/affective/ref wrappers as before
7395        let value = Self::unwrap_all(value);
7396
7397        // Debug string pattern matching
7398        if let Value::String(s) = &value {
7399            if **s == "fn" {
7400                crate::sigil_debug!("DEBUG pattern_matches: value='fn', pattern={:?}", pattern);
7401            }
7402        }
7403
7404        match (pattern, &value) {
7405            (Pattern::Wildcard, _) => Ok(true),
7406            (Pattern::Ident { .. }, _) => Ok(true),
7407            (Pattern::Literal(lit), val) => {
7408                let lit_val = self.eval_literal(lit)?;
7409                let result = self.values_equal(&lit_val, val);
7410                // Debug null pattern matching specifically
7411                if matches!(lit, Literal::Null) || matches!(val, Value::Null) {
7412                    crate::sigil_debug!(
7413                        "DEBUG literal pattern: lit={:?}, lit_val={}, val={}, result={}",
7414                        lit,
7415                        self.format_value(&lit_val),
7416                        self.format_value(val),
7417                        result
7418                    );
7419                }
7420                Ok(result)
7421            }
7422            (Pattern::Tuple(patterns), Value::Tuple(values)) => {
7423                if patterns.len() != values.len() {
7424                    return Ok(false);
7425                }
7426                for (p, v) in patterns.iter().zip(values.iter()) {
7427                    if !self.pattern_matches(p, v)? {
7428                        return Ok(false);
7429                    }
7430                }
7431                Ok(true)
7432            }
7433            // Path pattern - matches unit enum variants like CompileMode::Compile
7434            (
7435                Pattern::Path(path),
7436                Value::Variant {
7437                    variant_name,
7438                    fields,
7439                    ..
7440                },
7441            ) => {
7442                let pattern_variant = path
7443                    .segments
7444                    .last()
7445                    .map(|s| s.ident.name.as_str())
7446                    .unwrap_or("");
7447                // Match if variant name matches and has no fields
7448                Ok(pattern_variant == variant_name && fields.is_none())
7449            }
7450            // TupleStruct pattern - matches enum variants with data like Result::Ok(x)
7451            (
7452                Pattern::TupleStruct {
7453                    path,
7454                    fields: pat_fields,
7455                },
7456                Value::Variant {
7457                    variant_name,
7458                    fields,
7459                    ..
7460                },
7461            ) => {
7462                let pattern_variant = path
7463                    .segments
7464                    .last()
7465                    .map(|s| s.ident.name.as_str())
7466                    .unwrap_or("");
7467                if pattern_variant != variant_name {
7468                    return Ok(false);
7469                }
7470                // Match field patterns
7471                if let Some(variant_fields) = fields {
7472                    if pat_fields.len() != variant_fields.len() {
7473                        return Ok(false);
7474                    }
7475                    for (p, v) in pat_fields.iter().zip(variant_fields.iter()) {
7476                        if !self.pattern_matches(p, v)? {
7477                            return Ok(false);
7478                        }
7479                    }
7480                    Ok(true)
7481                } else {
7482                    // Variant has no fields but pattern expects some
7483                    Ok(pat_fields.is_empty())
7484                }
7485            }
7486            // Struct pattern - matches struct values
7487            (
7488                Pattern::Struct {
7489                    path,
7490                    fields: pat_fields,
7491                    rest,
7492                },
7493                Value::Struct {
7494                    name: struct_name,
7495                    fields: struct_fields,
7496                },
7497            ) => {
7498                let pattern_name = path
7499                    .segments
7500                    .iter()
7501                    .map(|s| s.ident.name.as_str())
7502                    .collect::<Vec<_>>()
7503                    .join("::");
7504                if pattern_name != *struct_name {
7505                    return Ok(false);
7506                }
7507                // Check each field in the pattern
7508                let borrowed = struct_fields.borrow();
7509                for field_pat in pat_fields {
7510                    let field_name = &field_pat.name.name;
7511                    if let Some(field_val) = borrowed.get(field_name) {
7512                        if let Some(sub_pat) = &field_pat.pattern {
7513                            if !self.pattern_matches(sub_pat, field_val)? {
7514                                return Ok(false);
7515                            }
7516                        }
7517                        // If no sub-pattern, any value matches
7518                    } else if !rest {
7519                        // Field not found and no rest pattern
7520                        return Ok(false);
7521                    }
7522                }
7523                Ok(true)
7524            }
7525            // Struct pattern - matches struct-like enum variants (e.g., TypeExpr::Evidential { inner, ... })
7526            (
7527                Pattern::Struct {
7528                    path,
7529                    fields: pat_fields,
7530                    rest,
7531                },
7532                Value::Variant {
7533                    variant_name,
7534                    fields: variant_fields,
7535                    ..
7536                },
7537            ) => {
7538                let pattern_variant = path
7539                    .segments
7540                    .last()
7541                    .map(|s| s.ident.name.as_str())
7542                    .unwrap_or("");
7543                if pattern_variant != variant_name {
7544                    return Ok(false);
7545                }
7546                // Struct-like variants store fields as a single wrapped Struct value
7547                if let Some(inner_fields) = variant_fields {
7548                    if inner_fields.len() == 1 {
7549                        if let Value::Struct {
7550                            fields: inner_struct,
7551                            ..
7552                        } = &inner_fields[0]
7553                        {
7554                            let borrowed = inner_struct.borrow();
7555                            for field_pat in pat_fields {
7556                                let field_name = &field_pat.name.name;
7557                                if let Some(field_val) = borrowed.get(field_name) {
7558                                    if let Some(sub_pat) = &field_pat.pattern {
7559                                        if !self.pattern_matches(sub_pat, field_val)? {
7560                                            return Ok(false);
7561                                        }
7562                                    }
7563                                } else if !rest {
7564                                    return Ok(false);
7565                                }
7566                            }
7567                            return Ok(true);
7568                        }
7569                    }
7570                }
7571                // No fields or structure doesn't match
7572                Ok(pat_fields.is_empty() || *rest)
7573            }
7574            // Or pattern - match if any sub-pattern matches
7575            (Pattern::Or(patterns), val) => {
7576                for p in patterns {
7577                    if self.pattern_matches(p, val)? {
7578                        return Ok(true);
7579                    }
7580                }
7581                Ok(false)
7582            }
7583            // Rest pattern always matches
7584            (Pattern::Rest, _) => Ok(true),
7585            // Range pattern: 'a'..='z' or 0..=9
7586            (
7587                Pattern::Range {
7588                    start,
7589                    end,
7590                    inclusive,
7591                },
7592                val,
7593            ) => {
7594                // Helper to extract char from pattern
7595                let extract_char = |pat: &Option<Box<Pattern>>| -> Option<char> {
7596                    match pat {
7597                        Some(p) => match p.as_ref() {
7598                            Pattern::Literal(Literal::Char(c)) => Some(*c),
7599                            _ => None,
7600                        },
7601                        None => None,
7602                    }
7603                };
7604                // Helper to extract int from pattern
7605                let extract_int = |pat: &Option<Box<Pattern>>| -> Option<i64> {
7606                    match pat {
7607                        Some(p) => match p.as_ref() {
7608                            Pattern::Literal(Literal::Int { value, .. }) => value.parse().ok(),
7609                            _ => None,
7610                        },
7611                        None => None,
7612                    }
7613                };
7614
7615                match val {
7616                    Value::Char(c) => {
7617                        let start_val = extract_char(start);
7618                        let end_val = extract_char(end);
7619                        let in_range = match (start_val, end_val, *inclusive) {
7620                            (Some(s), Some(e), true) => *c >= s && *c <= e,
7621                            (Some(s), Some(e), false) => *c >= s && *c < e,
7622                            (Some(s), None, _) => *c >= s,
7623                            (None, Some(e), true) => *c <= e,
7624                            (None, Some(e), false) => *c < e,
7625                            (None, None, _) => true,
7626                        };
7627                        Ok(in_range)
7628                    }
7629                    Value::Int(i) => {
7630                        let start_val = extract_int(start);
7631                        let end_val = extract_int(end);
7632                        let in_range = match (start_val, end_val, *inclusive) {
7633                            (Some(s), Some(e), true) => *i >= s && *i <= e,
7634                            (Some(s), Some(e), false) => *i >= s && *i < e,
7635                            (Some(s), None, _) => *i >= s,
7636                            (None, Some(e), true) => *i <= e,
7637                            (None, Some(e), false) => *i < e,
7638                            (None, None, _) => true,
7639                        };
7640                        Ok(in_range)
7641                    }
7642                    _ => Ok(false),
7643                }
7644            }
7645            // Literal matching against string or char
7646            (Pattern::Literal(Literal::String(s)), Value::String(vs)) => Ok(s == vs.as_str()),
7647            (Pattern::Literal(Literal::Char(c)), Value::Char(vc)) => Ok(c == vc),
7648            // Ref pattern: &var matches references (strip one level)
7649            (Pattern::Ref { pattern: inner, .. }, val) => {
7650                let unwrapped = match val {
7651                    Value::Ref(r) => r.borrow().clone(),
7652                    other => other.clone(),
7653                };
7654                self.pattern_matches(inner, &unwrapped)
7655            }
7656            _ => Ok(false),
7657        }
7658    }
7659
7660    fn values_equal(&self, a: &Value, b: &Value) -> bool {
7661        // Unwrap any Ref wrappers before comparison
7662        let a_unwrapped = match a {
7663            Value::Ref(r) => r.borrow().clone(),
7664            _ => a.clone(),
7665        };
7666        let b_unwrapped = match b {
7667            Value::Ref(r) => r.borrow().clone(),
7668            _ => b.clone(),
7669        };
7670        match (&a_unwrapped, &b_unwrapped) {
7671            (Value::Null, Value::Null) => true,
7672            (Value::Bool(a), Value::Bool(b)) => a == b,
7673            (Value::Int(a), Value::Int(b)) => a == b,
7674            (Value::Float(a), Value::Float(b)) => (a - b).abs() < f64::EPSILON,
7675            (Value::String(a), Value::String(b)) => {
7676                let result = **a == **b;
7677                // Debug ALL short string comparisons
7678                if a.len() <= 5 && b.len() <= 5 {
7679                    crate::sigil_debug!("DEBUG values_equal: '{}' == '{}' -> {}", a, b, result);
7680                }
7681                result
7682            }
7683            (Value::Char(a), Value::Char(b)) => a == b,
7684            _ => false,
7685        }
7686    }
7687
7688    fn eval_for(
7689        &mut self,
7690        pattern: &Pattern,
7691        iter: &Expr,
7692        body: &Block,
7693    ) -> Result<Value, RuntimeError> {
7694        let iterable_raw = self.evaluate(iter)?;
7695        let iterable = Self::unwrap_all(&iterable_raw);
7696        let items = match iterable {
7697            Value::Array(arr) => arr.borrow().clone(),
7698            Value::Tuple(t) => (*t).clone(),
7699            Value::String(s) => s.chars().map(Value::Char).collect(),
7700            Value::Map(m) => {
7701                // Iterate over key-value pairs as tuples
7702                m.borrow()
7703                    .iter()
7704                    .map(|(k, v)| {
7705                        Value::Tuple(Rc::new(vec![Value::String(Rc::new(k.clone())), v.clone()]))
7706                    })
7707                    .collect()
7708            }
7709            Value::Variant {
7710                fields: Some(f), ..
7711            } => (*f).clone(),
7712            _ => {
7713                return Err(RuntimeError::new(format!(
7714                    "Cannot iterate over non-iterable: {:?}",
7715                    iterable_raw
7716                )))
7717            }
7718        };
7719
7720        let mut result = Value::Null;
7721        for item in items {
7722            let env = Rc::new(RefCell::new(Environment::with_parent(
7723                self.environment.clone(),
7724            )));
7725            let prev_env = self.environment.clone();
7726            self.environment = env;
7727
7728            self.bind_pattern(pattern, item)?;
7729
7730            match self.eval_block(body) {
7731                Ok(val) => result = val,
7732                Err(e) if e.message == "break" => {
7733                    self.environment = prev_env;
7734                    break;
7735                }
7736                Err(e) if e.message == "continue" => {
7737                    self.environment = prev_env;
7738                    continue;
7739                }
7740                Err(e) => {
7741                    self.environment = prev_env;
7742                    return Err(e);
7743                }
7744            }
7745
7746            self.environment = prev_env;
7747        }
7748
7749        Ok(result)
7750    }
7751
7752    fn eval_while(&mut self, condition: &Expr, body: &Block) -> Result<Value, RuntimeError> {
7753        let mut result = Value::Null;
7754        loop {
7755            let cond = self.evaluate(condition)?;
7756            if !self.is_truthy(&cond) {
7757                break;
7758            }
7759
7760            match self.eval_block(body) {
7761                Ok(val) => result = val,
7762                Err(e) if e.message == "break" => break,
7763                Err(e) if e.message == "continue" => continue,
7764                Err(e) => return Err(e),
7765            }
7766        }
7767        Ok(result)
7768    }
7769
7770    fn eval_loop(&mut self, body: &Block) -> Result<Value, RuntimeError> {
7771        loop {
7772            match self.eval_block(body) {
7773                Ok(_) => {}
7774                Err(e) if e.message == "break" => break,
7775                Err(e) if e.message == "continue" => continue,
7776                Err(e) => return Err(e),
7777            }
7778        }
7779        Ok(Value::Null)
7780    }
7781
7782    fn eval_return(&mut self, value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
7783        let val = match value {
7784            Some(expr) => self.evaluate(expr)?,
7785            None => Value::Null,
7786        };
7787        // Store return value for call_function to retrieve
7788        self.return_value = Some(val);
7789        Err(RuntimeError::new("return"))
7790    }
7791
7792    fn eval_break(&mut self, _value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
7793        // TODO: break with value for loop expressions
7794        Err(RuntimeError::new("break"))
7795    }
7796
7797    fn eval_index(&mut self, expr: &Expr, index: &Expr) -> Result<Value, RuntimeError> {
7798        let collection = self.evaluate(expr)?;
7799
7800        // Dereference Ref values to get the underlying collection
7801        let collection = match collection {
7802            Value::Ref(r) => r.borrow().clone(),
7803            other => other,
7804        };
7805
7806        // Handle range slicing before evaluating the index
7807        if let Expr::Range {
7808            start,
7809            end,
7810            inclusive,
7811        } = index
7812        {
7813            let start_val = match start {
7814                Some(e) => match self.evaluate(e)? {
7815                    Value::Int(n) => n as usize,
7816                    _ => return Err(RuntimeError::new("Slice start must be an integer")),
7817                },
7818                None => 0,
7819            };
7820
7821            return match &collection {
7822                Value::Array(arr) => {
7823                    let arr = arr.borrow();
7824                    let len = arr.len();
7825                    let end_val = match end {
7826                        Some(e) => match self.evaluate(e)? {
7827                            Value::Int(n) => {
7828                                let n = n as usize;
7829                                if *inclusive {
7830                                    n + 1
7831                                } else {
7832                                    n
7833                                }
7834                            }
7835                            _ => return Err(RuntimeError::new("Slice end must be an integer")),
7836                        },
7837                        None => len, // Open-ended range: slice to end
7838                    };
7839                    let end_val = end_val.min(len);
7840                    let start_val = start_val.min(len);
7841                    let sliced: Vec<Value> = arr[start_val..end_val].to_vec();
7842                    Ok(Value::Array(Rc::new(RefCell::new(sliced))))
7843                }
7844                Value::String(s) => {
7845                    let len = s.len();
7846                    let end_val = match end {
7847                        Some(e) => match self.evaluate(e)? {
7848                            Value::Int(n) => {
7849                                let n = n as usize;
7850                                if *inclusive {
7851                                    n + 1
7852                                } else {
7853                                    n
7854                                }
7855                            }
7856                            _ => return Err(RuntimeError::new("Slice end must be an integer")),
7857                        },
7858                        None => len, // Open-ended range: slice to end
7859                    };
7860                    let end_val = end_val.min(len);
7861                    let start_val = start_val.min(len);
7862                    // Use byte slicing for consistency with char_at
7863                    let sliced = &s[start_val..end_val];
7864                    Ok(Value::String(Rc::new(sliced.to_string())))
7865                }
7866                _ => Err(RuntimeError::new("Cannot slice this type")),
7867            };
7868        }
7869
7870        let idx = self.evaluate(index)?;
7871
7872        match (collection, idx) {
7873            (Value::Array(arr), Value::Int(i)) => {
7874                let arr = arr.borrow();
7875                let len = arr.len();
7876
7877                // Check if this is a typed Vec<T> - if so, error on negative indices
7878                // Otherwise, support Python-style negative indexing
7879                let is_typed_vec = if let Some(var_name) = Self::extract_root_var(expr) {
7880                    self.var_types
7881                        .borrow()
7882                        .get(&var_name)
7883                        .map(|(type_name, _)| type_name == "Vec")
7884                        .unwrap_or(false)
7885                } else {
7886                    false
7887                };
7888
7889                let idx = if i < 0 {
7890                    if is_typed_vec {
7891                        return Err(RuntimeError::new(format!(
7892                            "negative index {} is invalid",
7893                            i
7894                        )));
7895                    }
7896                    // Python-style negative indexing for non-Vec arrays
7897                    let positive_idx = (len as i64 + i) as usize;
7898                    if positive_idx >= len {
7899                        return Err(RuntimeError::index_out_of_bounds(i, len));
7900                    }
7901                    positive_idx
7902                } else {
7903                    i as usize
7904                };
7905
7906                let result = arr
7907                    .get(idx)
7908                    .cloned()
7909                    .ok_or_else(|| RuntimeError::index_out_of_bounds(i, len));
7910                if let Ok(ref v) = result {
7911                    crate::sigil_debug!(
7912                        "DEBUG eval_index: arr[{}] = {:?}",
7913                        idx,
7914                        std::mem::discriminant(v)
7915                    );
7916                }
7917                result
7918            }
7919            (Value::Tuple(t), Value::Int(i)) => {
7920                // Error on negative indices
7921                if i < 0 {
7922                    return Err(RuntimeError::new(format!(
7923                        "negative index {} is invalid",
7924                        i
7925                    )));
7926                }
7927                let len = t.len();
7928                let idx = i as usize;
7929                t.get(idx)
7930                    .cloned()
7931                    .ok_or_else(|| RuntimeError::index_out_of_bounds(i, len))
7932            }
7933            (Value::String(s), Value::Int(i)) => {
7934                // Error on negative indices
7935                if i < 0 {
7936                    return Err(RuntimeError::new(format!(
7937                        "negative index {} is invalid",
7938                        i
7939                    )));
7940                }
7941                let len = s.len();
7942                let idx = i as usize;
7943                s.chars()
7944                    .nth(idx)
7945                    .map(Value::Char)
7946                    .ok_or_else(|| RuntimeError::index_out_of_bounds(i, len))
7947            }
7948            // Handle open-ended range slicing (from eval_range returning tuple)
7949            (Value::Array(arr), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
7950                let arr = arr.borrow();
7951                let start = match &range_tuple[0] {
7952                    Value::Int(n) => *n as usize,
7953                    _ => return Err(RuntimeError::new("Range start must be integer")),
7954                };
7955                let end = match &range_tuple[1] {
7956                    Value::Null => arr.len(), // Open end - slice to end
7957                    Value::Int(n) => *n as usize,
7958                    _ => return Err(RuntimeError::new("Range end must be integer or None")),
7959                };
7960                let start = start.min(arr.len());
7961                let end = end.min(arr.len());
7962                let sliced: Vec<Value> = arr[start..end].to_vec();
7963                Ok(Value::Array(Rc::new(RefCell::new(sliced))))
7964            }
7965            (Value::String(s), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
7966                let start = match &range_tuple[0] {
7967                    Value::Int(n) => *n as usize,
7968                    _ => return Err(RuntimeError::new("Range start must be integer")),
7969                };
7970                let end = match &range_tuple[1] {
7971                    Value::Null => s.len(), // Open end - slice to end
7972                    Value::Int(n) => *n as usize,
7973                    _ => return Err(RuntimeError::new("Range end must be integer or None")),
7974                };
7975                let start = start.min(s.len());
7976                let end = end.min(s.len());
7977                let sliced = &s[start..end];
7978                Ok(Value::String(Rc::new(sliced.to_string())))
7979            }
7980            // Handle Tensor indexing: tensor[i] -> row or scalar
7981            (Value::Struct { name, fields }, Value::Int(i)) if name == "Tensor" => {
7982                let fields_ref = fields.borrow();
7983
7984                // Get shape and data
7985                let shape: Vec<i64> = match fields_ref.get("shape") {
7986                    Some(Value::Array(arr)) => arr
7987                        .borrow()
7988                        .iter()
7989                        .filter_map(|v| match v {
7990                            Value::Int(n) => Some(*n),
7991                            _ => None,
7992                        })
7993                        .collect(),
7994                    _ => vec![],
7995                };
7996                let data: Vec<f64> = match fields_ref.get("data") {
7997                    Some(Value::Array(arr)) => arr
7998                        .borrow()
7999                        .iter()
8000                        .filter_map(|v| match v {
8001                            Value::Float(f) => Some(*f),
8002                            Value::Int(n) => Some(*n as f64),
8003                            _ => None,
8004                        })
8005                        .collect(),
8006                    _ => vec![],
8007                };
8008                drop(fields_ref);
8009
8010                let idx = if i < 0 { shape[0] + i } else { i } as usize;
8011
8012                if shape.len() == 1 {
8013                    // 1D tensor - return scalar
8014                    if idx < data.len() {
8015                        Ok(Value::Float(data[idx]))
8016                    } else {
8017                        Err(RuntimeError::index_out_of_bounds(i, data.len()))
8018                    }
8019                } else if shape.len() >= 2 {
8020                    // 2D+ tensor - return a row (as a new tensor with one less dimension)
8021                    let row_size: usize = shape[1..].iter().map(|&d| d as usize).product();
8022                    let start = idx * row_size;
8023                    let end = start + row_size;
8024
8025                    if end <= data.len() {
8026                        let row_data: Vec<Value> =
8027                            data[start..end].iter().map(|&f| Value::Float(f)).collect();
8028                        let row_shape: Vec<Value> =
8029                            shape[1..].iter().map(|&d| Value::Int(d)).collect();
8030
8031                        let mut new_fields = std::collections::HashMap::new();
8032                        new_fields.insert(
8033                            "shape".to_string(),
8034                            Value::Array(Rc::new(RefCell::new(row_shape))),
8035                        );
8036                        new_fields.insert(
8037                            "data".to_string(),
8038                            Value::Array(Rc::new(RefCell::new(row_data))),
8039                        );
8040                        new_fields.insert("requires_grad".to_string(), Value::Bool(false));
8041
8042                        Ok(Value::Struct {
8043                            name: "Tensor".to_string(),
8044                            fields: Rc::new(RefCell::new(new_fields)),
8045                        })
8046                    } else {
8047                        Err(RuntimeError::index_out_of_bounds(i, shape[0] as usize))
8048                    }
8049                } else {
8050                    // Scalar tensor - can't index
8051                    Err(RuntimeError::new("Cannot index scalar tensor"))
8052                }
8053            }
8054            (coll, idx) => {
8055                crate::sigil_debug!(
8056                    "DEBUG Cannot index: collection={:?}, index={:?}",
8057                    std::mem::discriminant(&coll),
8058                    std::mem::discriminant(&idx)
8059                );
8060                Err(RuntimeError::new("Cannot index"))
8061            }
8062        }
8063    }
8064
8065    fn eval_field(&mut self, expr: &Expr, field: &Ident) -> Result<Value, RuntimeError> {
8066        if field.name == "items" {
8067            crate::sigil_debug!("DEBUG eval_field: accessing .items on expr={:?}", expr);
8068        }
8069        // Debug evidence field access
8070        if field.name == "evidence" {
8071            crate::sigil_debug!("DEBUG eval_field: accessing .evidence");
8072        }
8073        let value = self.evaluate(expr)?;
8074        if field.name == "items" {
8075            crate::sigil_debug!(
8076                "DEBUG eval_field: .items receiver value={:?}",
8077                std::mem::discriminant(&value)
8078            );
8079        }
8080        if field.name == "evidence" {
8081            crate::sigil_debug!(
8082                "DEBUG eval_field: .evidence receiver value type={:?}",
8083                std::mem::discriminant(&value)
8084            );
8085        }
8086        // Helper to get field from a value
8087        fn get_field(val: &Value, field_name: &str) -> Result<Value, RuntimeError> {
8088            // Debug all field access on IrPattern
8089            if field_name == "evidence" {
8090                crate::sigil_debug!(
8091                    "DEBUG get_field 'evidence' on value type: {:?}",
8092                    std::mem::discriminant(val)
8093                );
8094            }
8095            match val {
8096                Value::Struct { name, fields } => {
8097                    let field_val = fields.borrow().get(field_name).cloned();
8098                    if field_val.is_none() && field_name == "path" {
8099                        crate::sigil_debug!(
8100                            "DEBUG Unknown field 'path': struct={}, available={:?}",
8101                            name,
8102                            fields.borrow().keys().collect::<Vec<_>>()
8103                        );
8104                    }
8105                    // Debug evidence field access
8106                    if field_name == "evidence" || name.contains("IrPattern") {
8107                        crate::sigil_debug!("DEBUG get_field on Struct: name={}, field={}, available={:?}, found={}",
8108                            name, field_name, fields.borrow().keys().collect::<Vec<_>>(), field_val.is_some());
8109                    }
8110                    // Error on unknown fields - type checking
8111                    match field_val {
8112                        Some(v) => Ok(v),
8113                        None => Err(RuntimeError::new(format!(
8114                            "no field '{}' on struct '{}'",
8115                            field_name, name
8116                        ))),
8117                    }
8118                }
8119                Value::Tuple(t) => {
8120                    // Tuple field access like .0, .1
8121                    let idx: usize = field_name
8122                        .parse()
8123                        .map_err(|_| RuntimeError::new("Invalid tuple index"))?;
8124                    t.get(idx)
8125                        .cloned()
8126                        .ok_or_else(|| RuntimeError::new("Tuple index out of bounds"))
8127                }
8128                Value::Ref(r) => {
8129                    // Dereference and access field on inner value
8130                    get_field(&r.borrow(), field_name)
8131                }
8132                Value::Evidential { value, .. } => {
8133                    // Unwrap evidential wrapper and access field
8134                    get_field(value, field_name)
8135                }
8136                Value::Affective { value, .. } => {
8137                    // Unwrap affective wrapper and access field
8138                    get_field(value, field_name)
8139                }
8140                Value::Map(map) => {
8141                    // Map field access: map.field_name
8142                    map.borrow()
8143                        .get(field_name)
8144                        .cloned()
8145                        .ok_or_else(|| RuntimeError::new(format!("no field '{}' in map", field_name)))
8146                }
8147                Value::Variant {
8148                    fields: variant_fields,
8149                    ..
8150                } => {
8151                    // Handle struct-like enum variants (e.g., IrPattern::Ident { name, evidence, .. })
8152                    // Variant fields may be stored as a Struct value or as positional values
8153                    if let Some(inner_fields) = variant_fields {
8154                        // Try to find a Struct value that contains the field
8155                        for f in inner_fields.iter() {
8156                            if let Value::Struct {
8157                                fields: struct_fields,
8158                                ..
8159                            } = f
8160                            {
8161                                if let Some(field_val) =
8162                                    struct_fields.borrow().get(field_name).cloned()
8163                                {
8164                                    return Ok(field_val);
8165                                }
8166                            }
8167                        }
8168                        // Field not found in any struct - return Null for optional fields
8169                        Ok(Value::Null)
8170                    } else {
8171                        // No fields in variant
8172                        Ok(Value::Null)
8173                    }
8174                }
8175                other => {
8176                    // Fallback for field access on non-struct types: return null
8177                    crate::sigil_warn!(
8178                        "WARN: Cannot access field '{}' on non-struct - returning null",
8179                        field_name
8180                    );
8181                    Ok(Value::Null)
8182                }
8183            }
8184        }
8185        get_field(&value, &field.name)
8186    }
8187
8188    // Helper: Extract the root variable name from a method chain
8189    fn extract_root_var(expr: &Expr) -> Option<String> {
8190        match expr {
8191            Expr::Path(path) if path.segments.len() == 1 => {
8192                Some(path.segments[0].ident.name.clone())
8193            }
8194            Expr::MethodCall { receiver, .. } => Self::extract_root_var(receiver),
8195            _ => None,
8196        }
8197    }
8198
8199    fn eval_method_call(
8200        &mut self,
8201        receiver: &Expr,
8202        method: &Ident,
8203        args: &[Expr],
8204    ) -> Result<Value, RuntimeError> {
8205        // Special handling for String::push/push_str - needs to mutate the variable
8206        if (method.name == "push" || method.name == "push_str") && args.len() == 1 {
8207            let recv_val = self.evaluate(receiver)?;
8208            let recv_unwrapped = Self::unwrap_all(&recv_val);
8209            if let Value::String(s) = &recv_unwrapped {
8210                let arg = self.evaluate(&args[0])?;
8211                let arg_unwrapped = Self::unwrap_all(&arg);
8212                let new_s = match arg_unwrapped {
8213                    Value::Char(c) => {
8214                        let mut new_str = (**s).clone();
8215                        new_str.push(c);
8216                        new_str
8217                    }
8218                    Value::String(ref add_s) => {
8219                        let mut new_str = (**s).clone();
8220                        new_str.push_str(add_s);
8221                        new_str
8222                    }
8223                    _ => return Err(RuntimeError::new("push expects char or string argument")),
8224                };
8225                let new_val = Value::String(Rc::new(new_s));
8226
8227                // Try to extract root variable from chain and mutate it
8228                if let Some(root_var) = Self::extract_root_var(receiver) {
8229                    self.environment
8230                        .borrow_mut()
8231                        .set(&root_var, new_val.clone())?;
8232                    // Return the new value for method chaining
8233                    return Ok(new_val);
8234                }
8235
8236                // Handle field access like self.output.push(c)
8237                if let Expr::Field {
8238                    expr: base_expr,
8239                    field: field_ident,
8240                } = receiver
8241                {
8242                    let base = self.evaluate(base_expr)?;
8243                    if let Value::Struct { fields, .. } = base {
8244                        fields
8245                            .borrow_mut()
8246                            .insert(field_ident.name.clone(), new_val.clone());
8247                        // Return the new value for method chaining
8248                        return Ok(new_val);
8249                    }
8250                }
8251                // Fallback: can't mutate, just return the new string
8252                return Ok(new_val);
8253            }
8254        }
8255
8256        let recv_raw = self.evaluate(receiver)?;
8257        // Unwrap evidential/affective wrappers for method dispatch
8258        let recv = Self::unwrap_value(&recv_raw).clone();
8259
8260        // Debug: trace ALL method calls to find Lexer
8261        static METHOD_COUNT: std::sync::atomic::AtomicUsize =
8262            std::sync::atomic::AtomicUsize::new(0);
8263        let count = METHOD_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
8264        if count < 500 {
8265            let recv_type = match &recv {
8266                Value::Struct { name, .. } => format!("Struct({})", name),
8267                Value::String(s) => format!(
8268                    "String('{}')",
8269                    if s.len() <= 20 { s.as_str() } else { "<long>" }
8270                ),
8271                Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
8272                other => format!("{:?}", std::mem::discriminant(other)),
8273            };
8274            if recv_type.contains("Lexer")
8275                || method.name.contains("keyword")
8276                || method.name.contains("lex")
8277            {
8278                crate::sigil_debug!("DEBUG method #{}: {}.{}()", count, recv_type, method.name);
8279            }
8280        }
8281        // Track named arguments for reordering (same as eval_call)
8282        let mut arg_entries: Vec<(Option<String>, Value)> = Vec::new();
8283        for arg in args.iter() {
8284            let (arg_name, inner_arg) = if let Expr::NamedArg { name, value } = arg {
8285                (Some(name.name.clone()), value.as_ref())
8286            } else {
8287                (None, arg)
8288            };
8289            let val = self.evaluate(inner_arg)?;
8290            arg_entries.push((arg_name, val));
8291        }
8292        // For built-in methods, just extract values (they don't support named params)
8293        let arg_values: Vec<Value> = arg_entries.iter().map(|(_, v)| v.clone()).collect();
8294
8295        // Debug: Trace cloned/clone method calls
8296        if method.name == "cloned" || method.name == "clone" {
8297            let recv_type = match &recv {
8298                Value::Struct { name, .. } => format!("Struct({})", name),
8299                Value::Variant {
8300                    enum_name,
8301                    variant_name,
8302                    ..
8303                } => format!("Variant({}::{})", enum_name, variant_name),
8304                Value::String(_) => "String".to_string(),
8305                Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
8306                Value::Null => "Null".to_string(),
8307                other => format!("{:?}", std::mem::discriminant(other)),
8308            };
8309            crate::sigil_debug!("DEBUG {}: recv_type={}", method.name, recv_type);
8310        }
8311
8312        // Debug: Trace ALL as_str calls
8313        if method.name == "as_str" {
8314            let recv_unwrapped = Self::unwrap_all(&recv);
8315            if let Value::String(s) = &recv_unwrapped {
8316                crate::sigil_debug!("DEBUG as_str CALL: recv='{}' len={}", s, s.len());
8317            } else {
8318                crate::sigil_debug!("DEBUG as_str CALL: recv={:?} (not string)", recv_unwrapped);
8319            }
8320        }
8321
8322        // Debug: trace keyword_or_ident method calls
8323        if method.name == "keyword_or_ident" {
8324            let recv_type = match &recv {
8325                Value::Struct { name, .. } => format!("Struct({})", name),
8326                Value::String(_) => "String".to_string(),
8327                Value::Ref(r) => format!(
8328                    "Ref({})",
8329                    match &*r.borrow() {
8330                        Value::Struct { name, .. } => format!("Struct({})", name),
8331                        other => format!("{:?}", std::mem::discriminant(other)),
8332                    }
8333                ),
8334                other => format!("{:?}", std::mem::discriminant(other)),
8335            };
8336            crate::sigil_debug!("DEBUG keyword_or_ident: recv_type={}", recv_type);
8337        }
8338
8339        // Debug: Find "fn" as method argument
8340        for arg in &arg_values {
8341            let unwrapped = Self::unwrap_all(arg);
8342            if let Value::String(s) = &unwrapped {
8343                if **s == "fn" {
8344                    let recv_type = match &recv {
8345                        Value::Struct { name, .. } => format!("Struct({})", name),
8346                        Value::String(_) => "String".to_string(),
8347                        Value::Ref(_) => "Ref".to_string(),
8348                        other => format!("{:?}", std::mem::discriminant(other)),
8349                    };
8350                    crate::sigil_debug!(
8351                        "DEBUG method call with 'fn': method={}, recv_type={}",
8352                        method.name,
8353                        recv_type
8354                    );
8355                }
8356            }
8357        }
8358
8359        // Built-in methods
8360        match (&recv, method.name.as_str()) {
8361            (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
8362            (Value::Array(arr), "capacity") => Ok(Value::Int(arr.borrow().capacity() as i64)),
8363            (Value::Array(arr), "as_slice") => {
8364                // In interpreter mode, just return a clone of the array
8365                Ok(Value::Array(Rc::new(RefCell::new(arr.borrow().clone()))))
8366            }
8367            (Value::Array(arr), "push") => {
8368                if arg_values.len() != 1 {
8369                    return Err(RuntimeError::new("push expects 1 argument"));
8370                }
8371                // Check Vec<T> element type constraint
8372                if let Some(var_name) = Self::extract_root_var(receiver) {
8373                    if let Some((type_name, type_params)) = self.var_types.borrow().get(&var_name) {
8374                        if type_name == "Vec" && !type_params.is_empty() {
8375                            let expected_type = &type_params[0];
8376                            let actual_type = self.value_type_name(&arg_values[0]);
8377                            if &actual_type != expected_type {
8378                                return Err(RuntimeError::new(format!(
8379                                    "type mismatch: expected Vec<{}>.push({}), found {}",
8380                                    expected_type, expected_type, actual_type
8381                                )));
8382                            }
8383                        }
8384                    }
8385                }
8386                arr.borrow_mut().push(arg_values[0].clone());
8387                Ok(Value::Null)
8388            }
8389            (Value::Array(arr), "pop") => {
8390                match arr.borrow_mut().pop() {
8391                    Some(value) => {
8392                        // Return Option::Some(value) as a Variant
8393                        Ok(Value::Variant {
8394                            enum_name: "Option".to_string(),
8395                            variant_name: "Some".to_string(),
8396                            fields: Some(Rc::new(vec![value])),
8397                        })
8398                    }
8399                    None => {
8400                        // Return Option::None as a Variant
8401                        Ok(Value::Variant {
8402                            enum_name: "Option".to_string(),
8403                            variant_name: "None".to_string(),
8404                            fields: None,
8405                        })
8406                    }
8407                }
8408            }
8409            (Value::Array(arr), "clear") => {
8410                arr.borrow_mut().clear();
8411                Ok(Value::Null)
8412            }
8413            (Value::Array(arr), "extend") => {
8414                if arg_values.len() != 1 {
8415                    return Err(RuntimeError::new("extend expects 1 argument"));
8416                }
8417                match &arg_values[0] {
8418                    Value::Array(other) => {
8419                        arr.borrow_mut().extend(other.borrow().iter().cloned());
8420                        Ok(Value::Null)
8421                    }
8422                    _ => Err(RuntimeError::new("extend expects array argument")),
8423                }
8424            }
8425            (Value::Array(arr), "reverse") => {
8426                arr.borrow_mut().reverse();
8427                Ok(Value::Array(arr.clone()))
8428            }
8429            (Value::Array(arr), "↓")
8430            | (Value::Array(arr), "skip")
8431            | (Value::Array(arr), "drop") => {
8432                // ↓(n) -> drop/skip first n elements
8433                // Symbolic: downward selection arrow
8434                let n = match arg_values.first() {
8435                    Some(Value::Int(i)) => *i as usize,
8436                    _ => 1,
8437                };
8438                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
8439                Ok(Value::Array(Rc::new(RefCell::new(v))))
8440            }
8441            (Value::Array(arr), "take") => {
8442                // Note: ↑ alias defined in Collection Morphemes section
8443                let n = match arg_values.first() {
8444                    Some(Value::Int(i)) => *i as usize,
8445                    _ => 1,
8446                };
8447                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
8448                Ok(Value::Array(Rc::new(RefCell::new(v))))
8449            }
8450            (Value::Array(arr), "step_by") => {
8451                let n = match arg_values.first() {
8452                    Some(Value::Int(i)) if *i > 0 => *i as usize,
8453                    _ => 1,
8454                };
8455                let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
8456                Ok(Value::Array(Rc::new(RefCell::new(v))))
8457            }
8458            (Value::Array(arr), "contains") => {
8459                if arg_values.len() != 1 {
8460                    return Err(RuntimeError::new("contains expects 1 argument"));
8461                }
8462                let target = &arg_values[0];
8463                let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
8464                Ok(Value::Bool(found))
8465            }
8466            (Value::Array(arr), "position") => {
8467                // position(predicate) -> Option<usize>
8468                // Returns the index of the first element matching the predicate
8469                if arg_values.len() != 1 {
8470                    return Err(RuntimeError::new("position expects 1 argument (closure)"));
8471                }
8472                match &arg_values[0] {
8473                    Value::Function(f) => {
8474                        for (i, val) in arr.borrow().iter().enumerate() {
8475                            let result = self.call_function(f, vec![val.clone()])?;
8476                            if matches!(result, Value::Bool(true)) {
8477                                return Ok(Value::Variant {
8478                                    enum_name: "Option".to_string(),
8479                                    variant_name: "Some".to_string(),
8480                                    fields: Some(Rc::new(vec![Value::Int(i as i64)])),
8481                                });
8482                            }
8483                        }
8484                        Ok(Value::Variant {
8485                            enum_name: "Option".to_string(),
8486                            variant_name: "None".to_string(),
8487                            fields: None,
8488                        })
8489                    }
8490                    _ => Err(RuntimeError::new("position expects closure argument")),
8491                }
8492            }
8493            (Value::Array(arr), "remove") => {
8494                // remove(index) -> Value
8495                // Removes and returns the element at the given index
8496                if arg_values.len() != 1 {
8497                    return Err(RuntimeError::new("remove expects 1 argument (index)"));
8498                }
8499                let index = match &arg_values[0] {
8500                    Value::Int(i) => *i as usize,
8501                    _ => return Err(RuntimeError::new("remove() index must be integer")),
8502                };
8503                let mut borrowed = arr.borrow_mut();
8504                if index >= borrowed.len() {
8505                    return Err(RuntimeError::new(format!(
8506                        "remove index {} out of bounds for array of length {}",
8507                        index,
8508                        borrowed.len()
8509                    )));
8510                }
8511                Ok(borrowed.remove(index))
8512            }
8513            (Value::Array(arr), "insert") => {
8514                // insert(index, value) -> ()
8515                // Inserts an element at the given index
8516                if arg_values.len() != 2 {
8517                    return Err(RuntimeError::new("insert expects 2 arguments (index, value)"));
8518                }
8519                let index = match &arg_values[0] {
8520                    Value::Int(i) => *i as usize,
8521                    _ => return Err(RuntimeError::new("insert() index must be integer")),
8522                };
8523                let mut borrowed = arr.borrow_mut();
8524                if index > borrowed.len() {
8525                    return Err(RuntimeError::new(format!(
8526                        "insert index {} out of bounds for array of length {}",
8527                        index,
8528                        borrowed.len()
8529                    )));
8530                }
8531                borrowed.insert(index, arg_values[1].clone());
8532                Ok(Value::Null)
8533            }
8534            (Value::Array(arr), "index_of") => {
8535                // index_of(element) -> i64
8536                // Returns index of first matching element, or -1
8537                if arg_values.len() != 1 {
8538                    return Err(RuntimeError::new("index_of expects 1 argument"));
8539                }
8540                let target = &arg_values[0];
8541                let idx = arr.borrow().iter().position(|v| self.values_equal(v, target));
8542                match idx {
8543                    Some(i) => Ok(Value::Int(i as i64)),
8544                    None => Ok(Value::Int(-1)),
8545                }
8546            }
8547            (Value::Array(arr), "swap") => {
8548                // swap(i, j) -> ()
8549                if arg_values.len() != 2 {
8550                    return Err(RuntimeError::new("swap expects 2 arguments"));
8551                }
8552                let i = match &arg_values[0] {
8553                    Value::Int(i) => *i as usize,
8554                    _ => return Err(RuntimeError::new("swap indices must be integers")),
8555                };
8556                let j = match &arg_values[1] {
8557                    Value::Int(j) => *j as usize,
8558                    _ => return Err(RuntimeError::new("swap indices must be integers")),
8559                };
8560                let mut borrowed = arr.borrow_mut();
8561                if i >= borrowed.len() || j >= borrowed.len() {
8562                    return Err(RuntimeError::new("swap index out of bounds"));
8563                }
8564                borrowed.swap(i, j);
8565                Ok(Value::Null)
8566            }
8567            (Value::Array(arr), "truncate") => {
8568                // truncate(len) -> ()
8569                if arg_values.len() != 1 {
8570                    return Err(RuntimeError::new("truncate expects 1 argument"));
8571                }
8572                let len = match &arg_values[0] {
8573                    Value::Int(i) => *i as usize,
8574                    _ => return Err(RuntimeError::new("truncate length must be integer")),
8575                };
8576                arr.borrow_mut().truncate(len);
8577                Ok(Value::Null)
8578            }
8579            (Value::Array(arr), "retain") => {
8580                // retain(predicate) -> ()
8581                // Keeps only elements for which the predicate returns true
8582                if arg_values.len() != 1 {
8583                    return Err(RuntimeError::new("retain expects 1 argument (closure)"));
8584                }
8585                match &arg_values[0] {
8586                    Value::Function(f) => {
8587                        let kept: Vec<Value> = arr.borrow().iter().filter(|val| {
8588                            matches!(self.call_function(f, vec![(*val).clone()]), Ok(Value::Bool(true)))
8589                        }).cloned().collect();
8590                        *arr.borrow_mut() = kept;
8591                        Ok(Value::Null)
8592                    }
8593                    _ => Err(RuntimeError::new("retain expects closure argument")),
8594                }
8595            }
8596            (Value::Array(arr), "dedup") => {
8597                // dedup() -> () - removes consecutive duplicate elements
8598                let mut borrowed = arr.borrow_mut();
8599                borrowed.dedup_by(|a, b| {
8600                    // Use simple equality check
8601                    format!("{}", a) == format!("{}", b)
8602                });
8603                Ok(Value::Null)
8604            }
8605            // Tuple methods
8606            (Value::Tuple(t), "to_string") | (Value::Tuple(t), "string") => {
8607                let s: Vec<String> = t.iter().map(|v| format!("{}", v)).collect();
8608                Ok(Value::String(Rc::new(format!("({})", s.join(", ")))))
8609            }
8610            (Value::Tuple(t), "len") => Ok(Value::Int(t.len() as i64)),
8611            (Value::Tuple(t), "first") => t
8612                .first()
8613                .cloned()
8614                .ok_or_else(|| RuntimeError::new("empty tuple")),
8615            (Value::Tuple(t), "last") => t
8616                .last()
8617                .cloned()
8618                .ok_or_else(|| RuntimeError::new("empty tuple")),
8619            (Value::Tuple(t), "get") => {
8620                let idx = match arg_values.first() {
8621                    Some(Value::Int(i)) => *i as usize,
8622                    _ => return Err(RuntimeError::new("get expects integer index")),
8623                };
8624                t.get(idx)
8625                    .cloned()
8626                    .ok_or_else(|| RuntimeError::new("tuple index out of bounds"))
8627            }
8628            (Value::Array(arr), "first") | (Value::Array(arr), "next") => {
8629                Ok(arr.borrow().first().cloned().unwrap_or(Value::Null))
8630            }
8631            (Value::Array(arr), "last") => arr
8632                .borrow()
8633                .last()
8634                .cloned()
8635                .ok_or_else(|| RuntimeError::new("empty array")),
8636            (Value::Array(arr), "iter") | (Value::Array(arr), "into_iter") => {
8637                // iter()/into_iter() on an array just returns the array - iteration happens in for loops
8638                Ok(Value::Array(arr.clone()))
8639            }
8640            (Value::Array(arr), "↦") | (Value::Array(arr), "map") => {
8641                // ↦(fn) -> element-wise transformation
8642                // Symbolic: maps-to arrow (function application)
8643                if arg_values.len() != 1 {
8644                    return Err(RuntimeError::new("map expects 1 argument (closure)"));
8645                }
8646                match &arg_values[0] {
8647                    Value::Function(f) => {
8648                        let mut results = Vec::new();
8649                        for val in arr.borrow().iter() {
8650                            let result = self.call_function(f, vec![val.clone()])?;
8651                            results.push(result);
8652                        }
8653                        Ok(Value::Array(Rc::new(RefCell::new(results))))
8654                    }
8655                    _ => Err(RuntimeError::new("map expects closure argument")),
8656                }
8657            }
8658            (Value::Array(arr), "⊛")
8659            | (Value::Array(arr), "filter")
8660            | (Value::Array(arr), "select")
8661            | (Value::Array(arr), "where") => {
8662                // ⊛(predicate) -> selection/sieve by predicate
8663                // Symbolic: circled asterisk (selection operator)
8664                if arg_values.len() != 1 {
8665                    return Err(RuntimeError::new("filter expects 1 argument (closure)"));
8666                }
8667                match &arg_values[0] {
8668                    Value::Function(f) => {
8669                        let mut results = Vec::new();
8670                        for val in arr.borrow().iter() {
8671                            let keep = self.call_function(f, vec![val.clone()])?;
8672                            if matches!(keep, Value::Bool(true)) {
8673                                results.push(val.clone());
8674                            }
8675                        }
8676                        Ok(Value::Array(Rc::new(RefCell::new(results))))
8677                    }
8678                    _ => Err(RuntimeError::new("filter expects closure argument")),
8679                }
8680            }
8681            (Value::Array(arr), "∃")
8682            | (Value::Array(arr), "any")
8683            | (Value::Array(arr), "some")
8684            | (Value::Array(arr), "exists") => {
8685                // ∃(predicate) -> existential quantification
8686                // Symbolic: there exists
8687                if arg_values.len() != 1 {
8688                    return Err(RuntimeError::new("any expects 1 argument (closure)"));
8689                }
8690                match &arg_values[0] {
8691                    Value::Function(f) => {
8692                        for val in arr.borrow().iter() {
8693                            let result = self.call_function(f, vec![val.clone()])?;
8694                            if matches!(result, Value::Bool(true)) {
8695                                return Ok(Value::Bool(true));
8696                            }
8697                        }
8698                        Ok(Value::Bool(false))
8699                    }
8700                    _ => Err(RuntimeError::new("any expects closure argument")),
8701                }
8702            }
8703            (Value::Array(arr), "∀∶")
8704            | (Value::Array(arr), "all")
8705            | (Value::Array(arr), "every")
8706            | (Value::Array(arr), "forall") => {
8707                // ∀∶(predicate) -> universal quantification test (returns bool)
8708                // Symbolic: for all (with colon to distinguish from forEach)
8709                if arg_values.len() != 1 {
8710                    return Err(RuntimeError::new("all expects 1 argument (closure)"));
8711                }
8712                match &arg_values[0] {
8713                    Value::Function(f) => {
8714                        for val in arr.borrow().iter() {
8715                            let result = self.call_function(f, vec![val.clone()])?;
8716                            if !matches!(result, Value::Bool(true)) {
8717                                return Ok(Value::Bool(false));
8718                            }
8719                        }
8720                        Ok(Value::Bool(true))
8721                    }
8722                    _ => Err(RuntimeError::new("all expects closure argument")),
8723                }
8724            }
8725            (Value::Array(arr), "∃?") | (Value::Array(arr), "find") => {
8726                // ∃?(predicate) -> find first matching element
8727                // Symbolic: existential query
8728                if arg_values.len() != 1 {
8729                    return Err(RuntimeError::new("find expects 1 argument (closure)"));
8730                }
8731                match &arg_values[0] {
8732                    Value::Function(f) => {
8733                        for val in arr.borrow().iter() {
8734                            let result = self.call_function(f, vec![val.clone()])?;
8735                            if matches!(result, Value::Bool(true)) {
8736                                return Ok(Value::Variant {
8737                                    enum_name: "Option".to_string(),
8738                                    variant_name: "Some".to_string(),
8739                                    fields: Some(Rc::new(vec![val.clone()])),
8740                                });
8741                            }
8742                        }
8743                        Ok(Value::Variant {
8744                            enum_name: "Option".to_string(),
8745                            variant_name: "None".to_string(),
8746                            fields: None,
8747                        })
8748                    }
8749                    _ => Err(RuntimeError::new("find expects closure argument")),
8750                }
8751            }
8752            (Value::Array(arr), "ι")
8753            | (Value::Array(arr), "enumerate")
8754            | (Value::Array(arr), "indexed") => {
8755                // ι() -> index-value pairs
8756                // Symbolic: iota (indexing function from APL)
8757                let enumerated: Vec<Value> = arr
8758                    .borrow()
8759                    .iter()
8760                    .enumerate()
8761                    .map(|(i, v)| Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()])))
8762                    .collect();
8763                Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
8764            }
8765            (Value::Array(arr), "⊗") | (Value::Array(arr), "zip") => {
8766                // ⊗(other) -> pair elements from two arrays
8767                // Symbolic: tensor/outer product
8768                if arg_values.len() != 1 {
8769                    return Err(RuntimeError::new("zip expects 1 argument"));
8770                }
8771                match &arg_values[0] {
8772                    Value::Array(other) => {
8773                        let a = arr.borrow();
8774                        let b = other.borrow();
8775                        let zipped: Vec<Value> = a
8776                            .iter()
8777                            .zip(b.iter())
8778                            .map(|(x, y)| Value::Tuple(Rc::new(vec![x.clone(), y.clone()])))
8779                            .collect();
8780                        Ok(Value::Array(Rc::new(RefCell::new(zipped))))
8781                    }
8782                    _ => Err(RuntimeError::new("zip expects array argument")),
8783                }
8784            }
8785            // ========== Collection Morphemes (Agent-Native Symbolic API) ==========
8786            // Primary: symbolic morphemes | Aliases: English names for tooling compatibility
8787            //
8788            // Aggregation:  ⊕ (fold)  ∑ (sum)  ∏ (product)  # (count)  ⊥ (min)  ⊤ (max)  μ (mean)
8789            // Transform:    ↦ (map)   ⤳ (flatMap)  ⊏ (flatten)  ⊴ (sort)  ◉ (distinct)  ⟲ (reverse)
8790            // Selection:    ↑ (take)  ↓ (drop)  ↑⦂ (takeWhile)  ↓⦂ (dropWhile)
8791            // Quantifiers:  ∀ (forEach)  ∃ (any)  ∄ (none)  ∃! (findFirst)
8792            // Grouping:     ⫴ (groupBy)  ⊘ (partition)  ⊞ (chunk)  ⌸ (window)
8793            // Combinators:  ⊗ (zip)  ⫰ (interleave)  ⋈ (join)
8794            // Collectors:   →[] (toVec)  →{} (toSet)  →⟨⟩ (toMap)
8795            //
8796            (Value::Array(arr), "⊕")
8797            | (Value::Array(arr), "fold")
8798            | (Value::Array(arr), "reduce") => {
8799                // ⊕(initial, accumulator) -> reduces array to single value
8800                // Symbolic: binary fold operator
8801                if arg_values.len() != 2 {
8802                    return Err(RuntimeError::new(
8803                        "fold expects 2 arguments (initial, accumulator)",
8804                    ));
8805                }
8806                let mut acc = arg_values[0].clone();
8807                match &arg_values[1] {
8808                    Value::Function(f) => {
8809                        for val in arr.borrow().iter() {
8810                            acc = self.call_function(f, vec![acc, val.clone()])?;
8811                        }
8812                        Ok(acc)
8813                    }
8814                    _ => Err(RuntimeError::new(
8815                        "fold expects function as second argument",
8816                    )),
8817                }
8818            }
8819            (Value::Array(arr), "⤳")
8820            | (Value::Array(arr), "flat_map")
8821            | (Value::Array(arr), "flatMap") => {
8822                // ⤳(fn) -> monadic bind: maps then flattens one level
8823                // Symbolic: Kleisli arrow / monadic bind
8824                if arg_values.len() != 1 {
8825                    return Err(RuntimeError::new("flat_map expects 1 argument (function)"));
8826                }
8827                match &arg_values[0] {
8828                    Value::Function(f) => {
8829                        let mut results = Vec::new();
8830                        for val in arr.borrow().iter() {
8831                            let mapped = self.call_function(f, vec![val.clone()])?;
8832                            // Flatten if result is an array
8833                            match mapped {
8834                                Value::Array(inner) => {
8835                                    results.extend(inner.borrow().iter().cloned());
8836                                }
8837                                other => results.push(other),
8838                            }
8839                        }
8840                        Ok(Value::Array(Rc::new(RefCell::new(results))))
8841                    }
8842                    _ => Err(RuntimeError::new("flat_map expects function argument")),
8843                }
8844            }
8845            (Value::Array(arr), "⊏") | (Value::Array(arr), "flatten") => {
8846                // ⊏() -> flattens one level of nesting
8847                // Symbolic: level collapse operator
8848                let mut results = Vec::new();
8849                for val in arr.borrow().iter() {
8850                    match val {
8851                        Value::Array(inner) => {
8852                            results.extend(inner.borrow().iter().cloned());
8853                        }
8854                        other => results.push(other.clone()),
8855                    }
8856                }
8857                Ok(Value::Array(Rc::new(RefCell::new(results))))
8858            }
8859            (Value::Array(arr), "∀")
8860            | (Value::Array(arr), "for_each")
8861            | (Value::Array(arr), "forEach") => {
8862                // ∀(fn) -> universal quantification with side effects
8863                // Symbolic: for all elements, apply
8864                if arg_values.len() != 1 {
8865                    return Err(RuntimeError::new("for_each expects 1 argument (function)"));
8866                }
8867                match &arg_values[0] {
8868                    Value::Function(f) => {
8869                        for val in arr.borrow().iter() {
8870                            self.call_function(f, vec![val.clone()])?;
8871                        }
8872                        Ok(Value::Null)
8873                    }
8874                    _ => Err(RuntimeError::new("for_each expects function argument")),
8875                }
8876            }
8877            (Value::Array(arr), "⊙") | (Value::Array(arr), "peek") => {
8878                // ⊙(fn) -> observe without consuming: side effects, returns original
8879                // Symbolic: circled dot (observation point)
8880                if arg_values.len() != 1 {
8881                    return Err(RuntimeError::new("peek expects 1 argument (function)"));
8882                }
8883                match &arg_values[0] {
8884                    Value::Function(f) => {
8885                        for val in arr.borrow().iter() {
8886                            self.call_function(f, vec![val.clone()])?;
8887                        }
8888                        Ok(Value::Array(arr.clone()))
8889                    }
8890                    _ => Err(RuntimeError::new("peek expects function argument")),
8891                }
8892            }
8893            (Value::Array(arr), "⊴")
8894            | (Value::Array(arr), "sorted")
8895            | (Value::Array(arr), "sort") => {
8896                // ⊴() or ⊴(comparator) -> returns ordered array
8897                // Symbolic: ordering/precedes relation
8898                let mut v = arr.borrow().clone();
8899                if arg_values.is_empty() {
8900                    // Natural ordering
8901                    v.sort_by(|a, b| self.compare_values(a, b, &None));
8902                } else if let Some(Value::Function(f)) = arg_values.first() {
8903                    // Custom comparator
8904                    v.sort_by(
8905                        |a, b| match self.call_function(f, vec![a.clone(), b.clone()]) {
8906                            Ok(Value::Int(n)) => {
8907                                if n < 0 {
8908                                    std::cmp::Ordering::Less
8909                                } else if n > 0 {
8910                                    std::cmp::Ordering::Greater
8911                                } else {
8912                                    std::cmp::Ordering::Equal
8913                                }
8914                            }
8915                            _ => std::cmp::Ordering::Equal,
8916                        },
8917                    );
8918                }
8919                Ok(Value::Array(Rc::new(RefCell::new(v))))
8920            }
8921            (Value::Array(arr), "◉") | (Value::Array(arr), "distinct") => {
8922                // ◉() -> unique elements only, preserving order
8923                // Symbolic: fisheye/unique marker
8924                let mut seen = Vec::new();
8925                let mut results = Vec::new();
8926                for val in arr.borrow().iter() {
8927                    let is_dup = seen.iter().any(|v| self.values_equal(v, val));
8928                    if !is_dup {
8929                        seen.push(val.clone());
8930                        results.push(val.clone());
8931                    }
8932                }
8933                Ok(Value::Array(Rc::new(RefCell::new(results))))
8934            }
8935            (Value::Array(arr), "↑")
8936            | (Value::Array(arr), "limit")
8937            | (Value::Array(arr), "take") => {
8938                // ↑(n) -> takes first n elements
8939                // Symbolic: upward selection arrow
8940                let n = match arg_values.first() {
8941                    Some(Value::Int(i)) => *i as usize,
8942                    _ => return Err(RuntimeError::new("limit expects integer argument")),
8943                };
8944                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
8945                Ok(Value::Array(Rc::new(RefCell::new(v))))
8946            }
8947            (Value::Array(arr), "↑⦂")
8948            | (Value::Array(arr), "take_while")
8949            | (Value::Array(arr), "takeWhile") => {
8950                // ↑⦂(predicate) -> takes while predicate holds
8951                // Symbolic: conditional upward selection
8952                if arg_values.len() != 1 {
8953                    return Err(RuntimeError::new(
8954                        "take_while expects 1 argument (predicate)",
8955                    ));
8956                }
8957                match &arg_values[0] {
8958                    Value::Function(f) => {
8959                        let mut results = Vec::new();
8960                        for val in arr.borrow().iter() {
8961                            let keep = self.call_function(f, vec![val.clone()])?;
8962                            if matches!(keep, Value::Bool(true)) {
8963                                results.push(val.clone());
8964                            } else {
8965                                break;
8966                            }
8967                        }
8968                        Ok(Value::Array(Rc::new(RefCell::new(results))))
8969                    }
8970                    _ => Err(RuntimeError::new("take_while expects function argument")),
8971                }
8972            }
8973            (Value::Array(arr), "↓⦂")
8974            | (Value::Array(arr), "drop_while")
8975            | (Value::Array(arr), "dropWhile")
8976            | (Value::Array(arr), "skip_while")
8977            | (Value::Array(arr), "skipWhile") => {
8978                // ↓⦂(predicate) -> drops while predicate holds
8979                // Symbolic: conditional downward skip
8980                if arg_values.len() != 1 {
8981                    return Err(RuntimeError::new(
8982                        "drop_while expects 1 argument (predicate)",
8983                    ));
8984                }
8985                match &arg_values[0] {
8986                    Value::Function(f) => {
8987                        let mut results = Vec::new();
8988                        let mut dropping = true;
8989                        for val in arr.borrow().iter() {
8990                            if dropping {
8991                                let skip = self.call_function(f, vec![val.clone()])?;
8992                                if !matches!(skip, Value::Bool(true)) {
8993                                    dropping = false;
8994                                    results.push(val.clone());
8995                                }
8996                            } else {
8997                                results.push(val.clone());
8998                            }
8999                        }
9000                        Ok(Value::Array(Rc::new(RefCell::new(results))))
9001                    }
9002                    _ => Err(RuntimeError::new("drop_while expects function argument")),
9003                }
9004            }
9005            (Value::Array(arr), "∑") | (Value::Array(arr), "sum") => {
9006                // ∑() -> summation of numeric elements
9007                // Symbolic: standard mathematical summation
9008                let mut total = 0i64;
9009                let mut has_float = false;
9010                let mut float_total = 0.0f64;
9011                for val in arr.borrow().iter() {
9012                    match val {
9013                        Value::Int(n) => {
9014                            if has_float {
9015                                float_total += *n as f64;
9016                            } else {
9017                                total += n;
9018                            }
9019                        }
9020                        Value::Float(n) => {
9021                            if !has_float {
9022                                float_total = total as f64;
9023                                has_float = true;
9024                            }
9025                            float_total += n;
9026                        }
9027                        _ => {}
9028                    }
9029                }
9030                if has_float {
9031                    Ok(Value::Float(float_total))
9032                } else {
9033                    Ok(Value::Int(total))
9034                }
9035            }
9036            (Value::Array(arr), "∏") | (Value::Array(arr), "product") => {
9037                // ∏() -> product of numeric elements
9038                // Symbolic: standard mathematical product
9039                let mut total = 1i64;
9040                let mut has_float = false;
9041                let mut float_total = 1.0f64;
9042                for val in arr.borrow().iter() {
9043                    match val {
9044                        Value::Int(n) => {
9045                            if has_float {
9046                                float_total *= *n as f64;
9047                            } else {
9048                                total *= n;
9049                            }
9050                        }
9051                        Value::Float(n) => {
9052                            if !has_float {
9053                                float_total = total as f64;
9054                                has_float = true;
9055                            }
9056                            float_total *= n;
9057                        }
9058                        _ => {}
9059                    }
9060                }
9061                if has_float {
9062                    Ok(Value::Float(float_total))
9063                } else {
9064                    Ok(Value::Int(total))
9065                }
9066            }
9067            (Value::Array(arr), "#")
9068            | (Value::Array(arr), "count")
9069            | (Value::Array(arr), "len") => {
9070                // #() -> cardinality of collection
9071                // Symbolic: standard cardinality notation
9072                Ok(Value::Int(arr.borrow().len() as i64))
9073            }
9074            (Value::Array(arr), "⊥")
9075            | (Value::Array(arr), "min")
9076            | (Value::Array(arr), "infimum") => {
9077                // ⊥() -> lattice infimum (minimum element)
9078                // Symbolic: bottom element of partial order
9079                let borrowed = arr.borrow();
9080                if borrowed.is_empty() {
9081                    return Ok(Value::Variant {
9082                        enum_name: "Option".to_string(),
9083                        variant_name: "None".to_string(),
9084                        fields: None,
9085                    });
9086                }
9087                let mut min_val = borrowed[0].clone();
9088                for val in borrowed.iter().skip(1) {
9089                    if self.compare_values(val, &min_val, &None) == std::cmp::Ordering::Less {
9090                        min_val = val.clone();
9091                    }
9092                }
9093                Ok(Value::Variant {
9094                    enum_name: "Option".to_string(),
9095                    variant_name: "Some".to_string(),
9096                    fields: Some(Rc::new(vec![min_val])),
9097                })
9098            }
9099            (Value::Array(arr), "⊤")
9100            | (Value::Array(arr), "max")
9101            | (Value::Array(arr), "supremum") => {
9102                // ⊤() -> lattice supremum (maximum element)
9103                // Symbolic: top element of partial order
9104                let borrowed = arr.borrow();
9105                if borrowed.is_empty() {
9106                    return Ok(Value::Variant {
9107                        enum_name: "Option".to_string(),
9108                        variant_name: "None".to_string(),
9109                        fields: None,
9110                    });
9111                }
9112                let mut max_val = borrowed[0].clone();
9113                for val in borrowed.iter().skip(1) {
9114                    if self.compare_values(val, &max_val, &None) == std::cmp::Ordering::Greater {
9115                        max_val = val.clone();
9116                    }
9117                }
9118                Ok(Value::Variant {
9119                    enum_name: "Option".to_string(),
9120                    variant_name: "Some".to_string(),
9121                    fields: Some(Rc::new(vec![max_val])),
9122                })
9123            }
9124            (Value::Array(arr), "μ")
9125            | (Value::Array(arr), "average")
9126            | (Value::Array(arr), "avg")
9127            | (Value::Array(arr), "mean") => {
9128                // μ() -> statistical mean of numeric elements
9129                // Symbolic: mu for mean (statistics)
9130                let borrowed = arr.borrow();
9131                if borrowed.is_empty() {
9132                    return Ok(Value::Variant {
9133                        enum_name: "Option".to_string(),
9134                        variant_name: "None".to_string(),
9135                        fields: None,
9136                    });
9137                }
9138                let mut sum = 0.0f64;
9139                let mut count = 0usize;
9140                for val in borrowed.iter() {
9141                    match val {
9142                        Value::Int(n) => {
9143                            sum += *n as f64;
9144                            count += 1;
9145                        }
9146                        Value::Float(n) => {
9147                            sum += n;
9148                            count += 1;
9149                        }
9150                        _ => {}
9151                    }
9152                }
9153                if count == 0 {
9154                    return Ok(Value::Variant {
9155                        enum_name: "Option".to_string(),
9156                        variant_name: "None".to_string(),
9157                        fields: None,
9158                    });
9159                }
9160                Ok(Value::Variant {
9161                    enum_name: "Option".to_string(),
9162                    variant_name: "Some".to_string(),
9163                    fields: Some(Rc::new(vec![Value::Float(sum / count as f64)])),
9164                })
9165            }
9166            (Value::Array(arr), "⫴")
9167            | (Value::Array(arr), "group_by")
9168            | (Value::Array(arr), "groupBy")
9169            | (Value::Array(arr), "grouping_by")
9170            | (Value::Array(arr), "groupingBy") => {
9171                // ⫴(key_fn) -> partition by key into Map
9172                // Symbolic: vertical partition lines
9173                if arg_values.len() != 1 {
9174                    return Err(RuntimeError::new(
9175                        "group_by expects 1 argument (key function)",
9176                    ));
9177                }
9178                match &arg_values[0] {
9179                    Value::Function(f) => {
9180                        let mut groups: HashMap<String, Vec<Value>> = HashMap::new();
9181                        for val in arr.borrow().iter() {
9182                            let key = self.call_function(f, vec![val.clone()])?;
9183                            let key_str = format!("{}", key);
9184                            groups.entry(key_str).or_default().push(val.clone());
9185                        }
9186                        let mut result_map: HashMap<String, Value> = HashMap::new();
9187                        for (k, v) in groups {
9188                            result_map.insert(k, Value::Array(Rc::new(RefCell::new(v))));
9189                        }
9190                        Ok(Value::Map(Rc::new(RefCell::new(result_map))))
9191                    }
9192                    _ => Err(RuntimeError::new("group_by expects function argument")),
9193                }
9194            }
9195            (Value::Array(arr), "⊘")
9196            | (Value::Array(arr), "partition_by")
9197            | (Value::Array(arr), "partitionBy")
9198            | (Value::Array(arr), "partition") => {
9199                // ⊘(predicate) -> bisect by predicate into (true, false) tuple
9200                // Symbolic: division/bisection operator
9201                if arg_values.len() != 1 {
9202                    return Err(RuntimeError::new(
9203                        "partition expects 1 argument (predicate)",
9204                    ));
9205                }
9206                match &arg_values[0] {
9207                    Value::Function(f) => {
9208                        let mut true_list = Vec::new();
9209                        let mut false_list = Vec::new();
9210                        for val in arr.borrow().iter() {
9211                            let result = self.call_function(f, vec![val.clone()])?;
9212                            if matches!(result, Value::Bool(true)) {
9213                                true_list.push(val.clone());
9214                            } else {
9215                                false_list.push(val.clone());
9216                            }
9217                        }
9218                        Ok(Value::Tuple(Rc::new(vec![
9219                            Value::Array(Rc::new(RefCell::new(true_list))),
9220                            Value::Array(Rc::new(RefCell::new(false_list))),
9221                        ])))
9222                    }
9223                    _ => Err(RuntimeError::new("partition expects function argument")),
9224                }
9225            }
9226            (Value::Array(arr), "⋈")
9227            | (Value::Array(arr), "joining")
9228            | (Value::Array(arr), "join") => {
9229                // ⋈(separator) -> concatenate elements with separator
9230                // Symbolic: bowtie (relational join)
9231                let sep = match arg_values.first() {
9232                    Some(Value::String(s)) => s.to_string(),
9233                    Some(Value::Char(c)) => c.to_string(),
9234                    _ => "".to_string(),
9235                };
9236                let parts: Vec<String> = arr.borrow().iter().map(|v| format!("{}", v)).collect();
9237                Ok(Value::String(Rc::new(parts.join(&sep))))
9238            }
9239            (Value::Array(arr), "∃!")
9240            | (Value::Array(arr), "find_first")
9241            | (Value::Array(arr), "findFirst")
9242            | (Value::Array(arr), "first") => {
9243                // ∃!() -> unique existence: first element as Option
9244                // Symbolic: exists unique
9245                match arr.borrow().first() {
9246                    Some(v) => Ok(Value::Variant {
9247                        enum_name: "Option".to_string(),
9248                        variant_name: "Some".to_string(),
9249                        fields: Some(Rc::new(vec![v.clone()])),
9250                    }),
9251                    None => Ok(Value::Variant {
9252                        enum_name: "Option".to_string(),
9253                        variant_name: "None".to_string(),
9254                        fields: None,
9255                    }),
9256                }
9257            }
9258            (Value::Array(arr), "∃⁻¹")
9259            | (Value::Array(arr), "find_last")
9260            | (Value::Array(arr), "findLast")
9261            | (Value::Array(arr), "last") => {
9262                // ∃⁻¹() -> inverse existence: last element as Option
9263                // Symbolic: exists inverse (from end)
9264                match arr.borrow().last() {
9265                    Some(v) => Ok(Value::Variant {
9266                        enum_name: "Option".to_string(),
9267                        variant_name: "Some".to_string(),
9268                        fields: Some(Rc::new(vec![v.clone()])),
9269                    }),
9270                    None => Ok(Value::Variant {
9271                        enum_name: "Option".to_string(),
9272                        variant_name: "None".to_string(),
9273                        fields: None,
9274                    }),
9275                }
9276            }
9277            (Value::Array(arr), "∄")
9278            | (Value::Array(arr), "none_match")
9279            | (Value::Array(arr), "noneMatch")
9280            | (Value::Array(arr), "none") => {
9281                // ∄(predicate) -> negated existence: true if none match
9282                // Symbolic: there does not exist
9283                if arg_values.is_empty() {
9284                    // No predicate - check if all elements are falsy
9285                    for val in arr.borrow().iter() {
9286                        let is_truthy = match val {
9287                            Value::Bool(true) => true,
9288                            Value::Int(n) if *n != 0 => true,
9289                            _ => false,
9290                        };
9291                        if is_truthy {
9292                            return Ok(Value::Bool(false));
9293                        }
9294                    }
9295                    return Ok(Value::Bool(true));
9296                }
9297                match &arg_values[0] {
9298                    Value::Function(f) => {
9299                        for val in arr.borrow().iter() {
9300                            let result = self.call_function(f, vec![val.clone()])?;
9301                            if matches!(result, Value::Bool(true)) {
9302                                return Ok(Value::Bool(false));
9303                            }
9304                        }
9305                        Ok(Value::Bool(true))
9306                    }
9307                    _ => Err(RuntimeError::new("none_match expects function argument")),
9308                }
9309            }
9310            (Value::Array(arr), "→[]")
9311            | (Value::Array(arr), "collect")
9312            | (Value::Array(arr), "to_vec")
9313            | (Value::Array(arr), "toList") => {
9314                // →[]() -> materialize to array
9315                // Symbolic: arrow to array brackets
9316                Ok(Value::Array(Rc::new(RefCell::new(arr.borrow().clone()))))
9317            }
9318            (Value::Array(arr), "→{}")
9319            | (Value::Array(arr), "to_set")
9320            | (Value::Array(arr), "toSet") => {
9321                // →{}() -> materialize to set
9322                // Symbolic: arrow to set braces
9323                let mut set = HashSet::new();
9324                for val in arr.borrow().iter() {
9325                    set.insert(format!("{}", val));
9326                }
9327                Ok(Value::Set(Rc::new(RefCell::new(set))))
9328            }
9329            (Value::Array(arr), "→⟨⟩")
9330            | (Value::Array(arr), "to_map")
9331            | (Value::Array(arr), "toMap") => {
9332                // →⟨⟩(key_fn, value_fn) -> materialize to map
9333                // Symbolic: arrow to angle brackets (key-value)
9334                if arg_values.len() < 2 {
9335                    return Err(RuntimeError::new(
9336                        "to_map expects 2 arguments (key_fn, value_fn)",
9337                    ));
9338                }
9339                match (&arg_values[0], &arg_values[1]) {
9340                    (Value::Function(key_fn), Value::Function(val_fn)) => {
9341                        let mut result_map: HashMap<String, Value> = HashMap::new();
9342                        for val in arr.borrow().iter() {
9343                            let key = self.call_function(key_fn, vec![val.clone()])?;
9344                            let value = self.call_function(val_fn, vec![val.clone()])?;
9345                            result_map.insert(format!("{}", key), value);
9346                        }
9347                        Ok(Value::Map(Rc::new(RefCell::new(result_map))))
9348                    }
9349                    _ => Err(RuntimeError::new("to_map expects function arguments")),
9350                }
9351            }
9352            (Value::Array(arr), "⊞")
9353            | (Value::Array(arr), "chunk")
9354            | (Value::Array(arr), "chunked") => {
9355                // ⊞(size) -> partition into fixed-size blocks
9356                // Symbolic: squared plus (blocked grouping)
9357                let size = match arg_values.first() {
9358                    Some(Value::Int(n)) if *n > 0 => *n as usize,
9359                    _ => return Err(RuntimeError::new("chunk expects positive integer")),
9360                };
9361                let chunks: Vec<Value> = arr
9362                    .borrow()
9363                    .chunks(size)
9364                    .map(|chunk| Value::Array(Rc::new(RefCell::new(chunk.to_vec()))))
9365                    .collect();
9366                Ok(Value::Array(Rc::new(RefCell::new(chunks))))
9367            }
9368            (Value::Array(arr), "⌸")
9369            | (Value::Array(arr), "windowed")
9370            | (Value::Array(arr), "windows")
9371            | (Value::Array(arr), "sliding") => {
9372                // ⌸(size) -> sliding window view
9373                // Symbolic: quad/window frame
9374                let size = match arg_values.first() {
9375                    Some(Value::Int(n)) if *n > 0 => *n as usize,
9376                    _ => return Err(RuntimeError::new("windowed expects positive integer")),
9377                };
9378                let borrowed = arr.borrow();
9379                if borrowed.len() < size {
9380                    return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
9381                }
9382                let windows: Vec<Value> = borrowed
9383                    .windows(size)
9384                    .map(|w| Value::Array(Rc::new(RefCell::new(w.to_vec()))))
9385                    .collect();
9386                Ok(Value::Array(Rc::new(RefCell::new(windows))))
9387            }
9388            (Value::Array(arr), "⫰") | (Value::Array(arr), "interleave") => {
9389                // ⫰(other) -> alternating merge of two arrays
9390                // Symbolic: interleave/weave pattern
9391                if arg_values.len() != 1 {
9392                    return Err(RuntimeError::new("interleave expects 1 argument"));
9393                }
9394                match &arg_values[0] {
9395                    Value::Array(other) => {
9396                        let a = arr.borrow();
9397                        let b = other.borrow();
9398                        let mut result = Vec::new();
9399                        let max_len = a.len().max(b.len());
9400                        for i in 0..max_len {
9401                            if i < a.len() {
9402                                result.push(a[i].clone());
9403                            }
9404                            if i < b.len() {
9405                                result.push(b[i].clone());
9406                            }
9407                        }
9408                        Ok(Value::Array(Rc::new(RefCell::new(result))))
9409                    }
9410                    _ => Err(RuntimeError::new("interleave expects array argument")),
9411                }
9412            }
9413            (Value::Array(arr), "⟲")
9414            | (Value::Array(arr), "reversed")
9415            | (Value::Array(arr), "reverse") => {
9416                // ⟲() -> reversed sequence
9417                // Symbolic: rotation/reversal arrow
9418                arr.borrow_mut().reverse();
9419                Ok(Value::Array(arr.clone()))
9420            }
9421            (Value::Array(arr), "⧢")
9422            | (Value::Array(arr), "shuffled")
9423            | (Value::Array(arr), "shuffle") => {
9424                // ⧢() -> randomly permuted sequence
9425                // Symbolic: shuffle/randomize
9426                use std::collections::hash_map::DefaultHasher;
9427                use std::hash::{Hash, Hasher};
9428                use std::time::{SystemTime, UNIX_EPOCH};
9429
9430                let mut v = arr.borrow().clone();
9431                // Simple Fisher-Yates shuffle with time-based seed
9432                let seed = SystemTime::now()
9433                    .duration_since(UNIX_EPOCH)
9434                    .map(|d| d.as_nanos())
9435                    .unwrap_or(0);
9436                let mut hasher = DefaultHasher::new();
9437                seed.hash(&mut hasher);
9438                let mut rng_state = hasher.finish();
9439
9440                for i in (1..v.len()).rev() {
9441                    rng_state = rng_state.wrapping_mul(6364136223846793005).wrapping_add(1);
9442                    let j = (rng_state as usize) % (i + 1);
9443                    v.swap(i, j);
9444                }
9445                Ok(Value::Array(Rc::new(RefCell::new(v))))
9446            }
9447            (Value::Array(arr), "∅?")
9448            | (Value::Array(arr), "is_empty")
9449            | (Value::Array(arr), "isEmpty") => {
9450                // ∅?() -> test for emptiness
9451                // Symbolic: empty set query
9452                Ok(Value::Bool(arr.borrow().is_empty()))
9453            }
9454            (Value::Array(arr), "@") | (Value::Array(arr), "get") | (Value::Array(arr), "at") => {
9455                // @(index) -> indexed access as Option, supports negative indices
9456                // Symbolic: at/address operator
9457                let idx = match arg_values.first() {
9458                    Some(Value::Int(i)) => *i,
9459                    _ => return Err(RuntimeError::new("get expects integer index")),
9460                };
9461                let borrowed = arr.borrow();
9462                let actual_idx = if idx < 0 {
9463                    (borrowed.len() as i64 + idx) as usize
9464                } else {
9465                    idx as usize
9466                };
9467                match borrowed.get(actual_idx) {
9468                    Some(v) => Ok(Value::Variant {
9469                        enum_name: "Option".to_string(),
9470                        variant_name: "Some".to_string(),
9471                        fields: Some(Rc::new(vec![v.clone()])),
9472                    }),
9473                    None => Ok(Value::Variant {
9474                        enum_name: "Option".to_string(),
9475                        variant_name: "None".to_string(),
9476                        fields: None,
9477                    }),
9478                }
9479            }
9480            // ========== End Collection Morphemes ==========
9481            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
9482            (Value::String(s), "chars") => {
9483                let chars: Vec<Value> = s.chars().map(Value::Char).collect();
9484                Ok(Value::Array(Rc::new(RefCell::new(chars))))
9485            }
9486            (Value::String(s), "as_bytes") => {
9487                let bytes: Vec<Value> = s.as_bytes().iter().map(|b| Value::Int(*b as i64)).collect();
9488                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
9489            }
9490            (Value::String(s), "bytes") => {
9491                let bytes: Vec<Value> = s.as_bytes().iter().map(|b| Value::Int(*b as i64)).collect();
9492                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
9493            }
9494            (Value::String(s), "contains") => {
9495                if arg_values.len() != 1 {
9496                    return Err(RuntimeError::new("contains expects 1 argument"));
9497                }
9498                match &arg_values[0] {
9499                    Value::String(sub) => Ok(Value::Bool(s.contains(sub.as_str()))),
9500                    Value::Char(c) => Ok(Value::Bool(s.contains(*c))),
9501                    Value::Ref(inner) => {
9502                        if let Value::String(sub) = &*inner.borrow() {
9503                            Ok(Value::Bool(s.contains(sub.as_str())))
9504                        } else {
9505                            Err(RuntimeError::new("contains expects string or char"))
9506                        }
9507                    }
9508                    _ => Err(RuntimeError::new("contains expects string or char")),
9509                }
9510            }
9511            (Value::String(s), "as_str") => {
9512                if s.len() <= 10 {
9513                    crate::sigil_debug!("DEBUG as_str: '{}'", s);
9514                }
9515                Ok(Value::String(s.clone()))
9516            }
9517            (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
9518            (Value::String(s), "into") => Ok(Value::String(s.clone())), // into() for String just returns String
9519            (Value::String(s), "starts_with") => {
9520                if arg_values.len() != 1 {
9521                    return Err(RuntimeError::new("starts_with expects 1 argument"));
9522                }
9523                match &arg_values[0] {
9524                    Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
9525                    _ => Err(RuntimeError::new("starts_with expects string")),
9526                }
9527            }
9528            (Value::String(s), "ends_with") => {
9529                if arg_values.len() != 1 {
9530                    return Err(RuntimeError::new("ends_with expects 1 argument"));
9531                }
9532                match &arg_values[0] {
9533                    Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
9534                    _ => Err(RuntimeError::new("ends_with expects string")),
9535                }
9536            }
9537            (Value::String(s), "strip_prefix") => {
9538                if arg_values.len() != 1 {
9539                    return Err(RuntimeError::new("strip_prefix expects 1 argument"));
9540                }
9541                match &arg_values[0] {
9542                    Value::String(prefix) => match s.strip_prefix(prefix.as_str()) {
9543                        Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
9544                        None => Ok(Value::Null),
9545                    },
9546                    _ => Err(RuntimeError::new("strip_prefix expects string")),
9547                }
9548            }
9549            (Value::String(s), "strip_suffix") => {
9550                if arg_values.len() != 1 {
9551                    return Err(RuntimeError::new("strip_suffix expects 1 argument"));
9552                }
9553                match &arg_values[0] {
9554                    Value::String(suffix) => match s.strip_suffix(suffix.as_str()) {
9555                        Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
9556                        None => Ok(Value::Null),
9557                    },
9558                    _ => Err(RuntimeError::new("strip_suffix expects string")),
9559                }
9560            }
9561            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
9562            (Value::String(s), "capacity") => Ok(Value::Int(s.capacity() as i64)),
9563            (Value::String(s), "find") => {
9564                if arg_values.len() != 1 {
9565                    return Err(RuntimeError::new("find expects 1 argument"));
9566                }
9567                match &arg_values[0] {
9568                    Value::Char(c) => match s.find(*c) {
9569                        Some(idx) => Ok(Value::Variant {
9570                            enum_name: "Option".to_string(),
9571                            variant_name: "Some".to_string(),
9572                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
9573                        }),
9574                        None => Ok(Value::Variant {
9575                            enum_name: "Option".to_string(),
9576                            variant_name: "None".to_string(),
9577                            fields: None,
9578                        }),
9579                    },
9580                    Value::String(pattern) => match s.find(pattern.as_str()) {
9581                        Some(idx) => Ok(Value::Variant {
9582                            enum_name: "Option".to_string(),
9583                            variant_name: "Some".to_string(),
9584                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
9585                        }),
9586                        None => Ok(Value::Variant {
9587                            enum_name: "Option".to_string(),
9588                            variant_name: "None".to_string(),
9589                            fields: None,
9590                        }),
9591                    },
9592                    Value::Function(f) => {
9593                        for (idx, c) in s.chars().enumerate() {
9594                            let result = self.call_function(f, vec![Value::Char(c)])?;
9595                            if let Value::Bool(true) = result {
9596                                return Ok(Value::Variant {
9597                                    enum_name: "Option".to_string(),
9598                                    variant_name: "Some".to_string(),
9599                                    fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
9600                                });
9601                            }
9602                        }
9603                        Ok(Value::Variant {
9604                            enum_name: "Option".to_string(),
9605                            variant_name: "None".to_string(),
9606                            fields: None,
9607                        })
9608                    }
9609                    _ => Err(RuntimeError::new("find expects a char, string, or closure")),
9610                }
9611            }
9612            (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
9613            (Value::String(s), "concat") => {
9614                if arg_values.len() != 1 {
9615                    return Err(RuntimeError::new("concat expects 1 argument"));
9616                }
9617                match &arg_values[0] {
9618                    Value::String(other) => {
9619                        let mut result = (**s).clone();
9620                        result.push_str(other);
9621                        Ok(Value::String(Rc::new(result)))
9622                    }
9623                    _ => Err(RuntimeError::new("concat expects string argument")),
9624                }
9625            }
9626            (Value::String(s), "as_ptr") => {
9627                // Return the string itself - FFI emulation doesn't need real pointers
9628                Ok(Value::String(s.clone()))
9629            }
9630            (Value::String(_), "is_null") => Ok(Value::Bool(false)),
9631            (Value::Null, "is_null") => Ok(Value::Bool(true)),
9632            (Value::String(s), "char_at") => {
9633                if arg_values.len() != 1 {
9634                    return Err(RuntimeError::new("char_at expects 1 argument"));
9635                }
9636                let idx = match &arg_values[0] {
9637                    Value::Int(i) => *i as usize,
9638                    _ => return Err(RuntimeError::new("char_at expects integer index")),
9639                };
9640                // Use byte-based indexing to match the self-hosted lexer's pos tracking
9641                // which increments by c.len_utf8() (byte count, not character count)
9642                if idx < s.len() {
9643                    // Get the character starting at byte position idx
9644                    let remaining = &s[idx..];
9645                    match remaining.chars().next() {
9646                        Some(c) => Ok(Value::Char(c)),
9647                        None => Ok(Value::Null),
9648                    }
9649                } else {
9650                    Ok(Value::Null) // Out of bounds
9651                }
9652            }
9653            (Value::String(s), "chars") => {
9654                let chars: Vec<Value> = s.chars().map(Value::Char).collect();
9655                Ok(Value::Array(Rc::new(RefCell::new(chars))))
9656            }
9657            (Value::String(s), "bytes") => {
9658                let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
9659                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
9660            }
9661            (Value::String(s), "split") => {
9662                if arg_values.len() != 1 {
9663                    return Err(RuntimeError::new("split expects 1 argument"));
9664                }
9665                match &arg_values[0] {
9666                    Value::String(sep) => {
9667                        let parts: Vec<Value> = s
9668                            .split(sep.as_str())
9669                            .map(|p| Value::String(Rc::new(p.to_string())))
9670                            .collect();
9671                        Ok(Value::Array(Rc::new(RefCell::new(parts))))
9672                    }
9673                    Value::Char(sep) => {
9674                        let parts: Vec<Value> = s
9675                            .split(*sep)
9676                            .map(|p| Value::String(Rc::new(p.to_string())))
9677                            .collect();
9678                        Ok(Value::Array(Rc::new(RefCell::new(parts))))
9679                    }
9680                    _ => Err(RuntimeError::new("split expects string or char separator")),
9681                }
9682            }
9683            // Char methods
9684            (Value::Char(c), "len_utf8") => Ok(Value::Int(c.len_utf8() as i64)),
9685            (Value::Char(c), "is_alphabetic") => Ok(Value::Bool(c.is_alphabetic())),
9686            (Value::Char(c), "is_alphanumeric") => Ok(Value::Bool(c.is_alphanumeric())),
9687            (Value::Char(c), "is_ascii_alphanumeric") => Ok(Value::Bool(c.is_ascii_alphanumeric())),
9688            (Value::Char(c), "is_ascii_alphabetic") => Ok(Value::Bool(c.is_ascii_alphabetic())),
9689            (Value::Char(c), "is_ascii_digit") => Ok(Value::Bool(c.is_ascii_digit())),
9690            (Value::Char(c), "is_ascii_hexdigit") => Ok(Value::Bool(c.is_ascii_hexdigit())),
9691            (Value::Char(c), "is_ascii") => Ok(Value::Bool(c.is_ascii())),
9692            (Value::Char(c), "is_digit") => {
9693                let radix = if arg_values.is_empty() {
9694                    10
9695                } else {
9696                    match &arg_values[0] {
9697                        Value::Int(n) => *n as u32,
9698                        _ => 10,
9699                    }
9700                };
9701                Ok(Value::Bool(c.is_digit(radix)))
9702            }
9703            (Value::Char(c), "is_numeric") => Ok(Value::Bool(c.is_numeric())),
9704            (Value::Char(c), "is_whitespace") => Ok(Value::Bool(c.is_whitespace())),
9705            (Value::Char(c), "is_uppercase") => Ok(Value::Bool(c.is_uppercase())),
9706            (Value::Char(c), "is_lowercase") => Ok(Value::Bool(c.is_lowercase())),
9707            (Value::Char(c), "to_uppercase") => {
9708                let upper: String = c.to_uppercase().collect();
9709                Ok(Value::String(Rc::new(upper)))
9710            }
9711            (Value::Char(c), "to_lowercase") => {
9712                let lower: String = c.to_lowercase().collect();
9713                Ok(Value::String(Rc::new(lower)))
9714            }
9715            (Value::Char(c), "to_string") => Ok(Value::String(Rc::new(c.to_string()))),
9716            (Value::Char(c), "to_digit") => {
9717                let radix = if arg_values.is_empty() {
9718                    10
9719                } else {
9720                    match &arg_values[0] {
9721                        Value::Int(n) => *n as u32,
9722                        _ => 10,
9723                    }
9724                };
9725                match c.to_digit(radix) {
9726                    Some(d) => Ok(Value::Int(d as i64)),
9727                    None => Ok(Value::Null),
9728                }
9729            }
9730            (Value::Char(c), "to_ascii_uppercase") => Ok(Value::Char(c.to_ascii_uppercase())),
9731            (Value::Char(c), "to_ascii_lowercase") => Ok(Value::Char(c.to_ascii_lowercase())),
9732            (Value::Char(c), "clone") => Ok(Value::Char(*c)),
9733            (Value::String(s), "upper")
9734            | (Value::String(s), "uppercase")
9735            | (Value::String(s), "to_uppercase") => Ok(Value::String(Rc::new(s.to_uppercase()))),
9736            (Value::String(s), "lower")
9737            | (Value::String(s), "lowercase")
9738            | (Value::String(s), "to_lowercase") => Ok(Value::String(Rc::new(s.to_lowercase()))),
9739            (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
9740            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
9741            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
9742            (Value::String(s), "capacity") => Ok(Value::Int(s.capacity() as i64)),
9743            // Path-like methods for strings (treat string as file path)
9744            (Value::String(s), "exists") => {
9745                Ok(Value::Bool(std::path::Path::new(s.as_str()).exists()))
9746            }
9747            (Value::String(s), "is_dir") => {
9748                Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir()))
9749            }
9750            (Value::String(s), "is_file") => {
9751                Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file()))
9752            }
9753            (Value::String(s), "join") => {
9754                // Path join: "dir".join("file") => "dir/file"
9755                if arg_values.len() != 1 {
9756                    return Err(RuntimeError::new(&format!(
9757                        "join expects 1 argument, got {}",
9758                        arg_values.len()
9759                    )));
9760                }
9761                let other = match &arg_values[0] {
9762                    Value::String(s2) => s2.as_str().to_string(),
9763                    other => {
9764                        return Err(RuntimeError::new(&format!(
9765                            "join expects String argument, got {:?}",
9766                            other
9767                        )))
9768                    }
9769                };
9770                let path = std::path::Path::new(s.as_str()).join(&other);
9771                Ok(Value::String(Rc::new(path.to_string_lossy().to_string())))
9772            }
9773            (Value::String(s), "parent") => {
9774                // Get parent directory
9775                let path = std::path::Path::new(s.as_str());
9776                match path.parent() {
9777                    Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
9778                    None => Ok(Value::Null),
9779                }
9780            }
9781            (Value::String(s), "file_name") => {
9782                // Get file name component
9783                let path = std::path::Path::new(s.as_str());
9784                match path.file_name() {
9785                    Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
9786                    None => Ok(Value::Null),
9787                }
9788            }
9789            (Value::String(s), "extension") => {
9790                // Get file extension
9791                let path = std::path::Path::new(s.as_str());
9792                match path.extension() {
9793                    Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
9794                    None => Ok(Value::Null),
9795                }
9796            }
9797            // Result-like chaining for strings (used when string represents a Result-like value)
9798            (Value::String(_), "and_then") | (Value::String(_), "or_else") => {
9799                // Just pass through - these are no-ops for plain strings
9800                Ok(recv.clone())
9801            }
9802            (Value::String(s), "first") => s
9803                .chars()
9804                .next()
9805                .map(Value::Char)
9806                .ok_or_else(|| RuntimeError::new("empty string")),
9807            (Value::String(s), "last") => s
9808                .chars()
9809                .last()
9810                .map(Value::Char)
9811                .ok_or_else(|| RuntimeError::new("empty string")),
9812            (Value::Array(arr), "is_empty") => Ok(Value::Bool(arr.borrow().is_empty())),
9813            (Value::Array(arr), "clone") => {
9814                Ok(Value::Array(Rc::new(RefCell::new(arr.borrow().clone()))))
9815            }
9816            (Value::Array(arr), "collect") => {
9817                // collect() on array just returns the array itself
9818                // It's the terminal operation that materializes pipeline results
9819                Ok(Value::Array(arr.clone()))
9820            }
9821            (Value::Array(arr), "join") => {
9822                let separator = if arg_values.is_empty() {
9823                    String::new()
9824                } else {
9825                    match &arg_values[0] {
9826                        Value::String(s) => (**s).clone(),
9827                        _ => return Err(RuntimeError::new("join separator must be string")),
9828                    }
9829                };
9830                let parts: Vec<String> =
9831                    arr.borrow().iter().map(|v| self.format_value(v)).collect();
9832                Ok(Value::String(Rc::new(parts.join(&separator))))
9833            }
9834            // Map methods
9835            (Value::Map(m), "insert") => {
9836                if arg_values.len() != 2 {
9837                    return Err(RuntimeError::new("insert expects 2 arguments"));
9838                }
9839                let key = match &arg_values[0] {
9840                    Value::String(s) => (**s).clone(),
9841                    _ => format!("{}", arg_values[0]),
9842                };
9843                m.borrow_mut().insert(key, arg_values[1].clone());
9844                Ok(Value::Null)
9845            }
9846            (Value::Map(m), "get") => {
9847                if arg_values.len() != 1 {
9848                    return Err(RuntimeError::new("get expects 1 argument"));
9849                }
9850                let key = match &arg_values[0] {
9851                    Value::String(s) => (**s).clone(),
9852                    _ => format!("{}", arg_values[0]),
9853                };
9854                Ok(m.borrow().get(&key).cloned().unwrap_or(Value::Null))
9855            }
9856            (Value::Map(m), "contains_key") => {
9857                if arg_values.len() != 1 {
9858                    return Err(RuntimeError::new("contains_key expects 1 argument"));
9859                }
9860                let key = match &arg_values[0] {
9861                    Value::String(s) => (**s).clone(),
9862                    _ => format!("{}", arg_values[0]),
9863                };
9864                Ok(Value::Bool(m.borrow().contains_key(&key)))
9865            }
9866            (Value::Map(m), "len") => Ok(Value::Int(m.borrow().len() as i64)),
9867            (Value::Map(m), "is_empty") => Ok(Value::Bool(m.borrow().is_empty())),
9868            (Value::Map(m), "keys") => {
9869                let keys: Vec<Value> = m
9870                    .borrow()
9871                    .keys()
9872                    .map(|k| Value::String(Rc::new(k.clone())))
9873                    .collect();
9874                Ok(Value::Array(Rc::new(RefCell::new(keys))))
9875            }
9876            (Value::Map(m), "values") => {
9877                let values: Vec<Value> = m.borrow().values().cloned().collect();
9878                Ok(Value::Array(Rc::new(RefCell::new(values))))
9879            }
9880            // Ref methods
9881            (Value::Ref(r), "cloned") => {
9882                // Clone the inner value
9883                Ok(r.borrow().clone())
9884            }
9885            (Value::Ref(r), "borrow") => {
9886                // Return a reference to the inner value
9887                Ok(recv.clone())
9888            }
9889            (Value::Ref(r), "borrow_mut") => {
9890                // Return a reference to the inner value (mutable in place)
9891                Ok(recv.clone())
9892            }
9893            // Forward method calls on Ref to inner value (struct method lookup)
9894            (Value::Ref(r), _) => {
9895                // Dereference and look up method on inner struct
9896                let inner = r.borrow().clone();
9897                if let Value::Struct { name, fields } = &inner {
9898                    // Try struct method lookup with the inner struct
9899                    let qualified_name = format!("{}·{}", name, method.name);
9900                    let func = self
9901                        .globals
9902                        .borrow()
9903                        .get(&qualified_name)
9904                        .map(|v| v.clone());
9905                    if let Some(func) = func {
9906                        if let Value::Function(f) = func {
9907                            let f = Self::wrap_with_const_generics(&f, fields);
9908                            // Set current Self type for Self { ... } resolution
9909                            let old_self_type = self.current_self_type.take();
9910                            self.current_self_type = Some(name.clone());
9911
9912                            // Pass the Ref as the receiver (for &mut self methods)
9913                            // Reorder named args to match function params (skip first param which is self)
9914                            let reordered = if f.params.len() > 1 {
9915                                Self::reorder_named_args(
9916                                    &f.params[1..].to_vec(),
9917                                    arg_entries.clone(),
9918                                )?
9919                            } else {
9920                                arg_values.clone()
9921                            };
9922                            let mut all_args = vec![recv.clone()];
9923                            all_args.extend(reordered);
9924                            let result = self.call_function(&f, all_args);
9925
9926                            // Restore old Self type
9927                            self.current_self_type = old_self_type;
9928                            return result;
9929                        } else if let Value::BuiltIn(b) = func {
9930                            let mut all_args = vec![recv.clone()];
9931                            all_args.extend(arg_values.clone());
9932                            return (b.func)(self, all_args);
9933                        }
9934                    }
9935
9936                    // If struct name is "Self", search by matching field names
9937                    if name == "Self" {
9938                        let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
9939
9940                        // Search through registered types to find a matching struct
9941                        for (type_name, type_def) in &self.types {
9942                            if let TypeDef::Struct(struct_def) = type_def {
9943                                let def_fields: Vec<String> = match &struct_def.fields {
9944                                    crate::ast::StructFields::Named(fs) => {
9945                                        fs.iter().map(|f| f.name.name.clone()).collect()
9946                                    }
9947                                    _ => continue,
9948                                };
9949
9950                                // Match if our fields exist in the definition
9951                                let matches = field_names.iter().all(|f| def_fields.contains(f));
9952                                if matches {
9953                                    let qualified_name = format!("{}·{}", type_name, method.name);
9954                                    let func = self
9955                                        .globals
9956                                        .borrow()
9957                                        .get(&qualified_name)
9958                                        .map(|v| v.clone());
9959                                    if let Some(func) = func {
9960                                        if let Value::Function(f) = func {
9961                                            let f = Self::wrap_with_const_generics(&f, fields);
9962                                            // Set current Self type for Self { ... } resolution
9963                                            let old_self_type = self.current_self_type.take();
9964                                            self.current_self_type = Some(type_name.clone());
9965
9966                                            // Reorder named args to match function params (skip first param which is self)
9967                                            let reordered = if f.params.len() > 1 {
9968                                                Self::reorder_named_args(
9969                                                    &f.params[1..].to_vec(),
9970                                                    arg_entries.clone(),
9971                                                )?
9972                                            } else {
9973                                                arg_values.clone()
9974                                            };
9975                                            let mut all_args = vec![recv.clone()];
9976                                            all_args.extend(reordered);
9977                                            let result = self.call_function(&f, all_args);
9978
9979                                            // Restore old Self type
9980                                            self.current_self_type = old_self_type;
9981                                            return result;
9982                                        } else if let Value::BuiltIn(b) = func {
9983                                            let mut all_args = vec![recv.clone()];
9984                                            all_args.extend(arg_values.clone());
9985                                            return (b.func)(self, all_args);
9986                                        }
9987                                    }
9988                                }
9989                            }
9990                        }
9991                    }
9992
9993                    // Built-in methods for PathBuf struct
9994                    if name == "PathBuf" || name == "Path" {
9995                        if let Some(Value::String(path)) = fields.borrow().get("path").cloned() {
9996                            match method.name.as_str() {
9997                                "exists" => {
9998                                    return Ok(Value::Bool(
9999                                        std::path::Path::new(path.as_str()).exists(),
10000                                    ))
10001                                }
10002                                "is_dir" => {
10003                                    return Ok(Value::Bool(
10004                                        std::path::Path::new(path.as_str()).is_dir(),
10005                                    ))
10006                                }
10007                                "is_file" => {
10008                                    return Ok(Value::Bool(
10009                                        std::path::Path::new(path.as_str()).is_file(),
10010                                    ))
10011                                }
10012                                "join" => {
10013                                    if let Some(Value::String(other)) = arg_values.first() {
10014                                        let new_path = std::path::Path::new(path.as_str())
10015                                            .join(other.as_str());
10016                                        let mut new_fields = std::collections::HashMap::new();
10017                                        new_fields.insert(
10018                                            "path".to_string(),
10019                                            Value::String(Rc::new(
10020                                                new_path.to_string_lossy().to_string(),
10021                                            )),
10022                                        );
10023                                        return Ok(Value::Struct {
10024                                            name: "PathBuf".to_string(),
10025                                            fields: Rc::new(RefCell::new(new_fields)),
10026                                        });
10027                                    }
10028                                    return Err(RuntimeError::new("join requires string argument"));
10029                                }
10030                                "parent" => {
10031                                    let p = std::path::Path::new(path.as_str());
10032                                    return match p.parent() {
10033                                        Some(par) => {
10034                                            let mut new_fields = std::collections::HashMap::new();
10035                                            new_fields.insert(
10036                                                "path".to_string(),
10037                                                Value::String(Rc::new(
10038                                                    par.to_string_lossy().to_string(),
10039                                                )),
10040                                            );
10041                                            Ok(Value::Struct {
10042                                                name: "PathBuf".to_string(),
10043                                                fields: Rc::new(RefCell::new(new_fields)),
10044                                            })
10045                                        }
10046                                        None => Ok(Value::Null),
10047                                    };
10048                                }
10049                                "file_name" => {
10050                                    let p = std::path::Path::new(path.as_str());
10051                                    return match p.file_name() {
10052                                        Some(n) => Ok(Value::String(Rc::new(
10053                                            n.to_string_lossy().to_string(),
10054                                        ))),
10055                                        None => Ok(Value::Null),
10056                                    };
10057                                }
10058                                "extension" => {
10059                                    let p = std::path::Path::new(path.as_str());
10060                                    return match p.extension() {
10061                                        Some(e) => Ok(Value::String(Rc::new(
10062                                            e.to_string_lossy().to_string(),
10063                                        ))),
10064                                        None => Ok(Value::Null),
10065                                    };
10066                                }
10067                                "to_string" | "display" | "to_str" => {
10068                                    return Ok(Value::String(path.clone()));
10069                                }
10070                                _ => {}
10071                            }
10072                        }
10073                    }
10074
10075                    // Error on unknown methods - type checking
10076                    return Err(RuntimeError::new(format!(
10077                        "no method '{}' on type '&{}'",
10078                        method.name, name
10079                    )));
10080                }
10081                // For non-struct refs (like &str), auto-deref and call method on inner value
10082                // Handle common methods on &str (reference to String)
10083                if let Value::String(s) = &inner {
10084                    match method.name.as_str() {
10085                        "to_string" => return Ok(Value::String(s.clone())),
10086                        "len" => return Ok(Value::Int(s.len() as i64)),
10087                        "is_empty" => return Ok(Value::Bool(s.is_empty())),
10088                        "capacity" => return Ok(Value::Int(s.capacity() as i64)),
10089                        "as_str" => return Ok(Value::String(s.clone())),
10090                        "starts_with" => {
10091                            let prefix = match arg_values.first() {
10092                                Some(Value::String(p)) => p.as_str(),
10093                                Some(Value::Char(c)) => return Ok(Value::Bool(s.starts_with(*c))),
10094                                _ => {
10095                                    return Err(RuntimeError::new(
10096                                        "starts_with expects string or char",
10097                                    ))
10098                                }
10099                            };
10100                            return Ok(Value::Bool(s.starts_with(prefix)));
10101                        }
10102                        "ends_with" => {
10103                            let suffix = match arg_values.first() {
10104                                Some(Value::String(p)) => p.as_str(),
10105                                Some(Value::Char(c)) => return Ok(Value::Bool(s.ends_with(*c))),
10106                                _ => {
10107                                    return Err(RuntimeError::new(
10108                                        "ends_with expects string or char",
10109                                    ))
10110                                }
10111                            };
10112                            return Ok(Value::Bool(s.ends_with(suffix)));
10113                        }
10114                        "contains" => {
10115                            let substr = match arg_values.first() {
10116                                Some(Value::String(p)) => p.as_str(),
10117                                Some(Value::Char(c)) => return Ok(Value::Bool(s.contains(*c))),
10118                                _ => {
10119                                    return Err(RuntimeError::new(
10120                                        "contains expects string or char",
10121                                    ))
10122                                }
10123                            };
10124                            return Ok(Value::Bool(s.contains(substr)));
10125                        }
10126                        "trim" => return Ok(Value::String(Rc::new(s.trim().to_string()))),
10127                        "to_lowercase" => return Ok(Value::String(Rc::new(s.to_lowercase()))),
10128                        "to_uppercase" => return Ok(Value::String(Rc::new(s.to_uppercase()))),
10129                        "chars" => {
10130                            let chars: Vec<Value> = s.chars().map(Value::Char).collect();
10131                            return Ok(Value::Array(Rc::new(RefCell::new(chars))));
10132                        }
10133                        "split" => {
10134                            let delim = match arg_values.first() {
10135                                Some(Value::String(d)) => d.as_str().to_string(),
10136                                Some(Value::Char(c)) => c.to_string(),
10137                                _ => " ".to_string(),
10138                            };
10139                            let parts: Vec<Value> = s
10140                                .split(&delim)
10141                                .map(|p| Value::String(Rc::new(p.to_string())))
10142                                .collect();
10143                            return Ok(Value::Array(Rc::new(RefCell::new(parts))));
10144                        }
10145                        "replace" => {
10146                            if arg_values.len() != 2 {
10147                                return Err(RuntimeError::new("replace expects 2 arguments"));
10148                            }
10149                            let from = match &arg_values[0] {
10150                                Value::String(f) => f.as_str().to_string(),
10151                                Value::Char(c) => c.to_string(),
10152                                _ => return Err(RuntimeError::new("replace expects strings")),
10153                            };
10154                            let to = match &arg_values[1] {
10155                                Value::String(t) => t.as_str().to_string(),
10156                                Value::Char(c) => c.to_string(),
10157                                _ => return Err(RuntimeError::new("replace expects strings")),
10158                            };
10159                            return Ok(Value::String(Rc::new(s.replace(&from, &to))));
10160                        }
10161                        _ => {}
10162                    }
10163                }
10164                // Handle methods on &[T] and &mut [T] (references to arrays/slices)
10165                if let Value::Array(arr) = &inner {
10166                    match method.name.as_str() {
10167                        "len" => return Ok(Value::Int(arr.borrow().len() as i64)),
10168                        "is_empty" => return Ok(Value::Bool(arr.borrow().is_empty())),
10169                        "push" => {
10170                            if arg_values.len() != 1 {
10171                                return Err(RuntimeError::new("push expects 1 argument"));
10172                            }
10173                            // Check Vec<T> element type constraint
10174                            if let Some(var_name) = Self::extract_root_var(receiver) {
10175                                if let Some((type_name, type_params)) =
10176                                    self.var_types.borrow().get(&var_name)
10177                                {
10178                                    if type_name == "Vec" && !type_params.is_empty() {
10179                                        let expected_type = &type_params[0];
10180                                        let actual_type = self.value_type_name(&arg_values[0]);
10181                                        if &actual_type != expected_type {
10182                                            return Err(RuntimeError::new(format!(
10183                                                "type mismatch: expected Vec<{}>.push({}), found {}",
10184                                                expected_type, expected_type, actual_type
10185                                            )));
10186                                        }
10187                                    }
10188                                }
10189                            }
10190                            arr.borrow_mut().push(arg_values[0].clone());
10191                            return Ok(Value::Null);
10192                        }
10193                        "pop" => {
10194                            return arr
10195                                .borrow_mut()
10196                                .pop()
10197                                .ok_or_else(|| RuntimeError::new("pop on empty array"));
10198                        }
10199                        "contains" => {
10200                            if arg_values.len() != 1 {
10201                                return Err(RuntimeError::new("contains expects 1 argument"));
10202                            }
10203                            let target = &arg_values[0];
10204                            let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
10205                            return Ok(Value::Bool(found));
10206                        }
10207                        "first" | "next" => {
10208                            return Ok(arr.borrow().first().cloned().unwrap_or(Value::Null));
10209                        }
10210                        "last" => {
10211                            return arr
10212                                .borrow()
10213                                .last()
10214                                .cloned()
10215                                .ok_or_else(|| RuntimeError::new("empty array"));
10216                        }
10217                        "iter" | "into_iter" => {
10218                            return Ok(Value::Array(arr.clone()));
10219                        }
10220                        "reverse" => {
10221                            arr.borrow_mut().reverse();
10222                            return Ok(Value::Array(arr.clone()));
10223                        }
10224                        "skip" => {
10225                            let n = match arg_values.first() {
10226                                Some(Value::Int(i)) => *i as usize,
10227                                _ => 1,
10228                            };
10229                            let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
10230                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
10231                        }
10232                        "take" => {
10233                            let n = match arg_values.first() {
10234                                Some(Value::Int(i)) => *i as usize,
10235                                _ => 1,
10236                            };
10237                            let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
10238                            return Ok(Value::Array(Rc::new(RefCell::new(v))));
10239                        }
10240                        "get" => {
10241                            let idx = match arg_values.first() {
10242                                Some(Value::Int(i)) => *i as usize,
10243                                _ => return Err(RuntimeError::new("get expects integer index")),
10244                            };
10245                            return Ok(arr.borrow().get(idx).cloned().unwrap_or(Value::Null));
10246                        }
10247                        _ => {}
10248                    }
10249                }
10250                // Handle clone on any Ref value - clone the inner value
10251                if method.name == "clone" {
10252                    crate::sigil_debug!(
10253                        "DEBUG clone: recv_type=Ref({:?})",
10254                        std::mem::discriminant(&inner)
10255                    );
10256                    return Ok(inner.clone());
10257                }
10258                // Handle into on Ref value - convert to owned value
10259                if method.name == "into" {
10260                    return Ok(inner.clone());
10261                }
10262                // Handle to_string on Ref value
10263                if method.name == "to_string" {
10264                    return Ok(Value::String(Rc::new(format!("{}", inner))));
10265                }
10266                // Path methods for Ref containing PathBuf struct
10267                if let Value::Struct { name, fields, .. } = &inner {
10268                    if name == "PathBuf" || name == "Path" {
10269                        let borrowed = fields.borrow();
10270                        if let Some(Value::String(path)) = borrowed.get("path") {
10271                            match method.name.as_str() {
10272                                "exists" => {
10273                                    return Ok(Value::Bool(
10274                                        std::path::Path::new(path.as_str()).exists(),
10275                                    ))
10276                                }
10277                                "is_dir" => {
10278                                    return Ok(Value::Bool(
10279                                        std::path::Path::new(path.as_str()).is_dir(),
10280                                    ))
10281                                }
10282                                "is_file" => {
10283                                    return Ok(Value::Bool(
10284                                        std::path::Path::new(path.as_str()).is_file(),
10285                                    ))
10286                                }
10287                                "join" => {
10288                                    if let Some(Value::String(other)) = arg_values.first() {
10289                                        let new_path = std::path::Path::new(path.as_str())
10290                                            .join(other.as_str());
10291                                        let mut new_fields = std::collections::HashMap::new();
10292                                        new_fields.insert(
10293                                            "path".to_string(),
10294                                            Value::String(Rc::new(
10295                                                new_path.to_string_lossy().to_string(),
10296                                            )),
10297                                        );
10298                                        return Ok(Value::Struct {
10299                                            name: "PathBuf".to_string(),
10300                                            fields: Rc::new(RefCell::new(new_fields)),
10301                                        });
10302                                    }
10303                                    return Err(RuntimeError::new("join requires string argument"));
10304                                }
10305                                "parent" => {
10306                                    let p = std::path::Path::new(path.as_str());
10307                                    return match p.parent() {
10308                                        Some(par) => {
10309                                            let mut new_fields = std::collections::HashMap::new();
10310                                            new_fields.insert(
10311                                                "path".to_string(),
10312                                                Value::String(Rc::new(
10313                                                    par.to_string_lossy().to_string(),
10314                                                )),
10315                                            );
10316                                            Ok(Value::Struct {
10317                                                name: "PathBuf".to_string(),
10318                                                fields: Rc::new(RefCell::new(new_fields)),
10319                                            })
10320                                        }
10321                                        None => Ok(Value::Null),
10322                                    };
10323                                }
10324                                "file_name" => {
10325                                    let p = std::path::Path::new(path.as_str());
10326                                    return match p.file_name() {
10327                                        Some(n) => Ok(Value::String(Rc::new(
10328                                            n.to_string_lossy().to_string(),
10329                                        ))),
10330                                        None => Ok(Value::Null),
10331                                    };
10332                                }
10333                                "extension" => {
10334                                    let p = std::path::Path::new(path.as_str());
10335                                    return match p.extension() {
10336                                        Some(e) => Ok(Value::String(Rc::new(
10337                                            e.to_string_lossy().to_string(),
10338                                        ))),
10339                                        None => Ok(Value::Null),
10340                                    };
10341                                }
10342                                "to_string" | "display" => {
10343                                    return Ok(Value::String(path.clone()));
10344                                }
10345                                _ => {}
10346                            }
10347                        }
10348                    }
10349                }
10350                // Path methods for Ref containing String (PathBuf behavior)
10351                if let Value::String(s) = &inner {
10352                    match method.name.as_str() {
10353                        "exists" => {
10354                            return Ok(Value::Bool(std::path::Path::new(s.as_str()).exists()))
10355                        }
10356                        "is_dir" => {
10357                            return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir()))
10358                        }
10359                        "is_file" => {
10360                            return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file()))
10361                        }
10362                        "join" => {
10363                            if let Some(Value::String(other)) = arg_values.first() {
10364                                let path = std::path::Path::new(s.as_str()).join(other.as_str());
10365                                return Ok(Value::String(Rc::new(
10366                                    path.to_string_lossy().to_string(),
10367                                )));
10368                            }
10369                            return Err(RuntimeError::new("join requires string argument"));
10370                        }
10371                        "parent" => {
10372                            let path = std::path::Path::new(s.as_str());
10373                            return match path.parent() {
10374                                Some(p) => {
10375                                    Ok(Value::String(Rc::new(p.to_string_lossy().to_string())))
10376                                }
10377                                None => Ok(Value::Null),
10378                            };
10379                        }
10380                        "file_name" => {
10381                            let path = std::path::Path::new(s.as_str());
10382                            return match path.file_name() {
10383                                Some(n) => {
10384                                    Ok(Value::String(Rc::new(n.to_string_lossy().to_string())))
10385                                }
10386                                None => Ok(Value::Null),
10387                            };
10388                        }
10389                        "extension" => {
10390                            let path = std::path::Path::new(s.as_str());
10391                            return match path.extension() {
10392                                Some(e) => {
10393                                    Ok(Value::String(Rc::new(e.to_string_lossy().to_string())))
10394                                }
10395                                None => Ok(Value::Null),
10396                            };
10397                        }
10398                        _ => {}
10399                    }
10400                }
10401                // If the inner value is a string, recursively call method dispatch
10402                // This handles cases like &s[..].find(...) where we have a Ref to a String slice
10403                if let Value::String(_) = inner {
10404                    // Recursively dispatch method call on the inner string
10405                    // Create a temporary receiver with the unwrapped string
10406                    let recv_unwrapped = inner.clone();
10407                    match (&recv_unwrapped, method.name.as_str()) {
10408                        (Value::String(s), "find") => {
10409                            if arg_values.len() != 1 {
10410                                return Err(RuntimeError::new("find expects 1 argument"));
10411                            }
10412                            match &arg_values[0] {
10413                                Value::Char(c) => {
10414                                    return match s.find(*c) {
10415                                        Some(idx) => Ok(Value::Variant {
10416                                            enum_name: "Option".to_string(),
10417                                            variant_name: "Some".to_string(),
10418                                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
10419                                        }),
10420                                        None => Ok(Value::Variant {
10421                                            enum_name: "Option".to_string(),
10422                                            variant_name: "None".to_string(),
10423                                            fields: None,
10424                                        }),
10425                                    }
10426                                }
10427                                Value::String(pattern) => {
10428                                    return match s.find(pattern.as_str()) {
10429                                        Some(idx) => Ok(Value::Variant {
10430                                            enum_name: "Option".to_string(),
10431                                            variant_name: "Some".to_string(),
10432                                            fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
10433                                        }),
10434                                        None => Ok(Value::Variant {
10435                                            enum_name: "Option".to_string(),
10436                                            variant_name: "None".to_string(),
10437                                            fields: None,
10438                                        }),
10439                                    }
10440                                }
10441                                Value::Function(f) => {
10442                                    for (idx, c) in s.chars().enumerate() {
10443                                        let result = self.call_function(f, vec![Value::Char(c)])?;
10444                                        if let Value::Bool(true) = result {
10445                                            return Ok(Value::Variant {
10446                                                enum_name: "Option".to_string(),
10447                                                variant_name: "Some".to_string(),
10448                                                fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
10449                                            });
10450                                        }
10451                                    }
10452                                    return Ok(Value::Variant {
10453                                        enum_name: "Option".to_string(),
10454                                        variant_name: "None".to_string(),
10455                                        fields: None,
10456                                    });
10457                                }
10458                                _ => {
10459                                    return Err(RuntimeError::new(
10460                                        "find expects a char, string, or closure",
10461                                    ))
10462                                }
10463                            }
10464                        }
10465                        (Value::String(s), "trim") => {
10466                            return Ok(Value::String(Rc::new(s.trim().to_string())))
10467                        }
10468                        (Value::String(s), "is_empty") => return Ok(Value::Bool(s.is_empty())),
10469                        (Value::String(s), "len") => return Ok(Value::Int(s.len() as i64)),
10470                        (Value::String(s), "to_string") => return Ok(Value::String(s.clone())),
10471                        (Value::String(s), "chars") => {
10472                            let chars: Vec<Value> = s.chars().map(Value::Char).collect();
10473                            return Ok(Value::Array(Rc::new(RefCell::new(chars))));
10474                        }
10475                        (Value::String(s), "starts_with") => {
10476                            if let Some(Value::String(prefix)) = arg_values.first() {
10477                                return Ok(Value::Bool(s.starts_with(prefix.as_str())));
10478                            }
10479                            return Err(RuntimeError::new("starts_with expects string argument"));
10480                        }
10481                        _ => {}
10482                    }
10483                }
10484                // Fallback: auto-deref and dispatch method on inner value.
10485                // This handles &Array, &Float, &Int, etc.
10486                {
10487                    static DEREF_CTR: std::sync::atomic::AtomicUsize =
10488                        std::sync::atomic::AtomicUsize::new(0);
10489                    let id = DEREF_CTR.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
10490                    let inner_name = format!("__ref_deref_{}", id);
10491                    self.environment.borrow_mut().define(inner_name.clone(), inner.clone());
10492                    let deref_expr = Expr::Path(TypePath {
10493                        segments: vec![PathSegment {
10494                            ident: Ident {
10495                                name: inner_name.clone(),
10496                                span: Default::default(),
10497                                evidentiality: None,
10498                                affect: None,
10499                            },
10500                            generics: None,
10501                        }],
10502                    });
10503                    let result = self.eval_method_call(&deref_expr, method, args);
10504                    let _ = self.environment.borrow_mut().set(&inner_name, Value::Null);
10505                    result
10506                }
10507            }
10508            // Try struct method lookup: StructName·method
10509            (Value::Struct { name, fields }, _) => {
10510                // Built-in struct methods
10511                if method.name == "clone" {
10512                    // Clone the struct value
10513                    return Ok(recv.clone());
10514                }
10515                // PathBuf struct methods
10516                if name == "PathBuf" || name == "Path" {
10517                    let borrowed = fields.borrow();
10518                    if let Some(Value::String(path)) = borrowed.get("path") {
10519                        match method.name.as_str() {
10520                            "exists" => {
10521                                return Ok(Value::Bool(
10522                                    std::path::Path::new(path.as_str()).exists(),
10523                                ))
10524                            }
10525                            "is_dir" => {
10526                                return Ok(Value::Bool(
10527                                    std::path::Path::new(path.as_str()).is_dir(),
10528                                ))
10529                            }
10530                            "is_file" => {
10531                                return Ok(Value::Bool(
10532                                    std::path::Path::new(path.as_str()).is_file(),
10533                                ))
10534                            }
10535                            "join" => {
10536                                if let Some(Value::String(other)) = arg_values.first() {
10537                                    let new_path =
10538                                        std::path::Path::new(path.as_str()).join(other.as_str());
10539                                    let mut new_fields = std::collections::HashMap::new();
10540                                    new_fields.insert(
10541                                        "path".to_string(),
10542                                        Value::String(Rc::new(
10543                                            new_path.to_string_lossy().to_string(),
10544                                        )),
10545                                    );
10546                                    return Ok(Value::Struct {
10547                                        name: "PathBuf".to_string(),
10548                                        fields: Rc::new(RefCell::new(new_fields)),
10549                                    });
10550                                }
10551                                return Err(RuntimeError::new("join requires string argument"));
10552                            }
10553                            "parent" => {
10554                                let p = std::path::Path::new(path.as_str());
10555                                return match p.parent() {
10556                                    Some(par) => {
10557                                        let mut new_fields = std::collections::HashMap::new();
10558                                        new_fields.insert(
10559                                            "path".to_string(),
10560                                            Value::String(Rc::new(
10561                                                par.to_string_lossy().to_string(),
10562                                            )),
10563                                        );
10564                                        Ok(Value::Struct {
10565                                            name: "PathBuf".to_string(),
10566                                            fields: Rc::new(RefCell::new(new_fields)),
10567                                        })
10568                                    }
10569                                    None => Ok(Value::Null),
10570                                };
10571                            }
10572                            "file_name" => {
10573                                let p = std::path::Path::new(path.as_str());
10574                                return match p.file_name() {
10575                                    Some(n) => {
10576                                        Ok(Value::String(Rc::new(n.to_string_lossy().to_string())))
10577                                    }
10578                                    None => Ok(Value::Null),
10579                                };
10580                            }
10581                            "extension" => {
10582                                let p = std::path::Path::new(path.as_str());
10583                                return match p.extension() {
10584                                    Some(e) => {
10585                                        Ok(Value::String(Rc::new(e.to_string_lossy().to_string())))
10586                                    }
10587                                    None => Ok(Value::Null),
10588                                };
10589                            }
10590                            "to_string" | "display" => {
10591                                return Ok(Value::String(path.clone()));
10592                            }
10593                            _ => {}
10594                        }
10595                    }
10596                }
10597                // Rc struct methods
10598                if name == "Rc" {
10599                    let borrowed = fields.borrow();
10600                    if let Some(value) = borrowed.get("_value") {
10601                        match method.name.as_str() {
10602                            "clone" => {
10603                                // Return a new Rc with same value
10604                                let mut new_fields = HashMap::new();
10605                                new_fields.insert("_value".to_string(), value.clone());
10606                                return Ok(Value::Struct {
10607                                    name: "Rc".to_string(),
10608                                    fields: Rc::new(RefCell::new(new_fields)),
10609                                });
10610                            }
10611                            _ => {}
10612                        }
10613                    }
10614                }
10615                // Cell struct methods
10616                if name == "Cell" {
10617                    match method.name.as_str() {
10618                        "get" => {
10619                            let borrowed = fields.borrow();
10620                            if let Some(value) = borrowed.get("_value") {
10621                                return Ok(value.clone());
10622                            }
10623                            return Err(RuntimeError::new("Cell has no value"));
10624                        }
10625                        "set" => {
10626                            if arg_values.len() != 1 {
10627                                return Err(RuntimeError::new("set expects 1 argument"));
10628                            }
10629                            fields
10630                                .borrow_mut()
10631                                .insert("_value".to_string(), arg_values[0].clone());
10632                            return Ok(Value::Null);
10633                        }
10634                        _ => {}
10635                    }
10636                }
10637                // Duration struct methods
10638                if name == "Duration" {
10639                    let borrowed = fields.borrow();
10640                    let secs = match borrowed.get("secs") {
10641                        Some(Value::Int(s)) => *s,
10642                        _ => 0,
10643                    };
10644                    let nanos = match borrowed.get("nanos") {
10645                        Some(Value::Int(n)) => *n,
10646                        _ => 0,
10647                    };
10648                    match method.name.as_str() {
10649                        "as_secs" => return Ok(Value::Int(secs)),
10650                        "as_millis" => return Ok(Value::Int(secs * 1000 + nanos / 1_000_000)),
10651                        "as_micros" => return Ok(Value::Int(secs * 1_000_000 + nanos / 1000)),
10652                        "as_nanos" => return Ok(Value::Int(secs * 1_000_000_000 + nanos)),
10653                        "subsec_nanos" => return Ok(Value::Int(nanos)),
10654                        "subsec_millis" => return Ok(Value::Int(nanos / 1_000_000)),
10655                        "is_zero" => return Ok(Value::Bool(secs == 0 && nanos == 0)),
10656                        _ => {}
10657                    }
10658                }
10659                // Mutex methods - lock() returns a Ref to the inner value
10660                if name == "Mutex" {
10661                    match method.name.as_str() {
10662                        "lock" => {
10663                            // lock() returns a guard that provides access to inner value
10664                            // In the interpreter, we just return a Ref to the inner value
10665                            let borrowed = fields.borrow();
10666                            if let Some(inner) = borrowed.get("__inner__") {
10667                                // Return a Ref wrapping the inner value for mutation
10668                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
10669                            }
10670                            return Err(RuntimeError::new("Mutex has no inner value"));
10671                        }
10672                        "try_lock" => {
10673                            // try_lock() returns Some(guard) - in interpreter always succeeds
10674                            let borrowed = fields.borrow();
10675                            if let Some(inner) = borrowed.get("__inner__") {
10676                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
10677                                return Ok(Value::Variant {
10678                                    enum_name: "Option".to_string(),
10679                                    variant_name: "Some".to_string(),
10680                                    fields: Some(Rc::new(vec![guard])),
10681                                });
10682                            }
10683                            return Ok(Value::Variant {
10684                                enum_name: "Option".to_string(),
10685                                variant_name: "None".to_string(),
10686                                fields: None,
10687                            });
10688                        }
10689                        "into_inner" => {
10690                            // into_inner() consumes the mutex and returns the inner value
10691                            let borrowed = fields.borrow();
10692                            if let Some(inner) = borrowed.get("__inner__") {
10693                                return Ok(inner.clone());
10694                            }
10695                            return Err(RuntimeError::new("Mutex has no inner value"));
10696                        }
10697                        "get_mut" => {
10698                            // get_mut() returns &mut T when we have exclusive access
10699                            let borrowed = fields.borrow();
10700                            if let Some(inner) = borrowed.get("__inner__") {
10701                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
10702                            }
10703                            return Err(RuntimeError::new("Mutex has no inner value"));
10704                        }
10705                        _ => {}
10706                    }
10707                }
10708                // RwLock methods - read() and write() return guards
10709                if name == "RwLock" {
10710                    match method.name.as_str() {
10711                        "read" => {
10712                            // read() returns a read guard
10713                            let borrowed = fields.borrow();
10714                            if let Some(inner) = borrowed.get("__inner__") {
10715                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
10716                            }
10717                            return Err(RuntimeError::new("RwLock has no inner value"));
10718                        }
10719                        "write" => {
10720                            // write() returns a write guard
10721                            let borrowed = fields.borrow();
10722                            if let Some(inner) = borrowed.get("__inner__") {
10723                                return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
10724                            }
10725                            return Err(RuntimeError::new("RwLock has no inner value"));
10726                        }
10727                        "try_read" => {
10728                            let borrowed = fields.borrow();
10729                            if let Some(inner) = borrowed.get("__inner__") {
10730                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
10731                                return Ok(Value::Variant {
10732                                    enum_name: "Option".to_string(),
10733                                    variant_name: "Some".to_string(),
10734                                    fields: Some(Rc::new(vec![guard])),
10735                                });
10736                            }
10737                            return Ok(Value::Variant {
10738                                enum_name: "Option".to_string(),
10739                                variant_name: "None".to_string(),
10740                                fields: None,
10741                            });
10742                        }
10743                        "try_write" => {
10744                            let borrowed = fields.borrow();
10745                            if let Some(inner) = borrowed.get("__inner__") {
10746                                let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
10747                                return Ok(Value::Variant {
10748                                    enum_name: "Option".to_string(),
10749                                    variant_name: "Some".to_string(),
10750                                    fields: Some(Rc::new(vec![guard])),
10751                                });
10752                            }
10753                            return Ok(Value::Variant {
10754                                enum_name: "Option".to_string(),
10755                                variant_name: "None".to_string(),
10756                                fields: None,
10757                            });
10758                        }
10759                        "into_inner" => {
10760                            let borrowed = fields.borrow();
10761                            if let Some(inner) = borrowed.get("__inner__") {
10762                                return Ok(inner.clone());
10763                            }
10764                            return Err(RuntimeError::new("RwLock has no inner value"));
10765                        }
10766                        _ => {}
10767                    }
10768                }
10769                // OnceLock methods - get_or_init(), get(), set()
10770                if name == "OnceLock" {
10771                    match method.name.as_str() {
10772                        "get_or_init" => {
10773                            // get_or_init(init_fn) - initialize on first access, return value
10774                            let is_initialized = {
10775                                let borrowed = fields.borrow();
10776                                matches!(borrowed.get("initialized"), Some(Value::Bool(true)))
10777                            };
10778                            if is_initialized {
10779                                let borrowed = fields.borrow();
10780                                return Ok(borrowed.get("value").cloned().unwrap_or(Value::Null));
10781                            }
10782                            // Not initialized yet - call the init function
10783                            let init_val = if !arg_values.is_empty() {
10784                                match &arg_values[0] {
10785                                    Value::Function(f) => self.call_function(f, vec![])?,
10786                                    Value::BuiltIn(b) => (b.func)(self, vec![])?,
10787                                    // If not callable, use as direct value
10788                                    other => other.clone(),
10789                                }
10790                            } else {
10791                                Value::Null
10792                            };
10793                            // Store the initialized value
10794                            {
10795                                let mut borrowed = fields.borrow_mut();
10796                                borrowed.insert("initialized".to_string(), Value::Bool(true));
10797                                borrowed.insert("value".to_string(), init_val.clone());
10798                            }
10799                            return Ok(init_val);
10800                        }
10801                        "get" => {
10802                            // get() - returns Option<&T>
10803                            let borrowed = fields.borrow();
10804                            if matches!(borrowed.get("initialized"), Some(Value::Bool(true))) {
10805                                let val = borrowed.get("value").cloned().unwrap_or(Value::Null);
10806                                return Ok(Value::Variant {
10807                                    enum_name: "Option".to_string(),
10808                                    variant_name: "Some".to_string(),
10809                                    fields: Some(Rc::new(vec![val])),
10810                                });
10811                            }
10812                            return Ok(Value::Variant {
10813                                enum_name: "Option".to_string(),
10814                                variant_name: "None".to_string(),
10815                                fields: None,
10816                            });
10817                        }
10818                        "set" => {
10819                            // set(value) - initialize if not already, returns Ok(()) or Err(value)
10820                            let is_initialized = {
10821                                let borrowed = fields.borrow();
10822                                matches!(borrowed.get("initialized"), Some(Value::Bool(true)))
10823                            };
10824                            if is_initialized {
10825                                let err_val = if !arg_values.is_empty() { arg_values[0].clone() } else { Value::Null };
10826                                return Ok(Value::Variant {
10827                                    enum_name: "Result".to_string(),
10828                                    variant_name: "Err".to_string(),
10829                                    fields: Some(Rc::new(vec![err_val])),
10830                                });
10831                            }
10832                            let val = if !arg_values.is_empty() { arg_values[0].clone() } else { Value::Null };
10833                            {
10834                                let mut borrowed = fields.borrow_mut();
10835                                borrowed.insert("initialized".to_string(), Value::Bool(true));
10836                                borrowed.insert("value".to_string(), val);
10837                            }
10838                            return Ok(Value::Variant {
10839                                enum_name: "Result".to_string(),
10840                                variant_name: "Ok".to_string(),
10841                                fields: Some(Rc::new(vec![Value::Null])),
10842                            });
10843                        }
10844                        _ => {}
10845                    }
10846                }
10847                // Barrier methods - wait() synchronization
10848                if name == "Barrier" {
10849                    match method.name.as_str() {
10850                        "wait" => {
10851                            // In single-threaded interpreter, wait() is a no-op
10852                            // Just return a BarrierWaitResult indicating this thread is not the leader
10853                            let mut result_fields = HashMap::new();
10854                            result_fields.insert("__type__".to_string(), Value::String(Rc::new("BarrierWaitResult".to_string())));
10855                            result_fields.insert("is_leader".to_string(), Value::Bool(true)); // first one through is leader
10856                            return Ok(Value::Map(Rc::new(RefCell::new(result_fields))));
10857                        }
10858                        "is_leader" => {
10859                            // Check if this was the leader thread (always true in single-threaded mode)
10860                            return Ok(Value::Bool(true));
10861                        }
10862                        _ => {}
10863                    }
10864                }
10865                // HTTP Client methods - get/post/etc.
10866                if name == "Client" || name == "HttpClient" {
10867                    match method.name.as_str() {
10868                        "get" => {
10869                            // client.get(url) - returns a Response with reported (~) evidence
10870                            if let Some(url) = arg_values.first() {
10871                                let url_str = match url {
10872                                    Value::String(s) => s.to_string(),
10873                                    _ => return Err(RuntimeError::new("get() requires a URL string")),
10874                                };
10875                                // Create a Response struct with reported evidence
10876                                let mut response_fields = HashMap::new();
10877                                response_fields.insert("__type__".to_string(), Value::String(Rc::new("Response".to_string())));
10878                                response_fields.insert("url".to_string(), Value::String(Rc::new(url_str)));
10879                                response_fields.insert("status".to_string(), Value::Int(200));
10880                                response_fields.insert("body".to_string(), Value::String(Rc::new("{}".to_string())));
10881                                response_fields.insert("__evidence__".to_string(), Value::String(Rc::new("reported".to_string())));
10882                                return Ok(Value::Struct {
10883                                    name: "Response".to_string(),
10884                                    fields: Rc::new(RefCell::new(response_fields)),
10885                                });
10886                            }
10887                            return Err(RuntimeError::new("get() requires a URL argument"));
10888                        }
10889                        "post" => {
10890                            // client.post(url, body) - returns a Response
10891                            if arg_values.len() >= 1 {
10892                                let url_str = match &arg_values[0] {
10893                                    Value::String(s) => s.to_string(),
10894                                    _ => return Err(RuntimeError::new("post() requires a URL string")),
10895                                };
10896                                let mut response_fields = HashMap::new();
10897                                response_fields.insert("__type__".to_string(), Value::String(Rc::new("Response".to_string())));
10898                                response_fields.insert("url".to_string(), Value::String(Rc::new(url_str)));
10899                                response_fields.insert("status".to_string(), Value::Int(200));
10900                                response_fields.insert("body".to_string(), Value::String(Rc::new("{}".to_string())));
10901                                response_fields.insert("__evidence__".to_string(), Value::String(Rc::new("reported".to_string())));
10902                                return Ok(Value::Struct {
10903                                    name: "Response".to_string(),
10904                                    fields: Rc::new(RefCell::new(response_fields)),
10905                                });
10906                            }
10907                            return Err(RuntimeError::new("post() requires a URL argument"));
10908                        }
10909                        _ => {}
10910                    }
10911                }
10912                // Response methods - verify, body, status, etc.
10913                if name == "Response" {
10914                    match method.name.as_str() {
10915                        "verify" => {
10916                            // verify() - verify the response data (promotes from reported to known)
10917                            // Returns the response data without the reported evidentiality marker
10918                            let borrowed = fields.borrow();
10919                            let mut verified_fields = HashMap::new();
10920                            for (k, v) in borrowed.iter() {
10921                                if k != "__evidence__" {
10922                                    verified_fields.insert(k.clone(), v.clone());
10923                                }
10924                            }
10925                            verified_fields.insert("__evidence__".to_string(), Value::String(Rc::new("known".to_string())));
10926                            return Ok(Value::Struct {
10927                                name: "Response".to_string(),
10928                                fields: Rc::new(RefCell::new(verified_fields)),
10929                            });
10930                        }
10931                        "body" => {
10932                            // body() - get response body
10933                            let borrowed = fields.borrow();
10934                            return Ok(borrowed.get("body").cloned().unwrap_or(Value::String(Rc::new("".to_string()))));
10935                        }
10936                        "status" => {
10937                            // status() - get HTTP status code
10938                            let borrowed = fields.borrow();
10939                            return Ok(borrowed.get("status").cloned().unwrap_or(Value::Int(0)));
10940                        }
10941                        "json" => {
10942                            // json() - parse body as JSON
10943                            let borrowed = fields.borrow();
10944                            if let Some(Value::String(body)) = borrowed.get("body") {
10945                                // Simple JSON parsing placeholder
10946                                return Ok(Value::String(body.clone()));
10947                            }
10948                            return Ok(Value::Null);
10949                        }
10950                        _ => {}
10951                    }
10952                }
10953                // Atomic methods - load/store/fetch_add etc.
10954                if name == "AtomicU64"
10955                    || name == "AtomicUsize"
10956                    || name == "AtomicI64"
10957                    || name == "AtomicIsize"
10958                {
10959                    match method.name.as_str() {
10960                        "load" => {
10961                            // load() returns the current value
10962                            let borrowed = fields.borrow();
10963                            if let Some(val) = borrowed.get("__value__") {
10964                                return Ok(val.clone());
10965                            }
10966                            return Ok(Value::Int(0));
10967                        }
10968                        "store" => {
10969                            // store(value) sets the value
10970                            if let Some(new_val) = arg_values.first() {
10971                                fields
10972                                    .borrow_mut()
10973                                    .insert("__value__".to_string(), new_val.clone());
10974                                return Ok(Value::Null);
10975                            }
10976                            return Err(RuntimeError::new("store requires a value"));
10977                        }
10978                        "fetch_add" => {
10979                            // fetch_add(n) adds n and returns old value
10980                            if let Some(Value::Int(n)) = arg_values.first() {
10981                                let mut borrowed = fields.borrow_mut();
10982                                let old = match borrowed.get("__value__") {
10983                                    Some(Value::Int(v)) => *v,
10984                                    _ => 0,
10985                                };
10986                                borrowed.insert("__value__".to_string(), Value::Int(old + n));
10987                                return Ok(Value::Int(old));
10988                            }
10989                            return Err(RuntimeError::new("fetch_add requires integer"));
10990                        }
10991                        "fetch_sub" => {
10992                            if let Some(Value::Int(n)) = arg_values.first() {
10993                                let mut borrowed = fields.borrow_mut();
10994                                let old = match borrowed.get("__value__") {
10995                                    Some(Value::Int(v)) => *v,
10996                                    _ => 0,
10997                                };
10998                                borrowed.insert("__value__".to_string(), Value::Int(old - n));
10999                                return Ok(Value::Int(old));
11000                            }
11001                            return Err(RuntimeError::new("fetch_sub requires integer"));
11002                        }
11003                        "swap" => {
11004                            if let Some(new_val) = arg_values.first() {
11005                                let mut borrowed = fields.borrow_mut();
11006                                let old =
11007                                    borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
11008                                borrowed.insert("__value__".to_string(), new_val.clone());
11009                                return Ok(old);
11010                            }
11011                            return Err(RuntimeError::new("swap requires a value"));
11012                        }
11013                        "compare_exchange" | "compare_and_swap" => {
11014                            // compare_exchange(current, new) - if value == current, set to new
11015                            if arg_values.len() >= 2 {
11016                                let current = &arg_values[0];
11017                                let new_val = &arg_values[1];
11018                                let mut borrowed = fields.borrow_mut();
11019                                let actual =
11020                                    borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
11021                                if self.values_equal(&actual, current) {
11022                                    borrowed.insert("__value__".to_string(), new_val.clone());
11023                                    return Ok(Value::Variant {
11024                                        enum_name: "Result".to_string(),
11025                                        variant_name: "Ok".to_string(),
11026                                        fields: Some(Rc::new(vec![actual])),
11027                                    });
11028                                } else {
11029                                    return Ok(Value::Variant {
11030                                        enum_name: "Result".to_string(),
11031                                        variant_name: "Err".to_string(),
11032                                        fields: Some(Rc::new(vec![actual])),
11033                                    });
11034                                }
11035                            }
11036                            return Err(RuntimeError::new(
11037                                "compare_exchange requires two arguments",
11038                            ));
11039                        }
11040                        _ => {}
11041                    }
11042                }
11043                // AtomicBool methods
11044                if name == "AtomicBool" {
11045                    match method.name.as_str() {
11046                        "load" => {
11047                            let borrowed = fields.borrow();
11048                            if let Some(val) = borrowed.get("__value__") {
11049                                return Ok(val.clone());
11050                            }
11051                            return Ok(Value::Bool(false));
11052                        }
11053                        "store" => {
11054                            if let Some(new_val) = arg_values.first() {
11055                                fields
11056                                    .borrow_mut()
11057                                    .insert("__value__".to_string(), new_val.clone());
11058                                return Ok(Value::Null);
11059                            }
11060                            return Err(RuntimeError::new("store requires a value"));
11061                        }
11062                        "swap" => {
11063                            if let Some(new_val) = arg_values.first() {
11064                                let mut borrowed = fields.borrow_mut();
11065                                let old = borrowed
11066                                    .get("__value__")
11067                                    .cloned()
11068                                    .unwrap_or(Value::Bool(false));
11069                                borrowed.insert("__value__".to_string(), new_val.clone());
11070                                return Ok(old);
11071                            }
11072                            return Err(RuntimeError::new("swap requires a value"));
11073                        }
11074                        "fetch_and" => {
11075                            if let Some(Value::Bool(b)) = arg_values.first() {
11076                                let mut borrowed = fields.borrow_mut();
11077                                let old = match borrowed.get("__value__") {
11078                                    Some(Value::Bool(v)) => *v,
11079                                    _ => false,
11080                                };
11081                                borrowed.insert("__value__".to_string(), Value::Bool(old && *b));
11082                                return Ok(Value::Bool(old));
11083                            }
11084                            return Err(RuntimeError::new("fetch_and requires boolean"));
11085                        }
11086                        "fetch_or" => {
11087                            if let Some(Value::Bool(b)) = arg_values.first() {
11088                                let mut borrowed = fields.borrow_mut();
11089                                let old = match borrowed.get("__value__") {
11090                                    Some(Value::Bool(v)) => *v,
11091                                    _ => false,
11092                                };
11093                                borrowed.insert("__value__".to_string(), Value::Bool(old || *b));
11094                                return Ok(Value::Bool(old));
11095                            }
11096                            return Err(RuntimeError::new("fetch_or requires boolean"));
11097                        }
11098                        _ => {}
11099                    }
11100                }
11101                if method.name == "to_string" {
11102                    // Check for user-defined to_string() method first
11103                    let user_method_name = format!("{}·to_string", name);
11104                    let user_fn = self.globals.borrow().get(&user_method_name).map(|v| v.clone());
11105                    if let Some(Value::Function(func)) = user_fn {
11106                        let self_val = Value::Struct {
11107                            name: name.clone(),
11108                            fields: fields.clone(),
11109                        };
11110                        return self.call_function(&func, vec![self_val]);
11111                    }
11112                    // Generic to_string for structs - returns a debug representation
11113                    let field_str = fields
11114                        .borrow()
11115                        .iter()
11116                        .map(|(k, v)| format!("{}: {}", k, v))
11117                        .collect::<Vec<_>>()
11118                        .join(", ");
11119                    return Ok(Value::String(Rc::new(format!(
11120                        "{} {{ {} }}",
11121                        name, field_str
11122                    ))));
11123                }
11124
11125                // Pattern methods - for AST patterns stored as structs (Pattern::Ident, Pattern::Tuple, etc.)
11126                if name.starts_with("Pattern::") {
11127                    match method.name.as_str() {
11128                        "evidentiality" => {
11129                            // Return the evidentiality field from the pattern struct
11130                            if let Some(ev) = fields.borrow().get("evidentiality") {
11131                                return Ok(ev.clone());
11132                            }
11133                            return Ok(Value::Null);
11134                        }
11135                        "name" | "binding_name" => {
11136                            // Return the name field from the pattern struct (for binding purposes)
11137                            if let Some(n) = fields.borrow().get("name") {
11138                                // The name field might be an Ident struct with a nested "name" field
11139                                // Extract the inner string if that's the case
11140                                let result = match &n {
11141                                    Value::Struct {
11142                                        fields: inner_fields,
11143                                        ..
11144                                    } => {
11145                                        if let Some(inner_name) = inner_fields.borrow().get("name")
11146                                        {
11147                                            crate::sigil_debug!("DEBUG binding_name: returning inner name {} from {}", inner_name, name);
11148                                            inner_name.clone()
11149                                        } else {
11150                                            crate::sigil_debug!(
11151                                                "DEBUG binding_name: returning struct {} from {}",
11152                                                n,
11153                                                name
11154                                            );
11155                                            n.clone()
11156                                        }
11157                                    }
11158                                    _ => {
11159                                        crate::sigil_debug!(
11160                                            "DEBUG binding_name: returning {} from {}",
11161                                            n,
11162                                            name
11163                                        );
11164                                        n.clone()
11165                                    }
11166                                };
11167                                return Ok(result);
11168                            }
11169                            crate::sigil_debug!(
11170                                "DEBUG binding_name: 'name' field not found in {}, fields: {:?}",
11171                                name,
11172                                fields.borrow().keys().collect::<Vec<_>>()
11173                            );
11174                            // For Pattern::Ident, name is the binding name
11175                            return Ok(Value::Null);
11176                        }
11177                        "mutable" => {
11178                            // Return the mutable field from the pattern struct
11179                            if let Some(m) = fields.borrow().get("mutable") {
11180                                return Ok(m.clone());
11181                            }
11182                            return Ok(Value::Bool(false));
11183                        }
11184                        "is_ident" => {
11185                            return Ok(Value::Bool(name == "Pattern::Ident"));
11186                        }
11187                        "is_wildcard" => {
11188                            return Ok(Value::Bool(name == "Pattern::Wildcard"));
11189                        }
11190                        "clone" => {
11191                            return Ok(recv.clone());
11192                        }
11193                        _ => {}
11194                    }
11195                }
11196
11197                // PathBuf methods
11198                if name == "PathBuf" || name == "Path" {
11199                    match method.name.as_str() {
11200                        "exists" => {
11201                            // Check if path exists
11202                            let path = match fields.borrow().get("path") {
11203                                Some(Value::String(s)) => s.to_string(),
11204                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11205                            };
11206                            return Ok(Value::Bool(std::path::Path::new(&path).exists()));
11207                        }
11208                        "is_dir" => {
11209                            let path = match fields.borrow().get("path") {
11210                                Some(Value::String(s)) => s.to_string(),
11211                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11212                            };
11213                            return Ok(Value::Bool(std::path::Path::new(&path).is_dir()));
11214                        }
11215                        "is_file" => {
11216                            let path = match fields.borrow().get("path") {
11217                                Some(Value::String(s)) => s.to_string(),
11218                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11219                            };
11220                            return Ok(Value::Bool(std::path::Path::new(&path).is_file()));
11221                        }
11222                        "extension" => {
11223                            let path = match fields.borrow().get("path") {
11224                                Some(Value::String(s)) => s.to_string(),
11225                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11226                            };
11227                            match std::path::Path::new(&path).extension() {
11228                                Some(ext) => {
11229                                    // Return Option::Some with an OsStr-like struct
11230                                    let ext_str = ext.to_string_lossy().to_string();
11231                                    let mut ext_fields = HashMap::new();
11232                                    ext_fields.insert(
11233                                        "value".to_string(),
11234                                        Value::String(Rc::new(ext_str)),
11235                                    );
11236                                    return Ok(Value::Variant {
11237                                        enum_name: "Option".to_string(),
11238                                        variant_name: "Some".to_string(),
11239                                        fields: Some(Rc::new(vec![Value::Struct {
11240                                            name: "OsStr".to_string(),
11241                                            fields: Rc::new(RefCell::new(ext_fields)),
11242                                        }])),
11243                                    });
11244                                }
11245                                None => {
11246                                    return Ok(Value::Variant {
11247                                        enum_name: "Option".to_string(),
11248                                        variant_name: "None".to_string(),
11249                                        fields: None,
11250                                    });
11251                                }
11252                            }
11253                        }
11254                        "file_name" => {
11255                            let path = match fields.borrow().get("path") {
11256                                Some(Value::String(s)) => s.to_string(),
11257                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11258                            };
11259                            match std::path::Path::new(&path).file_name() {
11260                                Some(fname) => {
11261                                    let fname_str = fname.to_string_lossy().to_string();
11262                                    let mut fname_fields = HashMap::new();
11263                                    fname_fields.insert(
11264                                        "value".to_string(),
11265                                        Value::String(Rc::new(fname_str)),
11266                                    );
11267                                    return Ok(Value::Variant {
11268                                        enum_name: "Option".to_string(),
11269                                        variant_name: "Some".to_string(),
11270                                        fields: Some(Rc::new(vec![Value::Struct {
11271                                            name: "OsStr".to_string(),
11272                                            fields: Rc::new(RefCell::new(fname_fields)),
11273                                        }])),
11274                                    });
11275                                }
11276                                None => {
11277                                    return Ok(Value::Variant {
11278                                        enum_name: "Option".to_string(),
11279                                        variant_name: "None".to_string(),
11280                                        fields: None,
11281                                    });
11282                                }
11283                            }
11284                        }
11285                        "parent" => {
11286                            let path = match fields.borrow().get("path") {
11287                                Some(Value::String(s)) => s.to_string(),
11288                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11289                            };
11290                            match std::path::Path::new(&path).parent() {
11291                                Some(parent) => {
11292                                    let mut parent_fields = HashMap::new();
11293                                    parent_fields.insert(
11294                                        "path".to_string(),
11295                                        Value::String(Rc::new(
11296                                            parent.to_string_lossy().to_string(),
11297                                        )),
11298                                    );
11299                                    return Ok(Value::Variant {
11300                                        enum_name: "Option".to_string(),
11301                                        variant_name: "Some".to_string(),
11302                                        fields: Some(Rc::new(vec![Value::Struct {
11303                                            name: "Path".to_string(),
11304                                            fields: Rc::new(RefCell::new(parent_fields)),
11305                                        }])),
11306                                    });
11307                                }
11308                                None => {
11309                                    return Ok(Value::Variant {
11310                                        enum_name: "Option".to_string(),
11311                                        variant_name: "None".to_string(),
11312                                        fields: None,
11313                                    });
11314                                }
11315                            }
11316                        }
11317                        "to_str" => {
11318                            // Convert to string (returns Option<&str>, we just return the string)
11319                            let path = match fields.borrow().get("path") {
11320                                Some(Value::String(s)) => s.clone(),
11321                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11322                            };
11323                            // Wrap in Some for unwrap() compatibility
11324                            return Ok(Value::Variant {
11325                                enum_name: "Option".to_string(),
11326                                variant_name: "Some".to_string(),
11327                                fields: Some(Rc::new(vec![Value::String(path)])),
11328                            });
11329                        }
11330                        "to_string_lossy" => {
11331                            let path = match fields.borrow().get("path") {
11332                                Some(Value::String(s)) => s.clone(),
11333                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11334                            };
11335                            return Ok(Value::String(path));
11336                        }
11337                        "join" => {
11338                            // Join path with another component
11339                            if arg_values.is_empty() {
11340                                return Err(RuntimeError::new("join expects 1 argument"));
11341                            }
11342                            let base = match fields.borrow().get("path") {
11343                                Some(Value::String(s)) => s.to_string(),
11344                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11345                            };
11346                            let component = match &arg_values[0] {
11347                                Value::String(s) => s.to_string(),
11348                                Value::Struct { name: n, fields: f }
11349                                    if n == "PathBuf" || n == "Path" =>
11350                                {
11351                                    match f.borrow().get("path") {
11352                                        Some(Value::String(s)) => s.to_string(),
11353                                        _ => {
11354                                            return Err(RuntimeError::new(
11355                                                "PathBuf has no path field",
11356                                            ))
11357                                        }
11358                                    }
11359                                }
11360                                _ => {
11361                                    return Err(RuntimeError::new("join expects string or PathBuf"))
11362                                }
11363                            };
11364                            let joined = std::path::Path::new(&base).join(&component);
11365                            let mut new_fields = HashMap::new();
11366                            new_fields.insert(
11367                                "path".to_string(),
11368                                Value::String(Rc::new(joined.to_string_lossy().to_string())),
11369                            );
11370                            return Ok(Value::Struct {
11371                                name: "PathBuf".to_string(),
11372                                fields: Rc::new(RefCell::new(new_fields)),
11373                            });
11374                        }
11375                        "display" => {
11376                            let path = match fields.borrow().get("path") {
11377                                Some(Value::String(s)) => s.clone(),
11378                                _ => return Err(RuntimeError::new("PathBuf has no path field")),
11379                            };
11380                            return Ok(Value::String(path));
11381                        }
11382                        "to_path_buf" => {
11383                            // Path -> PathBuf (just return a copy)
11384                            return Ok(recv.clone());
11385                        }
11386                        _ => {}
11387                    }
11388                }
11389
11390                // OsStr methods
11391                if name == "OsStr" {
11392                    match method.name.as_str() {
11393                        "to_str" => {
11394                            let val = match fields.borrow().get("value") {
11395                                Some(Value::String(s)) => s.clone(),
11396                                _ => return Err(RuntimeError::new("OsStr has no value field")),
11397                            };
11398                            return Ok(Value::Variant {
11399                                enum_name: "Option".to_string(),
11400                                variant_name: "Some".to_string(),
11401                                fields: Some(Rc::new(vec![Value::String(val)])),
11402                            });
11403                        }
11404                        "to_string_lossy" => {
11405                            let val = match fields.borrow().get("value") {
11406                                Some(Value::String(s)) => s.clone(),
11407                                _ => return Err(RuntimeError::new("OsStr has no value field")),
11408                            };
11409                            return Ok(Value::String(val));
11410                        }
11411                        "to_lowercase" => {
11412                            let val = match fields.borrow().get("value") {
11413                                Some(Value::String(s)) => s.to_lowercase(),
11414                                _ => return Err(RuntimeError::new("OsStr has no value field")),
11415                            };
11416                            return Ok(Value::String(Rc::new(val)));
11417                        }
11418                        "as_str" => {
11419                            let val = match fields.borrow().get("value") {
11420                                Some(Value::String(s)) => s.clone(),
11421                                _ => return Err(RuntimeError::new("OsStr has no value field")),
11422                            };
11423                            return Ok(Value::String(val));
11424                        }
11425                        _ => {}
11426                    }
11427                }
11428
11429                // DirEntry methods
11430                if name == "DirEntry" {
11431                    match method.name.as_str() {
11432                        "path" => {
11433                            let path = match fields.borrow().get("path") {
11434                                Some(Value::String(s)) => s.clone(),
11435                                _ => return Err(RuntimeError::new("DirEntry has no path field")),
11436                            };
11437                            let mut path_fields = HashMap::new();
11438                            path_fields.insert("path".to_string(), Value::String(path));
11439                            return Ok(Value::Struct {
11440                                name: "PathBuf".to_string(),
11441                                fields: Rc::new(RefCell::new(path_fields)),
11442                            });
11443                        }
11444                        "file_name" => {
11445                            let path = match fields.borrow().get("path") {
11446                                Some(Value::String(s)) => s.to_string(),
11447                                _ => return Err(RuntimeError::new("DirEntry has no path field")),
11448                            };
11449                            let fname = std::path::Path::new(&path)
11450                                .file_name()
11451                                .map(|f| f.to_string_lossy().to_string())
11452                                .unwrap_or_default();
11453                            let mut fname_fields = HashMap::new();
11454                            fname_fields.insert("value".to_string(), Value::String(Rc::new(fname)));
11455                            return Ok(Value::Struct {
11456                                name: "OsStr".to_string(),
11457                                fields: Rc::new(RefCell::new(fname_fields)),
11458                            });
11459                        }
11460                        _ => {}
11461                    }
11462                }
11463
11464                // Map methods - for built-in hash map operations
11465                if name == "Map" {
11466                    match method.name.as_str() {
11467                        "get" => {
11468                            // map.get(key) -> ?value
11469                            if arg_values.len() != 1 {
11470                                return Err(RuntimeError::new("Map.get expects 1 argument"));
11471                            }
11472                            let key = match &arg_values[0] {
11473                                Value::String(s) => s.to_string(),
11474                                Value::Int(n) => n.to_string(),
11475                                other => format!("{:?}", other),
11476                            };
11477                            if let Some(val) = fields.borrow().get(&key) {
11478                                return Ok(val.clone());
11479                            }
11480                            return Ok(Value::Null);
11481                        }
11482                        "insert" => {
11483                            // map.insert(key, value)
11484                            if arg_values.len() != 2 {
11485                                return Err(RuntimeError::new("Map.insert expects 2 arguments"));
11486                            }
11487                            let key = match &arg_values[0] {
11488                                Value::String(s) => s.to_string(),
11489                                Value::Int(n) => n.to_string(),
11490                                other => format!("{:?}", other),
11491                            };
11492                            crate::sigil_debug!(
11493                                "DEBUG Map.insert: key='{}', value={}",
11494                                key,
11495                                arg_values[1]
11496                            );
11497                            fields.borrow_mut().insert(key, arg_values[1].clone());
11498                            return Ok(Value::Null);
11499                        }
11500                        "contains_key" => {
11501                            if arg_values.len() != 1 {
11502                                return Err(RuntimeError::new(
11503                                    "Map.contains_key expects 1 argument",
11504                                ));
11505                            }
11506                            let key = match &arg_values[0] {
11507                                Value::String(s) => s.to_string(),
11508                                Value::Int(n) => n.to_string(),
11509                                other => format!("{:?}", other),
11510                            };
11511                            return Ok(Value::Bool(fields.borrow().contains_key(&key)));
11512                        }
11513                        "len" => {
11514                            return Ok(Value::Int(fields.borrow().len() as i64));
11515                        }
11516                        "is_empty" => {
11517                            return Ok(Value::Bool(fields.borrow().is_empty()));
11518                        }
11519                        "keys" => {
11520                            let keys: Vec<Value> = fields
11521                                .borrow()
11522                                .keys()
11523                                .map(|k| Value::String(Rc::new(k.clone())))
11524                                .collect();
11525                            return Ok(Value::Array(Rc::new(RefCell::new(keys))));
11526                        }
11527                        "values" => {
11528                            let vals: Vec<Value> = fields.borrow().values().cloned().collect();
11529                            return Ok(Value::Array(Rc::new(RefCell::new(vals))));
11530                        }
11531                        "clone" => {
11532                            return Ok(recv.clone());
11533                        }
11534                        _ => {}
11535                    }
11536                }
11537
11538                // HyperLogLog methods - probabilistic cardinality estimation
11539                if name == "HyperLogLog" {
11540                    match method.name.as_str() {
11541                        "insert" => {
11542                            // hll.insert(value) - add value to sketch
11543                            if arg_values.len() != 1 {
11544                                return Err(RuntimeError::new(
11545                                    "HyperLogLog.insert expects 1 argument",
11546                                ));
11547                            }
11548                            // Hash the value
11549                            let hash = match &arg_values[0] {
11550                                Value::String(s) => {
11551                                    use std::collections::hash_map::DefaultHasher;
11552                                    use std::hash::{Hash, Hasher};
11553                                    let mut hasher = DefaultHasher::new();
11554                                    s.hash(&mut hasher);
11555                                    hasher.finish()
11556                                }
11557                                Value::Int(n) => {
11558                                    use std::collections::hash_map::DefaultHasher;
11559                                    use std::hash::{Hash, Hasher};
11560                                    let mut hasher = DefaultHasher::new();
11561                                    n.hash(&mut hasher);
11562                                    hasher.finish()
11563                                }
11564                                other => {
11565                                    use std::collections::hash_map::DefaultHasher;
11566                                    use std::hash::{Hash, Hasher};
11567                                    let mut hasher = DefaultHasher::new();
11568                                    format!("{:?}", other).hash(&mut hasher);
11569                                    hasher.finish()
11570                                }
11571                            };
11572                            // Get precision and registers
11573                            let precision = match fields.borrow().get("__precision__") {
11574                                Some(Value::Int(p)) => *p as u32,
11575                                _ => 14,
11576                            };
11577                            let idx = (hash >> (64 - precision)) as usize;
11578                            let remaining = hash << precision | (1 << (precision - 1));
11579                            let leading_zeros = remaining.leading_zeros() + 1;
11580                            // Update register
11581                            if let Some(Value::Array(regs)) = fields.borrow().get("__registers__") {
11582                                let mut regs_borrow = regs.borrow_mut();
11583                                if idx < regs_borrow.len() {
11584                                    let current = match &regs_borrow[idx] {
11585                                        Value::Int(v) => *v as u32,
11586                                        _ => 0,
11587                                    };
11588                                    if leading_zeros > current {
11589                                        regs_borrow[idx] = Value::Int(leading_zeros as i64);
11590                                    }
11591                                }
11592                            }
11593                            // Increment count for tracking
11594                            let count_val = fields.borrow().get("__count__").cloned();
11595                            if let Some(Value::Int(c)) = count_val {
11596                                fields
11597                                    .borrow_mut()
11598                                    .insert("__count__".to_string(), Value::Int(c + 1));
11599                            }
11600                            return Ok(Value::Null);
11601                        }
11602                        "count" => {
11603                            // hll.count() or hll|◊count - get approximate cardinality
11604                            if let Some(Value::Array(regs)) = fields.borrow().get("__registers__") {
11605                                let regs_borrow = regs.borrow();
11606                                let m = regs_borrow.len() as f64;
11607                                // Harmonic mean of 2^(-register[i])
11608                                let mut sum = 0.0;
11609                                let mut zeros = 0;
11610                                for reg in regs_borrow.iter() {
11611                                    let val = match reg {
11612                                        Value::Int(v) => *v as i32,
11613                                        _ => 0,
11614                                    };
11615                                    sum += 2.0_f64.powi(-val);
11616                                    if val == 0 {
11617                                        zeros += 1;
11618                                    }
11619                                }
11620                                // Alpha correction factor for m=16384
11621                                let alpha = 0.7213 / (1.0 + 1.079 / m);
11622                                let estimate = alpha * m * m / sum;
11623                                // Linear counting for small cardinalities
11624                                let result = if estimate <= 2.5 * m && zeros > 0 {
11625                                    m * (m / zeros as f64).ln()
11626                                } else {
11627                                    estimate
11628                                };
11629                                return Ok(Value::Int(result.round() as i64));
11630                            }
11631                            return Ok(Value::Int(0));
11632                        }
11633                        _ => {}
11634                    }
11635                }
11636
11637                // BloomFilter methods - probabilistic set membership
11638                if name == "BloomFilter" {
11639                    match method.name.as_str() {
11640                        "insert" => {
11641                            if arg_values.len() != 1 {
11642                                return Err(RuntimeError::new(
11643                                    "BloomFilter.insert expects 1 argument",
11644                                ));
11645                            }
11646                            let size = match fields.borrow().get("__size__") {
11647                                Some(Value::Int(s)) => *s as usize,
11648                                _ => 1024,
11649                            };
11650                            let num_hashes = match fields.borrow().get("__num_hashes__") {
11651                                Some(Value::Int(n)) => *n as usize,
11652                                _ => 3,
11653                            };
11654                            // Hash the value multiple times
11655                            let base_hash = match &arg_values[0] {
11656                                Value::String(s) => {
11657                                    use std::collections::hash_map::DefaultHasher;
11658                                    use std::hash::{Hash, Hasher};
11659                                    let mut hasher = DefaultHasher::new();
11660                                    s.hash(&mut hasher);
11661                                    hasher.finish()
11662                                }
11663                                Value::Int(n) => *n as u64,
11664                                other => {
11665                                    use std::collections::hash_map::DefaultHasher;
11666                                    use std::hash::{Hash, Hasher};
11667                                    let mut hasher = DefaultHasher::new();
11668                                    format!("{:?}", other).hash(&mut hasher);
11669                                    hasher.finish()
11670                                }
11671                            };
11672                            // Set bits using double hashing
11673                            if let Some(Value::Array(bits)) = fields.borrow().get("__bits__") {
11674                                let mut bits_borrow = bits.borrow_mut();
11675                                for i in 0..num_hashes {
11676                                    let h = (base_hash
11677                                        .wrapping_add(i as u64 * base_hash.rotate_left(17)))
11678                                        % size as u64;
11679                                    bits_borrow[h as usize] = Value::Bool(true);
11680                                }
11681                            }
11682                            return Ok(Value::Null);
11683                        }
11684                        "contains" => {
11685                            if arg_values.len() != 1 {
11686                                return Err(RuntimeError::new(
11687                                    "BloomFilter.contains expects 1 argument",
11688                                ));
11689                            }
11690                            let size = match fields.borrow().get("__size__") {
11691                                Some(Value::Int(s)) => *s as usize,
11692                                _ => 1024,
11693                            };
11694                            let num_hashes = match fields.borrow().get("__num_hashes__") {
11695                                Some(Value::Int(n)) => *n as usize,
11696                                _ => 3,
11697                            };
11698                            let base_hash = match &arg_values[0] {
11699                                Value::String(s) => {
11700                                    use std::collections::hash_map::DefaultHasher;
11701                                    use std::hash::{Hash, Hasher};
11702                                    let mut hasher = DefaultHasher::new();
11703                                    s.hash(&mut hasher);
11704                                    hasher.finish()
11705                                }
11706                                Value::Int(n) => *n as u64,
11707                                other => {
11708                                    use std::collections::hash_map::DefaultHasher;
11709                                    use std::hash::{Hash, Hasher};
11710                                    let mut hasher = DefaultHasher::new();
11711                                    format!("{:?}", other).hash(&mut hasher);
11712                                    hasher.finish()
11713                                }
11714                            };
11715                            // Check all bits
11716                            if let Some(Value::Array(bits)) = fields.borrow().get("__bits__") {
11717                                let bits_borrow = bits.borrow();
11718                                for i in 0..num_hashes {
11719                                    let h = (base_hash
11720                                        .wrapping_add(i as u64 * base_hash.rotate_left(17)))
11721                                        % size as u64;
11722                                    match &bits_borrow[h as usize] {
11723                                        Value::Bool(true) => {}
11724                                        _ => return Ok(Value::Bool(false)),
11725                                    }
11726                                }
11727                                return Ok(Value::Bool(true));
11728                            }
11729                            return Ok(Value::Bool(false));
11730                        }
11731                        _ => {}
11732                    }
11733                }
11734
11735                // CountMinSketch methods - frequency estimation
11736                if name == "CountMinSketch" {
11737                    match method.name.as_str() {
11738                        "insert" => {
11739                            if arg_values.len() != 1 {
11740                                return Err(RuntimeError::new(
11741                                    "CountMinSketch.insert expects 1 argument",
11742                                ));
11743                            }
11744                            let depth = match fields.borrow().get("__depth__") {
11745                                Some(Value::Int(d)) => *d as usize,
11746                                _ => 4,
11747                            };
11748                            let width = match fields.borrow().get("__width__") {
11749                                Some(Value::Int(w)) => *w as usize,
11750                                _ => 1024,
11751                            };
11752                            let base_hash = match &arg_values[0] {
11753                                Value::String(s) => {
11754                                    use std::collections::hash_map::DefaultHasher;
11755                                    use std::hash::{Hash, Hasher};
11756                                    let mut hasher = DefaultHasher::new();
11757                                    s.hash(&mut hasher);
11758                                    hasher.finish()
11759                                }
11760                                Value::Int(n) => *n as u64,
11761                                other => {
11762                                    use std::collections::hash_map::DefaultHasher;
11763                                    use std::hash::{Hash, Hasher};
11764                                    let mut hasher = DefaultHasher::new();
11765                                    format!("{:?}", other).hash(&mut hasher);
11766                                    hasher.finish()
11767                                }
11768                            };
11769                            // Increment counters in each row
11770                            if let Some(Value::Array(counters)) = fields.borrow().get("__counters__") {
11771                                let counters_borrow = counters.borrow();
11772                                for i in 0..depth {
11773                                    let h = (base_hash.wrapping_add(i as u64 * 0x517cc1b727220a95))
11774                                        % width as u64;
11775                                    if let Value::Array(row) = &counters_borrow[i] {
11776                                        let mut row_borrow = row.borrow_mut();
11777                                        if let Value::Int(c) = &row_borrow[h as usize] {
11778                                            row_borrow[h as usize] = Value::Int(c + 1);
11779                                        }
11780                                    }
11781                                }
11782                            }
11783                            return Ok(Value::Null);
11784                        }
11785                        "frequency" => {
11786                            if arg_values.len() != 1 {
11787                                return Err(RuntimeError::new(
11788                                    "CountMinSketch.frequency expects 1 argument",
11789                                ));
11790                            }
11791                            let depth = match fields.borrow().get("__depth__") {
11792                                Some(Value::Int(d)) => *d as usize,
11793                                _ => 4,
11794                            };
11795                            let width = match fields.borrow().get("__width__") {
11796                                Some(Value::Int(w)) => *w as usize,
11797                                _ => 1024,
11798                            };
11799                            let base_hash = match &arg_values[0] {
11800                                Value::String(s) => {
11801                                    use std::collections::hash_map::DefaultHasher;
11802                                    use std::hash::{Hash, Hasher};
11803                                    let mut hasher = DefaultHasher::new();
11804                                    s.hash(&mut hasher);
11805                                    hasher.finish()
11806                                }
11807                                Value::Int(n) => *n as u64,
11808                                other => {
11809                                    use std::collections::hash_map::DefaultHasher;
11810                                    use std::hash::{Hash, Hasher};
11811                                    let mut hasher = DefaultHasher::new();
11812                                    format!("{:?}", other).hash(&mut hasher);
11813                                    hasher.finish()
11814                                }
11815                            };
11816                            // Get minimum counter value across all rows
11817                            let mut min_count = i64::MAX;
11818                            if let Some(Value::Array(counters)) = fields.borrow().get("__counters__") {
11819                                let counters_borrow = counters.borrow();
11820                                for i in 0..depth {
11821                                    let h = (base_hash.wrapping_add(i as u64 * 0x517cc1b727220a95))
11822                                        % width as u64;
11823                                    if let Value::Array(row) = &counters_borrow[i] {
11824                                        let row_borrow = row.borrow();
11825                                        if let Value::Int(c) = &row_borrow[h as usize] {
11826                                            if *c < min_count {
11827                                                min_count = *c;
11828                                            }
11829                                        }
11830                                    }
11831                                }
11832                            }
11833                            return Ok(Value::Int(if min_count == i64::MAX {
11834                                0
11835                            } else {
11836                                min_count
11837                            }));
11838                        }
11839                        _ => {}
11840                    }
11841                }
11842
11843                // MerkleTree methods - data integrity verification
11844                if name == "MerkleTree" {
11845                    match method.name.as_str() {
11846                        "insert" => {
11847                            if arg_values.len() != 1 {
11848                                return Err(RuntimeError::new(
11849                                    "MerkleTree.insert expects 1 argument",
11850                                ));
11851                            }
11852                            // Hash the value and add to leaves
11853                            let data = match &arg_values[0] {
11854                                Value::String(s) => s.as_bytes().to_vec(),
11855                                Value::Int(n) => n.to_le_bytes().to_vec(),
11856                                other => format!("{:?}", other).into_bytes(),
11857                            };
11858                            use std::collections::hash_map::DefaultHasher;
11859                            use std::hash::{Hash, Hasher};
11860                            let mut hasher = DefaultHasher::new();
11861                            data.hash(&mut hasher);
11862                            let leaf_hash = format!("{:016x}", hasher.finish());
11863                            if let Some(Value::Array(leaves)) = fields.borrow().get("_leaves") {
11864                                leaves.borrow_mut().push(Value::String(Rc::new(leaf_hash)));
11865                            }
11866                            // Rebuild tree (simplified - just set root to hash of all leaves)
11867                            if let Some(Value::Array(leaves)) = fields.borrow().get("_leaves") {
11868                                let leaves_borrow = leaves.borrow();
11869                                let combined: String = leaves_borrow
11870                                    .iter()
11871                                    .filter_map(|v| match v {
11872                                        Value::String(s) => Some(s.to_string()),
11873                                        _ => None,
11874                                    })
11875                                    .collect();
11876                                let mut root_hasher = DefaultHasher::new();
11877                                combined.hash(&mut root_hasher);
11878                                let root = format!("{:016x}", root_hasher.finish());
11879                                fields
11880                                    .borrow_mut()
11881                                    .insert("_root".to_string(), Value::String(Rc::new(root)));
11882                            }
11883                            return Ok(Value::Null);
11884                        }
11885                        "verify" => {
11886                            // Verify the tree is consistent (root matches leaves)
11887                            use std::collections::hash_map::DefaultHasher;
11888                            use std::hash::{Hash, Hasher};
11889                            if let (Some(Value::Array(leaves)), Some(Value::String(root))) = (
11890                                fields.borrow().get("_leaves").cloned(),
11891                                fields.borrow().get("_root").cloned(),
11892                            ) {
11893                                let leaves_borrow = leaves.borrow();
11894                                let combined: String = leaves_borrow
11895                                    .iter()
11896                                    .filter_map(|v| match v {
11897                                        Value::String(s) => Some(s.to_string()),
11898                                        _ => None,
11899                                    })
11900                                    .collect();
11901                                let mut hasher = DefaultHasher::new();
11902                                combined.hash(&mut hasher);
11903                                let computed_root = format!("{:016x}", hasher.finish());
11904                                return Ok(Value::Bool(*root == computed_root));
11905                            }
11906                            return Ok(Value::Bool(false));
11907                        }
11908                        "root" => {
11909                            // Get the root hash
11910                            if let Some(root) = fields.borrow().get("_root").cloned() {
11911                                return Ok(root);
11912                            }
11913                            return Ok(Value::Null);
11914                        }
11915                        "prove_inclusion" => {
11916                            // Generate inclusion proof for item at index
11917                            if arg_values.len() != 1 {
11918                                return Err(RuntimeError::new(
11919                                    "MerkleTree.prove_inclusion expects 1 argument",
11920                                ));
11921                            }
11922                            let idx = match &arg_values[0] {
11923                                Value::Int(i) => *i as usize,
11924                                _ => {
11925                                    return Err(RuntimeError::new(
11926                                        "prove_inclusion requires integer index",
11927                                    ))
11928                                }
11929                            };
11930                            // Create a proof struct
11931                            let mut proof_fields = std::collections::HashMap::new();
11932                            proof_fields.insert("_index".to_string(), Value::Int(idx as i64));
11933                            if let Some(root) = fields.borrow().get("_root").cloned() {
11934                                proof_fields.insert("_root".to_string(), root);
11935                            }
11936                            if let Some(leaves) = fields.borrow().get("_leaves").cloned() {
11937                                proof_fields.insert("_leaves".to_string(), leaves);
11938                            }
11939                            proof_fields.insert("_valid".to_string(), Value::Bool(true));
11940                            return Ok(Value::Struct {
11941                                name: "MerkleProof".to_string(),
11942                                fields: Rc::new(RefCell::new(proof_fields)),
11943                            });
11944                        }
11945                        _ => {}
11946                    }
11947                }
11948
11949                // MerkleProof methods
11950                if name == "MerkleProof" {
11951                    match method.name.as_str() {
11952                        "verify" => {
11953                            // Verify the proof is valid
11954                            if let Some(Value::Bool(valid)) = fields.borrow().get("_valid") {
11955                                return Ok(Value::Bool(*valid));
11956                            }
11957                            return Ok(Value::Bool(false));
11958                        }
11959                        _ => {}
11960                    }
11961                }
11962
11963                // UntrustedData methods
11964                if name == "UntrustedData" {
11965                    match method.name.as_str() {
11966                        "verify" => {
11967                            // Simulate verification - return the verified value
11968                            fields
11969                                .borrow_mut()
11970                                .insert("_verified".to_string(), Value::Bool(true));
11971                            // Return the value field if it exists
11972                            if let Some(val) = fields.borrow().get("value").cloned() {
11973                                return Ok(val);
11974                            }
11975                            return Ok(Value::Bool(true));
11976                        }
11977                        _ => {}
11978                    }
11979                }
11980
11981                // QHCompressed methods
11982                if name == "QHCompressed" {
11983                    match method.name.as_str() {
11984                        "size" => {
11985                            if let Some(Value::Int(size)) = fields.borrow().get("_compressed_size")
11986                            {
11987                                return Ok(Value::Int(*size));
11988                            }
11989                            return Ok(Value::Int(1)); // Default size
11990                        }
11991                        _ => {}
11992                    }
11993                }
11994
11995                // Superposition methods
11996                if name == "Superposition" {
11997                    match method.name.as_str() {
11998                        "observe" => {
11999                            // Collapse superposition to a single value
12000                            // Check _values field first
12001                            if let Some(Value::Array(values)) = fields.borrow().get("_values") {
12002                                let values_borrow = values.borrow();
12003                                if !values_borrow.is_empty() {
12004                                    // For deterministic tests, return first value
12005                                    // In real impl, would use weighted random
12006                                    return Ok(values_borrow[0].clone());
12007                                }
12008                            }
12009                            // Also check states field (used by QH uniform)
12010                            if let Some(Value::Array(states)) = fields.borrow().get("states") {
12011                                let states_borrow = states.borrow();
12012                                if !states_borrow.is_empty() {
12013                                    return Ok(states_borrow[0].clone());
12014                                }
12015                            }
12016                            return Ok(Value::Null);
12017                        }
12018                        _ => {}
12019                    }
12020                }
12021
12022                // Check for user-defined method before hardcoded struct handlers
12023                // This ensures user impls take priority over stdlib defaults
12024                {
12025                    let user_method_name = format!("{}·{}", name, method.name);
12026                    let user_fn = self.globals.borrow().get(&user_method_name).map(|v| v.clone());
12027                    if let Some(Value::Function(func)) = user_fn {
12028                        let func = Self::wrap_with_const_generics(&func, fields);
12029                        let old_self_type = self.current_self_type.take();
12030                        self.current_self_type = Some(name.clone());
12031
12032                        // Reorder named args to match function params (skip first param which is self)
12033                        let reordered = if func.params.len() > 1 {
12034                            Self::reorder_named_args(&func.params[1..].to_vec(), arg_entries.clone())?
12035                        } else {
12036                            arg_values.clone()
12037                        };
12038                        let self_val = Value::Struct {
12039                            name: name.clone(),
12040                            fields: fields.clone(),
12041                        };
12042                        let mut all_args = vec![self_val];
12043                        all_args.extend(reordered);
12044                        let result = self.call_function(&func, all_args);
12045
12046                        self.current_self_type = old_self_type;
12047                        return result;
12048                    }
12049                }
12050
12051                // ReLU forward method (stdlib fallback)
12052                if name == "ReLU" && method.name == "forward" {
12053                    if let Some(input) = arg_values.first() {
12054                        // Apply ReLU: max(0, x) for each element
12055                        if let Value::Struct {
12056                            name: tensor_name,
12057                            fields: tensor_fields,
12058                        } = input
12059                        {
12060                            if tensor_name == "Tensor" {
12061                                let tensor_ref = tensor_fields.borrow();
12062                                let shape = tensor_ref.get("shape").cloned();
12063                                let data: Vec<f64> = match tensor_ref.get("data") {
12064                                    Some(Value::Array(arr)) => arr
12065                                        .borrow()
12066                                        .iter()
12067                                        .map(|v| match v {
12068                                            Value::Float(f) => *f,
12069                                            Value::Int(n) => *n as f64,
12070                                            _ => 0.0,
12071                                        })
12072                                        .collect(),
12073                                    _ => vec![],
12074                                };
12075                                drop(tensor_ref);
12076
12077                                // Apply ReLU
12078                                let relu_data: Vec<Value> = data
12079                                    .iter()
12080                                    .map(|x| Value::Float(if *x > 0.0 { *x } else { 0.0 }))
12081                                    .collect();
12082
12083                                let mut result_fields = HashMap::new();
12084                                if let Some(s) = shape {
12085                                    result_fields.insert("shape".to_string(), s);
12086                                }
12087                                result_fields.insert(
12088                                    "data".to_string(),
12089                                    Value::Array(Rc::new(RefCell::new(relu_data))),
12090                                );
12091                                result_fields
12092                                    .insert("requires_grad".to_string(), Value::Bool(false));
12093                                return Ok(Value::Struct {
12094                                    name: "Tensor".to_string(),
12095                                    fields: Rc::new(RefCell::new(result_fields)),
12096                                });
12097                            }
12098                        }
12099                    }
12100                    return Err(RuntimeError::new("ReLU.forward expects a Tensor"));
12101                }
12102
12103                // Sequential forward method
12104                if name == "Sequential" && method.name == "forward" {
12105                    if let Some(input) = arg_values.first().cloned() {
12106                        let layers = fields.borrow().get("layers").cloned();
12107                        if let Some(Value::Array(layers_arr)) = layers {
12108                            let mut current = input;
12109                            for layer in layers_arr.borrow().iter() {
12110                                if let Value::Struct {
12111                                    name: layer_name,
12112                                    fields: layer_fields,
12113                                } = layer
12114                                {
12115                                    // Try built-in forward for known layer types
12116                                    if layer_name == "ReLU" {
12117                                        // Apply ReLU
12118                                        if let Value::Struct {
12119                                            name: tn,
12120                                            fields: tf,
12121                                        } = &current
12122                                        {
12123                                            if tn == "Tensor" {
12124                                                let tf_ref = tf.borrow();
12125                                                let shape = tf_ref.get("shape").cloned();
12126                                                let data: Vec<f64> = match tf_ref.get("data") {
12127                                                    Some(Value::Array(arr)) => arr
12128                                                        .borrow()
12129                                                        .iter()
12130                                                        .map(|v| match v {
12131                                                            Value::Float(f) => *f,
12132                                                            Value::Int(n) => *n as f64,
12133                                                            _ => 0.0,
12134                                                        })
12135                                                        .collect(),
12136                                                    _ => vec![],
12137                                                };
12138                                                drop(tf_ref);
12139
12140                                                let relu_data: Vec<Value> = data
12141                                                    .iter()
12142                                                    .map(|x| {
12143                                                        Value::Float(if *x > 0.0 {
12144                                                            *x
12145                                                        } else {
12146                                                            0.0
12147                                                        })
12148                                                    })
12149                                                    .collect();
12150
12151                                                let mut result_fields = HashMap::new();
12152                                                if let Some(s) = shape {
12153                                                    result_fields.insert("shape".to_string(), s);
12154                                                }
12155                                                result_fields.insert(
12156                                                    "data".to_string(),
12157                                                    Value::Array(Rc::new(RefCell::new(relu_data))),
12158                                                );
12159                                                result_fields.insert(
12160                                                    "requires_grad".to_string(),
12161                                                    Value::Bool(false),
12162                                                );
12163                                                current = Value::Struct {
12164                                                    name: "Tensor".to_string(),
12165                                                    fields: Rc::new(RefCell::new(result_fields)),
12166                                                };
12167                                            }
12168                                        }
12169                                    } else if layer_name == "Linear" {
12170                                        // Apply Linear: weight @ x + bias
12171                                        let layer_ref = layer_fields.borrow();
12172                                        let weight = layer_ref.get("weight").cloned();
12173                                        let bias = layer_ref.get("bias").cloned();
12174                                        drop(layer_ref);
12175
12176                                        if let (Some(w), Some(b)) = (weight, bias) {
12177                                            // We need to do matmul and add for Linear
12178                                            // For now, just extract data and do the computation inline
12179                                            if let (
12180                                                Value::Struct {
12181                                                    fields: w_fields, ..
12182                                                },
12183                                                Value::Struct {
12184                                                    fields: x_fields, ..
12185                                                },
12186                                                Value::Struct {
12187                                                    fields: b_fields, ..
12188                                                },
12189                                            ) = (&w, &current, &b)
12190                                            {
12191                                                // Get weight matrix [out, in]
12192                                                let w_shape: Vec<usize> =
12193                                                    match w_fields.borrow().get("shape") {
12194                                                        Some(Value::Array(arr)) => arr
12195                                                            .borrow()
12196                                                            .iter()
12197                                                            .filter_map(|v| match v {
12198                                                                Value::Int(n) => Some(*n as usize),
12199                                                                _ => None,
12200                                                            })
12201                                                            .collect(),
12202                                                        _ => vec![],
12203                                                    };
12204                                                let w_data: Vec<f64> =
12205                                                    match w_fields.borrow().get("data") {
12206                                                        Some(Value::Array(arr)) => arr
12207                                                            .borrow()
12208                                                            .iter()
12209                                                            .filter_map(|v| match v {
12210                                                                Value::Float(f) => Some(*f),
12211                                                                Value::Int(n) => Some(*n as f64),
12212                                                                _ => None,
12213                                                            })
12214                                                            .collect(),
12215                                                        _ => vec![],
12216                                                    };
12217
12218                                                // Get input [in] or [in, 1]
12219                                                let x_data: Vec<f64> =
12220                                                    match x_fields.borrow().get("data") {
12221                                                        Some(Value::Array(arr)) => arr
12222                                                            .borrow()
12223                                                            .iter()
12224                                                            .filter_map(|v| match v {
12225                                                                Value::Float(f) => Some(*f),
12226                                                                Value::Int(n) => Some(*n as f64),
12227                                                                _ => None,
12228                                                            })
12229                                                            .collect(),
12230                                                        _ => vec![],
12231                                                    };
12232
12233                                                // Get bias [out]
12234                                                let b_data: Vec<f64> =
12235                                                    match b_fields.borrow().get("data") {
12236                                                        Some(Value::Array(arr)) => arr
12237                                                            .borrow()
12238                                                            .iter()
12239                                                            .filter_map(|v| match v {
12240                                                                Value::Float(f) => Some(*f),
12241                                                                Value::Int(n) => Some(*n as f64),
12242                                                                _ => None,
12243                                                            })
12244                                                            .collect(),
12245                                                        _ => vec![],
12246                                                    };
12247
12248                                                // Matmul: w @ x + b
12249                                                let out_size =
12250                                                    if w_shape.len() >= 2 { w_shape[0] } else { 1 };
12251                                                let in_size = if w_shape.len() >= 2 {
12252                                                    w_shape[1]
12253                                                } else if !w_shape.is_empty() {
12254                                                    w_shape[0]
12255                                                } else {
12256                                                    1
12257                                                };
12258
12259                                                let mut result = vec![0.0; out_size];
12260                                                for i in 0..out_size {
12261                                                    let mut sum = 0.0;
12262                                                    for j in 0..in_size {
12263                                                        if i * in_size + j < w_data.len()
12264                                                            && j < x_data.len()
12265                                                        {
12266                                                            sum +=
12267                                                                w_data[i * in_size + j] * x_data[j];
12268                                                        }
12269                                                    }
12270                                                    // Add bias
12271                                                    if i < b_data.len() {
12272                                                        sum += b_data[i];
12273                                                    }
12274                                                    result[i] = sum;
12275                                                }
12276
12277                                                // Create output tensor
12278                                                let mut result_fields = HashMap::new();
12279                                                result_fields.insert(
12280                                                    "shape".to_string(),
12281                                                    Value::Array(Rc::new(RefCell::new(vec![
12282                                                        Value::Int(out_size as i64),
12283                                                    ]))),
12284                                                );
12285                                                result_fields.insert(
12286                                                    "data".to_string(),
12287                                                    Value::Array(Rc::new(RefCell::new(
12288                                                        result
12289                                                            .into_iter()
12290                                                            .map(Value::Float)
12291                                                            .collect(),
12292                                                    ))),
12293                                                );
12294                                                result_fields.insert(
12295                                                    "requires_grad".to_string(),
12296                                                    Value::Bool(false),
12297                                                );
12298                                                current = Value::Struct {
12299                                                    name: "Tensor".to_string(),
12300                                                    fields: Rc::new(RefCell::new(result_fields)),
12301                                                };
12302                                            }
12303                                        }
12304                                    }
12305                                }
12306                            }
12307                            return Ok(current);
12308                        }
12309                    }
12310                    return Err(RuntimeError::new("Sequential.forward expects input tensor"));
12311                }
12312
12313                let qualified_name = format!("{}·{}", name, method.name);
12314
12315                // Debug: track Parser method calls
12316                if name == "Parser" && (method.name == "parse_file" || method.name == "read_source")
12317                {
12318                    crate::sigil_debug!("DEBUG Parser method call: {}", qualified_name);
12319                    for (i, arg) in arg_values.iter().enumerate() {
12320                        crate::sigil_debug!("  arg_value[{}] = {:?}", i, arg);
12321                    }
12322                }
12323
12324                // Debug: track Lexer method calls
12325                if name == "Lexer" {
12326                    // Print all args for lex_ident_or_keyword
12327                    if method.name == "lex_ident_or_keyword" {
12328                        for (i, arg) in arg_values.iter().enumerate() {
12329                            let unwrapped = Self::unwrap_all(arg);
12330                            if let Value::Char(c) = &unwrapped {
12331                                crate::sigil_debug!(
12332                                    "DEBUG Lexer·lex_ident_or_keyword arg[{}]='{}'",
12333                                    i,
12334                                    c
12335                                );
12336                            }
12337                        }
12338                    }
12339                    crate::sigil_debug!("DEBUG Lexer method call: {}", qualified_name);
12340                }
12341                // Check if arg is "fn" string
12342                for arg in &arg_values {
12343                    let unwrapped = Self::unwrap_all(arg);
12344                    if let Value::String(s) = &unwrapped {
12345                        if **s == "fn" {
12346                            crate::sigil_debug!(
12347                                "DEBUG struct method with 'fn': {} recv_name={}",
12348                                method.name,
12349                                name
12350                            );
12351                        }
12352                    }
12353                }
12354
12355                let func = self
12356                    .globals
12357                    .borrow()
12358                    .get(&qualified_name)
12359                    .map(|v| v.clone());
12360                if let Some(func) = func {
12361                    if let Value::Function(f) = func {
12362                        let f = Self::wrap_with_const_generics(&f, fields);
12363                        // Set current Self type for Self { ... } resolution
12364                        let old_self_type = self.current_self_type.take();
12365                        self.current_self_type = Some(name.clone());
12366
12367                        // Call with self as first argument
12368                        // Reorder named args to match function params (skip first param which is self)
12369                        let reordered = if f.params.len() > 1 {
12370                            Self::reorder_named_args(&f.params[1..].to_vec(), arg_entries.clone())?
12371                        } else {
12372                            arg_values.clone()
12373                        };
12374                        let mut all_args = vec![recv.clone()];
12375                        all_args.extend(reordered);
12376                        let result = self.call_function(&f, all_args);
12377
12378                        // Restore old Self type
12379                        self.current_self_type = old_self_type;
12380                        return result;
12381                    } else if let Value::BuiltIn(b) = func {
12382                        let mut all_args = vec![recv.clone()];
12383                        all_args.extend(arg_values.clone());
12384                        return (b.func)(self, all_args);
12385                    }
12386                }
12387
12388                // If struct name is "Self", try to find the method by searching all types
12389                if name == "Self" {
12390                    // Get field names to match struct type
12391                    let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
12392
12393                    // Search through registered types to find a matching struct
12394                    for (type_name, type_def) in &self.types {
12395                        if let TypeDef::Struct(struct_def) = type_def {
12396                            // Check if field names match
12397                            let def_fields: Vec<String> = match &struct_def.fields {
12398                                crate::ast::StructFields::Named(fs) => {
12399                                    fs.iter().map(|f| f.name.name.clone()).collect()
12400                                }
12401                                _ => continue,
12402                            };
12403
12404                            // Rough match - if we have fields that exist in the definition
12405                            let matches = field_names.iter().all(|f| def_fields.contains(f));
12406                            if matches {
12407                                let qualified_name = format!("{}·{}", type_name, method.name);
12408                                let func = self
12409                                    .globals
12410                                    .borrow()
12411                                    .get(&qualified_name)
12412                                    .map(|v| v.clone());
12413                                if let Some(func) = func {
12414                                    if let Value::Function(f) = func {
12415                                        let f = Self::wrap_with_const_generics(&f, fields);
12416                                        // Set current Self type for Self { ... } resolution
12417                                        let old_self_type = self.current_self_type.take();
12418                                        self.current_self_type = Some(type_name.clone());
12419
12420                                        // Reorder named args to match function params (skip first param which is self)
12421                                        let reordered = if f.params.len() > 1 {
12422                                            Self::reorder_named_args(
12423                                                &f.params[1..].to_vec(),
12424                                                arg_entries.clone(),
12425                                            )?
12426                                        } else {
12427                                            arg_values.clone()
12428                                        };
12429                                        let mut all_args = vec![recv.clone()];
12430                                        all_args.extend(reordered);
12431                                        let result = self.call_function(&f, all_args);
12432
12433                                        // Restore old Self type
12434                                        self.current_self_type = old_self_type;
12435                                        return result;
12436                                    } else if let Value::BuiltIn(b) = func {
12437                                        let mut all_args = vec![recv.clone()];
12438                                        all_args.extend(arg_values.clone());
12439                                        return (b.func)(self, all_args);
12440                                    }
12441                                }
12442                            }
12443                        }
12444                    }
12445                }
12446
12447                // Error on unknown methods - type checking
12448                Err(RuntimeError::new(format!(
12449                    "no method '{}' on struct '{}'",
12450                    method.name, name
12451                )))
12452            }
12453            // Try variant method lookup: EnumName·method
12454            (
12455                Value::Variant {
12456                    enum_name,
12457                    variant_name,
12458                    fields,
12459                },
12460                _,
12461            ) => {
12462                // Built-in Option methods
12463                if enum_name == "Option" {
12464                    match method.name.as_str() {
12465                        "cloned" => {
12466                            // cloned() on Option<&T> returns Option<T>
12467                            // In our interpreter, just clone the value
12468                            return Ok(recv.clone());
12469                        }
12470                        "is_some" => {
12471                            return Ok(Value::Bool(variant_name == "Some"));
12472                        }
12473                        "is_none" => {
12474                            return Ok(Value::Bool(variant_name == "None"));
12475                        }
12476                        "unwrap" => {
12477                            crate::sigil_debug!(
12478                                "DEBUG Option.unwrap: variant={}, fields={:?}",
12479                                variant_name,
12480                                fields
12481                            );
12482                            if variant_name == "Some" {
12483                                if let Some(f) = fields {
12484                                    let result = f.first().cloned().unwrap_or(Value::Null);
12485                                    crate::sigil_debug!(
12486                                        "DEBUG Option.unwrap: returning {:?}",
12487                                        result
12488                                    );
12489                                    return Ok(result);
12490                                }
12491                            }
12492                            return Err(RuntimeError::new("unwrap on None"));
12493                        }
12494                        "unwrap_or" => {
12495                            if variant_name == "Some" {
12496                                if let Some(f) = fields {
12497                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
12498                                }
12499                            }
12500                            return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
12501                        }
12502                        "map" => {
12503                            // Option::map takes a closure
12504                            if variant_name == "Some" {
12505                                if let Some(f) = fields {
12506                                    if let Some(inner) = f.first() {
12507                                        if let Some(Value::Function(func)) = arg_values.first() {
12508                                            let result =
12509                                                self.call_function(func, vec![inner.clone()])?;
12510                                            return Ok(Value::Variant {
12511                                                enum_name: "Option".to_string(),
12512                                                variant_name: "Some".to_string(),
12513                                                fields: Some(Rc::new(vec![result])),
12514                                            });
12515                                        }
12516                                    }
12517                                }
12518                            }
12519                            return Ok(Value::Variant {
12520                                enum_name: "Option".to_string(),
12521                                variant_name: "None".to_string(),
12522                                fields: None,
12523                            });
12524                        }
12525                        "and_then" => {
12526                            // Option::and_then takes a closure that returns Option<U>
12527                            crate::sigil_debug!(
12528                                "DEBUG and_then: variant={}, has_fields={}, arg_count={}",
12529                                variant_name,
12530                                fields.is_some(),
12531                                arg_values.len()
12532                            );
12533                            if let Some(arg) = arg_values.first() {
12534                                crate::sigil_debug!(
12535                                    "DEBUG and_then: arg type = {:?}",
12536                                    std::mem::discriminant(arg)
12537                                );
12538                            }
12539                            if variant_name == "Some" {
12540                                if let Some(f) = fields {
12541                                    if let Some(inner) = f.first() {
12542                                        crate::sigil_debug!("DEBUG and_then: inner = {:?}", inner);
12543                                        if let Some(Value::Function(func)) = arg_values.first() {
12544                                            let result =
12545                                                self.call_function(func, vec![inner.clone()])?;
12546                                            crate::sigil_debug!(
12547                                                "DEBUG and_then: result = {:?}",
12548                                                result
12549                                            );
12550                                            // The closure should return an Option, return it directly
12551                                            return Ok(result);
12552                                        } else {
12553                                            crate::sigil_debug!(
12554                                                "DEBUG and_then: arg is not a Function!"
12555                                            );
12556                                        }
12557                                    }
12558                                }
12559                            }
12560                            // None case - return None
12561                            return Ok(Value::Variant {
12562                                enum_name: "Option".to_string(),
12563                                variant_name: "None".to_string(),
12564                                fields: None,
12565                            });
12566                        }
12567                        "or_else" => {
12568                            // Option::or_else takes a closure that returns Option<T>
12569                            if variant_name == "Some" {
12570                                // Some case - return self
12571                                return Ok(recv.clone());
12572                            }
12573                            // None case - call the closure
12574                            if let Some(Value::Function(func)) = arg_values.first() {
12575                                return self.call_function(func, vec![]);
12576                            }
12577                            return Ok(recv.clone());
12578                        }
12579                        "ok_or" | "ok_or_else" => {
12580                            // Convert Option to Result
12581                            if variant_name == "Some" {
12582                                if let Some(f) = fields {
12583                                    if let Some(inner) = f.first() {
12584                                        return Ok(Value::Variant {
12585                                            enum_name: "Result".to_string(),
12586                                            variant_name: "Ok".to_string(),
12587                                            fields: Some(Rc::new(vec![inner.clone()])),
12588                                        });
12589                                    }
12590                                }
12591                            }
12592                            // None case - return Err with the provided value
12593                            let err_val = arg_values
12594                                .first()
12595                                .cloned()
12596                                .unwrap_or(Value::String(Rc::new("None".to_string())));
12597                            return Ok(Value::Variant {
12598                                enum_name: "Result".to_string(),
12599                                variant_name: "Err".to_string(),
12600                                fields: Some(Rc::new(vec![err_val])),
12601                            });
12602                        }
12603                        _ => {}
12604                    }
12605                }
12606                // Built-in Result methods
12607                if enum_name == "Result" {
12608                    match method.name.as_str() {
12609                        "is_ok" => {
12610                            return Ok(Value::Bool(variant_name == "Ok"));
12611                        }
12612                        "is_err" => {
12613                            return Ok(Value::Bool(variant_name == "Err"));
12614                        }
12615                        "ok" => {
12616                            // Convert Result<T, E> to Option<T>
12617                            // Ok(val) -> Some(val), Err(_) -> None
12618                            if variant_name == "Ok" {
12619                                let inner = fields
12620                                    .as_ref()
12621                                    .and_then(|f| f.first().cloned())
12622                                    .unwrap_or(Value::Null);
12623                                return Ok(Value::Variant {
12624                                    enum_name: "Option".to_string(),
12625                                    variant_name: "Some".to_string(),
12626                                    fields: Some(Rc::new(vec![inner])),
12627                                });
12628                            }
12629                            return Ok(Value::Variant {
12630                                enum_name: "Option".to_string(),
12631                                variant_name: "None".to_string(),
12632                                fields: None,
12633                            });
12634                        }
12635                        "err" => {
12636                            // Convert Result<T, E> to Option<E>
12637                            // Ok(_) -> None, Err(e) -> Some(e)
12638                            if variant_name == "Err" {
12639                                let inner = fields
12640                                    .as_ref()
12641                                    .and_then(|f| f.first().cloned())
12642                                    .unwrap_or(Value::Null);
12643                                return Ok(Value::Variant {
12644                                    enum_name: "Option".to_string(),
12645                                    variant_name: "Some".to_string(),
12646                                    fields: Some(Rc::new(vec![inner])),
12647                                });
12648                            }
12649                            return Ok(Value::Variant {
12650                                enum_name: "Option".to_string(),
12651                                variant_name: "None".to_string(),
12652                                fields: None,
12653                            });
12654                        }
12655                        "unwrap" => {
12656                            if variant_name == "Ok" {
12657                                if let Some(f) = fields {
12658                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
12659                                }
12660                            }
12661                            return Err(RuntimeError::new("unwrap on Err"));
12662                        }
12663                        "unwrap_or" => {
12664                            if variant_name == "Ok" {
12665                                if let Some(f) = fields {
12666                                    return Ok(f.first().cloned().unwrap_or(Value::Null));
12667                                }
12668                            }
12669                            return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
12670                        }
12671                        "map" => {
12672                            // map(fn) - apply fn to Ok value, leave Err unchanged
12673                            if variant_name == "Ok" {
12674                                if let Some(Value::Function(f)) = arg_values.first() {
12675                                    let inner = fields
12676                                        .as_ref()
12677                                        .and_then(|f| f.first().cloned())
12678                                        .unwrap_or(Value::Null);
12679                                    let result = self.call_function(f, vec![inner])?;
12680                                    return Ok(Value::Variant {
12681                                        enum_name: "Result".to_string(),
12682                                        variant_name: "Ok".to_string(),
12683                                        fields: Some(Rc::new(vec![result])),
12684                                    });
12685                                }
12686                            }
12687                            // For Err variant, return unchanged
12688                            return Ok(recv.clone());
12689                        }
12690                        "map_err" => {
12691                            // map_err(fn) - apply fn to Err value, leave Ok unchanged
12692                            if variant_name == "Err" {
12693                                if let Some(Value::Function(f)) = arg_values.first() {
12694                                    let inner = fields
12695                                        .as_ref()
12696                                        .and_then(|f| f.first().cloned())
12697                                        .unwrap_or(Value::Null);
12698                                    let result = self.call_function(f, vec![inner])?;
12699                                    return Ok(Value::Variant {
12700                                        enum_name: "Result".to_string(),
12701                                        variant_name: "Err".to_string(),
12702                                        fields: Some(Rc::new(vec![result])),
12703                                    });
12704                                }
12705                            }
12706                            // For Ok variant, return unchanged
12707                            return Ok(recv.clone());
12708                        }
12709                        "and_then" => {
12710                            // and_then(fn) - chain Result-returning functions
12711                            if variant_name == "Ok" {
12712                                if let Some(Value::Function(f)) = arg_values.first() {
12713                                    let inner = fields
12714                                        .as_ref()
12715                                        .and_then(|f| f.first().cloned())
12716                                        .unwrap_or(Value::Null);
12717                                    return self.call_function(f, vec![inner]);
12718                                }
12719                            }
12720                            // For Err variant, return unchanged
12721                            return Ok(recv.clone());
12722                        }
12723                        _ => {}
12724                    }
12725                }
12726                // Pattern methods - for AST pattern access
12727                crate::sigil_debug!(
12728                    "DEBUG variant method call: enum_name={}, variant_name={}, method={}",
12729                    enum_name,
12730                    variant_name,
12731                    method.name
12732                );
12733
12734                // Type methods
12735                if enum_name == "Type" {
12736                    match method.name.as_str() {
12737                        "is_never" => {
12738                            // Type::Never is the never type, all others are not
12739                            return Ok(Value::Bool(variant_name == "Never"));
12740                        }
12741                        "to_string" => {
12742                            // Convert type to string representation
12743                            let type_str = match variant_name.as_str() {
12744                                "Bool" => "bool".to_string(),
12745                                "Int" => "i64".to_string(),
12746                                "Float" => "f64".to_string(),
12747                                "Str" => "str".to_string(),
12748                                "Char" => "char".to_string(),
12749                                "Unit" => "()".to_string(),
12750                                "Never" => "!".to_string(),
12751                                "Error" => "<error>".to_string(),
12752                                other => format!("Type::{}", other),
12753                            };
12754                            return Ok(Value::String(Rc::new(type_str)));
12755                        }
12756                        _ => {}
12757                    }
12758                }
12759
12760                if enum_name == "Pattern" {
12761                    match method.name.as_str() {
12762                        "evidentiality" => {
12763                            // Pattern::Ident { name, mutable, evidentiality } - return the evidentiality field
12764                            if variant_name == "Ident" {
12765                                if let Some(f) = fields {
12766                                    // Fields are stored as a struct or in order
12767                                    // Try to find evidentiality field
12768                                    for field_val in f.iter() {
12769                                        if let Value::Struct { fields: inner, .. } = field_val {
12770                                            if let Some(ev) = inner.borrow().get("evidentiality") {
12771                                                return Ok(ev.clone());
12772                                            }
12773                                        }
12774                                    }
12775                                    // If fields are stored in order: name, mutable, evidentiality (index 2)
12776                                    if f.len() > 2 {
12777                                        return Ok(f[2].clone());
12778                                    }
12779                                }
12780                            }
12781                            // No evidentiality for other pattern types
12782                            return Ok(Value::Null);
12783                        }
12784                        "name" => {
12785                            // Get the name from Pattern::Ident
12786                            if variant_name == "Ident" {
12787                                if let Some(f) = fields {
12788                                    for field_val in f.iter() {
12789                                        if let Value::Struct { fields: inner, .. } = field_val {
12790                                            if let Some(n) = inner.borrow().get("name") {
12791                                                return Ok(n.clone());
12792                                            }
12793                                        }
12794                                    }
12795                                    // First field is name
12796                                    if let Some(n) = f.first() {
12797                                        return Ok(n.clone());
12798                                    }
12799                                }
12800                            }
12801                            return Ok(Value::Null);
12802                        }
12803                        "mutable" => {
12804                            // Get mutable flag from Pattern::Ident
12805                            if variant_name == "Ident" {
12806                                if let Some(f) = fields {
12807                                    for field_val in f.iter() {
12808                                        if let Value::Struct { fields: inner, .. } = field_val {
12809                                            if let Some(m) = inner.borrow().get("mutable") {
12810                                                return Ok(m.clone());
12811                                            }
12812                                        }
12813                                    }
12814                                    // Second field is mutable
12815                                    if f.len() > 1 {
12816                                        return Ok(f[1].clone());
12817                                    }
12818                                }
12819                            }
12820                            return Ok(Value::Bool(false));
12821                        }
12822                        _ => {}
12823                    }
12824                }
12825                // Built-in clone method for all variants
12826                if method.name == "clone" {
12827                    return Ok(recv.clone());
12828                }
12829
12830                let qualified_name = format!("{}·{}", enum_name, method.name);
12831                let func = self
12832                    .globals
12833                    .borrow()
12834                    .get(&qualified_name)
12835                    .map(|v| v.clone());
12836                if let Some(func) = func {
12837                    if let Value::Function(f) = func {
12838                        let mut all_args = vec![recv.clone()];
12839                        all_args.extend(arg_values.clone());
12840                        return self.call_function(&f, all_args);
12841                    } else if let Value::BuiltIn(b) = func {
12842                        let mut all_args = vec![recv.clone()];
12843                        all_args.extend(arg_values.clone());
12844                        return (b.func)(self, all_args);
12845                    }
12846                }
12847                // Error on unknown methods - type checking
12848                Err(RuntimeError::new(format!(
12849                    "no method '{}' on enum '{}'",
12850                    method.name, enum_name
12851                )))
12852            }
12853            // Null-safe method handlers - methods called on null return sensible defaults
12854            (Value::Null, "len_utf8") => Ok(Value::Int(0)),
12855            (Value::Null, "is_ascii") => Ok(Value::Bool(false)),
12856            (Value::Null, "is_alphabetic") => Ok(Value::Bool(false)),
12857            (Value::Null, "is_alphanumeric") => Ok(Value::Bool(false)),
12858            (Value::Null, "is_numeric") | (Value::Null, "is_digit") => Ok(Value::Bool(false)),
12859            (Value::Null, "is_whitespace") => Ok(Value::Bool(false)),
12860            (Value::Null, "is_uppercase") => Ok(Value::Bool(false)),
12861            (Value::Null, "is_lowercase") => Ok(Value::Bool(false)),
12862            (Value::Null, "len") => Ok(Value::Int(0)),
12863            (Value::Null, "is_empty") => Ok(Value::Bool(true)),
12864            (Value::Null, "to_string") => Ok(Value::String(Rc::new("".to_string()))),
12865            (Value::Null, "clone") => Ok(Value::Null),
12866            (Value::Null, "is_some") => Ok(Value::Bool(false)),
12867            (Value::Null, "is_none") => Ok(Value::Bool(true)),
12868            (Value::Null, "unwrap_or") => {
12869                if arg_values.is_empty() {
12870                    Ok(Value::Null)
12871                } else {
12872                    Ok(arg_values[0].clone())
12873                }
12874            }
12875            // unwrap_or for non-null values returns the value itself
12876            (Value::Char(c), "unwrap_or") => Ok(Value::Char(*c)),
12877            (Value::Int(n), "unwrap_or") => Ok(Value::Int(*n)),
12878            (Value::Float(n), "unwrap_or") => Ok(Value::Float(*n)),
12879            (Value::String(s), "unwrap_or") => Ok(Value::String(s.clone())),
12880            (Value::Bool(b), "unwrap_or") => Ok(Value::Bool(*b)),
12881            // Int methods
12882            (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
12883                Ok(Value::String(Rc::new(n.to_string())))
12884            }
12885            (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
12886            (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
12887            (Value::Int(n), "duration_since") => {
12888                // Treat Int as nanoseconds since some epoch
12889                // Return a Duration struct
12890                let other_ns = match arg_values.first() {
12891                    Some(Value::Int(i)) => *i,
12892                    Some(Value::Struct { fields, .. }) => {
12893                        let borrowed = fields.borrow();
12894                        let secs = match borrowed.get("secs") {
12895                            Some(Value::Int(s)) => *s,
12896                            _ => 0,
12897                        };
12898                        let nanos = match borrowed.get("nanos") {
12899                            Some(Value::Int(n)) => *n,
12900                            _ => 0,
12901                        };
12902                        secs * 1_000_000_000 + nanos
12903                    }
12904                    _ => 0,
12905                };
12906                let diff_ns = n - other_ns;
12907                let mut fields = std::collections::HashMap::new();
12908                fields.insert("secs".to_string(), Value::Int(diff_ns / 1_000_000_000));
12909                fields.insert("nanos".to_string(), Value::Int(diff_ns % 1_000_000_000));
12910                Ok(Value::Variant {
12911                    enum_name: "Result".to_string(),
12912                    variant_name: "Ok".to_string(),
12913                    fields: Some(Rc::new(vec![Value::Struct {
12914                        name: "Duration".to_string(),
12915                        fields: Rc::new(RefCell::new(fields)),
12916                    }])),
12917                })
12918            }
12919            // Float methods
12920            (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
12921                Ok(Value::String(Rc::new(n.to_string())))
12922            }
12923            (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
12924            // Float math methods (numeric primitive instance methods)
12925            (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
12926            (Value::Float(n), "exp") => Ok(Value::Float(n.exp())),
12927            (Value::Float(n), "exp2") => Ok(Value::Float(n.exp2())),
12928            (Value::Float(n), "ln") => Ok(Value::Float(n.ln())),
12929            (Value::Float(n), "log2") => Ok(Value::Float(n.log2())),
12930            (Value::Float(n), "log10") => Ok(Value::Float(n.log10())),
12931            (Value::Float(n), "sqrt") => Ok(Value::Float(n.sqrt())),
12932            (Value::Float(n), "cbrt") => Ok(Value::Float(n.cbrt())),
12933            (Value::Float(n), "sin") => Ok(Value::Float(n.sin())),
12934            (Value::Float(n), "cos") => Ok(Value::Float(n.cos())),
12935            (Value::Float(n), "tan") => Ok(Value::Float(n.tan())),
12936            (Value::Float(n), "asin") => Ok(Value::Float(n.asin())),
12937            (Value::Float(n), "acos") => Ok(Value::Float(n.acos())),
12938            (Value::Float(n), "atan") => Ok(Value::Float(n.atan())),
12939            (Value::Float(n), "sinh") => Ok(Value::Float(n.sinh())),
12940            (Value::Float(n), "cosh") => Ok(Value::Float(n.cosh())),
12941            (Value::Float(n), "tanh") => Ok(Value::Float(n.tanh())),
12942            (Value::Float(n), "asinh") => Ok(Value::Float(n.asinh())),
12943            (Value::Float(n), "acosh") => Ok(Value::Float(n.acosh())),
12944            (Value::Float(n), "atanh") => Ok(Value::Float(n.atanh())),
12945            (Value::Float(n), "floor") => Ok(Value::Float(n.floor())),
12946            (Value::Float(n), "ceil") => Ok(Value::Float(n.ceil())),
12947            (Value::Float(n), "round") => Ok(Value::Float(n.round())),
12948            (Value::Float(n), "trunc") => Ok(Value::Float(n.trunc())),
12949            (Value::Float(n), "fract") => Ok(Value::Float(n.fract())),
12950            (Value::Float(n), "signum") => Ok(Value::Float(n.signum())),
12951            (Value::Float(n), "is_nan") => Ok(Value::Bool(n.is_nan())),
12952            (Value::Float(n), "is_infinite") => Ok(Value::Bool(n.is_infinite())),
12953            (Value::Float(n), "is_finite") => Ok(Value::Bool(n.is_finite())),
12954            (Value::Float(n), "is_normal") => Ok(Value::Bool(n.is_normal())),
12955            (Value::Float(n), "to_bits") => Ok(Value::Int(n.to_bits() as i64)),
12956            (Value::Float(n), "powf") => {
12957                if arg_values.is_empty() {
12958                    return Err(RuntimeError::new("powf requires 1 argument"));
12959                }
12960                let exp = match &arg_values[0] {
12961                    Value::Float(f) => *f,
12962                    Value::Int(i) => *i as f64,
12963                    _ => return Err(RuntimeError::new("powf argument must be numeric")),
12964                };
12965                Ok(Value::Float(n.powf(exp)))
12966            }
12967            (Value::Float(n), "powi") => {
12968                if arg_values.is_empty() {
12969                    return Err(RuntimeError::new("powi requires 1 argument"));
12970                }
12971                let exp = match &arg_values[0] {
12972                    Value::Int(i) => *i as i32,
12973                    Value::Float(f) => *f as i32,
12974                    _ => return Err(RuntimeError::new("powi argument must be integer")),
12975                };
12976                Ok(Value::Float(n.powi(exp)))
12977            }
12978            (Value::Float(n), "atan2") => {
12979                if arg_values.is_empty() {
12980                    return Err(RuntimeError::new("atan2 requires 1 argument"));
12981                }
12982                let other = match &arg_values[0] {
12983                    Value::Float(f) => *f,
12984                    Value::Int(i) => *i as f64,
12985                    _ => return Err(RuntimeError::new("atan2 argument must be numeric")),
12986                };
12987                Ok(Value::Float(n.atan2(other)))
12988            }
12989            (Value::Float(n), "copysign") => {
12990                if arg_values.is_empty() {
12991                    return Err(RuntimeError::new("copysign requires 1 argument"));
12992                }
12993                let sign = match &arg_values[0] {
12994                    Value::Float(f) => *f,
12995                    Value::Int(i) => *i as f64,
12996                    _ => return Err(RuntimeError::new("copysign argument must be numeric")),
12997                };
12998                Ok(Value::Float(n.copysign(sign)))
12999            }
13000            (Value::Float(n), "mul_add") => {
13001                if arg_values.len() < 2 {
13002                    return Err(RuntimeError::new("mul_add requires 2 arguments"));
13003                }
13004                let a = match &arg_values[0] {
13005                    Value::Float(f) => *f,
13006                    Value::Int(i) => *i as f64,
13007                    _ => return Err(RuntimeError::new("mul_add arguments must be numeric")),
13008                };
13009                let b = match &arg_values[1] {
13010                    Value::Float(f) => *f,
13011                    Value::Int(i) => *i as f64,
13012                    _ => return Err(RuntimeError::new("mul_add arguments must be numeric")),
13013                };
13014                Ok(Value::Float(n.mul_add(a, b)))
13015            }
13016            (Value::Float(n), "max") => {
13017                if arg_values.is_empty() {
13018                    return Err(RuntimeError::new("max requires 1 argument"));
13019                }
13020                let other = match &arg_values[0] {
13021                    Value::Float(f) => *f,
13022                    Value::Int(i) => *i as f64,
13023                    _ => return Err(RuntimeError::new("max argument must be numeric")),
13024                };
13025                Ok(Value::Float(n.max(other)))
13026            }
13027            (Value::Float(n), "min") => {
13028                if arg_values.is_empty() {
13029                    return Err(RuntimeError::new("min requires 1 argument"));
13030                }
13031                let other = match &arg_values[0] {
13032                    Value::Float(f) => *f,
13033                    Value::Int(i) => *i as f64,
13034                    _ => return Err(RuntimeError::new("min argument must be numeric")),
13035                };
13036                Ok(Value::Float(n.min(other)))
13037            }
13038            (Value::Float(n), "clamp") => {
13039                if arg_values.len() < 2 {
13040                    return Err(RuntimeError::new("clamp requires 2 arguments"));
13041                }
13042                let min_val = match &arg_values[0] {
13043                    Value::Float(f) => *f,
13044                    Value::Int(i) => *i as f64,
13045                    _ => return Err(RuntimeError::new("clamp arguments must be numeric")),
13046                };
13047                let max_val = match &arg_values[1] {
13048                    Value::Float(f) => *f,
13049                    Value::Int(i) => *i as f64,
13050                    _ => return Err(RuntimeError::new("clamp arguments must be numeric")),
13051                };
13052                Ok(Value::Float(n.clamp(min_val, max_val)))
13053            }
13054            (Value::Float(n), "log") => {
13055                if arg_values.is_empty() {
13056                    return Err(RuntimeError::new("log requires 1 argument (base)"));
13057                }
13058                let base = match &arg_values[0] {
13059                    Value::Float(f) => *f,
13060                    Value::Int(i) => *i as f64,
13061                    _ => return Err(RuntimeError::new("log argument must be numeric")),
13062                };
13063                Ok(Value::Float(n.log(base)))
13064            }
13065            // Integer math methods
13066            (Value::Int(n), "pow") => {
13067                if arg_values.is_empty() {
13068                    return Err(RuntimeError::new("pow requires 1 argument"));
13069                }
13070                let exp = match &arg_values[0] {
13071                    Value::Int(i) => *i as u32,
13072                    _ => return Err(RuntimeError::new("pow argument must be integer")),
13073                };
13074                Ok(Value::Int(n.pow(exp)))
13075            }
13076            (Value::Int(n), "max") => {
13077                if arg_values.is_empty() {
13078                    return Err(RuntimeError::new("max requires 1 argument"));
13079                }
13080                let other = match &arg_values[0] {
13081                    Value::Int(i) => *i,
13082                    _ => return Err(RuntimeError::new("max argument must be integer")),
13083                };
13084                Ok(Value::Int(std::cmp::max(*n, other)))
13085            }
13086            (Value::Int(n), "min") => {
13087                if arg_values.is_empty() {
13088                    return Err(RuntimeError::new("min requires 1 argument"));
13089                }
13090                let other = match &arg_values[0] {
13091                    Value::Int(i) => *i,
13092                    _ => return Err(RuntimeError::new("min argument must be integer")),
13093                };
13094                Ok(Value::Int(std::cmp::min(*n, other)))
13095            }
13096            (Value::Int(n), "clamp") => {
13097                if arg_values.len() < 2 {
13098                    return Err(RuntimeError::new("clamp requires 2 arguments"));
13099                }
13100                let min_val = match &arg_values[0] {
13101                    Value::Int(i) => *i,
13102                    _ => return Err(RuntimeError::new("clamp arguments must be integer")),
13103                };
13104                let max_val = match &arg_values[1] {
13105                    Value::Int(i) => *i,
13106                    _ => return Err(RuntimeError::new("clamp arguments must be integer")),
13107                };
13108                Ok(Value::Int((*n).max(min_val).min(max_val)))
13109            }
13110            // Bool methods
13111            (Value::Bool(b), "to_string") | (Value::Bool(b), "string") => {
13112                Ok(Value::String(Rc::new(b.to_string())))
13113            }
13114            // Char methods
13115            (Value::Char(c), "to_string") | (Value::Char(c), "string") => {
13116                Ok(Value::String(Rc::new(c.to_string())))
13117            }
13118            // Int methods (including pointer methods)
13119            (Value::Int(n), "is_null") => {
13120                // For raw pointers cast to Int, is_null() checks if value is 0
13121                Ok(Value::Bool(*n == 0))
13122            }
13123            (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
13124                Ok(Value::String(Rc::new(n.to_string())))
13125            }
13126            (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
13127            _ => {
13128                // Debug: what type is failing method lookup
13129                let recv_type = match &recv {
13130                    Value::String(s) => format!("String(len={})", s.len()),
13131                    Value::Array(arr) => format!("Array(len={})", arr.borrow().len()),
13132                    Value::Struct { name, .. } => format!("Struct({})", name),
13133                    Value::Variant {
13134                        enum_name,
13135                        variant_name,
13136                        ..
13137                    } => format!("Variant({}::{})", enum_name, variant_name),
13138                    Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
13139                    Value::Null => "Null".to_string(),
13140                    other => format!("{:?}", std::mem::discriminant(other)),
13141                };
13142                // Error on unknown methods - type checking
13143                Err(RuntimeError::new(format!(
13144                    "no method '{}' on type '{}'",
13145                    method.name, recv_type
13146                )))
13147            }
13148        }
13149    }
13150
13151    /// Evaluate polysynthetic incorporation: path·file·read·string
13152    /// The first segment provides the initial value, subsequent segments are method-like transformations
13153    fn eval_incorporation(
13154        &mut self,
13155        segments: &[IncorporationSegment],
13156    ) -> Result<Value, RuntimeError> {
13157        if segments.is_empty() {
13158            return Err(RuntimeError::new("empty incorporation chain"));
13159        }
13160
13161        // First segment: get initial value (variable lookup or function call)
13162        let first = &segments[0];
13163        let mut value = if let Some(args) = &first.args {
13164            // First segment is a function call: func(args)·next·...
13165            let arg_values: Vec<Value> = args
13166                .iter()
13167                .map(|a| self.evaluate(a))
13168                .collect::<Result<_, _>>()?;
13169            self.call_function_by_name(&first.name.name, arg_values)?
13170        } else if first.name.name == "Self" || first.name.name == "This" {
13171            // Self/This refers to the current impl type - handle as static method call
13172            if let Some(self_type) = self.current_self_type.clone() {
13173                // If there's a second segment with args, it's a static method call: This·method(args)
13174                if segments.len() > 1 {
13175                    let method_segment = &segments[1];
13176                    let arg_values: Vec<Value> = method_segment
13177                        .args
13178                        .as_ref()
13179                        .map(|args| {
13180                            args.iter()
13181                                .map(|a| self.evaluate(a))
13182                                .collect::<Result<Vec<_>, _>>()
13183                        })
13184                        .transpose()?
13185                        .unwrap_or_default();
13186
13187                    // Call as TypeName::method(args)
13188                    let full_name = format!("{}::{}", self_type, method_segment.name.name);
13189                    let result = self.call_function_by_name(&full_name, arg_values)?;
13190
13191                    // Continue processing remaining segments (skip first two)
13192                    let mut value = result;
13193                    for segment in segments.iter().skip(2) {
13194                        let seg_args: Vec<Value> = segment
13195                            .args
13196                            .as_ref()
13197                            .map(|args| {
13198                                args.iter()
13199                                    .map(|a| self.evaluate(a))
13200                                    .collect::<Result<Vec<_>, _>>()
13201                            })
13202                            .transpose()?
13203                            .unwrap_or_default();
13204                        value =
13205                            self.call_incorporation_method(&value, &segment.name.name, seg_args)?;
13206                    }
13207                    return Ok(value);
13208                } else {
13209                    // Just "Self" or "This" alone - return the type as a value for type-level operations
13210                    return Err(RuntimeError::new(format!(
13211                        "Self/This requires a method: use {}·method() instead of just {}",
13212                        self_type, first.name.name
13213                    )));
13214                }
13215            } else {
13216                return Err(RuntimeError::new(format!(
13217                    "{} can only be used inside an impl block",
13218                    first.name.name
13219                )));
13220            }
13221        } else {
13222            // First segment is a variable: var·next·...
13223            self.environment
13224                .borrow()
13225                .get(&first.name.name)
13226                .ok_or_else(|| RuntimeError::new(format!("undefined: {}", first.name.name)))?
13227        };
13228
13229        // Process remaining segments as method-like calls
13230        for segment in segments.iter().skip(1) {
13231            let arg_values: Vec<Value> = segment
13232                .args
13233                .as_ref()
13234                .map(|args| {
13235                    args.iter()
13236                        .map(|a| self.evaluate(a))
13237                        .collect::<Result<Vec<_>, _>>()
13238                })
13239                .transpose()?
13240                .unwrap_or_default();
13241
13242            // Try to call as a method on the value
13243            value = self.call_incorporation_method(&value, &segment.name.name, arg_values)?;
13244        }
13245
13246        Ok(value)
13247    }
13248
13249    /// Call a method in an incorporation chain
13250    /// This looks up the segment name as a method or stdlib function
13251    fn call_incorporation_method(
13252        &mut self,
13253        receiver: &Value,
13254        method_name: &str,
13255        args: Vec<Value>,
13256    ) -> Result<Value, RuntimeError> {
13257        // First try as a method on the receiver value
13258        match (receiver, method_name) {
13259            // String methods
13260            (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
13261            (Value::String(s), "upper")
13262            | (Value::String(s), "uppercase")
13263            | (Value::String(s), "to_uppercase") => Ok(Value::String(Rc::new(s.to_uppercase()))),
13264            (Value::String(s), "lower")
13265            | (Value::String(s), "lowercase")
13266            | (Value::String(s), "to_lowercase") => Ok(Value::String(Rc::new(s.to_lowercase()))),
13267            (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
13268            (Value::String(s), "chars") => {
13269                let chars: Vec<Value> = s
13270                    .chars()
13271                    .map(|c| Value::String(Rc::new(c.to_string())))
13272                    .collect();
13273                Ok(Value::Array(Rc::new(RefCell::new(chars))))
13274            }
13275            (Value::String(s), "lines") => {
13276                let lines: Vec<Value> = s
13277                    .lines()
13278                    .map(|l| Value::String(Rc::new(l.to_string())))
13279                    .collect();
13280                Ok(Value::Array(Rc::new(RefCell::new(lines))))
13281            }
13282            (Value::String(s), "bytes") => {
13283                let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
13284                Ok(Value::Array(Rc::new(RefCell::new(bytes))))
13285            }
13286            (Value::String(s), "parse_int") | (Value::String(s), "to_int") => s
13287                .parse::<i64>()
13288                .map(Value::Int)
13289                .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as int", s))),
13290            (Value::String(s), "parse_float") | (Value::String(s), "to_float") => s
13291                .parse::<f64>()
13292                .map(Value::Float)
13293                .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as float", s))),
13294            (Value::String(s), "as_str") => {
13295                if s.len() <= 10 {
13296                    crate::sigil_debug!("DEBUG as_str: '{}'", s);
13297                }
13298                Ok(Value::String(s.clone()))
13299            }
13300            (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
13301            (Value::String(s), "starts_with") => {
13302                if args.len() != 1 {
13303                    return Err(RuntimeError::new("starts_with expects 1 argument"));
13304                }
13305                match &args[0] {
13306                    Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
13307                    _ => Err(RuntimeError::new("starts_with expects string")),
13308                }
13309            }
13310            (Value::String(s), "ends_with") => {
13311                if args.len() != 1 {
13312                    return Err(RuntimeError::new("ends_with expects 1 argument"));
13313                }
13314                match &args[0] {
13315                    Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
13316                    _ => Err(RuntimeError::new("ends_with expects string")),
13317                }
13318            }
13319            (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
13320            (Value::String(s), "capacity") => Ok(Value::Int(s.capacity() as i64)),
13321            (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
13322            (Value::String(s), "first") => s
13323                .chars()
13324                .next()
13325                .map(Value::Char)
13326                .ok_or_else(|| RuntimeError::new("empty string")),
13327            (Value::String(s), "last") => s
13328                .chars()
13329                .last()
13330                .map(Value::Char)
13331                .ok_or_else(|| RuntimeError::new("empty string")),
13332
13333            // Array methods
13334            (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
13335            (Value::Array(arr), "first") | (Value::Array(arr), "next") => {
13336                Ok(arr.borrow().first().cloned().unwrap_or(Value::Null))
13337            }
13338            (Value::Array(arr), "last") => arr
13339                .borrow()
13340                .last()
13341                .cloned()
13342                .ok_or_else(|| RuntimeError::new("empty array")),
13343            (Value::Array(arr), "reverse") | (Value::Array(arr), "rev") => {
13344                arr.borrow_mut().reverse();
13345                Ok(Value::Array(arr.clone()))
13346            }
13347            (Value::Array(arr), "join") => {
13348                let sep = args
13349                    .first()
13350                    .map(|v| match v {
13351                        Value::String(s) => s.to_string(),
13352                        _ => "".to_string(),
13353                    })
13354                    .unwrap_or_default();
13355                let joined = arr
13356                    .borrow()
13357                    .iter()
13358                    .map(|v| format!("{}", v))
13359                    .collect::<Vec<_>>()
13360                    .join(&sep);
13361                Ok(Value::String(Rc::new(joined)))
13362            }
13363            (Value::Array(arr), "sum") => {
13364                let mut sum = 0i64;
13365                for v in arr.borrow().iter() {
13366                    match v {
13367                        Value::Int(i) => sum += i,
13368                        Value::Float(f) => return Ok(Value::Float(sum as f64 + f)),
13369                        _ => {}
13370                    }
13371                }
13372                Ok(Value::Int(sum))
13373            }
13374            (Value::Array(arr), "skip") => {
13375                let n = match args.first() {
13376                    Some(Value::Int(i)) => *i as usize,
13377                    _ => 1,
13378                };
13379                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
13380                Ok(Value::Array(Rc::new(RefCell::new(v))))
13381            }
13382            (Value::Array(arr), "take") => {
13383                let n = match args.first() {
13384                    Some(Value::Int(i)) => *i as usize,
13385                    _ => 1,
13386                };
13387                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
13388                Ok(Value::Array(Rc::new(RefCell::new(v))))
13389            }
13390            (Value::Array(arr), "step_by") => {
13391                let n = match args.first() {
13392                    Some(Value::Int(i)) if *i > 0 => *i as usize,
13393                    _ => 1,
13394                };
13395                let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
13396                Ok(Value::Array(Rc::new(RefCell::new(v))))
13397            }
13398
13399            // Number methods
13400            (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
13401            (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
13402            (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
13403                Ok(Value::String(Rc::new(n.to_string())))
13404            }
13405            (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
13406                Ok(Value::String(Rc::new(n.to_string())))
13407            }
13408            (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
13409            (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
13410
13411            // Map/Struct field access
13412            (Value::Map(map), field) => map
13413                .borrow()
13414                .get(field)
13415                .cloned()
13416                .ok_or_else(|| RuntimeError::new(format!("no field '{}' in map", field))),
13417            (Value::Struct { fields, .. }, field) => fields
13418                .borrow()
13419                .get(field)
13420                .cloned()
13421                .ok_or_else(|| RuntimeError::new(format!("no field '{}' in struct", field))),
13422
13423            // Try stdlib function with receiver as first arg
13424            _ => {
13425                let mut all_args = vec![receiver.clone()];
13426                all_args.extend(args);
13427                self.call_function_by_name(method_name, all_args)
13428            }
13429        }
13430    }
13431
13432    /// Call a function by name from the environment
13433    pub fn call_function_by_name(
13434        &mut self,
13435        name: &str,
13436        args: Vec<Value>,
13437    ) -> Result<Value, RuntimeError> {
13438        // Get the function value from environment (clone to avoid borrow issues)
13439        let func_value = self.environment.borrow().get(name);
13440
13441        match func_value {
13442            Some(Value::Function(f)) => self.call_function(&f, args),
13443            Some(Value::BuiltIn(b)) => self.call_builtin(&b, args),
13444            Some(_) => Err(RuntimeError::new(format!("{} is not a function", name))),
13445            None => {
13446                // Check for variant constructor
13447                if let Some((enum_name, variant_name, arity)) =
13448                    self.variant_constructors.get(name).cloned()
13449                {
13450                    if arity == 0 && args.is_empty() {
13451                        return Ok(Value::Variant {
13452                            enum_name,
13453                            variant_name,
13454                            fields: None,
13455                        });
13456                    } else if args.len() == arity {
13457                        return Ok(Value::Variant {
13458                            enum_name,
13459                            variant_name,
13460                            fields: Some(Rc::new(args)),
13461                        });
13462                    } else {
13463                        return Err(RuntimeError::new(format!(
13464                            "{} expects {} arguments, got {}",
13465                            name,
13466                            arity,
13467                            args.len()
13468                        )));
13469                    }
13470                }
13471                Err(RuntimeError::new(format!("undefined function: {}", name)))
13472            }
13473        }
13474    }
13475
13476    fn eval_pipe(&mut self, expr: &Expr, operations: &[PipeOp]) -> Result<Value, RuntimeError> {
13477        let mut value = self.evaluate(expr)?;
13478
13479        for op in operations {
13480            value = self.apply_pipe_op(value, op)?;
13481        }
13482
13483        Ok(value)
13484    }
13485
13486    fn apply_pipe_op(&mut self, value: Value, op: &PipeOp) -> Result<Value, RuntimeError> {
13487        // Unwrap evidential/affective wrappers for pipe operations
13488        let value = Self::unwrap_all(&value);
13489
13490        match op {
13491            PipeOp::Transform(body) => {
13492                // τ{f} - map over collection or apply to single value
13493                // Extract closure parameter pattern and body
13494                let (param_pattern, inner_body) = match body.as_ref() {
13495                    Expr::Closure { params, body, .. } => {
13496                        let pattern = params.first().map(|p| p.pattern.clone());
13497                        (pattern, body.as_ref())
13498                    }
13499                    _ => (None, body.as_ref()),
13500                };
13501
13502                match value {
13503                    Value::Array(arr) => {
13504                        let results: Vec<Value> = arr
13505                            .borrow()
13506                            .iter()
13507                            .map(|item| {
13508                                // Bind the item to the pattern (supports tuple destructuring)
13509                                if let Some(ref pattern) = param_pattern {
13510                                    self.bind_pattern(pattern, item.clone())?;
13511                                } else {
13512                                    self.environment
13513                                        .borrow_mut()
13514                                        .define("_".to_string(), item.clone());
13515                                }
13516                                self.evaluate(inner_body)
13517                            })
13518                            .collect::<Result<_, _>>()?;
13519                        Ok(Value::Array(Rc::new(RefCell::new(results))))
13520                    }
13521                    single => {
13522                        if let Some(ref pattern) = param_pattern {
13523                            self.bind_pattern(pattern, single)?;
13524                        } else {
13525                            self.environment
13526                                .borrow_mut()
13527                                .define("_".to_string(), single);
13528                        }
13529                        self.evaluate(inner_body)
13530                    }
13531                }
13532            }
13533            PipeOp::Filter(predicate) => {
13534                // φ{p} - filter collection
13535                // Extract closure parameter pattern and body
13536                let (param_pattern, inner_pred) = match predicate.as_ref() {
13537                    Expr::Closure { params, body, .. } => {
13538                        let pattern = params.first().map(|p| p.pattern.clone());
13539                        (pattern, body.as_ref())
13540                    }
13541                    _ => (None, predicate.as_ref()),
13542                };
13543
13544                match value {
13545                    Value::Array(arr) => {
13546                        let results: Vec<Value> = arr
13547                            .borrow()
13548                            .iter()
13549                            .filter_map(|item| {
13550                                // Bind the item to the pattern (supports tuple destructuring)
13551                                if let Some(ref pattern) = param_pattern {
13552                                    if let Err(e) = self.bind_pattern(pattern, item.clone()) {
13553                                        return Some(Err(e));
13554                                    }
13555                                } else {
13556                                    self.environment
13557                                        .borrow_mut()
13558                                        .define("_".to_string(), item.clone());
13559                                }
13560                                match self.evaluate(inner_pred) {
13561                                    Ok(v) if self.is_truthy(&v) => Some(Ok(item.clone())),
13562                                    Ok(_) => None,
13563                                    Err(e) => Some(Err(e)),
13564                                }
13565                            })
13566                            .collect::<Result<_, _>>()?;
13567                        Ok(Value::Array(Rc::new(RefCell::new(results))))
13568                    }
13569                    _ => Err(RuntimeError::new("Filter requires array")),
13570                }
13571            }
13572            PipeOp::Sort(field) => {
13573                // σ/Σ - sort collection or sum for tensors
13574                match value {
13575                    Value::Array(arr) => {
13576                        let mut v = arr.borrow().clone();
13577                        v.sort_by(|a, b| self.compare_values(a, b, field));
13578                        Ok(Value::Array(Rc::new(RefCell::new(v))))
13579                    }
13580                    // For Tensors, Σ acts as sum operation
13581                    Value::Struct { ref name, .. } if name == "Tensor" => self.sum_values(value),
13582                    _ => Err(RuntimeError::new("Sort requires array")),
13583                }
13584            }
13585            PipeOp::SortBy(body) => {
13586                // σ{a, b => b - a} - sort with custom comparator closure
13587                match value {
13588                    Value::Array(arr) => {
13589                        let mut v = arr.borrow().clone();
13590                        let (params, inner_body) = match body.as_ref() {
13591                            Expr::Closure { params, body, .. } => (params, body.as_ref()),
13592                            _ => return Err(RuntimeError::new("SortBy requires closure")),
13593                        };
13594                        // Bubble sort: can't use Rust's sort_by with &mut self borrow
13595                        let n = v.len();
13596                        for i in 0..n {
13597                            for j in 0..n.saturating_sub(1).saturating_sub(i) {
13598                                if params.len() >= 2 {
13599                                    self.bind_pattern(&params[0].pattern, v[j].clone())?;
13600                                    self.bind_pattern(&params[1].pattern, v[j + 1].clone())?;
13601                                }
13602                                let cmp = self.evaluate(inner_body)?;
13603                                if matches!(&cmp, Value::Int(n) if *n > 0) {
13604                                    v.swap(j, j + 1);
13605                                }
13606                            }
13607                        }
13608                        Ok(Value::Array(Rc::new(RefCell::new(v))))
13609                    }
13610                    _ => Err(RuntimeError::new("SortBy requires array")),
13611                }
13612            }
13613            PipeOp::Reduce(body) => {
13614                // ρ{f} - reduce collection
13615                match value {
13616                    Value::Array(arr) => {
13617                        let arr = arr.borrow();
13618                        if arr.is_empty() {
13619                            return Err(RuntimeError::new("Cannot reduce empty array"));
13620                        }
13621                        let mut acc = arr[0].clone();
13622                        for item in arr.iter().skip(1) {
13623                            self.environment.borrow_mut().define("acc".to_string(), acc);
13624                            self.environment
13625                                .borrow_mut()
13626                                .define("_".to_string(), item.clone());
13627                            acc = self.evaluate(body)?;
13628                        }
13629                        Ok(acc)
13630                    }
13631                    _ => Err(RuntimeError::new("Reduce requires array")),
13632                }
13633            }
13634            PipeOp::ReduceWithInit(init_expr, closure) => {
13635                // ρ{0, acc, x => acc + x} - reduce with initial value
13636                match value {
13637                    Value::Array(arr) => {
13638                        let items: Vec<Value> = arr.borrow().clone();
13639                        let mut acc = self.evaluate(init_expr)?;
13640                        let (params, inner_body) = match closure.as_ref() {
13641                            Expr::Closure { params, body, .. } => (params, body.as_ref()),
13642                            _ => return Err(RuntimeError::new("ReduceWithInit requires closure")),
13643                        };
13644                        for item in items.iter() {
13645                            if params.len() >= 2 {
13646                                self.bind_pattern(&params[0].pattern, acc)?;
13647                                self.bind_pattern(&params[1].pattern, item.clone())?;
13648                            }
13649                            acc = self.evaluate(inner_body)?;
13650                        }
13651                        Ok(acc)
13652                    }
13653                    _ => Err(RuntimeError::new("ReduceWithInit requires array")),
13654                }
13655            }
13656            PipeOp::ReduceSum => {
13657                // ρ+ or ρ_sum - sum all elements
13658                self.sum_values(value)
13659            }
13660            PipeOp::ReduceProd => {
13661                // ρ* or ρ_prod - multiply all elements
13662                self.product_values(value)
13663            }
13664            PipeOp::ReduceMin => {
13665                // ρ_min - find minimum element
13666                self.min_values(value)
13667            }
13668            PipeOp::ReduceMax => {
13669                // ρ_max - find maximum element
13670                self.max_values(value)
13671            }
13672            PipeOp::ReduceConcat => {
13673                // ρ++ or ρ_cat - concatenate strings/arrays
13674                self.concat_values(value)
13675            }
13676            PipeOp::ReduceAll => {
13677                // ρ& or ρ_all - logical AND (all true)
13678                self.all_values(value)
13679            }
13680            PipeOp::ReduceAny => {
13681                // ρ| or ρ_any - logical OR (any true)
13682                self.any_values(value)
13683            }
13684            PipeOp::Match(arms) => {
13685                // |match{ Pattern => expr, ... } - pattern matching in pipe
13686                for arm in arms {
13687                    if self.pattern_matches(&arm.pattern, &value)? {
13688                        // Create new scope for pattern bindings
13689                        let prev_env = self.environment.clone();
13690                        self.environment =
13691                            Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
13692
13693                        // Bind pattern variables
13694                        self.bind_pattern(&arm.pattern, value.clone())?;
13695
13696                        // Also bind _ to the piped value for convenient access
13697                        self.environment
13698                            .borrow_mut()
13699                            .define("_".to_string(), value.clone());
13700
13701                        // Check guard if present
13702                        let guard_passes = if let Some(guard) = &arm.guard {
13703                            matches!(self.evaluate(guard)?, Value::Bool(true))
13704                        } else {
13705                            true
13706                        };
13707
13708                        if guard_passes {
13709                            let result = self.evaluate(&arm.body)?;
13710                            self.environment = prev_env;
13711                            return Ok(result);
13712                        }
13713
13714                        // Guard failed, restore environment and try next arm
13715                        self.environment = prev_env;
13716                    }
13717                }
13718                Err(RuntimeError::new("No pattern matched in pipe match"))
13719            }
13720            PipeOp::TryMap(mapper) => {
13721                // |? or |?{mapper} - unwrap Result/Option or transform error
13722                match &value {
13723                    // Handle Result-like values (struct with ok/err fields)
13724                    Value::Struct { name, fields } if name == "Ok" || name.ends_with("::Ok") => {
13725                        // Extract the inner value from Ok
13726                        let fields = fields.borrow();
13727                        fields
13728                            .get("0")
13729                            .or_else(|| fields.get("value"))
13730                            .cloned()
13731                            .ok_or_else(|| RuntimeError::new("Ok variant has no value"))
13732                    }
13733                    Value::Struct { name, fields } if name == "Err" || name.ends_with("::Err") => {
13734                        // Transform error if mapper provided, otherwise propagate
13735                        let fields = fields.borrow();
13736                        let err_val = fields
13737                            .get("0")
13738                            .or_else(|| fields.get("error"))
13739                            .cloned()
13740                            .unwrap_or(Value::Null);
13741                        if let Some(mapper_expr) = mapper {
13742                            // Apply mapper to error
13743                            let prev_env = self.environment.clone();
13744                            self.environment =
13745                                Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
13746                            self.environment
13747                                .borrow_mut()
13748                                .define("_".to_string(), err_val);
13749                            let mapped = self.evaluate(mapper_expr)?;
13750                            self.environment = prev_env;
13751                            Err(RuntimeError::new(format!("Error: {:?}", mapped)))
13752                        } else {
13753                            Err(RuntimeError::new(format!("Error: {:?}", err_val)))
13754                        }
13755                    }
13756                    // Handle Option-like values
13757                    Value::Struct { name, fields }
13758                        if name == "Some" || name.ends_with("::Some") =>
13759                    {
13760                        let fields = fields.borrow();
13761                        fields
13762                            .get("0")
13763                            .or_else(|| fields.get("value"))
13764                            .cloned()
13765                            .ok_or_else(|| RuntimeError::new("Some variant has no value"))
13766                    }
13767                    Value::Struct { name, .. } if name == "None" || name.ends_with("::None") => {
13768                        Err(RuntimeError::new("Unwrapped None value"))
13769                    }
13770                    Value::Null => Err(RuntimeError::new("Unwrapped null value")),
13771                    // Pass through non-Result/Option values unchanged
13772                    _ => Ok(value),
13773                }
13774            }
13775            PipeOp::Call(callee) => {
13776                // Special handling for macro invocations in pipe context: |macro_name!{}
13777                // Pass the pipe value to the macro as $__pipe
13778                if let Expr::Macro { path, tokens } = callee.as_ref() {
13779                    let macro_name = path
13780                        .segments
13781                        .last()
13782                        .map(|s| s.ident.name.as_str())
13783                        .unwrap_or("");
13784
13785                    // Check for user-defined macro
13786                    // Clone the macro definition out of the borrow to avoid lifetime issues
13787                    let macro_def = self.user_macros.borrow().get(macro_name).cloned();
13788                    if let Some((params, body, field_map)) = macro_def {
13789                        return self.expand_user_macro(&params, &body, tokens, Some(value), &field_map);
13790                    }
13791                    // Built-in macros don't use $__pipe, so fall through
13792                }
13793
13794                // Special handling for |func(args) - prepend piped value to arguments
13795                // e.g., q|Rx(3.14159) should call Rx(q, 3.14159)
13796                if let Expr::Call { func: inner_func, args } = callee.as_ref() {
13797                    // Evaluate the function
13798                    let func_val = self.evaluate(inner_func)?;
13799
13800                    // Evaluate the explicit arguments
13801                    let mut all_args = vec![value];
13802                    for arg in args {
13803                        all_args.push(self.evaluate(arg)?);
13804                    }
13805
13806                    // Call with piped value prepended to args
13807                    return match func_val {
13808                        Value::Function(f) => self.call_function(&f, all_args),
13809                        Value::BuiltIn(b) => self.call_builtin(&b, all_args),
13810                        _ => Err(RuntimeError::new(format!(
13811                            "Cannot call non-function value in pipe: {:?}",
13812                            func_val
13813                        ))),
13814                    };
13815                }
13816
13817                // |expr - call an arbitrary expression (like self.layer) with piped value
13818                let callee_val = self.evaluate(callee)?;
13819                match callee_val {
13820                    Value::Function(f) => {
13821                        // Call the function with the piped value as argument
13822                        self.call_function(&f, vec![value])
13823                    }
13824                    Value::BuiltIn(b) => {
13825                        // Call built-in with the piped value
13826                        self.call_builtin(&b, vec![value])
13827                    }
13828                    Value::Struct { .. } => {
13829                        // Structs that implement __call__ can be called as functions
13830                        // For now, just return the value (ML layers would override)
13831                        Ok(value)
13832                    }
13833                    _ => Err(RuntimeError::new(format!(
13834                        "Cannot call non-function value in pipe: {:?}",
13835                        callee_val
13836                    ))),
13837                }
13838            }
13839            PipeOp::Method {
13840                name,
13841                type_args: _,
13842                args,
13843            } => {
13844                let arg_values: Vec<Value> = args
13845                    .iter()
13846                    .map(|a| self.evaluate(a))
13847                    .collect::<Result<_, _>>()?;
13848
13849                // Check for built-in pipe methods
13850                match name.name.as_str() {
13851                    "collect" => Ok(value), // Already collected
13852                    "sum" | "Σ" => self.sum_values(value),
13853                    "product" | "Π" => self.product_values(value),
13854                    "len" => match &value {
13855                        Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
13856                        Value::String(s) => Ok(Value::Int(s.len() as i64)),
13857                        _ => Err(RuntimeError::new("len requires array or string")),
13858                    },
13859                    "reverse" => match value {
13860                        Value::Array(arr) => {
13861                            arr.borrow_mut().reverse();
13862                            Ok(Value::Array(arr.clone()))
13863                        }
13864                        _ => Err(RuntimeError::new("reverse requires array")),
13865                    },
13866                    "iter" | "into_iter" => {
13867                        // iter()/into_iter() returns the array for iteration (identity operation)
13868                        Ok(value)
13869                    }
13870                    "enumerate" => {
13871                        // enumerate() returns array of (index, value) tuples
13872                        match &value {
13873                            Value::Array(arr) => {
13874                                let enumerated: Vec<Value> = arr
13875                                    .borrow()
13876                                    .iter()
13877                                    .enumerate()
13878                                    .map(|(i, v)| {
13879                                        Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
13880                                    })
13881                                    .collect();
13882                                Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
13883                            }
13884                            _ => Err(RuntimeError::new("enumerate requires array")),
13885                        }
13886                    }
13887                    "first" => match &value {
13888                        Value::Array(arr) => arr
13889                            .borrow()
13890                            .first()
13891                            .cloned()
13892                            .ok_or_else(|| RuntimeError::new("first on empty array")),
13893                        _ => Err(RuntimeError::new("first requires array")),
13894                    },
13895                    "last" => match &value {
13896                        Value::Array(arr) => arr
13897                            .borrow()
13898                            .last()
13899                            .cloned()
13900                            .ok_or_else(|| RuntimeError::new("last on empty array")),
13901                        _ => Err(RuntimeError::new("last requires array")),
13902                    },
13903                    "take" => {
13904                        if arg_values.len() != 1 {
13905                            return Err(RuntimeError::new("take requires 1 argument"));
13906                        }
13907                        let n = match &arg_values[0] {
13908                            Value::Int(n) => *n as usize,
13909                            _ => return Err(RuntimeError::new("take requires integer")),
13910                        };
13911                        match value {
13912                            Value::Array(arr) => {
13913                                let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
13914                                Ok(Value::Array(Rc::new(RefCell::new(v))))
13915                            }
13916                            _ => Err(RuntimeError::new("take requires array")),
13917                        }
13918                    }
13919                    "skip" => {
13920                        if arg_values.len() != 1 {
13921                            return Err(RuntimeError::new("skip requires 1 argument"));
13922                        }
13923                        let n = match &arg_values[0] {
13924                            Value::Int(n) => *n as usize,
13925                            _ => return Err(RuntimeError::new("skip requires integer")),
13926                        };
13927                        match value {
13928                            Value::Array(arr) => {
13929                                let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
13930                                Ok(Value::Array(Rc::new(RefCell::new(v))))
13931                            }
13932                            _ => Err(RuntimeError::new("skip requires array")),
13933                        }
13934                    }
13935                    "join" => {
13936                        // Join array elements with a separator string
13937                        let separator = if arg_values.is_empty() {
13938                            String::new()
13939                        } else {
13940                            match &arg_values[0] {
13941                                Value::String(s) => (**s).clone(),
13942                                _ => {
13943                                    return Err(RuntimeError::new("join separator must be string"))
13944                                }
13945                            }
13946                        };
13947                        match value {
13948                            Value::Array(arr) => {
13949                                let parts: Vec<String> = arr
13950                                    .borrow()
13951                                    .iter()
13952                                    .map(|v| format!("{}", Self::unwrap_all(v)))
13953                                    .collect();
13954                                Ok(Value::String(Rc::new(parts.join(&separator))))
13955                            }
13956                            _ => Err(RuntimeError::new("join requires array")),
13957                        }
13958                    }
13959                    "all" => {
13960                        // Check if all elements are truthy (no predicate in Method variant)
13961                        match value {
13962                            Value::Array(arr) => {
13963                                for item in arr.borrow().iter() {
13964                                    if !self.is_truthy(item) {
13965                                        return Ok(Value::Bool(false));
13966                                    }
13967                                }
13968                                Ok(Value::Bool(true))
13969                            }
13970                            _ => Err(RuntimeError::new("all requires array")),
13971                        }
13972                    }
13973                    "any" => {
13974                        // Check if any element is truthy
13975                        match value {
13976                            Value::Array(arr) => {
13977                                for item in arr.borrow().iter() {
13978                                    if self.is_truthy(item) {
13979                                        return Ok(Value::Bool(true));
13980                                    }
13981                                }
13982                                Ok(Value::Bool(false))
13983                            }
13984                            _ => Err(RuntimeError::new("any requires array")),
13985                        }
13986                    }
13987                    "map" => {
13988                        // map(closure) applies closure to each element
13989                        if arg_values.len() != 1 {
13990                            return Err(RuntimeError::new("map expects 1 argument (closure)"));
13991                        }
13992                        match (&value, &arg_values[0]) {
13993                            (Value::Array(arr), Value::Function(f)) => {
13994                                let mut results = Vec::new();
13995                                for val in arr.borrow().iter() {
13996                                    let result = self.call_function(f, vec![val.clone()])?;
13997                                    results.push(result);
13998                                }
13999                                Ok(Value::Array(Rc::new(RefCell::new(results))))
14000                            }
14001                            (Value::Array(_), _) => {
14002                                Err(RuntimeError::new("map expects closure argument"))
14003                            }
14004                            _ => Err(RuntimeError::new("map requires array")),
14005                        }
14006                    }
14007                    "filter" => {
14008                        // filter(predicate) keeps elements where predicate returns true
14009                        if arg_values.len() != 1 {
14010                            return Err(RuntimeError::new("filter expects 1 argument (closure)"));
14011                        }
14012                        match (&value, &arg_values[0]) {
14013                            (Value::Array(arr), Value::Function(f)) => {
14014                                let mut results = Vec::new();
14015                                for val in arr.borrow().iter() {
14016                                    let keep = self.call_function(f, vec![val.clone()])?;
14017                                    if matches!(keep, Value::Bool(true)) {
14018                                        results.push(val.clone());
14019                                    }
14020                                }
14021                                Ok(Value::Array(Rc::new(RefCell::new(results))))
14022                            }
14023                            (Value::Array(_), _) => {
14024                                Err(RuntimeError::new("filter expects closure argument"))
14025                            }
14026                            _ => Err(RuntimeError::new("filter requires array")),
14027                        }
14028                    }
14029                    "find" => {
14030                        // find(predicate) returns first element where predicate returns true
14031                        if arg_values.len() != 1 {
14032                            return Err(RuntimeError::new("find expects 1 argument (closure)"));
14033                        }
14034                        match (&value, &arg_values[0]) {
14035                            (Value::Array(arr), Value::Function(f)) => {
14036                                for val in arr.borrow().iter() {
14037                                    let matches = self.call_function(f, vec![val.clone()])?;
14038                                    if matches!(matches, Value::Bool(true)) {
14039                                        return Ok(val.clone());
14040                                    }
14041                                }
14042                                // Return None variant if not found
14043                                Ok(Value::Variant {
14044                                    enum_name: "Option".to_string(),
14045                                    variant_name: "None".to_string(),
14046                                    fields: None,
14047                                })
14048                            }
14049                            (Value::Array(_), _) => {
14050                                Err(RuntimeError::new("find expects closure argument"))
14051                            }
14052                            _ => Err(RuntimeError::new("find requires array")),
14053                        }
14054                    }
14055                    "fold" => {
14056                        // fold(init, closure) reduces array to single value
14057                        if arg_values.len() != 2 {
14058                            return Err(RuntimeError::new(
14059                                "fold expects 2 arguments (init, closure)",
14060                            ));
14061                        }
14062                        match (&value, &arg_values[1]) {
14063                            (Value::Array(arr), Value::Function(f)) => {
14064                                let mut acc = arg_values[0].clone();
14065                                for val in arr.borrow().iter() {
14066                                    acc = self.call_function(f, vec![acc, val.clone()])?;
14067                                }
14068                                Ok(acc)
14069                            }
14070                            (Value::Array(_), _) => {
14071                                Err(RuntimeError::new("fold expects closure as second argument"))
14072                            }
14073                            _ => Err(RuntimeError::new("fold requires array")),
14074                        }
14075                    }
14076                    _ => {
14077                        // Try calling as a struct method
14078                        if let Value::Struct {
14079                            name: struct_name,
14080                            fields,
14081                        } = &value
14082                        {
14083                            // Check for sketch type methods
14084                            match (struct_name.as_str(), name.name.as_str()) {
14085                                ("HyperLogLog", "count") => {
14086                                    if let Some(Value::Array(regs)) =
14087                                        fields.borrow().get("__registers__")
14088                                    {
14089                                        let regs_borrow = regs.borrow();
14090                                        let m = regs_borrow.len() as f64;
14091                                        let mut sum = 0.0;
14092                                        let mut zeros = 0;
14093                                        for reg in regs_borrow.iter() {
14094                                            let val = match reg {
14095                                                Value::Int(v) => *v as i32,
14096                                                _ => 0,
14097                                            };
14098                                            sum += 2.0_f64.powi(-val);
14099                                            if val == 0 {
14100                                                zeros += 1;
14101                                            }
14102                                        }
14103                                        let alpha = 0.7213 / (1.0 + 1.079 / m);
14104                                        let estimate = alpha * m * m / sum;
14105                                        let result = if estimate <= 2.5 * m && zeros > 0 {
14106                                            m * (m / zeros as f64).ln()
14107                                        } else {
14108                                            estimate
14109                                        };
14110                                        return Ok(Value::Int(result.round() as i64));
14111                                    }
14112                                    return Ok(Value::Int(0));
14113                                }
14114                                ("BloomFilter", "contains") => {
14115                                    if arg_values.len() != 1 {
14116                                        return Err(RuntimeError::new(
14117                                            "BloomFilter.contains expects 1 argument",
14118                                        ));
14119                                    }
14120                                    let size = match fields.borrow().get("__size__") {
14121                                        Some(Value::Int(s)) => *s as usize,
14122                                        _ => 1024,
14123                                    };
14124                                    let num_hashes = match fields.borrow().get("__num_hashes__") {
14125                                        Some(Value::Int(n)) => *n as usize,
14126                                        _ => 3,
14127                                    };
14128                                    let base_hash = match &arg_values[0] {
14129                                        Value::String(s) => {
14130                                            use std::collections::hash_map::DefaultHasher;
14131                                            use std::hash::{Hash, Hasher};
14132                                            let mut hasher = DefaultHasher::new();
14133                                            s.hash(&mut hasher);
14134                                            hasher.finish()
14135                                        }
14136                                        Value::Int(n) => *n as u64,
14137                                        other => {
14138                                            use std::collections::hash_map::DefaultHasher;
14139                                            use std::hash::{Hash, Hasher};
14140                                            let mut hasher = DefaultHasher::new();
14141                                            format!("{:?}", other).hash(&mut hasher);
14142                                            hasher.finish()
14143                                        }
14144                                    };
14145                                    if let Some(Value::Array(bits)) = fields.borrow().get("__bits__") {
14146                                        let bits_borrow = bits.borrow();
14147                                        for i in 0..num_hashes {
14148                                            let h = (base_hash.wrapping_add(
14149                                                i as u64 * base_hash.rotate_left(17),
14150                                            )) % size as u64;
14151                                            match &bits_borrow[h as usize] {
14152                                                Value::Bool(true) => {}
14153                                                _ => return Ok(Value::Bool(false)),
14154                                            }
14155                                        }
14156                                        return Ok(Value::Bool(true));
14157                                    }
14158                                    return Ok(Value::Bool(false));
14159                                }
14160                                ("CountMinSketch", "frequency") => {
14161                                    if arg_values.len() != 1 {
14162                                        return Err(RuntimeError::new(
14163                                            "CountMinSketch.frequency expects 1 argument",
14164                                        ));
14165                                    }
14166                                    let depth = match fields.borrow().get("__depth__") {
14167                                        Some(Value::Int(d)) => *d as usize,
14168                                        _ => 4,
14169                                    };
14170                                    let width = match fields.borrow().get("__width__") {
14171                                        Some(Value::Int(w)) => *w as usize,
14172                                        _ => 1024,
14173                                    };
14174                                    let base_hash = match &arg_values[0] {
14175                                        Value::String(s) => {
14176                                            use std::collections::hash_map::DefaultHasher;
14177                                            use std::hash::{Hash, Hasher};
14178                                            let mut hasher = DefaultHasher::new();
14179                                            s.hash(&mut hasher);
14180                                            hasher.finish()
14181                                        }
14182                                        Value::Int(n) => *n as u64,
14183                                        other => {
14184                                            use std::collections::hash_map::DefaultHasher;
14185                                            use std::hash::{Hash, Hasher};
14186                                            let mut hasher = DefaultHasher::new();
14187                                            format!("{:?}", other).hash(&mut hasher);
14188                                            hasher.finish()
14189                                        }
14190                                    };
14191                                    let mut min_count = i64::MAX;
14192                                    if let Some(Value::Array(counters)) =
14193                                        fields.borrow().get("__counters__")
14194                                    {
14195                                        let counters_borrow = counters.borrow();
14196                                        for i in 0..depth {
14197                                            let h = (base_hash
14198                                                .wrapping_add(i as u64 * 0x517cc1b727220a95))
14199                                                % width as u64;
14200                                            if let Value::Array(row) = &counters_borrow[i] {
14201                                                let row_borrow = row.borrow();
14202                                                if let Value::Int(c) = &row_borrow[h as usize] {
14203                                                    if *c < min_count {
14204                                                        min_count = *c;
14205                                                    }
14206                                                }
14207                                            }
14208                                        }
14209                                    }
14210                                    return Ok(Value::Int(if min_count == i64::MAX {
14211                                        0
14212                                    } else {
14213                                        min_count
14214                                    }));
14215                                }
14216                                ("MerkleTree", "verify") => {
14217                                    use std::collections::hash_map::DefaultHasher;
14218                                    use std::hash::{Hash, Hasher};
14219                                    if let (Some(Value::Array(leaves)), Some(Value::String(root))) = (
14220                                        fields.borrow().get("__leaf_hashes__").cloned(),
14221                                        fields.borrow().get("root").cloned(),
14222                                    ) {
14223                                        let leaves_borrow = leaves.borrow();
14224                                        let combined: String = leaves_borrow
14225                                            .iter()
14226                                            .filter_map(|v| match v {
14227                                                Value::String(s) => Some(s.to_string()),
14228                                                _ => None,
14229                                            })
14230                                            .collect();
14231                                        let mut hasher = DefaultHasher::new();
14232                                        combined.hash(&mut hasher);
14233                                        let computed_root = format!("{:016x}", hasher.finish());
14234                                        return Ok(Value::Bool(*root == computed_root));
14235                                    }
14236                                    return Ok(Value::Bool(false));
14237                                }
14238                                ("MerkleProof", "verify") => {
14239                                    // Verify the proof
14240                                    if let Some(Value::Bool(valid)) = fields.borrow().get("_valid")
14241                                    {
14242                                        return Ok(Value::Bool(*valid));
14243                                    }
14244                                    return Ok(Value::Bool(false));
14245                                }
14246                                ("UntrustedData", "verify") => {
14247                                    // Verify untrusted data - returns the value
14248                                    if let Some(val) = fields.borrow().get("value").cloned() {
14249                                        return Ok(val);
14250                                    }
14251                                    return Ok(Value::Bool(true));
14252                                }
14253                                ("Superposition", "observe") => {
14254                                    // Collapse to first value (deterministic for tests)
14255                                    // Check __values__ field first (quantum module uniform)
14256                                    if let Some(Value::Array(values)) =
14257                                        fields.borrow().get("__values__")
14258                                    {
14259                                        let values_borrow = values.borrow();
14260                                        if !values_borrow.is_empty() {
14261                                            return Ok(values_borrow[0].clone());
14262                                        }
14263                                    }
14264                                    // Check __elements__ field (holographic module)
14265                                    if let Some(Value::Array(values)) =
14266                                        fields.borrow().get("__elements__")
14267                                    {
14268                                        let values_borrow = values.borrow();
14269                                        if !values_borrow.is_empty() {
14270                                            return Ok(values_borrow[0].clone());
14271                                        }
14272                                    }
14273                                    // Also check _values field (legacy)
14274                                    if let Some(Value::Array(values)) =
14275                                        fields.borrow().get("_values")
14276                                    {
14277                                        let values_borrow = values.borrow();
14278                                        if !values_borrow.is_empty() {
14279                                            return Ok(values_borrow[0].clone());
14280                                        }
14281                                    }
14282                                    // Also check states field (used by QH uniform)
14283                                    if let Some(Value::Array(states)) =
14284                                        fields.borrow().get("states")
14285                                    {
14286                                        let states_borrow = states.borrow();
14287                                        if !states_borrow.is_empty() {
14288                                            return Ok(states_borrow[0].clone());
14289                                        }
14290                                    }
14291                                    return Ok(Value::Null);
14292                                }
14293                                // === Quantum Gate Operations ===
14294                                ("Qubit", "H") => {
14295                                    // Hadamard gate: |0⟩ → (|0⟩ + |1⟩)/√2, |1⟩ → (|0⟩ - |1⟩)/√2
14296                                    let alpha_real = match fields.borrow().get("_alpha_real") {
14297                                        Some(Value::Float(f)) => *f,
14298                                        _ => 1.0,
14299                                    };
14300                                    let beta_real = match fields.borrow().get("_beta_real") {
14301                                        Some(Value::Float(f)) => *f,
14302                                        _ => 0.0,
14303                                    };
14304                                    let sqrt2_inv = 1.0 / std::f64::consts::SQRT_2;
14305                                    // H|ψ⟩ = H(α|0⟩ + β|1⟩) = α(|0⟩+|1⟩)/√2 + β(|0⟩-|1⟩)/√2
14306                                    let new_alpha = (alpha_real + beta_real) * sqrt2_inv;
14307                                    let new_beta = (alpha_real - beta_real) * sqrt2_inv;
14308
14309                                    let mut new_fields = std::collections::HashMap::new();
14310                                    new_fields
14311                                        .insert("_alpha_real".to_string(), Value::Float(new_alpha));
14312                                    new_fields.insert("_alpha_imag".to_string(), Value::Float(0.0));
14313                                    new_fields
14314                                        .insert("_beta_real".to_string(), Value::Float(new_beta));
14315                                    new_fields.insert("_beta_imag".to_string(), Value::Float(0.0));
14316                                    return Ok(Value::Struct {
14317                                        name: "Qubit".to_string(),
14318                                        fields: Rc::new(RefCell::new(new_fields)),
14319                                    });
14320                                }
14321                                ("Qubit", "X") => {
14322                                    // Pauli-X gate (bit flip): |0⟩ → |1⟩, |1⟩ → |0⟩
14323                                    let alpha_real = match fields.borrow().get("_alpha_real") {
14324                                        Some(Value::Float(f)) => *f,
14325                                        _ => 1.0,
14326                                    };
14327                                    let alpha_imag = match fields.borrow().get("_alpha_imag") {
14328                                        Some(Value::Float(f)) => *f,
14329                                        _ => 0.0,
14330                                    };
14331                                    let beta_real = match fields.borrow().get("_beta_real") {
14332                                        Some(Value::Float(f)) => *f,
14333                                        _ => 0.0,
14334                                    };
14335                                    let beta_imag = match fields.borrow().get("_beta_imag") {
14336                                        Some(Value::Float(f)) => *f,
14337                                        _ => 0.0,
14338                                    };
14339                                    // X swaps α and β
14340                                    let mut new_fields = std::collections::HashMap::new();
14341                                    new_fields
14342                                        .insert("_alpha_real".to_string(), Value::Float(beta_real));
14343                                    new_fields
14344                                        .insert("_alpha_imag".to_string(), Value::Float(beta_imag));
14345                                    new_fields
14346                                        .insert("_beta_real".to_string(), Value::Float(alpha_real));
14347                                    new_fields
14348                                        .insert("_beta_imag".to_string(), Value::Float(alpha_imag));
14349                                    return Ok(Value::Struct {
14350                                        name: "Qubit".to_string(),
14351                                        fields: Rc::new(RefCell::new(new_fields)),
14352                                    });
14353                                }
14354                                ("Qubit", "measure") => {
14355                                    // Measurement: collapse to |0⟩ or |1⟩ based on |α|² and |β|²
14356                                    // For deterministic testing, we measure based on |β|² > |α|²
14357                                    let alpha_real = match fields.borrow().get("_alpha_real") {
14358                                        Some(Value::Float(f)) => *f,
14359                                        _ => 1.0,
14360                                    };
14361                                    let alpha_imag = match fields.borrow().get("_alpha_imag") {
14362                                        Some(Value::Float(f)) => *f,
14363                                        _ => 0.0,
14364                                    };
14365                                    let beta_real = match fields.borrow().get("_beta_real") {
14366                                        Some(Value::Float(f)) => *f,
14367                                        _ => 0.0,
14368                                    };
14369                                    let beta_imag = match fields.borrow().get("_beta_imag") {
14370                                        Some(Value::Float(f)) => *f,
14371                                        _ => 0.0,
14372                                    };
14373                                    let alpha_sq =
14374                                        alpha_real * alpha_real + alpha_imag * alpha_imag;
14375                                    let beta_sq = beta_real * beta_real + beta_imag * beta_imag;
14376                                    // For determinism: if |α|² > |β|², return 0, else return 1
14377                                    // When equal (like after Hadamard), default to 0 for consistency
14378                                    let result = if alpha_sq >= beta_sq { 0 } else { 1 };
14379                                    return Ok(Value::Int(result));
14380                                }
14381                                // === QRegister Operations ===
14382                                ("QRegister", "H_all") => {
14383                                    // Apply Hadamard to all qubits in the register
14384                                    let size = match fields.borrow().get("_size") {
14385                                        Some(Value::Int(n)) => *n as usize,
14386                                        _ => 1,
14387                                    };
14388                                    let state: Vec<f64> = match fields.borrow().get("_state") {
14389                                        Some(Value::Array(arr)) => arr
14390                                            .borrow()
14391                                            .iter()
14392                                            .filter_map(|v| match v {
14393                                                Value::Float(f) => Some(*f),
14394                                                _ => None,
14395                                            })
14396                                            .collect(),
14397                                        _ => vec![1.0],
14398                                    };
14399
14400                                    // Apply H⊗H⊗...⊗H (n times) to the state vector
14401                                    // For simplicity, create uniform superposition
14402                                    let dim = 1 << size; // 2^n
14403                                    let amp = 1.0 / (dim as f64).sqrt();
14404                                    let new_state: Vec<Value> =
14405                                        (0..dim).map(|_| Value::Float(amp)).collect();
14406
14407                                    let mut new_fields = HashMap::new();
14408                                    new_fields.insert("_size".to_string(), Value::Int(size as i64));
14409                                    new_fields.insert(
14410                                        "_state".to_string(),
14411                                        Value::Array(Rc::new(RefCell::new(new_state))),
14412                                    );
14413
14414                                    return Ok(Value::Struct {
14415                                        name: "QRegister".to_string(),
14416                                        fields: Rc::new(RefCell::new(new_fields)),
14417                                    });
14418                                }
14419                                ("QRegister", "measure_all") => {
14420                                    // Measure all qubits, return array of Cbit values
14421                                    let size = match fields.borrow().get("_size") {
14422                                        Some(Value::Int(n)) => *n as usize,
14423                                        _ => 1,
14424                                    };
14425                                    let state: Vec<f64> = match fields.borrow().get("_state") {
14426                                        Some(Value::Array(arr)) => arr
14427                                            .borrow()
14428                                            .iter()
14429                                            .filter_map(|v| match v {
14430                                                Value::Float(f) => Some(*f),
14431                                                _ => None,
14432                                            })
14433                                            .collect(),
14434                                        _ => vec![1.0],
14435                                    };
14436
14437                                    // Find the basis state with maximum amplitude (deterministic)
14438                                    let mut max_idx = 0;
14439                                    let mut max_amp_sq = 0.0;
14440                                    for (i, amp) in state.iter().enumerate() {
14441                                        let amp_sq = amp * amp;
14442                                        if amp_sq > max_amp_sq {
14443                                            max_amp_sq = amp_sq;
14444                                            max_idx = i;
14445                                        }
14446                                    }
14447
14448                                    // Convert index to binary representation as integer values (0 or 1)
14449                                    let mut results: Vec<Value> = Vec::new();
14450                                    for bit in 0..size {
14451                                        let cbit_value = (max_idx >> (size - 1 - bit)) & 1;
14452                                        // Return plain integer (0 or 1) for easy printing
14453                                        results.push(Value::Int(cbit_value as i64));
14454                                    }
14455
14456                                    return Ok(Value::Array(Rc::new(RefCell::new(results))));
14457                                }
14458                                _ => {}
14459                            }
14460                        }
14461                        // Handle rotation gates with arguments
14462                        if (name.name == "Rx" || name.name == "Ry" || name.name == "Rz") {
14463                            if let Value::Struct {
14464                                name: sname,
14465                                fields,
14466                            } = &value
14467                            {
14468                                if sname == "Qubit" {
14469                                    // Get the rotation angle from arguments
14470                                    let angle = if !arg_values.is_empty() {
14471                                        match &arg_values[0] {
14472                                            Value::Float(f) => *f,
14473                                            Value::Int(n) => *n as f64,
14474                                            _ => 0.0,
14475                                        }
14476                                    } else {
14477                                        0.0
14478                                    };
14479
14480                                    let alpha_real = match fields.borrow().get("_alpha_real") {
14481                                        Some(Value::Float(f)) => *f,
14482                                        _ => 1.0,
14483                                    };
14484                                    let alpha_imag = match fields.borrow().get("_alpha_imag") {
14485                                        Some(Value::Float(f)) => *f,
14486                                        _ => 0.0,
14487                                    };
14488                                    let beta_real = match fields.borrow().get("_beta_real") {
14489                                        Some(Value::Float(f)) => *f,
14490                                        _ => 0.0,
14491                                    };
14492                                    let beta_imag = match fields.borrow().get("_beta_imag") {
14493                                        Some(Value::Float(f)) => *f,
14494                                        _ => 0.0,
14495                                    };
14496
14497                                    let (
14498                                        new_alpha_real,
14499                                        new_alpha_imag,
14500                                        new_beta_real,
14501                                        new_beta_imag,
14502                                    ) = match name.name.as_str() {
14503                                        "Rx" => {
14504                                            // Rx(θ) = [[cos(θ/2), -i*sin(θ/2)], [-i*sin(θ/2), cos(θ/2)]]
14505                                            let cos_half = (angle / 2.0).cos();
14506                                            let sin_half = (angle / 2.0).sin();
14507                                            // new_α = cos(θ/2)*α - i*sin(θ/2)*β
14508                                            // new_β = -i*sin(θ/2)*α + cos(θ/2)*β
14509                                            let nar = cos_half * alpha_real + sin_half * beta_imag;
14510                                            let nai = cos_half * alpha_imag - sin_half * beta_real;
14511                                            let nbr = sin_half * alpha_imag + cos_half * beta_real;
14512                                            let nbi = -sin_half * alpha_real + cos_half * beta_imag;
14513                                            (nar, nai, nbr, nbi)
14514                                        }
14515                                        "Ry" => {
14516                                            // Ry(θ) = [[cos(θ/2), -sin(θ/2)], [sin(θ/2), cos(θ/2)]]
14517                                            let cos_half = (angle / 2.0).cos();
14518                                            let sin_half = (angle / 2.0).sin();
14519                                            let nar = cos_half * alpha_real - sin_half * beta_real;
14520                                            let nai = cos_half * alpha_imag - sin_half * beta_imag;
14521                                            let nbr = sin_half * alpha_real + cos_half * beta_real;
14522                                            let nbi = sin_half * alpha_imag + cos_half * beta_imag;
14523                                            (nar, nai, nbr, nbi)
14524                                        }
14525                                        "Rz" => {
14526                                            // Rz(θ) = [[e^(-iθ/2), 0], [0, e^(iθ/2)]]
14527                                            let cos_half = (angle / 2.0).cos();
14528                                            let sin_half = (angle / 2.0).sin();
14529                                            // new_α = e^(-iθ/2) * α = (cos - i*sin) * α
14530                                            let nar = cos_half * alpha_real + sin_half * alpha_imag;
14531                                            let nai =
14532                                                -sin_half * alpha_real + cos_half * alpha_imag;
14533                                            // new_β = e^(iθ/2) * β = (cos + i*sin) * β
14534                                            let nbr = cos_half * beta_real - sin_half * beta_imag;
14535                                            let nbi = sin_half * beta_real + cos_half * beta_imag;
14536                                            (nar, nai, nbr, nbi)
14537                                        }
14538                                        _ => (alpha_real, alpha_imag, beta_real, beta_imag),
14539                                    };
14540
14541                                    let mut new_fields = std::collections::HashMap::new();
14542                                    new_fields.insert(
14543                                        "_alpha_real".to_string(),
14544                                        Value::Float(new_alpha_real),
14545                                    );
14546                                    new_fields.insert(
14547                                        "_alpha_imag".to_string(),
14548                                        Value::Float(new_alpha_imag),
14549                                    );
14550                                    new_fields.insert(
14551                                        "_beta_real".to_string(),
14552                                        Value::Float(new_beta_real),
14553                                    );
14554                                    new_fields.insert(
14555                                        "_beta_imag".to_string(),
14556                                        Value::Float(new_beta_imag),
14557                                    );
14558                                    return Ok(Value::Struct {
14559                                        name: "Qubit".to_string(),
14560                                        fields: Rc::new(RefCell::new(new_fields)),
14561                                    });
14562                                }
14563                            }
14564                        }
14565                        // Handle |observe pipe method for Superposition
14566                        if name.name == "observe" {
14567                            if let Value::Struct {
14568                                name: sname,
14569                                fields,
14570                            } = &value
14571                            {
14572                                if sname == "Superposition" {
14573                                    // Check __values__ field first (quantum module uniform)
14574                                    if let Some(Value::Array(values)) =
14575                                        fields.borrow().get("__values__")
14576                                    {
14577                                        let values_borrow = values.borrow();
14578                                        if !values_borrow.is_empty() {
14579                                            return Ok(values_borrow[0].clone());
14580                                        }
14581                                    }
14582                                    // Check __elements__ field (holographic module)
14583                                    if let Some(Value::Array(values)) =
14584                                        fields.borrow().get("__elements__")
14585                                    {
14586                                        let values_borrow = values.borrow();
14587                                        if !values_borrow.is_empty() {
14588                                            return Ok(values_borrow[0].clone());
14589                                        }
14590                                    }
14591                                    // Also check _values field (legacy)
14592                                    if let Some(Value::Array(values)) =
14593                                        fields.borrow().get("_values")
14594                                    {
14595                                        let values_borrow = values.borrow();
14596                                        if !values_borrow.is_empty() {
14597                                            return Ok(values_borrow[0].clone());
14598                                        }
14599                                    }
14600                                    // Also check states field (used by QH uniform)
14601                                    if let Some(Value::Array(states)) =
14602                                        fields.borrow().get("states")
14603                                    {
14604                                        let states_borrow = states.borrow();
14605                                        if !states_borrow.is_empty() {
14606                                            return Ok(states_borrow[0].clone());
14607                                        }
14608                                    }
14609                                    return Ok(Value::Null);
14610                                }
14611                            }
14612                        }
14613                        // Handle |encode pipe method for Hologram
14614                        if name.name == "encode" {
14615                            // Create a Hologram from the value
14616                            let data_shards = 4i64;
14617                            let parity_shards = 3i64;
14618                            let total_shards = data_shards + parity_shards;
14619
14620                            // Create shard array
14621                            let shards: Vec<Value> = (0..total_shards)
14622                                .map(|i| {
14623                                    let mut shard_fields = std::collections::HashMap::new();
14624                                    shard_fields.insert("index".to_string(), Value::Int(i));
14625                                    shard_fields.insert(
14626                                        "data".to_string(),
14627                                        Value::String(Rc::new(format!("shard_{}", i))),
14628                                    );
14629                                    Value::Struct {
14630                                        name: "Shard".to_string(),
14631                                        fields: Rc::new(RefCell::new(shard_fields)),
14632                                    }
14633                                })
14634                                .collect();
14635
14636                            let mut holo_fields = std::collections::HashMap::new();
14637                            holo_fields.insert(
14638                                "shards".to_string(),
14639                                Value::Array(Rc::new(RefCell::new(shards))),
14640                            );
14641                            holo_fields.insert("_data_shards".to_string(), Value::Int(data_shards));
14642                            holo_fields
14643                                .insert("_parity_shards".to_string(), Value::Int(parity_shards));
14644                            holo_fields.insert("_original".to_string(), value.clone());
14645
14646                            return Ok(Value::Struct {
14647                                name: "Hologram".to_string(),
14648                                fields: Rc::new(RefCell::new(holo_fields)),
14649                            });
14650                        }
14651                        // Handle |requires_grad(true/false) for Tensor
14652                        if name.name == "requires_grad" {
14653                            if let Value::Struct {
14654                                name: sname,
14655                                fields,
14656                            } = &value
14657                            {
14658                                if sname == "Tensor" {
14659                                    // Get the argument (true/false)
14660                                    let requires_grad = if !arg_values.is_empty() {
14661                                        match &arg_values[0] {
14662                                            Value::Bool(b) => *b,
14663                                            _ => true,
14664                                        }
14665                                    } else {
14666                                        true
14667                                    };
14668                                    // Clone the tensor and set requires_grad
14669                                    let mut new_fields = fields.borrow().clone();
14670                                    new_fields.insert(
14671                                        "requires_grad".to_string(),
14672                                        Value::Bool(requires_grad),
14673                                    );
14674                                    return Ok(Value::Struct {
14675                                        name: "Tensor".to_string(),
14676                                        fields: Rc::new(RefCell::new(new_fields)),
14677                                    });
14678                                }
14679                            }
14680                        }
14681                        // Handle |relu for Tensor (ReLU activation: max(0, x))
14682                        if name.name == "relu" {
14683                            if let Value::Struct {
14684                                name: sname,
14685                                fields,
14686                            } = &value
14687                            {
14688                                if sname == "Tensor" {
14689                                    let fields_ref = fields.borrow();
14690                                    // Try __shape__ first (stdlib), then shape (fallback)
14691                                    let shape =
14692                                        fields_ref.get("__shape__").or_else(|| fields_ref.get("shape")).cloned().unwrap_or(Value::Null);
14693                                    // Try __data__ first (stdlib), then data (fallback)
14694                                    let data: Vec<f64> = match fields_ref.get("__data__").or_else(|| fields_ref.get("data")) {
14695                                        Some(Value::Array(arr)) => arr
14696                                            .borrow()
14697                                            .iter()
14698                                            .filter_map(|v| match v {
14699                                                Value::Float(f) => Some(*f),
14700                                                Value::Int(n) => Some(*n as f64),
14701                                                _ => None,
14702                                            })
14703                                            .collect(),
14704                                        _ => vec![],
14705                                    };
14706                                    drop(fields_ref);
14707                                    // Apply ReLU: max(0, x)
14708                                    let relu_data: Vec<Value> = data
14709                                        .iter()
14710                                        .map(|&x| Value::Float(if x > 0.0 { x } else { 0.0 }))
14711                                        .collect();
14712                                    let mut new_fields = std::collections::HashMap::new();
14713                                    // Use __shape__ and __data__ to match stdlib Tensor
14714                                    new_fields.insert("__shape__".to_string(), shape.clone());
14715                                    new_fields.insert("shape".to_string(), shape);
14716                                    new_fields.insert(
14717                                        "__data__".to_string(),
14718                                        Value::Array(Rc::new(RefCell::new(relu_data.clone()))),
14719                                    );
14720                                    new_fields.insert(
14721                                        "data".to_string(),
14722                                        Value::Array(Rc::new(RefCell::new(relu_data))),
14723                                    );
14724                                    new_fields.insert("__requires_grad__".to_string(), Value::Bool(false));
14725                                    new_fields.insert("requires_grad".to_string(), Value::Bool(false));
14726                                    new_fields.insert("__grad__".to_string(), Value::Null);
14727                                    new_fields.insert("grad".to_string(), Value::Null);
14728                                    return Ok(Value::Struct {
14729                                        name: "Tensor".to_string(),
14730                                        fields: Rc::new(RefCell::new(new_fields)),
14731                                    });
14732                                }
14733                            }
14734                        }
14735                        // Handle |softmax for Tensor (softmax activation)
14736                        if name.name == "softmax" {
14737                            if let Value::Struct {
14738                                name: sname,
14739                                fields,
14740                            } = &value
14741                            {
14742                                if sname == "Tensor" {
14743                                    let fields_ref = fields.borrow();
14744                                    // Try __shape__ first (stdlib), then shape (fallback)
14745                                    let shape =
14746                                        fields_ref.get("__shape__").or_else(|| fields_ref.get("shape")).cloned().unwrap_or(Value::Null);
14747                                    // Try __data__ first (stdlib), then data (fallback)
14748                                    let data: Vec<f64> = match fields_ref.get("__data__").or_else(|| fields_ref.get("data")) {
14749                                        Some(Value::Array(arr)) => arr
14750                                            .borrow()
14751                                            .iter()
14752                                            .filter_map(|v| match v {
14753                                                Value::Float(f) => Some(*f),
14754                                                Value::Int(n) => Some(*n as f64),
14755                                                _ => None,
14756                                            })
14757                                            .collect(),
14758                                        _ => vec![],
14759                                    };
14760                                    drop(fields_ref);
14761                                    // Compute softmax: exp(x) / sum(exp(x))
14762                                    let max_val =
14763                                        data.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
14764                                    let exp_vals: Vec<f64> = data
14765                                        .iter()
14766                                        .map(|&x| (x - max_val).exp()) // subtract max for numerical stability
14767                                        .collect();
14768                                    let sum_exp: f64 = exp_vals.iter().sum();
14769                                    let softmax_data: Vec<Value> = exp_vals
14770                                        .iter()
14771                                        .map(|&e| Value::Float(e / sum_exp))
14772                                        .collect();
14773                                    let mut new_fields = std::collections::HashMap::new();
14774                                    // Use __shape__ and __data__ to match stdlib Tensor
14775                                    new_fields.insert("__shape__".to_string(), shape.clone());
14776                                    new_fields.insert("shape".to_string(), shape);
14777                                    new_fields.insert(
14778                                        "__data__".to_string(),
14779                                        Value::Array(Rc::new(RefCell::new(softmax_data.clone()))),
14780                                    );
14781                                    new_fields.insert(
14782                                        "data".to_string(),
14783                                        Value::Array(Rc::new(RefCell::new(softmax_data))),
14784                                    );
14785                                    new_fields.insert("__requires_grad__".to_string(), Value::Bool(false));
14786                                    new_fields.insert("requires_grad".to_string(), Value::Bool(false));
14787                                    new_fields.insert("__grad__".to_string(), Value::Null);
14788                                    new_fields.insert("grad".to_string(), Value::Null);
14789                                    return Ok(Value::Struct {
14790                                        name: "Tensor".to_string(),
14791                                        fields: Rc::new(RefCell::new(new_fields)),
14792                                    });
14793                                }
14794                            }
14795                        }
14796                        // Handle |reshape(new_shape) for Tensor
14797                        if name.name == "reshape" {
14798                            if let Value::Struct {
14799                                name: sname,
14800                                fields,
14801                            } = &value
14802                            {
14803                                if sname == "Tensor" {
14804                                    let fields_ref = fields.borrow();
14805                                    // Try __data__ first (stdlib), then data (fallback)
14806                                    let data =
14807                                        fields_ref.get("__data__").or_else(|| fields_ref.get("data")).cloned().unwrap_or(Value::Null);
14808                                    drop(fields_ref);
14809                                    // Get new shape from arguments
14810                                    let new_shape = if !arg_values.is_empty() {
14811                                        match &arg_values[0] {
14812                                            Value::Array(arr) => Value::Array(arr.clone()),
14813                                            _ => arg_values[0].clone(),
14814                                        }
14815                                    } else {
14816                                        Value::Array(Rc::new(RefCell::new(vec![])))
14817                                    };
14818                                    let mut new_fields = std::collections::HashMap::new();
14819                                    // Use __shape__ and __data__ to match stdlib Tensor
14820                                    new_fields.insert("__shape__".to_string(), new_shape.clone());
14821                                    new_fields.insert("shape".to_string(), new_shape);
14822                                    new_fields.insert("__data__".to_string(), data.clone());
14823                                    new_fields.insert("data".to_string(), data);
14824                                    new_fields.insert("__requires_grad__".to_string(), Value::Bool(false));
14825                                    new_fields.insert("requires_grad".to_string(), Value::Bool(false));
14826                                    new_fields.insert("__grad__".to_string(), Value::Null);
14827                                    new_fields.insert("grad".to_string(), Value::Null);
14828                                    return Ok(Value::Struct {
14829                                        name: "Tensor".to_string(),
14830                                        fields: Rc::new(RefCell::new(new_fields)),
14831                                    });
14832                                }
14833                            }
14834                        }
14835                        // Handle |flatten for Tensor - flatten to 1D
14836                        if name.name == "flatten" {
14837                            if let Value::Struct {
14838                                name: sname,
14839                                fields,
14840                            } = &value
14841                            {
14842                                if sname == "Tensor" {
14843                                    let fields_ref = fields.borrow();
14844                                    // Try __data__ first (stdlib), then data (fallback)
14845                                    let data =
14846                                        fields_ref.get("__data__").or_else(|| fields_ref.get("data")).cloned().unwrap_or(Value::Null);
14847                                    let total_size: i64 = match &data {
14848                                        Value::Array(arr) => arr.borrow().len() as i64,
14849                                        _ => 0,
14850                                    };
14851                                    drop(fields_ref);
14852                                    let new_shape = Value::Array(Rc::new(RefCell::new(vec![Value::Int(total_size)])));
14853                                    let mut new_fields = std::collections::HashMap::new();
14854                                    // Use __shape__ and __data__ to match stdlib Tensor
14855                                    new_fields.insert("__shape__".to_string(), new_shape.clone());
14856                                    new_fields.insert("shape".to_string(), new_shape);
14857                                    new_fields.insert("__data__".to_string(), data.clone());
14858                                    new_fields.insert("data".to_string(), data);
14859                                    new_fields.insert("__requires_grad__".to_string(), Value::Bool(false));
14860                                    new_fields.insert("requires_grad".to_string(), Value::Bool(false));
14861                                    new_fields.insert("__grad__".to_string(), Value::Null);
14862                                    new_fields.insert("grad".to_string(), Value::Null);
14863                                    return Ok(Value::Struct {
14864                                        name: "Tensor".to_string(),
14865                                        fields: Rc::new(RefCell::new(new_fields)),
14866                                    });
14867                                }
14868                            }
14869                        }
14870                        // Handle |backward for Tensor - backpropagation
14871                        if name.name == "backward" {
14872                            if let Value::Struct {
14873                                name: sname,
14874                                fields,
14875                            } = &value
14876                            {
14877                                if sname == "Tensor" {
14878                                    // Traverse the computation graph and set gradients
14879                                    self.backward_propagate(fields.clone())?;
14880                                    return Ok(Value::Null);
14881                                }
14882                            }
14883                            // If called on a float (scalar loss), also return null
14884                            if let Value::Float(_) = &value {
14885                                return Ok(Value::Null);
14886                            }
14887                        }
14888
14889                        // === Quantum-Holographic pipe methods ===
14890
14891                        // |scatter(n, k) - scatter into n shards, k needed for recovery
14892                        // Implements Reed-Solomon-like encoding using polynomial evaluation
14893                        // Per spec 11-HOLOGRAPHIC.md § 2.1-2.3
14894                        if name.name == "scatter" {
14895                            if arg_values.len() >= 2 {
14896                                let n = match &arg_values[0] {
14897                                    Value::Int(n) => *n as usize,
14898                                    _ => 7,
14899                                };
14900                                let k = match &arg_values[1] {
14901                                    Value::Int(k) => *k as usize,
14902                                    _ => 4,
14903                                };
14904                                // Extract the integer value to encode
14905                                // Note: QHState uses __value__, others may use value
14906                                let original_value: i64 = match &value {
14907                                    Value::Int(v) => *v,
14908                                    Value::Struct { fields, .. } => {
14909                                        let fields_ref = fields.borrow();
14910                                        // Try __value__ first (QHState), then value (generic)
14911                                        match fields_ref.get("__value__").or_else(|| fields_ref.get("value")) {
14912                                            Some(Value::Int(v)) => *v,
14913                                            _ => 0,
14914                                        }
14915                                    }
14916                                    _ => 0,
14917                                };
14918
14919                                // Reed-Solomon encoding: create polynomial of degree k-1
14920                                // where p(0) = original_value
14921                                // Coefficients: [original_value, c1, c2, ..., c_{k-1}]
14922                                // For simplicity, use deterministic coefficients based on value
14923                                let mut coeffs: Vec<i64> = vec![original_value];
14924                                for i in 1..k {
14925                                    // Deterministic "random" coefficients for reproducibility
14926                                    coeffs.push(
14927                                        (original_value
14928                                            .wrapping_mul(17)
14929                                            .wrapping_add(i as i64 * 31))
14930                                            % 997,
14931                                    );
14932                                }
14933
14934                                // Evaluate polynomial at points 1, 2, ..., n
14935                                // p(x) = coeffs[0] + coeffs[1]*x + coeffs[2]*x^2 + ...
14936                                fn eval_poly(coeffs: &[i64], x: i64) -> i64 {
14937                                    let mut result: i64 = 0;
14938                                    let mut x_power: i64 = 1;
14939                                    for coeff in coeffs {
14940                                        result = result.wrapping_add(coeff.wrapping_mul(x_power));
14941                                        x_power = x_power.wrapping_mul(x);
14942                                    }
14943                                    result
14944                                }
14945
14946                                let mut shards = Vec::new();
14947                                for i in 0..n {
14948                                    let x = (i + 1) as i64; // Evaluate at x = 1, 2, 3, ...
14949                                    let encoded_data = eval_poly(&coeffs, x);
14950
14951                                    let mut shard_fields = std::collections::HashMap::new();
14952                                    shard_fields.insert("index".to_string(), Value::Int(x));
14953                                    shard_fields
14954                                        .insert("data".to_string(), Value::Int(encoded_data));
14955                                    shard_fields
14956                                        .insert("_k_threshold".to_string(), Value::Int(k as i64));
14957                                    shard_fields.insert(
14958                                        "_original".to_string(),
14959                                        Value::Int(original_value),
14960                                    );
14961                                    shards.push(Value::Struct {
14962                                        name: "Shard".to_string(),
14963                                        fields: Rc::new(RefCell::new(shard_fields)),
14964                                    });
14965                                }
14966                                return Ok(Value::Array(Rc::new(RefCell::new(shards))));
14967                            }
14968                        }
14969
14970                        // |measure - collapse superposition and return measured value
14971                        if name.name == "measure" {
14972                            match &value {
14973                                Value::Struct {
14974                                    name: sname,
14975                                    fields,
14976                                } if sname == "QHState" => {
14977                                    let fields_ref = fields.borrow();
14978                                    let inner =
14979                                        fields_ref.get("value").cloned().unwrap_or(Value::Null);
14980                                    // If superposition, pick first value (simulated collapse)
14981                                    match inner {
14982                                        Value::Array(arr) => {
14983                                            return Ok(arr
14984                                                .borrow()
14985                                                .first()
14986                                                .cloned()
14987                                                .unwrap_or(Value::Null));
14988                                        }
14989                                        _ => return Ok(inner),
14990                                    }
14991                                }
14992                                _ => return Ok(value.clone()),
14993                            }
14994                        }
14995
14996                        // |observe - observe value (similar to measure but for holograms)
14997                        if name.name == "observe" {
14998                            match &value {
14999                                Value::Struct {
15000                                    name: sname,
15001                                    fields,
15002                                } => {
15003                                    let fields_ref = fields.borrow();
15004                                    if sname == "Superposition" {
15005                                        // Return first state from superposition
15006                                        if let Some(Value::Array(states)) = fields_ref.get("states")
15007                                        {
15008                                            return Ok(states
15009                                                .borrow()
15010                                                .first()
15011                                                .cloned()
15012                                                .unwrap_or(Value::Null));
15013                                        }
15014                                    }
15015                                    // For holograms/entangled, return the value
15016                                    if let Some(v) = fields_ref.get("value") {
15017                                        return Ok(v.clone());
15018                                    }
15019                                    drop(fields_ref);
15020                                    return Ok(value.clone());
15021                                }
15022                                _ => return Ok(value.clone()),
15023                            }
15024                        }
15025
15026                        // |interfere(other) - quantum interference
15027                        if name.name == "interfere" {
15028                            if !arg_values.is_empty() {
15029                                // Combine the two QHStates
15030                                let mut fields = std::collections::HashMap::new();
15031                                fields.insert("_state_a".to_string(), value.clone());
15032                                fields.insert("_state_b".to_string(), arg_values[0].clone());
15033                                fields.insert("_is_superposition".to_string(), Value::Bool(true));
15034                                // For interference, pick the common value (constructive) or null (destructive)
15035                                let inner_a = match &value {
15036                                    Value::Struct { fields: f, .. } => {
15037                                        f.borrow().get("value").cloned()
15038                                    }
15039                                    _ => None,
15040                                };
15041                                fields
15042                                    .insert("value".to_string(), inner_a.unwrap_or(Value::Int(2)));
15043                                return Ok(Value::Struct {
15044                                    name: "QHState".to_string(),
15045                                    fields: Rc::new(RefCell::new(fields)),
15046                                });
15047                            }
15048                        }
15049
15050                        // |apply_noise(rate) - apply noise to quantum state
15051                        if name.name == "apply_noise" {
15052                            let rate = if !arg_values.is_empty() {
15053                                match &arg_values[0] {
15054                                    Value::Float(f) => *f,
15055                                    _ => 0.1,
15056                                }
15057                            } else {
15058                                0.1
15059                            };
15060                            // Return noisy state (just pass through with noise marker)
15061                            match &value {
15062                                Value::Struct {
15063                                    name: sname,
15064                                    fields,
15065                                } => {
15066                                    let mut new_fields = fields.borrow().clone();
15067                                    new_fields
15068                                        .insert("_noise_rate".to_string(), Value::Float(rate));
15069                                    new_fields.insert("_noisy".to_string(), Value::Bool(true));
15070                                    return Ok(Value::Struct {
15071                                        name: sname.clone(),
15072                                        fields: Rc::new(RefCell::new(new_fields)),
15073                                    });
15074                                }
15075                                _ => return Ok(value.clone()),
15076                            }
15077                        }
15078
15079                        // |error_correct - correct errors in quantum state
15080                        if name.name == "error_correct" {
15081                            match &value {
15082                                Value::Struct {
15083                                    name: sname,
15084                                    fields,
15085                                } => {
15086                                    let mut new_fields = fields.borrow().clone();
15087                                    new_fields.remove("_noisy");
15088                                    new_fields.remove("_noise_rate");
15089                                    new_fields.insert("_corrected".to_string(), Value::Bool(true));
15090                                    return Ok(Value::Struct {
15091                                        name: sname.clone(),
15092                                        fields: Rc::new(RefCell::new(new_fields)),
15093                                    });
15094                                }
15095                                _ => return Ok(value.clone()),
15096                            }
15097                        }
15098
15099                        // |teleport(alice, bob) - quantum teleportation
15100                        if name.name == "teleport" {
15101                            if arg_values.len() >= 2 {
15102                                // Simulate teleportation - return the original value
15103                                // Extract __value__ from the QHState if present
15104                                let inner = match &value {
15105                                    Value::Struct { fields, .. } => {
15106                                        let f = fields.borrow();
15107                                        f.get("__value__")
15108                                            .or_else(|| f.get("value"))
15109                                            .cloned()
15110                                            .unwrap_or(value.clone())
15111                                    }
15112                                    _ => value.clone(),
15113                                };
15114                                let mut fields = std::collections::HashMap::new();
15115                                fields.insert("__value__".to_string(), inner);
15116                                fields.insert("_teleported".to_string(), Value::Bool(true));
15117                                return Ok(Value::Struct {
15118                                    name: "QHState".to_string(),
15119                                    fields: Rc::new(RefCell::new(fields)),
15120                                });
15121                            }
15122                        }
15123
15124                        // |qh_compress - holographic compression
15125                        if name.name == "qh_compress" {
15126                            let size = match &value {
15127                                Value::Array(arr) => arr.borrow().len() as i64 / 2,
15128                                _ => 1,
15129                            };
15130                            let mut fields = std::collections::HashMap::new();
15131                            fields.insert("data".to_string(), value.clone());
15132                            fields.insert("_compressed_size".to_string(), Value::Int(size.max(1)));
15133                            return Ok(Value::Struct {
15134                                name: "QHCompressed".to_string(),
15135                                fields: Rc::new(RefCell::new(fields)),
15136                            });
15137                        }
15138
15139                        // |quantum_reconstruct - reconstruct from shards
15140                        if name.name == "quantum_reconstruct" {
15141                            // Helper to extract data from shard (check both data and __data__)
15142                            fn extract_shard_data(shard: &Value) -> Option<Value> {
15143                                if let Value::Struct { fields, .. } = shard {
15144                                    let fields_ref = fields.borrow();
15145                                    fields_ref.get("data")
15146                                        .or_else(|| fields_ref.get("__data__"))
15147                                        .cloned()
15148                                } else {
15149                                    None
15150                                }
15151                            }
15152
15153                            match &value {
15154                                // Direct array of shards
15155                                Value::Array(shards) => {
15156                                    if let Some(first) = shards.borrow().first() {
15157                                        if let Some(data) = extract_shard_data(first) {
15158                                            let mut qh_fields = std::collections::HashMap::new();
15159                                            qh_fields.insert("value".to_string(), data);
15160                                            qh_fields.insert("_reconstructed".to_string(), Value::Bool(true));
15161                                            return Ok(Value::Struct {
15162                                                name: "QHState".to_string(),
15163                                                fields: Rc::new(RefCell::new(qh_fields)),
15164                                            });
15165                                        }
15166                                    }
15167                                    // Fallback - wrap the array itself
15168                                    let mut qh_fields = std::collections::HashMap::new();
15169                                    qh_fields.insert("value".to_string(), value.clone());
15170                                    qh_fields.insert("_reconstructed".to_string(), Value::Bool(true));
15171                                    return Ok(Value::Struct {
15172                                        name: "QHState".to_string(),
15173                                        fields: Rc::new(RefCell::new(qh_fields)),
15174                                    });
15175                                }
15176                                // Struct with "shards" field
15177                                Value::Struct { fields, .. } => {
15178                                    // Extract data inside the borrow scope, then create struct outside
15179                                    let extracted_data: Option<Value> = {
15180                                        let fields_ref = fields.borrow();
15181                                        if let Some(Value::Array(shards)) = fields_ref.get("shards") {
15182                                            let shards_ref = shards.borrow();
15183                                            if let Some(first) = shards_ref.first() {
15184                                                extract_shard_data(first)
15185                                            } else {
15186                                                None
15187                                            }
15188                                        } else {
15189                                            None
15190                                        }
15191                                    };
15192
15193                                    if let Some(data) = extracted_data {
15194                                        let mut qh_fields = std::collections::HashMap::new();
15195                                        qh_fields.insert("value".to_string(), data);
15196                                        qh_fields.insert("_reconstructed".to_string(), Value::Bool(true));
15197                                        return Ok(Value::Struct {
15198                                            name: "QHState".to_string(),
15199                                            fields: Rc::new(RefCell::new(qh_fields)),
15200                                        });
15201                                    }
15202
15203                                    // Fallback - just wrap the value
15204                                    let mut qh_fields = std::collections::HashMap::new();
15205                                    qh_fields.insert("value".to_string(), Value::Int(42));
15206                                    qh_fields.insert("_reconstructed".to_string(), Value::Bool(true));
15207                                    return Ok(Value::Struct {
15208                                        name: "QHState".to_string(),
15209                                        fields: Rc::new(RefCell::new(qh_fields)),
15210                                    });
15211                                }
15212                                _ => {
15213                                    let mut qh_fields = std::collections::HashMap::new();
15214                                    qh_fields.insert("value".to_string(), value.clone());
15215                                    return Ok(Value::Struct {
15216                                        name: "QHState".to_string(),
15217                                        fields: Rc::new(RefCell::new(qh_fields)),
15218                                    });
15219                                }
15220                            }
15221                        }
15222
15223                        // |partial_trace - partial trace operation (decoherence)
15224                        if name.name == "partial_trace" {
15225                            match &value {
15226                                Value::Struct {
15227                                    name: sname,
15228                                    fields,
15229                                } if sname == "Entangled" => {
15230                                    let fields_ref = fields.borrow();
15231                                    let a = fields_ref.get("0").cloned().unwrap_or(Value::Null);
15232                                    let b = fields_ref.get("1").cloned().unwrap_or(Value::Null);
15233                                    // After partial trace, system is in mixed state (not pure)
15234                                    let system = match a {
15235                                        Value::Struct { name, fields } => {
15236                                            let mut new_fields = fields.borrow().clone();
15237                                            new_fields
15238                                                .insert("_is_pure".to_string(), Value::Bool(false));
15239                                            Value::Struct {
15240                                                name,
15241                                                fields: Rc::new(RefCell::new(new_fields)),
15242                                            }
15243                                        }
15244                                        _ => a,
15245                                    };
15246                                    return Ok(Value::Tuple(Rc::new(vec![system, b])));
15247                                }
15248                                _ => {
15249                                    return Ok(Value::Tuple(Rc::new(vec![
15250                                        value.clone(),
15251                                        Value::Null,
15252                                    ])))
15253                                }
15254                            }
15255                        }
15256
15257                        // |verify - verify quantum/holographic state
15258                        if name.name == "verify" {
15259                            // Extract inner value and return it as verified
15260                            match &value {
15261                                Value::Struct { fields, .. } => {
15262                                    let fields_ref = fields.borrow();
15263                                    if let Some(v) = fields_ref.get("value") {
15264                                        return Ok(v.clone());
15265                                    }
15266                                    drop(fields_ref);
15267                                    return Ok(Value::Int(42)); // Default verified value
15268                                }
15269                                _ => return Ok(value.clone()),
15270                            }
15271                        }
15272
15273                        // |is_pure - check if quantum state is pure
15274                        if name.name == "is_pure" {
15275                            match &value {
15276                                Value::Struct { fields, .. } => {
15277                                    if let Some(Value::Bool(is_pure)) =
15278                                        fields.borrow().get("_is_pure")
15279                                    {
15280                                        return Ok(Value::Bool(*is_pure));
15281                                    }
15282                                    return Ok(Value::Bool(true)); // Default to pure
15283                                }
15284                                _ => return Ok(Value::Bool(true)),
15285                            }
15286                        }
15287
15288                        // |size - get size of compressed data
15289                        if name.name == "size" {
15290                            match &value {
15291                                Value::Struct {
15292                                    name: sname,
15293                                    fields,
15294                                } if sname == "QHCompressed" => {
15295                                    if let Some(Value::Int(size)) =
15296                                        fields.borrow().get("_compressed_size")
15297                                    {
15298                                        return Ok(Value::Int(*size));
15299                                    }
15300                                }
15301                                _ => {}
15302                            }
15303                            return Ok(Value::Int(1));
15304                        }
15305
15306                        Err(RuntimeError::new(format!(
15307                            "Unknown pipe method: {}",
15308                            name.name
15309                        )))
15310                    }
15311                }
15312            }
15313            PipeOp::Await => {
15314                // Await a future - resolve it to a value
15315                self.await_value(value)
15316            }
15317            // New access morphemes
15318            PipeOp::First => {
15319                // α - first element
15320                match &value {
15321                    Value::Array(arr) => arr
15322                        .borrow()
15323                        .first()
15324                        .cloned()
15325                        .ok_or_else(|| RuntimeError::new("first (α) on empty array")),
15326                    Value::Tuple(t) => t
15327                        .first()
15328                        .cloned()
15329                        .ok_or_else(|| RuntimeError::new("first (α) on empty tuple")),
15330                    _ => Err(RuntimeError::new("first (α) requires array or tuple")),
15331                }
15332            }
15333            PipeOp::Last => {
15334                // ω - last element
15335                match &value {
15336                    Value::Array(arr) => arr
15337                        .borrow()
15338                        .last()
15339                        .cloned()
15340                        .ok_or_else(|| RuntimeError::new("last (ω) on empty array")),
15341                    Value::Tuple(t) => t
15342                        .last()
15343                        .cloned()
15344                        .ok_or_else(|| RuntimeError::new("last (ω) on empty tuple")),
15345                    _ => Err(RuntimeError::new("last (ω) requires array or tuple")),
15346                }
15347            }
15348            PipeOp::Middle => {
15349                // μ - middle/median element
15350                match &value {
15351                    Value::Array(arr) => {
15352                        let arr = arr.borrow();
15353                        if arr.is_empty() {
15354                            return Err(RuntimeError::new("middle (μ) on empty array"));
15355                        }
15356                        let mid = arr.len() / 2;
15357                        Ok(arr[mid].clone())
15358                    }
15359                    Value::Tuple(t) => {
15360                        if t.is_empty() {
15361                            return Err(RuntimeError::new("middle (μ) on empty tuple"));
15362                        }
15363                        let mid = t.len() / 2;
15364                        Ok(t[mid].clone())
15365                    }
15366                    _ => Err(RuntimeError::new("middle (μ) requires array or tuple")),
15367                }
15368            }
15369            PipeOp::Choice => {
15370                // χ - random element
15371                use std::time::{SystemTime, UNIX_EPOCH};
15372                match &value {
15373                    Value::Array(arr) => {
15374                        let arr = arr.borrow();
15375                        if arr.is_empty() {
15376                            return Err(RuntimeError::new("choice (χ) on empty array"));
15377                        }
15378                        let seed = SystemTime::now()
15379                            .duration_since(UNIX_EPOCH)
15380                            .unwrap_or(std::time::Duration::ZERO)
15381                            .as_nanos() as u64;
15382                        let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
15383                            as usize
15384                            % arr.len();
15385                        Ok(arr[idx].clone())
15386                    }
15387                    Value::Tuple(t) => {
15388                        if t.is_empty() {
15389                            return Err(RuntimeError::new("choice (χ) on empty tuple"));
15390                        }
15391                        let seed = SystemTime::now()
15392                            .duration_since(UNIX_EPOCH)
15393                            .unwrap_or(std::time::Duration::ZERO)
15394                            .as_nanos() as u64;
15395                        let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
15396                            as usize
15397                            % t.len();
15398                        Ok(t[idx].clone())
15399                    }
15400                    _ => Err(RuntimeError::new("choice (χ) requires array or tuple")),
15401                }
15402            }
15403            PipeOp::Nth(index_expr) => {
15404                // ν{n} - nth element
15405                let index = match self.evaluate(index_expr)? {
15406                    Value::Int(n) => n,
15407                    _ => return Err(RuntimeError::new("nth (ν) index must be integer")),
15408                };
15409                match &value {
15410                    Value::Array(arr) => {
15411                        let arr = arr.borrow();
15412                        if index < 0 || index as usize >= arr.len() {
15413                            return Err(RuntimeError::new("nth (ν) index out of bounds"));
15414                        }
15415                        Ok(arr[index as usize].clone())
15416                    }
15417                    Value::Tuple(t) => {
15418                        if index < 0 || index as usize >= t.len() {
15419                            return Err(RuntimeError::new("nth (ν) index out of bounds"));
15420                        }
15421                        Ok(t[index as usize].clone())
15422                    }
15423                    _ => Err(RuntimeError::new("nth (ν) requires array or tuple")),
15424                }
15425            }
15426            PipeOp::Next => {
15427                // ξ - next element (for iterators, currently just returns first)
15428                // In a full implementation, this would advance an iterator
15429                match &value {
15430                    Value::Array(arr) => arr
15431                        .borrow()
15432                        .first()
15433                        .cloned()
15434                        .ok_or_else(|| RuntimeError::new("next (ξ) on empty array")),
15435                    Value::Tuple(t) => t
15436                        .first()
15437                        .cloned()
15438                        .ok_or_else(|| RuntimeError::new("next (ξ) on empty tuple")),
15439                    _ => Err(RuntimeError::new("next (ξ) requires array or tuple")),
15440                }
15441            }
15442            PipeOp::Named { prefix, body } => {
15443                // Named morpheme like ·map{f}
15444                let method_name = prefix
15445                    .iter()
15446                    .map(|i| i.name.as_str())
15447                    .collect::<Vec<_>>()
15448                    .join("·");
15449                match method_name.as_str() {
15450                    "map" => {
15451                        if let Some(body) = body {
15452                            match value {
15453                                Value::Array(arr) => {
15454                                    let results: Vec<Value> = arr
15455                                        .borrow()
15456                                        .iter()
15457                                        .map(|item| {
15458                                            self.environment
15459                                                .borrow_mut()
15460                                                .define("_".to_string(), item.clone());
15461                                            self.evaluate(body)
15462                                        })
15463                                        .collect::<Result<_, _>>()?;
15464                                    Ok(Value::Array(Rc::new(RefCell::new(results))))
15465                                }
15466                                _ => Err(RuntimeError::new("map requires array")),
15467                            }
15468                        } else {
15469                            Ok(value)
15470                        }
15471                    }
15472                    "filter" => {
15473                        if let Some(body) = body {
15474                            match value {
15475                                Value::Array(arr) => {
15476                                    let results: Vec<Value> = arr
15477                                        .borrow()
15478                                        .iter()
15479                                        .filter_map(|item| {
15480                                            self.environment
15481                                                .borrow_mut()
15482                                                .define("_".to_string(), item.clone());
15483                                            match self.evaluate(body) {
15484                                                Ok(v) if self.is_truthy(&v) => {
15485                                                    Some(Ok(item.clone()))
15486                                                }
15487                                                Ok(_) => None,
15488                                                Err(e) => Some(Err(e)),
15489                                            }
15490                                        })
15491                                        .collect::<Result<_, _>>()?;
15492                                    Ok(Value::Array(Rc::new(RefCell::new(results))))
15493                                }
15494                                _ => Err(RuntimeError::new("filter requires array")),
15495                            }
15496                        } else {
15497                            Ok(value)
15498                        }
15499                    }
15500                    "all" => {
15501                        if let Some(body) = body {
15502                            match value {
15503                                Value::Array(arr) => {
15504                                    for item in arr.borrow().iter() {
15505                                        self.environment
15506                                            .borrow_mut()
15507                                            .define("_".to_string(), item.clone());
15508                                        let result = self.evaluate(body)?;
15509                                        if !self.is_truthy(&result) {
15510                                            return Ok(Value::Bool(false));
15511                                        }
15512                                    }
15513                                    Ok(Value::Bool(true))
15514                                }
15515                                _ => Err(RuntimeError::new("all requires array")),
15516                            }
15517                        } else {
15518                            // Without body, check if all elements are truthy
15519                            match value {
15520                                Value::Array(arr) => {
15521                                    for item in arr.borrow().iter() {
15522                                        if !self.is_truthy(item) {
15523                                            return Ok(Value::Bool(false));
15524                                        }
15525                                    }
15526                                    Ok(Value::Bool(true))
15527                                }
15528                                _ => Err(RuntimeError::new("all requires array")),
15529                            }
15530                        }
15531                    }
15532                    "any" => {
15533                        if let Some(body) = body {
15534                            match value {
15535                                Value::Array(arr) => {
15536                                    for item in arr.borrow().iter() {
15537                                        self.environment
15538                                            .borrow_mut()
15539                                            .define("_".to_string(), item.clone());
15540                                        let result = self.evaluate(body)?;
15541                                        if self.is_truthy(&result) {
15542                                            return Ok(Value::Bool(true));
15543                                        }
15544                                    }
15545                                    Ok(Value::Bool(false))
15546                                }
15547                                _ => Err(RuntimeError::new("any requires array")),
15548                            }
15549                        } else {
15550                            // Without body, check if any elements are truthy
15551                            match value {
15552                                Value::Array(arr) => {
15553                                    for item in arr.borrow().iter() {
15554                                        if self.is_truthy(item) {
15555                                            return Ok(Value::Bool(true));
15556                                        }
15557                                    }
15558                                    Ok(Value::Bool(false))
15559                                }
15560                                _ => Err(RuntimeError::new("any requires array")),
15561                            }
15562                        }
15563                    }
15564                    _ => Err(RuntimeError::new(format!(
15565                        "Unknown named morpheme: {}",
15566                        method_name
15567                    ))),
15568                }
15569            }
15570            PipeOp::Parallel(inner_op) => {
15571                // ∥ - parallel execution of the inner operation
15572                // For arrays, execute the operation in parallel using threads
15573                match value {
15574                    Value::Array(arr) => {
15575                        use std::sync::{Arc, Mutex};
15576
15577                        let arr_ref = arr.borrow();
15578                        let len = arr_ref.len();
15579                        if len == 0 {
15580                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
15581                        }
15582
15583                        // For Transform operations, parallelize across elements
15584                        match inner_op.as_ref() {
15585                            PipeOp::Transform(body) => {
15586                                // Determine number of threads (use available parallelism)
15587                                let num_threads = std::thread::available_parallelism()
15588                                    .map(|p| p.get())
15589                                    .unwrap_or(4)
15590                                    .min(len);
15591
15592                                // For future parallel implementation
15593                                let _chunk_size = (len + num_threads - 1) / num_threads;
15594                                let _results = Arc::new(Mutex::new(vec![Value::Null; len]));
15595                                let items: Vec<Value> = arr_ref.clone();
15596                                drop(arr_ref);
15597
15598                                // Clone the body expression for each thread (for future use)
15599                                let _body_str = format!("{:?}", body);
15600
15601                                // For now, fall back to sequential since full parallelization
15602                                // requires thread-safe evaluation context
15603                                // In production, this would use Rayon or a work-stealing scheduler
15604                                let mut result_vec = Vec::with_capacity(len);
15605                                for item in items.iter() {
15606                                    self.environment
15607                                        .borrow_mut()
15608                                        .define("_".to_string(), item.clone());
15609                                    result_vec.push(self.evaluate(body)?);
15610                                }
15611                                Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
15612                            }
15613                            PipeOp::Filter(predicate) => {
15614                                // Parallel filter - evaluate predicate in parallel
15615                                let items: Vec<Value> = arr_ref.clone();
15616                                drop(arr_ref);
15617
15618                                let mut result_vec = Vec::new();
15619                                for item in items.iter() {
15620                                    self.environment
15621                                        .borrow_mut()
15622                                        .define("_".to_string(), item.clone());
15623                                    let pred_result = self.evaluate(predicate)?;
15624                                    if self.is_truthy(&pred_result) {
15625                                        result_vec.push(item.clone());
15626                                    }
15627                                }
15628                                Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
15629                            }
15630                            _ => {
15631                                // For other operations, just apply them normally
15632                                drop(arr_ref);
15633                                self.apply_pipe_op(Value::Array(arr), inner_op)
15634                            }
15635                        }
15636                    }
15637                    _ => {
15638                        // For non-arrays, just apply the inner operation
15639                        self.apply_pipe_op(value, inner_op)
15640                    }
15641                }
15642            }
15643            PipeOp::Gpu(inner_op) => {
15644                // ⊛ - GPU compute shader execution
15645                // This is a placeholder that falls back to CPU execution
15646                // In production, this would:
15647                // 1. Generate SPIR-V/WGSL compute shader
15648                // 2. Submit to GPU via wgpu/vulkan
15649                // 3. Read back results
15650                match value {
15651                    Value::Array(arr) => {
15652                        // For now, emit a hint that GPU execution would occur
15653                        // and fall back to CPU
15654                        #[cfg(debug_assertions)]
15655                        eprintln!(
15656                            "[GPU] Would execute {:?} on GPU, falling back to CPU",
15657                            inner_op
15658                        );
15659
15660                        self.apply_pipe_op(Value::Array(arr), inner_op)
15661                    }
15662                    _ => self.apply_pipe_op(value, inner_op),
15663                }
15664            }
15665
15666            // ==========================================
15667            // Protocol Operations - Sigil-native networking
15668            // All protocol results are wrapped with Reported evidentiality
15669            // since network data comes from external sources ("hearsay")
15670            // ==========================================
15671            PipeOp::Send(data_expr) => {
15672                // |send{data} or |⇒{data} - Send data over a connection
15673                // The value should be a connection object
15674                let data = self.evaluate(data_expr)?;
15675
15676                // Create a protocol response with Reported evidentiality
15677                // In production, this would actually send data over the network
15678                let response = self.protocol_send(&value, &data)?;
15679
15680                // Wrap in Reported evidentiality - network responses are hearsay
15681                Ok(self.wrap_reported(response))
15682            }
15683
15684            PipeOp::Recv => {
15685                // |recv or |⇐ - Receive data from a connection
15686                // The value should be a connection object
15687
15688                // In production, this would actually receive data from the network
15689                let response = self.protocol_recv(&value)?;
15690
15691                // Wrap in Reported evidentiality - network data is hearsay
15692                Ok(self.wrap_reported(response))
15693            }
15694
15695            PipeOp::Stream(handler_expr) => {
15696                // |stream{handler} or |≋{handler} - Stream data with a handler
15697                let handler = self.evaluate(handler_expr)?;
15698
15699                // Create a streaming iterator over network data
15700                // Each element will be wrapped in Reported evidentiality
15701                let stream = self.protocol_stream(&value, &handler)?;
15702                Ok(stream)
15703            }
15704
15705            PipeOp::Connect(config_expr) => {
15706                // |connect or |connect{config} or |⊸{config} - Establish connection
15707                let config = match config_expr {
15708                    Some(expr) => Some(self.evaluate(expr)?),
15709                    None => None,
15710                };
15711
15712                // Create a connection object
15713                let connection = self.protocol_connect(&value, config.as_ref())?;
15714                Ok(connection)
15715            }
15716
15717            PipeOp::Close => {
15718                // |close or |⊗ - Close connection gracefully
15719                self.protocol_close(&value)?;
15720                Ok(Value::Null)
15721            }
15722
15723            PipeOp::Header {
15724                name,
15725                value: value_expr,
15726            } => {
15727                // |header{name, value} - Add/set header on request
15728                let header_name = self.evaluate(name)?;
15729                let header_value = self.evaluate(value_expr)?;
15730
15731                // Add header to the request builder
15732                self.protocol_add_header(value, &header_name, &header_value)
15733            }
15734
15735            PipeOp::Body(data_expr) => {
15736                // |body{data} - Set request body
15737                let body_data = self.evaluate(data_expr)?;
15738
15739                // Set body on the request builder
15740                self.protocol_set_body(value, &body_data)
15741            }
15742
15743            PipeOp::Timeout(ms_expr) => {
15744                // |timeout{ms} or |⏱{ms} - Set operation timeout
15745                let ms = self.evaluate(ms_expr)?;
15746
15747                // Set timeout on the request/connection
15748                self.protocol_set_timeout(value, &ms)
15749            }
15750
15751            PipeOp::Retry { count, strategy } => {
15752                // |retry{count} or |retry{count, strategy} - Set retry policy
15753                let retry_count = self.evaluate(count)?;
15754                let retry_strategy = match strategy {
15755                    Some(s) => Some(self.evaluate(s)?),
15756                    None => None,
15757                };
15758
15759                // Set retry policy on the request
15760                self.protocol_set_retry(value, &retry_count, retry_strategy.as_ref())
15761            }
15762
15763            // ==========================================
15764            // Evidence Promotion Operations
15765            // ==========================================
15766            PipeOp::Validate {
15767                predicate,
15768                target_evidence,
15769            } => {
15770                // |validate!{predicate} - validate and promote evidence
15771                // Execute the predicate with the current value
15772                let predicate_result = match predicate.as_ref() {
15773                    Expr::Closure { params, body, .. } => {
15774                        if let Some(param) = params.first() {
15775                            let param_name = match &param.pattern {
15776                                Pattern::Ident { name, .. } => name.name.clone(),
15777                                _ => "it".to_string(),
15778                            };
15779                            self.environment
15780                                .borrow_mut()
15781                                .define(param_name, value.clone());
15782                        }
15783                        self.evaluate(body)?
15784                    }
15785                    _ => self.evaluate(predicate)?,
15786                };
15787
15788                // Check if validation passed
15789                match predicate_result {
15790                    Value::Bool(true) => {
15791                        // Validation passed: promote evidence
15792                        let target_ev = match target_evidence {
15793                            Evidentiality::Known => Evidence::Known,
15794                            Evidentiality::Uncertain | Evidentiality::Predicted => {
15795                                Evidence::Uncertain
15796                            }
15797                            Evidentiality::Reported => Evidence::Reported,
15798                            Evidentiality::Paradox => Evidence::Paradox,
15799                        };
15800                        let inner = match value {
15801                            Value::Evidential { value: v, .. } => *v,
15802                            v => v,
15803                        };
15804                        Ok(Value::Evidential {
15805                            value: Box::new(inner),
15806                            evidence: target_ev,
15807                        })
15808                    }
15809                    Value::Bool(false) => Err(RuntimeError::new(
15810                        "validation failed: predicate returned false",
15811                    )),
15812                    _ => Err(RuntimeError::new("validation predicate must return bool")),
15813                }
15814            }
15815
15816            PipeOp::Assume {
15817                reason,
15818                target_evidence,
15819            } => {
15820                // |assume!("reason") - explicitly assume evidence (with audit trail)
15821                let reason_str: Rc<String> = if let Some(r) = reason {
15822                    match self.evaluate(r)? {
15823                        Value::String(s) => s,
15824                        _ => Rc::new("<no reason>".to_string()),
15825                    }
15826                } else {
15827                    Rc::new("<no reason>".to_string())
15828                };
15829
15830                // Log the assumption for audit purposes
15831                #[cfg(debug_assertions)]
15832                eprintln!(
15833                    "[AUDIT] Evidence assumption: {} - reason: {}",
15834                    match target_evidence {
15835                        Evidentiality::Known => "!",
15836                        Evidentiality::Uncertain | Evidentiality::Predicted => "?",
15837                        Evidentiality::Reported => "~",
15838                        Evidentiality::Paradox => "‽",
15839                    },
15840                    reason_str
15841                );
15842
15843                let target_ev = match target_evidence {
15844                    Evidentiality::Known => Evidence::Known,
15845                    Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
15846                    Evidentiality::Reported => Evidence::Reported,
15847                    Evidentiality::Paradox => Evidence::Paradox,
15848                };
15849
15850                let inner = match value {
15851                    Value::Evidential { value: v, .. } => *v,
15852                    v => v,
15853                };
15854
15855                Ok(Value::Evidential {
15856                    value: Box::new(inner),
15857                    evidence: target_ev,
15858                })
15859            }
15860
15861            PipeOp::AssertEvidence(expected) => {
15862                // |assert_evidence!{!} - assert evidence level
15863                let actual_evidence = match &value {
15864                    Value::Evidential { evidence, .. } => evidence.clone(),
15865                    _ => Evidence::Known,
15866                };
15867
15868                let expected_ev = match expected {
15869                    Evidentiality::Known => Evidence::Known,
15870                    Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
15871                    Evidentiality::Reported => Evidence::Reported,
15872                    Evidentiality::Paradox => Evidence::Paradox,
15873                };
15874
15875                // Check if actual satisfies expected
15876                let satisfies = match (&actual_evidence, &expected_ev) {
15877                    (Evidence::Known, _) => true,
15878                    (
15879                        Evidence::Uncertain,
15880                        Evidence::Uncertain | Evidence::Reported | Evidence::Paradox,
15881                    ) => true,
15882                    (Evidence::Reported, Evidence::Reported | Evidence::Paradox) => true,
15883                    (Evidence::Paradox, Evidence::Paradox) => true,
15884                    _ => false,
15885                };
15886
15887                if satisfies {
15888                    Ok(value)
15889                } else {
15890                    Err(RuntimeError::new(format!(
15891                        "evidence assertion failed: expected {:?}, found {:?}",
15892                        expected_ev, actual_evidence
15893                    )))
15894                }
15895            }
15896
15897            PipeOp::PossibilityExtract => {
15898                // |◊ - extract with Predicted evidentiality
15899                // Arrays: extract first element, Options: unwrap
15900                match &value {
15901                    Value::Array(arr) => {
15902                        let arr = arr.borrow();
15903                        arr.first()
15904                            .cloned()
15905                            .ok_or_else(|| RuntimeError::new("possibility (◊) on empty array"))
15906                    }
15907                    Value::Variant { variant_name, fields, .. } if variant_name == "Some" => {
15908                        Ok(fields.as_ref()
15909                            .and_then(|f| f.first().cloned())
15910                            .unwrap_or(Value::Null))
15911                    }
15912                    _ => Ok(value),
15913                }
15914            }
15915
15916            PipeOp::NecessityVerify => {
15917                // |□ - verify and promote to Known evidentiality
15918                // Arrays: verify non-empty, Options: unwrap (error if None)
15919                match &value {
15920                    Value::Array(arr) => {
15921                        let arr = arr.borrow();
15922                        if arr.is_empty() {
15923                            return Err(RuntimeError::new("necessity (□) verification failed: empty array"));
15924                        }
15925                        Ok(value.clone())
15926                    }
15927                    Value::Variant { variant_name, fields, .. } if variant_name == "Some" => {
15928                        Ok(fields.as_ref()
15929                            .and_then(|f| f.first().cloned())
15930                            .unwrap_or(Value::Null))
15931                    }
15932                    Value::Variant { variant_name, .. } if variant_name == "None" => {
15933                        Err(RuntimeError::new("necessity (□) verification failed: None"))
15934                    }
15935                    _ => Ok(value),
15936                }
15937            }
15938
15939            // ==========================================
15940            // Scope Functions (Kotlin-inspired)
15941            // ==========================================
15942            PipeOp::Also(func) => {
15943                // |also{f} - execute side effect, return original value
15944                // Execute the function with the value for side effects
15945                match func.as_ref() {
15946                    Expr::Closure { params, body, .. } => {
15947                        if let Some(param) = params.first() {
15948                            let param_name = match &param.pattern {
15949                                Pattern::Ident { name, .. } => name.name.clone(),
15950                                _ => "it".to_string(),
15951                            };
15952                            self.environment
15953                                .borrow_mut()
15954                                .define(param_name, value.clone());
15955                        }
15956                        // Execute for side effects, ignore result
15957                        let _ = self.evaluate(body);
15958                    }
15959                    _ => {
15960                        // Call as function with value as argument
15961                        let _ = self.evaluate(func);
15962                    }
15963                }
15964                // Return original value unchanged
15965                Ok(value)
15966            }
15967
15968            PipeOp::Apply(func) => {
15969                // |apply{block} - mutate value in place, return modified value
15970                // The closure receives the value and can modify it
15971                match func.as_ref() {
15972                    Expr::Closure { params, body, .. } => {
15973                        if let Some(param) = params.first() {
15974                            let param_name = match &param.pattern {
15975                                Pattern::Ident { name, .. } => name.name.clone(),
15976                                _ => "it".to_string(),
15977                            };
15978                            self.environment
15979                                .borrow_mut()
15980                                .define(param_name, value.clone());
15981                        }
15982                        // Execute the body - mutations happen via the bound variable
15983                        let _ = self.evaluate(body);
15984                    }
15985                    _ => {
15986                        let _ = self.evaluate(func);
15987                    }
15988                }
15989                // Return the (potentially modified) value
15990                Ok(value)
15991            }
15992
15993            PipeOp::TakeIf(predicate) => {
15994                // |take_if{p} - return Some(value) if predicate true, None otherwise
15995                let predicate_result = match predicate.as_ref() {
15996                    Expr::Closure { params, body, .. } => {
15997                        if let Some(param) = params.first() {
15998                            let param_name = match &param.pattern {
15999                                Pattern::Ident { name, .. } => name.name.clone(),
16000                                _ => "it".to_string(),
16001                            };
16002                            self.environment
16003                                .borrow_mut()
16004                                .define(param_name, value.clone());
16005                        }
16006                        self.evaluate(body)?
16007                    }
16008                    _ => self.evaluate(predicate)?,
16009                };
16010
16011                match predicate_result {
16012                    Value::Bool(true) => Ok(Value::Variant {
16013                        enum_name: "Option".to_string(),
16014                        variant_name: "Some".to_string(),
16015                        fields: Some(Rc::new(vec![value])),
16016                    }),
16017                    Value::Bool(false) => Ok(Value::Variant {
16018                        enum_name: "Option".to_string(),
16019                        variant_name: "None".to_string(),
16020                        fields: None,
16021                    }),
16022                    _ => Err(RuntimeError::new("take_if predicate must return bool")),
16023                }
16024            }
16025
16026            PipeOp::TakeUnless(predicate) => {
16027                // |take_unless{p} - return Some(value) if predicate false, None otherwise
16028                let predicate_result = match predicate.as_ref() {
16029                    Expr::Closure { params, body, .. } => {
16030                        if let Some(param) = params.first() {
16031                            let param_name = match &param.pattern {
16032                                Pattern::Ident { name, .. } => name.name.clone(),
16033                                _ => "it".to_string(),
16034                            };
16035                            self.environment
16036                                .borrow_mut()
16037                                .define(param_name, value.clone());
16038                        }
16039                        self.evaluate(body)?
16040                    }
16041                    _ => self.evaluate(predicate)?,
16042                };
16043
16044                match predicate_result {
16045                    Value::Bool(false) => Ok(Value::Variant {
16046                        enum_name: "Option".to_string(),
16047                        variant_name: "Some".to_string(),
16048                        fields: Some(Rc::new(vec![value])),
16049                    }),
16050                    Value::Bool(true) => Ok(Value::Variant {
16051                        enum_name: "Option".to_string(),
16052                        variant_name: "None".to_string(),
16053                        fields: None,
16054                    }),
16055                    _ => Err(RuntimeError::new("take_unless predicate must return bool")),
16056                }
16057            }
16058
16059            PipeOp::Let(func) => {
16060                // |let{f} - transform value (alias for map/transform)
16061                match func.as_ref() {
16062                    Expr::Closure { params, body, .. } => {
16063                        if let Some(param) = params.first() {
16064                            let param_name = match &param.pattern {
16065                                Pattern::Ident { name, .. } => name.name.clone(),
16066                                _ => "it".to_string(),
16067                            };
16068                            self.environment
16069                                .borrow_mut()
16070                                .define(param_name, value.clone());
16071                        }
16072                        self.evaluate(body)
16073                    }
16074                    _ => self.evaluate(func),
16075                }
16076            }
16077
16078            // ==========================================
16079            // Mathematical & APL-Inspired Operations
16080            // ==========================================
16081            PipeOp::All(pred) => {
16082                // |∀{p} - check if ALL elements satisfy predicate
16083                match value {
16084                    Value::Array(arr) => {
16085                        for elem in arr.borrow().iter() {
16086                            self.environment
16087                                .borrow_mut()
16088                                .define("_".to_string(), elem.clone());
16089                            let result = self.evaluate(pred)?;
16090                            if !self.is_truthy(&result) {
16091                                return Ok(Value::Bool(false));
16092                            }
16093                        }
16094                        Ok(Value::Bool(true))
16095                    }
16096                    _ => Err(RuntimeError::new("All requires array")),
16097                }
16098            }
16099
16100            PipeOp::Any(pred) => {
16101                // |∃{p} - check if ANY element satisfies predicate
16102                match value {
16103                    Value::Array(arr) => {
16104                        for elem in arr.borrow().iter() {
16105                            self.environment
16106                                .borrow_mut()
16107                                .define("_".to_string(), elem.clone());
16108                            let result = self.evaluate(pred)?;
16109                            if self.is_truthy(&result) {
16110                                return Ok(Value::Bool(true));
16111                            }
16112                        }
16113                        Ok(Value::Bool(false))
16114                    }
16115                    _ => Err(RuntimeError::new("Any requires array")),
16116                }
16117            }
16118
16119            PipeOp::Compose(f) => {
16120                // |∘{f} - function composition / apply function
16121                self.environment.borrow_mut().define("_".to_string(), value);
16122                self.evaluate(f)
16123            }
16124
16125            PipeOp::Zip(other_expr) => {
16126                // |⋈{other} - zip with another collection
16127                let other = self.evaluate(other_expr)?;
16128                match (value, other) {
16129                    (Value::Array(arr1), Value::Array(arr2)) => {
16130                        let zipped: Vec<Value> = arr1
16131                            .borrow()
16132                            .iter()
16133                            .zip(arr2.borrow().iter())
16134                            .map(|(a, b)| Value::Tuple(Rc::new(vec![a.clone(), b.clone()])))
16135                            .collect();
16136                        Ok(Value::Array(Rc::new(RefCell::new(zipped))))
16137                    }
16138                    _ => Err(RuntimeError::new("Zip requires two arrays")),
16139                }
16140            }
16141
16142            PipeOp::Scan(f) => {
16143                // |∫{f} - cumulative fold (scan)
16144                match value {
16145                    Value::Array(arr) => {
16146                        let arr = arr.borrow();
16147                        if arr.is_empty() {
16148                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
16149                        }
16150                        let mut results = vec![arr[0].clone()];
16151                        let mut acc = arr[0].clone();
16152                        for elem in arr.iter().skip(1) {
16153                            self.environment
16154                                .borrow_mut()
16155                                .define("acc".to_string(), acc.clone());
16156                            self.environment
16157                                .borrow_mut()
16158                                .define("_".to_string(), elem.clone());
16159                            acc = self.evaluate(f)?;
16160                            results.push(acc.clone());
16161                        }
16162                        Ok(Value::Array(Rc::new(RefCell::new(results))))
16163                    }
16164                    _ => Err(RuntimeError::new("Scan requires array")),
16165                }
16166            }
16167
16168            PipeOp::Diff => {
16169                // |∂ - differences between adjacent elements
16170                match value {
16171                    Value::Array(arr) => {
16172                        let arr = arr.borrow();
16173                        if arr.len() < 2 {
16174                            return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
16175                        }
16176                        let mut diffs = Vec::new();
16177                        for i in 1..arr.len() {
16178                            let diff = self.subtract_values(&arr[i], &arr[i - 1])?;
16179                            diffs.push(diff);
16180                        }
16181                        Ok(Value::Array(Rc::new(RefCell::new(diffs))))
16182                    }
16183                    _ => Err(RuntimeError::new("Diff requires array")),
16184                }
16185            }
16186
16187            PipeOp::Gradient(var_expr) => {
16188                // |∇{var} - automatic differentiation
16189                // For now, just a placeholder - real autodiff requires tape recording
16190                let _ = var_expr;
16191                Ok(Value::Float(0.0)) // TODO: Implement real autodiff
16192            }
16193
16194            PipeOp::SortAsc => {
16195                // |⍋ - sort ascending
16196                match value {
16197                    Value::Array(arr) => {
16198                        let mut v = arr.borrow().clone();
16199                        v.sort_by(|a, b| self.compare_values(a, b, &None));
16200                        Ok(Value::Array(Rc::new(RefCell::new(v))))
16201                    }
16202                    _ => Err(RuntimeError::new("SortAsc requires array")),
16203                }
16204            }
16205
16206            PipeOp::SortDesc => {
16207                // |⍒ - sort descending
16208                match value {
16209                    Value::Array(arr) => {
16210                        let mut v = arr.borrow().clone();
16211                        v.sort_by(|a, b| self.compare_values(b, a, &None));
16212                        Ok(Value::Array(Rc::new(RefCell::new(v))))
16213                    }
16214                    _ => Err(RuntimeError::new("SortDesc requires array")),
16215                }
16216            }
16217
16218            PipeOp::Reverse => {
16219                // |⌽ - reverse collection
16220                match value {
16221                    Value::Array(arr) => {
16222                        let mut v = arr.borrow().clone();
16223                        v.reverse();
16224                        Ok(Value::Array(Rc::new(RefCell::new(v))))
16225                    }
16226                    _ => Err(RuntimeError::new("Reverse requires array")),
16227                }
16228            }
16229
16230            PipeOp::Cycle(n_expr) => {
16231                // |↻{n} - repeat collection n times
16232                match value {
16233                    Value::Array(arr) => {
16234                        let n_val = self.evaluate(n_expr)?;
16235                        let n = match n_val {
16236                            Value::Int(i) => i as usize,
16237                            _ => return Err(RuntimeError::new("Cycle count must be integer")),
16238                        };
16239                        let arr = arr.borrow();
16240                        let cycled: Vec<Value> =
16241                            arr.iter().cloned().cycle().take(arr.len() * n).collect();
16242                        Ok(Value::Array(Rc::new(RefCell::new(cycled))))
16243                    }
16244                    _ => Err(RuntimeError::new("Cycle requires array")),
16245                }
16246            }
16247
16248            PipeOp::Windows(n_expr) => {
16249                // |⌺{n} - sliding windows
16250                match value {
16251                    Value::Array(arr) => {
16252                        let n_val = self.evaluate(n_expr)?;
16253                        let n = match n_val {
16254                            Value::Int(i) => i as usize,
16255                            _ => return Err(RuntimeError::new("Window size must be integer")),
16256                        };
16257                        let arr = arr.borrow();
16258                        let windows: Vec<Value> = arr
16259                            .windows(n)
16260                            .map(|w| Value::Array(Rc::new(RefCell::new(w.to_vec()))))
16261                            .collect();
16262                        Ok(Value::Array(Rc::new(RefCell::new(windows))))
16263                    }
16264                    _ => Err(RuntimeError::new("Windows requires array")),
16265                }
16266            }
16267
16268            PipeOp::Chunks(n_expr) => {
16269                // |⊞{n} - split into chunks
16270                match value {
16271                    Value::Array(arr) => {
16272                        let n_val = self.evaluate(n_expr)?;
16273                        let n = match n_val {
16274                            Value::Int(i) => i as usize,
16275                            _ => return Err(RuntimeError::new("Chunk size must be integer")),
16276                        };
16277                        let arr = arr.borrow();
16278                        let chunks: Vec<Value> = arr
16279                            .chunks(n)
16280                            .map(|c| Value::Array(Rc::new(RefCell::new(c.to_vec()))))
16281                            .collect();
16282                        Ok(Value::Array(Rc::new(RefCell::new(chunks))))
16283                    }
16284                    _ => Err(RuntimeError::new("Chunks requires array")),
16285                }
16286            }
16287
16288            PipeOp::Flatten => {
16289                // |⋳ - flatten nested collection
16290                match value {
16291                    Value::Array(arr) => {
16292                        let mut flat = Vec::new();
16293                        for elem in arr.borrow().iter() {
16294                            match elem {
16295                                Value::Array(inner) => {
16296                                    flat.extend(inner.borrow().iter().cloned());
16297                                }
16298                                other => flat.push(other.clone()),
16299                            }
16300                        }
16301                        Ok(Value::Array(Rc::new(RefCell::new(flat))))
16302                    }
16303                    _ => Err(RuntimeError::new("Flatten requires array")),
16304                }
16305            }
16306
16307            PipeOp::Unique => {
16308                // |∪ - remove duplicates
16309                match value {
16310                    Value::Array(arr) => {
16311                        let mut seen = std::collections::HashSet::new();
16312                        let mut unique = Vec::new();
16313                        for elem in arr.borrow().iter() {
16314                            let key = format!("{:?}", elem);
16315                            if seen.insert(key) {
16316                                unique.push(elem.clone());
16317                            }
16318                        }
16319                        Ok(Value::Array(Rc::new(RefCell::new(unique))))
16320                    }
16321                    _ => Err(RuntimeError::new("Unique requires array")),
16322                }
16323            }
16324
16325            PipeOp::Enumerate => {
16326                // |⍳ - pair with indices
16327                match value {
16328                    Value::Array(arr) => {
16329                        let enumerated: Vec<Value> = arr
16330                            .borrow()
16331                            .iter()
16332                            .enumerate()
16333                            .map(|(i, v)| {
16334                                Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
16335                            })
16336                            .collect();
16337                        Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
16338                    }
16339                    _ => Err(RuntimeError::new("Enumerate requires array")),
16340                }
16341            }
16342
16343            // ==========================================
16344            // Holographic Operations
16345            // ==========================================
16346            PipeOp::Universal => {
16347                // |∀ - universal reconstruction (sum all elements or reconstruct from shards)
16348                // Reconstructs whole from shards by extracting data
16349                // Note: QH types use __value__, others may use value
16350                match value {
16351                    // Handle single Hologram/Struct - extract inner value
16352                    Value::Struct { name, fields } => {
16353                        let fields_ref = fields.borrow();
16354                        // For Hologram, extract value (check both __value__ and value)
16355                        if name == "Hologram" || name == "EntangledHologram" {
16356                            if let Some(v) = fields_ref.get("__value__").or_else(|| fields_ref.get("value")) {
16357                                return Ok(v.clone());
16358                            }
16359                        }
16360                        // For QHState, extract value
16361                        if name == "QHState" {
16362                            if let Some(v) = fields_ref.get("__value__").or_else(|| fields_ref.get("value")) {
16363                                return Ok(v.clone());
16364                            }
16365                        }
16366                        // For Superposition, return first state's value
16367                        if name == "Superposition" {
16368                            if let Some(Value::Array(states)) = fields_ref.get("states").or_else(|| fields_ref.get("__values__")) {
16369                                if let Some(first) = states.borrow().first() {
16370                                    // If first is a Hologram, extract its value
16371                                    if let Value::Struct {
16372                                        fields: inner_fields,
16373                                        ..
16374                                    } = first
16375                                    {
16376                                        let inner_fields_ref = inner_fields.borrow();
16377                                        if let Some(v) = inner_fields_ref.get("__value__").or_else(|| inner_fields_ref.get("value")) {
16378                                            return Ok(v.clone());
16379                                        }
16380                                    }
16381                                    return Ok(first.clone());
16382                                }
16383                            }
16384                        }
16385                        // Generic fallback - try to extract value field (both variants)
16386                        if let Some(v) = fields_ref.get("__value__").or_else(|| fields_ref.get("value")) {
16387                            return Ok(v.clone());
16388                        }
16389                        drop(fields_ref);
16390                        return Ok(Value::Struct { name, fields });
16391                    }
16392                    Value::Array(arr) => {
16393                        let arr = arr.borrow();
16394                        if arr.is_empty() {
16395                            return Ok(Value::Int(0));
16396                        }
16397                        // Check if this is an array of Shard structs
16398                        // Per spec 11-HOLOGRAPHIC.md § 2.3:
16399                        // ∀ reconstructs whole from available shards
16400                        if let Some(Value::Struct { name, .. }) = arr.first() {
16401                            if name == "Shard" {
16402                                // Collect all shard data values
16403                                let mut data_values: Vec<Value> = Vec::new();
16404                                for shard in arr.iter() {
16405                                    if let Value::Struct { fields, .. } = shard {
16406                                        if let Some(data) = fields.borrow().get("data") {
16407                                            data_values.push(data.clone());
16408                                        }
16409                                    }
16410                                }
16411
16412                                if data_values.is_empty() {
16413                                    return Ok(Value::Int(0));
16414                                }
16415
16416                                // Collect (x, y) points from shards
16417                                let mut points: Vec<(i64, i64)> = Vec::new();
16418                                let mut has_index_zero = false;
16419                                for shard in arr.iter() {
16420                                    if let Value::Struct { fields, .. } = shard {
16421                                        let fields_ref = fields.borrow();
16422                                        let idx = fields_ref.get("index");
16423                                        let data = fields_ref.get("data");
16424                                        if let (Some(Value::Int(x)), Some(Value::Int(y))) =
16425                                            (idx, data)
16426                                        {
16427                                            if *x == 0 {
16428                                                has_index_zero = true;
16429                                            }
16430                                            points.push((*x, *y));
16431                                        }
16432                                    }
16433                                }
16434
16435                                if points.is_empty() {
16436                                    return Ok(Value::Int(0));
16437                                }
16438
16439                                // Check if all data values are identical (simple scatter without RS)
16440                                let first_y = points[0].1;
16441                                let all_same = points.iter().all(|(_, y)| *y == first_y);
16442                                if all_same {
16443                                    return Ok(Value::Int(first_y));
16444                                }
16445
16446                                // Distinguish between RS-encoded shards and manual shards:
16447                                // - RS-encoded shards (from scatter) have indices 1..n (never 0)
16448                                // - Manual shards may have index 0
16449                                // If index 0 is present, treat as manual shards → aggregate
16450                                if has_index_zero {
16451                                    // Manual shards: aggregate (sum for numerics)
16452                                    let mut total: i64 = 0;
16453                                    for (_, y) in &points {
16454                                        total += y;
16455                                    }
16456                                    return Ok(Value::Int(total));
16457                                }
16458
16459                                // Reed-Solomon reconstruction via Lagrange interpolation
16460                                // Per spec 11-HOLOGRAPHIC.md § 2.5:
16461                                // Given k or more shards with (index, data) pairs where
16462                                // data = p(index) for some polynomial p, reconstruct p(0)
16463                                //
16464                                // Lagrange interpolation to find p(0)
16465                                // p(0) = Σᵢ yᵢ × Πⱼ≠ᵢ (xⱼ / (xⱼ - xᵢ))
16466                                // Using floating point for precision, then round
16467                                let mut result: f64 = 0.0;
16468                                let n = points.len();
16469
16470                                for i in 0..n {
16471                                    let (xi, yi) = points[i];
16472                                    let mut basis = 1.0f64;
16473
16474                                    for j in 0..n {
16475                                        if i != j {
16476                                            let xj = points[j].0 as f64;
16477                                            let xi_f = xi as f64;
16478                                            // Lagrange basis: xj / (xj - xi) for evaluating at x=0
16479                                            basis *= xj / (xj - xi_f);
16480                                        }
16481                                    }
16482
16483                                    result += (yi as f64) * basis;
16484                                }
16485
16486                                // Round to nearest integer (original value was integer)
16487                                return Ok(Value::Int(result.round() as i64));
16488                            }
16489                            // For Hologram structs, extract value
16490                            if name == "Hologram" {
16491                                if let Value::Struct { fields, .. } = arr.first().unwrap() {
16492                                    if let Some(value) = fields.borrow().get("value") {
16493                                        return Ok(value.clone());
16494                                    }
16495                                }
16496                            }
16497                        }
16498                        // Sum all elements for numeric arrays
16499                        let mut sum = 0i64;
16500                        let mut has_float = false;
16501                        let mut float_sum = 0.0f64;
16502                        for elem in arr.iter() {
16503                            match elem {
16504                                Value::Int(i) => {
16505                                    sum += i;
16506                                    float_sum += *i as f64;
16507                                }
16508                                Value::Float(f) => {
16509                                    has_float = true;
16510                                    float_sum += f;
16511                                }
16512                                // For structs, try to extract inner value
16513                                Value::Struct { fields, .. } => {
16514                                    if let Some(Value::Int(i)) = fields.borrow().get("value") {
16515                                        sum += i;
16516                                        float_sum += *i as f64;
16517                                    } else if let Some(Value::Float(f)) =
16518                                        fields.borrow().get("value")
16519                                    {
16520                                        has_float = true;
16521                                        float_sum += *f;
16522                                    } else if let Some(data) = fields.borrow().get("data") {
16523                                        // Return data from first element
16524                                        return Ok(data.clone());
16525                                    }
16526                                }
16527                                _ => {} // Skip non-numeric elements
16528                            }
16529                        }
16530                        if has_float {
16531                            Ok(Value::Float(float_sum))
16532                        } else {
16533                            Ok(Value::Int(sum))
16534                        }
16535                    }
16536                    _ => Err(RuntimeError::new("Universal requires array")),
16537                }
16538            }
16539
16540            PipeOp::Possibility { method, args } => {
16541                // |◊method - possibility/approximate query with method call
16542                // Per spec 11-HOLOGRAPHIC.md § 11.2.2:
16543                // Returns approximate values with Predicted (◊) evidentiality.
16544
16545                // Evaluate as a regular method call first
16546                let method_result = self.apply_pipe_op(
16547                    value.clone(),
16548                    &PipeOp::Method {
16549                        name: method.clone(),
16550                        type_args: None,
16551                        args: args.clone(),
16552                    },
16553                )?;
16554
16555                // Wrap result in Predicted evidentiality (approximate)
16556                Ok(Value::Evidential {
16557                    value: Box::new(method_result),
16558                    evidence: Evidence::Predicted,
16559                })
16560            }
16561
16562            PipeOp::Necessity { method, args } => {
16563                // |□method - necessity/verification with method call
16564                // Returns verified result wrapped in Known evidentiality
16565
16566                // Evaluate as a regular method call first
16567                let method_result = self.apply_pipe_op(
16568                    value.clone(),
16569                    &PipeOp::Method {
16570                        name: method.clone(),
16571                        type_args: None,
16572                        args: args.clone(),
16573                    },
16574                )?;
16575
16576                // Wrap result in Known evidentiality (verified)
16577                Ok(Value::Evidential {
16578                    value: Box::new(method_result),
16579                    evidence: Evidence::Known,
16580                })
16581            }
16582        }
16583    }
16584
16585    // ==========================================
16586    // Protocol Helper Methods
16587    // ==========================================
16588
16589    /// Wrap a value in Reported evidentiality
16590    /// Network data is "hearsay" - it comes from external sources we can't verify
16591    fn wrap_reported(&self, value: Value) -> Value {
16592        Value::Evidential {
16593            value: Box::new(value),
16594            evidence: Evidence::Reported,
16595        }
16596    }
16597
16598    /// Send data over a protocol connection
16599    fn protocol_send(&mut self, connection: &Value, data: &Value) -> Result<Value, RuntimeError> {
16600        // Extract connection info and send data
16601        match connection {
16602            Value::Map(obj) => {
16603                let obj = obj.borrow();
16604                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
16605                    match protocol.as_str() {
16606                        "http" | "https" => {
16607                            // For HTTP, "send" means execute the request
16608                            // The data becomes the body
16609                            #[cfg(debug_assertions)]
16610                            eprintln!("[HTTP] Would send request with body: {:?}", data);
16611                            Ok(Value::Map(Rc::new(RefCell::new({
16612                                let mut response = HashMap::new();
16613                                response.insert("status".to_string(), Value::Int(200));
16614                                response.insert("body".to_string(), data.clone());
16615                                response.insert(
16616                                    "__protocol__".to_string(),
16617                                    Value::String(Rc::new("http_response".to_string())),
16618                                );
16619                                response
16620                            }))))
16621                        }
16622                        "ws" | "wss" => {
16623                            // For WebSocket, connect, send message, receive response
16624                            // Uses native Sigil WebSocket implementation (RFC 6455)
16625                            #[cfg(feature = "websocket")]
16626                            {
16627                                let url_str = obj.get("url")
16628                                    .and_then(|v| if let Value::String(s) = v { Some((**s).clone()) } else { None })
16629                                    .ok_or_else(|| RuntimeError::new("WebSocket connection missing URL"))?;
16630
16631                                let message = match data {
16632                                    Value::String(s) => (**s).clone(),
16633                                    _ => format!("{}", data),
16634                                };
16635
16636                                // Use native WebSocket implementation
16637                                match websocket::send_and_receive(&url_str, &message) {
16638                                    Ok(response) => Ok(Value::String(Rc::new(response))),
16639                                    Err(e) => Err(RuntimeError::new(format!("WebSocket error: {}", e))),
16640                                }
16641                            }
16642                            #[cfg(not(feature = "websocket"))]
16643                            {
16644                                #[cfg(debug_assertions)]
16645                                eprintln!("[WebSocket] Would send message: {:?} (feature disabled)", data);
16646                                Ok(Value::Bool(true))
16647                            }
16648                        }
16649                        "grpc" => {
16650                            // For gRPC, send the request message
16651                            #[cfg(debug_assertions)]
16652                            eprintln!("[gRPC] Would send message: {:?}", data);
16653                            Ok(Value::Map(Rc::new(RefCell::new({
16654                                let mut response = HashMap::new();
16655                                response.insert("status".to_string(), Value::Int(0)); // OK
16656                                response.insert("message".to_string(), data.clone());
16657                                response.insert(
16658                                    "__protocol__".to_string(),
16659                                    Value::String(Rc::new("grpc_response".to_string())),
16660                                );
16661                                response
16662                            }))))
16663                        }
16664                        "kafka" => {
16665                            // For Kafka, produce a message
16666                            #[cfg(debug_assertions)]
16667                            eprintln!("[Kafka] Would produce message: {:?}", data);
16668                            Ok(Value::Map(Rc::new(RefCell::new({
16669                                let mut result = HashMap::new();
16670                                result.insert("partition".to_string(), Value::Int(0));
16671                                result.insert("offset".to_string(), Value::Int(42));
16672                                result
16673                            }))))
16674                        }
16675                        _ => Err(RuntimeError::new(format!("Unknown protocol: {}", protocol))),
16676                    }
16677                } else {
16678                    Err(RuntimeError::new(
16679                        "Connection object missing __protocol__ field",
16680                    ))
16681                }
16682            }
16683            _ => Err(RuntimeError::new("send requires a connection object")),
16684        }
16685    }
16686
16687    /// Receive data from a protocol connection
16688    fn protocol_recv(&mut self, connection: &Value) -> Result<Value, RuntimeError> {
16689        match connection {
16690            Value::Map(obj) => {
16691                let obj = obj.borrow();
16692                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
16693                    match protocol.as_str() {
16694                        "ws" | "wss" => {
16695                            // For WebSocket, receive a message
16696                            #[cfg(debug_assertions)]
16697                            eprintln!("[WebSocket] Would receive message");
16698                            Ok(Value::String(Rc::new("received message".to_string())))
16699                        }
16700                        "kafka" => {
16701                            // For Kafka, consume a message
16702                            #[cfg(debug_assertions)]
16703                            eprintln!("[Kafka] Would consume message");
16704                            Ok(Value::Map(Rc::new(RefCell::new({
16705                                let mut msg = HashMap::new();
16706                                msg.insert("key".to_string(), Value::Null);
16707                                msg.insert(
16708                                    "value".to_string(),
16709                                    Value::String(Rc::new("consumed message".to_string())),
16710                                );
16711                                msg.insert("partition".to_string(), Value::Int(0));
16712                                msg.insert("offset".to_string(), Value::Int(100));
16713                                msg
16714                            }))))
16715                        }
16716                        "grpc" => {
16717                            // For gRPC streaming, receive next message
16718                            #[cfg(debug_assertions)]
16719                            eprintln!("[gRPC] Would receive stream message");
16720                            Ok(Value::Map(Rc::new(RefCell::new({
16721                                let mut msg = HashMap::new();
16722                                msg.insert(
16723                                    "data".to_string(),
16724                                    Value::String(Rc::new("stream data".to_string())),
16725                                );
16726                                msg
16727                            }))))
16728                        }
16729                        _ => Err(RuntimeError::new(format!(
16730                            "recv not supported for protocol: {}",
16731                            protocol
16732                        ))),
16733                    }
16734                } else {
16735                    Err(RuntimeError::new(
16736                        "Connection object missing __protocol__ field",
16737                    ))
16738                }
16739            }
16740            _ => Err(RuntimeError::new("recv requires a connection object")),
16741        }
16742    }
16743
16744    /// Create a streaming iterator over protocol data
16745    fn protocol_stream(
16746        &mut self,
16747        connection: &Value,
16748        _handler: &Value,
16749    ) -> Result<Value, RuntimeError> {
16750        // Create a lazy stream that yields values with Reported evidentiality
16751        match connection {
16752            Value::Map(obj) => {
16753                let obj = obj.borrow();
16754                if let Some(Value::String(protocol)) = obj.get("__protocol__") {
16755                    #[cfg(debug_assertions)]
16756                    eprintln!("[{}] Would create stream", protocol);
16757
16758                    // Return a stream object that can be iterated
16759                    Ok(Value::Map(Rc::new(RefCell::new({
16760                        let mut stream = HashMap::new();
16761                        stream.insert(
16762                            "__type__".to_string(),
16763                            Value::String(Rc::new("Stream".to_string())),
16764                        );
16765                        stream.insert("__protocol__".to_string(), Value::String(protocol.clone()));
16766                        stream.insert(
16767                            "__evidentiality__".to_string(),
16768                            Value::String(Rc::new("reported".to_string())),
16769                        );
16770                        stream
16771                    }))))
16772                } else {
16773                    Err(RuntimeError::new(
16774                        "Connection object missing __protocol__ field",
16775                    ))
16776                }
16777            }
16778            _ => Err(RuntimeError::new("stream requires a connection object")),
16779        }
16780    }
16781
16782    /// Establish a protocol connection
16783    fn protocol_connect(
16784        &mut self,
16785        target: &Value,
16786        _config: Option<&Value>,
16787    ) -> Result<Value, RuntimeError> {
16788        match target {
16789            Value::String(url) => {
16790                // Parse URL to determine protocol
16791                let protocol = if url.starts_with("wss://") || url.starts_with("ws://") {
16792                    if url.starts_with("wss://") {
16793                        "wss"
16794                    } else {
16795                        "ws"
16796                    }
16797                } else if url.starts_with("https://") || url.starts_with("http://") {
16798                    if url.starts_with("https://") {
16799                        "https"
16800                    } else {
16801                        "http"
16802                    }
16803                } else if url.starts_with("grpc://") || url.starts_with("grpcs://") {
16804                    "grpc"
16805                } else if url.starts_with("kafka://") {
16806                    "kafka"
16807                } else if url.starts_with("amqp://") || url.starts_with("amqps://") {
16808                    "amqp"
16809                } else {
16810                    "unknown"
16811                };
16812
16813                #[cfg(debug_assertions)]
16814                eprintln!("[{}] Would connect to: {}", protocol, url);
16815
16816                // Return a connection object
16817                Ok(Value::Map(Rc::new(RefCell::new({
16818                    let mut conn = HashMap::new();
16819                    conn.insert(
16820                        "__protocol__".to_string(),
16821                        Value::String(Rc::new(protocol.to_string())),
16822                    );
16823                    conn.insert("url".to_string(), Value::String(url.clone()));
16824                    conn.insert("connected".to_string(), Value::Bool(true));
16825                    conn
16826                }))))
16827            }
16828            Value::Map(obj) => {
16829                // Already a connection config object
16830                let mut conn = obj.borrow().clone();
16831                conn.insert("connected".to_string(), Value::Bool(true));
16832                Ok(Value::Map(Rc::new(RefCell::new(conn))))
16833            }
16834            _ => Err(RuntimeError::new(
16835                "connect requires URL string or config object",
16836            )),
16837        }
16838    }
16839
16840    /// Close a protocol connection
16841    fn protocol_close(&mut self, connection: &Value) -> Result<(), RuntimeError> {
16842        match connection {
16843            Value::Map(obj) => {
16844                let mut obj = obj.borrow_mut();
16845                if let Some(Value::String(protocol)) = obj.get("__protocol__").cloned() {
16846                    #[cfg(debug_assertions)]
16847                    eprintln!("[{}] Would close connection", protocol);
16848                    obj.insert("connected".to_string(), Value::Bool(false));
16849                    Ok(())
16850                } else {
16851                    Err(RuntimeError::new(
16852                        "Connection object missing __protocol__ field",
16853                    ))
16854                }
16855            }
16856            _ => Err(RuntimeError::new("close requires a connection object")),
16857        }
16858    }
16859
16860    /// Add a header to a protocol request
16861    fn protocol_add_header(
16862        &mut self,
16863        mut request: Value,
16864        name: &Value,
16865        header_value: &Value,
16866    ) -> Result<Value, RuntimeError> {
16867        let name_str = match name {
16868            Value::String(s) => (**s).clone(),
16869            _ => return Err(RuntimeError::new("Header name must be a string")),
16870        };
16871        let value_str = match header_value {
16872            Value::String(s) => (**s).clone(),
16873            Value::Int(i) => i.to_string(),
16874            _ => return Err(RuntimeError::new("Header value must be string or int")),
16875        };
16876
16877        match &mut request {
16878            Value::Map(obj) => {
16879                let mut obj = obj.borrow_mut();
16880
16881                // Get or create headers map
16882                let headers = obj
16883                    .entry("headers".to_string())
16884                    .or_insert_with(|| Value::Map(Rc::new(RefCell::new(HashMap::new()))));
16885
16886                if let Value::Map(headers_obj) = headers {
16887                    headers_obj
16888                        .borrow_mut()
16889                        .insert(name_str, Value::String(Rc::new(value_str)));
16890                }
16891                drop(obj);
16892                Ok(request)
16893            }
16894            _ => Err(RuntimeError::new("header requires a request object")),
16895        }
16896    }
16897
16898    /// Set the body of a protocol request
16899    fn protocol_set_body(
16900        &mut self,
16901        mut request: Value,
16902        body: &Value,
16903    ) -> Result<Value, RuntimeError> {
16904        match &mut request {
16905            Value::Map(obj) => {
16906                obj.borrow_mut().insert("body".to_string(), body.clone());
16907                Ok(request)
16908            }
16909            _ => Err(RuntimeError::new("body requires a request object")),
16910        }
16911    }
16912
16913    /// Set the timeout for a protocol operation
16914    fn protocol_set_timeout(
16915        &mut self,
16916        mut request: Value,
16917        ms: &Value,
16918    ) -> Result<Value, RuntimeError> {
16919        let timeout_ms = match ms {
16920            Value::Int(n) => *n,
16921            Value::Float(f) => *f as i64,
16922            _ => return Err(RuntimeError::new("Timeout must be a number (milliseconds)")),
16923        };
16924
16925        match &mut request {
16926            Value::Map(obj) => {
16927                obj.borrow_mut()
16928                    .insert("timeout_ms".to_string(), Value::Int(timeout_ms));
16929                Ok(request)
16930            }
16931            _ => Err(RuntimeError::new("timeout requires a request object")),
16932        }
16933    }
16934
16935    /// Set the retry policy for a protocol operation
16936    fn protocol_set_retry(
16937        &mut self,
16938        mut request: Value,
16939        count: &Value,
16940        strategy: Option<&Value>,
16941    ) -> Result<Value, RuntimeError> {
16942        let retry_count = match count {
16943            Value::Int(n) => *n,
16944            _ => return Err(RuntimeError::new("Retry count must be an integer")),
16945        };
16946
16947        match &mut request {
16948            Value::Map(obj) => {
16949                let mut obj = obj.borrow_mut();
16950                obj.insert("retry_count".to_string(), Value::Int(retry_count));
16951                if let Some(strat) = strategy {
16952                    obj.insert("retry_strategy".to_string(), strat.clone());
16953                }
16954                drop(obj);
16955                Ok(request)
16956            }
16957            _ => Err(RuntimeError::new("retry requires a request object")),
16958        }
16959    }
16960
16961    /// Backward propagation for autograd - traverse computation graph and set gradients
16962    fn backward_propagate(
16963        &self,
16964        tensor_fields: Rc<RefCell<std::collections::HashMap<String, Value>>>,
16965    ) -> Result<(), RuntimeError> {
16966        let fields_ref = tensor_fields.borrow();
16967
16968        // Get the gradient input references and propagate
16969        if let Some(Value::Struct {
16970            fields: grad_fields,
16971            ..
16972        }) = fields_ref.get("_grad_left")
16973        {
16974            // This tensor was an operand in a computation - set its gradient
16975            let shape = grad_fields.borrow().get("shape").cloned();
16976            let data_len = match grad_fields.borrow().get("data") {
16977                Some(Value::Array(arr)) => arr.borrow().len(),
16978                _ => 0,
16979            };
16980
16981            // Create gradient tensor (all ones for simplicity - this is the gradient of sum)
16982            let grad_data: Vec<Value> = vec![Value::Float(1.0); data_len];
16983            let mut grad_tensor_fields = std::collections::HashMap::new();
16984            if let Some(s) = shape {
16985                grad_tensor_fields.insert("shape".to_string(), s);
16986            }
16987            grad_tensor_fields.insert(
16988                "data".to_string(),
16989                Value::Array(Rc::new(RefCell::new(grad_data))),
16990            );
16991            grad_tensor_fields.insert("requires_grad".to_string(), Value::Bool(false));
16992
16993            // Set the grad field on the original tensor as a proper Variant
16994            grad_fields.borrow_mut().insert(
16995                "grad".to_string(),
16996                Value::Variant {
16997                    enum_name: "Option".to_string(),
16998                    variant_name: "Some".to_string(),
16999                    fields: Some(Rc::new(vec![Value::Struct {
17000                        name: "Tensor".to_string(),
17001                        fields: Rc::new(RefCell::new(grad_tensor_fields)),
17002                    }])),
17003                },
17004            );
17005
17006            // Recursively propagate to any further inputs
17007            self.backward_propagate(grad_fields.clone())?;
17008        }
17009
17010        if let Some(Value::Struct {
17011            fields: grad_fields,
17012            ..
17013        }) = fields_ref.get("_grad_input")
17014        {
17015            // This is from sum operation - propagate to the input tensor
17016            let shape = grad_fields.borrow().get("shape").cloned();
17017            let data_len = match grad_fields.borrow().get("data") {
17018                Some(Value::Array(arr)) => arr.borrow().len(),
17019                _ => 0,
17020            };
17021
17022            let grad_data: Vec<Value> = vec![Value::Float(1.0); data_len];
17023            let mut grad_tensor_fields = std::collections::HashMap::new();
17024            if let Some(s) = shape {
17025                grad_tensor_fields.insert("shape".to_string(), s);
17026            }
17027            grad_tensor_fields.insert(
17028                "data".to_string(),
17029                Value::Array(Rc::new(RefCell::new(grad_data))),
17030            );
17031            grad_tensor_fields.insert("requires_grad".to_string(), Value::Bool(false));
17032
17033            // Set the grad field as a proper Variant
17034            grad_fields.borrow_mut().insert(
17035                "grad".to_string(),
17036                Value::Variant {
17037                    enum_name: "Option".to_string(),
17038                    variant_name: "Some".to_string(),
17039                    fields: Some(Rc::new(vec![Value::Struct {
17040                        name: "Tensor".to_string(),
17041                        fields: Rc::new(RefCell::new(grad_tensor_fields)),
17042                    }])),
17043                },
17044            );
17045
17046            self.backward_propagate(grad_fields.clone())?;
17047        }
17048
17049        Ok(())
17050    }
17051
17052    fn sum_values(&self, value: Value) -> Result<Value, RuntimeError> {
17053        match value {
17054            Value::Array(arr) => {
17055                let arr = arr.borrow();
17056                if arr.is_empty() {
17057                    return Ok(Value::Int(0));
17058                }
17059                let mut sum = match &arr[0] {
17060                    Value::Int(_) => Value::Int(0),
17061                    Value::Float(_) => Value::Float(0.0),
17062                    _ => return Err(RuntimeError::new("Cannot sum non-numeric array")),
17063                };
17064                for item in arr.iter() {
17065                    sum = match (&sum, item) {
17066                        (Value::Int(a), Value::Int(b)) => Value::Int(a + b),
17067                        (Value::Float(a), Value::Float(b)) => Value::Float(a + b),
17068                        (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 + b),
17069                        (Value::Float(a), Value::Int(b)) => Value::Float(a + *b as f64),
17070                        _ => return Err(RuntimeError::new("Cannot sum non-numeric values")),
17071                    };
17072                }
17073                Ok(sum)
17074            }
17075            // Handle Tensor sum
17076            Value::Struct { name, fields } if name == "Tensor" => {
17077                let fields_ref = fields.borrow();
17078                let requires_grad =
17079                    matches!(fields_ref.get("requires_grad"), Some(Value::Bool(true)));
17080                let grad_left = fields_ref.get("_grad_left").cloned();
17081                let data: Vec<f64> = match fields_ref.get("data") {
17082                    Some(Value::Array(arr)) => arr
17083                        .borrow()
17084                        .iter()
17085                        .filter_map(|v| match v {
17086                            Value::Float(f) => Some(*f),
17087                            Value::Int(n) => Some(*n as f64),
17088                            _ => None,
17089                        })
17090                        .collect(),
17091                    _ => vec![],
17092                };
17093                drop(fields_ref);
17094                let sum: f64 = data.iter().sum();
17095
17096                // If this tensor requires grad, return a scalar tensor with computation graph
17097                if requires_grad {
17098                    let mut result_fields = std::collections::HashMap::new();
17099                    result_fields.insert(
17100                        "shape".to_string(),
17101                        Value::Array(Rc::new(RefCell::new(vec![]))),
17102                    );
17103                    result_fields.insert(
17104                        "data".to_string(),
17105                        Value::Array(Rc::new(RefCell::new(vec![Value::Float(sum)]))),
17106                    );
17107                    result_fields.insert("_value".to_string(), Value::Float(sum));
17108                    result_fields.insert("requires_grad".to_string(), Value::Bool(true));
17109                    result_fields
17110                        .insert("_op".to_string(), Value::String(Rc::new("sum".to_string())));
17111                    // Propagate the gradient input reference
17112                    if let Some(grad_input) = grad_left {
17113                        result_fields.insert("_grad_left".to_string(), grad_input);
17114                    } else {
17115                        // Store reference to the input tensor
17116                        result_fields.insert(
17117                            "_grad_input".to_string(),
17118                            Value::Struct {
17119                                name: "Tensor".to_string(),
17120                                fields: fields.clone(),
17121                            },
17122                        );
17123                    }
17124                    Ok(Value::Struct {
17125                        name: "Tensor".to_string(),
17126                        fields: Rc::new(RefCell::new(result_fields)),
17127                    })
17128                } else {
17129                    Ok(Value::Float(sum))
17130                }
17131            }
17132            _ => Err(RuntimeError::new("sum requires array")),
17133        }
17134    }
17135
17136    fn product_values(&self, value: Value) -> Result<Value, RuntimeError> {
17137        match value {
17138            Value::Array(arr) => {
17139                let arr = arr.borrow();
17140                if arr.is_empty() {
17141                    return Ok(Value::Int(1));
17142                }
17143                let mut prod = match &arr[0] {
17144                    Value::Int(_) => Value::Int(1),
17145                    Value::Float(_) => Value::Float(1.0),
17146                    _ => return Err(RuntimeError::new("Cannot multiply non-numeric array")),
17147                };
17148                for item in arr.iter() {
17149                    prod = match (&prod, item) {
17150                        (Value::Int(a), Value::Int(b)) => Value::Int(a * b),
17151                        (Value::Float(a), Value::Float(b)) => Value::Float(a * b),
17152                        (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 * b),
17153                        (Value::Float(a), Value::Int(b)) => Value::Float(a * *b as f64),
17154                        _ => return Err(RuntimeError::new("Cannot multiply non-numeric values")),
17155                    };
17156                }
17157                Ok(prod)
17158            }
17159            _ => Err(RuntimeError::new("product requires array")),
17160        }
17161    }
17162
17163    fn min_values(&self, value: Value) -> Result<Value, RuntimeError> {
17164        match value {
17165            Value::Array(arr) => {
17166                let arr = arr.borrow();
17167                if arr.is_empty() {
17168                    return Err(RuntimeError::new("Cannot find min of empty array"));
17169                }
17170                let mut min = arr[0].clone();
17171                for item in arr.iter().skip(1) {
17172                    min = match (&min, item) {
17173                        (Value::Int(a), Value::Int(b)) => {
17174                            if *b < *a {
17175                                Value::Int(*b)
17176                            } else {
17177                                Value::Int(*a)
17178                            }
17179                        }
17180                        (Value::Float(a), Value::Float(b)) => {
17181                            if *b < *a {
17182                                Value::Float(*b)
17183                            } else {
17184                                Value::Float(*a)
17185                            }
17186                        }
17187                        (Value::Int(a), Value::Float(b)) => {
17188                            let af = *a as f64;
17189                            if *b < af {
17190                                Value::Float(*b)
17191                            } else {
17192                                Value::Float(af)
17193                            }
17194                        }
17195                        (Value::Float(a), Value::Int(b)) => {
17196                            let bf = *b as f64;
17197                            if bf < *a {
17198                                Value::Float(bf)
17199                            } else {
17200                                Value::Float(*a)
17201                            }
17202                        }
17203                        _ => {
17204                            return Err(RuntimeError::new("Cannot find min of non-numeric values"))
17205                        }
17206                    };
17207                }
17208                Ok(min)
17209            }
17210            _ => Err(RuntimeError::new("min requires array")),
17211        }
17212    }
17213
17214    fn max_values(&self, value: Value) -> Result<Value, RuntimeError> {
17215        match value {
17216            Value::Array(arr) => {
17217                let arr = arr.borrow();
17218                if arr.is_empty() {
17219                    return Err(RuntimeError::new("Cannot find max of empty array"));
17220                }
17221                let mut max = arr[0].clone();
17222                for item in arr.iter().skip(1) {
17223                    max = match (&max, item) {
17224                        (Value::Int(a), Value::Int(b)) => {
17225                            if *b > *a {
17226                                Value::Int(*b)
17227                            } else {
17228                                Value::Int(*a)
17229                            }
17230                        }
17231                        (Value::Float(a), Value::Float(b)) => {
17232                            if *b > *a {
17233                                Value::Float(*b)
17234                            } else {
17235                                Value::Float(*a)
17236                            }
17237                        }
17238                        (Value::Int(a), Value::Float(b)) => {
17239                            let af = *a as f64;
17240                            if *b > af {
17241                                Value::Float(*b)
17242                            } else {
17243                                Value::Float(af)
17244                            }
17245                        }
17246                        (Value::Float(a), Value::Int(b)) => {
17247                            let bf = *b as f64;
17248                            if bf > *a {
17249                                Value::Float(bf)
17250                            } else {
17251                                Value::Float(*a)
17252                            }
17253                        }
17254                        _ => {
17255                            return Err(RuntimeError::new("Cannot find max of non-numeric values"))
17256                        }
17257                    };
17258                }
17259                Ok(max)
17260            }
17261            _ => Err(RuntimeError::new("max requires array")),
17262        }
17263    }
17264
17265    fn concat_values(&self, value: Value) -> Result<Value, RuntimeError> {
17266        match value {
17267            Value::Array(arr) => {
17268                let arr = arr.borrow();
17269                if arr.is_empty() {
17270                    return Ok(Value::String(Rc::new(String::new())));
17271                }
17272                // Determine if we're concatenating strings or arrays
17273                match &arr[0] {
17274                    Value::String(_) => {
17275                        let mut result = String::new();
17276                        for item in arr.iter() {
17277                            if let Value::String(s) = item {
17278                                result.push_str(s);
17279                            } else {
17280                                return Err(RuntimeError::new(
17281                                    "concat requires all elements to be strings",
17282                                ));
17283                            }
17284                        }
17285                        Ok(Value::String(Rc::new(result)))
17286                    }
17287                    Value::Array(_) => {
17288                        let mut result = Vec::new();
17289                        for item in arr.iter() {
17290                            if let Value::Array(inner) = item {
17291                                result.extend(inner.borrow().iter().cloned());
17292                            } else {
17293                                return Err(RuntimeError::new(
17294                                    "concat requires all elements to be arrays",
17295                                ));
17296                            }
17297                        }
17298                        Ok(Value::Array(Rc::new(RefCell::new(result))))
17299                    }
17300                    _ => Err(RuntimeError::new("concat requires strings or arrays")),
17301                }
17302            }
17303            _ => Err(RuntimeError::new("concat requires array")),
17304        }
17305    }
17306
17307    fn all_values(&self, value: Value) -> Result<Value, RuntimeError> {
17308        match value {
17309            Value::Array(arr) => {
17310                let arr = arr.borrow();
17311                for item in arr.iter() {
17312                    match item {
17313                        Value::Bool(b) => {
17314                            if !*b {
17315                                return Ok(Value::Bool(false));
17316                            }
17317                        }
17318                        _ => return Err(RuntimeError::new("all requires array of booleans")),
17319                    }
17320                }
17321                Ok(Value::Bool(true))
17322            }
17323            _ => Err(RuntimeError::new("all requires array")),
17324        }
17325    }
17326
17327    fn any_values(&self, value: Value) -> Result<Value, RuntimeError> {
17328        match value {
17329            Value::Array(arr) => {
17330                let arr = arr.borrow();
17331                for item in arr.iter() {
17332                    match item {
17333                        Value::Bool(b) => {
17334                            if *b {
17335                                return Ok(Value::Bool(true));
17336                            }
17337                        }
17338                        _ => return Err(RuntimeError::new("any requires array of booleans")),
17339                    }
17340                }
17341                Ok(Value::Bool(false))
17342            }
17343            _ => Err(RuntimeError::new("any requires array")),
17344        }
17345    }
17346
17347    fn compare_values(&self, a: &Value, b: &Value, _field: &Option<Ident>) -> std::cmp::Ordering {
17348        // Simple comparison for now
17349        match (a, b) {
17350            (Value::Int(a), Value::Int(b)) => a.cmp(b),
17351            (Value::Float(a), Value::Float(b)) => {
17352                a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)
17353            }
17354            (Value::String(a), Value::String(b)) => a.cmp(b),
17355            _ => std::cmp::Ordering::Equal,
17356        }
17357    }
17358
17359    /// Subtract two values (for diff operation)
17360    fn subtract_values(&self, a: &Value, b: &Value) -> Result<Value, RuntimeError> {
17361        match (a, b) {
17362            (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a - b)),
17363            (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a - b)),
17364            (Value::Int(a), Value::Float(b)) => Ok(Value::Float(*a as f64 - b)),
17365            (Value::Float(a), Value::Int(b)) => Ok(Value::Float(a - *b as f64)),
17366            _ => Err(RuntimeError::new(format!(
17367                "Cannot subtract {:?} from {:?}",
17368                b, a
17369            ))),
17370        }
17371    }
17372
17373    fn eval_closure(
17374        &mut self,
17375        params: &[ClosureParam],
17376        body: &Expr,
17377    ) -> Result<Value, RuntimeError> {
17378        let param_names: Vec<String> = params
17379            .iter()
17380            .map(|p| Self::extract_param_name(&p.pattern))
17381            .collect();
17382
17383        Ok(Value::Function(Rc::new(Function {
17384            name: None,
17385            params: param_names,
17386            body: body.clone(),
17387            closure: self.environment.clone(),
17388            generic_params: Vec::new(),
17389        })))
17390    }
17391
17392    fn eval_struct_literal(
17393        &mut self,
17394        path: &TypePath,
17395        fields: &[FieldInit],
17396        rest: &Option<Box<Expr>>,
17397    ) -> Result<Value, RuntimeError> {
17398        let raw_name = path
17399            .segments
17400            .iter()
17401            .map(|s| s.ident.name.as_str())
17402            .collect::<Vec<_>>()
17403            .join("·"); // Use middle dot to match method registration format
17404
17405        // Resolve "Self" to the actual type name if we're in an impl block
17406        let name = if raw_name == "Self" || raw_name == "This" {
17407            if let Some(ref self_type) = self.current_self_type {
17408                self_type.clone()
17409            } else {
17410                // Fall back to trying to infer from field names
17411                raw_name
17412            }
17413        } else {
17414            // Normalize :: to · for consistency with internal naming
17415            raw_name.replace("::", "·")
17416        };
17417
17418        let mut field_values = HashMap::new();
17419
17420        // If there's a rest expression (..expr), evaluate it first to get base fields
17421        if let Some(rest_expr) = rest {
17422            // Set current_self_type for the rest expression (e.g., Default::default())
17423            let prev_self_type = self.current_self_type.clone();
17424            self.current_self_type = Some(name.clone());
17425
17426            let rest_value = self.evaluate(rest_expr)?;
17427
17428            self.current_self_type = prev_self_type;
17429
17430            // Extract fields from the rest value
17431            if let Value::Struct {
17432                fields: rest_fields,
17433                ..
17434            } = rest_value
17435            {
17436                for (k, v) in rest_fields.borrow().iter() {
17437                    field_values.insert(k.clone(), v.clone());
17438                }
17439            }
17440        }
17441
17442        // Override with explicitly provided fields
17443        for field in fields {
17444            let value = match &field.value {
17445                Some(expr) => self.evaluate(expr)?,
17446                None => self
17447                    .environment
17448                    .borrow()
17449                    .get(&field.name.name)
17450                    .ok_or_else(|| {
17451                        RuntimeError::new(format!("Unknown variable: {}", field.name.name))
17452                    })?,
17453            };
17454            field_values.insert(field.name.name.clone(), value);
17455        }
17456
17457        // Check if this is an enum variant with struct fields (e.g., Message::Move { x, y })
17458        // Path will have 2+ segments for enum variants
17459        if path.segments.len() >= 2 {
17460            let enum_name_segments: Vec<&str> = path.segments[..path.segments.len() - 1]
17461                .iter()
17462                .map(|s| s.ident.name.as_str())
17463                .collect();
17464            let variant_name = &path.segments.last().unwrap().ident.name;
17465
17466            // Try different enum name formats
17467            let enum_name_direct = enum_name_segments.join("::");
17468            let enum_name_qualified = enum_name_segments.join("·");
17469
17470            // Check if this is an enum variant
17471            let enum_def_opt = self
17472                .types
17473                .get(&enum_name_direct)
17474                .or_else(|| self.types.get(&enum_name_qualified));
17475
17476            if let Some(TypeDef::Enum(enum_def)) = enum_def_opt {
17477                // Check if this variant exists
17478                for variant in &enum_def.variants {
17479                    if &variant.name.name == variant_name {
17480                        // This is an enum variant with struct-like fields
17481                        // Create a Variant value with the fields wrapped in a Struct
17482                        let inner_struct = Value::Struct {
17483                            name: format!("{}::{}", enum_name_direct, variant_name),
17484                            fields: Rc::new(RefCell::new(field_values)),
17485                        };
17486                        return Ok(Value::Variant {
17487                            enum_name: enum_name_direct,
17488                            variant_name: variant_name.clone(),
17489                            fields: Some(Rc::new(vec![inner_struct])),
17490                        });
17491                    }
17492                }
17493            }
17494        }
17495
17496        // Check for missing required fields (type checking)
17497        if let Some(TypeDef::Struct(struct_def)) = self.types.get(&name) {
17498            if let crate::ast::StructFields::Named(def_fields) = &struct_def.fields {
17499                for def_field in def_fields {
17500                    if !field_values.contains_key(&def_field.name.name) {
17501                        return Err(RuntimeError::new(format!(
17502                            "missing field '{}' in struct '{}'",
17503                            def_field.name.name, name
17504                        )));
17505                    }
17506                }
17507            }
17508        }
17509
17510        // Inject const generic values as hidden fields from path generics
17511        // e.g., Shape1<3> {} → __const_N__ = 3
17512        if let Some(segment) = path.segments.first() {
17513            if let Some(generics) = &segment.generics {
17514                let base_name = &segment.ident.name;
17515                if let Some(param_names) = self.const_generic_params.get(base_name.as_str()).cloned() {
17516                    let mut idx = 0;
17517                    for generic in generics {
17518                        if idx >= param_names.len() { break; }
17519                        let val = match generic {
17520                            crate::ast::TypeExpr::ConstExpr(expr) => {
17521                                if let crate::ast::Expr::Literal(crate::ast::Literal::Int { value, .. }) = expr.as_ref() {
17522                                    value.parse::<i64>().ok()
17523                                } else { None }
17524                            }
17525                            crate::ast::TypeExpr::Path(inner_path) => {
17526                                if let Some(inner_seg) = inner_path.segments.first() {
17527                                    inner_seg.ident.name.parse::<i64>().ok()
17528                                } else { None }
17529                            }
17530                            _ => None,
17531                        };
17532                        if let Some(v) = val {
17533                            field_values.insert(
17534                                format!("__const_{}__", param_names[idx]),
17535                                Value::Int(v),
17536                            );
17537                            idx += 1;
17538                        }
17539                    }
17540                }
17541            }
17542        }
17543
17544        // Also inject from type_context.struct_generics (type annotation path)
17545        if let Some((ctx_name, ctx_values)) = self.type_context.struct_generics.borrow().clone() {
17546            if ctx_name == name {
17547                if let Some(param_names) = self.const_generic_params.get(&name).cloned() {
17548                    for (param_name, value) in param_names.iter().zip(ctx_values.iter()) {
17549                        let key = format!("__const_{}__", param_name);
17550                        if !field_values.contains_key(&key) {
17551                            field_values.insert(key, Value::Int(*value));
17552                        }
17553                    }
17554                }
17555            }
17556        }
17557
17558        // Also inject from current scope: if the struct type has const generic params,
17559        // check if those param names are defined as variables in the current environment.
17560        // This handles constructors like FixedVec·<5>·new() where N=5 is in scope.
17561        if let Some(param_names) = self.const_generic_params.get(&name).cloned() {
17562            for param_name in &param_names {
17563                let key = format!("__const_{}__", param_name);
17564                if !field_values.contains_key(&key) {
17565                    if let Some(val) = self.environment.borrow().get(param_name) {
17566                        if let Value::Int(_) = &val {
17567                            field_values.insert(key, val);
17568                        }
17569                    }
17570                }
17571            }
17572        }
17573
17574        Ok(Value::Struct {
17575            name,
17576            fields: Rc::new(RefCell::new(field_values)),
17577        })
17578    }
17579
17580    /// Extract evidentiality from a value (recursively unwraps Evidential wrapper)
17581    fn extract_evidence(value: &Value) -> Option<Evidence> {
17582        match value {
17583            Value::Evidential { evidence, .. } => Some(*evidence),
17584            _ => None,
17585        }
17586    }
17587
17588    /// Extract affect from a value
17589    fn extract_affect(value: &Value) -> Option<&RuntimeAffect> {
17590        match value {
17591            Value::Affective { affect, .. } => Some(affect),
17592            _ => None,
17593        }
17594    }
17595
17596    /// Derive evidence from affect markers.
17597    /// Sarcasm implies uncertainty (meaning is inverted).
17598    /// Confidence directly maps to evidence levels.
17599    fn affect_to_evidence(affect: &RuntimeAffect) -> Option<Evidence> {
17600        // Sarcasm indicates the literal meaning shouldn't be trusted
17601        if affect.sarcasm {
17602            return Some(Evidence::Uncertain);
17603        }
17604
17605        // Confidence maps directly to evidence
17606        match affect.confidence {
17607            Some(RuntimeConfidence::High) => Some(Evidence::Known),
17608            Some(RuntimeConfidence::Low) => Some(Evidence::Uncertain),
17609            Some(RuntimeConfidence::Medium) | None => None,
17610        }
17611    }
17612
17613    /// Combine two evidence levels, returning the "worst" (most uncertain) one.
17614    /// Order: Known < Uncertain < Reported < Paradox
17615    fn combine_evidence(a: Option<Evidence>, b: Option<Evidence>) -> Option<Evidence> {
17616        match (a, b) {
17617            (None, None) => None,
17618            (Some(e), None) | (None, Some(e)) => Some(e),
17619            (Some(a), Some(b)) => {
17620                let rank = |e: Evidence| match e {
17621                    Evidence::Known => 0,
17622                    Evidence::Uncertain => 1,
17623                    Evidence::Predicted => 2,
17624                    Evidence::Reported => 3,
17625                    Evidence::Paradox => 4,
17626                };
17627                if rank(a) >= rank(b) {
17628                    Some(a)
17629                } else {
17630                    Some(b)
17631                }
17632            }
17633        }
17634    }
17635
17636    /// Unwrap an evidential value to get the inner value for display
17637    fn unwrap_evidential(value: &Value) -> &Value {
17638        match value {
17639            Value::Evidential { value: inner, .. } => Self::unwrap_evidential(inner),
17640            _ => value,
17641        }
17642    }
17643
17644    /// Unwrap an affective value to get the inner value
17645    fn unwrap_affective(value: &Value) -> &Value {
17646        match value {
17647            Value::Affective { value: inner, .. } => Self::unwrap_affective(inner),
17648            _ => value,
17649        }
17650    }
17651
17652    /// Unwrap both evidential and affective wrappers
17653    fn unwrap_value(value: &Value) -> &Value {
17654        match value {
17655            Value::Evidential { value: inner, .. } => Self::unwrap_value(inner),
17656            Value::Affective { value: inner, .. } => Self::unwrap_value(inner),
17657            _ => value,
17658        }
17659    }
17660
17661    /// Unwrap all wrappers including Ref for deep value access
17662    fn unwrap_all(value: &Value) -> Value {
17663        match value {
17664            Value::Evidential { value: inner, .. } => Self::unwrap_all(inner),
17665            Value::Affective { value: inner, .. } => Self::unwrap_all(inner),
17666            Value::Ref(r) => Self::unwrap_all(&r.borrow()),
17667            _ => value.clone(),
17668        }
17669    }
17670
17671    fn eval_evidential(&mut self, expr: &Expr, ev: &Evidentiality) -> Result<Value, RuntimeError> {
17672        let value = self.evaluate(expr)?;
17673
17674        // When ? (Uncertain) is applied to Result or Option, act as try operator:
17675        // - Result::Ok(v) / Option::Some(v) → return v (unwrap)
17676        // - Result::Err(e) / Option::None / null → early return from function
17677        if matches!(ev, Evidentiality::Uncertain) {
17678            // Strip existing evidential wrapper first
17679            let unwrapped = match &value {
17680                Value::Evidential { value: inner, .. } => inner.as_ref().clone(),
17681                other => other.clone(),
17682            };
17683            match &unwrapped {
17684                Value::Variant { enum_name, variant_name, fields, .. }
17685                    if (enum_name == "Result" || enum_name == "Option")
17686                        && (variant_name == "Ok" || variant_name == "Some") =>
17687                {
17688                    // Unwrap Ok(v) or Some(v) → v
17689                    let inner_val = fields.as_ref()
17690                        .and_then(|f| f.first().cloned())
17691                        .unwrap_or(Value::Null);
17692                    return Ok(inner_val);
17693                }
17694                Value::Variant { enum_name, variant_name, .. }
17695                    if (enum_name == "Result" && variant_name == "Err")
17696                        || (enum_name == "Option" && variant_name == "None") =>
17697                {
17698                    // Early return with the error/none value
17699                    self.return_value = Some(unwrapped);
17700                    return Err(RuntimeError::new("return"));
17701                }
17702                Value::Null => {
17703                    self.return_value = Some(Value::Null);
17704                    return Err(RuntimeError::new("return"));
17705                }
17706                _ => {}
17707            }
17708        }
17709
17710        // All evidentiality markers wrap the value with the corresponding evidence level.
17711        // If the value is already evidential, re-wrap with the new evidence level.
17712        // Null propagates as-is (no evidence on null).
17713        if let Value::Null = &value {
17714            return Ok(Value::Null);
17715        }
17716
17717        let inner = match value {
17718            Value::Evidential { value: inner, .. } => *inner, // Strip existing evidence before re-wrapping
17719            other => other,
17720        };
17721
17722        let evidence = match ev {
17723            Evidentiality::Known => Evidence::Known,
17724            Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
17725            Evidentiality::Reported => Evidence::Reported,
17726            Evidentiality::Paradox => Evidence::Paradox,
17727        };
17728        Ok(Value::Evidential {
17729            value: Box::new(inner),
17730            evidence,
17731        })
17732    }
17733
17734    /// Expand a user-defined macro
17735    /// params: parameter names (without $)
17736    /// body: the macro body template
17737    /// tokens: the arguments passed to the macro invocation
17738    /// pipe_value: if called from pipe context, the piped value
17739    fn expand_user_macro(
17740        &mut self,
17741        params: &[String],
17742        body: &str,
17743        tokens: &str,
17744        pipe_value: Option<Value>,
17745        field_map: &HashMap<String, String>,
17746    ) -> Result<Value, RuntimeError> {
17747        // Build substitution map
17748        let mut substitutions: HashMap<String, String> = HashMap::new();
17749
17750        // Handle $__pipe for pipe-invoked macros
17751        if let Some(ref val) = pipe_value {
17752            substitutions.insert("__pipe".to_string(), self.value_to_source(val));
17753
17754            // If macro has parameters but tokens are empty, use pipe value as first parameter
17755            // This allows `3|double_it!{}` to work the same as `double_it!(3)`
17756            if !params.is_empty() && tokens.trim().is_empty() {
17757                substitutions.insert(params[0].clone(), self.value_to_source(val));
17758            }
17759        }
17760
17761        // Parse arguments from tokens and map to parameters
17762        let tokens = tokens.trim();
17763        if !params.is_empty() && !tokens.is_empty() {
17764            // Split tokens by comma, respecting nesting
17765            let args = self.split_macro_args(tokens);
17766
17767            // Try named argument matching first: "key: value" pairs
17768            // This handles rune patterns like ({ min: $min:expr, max: $max:expr })
17769            // Uses field_map to resolve field names → param names when they differ
17770            // e.g., pattern "{ prompt: $prompt_check:expr }" → field_map {"prompt" → "prompt_check"}
17771            let mut named_matched = false;
17772            for arg in &args {
17773                let trimmed = arg.trim();
17774                if let Some(colon_pos) = trimmed.find(':') {
17775                    let key = trimmed[..colon_pos].trim();
17776                    let value = trimmed[colon_pos + 1..].trim();
17777                    // First check field_map: field name → param name
17778                    if let Some(param_name) = field_map.get(key) {
17779                        substitutions.insert(param_name.clone(), value.to_string());
17780                        named_matched = true;
17781                    } else if params.contains(&key.to_string()) {
17782                        // Direct match: field name == param name
17783                        substitutions.insert(key.to_string(), value.to_string());
17784                        named_matched = true;
17785                    }
17786                }
17787            }
17788
17789            // Fall back to positional matching if no named args matched
17790            if !named_matched {
17791                for (i, param) in params.iter().enumerate() {
17792                    if i < args.len() {
17793                        substitutions.insert(param.clone(), args[i].trim().to_string());
17794                    }
17795                }
17796            }
17797        }
17798
17799        // Substitute $param with their values in the body
17800        let mut expanded = body.to_string();
17801        for (param, value) in &substitutions {
17802            // Replace $param with value (dollar-prefixed substitution)
17803            let pattern = format!("${}", param);
17804            expanded = expanded.replace(&pattern, value);
17805        }
17806
17807        // For rune-style macros: also replace bare __pipe references (without $)
17808        // This allows rune bodies to use `__pipe` directly instead of `$__pipe`
17809        if let Some(ref val) = pipe_value {
17810            let pipe_source = self.value_to_source(val);
17811            // Replace bare __pipe that aren't already part of $__pipe
17812            // Since we already replaced $__pipe above, bare __pipe is what remains
17813            expanded = expanded.replace("__pipe", &pipe_source);
17814        }
17815
17816        // Parse and evaluate the expanded expression
17817        let expr_source = format!("rite __macro_expand__() {{ {} }}", expanded);
17818        let mut parser = crate::Parser::new(&expr_source);
17819        match parser.parse_file() {
17820            Ok(file) => {
17821                // Find and execute the function
17822                for item in &file.items {
17823                    if let Item::Function(func) = &item.node {
17824                        if func.name.name == "__macro_expand__" {
17825                            // Create and call the function
17826                            let fn_value = self.create_function(func)?;
17827                            if let Value::Function(f) = fn_value {
17828                                return self.call_function(&f, Vec::new());
17829                            }
17830                            return Err(RuntimeError::new("Macro expansion failed: function not created"));
17831                        }
17832                    }
17833                }
17834                Err(RuntimeError::new("Macro expansion failed: no function created"))
17835            }
17836            Err(e) => Err(RuntimeError::new(format!(
17837                "Macro expansion parse error: {:?}",
17838                e
17839            ))),
17840        }
17841    }
17842
17843    /// Convert a Value to source code representation for macro substitution
17844    fn value_to_source(&self, val: &Value) -> String {
17845        match val {
17846            Value::Int(n) => n.to_string(),
17847            Value::Float(f) => format!("{:?}", f),
17848            Value::Bool(b) => b.to_string(),
17849            Value::String(s) => format!("\"{}\"", s),
17850            Value::Null => "null".to_string(),
17851            Value::Char(c) => format!("'{}'", c),
17852            Value::Array(arr) => {
17853                let arr = arr.borrow();
17854                let items: Vec<String> = arr.iter().map(|v| self.value_to_source(v)).collect();
17855                format!("[{}]", items.join(", "))
17856            }
17857            Value::Struct { name, fields } => {
17858                let fields = fields.borrow();
17859                let field_strs: Vec<String> = fields.iter()
17860                    .map(|(k, v)| format!("{}: {}", k, self.value_to_source(v)))
17861                    .collect();
17862                format!("{} {{ {} }}", name, field_strs.join(", "))
17863            }
17864            Value::Variant { enum_name, variant_name, fields } => {
17865                if let Some(f) = fields {
17866                    let args: Vec<String> = f.iter().map(|v| self.value_to_source(v)).collect();
17867                    format!("{}·{}({})", enum_name, variant_name, args.join(", "))
17868                } else {
17869                    format!("{}·{}", enum_name, variant_name)
17870                }
17871            }
17872            _ => format!("{}", val),
17873        }
17874    }
17875
17876    /// Split macro arguments by comma, respecting nesting
17877    fn split_macro_args(&self, tokens: &str) -> Vec<String> {
17878        let mut args = Vec::new();
17879        let mut current = String::new();
17880        let mut depth = 0;
17881
17882        for c in tokens.chars() {
17883            match c {
17884                '(' | '[' | '{' => {
17885                    depth += 1;
17886                    current.push(c);
17887                }
17888                ')' | ']' | '}' => {
17889                    depth -= 1;
17890                    current.push(c);
17891                }
17892                ',' if depth == 0 => {
17893                    args.push(current.trim().to_string());
17894                    current = String::new();
17895                }
17896                _ => current.push(c),
17897            }
17898        }
17899        if !current.is_empty() {
17900            args.push(current.trim().to_string());
17901        }
17902        args
17903    }
17904
17905    /// Evaluate format! macro - parse format string and arguments
17906    fn eval_format_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
17907        // Token string looks like: "\"format string\" , arg1 , arg2"
17908        // We need to parse this properly
17909
17910        // Find the format string (first quoted string)
17911        let tokens = tokens.trim();
17912        if !tokens.starts_with('"') {
17913            // No format string - just return the tokens as-is
17914            return Ok(Value::String(Rc::new(tokens.to_string())));
17915        }
17916
17917        // Find the end of the format string
17918        let mut in_escape = false;
17919        let mut format_end = 1;
17920        for (i, c) in tokens[1..].char_indices() {
17921            if in_escape {
17922                in_escape = false;
17923            } else if c == '\\' {
17924                in_escape = true;
17925            } else if c == '"' {
17926                format_end = i + 2; // +1 for starting quote, +1 for this quote
17927                break;
17928            }
17929        }
17930
17931        let format_str = &tokens[1..format_end - 1]; // Remove quotes
17932        crate::sigil_debug!("DEBUG format_str: '{}'", format_str);
17933        let args_str = if format_end < tokens.len() {
17934            tokens[format_end..].trim_start_matches(',').trim()
17935        } else {
17936            ""
17937        };
17938
17939        // Parse and evaluate arguments
17940        let mut arg_values: Vec<String> = Vec::new();
17941        if !args_str.is_empty() {
17942            // Split by comma, but respect parentheses/brackets
17943            let mut depth = 0;
17944            let mut current_arg = String::new();
17945            for c in args_str.chars() {
17946                match c {
17947                    '(' | '[' | '{' => {
17948                        depth += 1;
17949                        current_arg.push(c);
17950                    }
17951                    ')' | ']' | '}' => {
17952                        depth -= 1;
17953                        current_arg.push(c);
17954                    }
17955                    ',' if depth == 0 => {
17956                        let arg = current_arg.trim().to_string();
17957                        if !arg.is_empty() {
17958                            // Parse and evaluate the argument expression
17959                            let mut parser = crate::parser::Parser::new(&arg);
17960                            match parser.parse_expr() {
17961                                Ok(expr) => match self.evaluate(&expr) {
17962                                    Ok(val) => arg_values.push(self.format_value(&val)),
17963                                    Err(_) => arg_values.push(arg),
17964                                },
17965                                Err(_) => arg_values.push(arg),
17966                            }
17967                        }
17968                        current_arg.clear();
17969                    }
17970                    _ => current_arg.push(c),
17971                }
17972            }
17973            // Don't forget the last argument
17974            let arg = current_arg.trim().to_string();
17975            if !arg.is_empty() {
17976                let mut parser = crate::parser::Parser::new(&arg);
17977                match parser.parse_expr() {
17978                    Ok(expr) => match self.evaluate(&expr) {
17979                        Ok(val) => arg_values.push(self.format_value(&val)),
17980                        Err(_) => arg_values.push(arg),
17981                    },
17982                    Err(_) => arg_values.push(arg),
17983                }
17984            }
17985        }
17986
17987        // Format the string by replacing {} and {:?} with arguments
17988        let mut result = String::new();
17989        let mut arg_idx = 0;
17990        let mut chars = format_str.chars().peekable();
17991
17992        while let Some(c) = chars.next() {
17993            if c == '{' {
17994                if chars.peek() == Some(&'{') {
17995                    // Escaped {{ -> {
17996                    chars.next();
17997                    result.push('{');
17998                } else {
17999                    // Consume until }
18000                    let mut placeholder = String::new();
18001                    while let Some(pc) = chars.next() {
18002                        if pc == '}' {
18003                            break;
18004                        }
18005                        placeholder.push(pc);
18006                    }
18007                    // Insert argument value
18008                    if arg_idx < arg_values.len() {
18009                        result.push_str(&arg_values[arg_idx]);
18010                        arg_idx += 1;
18011                    } else {
18012                        result.push_str(&format!("{{{}}}", placeholder));
18013                    }
18014                }
18015            } else if c == '}' {
18016                if chars.peek() == Some(&'}') {
18017                    // Escaped }} -> }
18018                    chars.next();
18019                    result.push('}');
18020                } else {
18021                    result.push('}');
18022                }
18023            } else if c == '\\' {
18024                // Handle escape sequences
18025                if let Some(next) = chars.next() {
18026                    match next {
18027                        'n' => result.push('\n'),
18028                        't' => result.push('\t'),
18029                        'r' => result.push('\r'),
18030                        '\\' => result.push('\\'),
18031                        '"' => result.push('"'),
18032                        _ => {
18033                            result.push('\\');
18034                            result.push(next);
18035                        }
18036                    }
18037                }
18038            } else {
18039                result.push(c);
18040            }
18041        }
18042
18043        Ok(Value::String(Rc::new(result)))
18044    }
18045
18046    /// Infer the type of an expression without evaluating it (for type checking)
18047    /// Returns None if type cannot be determined statically
18048    fn infer_expr_type(&self, expr: &Expr) -> Option<String> {
18049        match expr {
18050            Expr::Literal(lit) => match lit {
18051                Literal::Int { .. } => Some("i32".to_string()),
18052                Literal::Float { .. } => Some("f64".to_string()),
18053                Literal::String(_) | Literal::RawString(_) => Some("String".to_string()),
18054                Literal::Bool(_) => Some("bool".to_string()),
18055                Literal::Char(_) => Some("char".to_string()),
18056                Literal::Null => Some("null".to_string()),
18057                _ => None,
18058            },
18059            Expr::Array(elements) => {
18060                // Infer element type from first element
18061                if let Some(first) = elements.first() {
18062                    if let Some(elem_type) = self.infer_expr_type(first) {
18063                        return Some(format!("[{}]", elem_type));
18064                    }
18065                }
18066                Some("[_]".to_string())
18067            }
18068            Expr::Tuple(elements) => {
18069                let types: Vec<String> = elements
18070                    .iter()
18071                    .filter_map(|e| self.infer_expr_type(e))
18072                    .collect();
18073                Some(format!("({})", types.join(", ")))
18074            }
18075            Expr::Block(block) => {
18076                // Type of block is type of last expression or return
18077                if let Some(ref e) = block.expr {
18078                    return self.infer_expr_type(e);
18079                }
18080                Some("()".to_string())
18081            }
18082            Expr::If {
18083                then_branch,
18084                else_branch,
18085                ..
18086            } => {
18087                // Prefer then branch type - check last expr in block
18088                if let Some(ref e) = then_branch.expr {
18089                    if let Some(t) = self.infer_expr_type(e) {
18090                        return Some(t);
18091                    }
18092                }
18093                if let Some(e) = else_branch {
18094                    return self.infer_expr_type(e);
18095                }
18096                None
18097            }
18098            _ => None, // Cannot determine type statically for complex expressions
18099        }
18100    }
18101
18102    /// Get the runtime type name of a Value
18103    fn value_type_name(&self, value: &Value) -> String {
18104        match value {
18105            Value::Int(_) => "i32".to_string(),
18106            Value::Float(_) => "f64".to_string(),
18107            Value::String(_) => "String".to_string(),
18108            Value::Bool(_) => "bool".to_string(),
18109            Value::Char(_) => "char".to_string(),
18110            Value::Null => "null".to_string(),
18111            Value::Array(_) => "Array".to_string(),
18112            Value::Tuple(_) => "Tuple".to_string(),
18113            Value::Struct { name, .. } => name.clone(),
18114            Value::Variant { enum_name, .. } => enum_name.clone(),
18115            Value::Function(_) => "Function".to_string(),
18116            Value::BuiltIn(_) => "BuiltIn".to_string(),
18117            Value::Ref(_) => "Ref".to_string(),
18118            _ => "unknown".to_string(),
18119        }
18120    }
18121
18122    /// Extract type name and generic type parameters from a TypeExpr
18123    /// e.g., Option<i32> -> ("Option", ["i32"]), Result<i32, String> -> ("Result", ["i32", "String"])
18124    fn extract_type_params(
18125        &self,
18126        type_expr: &crate::ast::TypeExpr,
18127    ) -> Option<(String, Vec<String>)> {
18128        use crate::ast::TypeExpr;
18129
18130        if let TypeExpr::Path(path) = type_expr {
18131            if let Some(segment) = path.segments.first() {
18132                let type_name = segment.ident.name.clone();
18133                if let Some(generics) = &segment.generics {
18134                    let mut type_params: Vec<String> = Vec::new();
18135                    for generic in generics {
18136                        if let TypeExpr::Path(inner_path) = generic {
18137                            if let Some(inner_seg) = inner_path.segments.first() {
18138                                type_params.push(inner_seg.ident.name.clone());
18139                            }
18140                        }
18141                    }
18142                    return Some((type_name, type_params));
18143                }
18144                return Some((type_name, vec![]));
18145            }
18146        }
18147        None
18148    }
18149
18150    /// Check if a value matches the expected generic type for Option/Result
18151    fn check_generic_type_match(
18152        &self,
18153        type_name: &str,
18154        type_params: &[String],
18155        value: &Value,
18156    ) -> Result<(), RuntimeError> {
18157        match (type_name, value) {
18158            // Option<T>: Some(x) must have x: T
18159            (
18160                "Option",
18161                Value::Variant {
18162                    enum_name,
18163                    variant_name,
18164                    fields,
18165                },
18166            ) if enum_name == "Option" && variant_name == "Some" => {
18167                if let (Some(expected_type), Some(fields)) = (type_params.first(), fields) {
18168                    if let Some(inner_value) = fields.first() {
18169                        let actual_type = self.value_type_name(inner_value);
18170                        if &actual_type != expected_type {
18171                            return Err(RuntimeError::new(format!(
18172                                "type mismatch: expected Option<{}>, found Some({})",
18173                                expected_type, actual_type
18174                            )));
18175                        }
18176                    }
18177                }
18178            }
18179            // Result<T, E>: Ok(x) must have x: T
18180            (
18181                "Result",
18182                Value::Variant {
18183                    enum_name,
18184                    variant_name,
18185                    fields,
18186                },
18187            ) if enum_name == "Result" && variant_name == "Ok" => {
18188                if let (Some(expected_type), Some(fields)) = (type_params.first(), fields) {
18189                    if let Some(inner_value) = fields.first() {
18190                        let actual_type = self.value_type_name(inner_value);
18191                        if &actual_type != expected_type {
18192                            return Err(RuntimeError::new(format!(
18193                                "type mismatch: expected Result<{}, _>, found Ok({})",
18194                                expected_type, actual_type
18195                            )));
18196                        }
18197                    }
18198                }
18199            }
18200            // Result<T, E>: Err(e) must have e: E
18201            (
18202                "Result",
18203                Value::Variant {
18204                    enum_name,
18205                    variant_name,
18206                    fields,
18207                },
18208            ) if enum_name == "Result" && variant_name == "Err" => {
18209                if let (Some(expected_type), Some(fields)) = (type_params.get(1), fields) {
18210                    if let Some(inner_value) = fields.first() {
18211                        let actual_type = self.value_type_name(inner_value);
18212                        if &actual_type != expected_type {
18213                            return Err(RuntimeError::new(format!(
18214                                "type mismatch: expected Result<_, {}>, found Err({})",
18215                                expected_type, actual_type
18216                            )));
18217                        }
18218                    }
18219                }
18220            }
18221            _ => {} // No check needed
18222        }
18223        Ok(())
18224    }
18225
18226    /// Format a value for display in format!
18227    fn format_value(&self, value: &Value) -> String {
18228        match value {
18229            Value::String(s) => s.to_string(),
18230            Value::Int(n) => n.to_string(),
18231            Value::Float(f) => f.to_string(),
18232            Value::Bool(b) => b.to_string(),
18233            Value::Char(c) => c.to_string(),
18234            Value::Null => "null".to_string(),
18235            Value::Array(arr) => {
18236                let items: Vec<String> =
18237                    arr.borrow().iter().map(|v| self.format_value(v)).collect();
18238                format!("[{}]", items.join(", "))
18239            }
18240            Value::Tuple(items) => {
18241                let formatted: Vec<String> = items.iter().map(|v| self.format_value(v)).collect();
18242                format!("({})", formatted.join(", "))
18243            }
18244            Value::Struct { name, fields } => {
18245                let field_strs: Vec<String> = fields
18246                    .borrow()
18247                    .iter()
18248                    .map(|(k, v)| format!("{}: {}", k, self.format_value(v)))
18249                    .collect();
18250                format!("{} {{ {} }}", name, field_strs.join(", "))
18251            }
18252            Value::Variant {
18253                enum_name,
18254                variant_name,
18255                fields,
18256            } => match fields {
18257                Some(f) if !f.is_empty() => {
18258                    let formatted: Vec<String> = f.iter().map(|v| self.format_value(v)).collect();
18259                    format!("{}::{}({})", enum_name, variant_name, formatted.join(", "))
18260                }
18261                _ => format!("{}::{}", enum_name, variant_name),
18262            },
18263            Value::Evidential {
18264                value: inner,
18265                evidence,
18266            } => {
18267                format!("{:?}{}", evidence, self.format_value(inner))
18268            }
18269            Value::Ref(r) => self.format_value(&r.borrow()),
18270            _ => format!("{:?}", value),
18271        }
18272    }
18273
18274    /// Evaluate vec! macro
18275    fn eval_vec_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
18276        // Check for fill syntax: vec![value; count]
18277        // Find ';' at depth 0
18278        let mut depth = 0;
18279        let mut semicolon_pos = None;
18280        for (i, c) in tokens.chars().enumerate() {
18281            match c {
18282                '(' | '[' | '{' => depth += 1,
18283                ')' | ']' | '}' => depth -= 1,
18284                ';' if depth == 0 => {
18285                    semicolon_pos = Some(i);
18286                    break;
18287                }
18288                _ => {}
18289            }
18290        }
18291
18292        if let Some(pos) = semicolon_pos {
18293            // Fill syntax: vec![value; count]
18294            let value_str = tokens[..pos].trim();
18295            let count_str = tokens[pos + 1..].trim();
18296
18297            let mut parser = crate::parser::Parser::new(value_str);
18298            let value_expr = parser.parse_expr().map_err(|e| RuntimeError::new(format!("vec! fill value parse error: {}", e)))?;
18299            let value = self.evaluate(&value_expr)?;
18300
18301            let mut parser = crate::parser::Parser::new(count_str);
18302            let count_expr = parser.parse_expr().map_err(|e| RuntimeError::new(format!("vec! fill count parse error: {}", e)))?;
18303            let count_val = self.evaluate(&count_expr)?;
18304            let count = match count_val {
18305                Value::Int(n) => n as usize,
18306                _ => return Err(RuntimeError::new(format!("vec! fill count must be integer, got {:?}", count_val))),
18307            };
18308
18309            let elements: Vec<Value> = (0..count).map(|_| value.clone()).collect();
18310            return Ok(Value::Array(Rc::new(RefCell::new(elements))));
18311        }
18312
18313        // Parse comma-separated elements
18314        let mut elements = Vec::new();
18315        depth = 0;
18316        let mut current = String::new();
18317
18318        for c in tokens.chars() {
18319            match c {
18320                '(' | '[' | '{' => {
18321                    depth += 1;
18322                    current.push(c);
18323                }
18324                ')' | ']' | '}' => {
18325                    depth -= 1;
18326                    current.push(c);
18327                }
18328                ',' if depth == 0 => {
18329                    let elem = current.trim().to_string();
18330                    if !elem.is_empty() {
18331                        let mut parser = crate::parser::Parser::new(&elem);
18332                        if let Ok(expr) = parser.parse_expr() {
18333                            elements.push(self.evaluate(&expr)?);
18334                        }
18335                    }
18336                    current.clear();
18337                }
18338                _ => current.push(c),
18339            }
18340        }
18341
18342        // Last element
18343        let elem = current.trim().to_string();
18344        if !elem.is_empty() {
18345            let mut parser = crate::parser::Parser::new(&elem);
18346            if let Ok(expr) = parser.parse_expr() {
18347                elements.push(self.evaluate(&expr)?);
18348            }
18349        }
18350
18351        Ok(Value::Array(Rc::new(RefCell::new(elements))))
18352    }
18353
18354    fn eval_range(
18355        &mut self,
18356        start: &Option<Box<Expr>>,
18357        end: &Option<Box<Expr>>,
18358        inclusive: bool,
18359    ) -> Result<Value, RuntimeError> {
18360        let start_val = match start {
18361            Some(e) => match self.evaluate(e)? {
18362                Value::Int(n) => n,
18363                _ => return Err(RuntimeError::new("Range requires integer bounds")),
18364            },
18365            None => 0,
18366        };
18367
18368        let end_val = match end {
18369            Some(e) => match self.evaluate(e)? {
18370                Value::Int(n) => n,
18371                _ => return Err(RuntimeError::new("Range requires integer bounds")),
18372            },
18373            None => {
18374                // Open-ended range (like 1..) - return a tuple (start, None) marker
18375                // This can be used by slice operations to slice to end
18376                return Ok(Value::Tuple(Rc::new(vec![
18377                    Value::Int(start_val),
18378                    Value::Null, // None marker for open end
18379                ])));
18380            }
18381        };
18382
18383        let values: Vec<Value> = if inclusive {
18384            (start_val..=end_val).map(Value::Int).collect()
18385        } else {
18386            (start_val..end_val).map(Value::Int).collect()
18387        };
18388
18389        Ok(Value::Array(Rc::new(RefCell::new(values))))
18390    }
18391
18392    fn is_truthy(&self, value: &Value) -> bool {
18393        match value {
18394            Value::Null => false,
18395            Value::Bool(b) => *b,
18396            Value::Int(n) => *n != 0,
18397            Value::Float(n) => *n != 0.0,
18398            Value::String(s) => !s.is_empty(),
18399            Value::Array(arr) => !arr.borrow().is_empty(),
18400            Value::Empty => false,
18401            Value::Evidential { value, .. } => self.is_truthy(value),
18402            _ => true,
18403        }
18404    }
18405}
18406
18407impl Default for Interpreter {
18408    fn default() -> Self {
18409        Self::new()
18410    }
18411}
18412
18413#[cfg(test)]
18414mod tests {
18415    use super::*;
18416    use crate::Parser;
18417
18418    fn run(source: &str) -> Result<Value, RuntimeError> {
18419        let mut parser = Parser::new(source);
18420        let file = parser
18421            .parse_file()
18422            .map_err(|e| RuntimeError::new(e.to_string()))?;
18423        let mut interp = Interpreter::new();
18424        interp.execute(&file)
18425    }
18426
18427    #[test]
18428    fn test_arithmetic() {
18429        assert!(matches!(run("rite main() { ⤺ 2 + 3; }"), Ok(Value::Int(5))));
18430        assert!(matches!(
18431            run("rite main() { ⤺ 10 - 4; }"),
18432            Ok(Value::Int(6))
18433        ));
18434        assert!(matches!(
18435            run("rite main() { ⤺ 3 * 4; }"),
18436            Ok(Value::Int(12))
18437        ));
18438        assert!(matches!(
18439            run("rite main() { ⤺ 15 / 3; }"),
18440            Ok(Value::Int(5))
18441        ));
18442        assert!(matches!(
18443            run("rite main() { ⤺ 2 ** 10; }"),
18444            Ok(Value::Int(1024))
18445        ));
18446    }
18447
18448    #[test]
18449    fn test_variables() {
18450        assert!(matches!(
18451            run("rite main() { ≔ x = 42; ⤺ x; }"),
18452            Ok(Value::Int(42))
18453        ));
18454    }
18455
18456    #[test]
18457    fn test_conditionals() {
18458        assert!(matches!(
18459            run("rite main() { ⎇ true { ⤺ 1; } ⎉ { ⤺ 2; } }"),
18460            Ok(Value::Int(1))
18461        ));
18462        assert!(matches!(
18463            run("rite main() { ⎇ false { ⤺ 1; } ⎉ { ⤺ 2; } }"),
18464            Ok(Value::Int(2))
18465        ));
18466    }
18467
18468    #[test]
18469    fn test_arrays() {
18470        assert!(matches!(
18471            run("rite main() { ⤺ [1, 2, 3][1]; }"),
18472            Ok(Value::Int(2))
18473        ));
18474    }
18475
18476    #[test]
18477    fn test_functions() {
18478        let result = run("
18479            rite double(x: i64) → i64 { ⤺ x * 2; }
18480            rite main() { ⤺ double(21); }
18481        ");
18482        assert!(matches!(result, Ok(Value::Int(42))));
18483    }
18484
18485    #[test]
18486    fn test_pipe_transform() {
18487        let result = run("rite main() { ⤺ [1, 2, 3]|τ{_ * 2}|sum; }");
18488        assert!(matches!(result, Ok(Value::Int(12))));
18489    }
18490
18491    #[test]
18492    fn test_pipe_filter() {
18493        let result = run("rite main() { ⤺ [1, 2, 3, 4, 5]|φ{_ > 2}|sum; }");
18494        assert!(matches!(result, Ok(Value::Int(12)))); // 3 + 4 + 5
18495    }
18496
18497    #[test]
18498    fn test_interpolation_evidentiality_propagation() {
18499        // Test that evidentiality propagates through string interpolation
18500        // When an evidential value is interpolated, the result string should carry that evidentiality
18501        let result = run(r#"
18502            rite main() {
18503                ≔ rep = reported(42);
18504
18505                // Interpolating a reported value should make the string reported
18506                ≔ s = f"Value: {rep}";
18507                ⤺ s;
18508            }
18509        "#);
18510
18511        match result {
18512            Ok(Value::Evidential {
18513                evidence: Evidence::Reported,
18514                value,
18515            }) => {
18516                // The inner value should be a string
18517                assert!(matches!(*value, Value::String(_)));
18518            }
18519            Ok(other) => panic!("Expected Evidential Reported, got {:?}", other),
18520            Err(e) => panic!("Error: {:?}", e),
18521        }
18522    }
18523
18524    #[test]
18525    fn test_interpolation_worst_evidence_wins() {
18526        // When multiple evidential values are interpolated, the worst evidence level wins
18527        let result = run(r#"
18528            rite main() {
18529                ≔ k = known(1);         // Known is best
18530                ≔ u = uncertain(2);     // Uncertain is worse
18531
18532                // Combining known and uncertain should yield uncertain
18533                ≔ s = f"{k} and {u}";
18534                ⤺ s;
18535            }
18536        "#);
18537
18538        match result {
18539            Ok(Value::Evidential {
18540                evidence: Evidence::Uncertain,
18541                ..
18542            }) => (),
18543            Ok(other) => panic!("Expected Evidential Uncertain, got {:?}", other),
18544            Err(e) => panic!("Error: {:?}", e),
18545        }
18546    }
18547
18548    #[test]
18549    fn test_interpolation_no_evidential_plain_string() {
18550        // When no evidential values are interpolated, the result is a plain string
18551        let result = run(r#"
18552            rite main() {
18553                ≔ x = 42;
18554                ≔ s = f"Value: {x}";
18555                ⤺ s;
18556            }
18557        "#);
18558
18559        match result {
18560            Ok(Value::String(s)) => {
18561                assert_eq!(*s, "Value: 42");
18562            }
18563            Ok(other) => panic!("Expected plain String, got {:?}", other),
18564            Err(e) => panic!("Error: {:?}", e),
18565        }
18566    }
18567}