ruchy/runtime/
interpreter.rs

1//! High-Performance Interpreter with Safe Value Representation
2//!
3//! This module implements the two-tier execution strategy from ruchy-interpreter-spec.md:
4//! - Tier 0: AST interpreter with enum-based values (safe alternative)
5//! - Tier 1: JIT compilation (future)
6//!
7//! Uses safe Rust enum approach instead of tagged pointers to respect `unsafe_code = "forbid"`.
8
9#![allow(clippy::unused_self)] // Methods will use self in future phases
10#![allow(clippy::only_used_in_recursion)] // Recursive print_value is intentional
11#![allow(clippy::uninlined_format_args)] // Some format strings are clearer unexpanded
12#![allow(clippy::cast_precision_loss)] // Acceptable for arithmetic operations
13#![allow(clippy::expect_used)] // Used appropriately in tests
14#![allow(clippy::cast_possible_truncation)] // Controlled truncations for indices
15#![allow(unsafe_code)] // Required for CallFrame Send implementation - see DEFECT-001-B
16
17use super::eval_expr;
18use super::eval_func;
19use super::eval_literal;
20use super::eval_method;
21use super::eval_operations;
22use crate::frontend::ast::{
23    BinaryOp as AstBinaryOp, Expr, ExprKind, Literal, MatchArm, Pattern, StringPart,
24};
25use crate::frontend::Param;
26use smallvec::{smallvec, SmallVec};
27use std::collections::HashMap;
28use std::sync::Arc;
29
30/// Control flow for loop iterations or error
31#[derive(Debug)]
32enum LoopControlOrError {
33    Break(Option<String>, Value),
34    Continue(Option<String>),
35    Return(Value), // Early return from function (exits both loop and function)
36    Error(InterpreterError),
37}
38
39/// `DataFrame` column representation for the interpreter
40#[derive(Debug, Clone)]
41pub struct DataFrameColumn {
42    pub name: String,
43    pub values: Vec<Value>,
44}
45
46/// Runtime value representation using safe enum approach.
47///
48/// `Value` represents all runtime values in the Ruchy interpreter. This is an
49/// enum-based approach that avoids unsafe code while maintaining good performance
50/// through strategic use of `Rc` for heap-allocated data.
51///
52/// # Examples
53///
54/// ```
55/// use ruchy::runtime::interpreter::Value;
56///
57/// let int_val = Value::from_i64(42);
58/// let str_val = Value::from_string("hello".to_string());
59/// let arr_val = Value::from_array(vec![int_val.clone(), str_val]);
60/// ```
61#[derive(Clone, Debug)]
62pub enum Value {
63    /// 64-bit signed integer
64    Integer(i64),
65    /// 64-bit float
66    Float(f64),
67    /// Boolean value
68    Bool(bool),
69    /// Byte value (0-255)
70    Byte(u8),
71    /// Nil/null value
72    Nil,
73    /// String value (reference-counted for efficiency, thread-safe)
74    String(Arc<str>),
75    /// Array of values
76    Array(Arc<[Value]>),
77    /// Tuple of values
78    Tuple(Arc<[Value]>),
79    /// Function closure
80    Closure {
81        params: Vec<String>,
82        body: Arc<Expr>,
83        env: Arc<HashMap<String, Value>>, // Captured environment
84    },
85    /// `DataFrame` value
86    DataFrame { columns: Vec<DataFrameColumn> },
87    /// Object/HashMap value for key-value mappings (immutable)
88    Object(Arc<HashMap<String, Value>>),
89    /// Mutable object with interior mutability (for actors and classes, thread-safe)
90    ObjectMut(Arc<std::sync::Mutex<HashMap<String, Value>>>),
91    /// Range value for representing ranges
92    Range {
93        start: Box<Value>,
94        end: Box<Value>,
95        inclusive: bool,
96    },
97    /// Enum variant value
98    EnumVariant {
99        enum_name: String,       // The enum type (e.g., "LogLevel")
100        variant_name: String,    // The variant (e.g., "Debug", "Info")
101        data: Option<Vec<Value>>,
102    },
103    /// Built-in function reference
104    BuiltinFunction(String),
105    /// Struct instance (value type with named fields)
106    /// Thread-safe via Arc, value semantics via cloning
107    Struct {
108        name: String,
109        fields: Arc<HashMap<String, Value>>,
110    },
111    /// Class instance (reference type with methods)
112    /// Thread-safe via Arc, reference semantics, mutable via `RwLock`
113    /// Identity-based equality (pointer comparison)
114    Class {
115        class_name: String,
116        fields: Arc<std::sync::RwLock<HashMap<String, Value>>>,
117        methods: Arc<HashMap<String, Value>>, // method name -> Closure
118    },
119    /// HTML document (HTTP-002-C)
120    #[cfg(not(target_arch = "wasm32"))]
121    HtmlDocument(crate::stdlib::html::HtmlDocument),
122    /// HTML element (HTTP-002-C)
123    #[cfg(not(target_arch = "wasm32"))]
124    HtmlElement(crate::stdlib::html::HtmlElement),
125}
126
127// Manual PartialEq implementation because Mutex doesn't implement PartialEq
128// ObjectMut uses identity-based equality (Arc pointer comparison) since it represents mutable state
129impl PartialEq for Value {
130    fn eq(&self, other: &Self) -> bool {
131        match (self, other) {
132            (Value::Integer(a), Value::Integer(b)) => a == b,
133            (Value::Float(a), Value::Float(b)) => a == b,
134            (Value::String(a), Value::String(b)) => a == b,
135            (Value::Bool(a), Value::Bool(b)) => a == b,
136            (Value::Array(a), Value::Array(b)) => a == b,
137            (Value::Tuple(a), Value::Tuple(b)) => a == b,
138            (Value::Object(a), Value::Object(b)) => Arc::ptr_eq(a, b) || **a == **b,
139            (Value::ObjectMut(a), Value::ObjectMut(b)) => Arc::ptr_eq(a, b), // Identity-based
140            (Value::Struct { name: n1, fields: f1 }, Value::Struct { name: n2, fields: f2 }) => {
141                n1 == n2 && **f1 == **f2 // Value equality (compare fields)
142            }
143            (Value::Class { fields: f1, .. }, Value::Class { fields: f2, .. }) => {
144                Arc::ptr_eq(f1, f2) // Identity-based: same instance only
145            }
146            (Value::Nil, Value::Nil) => true,
147            (Value::Byte(a), Value::Byte(b)) => a == b,
148            #[cfg(not(target_arch = "wasm32"))]
149            (Value::HtmlDocument(_), Value::HtmlDocument(_)) => false, // Documents compared by identity
150            #[cfg(not(target_arch = "wasm32"))]
151            (Value::HtmlElement(_), Value::HtmlElement(_)) => false, // Elements compared by identity
152            _ => false, // Different variants are not equal
153        }
154    }
155}
156
157impl Value {
158    /// Get the type ID for this value for caching purposes
159    ///
160    /// # Complexity
161    /// Cyclomatic complexity: 10 (within Toyota Way limits, just barely)
162    pub fn type_id(&self) -> std::any::TypeId {
163        use std::any::TypeId;
164        match self {
165            Value::Integer(_) => TypeId::of::<i64>(),
166            Value::Float(_) => TypeId::of::<f64>(),
167            Value::Bool(_) => TypeId::of::<bool>(),
168            Value::Byte(_) => TypeId::of::<u8>(),
169            Value::String(_) => TypeId::of::<String>(),
170            Value::Nil => TypeId::of::<()>(),
171            Value::Array(_) => TypeId::of::<Vec<Value>>(),
172            Value::Tuple(_) => TypeId::of::<(Value,)>(), // Generic tuple marker
173            Value::Closure { .. } => TypeId::of::<fn()>(), // Generic closure marker
174            Value::DataFrame { .. } => TypeId::of::<crate::runtime::DataFrameColumn>(),
175            Value::Object(_) => TypeId::of::<HashMap<String, Value>>(),
176            Value::ObjectMut(_) => TypeId::of::<HashMap<String, Value>>(),
177            Value::Range { .. } => TypeId::of::<std::ops::Range<i64>>(),
178            Value::EnumVariant { .. } => TypeId::of::<(String, Option<Vec<Value>>)>(),
179            Value::BuiltinFunction(_) => TypeId::of::<fn()>(),
180            Value::Struct { .. } => TypeId::of::<HashMap<String, Value>>(),
181            Value::Class { .. } => TypeId::of::<HashMap<String, Value>>(),
182            #[cfg(not(target_arch = "wasm32"))]
183            Value::HtmlDocument(_) => TypeId::of::<crate::stdlib::html::HtmlDocument>(),
184            #[cfg(not(target_arch = "wasm32"))]
185            Value::HtmlElement(_) => TypeId::of::<crate::stdlib::html::HtmlElement>(),
186        }
187    }
188}
189
190// Value utility methods moved to value_utils.rs
191
192// Note: Complex object structures (ObjectHeader, Class, etc.) will be implemented
193// in Phase 1 of the interpreter spec when we add proper GC and method dispatch.
194
195/// Runtime interpreter state.
196///
197/// The `Interpreter` manages the execution environment for Ruchy programs.
198/// It maintains:
199/// - A value stack for computation
200/// - Environment stack for lexical scoping
201/// - Inline caches for field/method optimization
202/// - Type feedback for future JIT compilation
203/// - Conservative garbage collection
204///
205/// # Implementation Strategy
206///
207/// This follows a two-tier execution model:
208/// - **Tier 0**: AST interpretation (current)
209/// - **Tier 1**: JIT compilation (future)
210///
211/// Type feedback and execution counts are collected for hot code
212/// identification and optimization.
213#[derive(Debug)]
214pub struct Interpreter {
215    /// Tagged pointer values for fast operation
216    stack: Vec<Value>,
217
218    /// Environment stack for lexical scoping
219    env_stack: Vec<HashMap<std::string::String, Value>>,
220
221    /// Call frame for function calls
222    #[allow(dead_code)]
223    frames: Vec<CallFrame>,
224
225    /// Execution statistics for tier transition (will be used in Phase 1)
226    #[allow(dead_code)]
227    execution_counts: HashMap<usize, u32>, // Function/method ID -> execution count
228
229    /// Inline caches for field/method access optimization
230    field_caches: HashMap<String, InlineCache>,
231
232    /// Type feedback collection for JIT compilation
233    type_feedback: TypeFeedback,
234
235    /// Conservative garbage collector
236    gc: ConservativeGC,
237
238    /// Error handler scopes for try/catch
239    error_scopes: Vec<ErrorScope>,
240
241    /// Stdout buffer for capturing println output (WASM/REPL)
242    /// Complexity: 1 (simple field addition)
243    stdout_buffer: Vec<String>,
244}
245
246/// Error scope for try/catch blocks
247#[derive(Debug, Clone)]
248struct ErrorScope {
249    /// Depth of environment stack when try block started
250    env_depth: usize,
251}
252
253/// Call frame for function invocation (will be used in Phase 1)
254#[derive(Debug)]
255#[allow(dead_code)]
256pub struct CallFrame {
257    /// Function being executed
258    closure: Value,
259
260    /// Instruction pointer
261    ip: *const u8,
262
263    /// Base of stack frame
264    base: usize,
265
266    /// Number of locals in this frame
267    locals: usize,
268}
269
270// SAFETY: CallFrame can safely be Send because:
271// 1. The `ip` raw pointer points to immutable bytecode that never changes
272// 2. CallFrame has exclusive ownership of the data (no sharing)
273// 3. The pointer is never dereferenced across thread boundaries
274// 4. CallFrame is only used in single-threaded execution contexts within each thread
275// 5. When Repl is shared across threads, each thread gets its own CallFrame instance
276unsafe impl Send for CallFrame {}
277
278/// Interpreter execution result
279pub enum InterpreterResult {
280    Continue,
281    Jump(usize),
282    Return(Value),
283    Error(InterpreterError),
284}
285
286/// Errors that can occur during interpretation.
287///
288/// # Examples
289///
290/// ```
291/// use ruchy::runtime::interpreter::InterpreterError;
292///
293/// let err = InterpreterError::TypeError("Expected integer".to_string());
294/// assert_eq!(err.to_string(), "Type error: Expected integer");
295/// ```
296#[derive(Debug, Clone)]
297pub enum InterpreterError {
298    TypeError(std::string::String),
299    RuntimeError(std::string::String),
300    StackOverflow,
301    StackUnderflow,
302    InvalidInstruction,
303    DivisionByZero,
304    IndexOutOfBounds,
305    Break(Option<String>, Value),
306    Continue(Option<String>),
307    Return(Value),
308    Throw(Value), // EXTREME TDD: Exception handling
309    AssertionFailed(std::string::String), // BUG-037: Test assertions
310    /// Recursion depth limit exceeded (`current_depth`, `max_depth`)
311    /// Added via [RUNTIME-001] fix for stack overflow crashes
312    RecursionLimitExceeded(usize, usize),
313}
314
315// Display implementations moved to eval_display.rs
316
317/// Inline cache states for polymorphic method dispatch
318#[derive(Clone, Copy, Debug, PartialEq, Eq)]
319pub enum CacheState {
320    /// No cache entry yet
321    Uninitialized,
322    /// Single type cached - fastest path
323    Monomorphic,
324    /// 2-4 types cached - still fast
325    Polymorphic,
326    /// Too many types - fallback to hash lookup
327    Megamorphic,
328}
329
330/// Cache entry for field access optimization
331#[derive(Clone, Debug)]
332pub struct CacheEntry {
333    /// Type identifier for cache validity
334    type_id: std::any::TypeId,
335    /// Field name being accessed
336    field_name: String,
337    /// Cached result for this type/field combination
338    cached_result: Value,
339    /// Hit count for LRU eviction
340    hit_count: u32,
341}
342
343/// Inline cache for method/field dispatch
344#[derive(Clone, Debug)]
345pub struct InlineCache {
346    /// Current cache state
347    state: CacheState,
348    /// Cache entries (inline storage for 2 common entries)
349    entries: SmallVec<[CacheEntry; 2]>,
350    /// Total hit count
351    total_hits: u32,
352    /// Total miss count
353    total_misses: u32,
354}
355
356impl InlineCache {
357    /// Create new empty inline cache
358    pub fn new() -> Self {
359        Self {
360            state: CacheState::Uninitialized,
361            entries: smallvec![],
362            total_hits: 0,
363            total_misses: 0,
364        }
365    }
366
367    /// Look up a field access in the cache
368    pub fn lookup(&mut self, obj: &Value, field_name: &str) -> Option<Value> {
369        let type_id = obj.type_id();
370
371        // Fast path: check cached entries
372        for entry in &mut self.entries {
373            if entry.type_id == type_id && entry.field_name == field_name {
374                entry.hit_count += 1;
375                self.total_hits += 1;
376                return Some(entry.cached_result.clone());
377            }
378        }
379
380        // Cache miss
381        self.total_misses += 1;
382        None
383    }
384
385    /// Add a new cache entry
386    pub fn insert(&mut self, obj: &Value, field_name: String, result: Value) {
387        let type_id = obj.type_id();
388        let entry = CacheEntry {
389            type_id,
390            field_name,
391            cached_result: result,
392            hit_count: 1,
393        };
394
395        // Update cache state based on entry count
396        match self.entries.len() {
397            0 => {
398                self.state = CacheState::Monomorphic;
399                self.entries.push(entry);
400            }
401            1..=3 => {
402                self.state = CacheState::Polymorphic;
403                self.entries.push(entry);
404            }
405            _ => {
406                // Too many entries - transition to megamorphic
407                self.state = CacheState::Megamorphic;
408                // Evict least used entry
409                if let Some(min_idx) = self
410                    .entries
411                    .iter()
412                    .enumerate()
413                    .min_by_key(|(_, e)| e.hit_count)
414                    .map(|(i, _)| i)
415                {
416                    self.entries[min_idx] = entry;
417                }
418            }
419        }
420    }
421
422    /// Get cache hit rate for profiling
423    pub fn hit_rate(&self) -> f64 {
424        let total = self.total_hits + self.total_misses;
425        if total == 0 {
426            0.0
427        } else {
428            f64::from(self.total_hits) / f64::from(total)
429        }
430    }
431}
432
433impl Default for InlineCache {
434    fn default() -> Self {
435        Self::new()
436    }
437}
438
439/// Type feedback collection for JIT compilation decisions.
440///
441/// Collects runtime type information to guide optimization decisions in
442/// future JIT compilation tiers. This includes:
443///
444/// - Operation site type patterns (for inline caching)
445/// - Variable type stability (for specialization)
446/// - Call site patterns (for method inlining)
447///
448/// # Usage
449///
450/// The interpreter automatically collects type feedback during execution.
451/// When functions become "hot" (frequently executed), this data guides
452/// JIT compilation decisions.
453///
454/// # Statistics
455///
456/// Use `get_stats()` to retrieve feedback statistics for monitoring
457/// and debugging optimization decisions.
458#[derive(Clone, Debug)]
459pub struct TypeFeedback {
460    /// Operation site feedback (indexed by AST node or bytecode offset)
461    operation_sites: HashMap<usize, OperationFeedback>,
462    /// Variable type patterns (variable name -> type feedback)
463    variable_types: HashMap<String, VariableTypeFeedback>,
464    /// Function call sites with argument/return type information
465    call_sites: HashMap<usize, CallSiteFeedback>,
466    /// Total feedback collection count
467    total_samples: u64,
468}
469
470/// Feedback for a specific operation site (binary ops, field access, etc.)
471#[derive(Clone, Debug)]
472pub struct OperationFeedback {
473    /// Types observed for left operand
474    left_types: SmallVec<[std::any::TypeId; 4]>,
475    /// Types observed for right operand (for binary ops)
476    right_types: SmallVec<[std::any::TypeId; 4]>,
477    /// Result types observed
478    result_types: SmallVec<[std::any::TypeId; 4]>,
479    /// Hit counts for each type combination
480    type_counts: HashMap<(std::any::TypeId, std::any::TypeId), u32>,
481    /// Total operation count
482    total_count: u32,
483}
484
485/// Type feedback for variables across their lifetime
486#[derive(Clone, Debug)]
487pub struct VariableTypeFeedback {
488    /// Types assigned to this variable
489    assigned_types: SmallVec<[std::any::TypeId; 4]>,
490    /// Type transitions (`from_type` -> `to_type`)
491    transitions: HashMap<std::any::TypeId, HashMap<std::any::TypeId, u32>>,
492    /// Most common type (for specialization)
493    dominant_type: Option<std::any::TypeId>,
494    /// Type stability score (0.0 = highly polymorphic, 1.0 = monomorphic)
495    stability_score: f64,
496}
497
498/// Feedback for function call sites
499#[derive(Clone, Debug)]
500pub struct CallSiteFeedback {
501    /// Argument type patterns observed
502    arg_type_patterns: SmallVec<[Vec<std::any::TypeId>; 4]>,
503    /// Return types observed
504    return_types: SmallVec<[std::any::TypeId; 4]>,
505    /// Call frequency
506    call_count: u32,
507    /// Functions called at this site (for polymorphic calls)
508    called_functions: HashMap<String, u32>,
509}
510
511impl TypeFeedback {
512    /// Create new type feedback collector
513    pub fn new() -> Self {
514        Self {
515            operation_sites: HashMap::new(),
516            variable_types: HashMap::new(),
517            call_sites: HashMap::new(),
518            total_samples: 0,
519        }
520    }
521
522    /// Record binary operation type feedback
523    pub fn record_binary_op(
524        &mut self,
525        site_id: usize,
526        left: &Value,
527        right: &Value,
528        result: &Value,
529    ) {
530        let left_type = left.type_id();
531        let right_type = right.type_id();
532        let result_type = result.type_id();
533
534        let feedback = self
535            .operation_sites
536            .entry(site_id)
537            .or_insert_with(|| OperationFeedback {
538                left_types: smallvec![],
539                right_types: smallvec![],
540                result_types: smallvec![],
541                type_counts: HashMap::new(),
542                total_count: 0,
543            });
544
545        // Record types if not already seen
546        if !feedback.left_types.contains(&left_type) {
547            feedback.left_types.push(left_type);
548        }
549        if !feedback.right_types.contains(&right_type) {
550            feedback.right_types.push(right_type);
551        }
552        if !feedback.result_types.contains(&result_type) {
553            feedback.result_types.push(result_type);
554        }
555
556        // Update type combination counts
557        let type_pair = (left_type, right_type);
558        *feedback.type_counts.entry(type_pair).or_insert(0) += 1;
559        feedback.total_count += 1;
560        self.total_samples += 1;
561    }
562
563    /// Record variable assignment type feedback
564    pub fn record_variable_assignment(&mut self, var_name: &str, new_type: std::any::TypeId) {
565        let feedback = self
566            .variable_types
567            .entry(var_name.to_string())
568            .or_insert_with(|| VariableTypeFeedback {
569                assigned_types: smallvec![],
570                transitions: HashMap::new(),
571                dominant_type: None,
572                stability_score: 1.0,
573            });
574
575        // Record type transition if there was a previous type
576        if let Some(prev_type) = feedback.dominant_type {
577            if prev_type != new_type {
578                feedback
579                    .transitions
580                    .entry(prev_type)
581                    .or_default()
582                    .entry(new_type)
583                    .and_modify(|count| *count += 1)
584                    .or_insert(1);
585            }
586        }
587
588        // Add new type if not seen before
589        if !feedback.assigned_types.contains(&new_type) {
590            feedback.assigned_types.push(new_type);
591        }
592
593        // Update dominant type (most recently assigned for simplicity)
594        feedback.dominant_type = Some(new_type);
595
596        // Recalculate stability score
597        feedback.stability_score = if feedback.assigned_types.len() == 1 {
598            1.0 // Monomorphic
599        } else {
600            1.0 / f64::from(u32::try_from(feedback.assigned_types.len()).unwrap_or(u32::MAX))
601            // Decreases with more types
602        };
603    }
604
605    /// Record function call type feedback
606    pub fn record_function_call(
607        &mut self,
608        site_id: usize,
609        func_name: &str,
610        args: &[Value],
611        result: &Value,
612    ) {
613        let arg_types: Vec<std::any::TypeId> = args.iter().map(Value::type_id).collect();
614        let return_type = result.type_id();
615
616        let feedback = self
617            .call_sites
618            .entry(site_id)
619            .or_insert_with(|| CallSiteFeedback {
620                arg_type_patterns: smallvec![],
621                return_types: smallvec![],
622                call_count: 0,
623                called_functions: HashMap::new(),
624            });
625
626        // Record argument pattern if not seen before
627        if !feedback
628            .arg_type_patterns
629            .iter()
630            .any(|pattern| pattern == &arg_types)
631        {
632            feedback.arg_type_patterns.push(arg_types);
633        }
634
635        // Record return type if not seen before
636        if !feedback.return_types.contains(&return_type) {
637            feedback.return_types.push(return_type);
638        }
639
640        // Update function call counts
641        *feedback
642            .called_functions
643            .entry(func_name.to_string())
644            .or_insert(0) += 1;
645        feedback.call_count += 1;
646    }
647
648    /// Get type specialization suggestions for optimization
649    /// # Panics
650    /// Panics if a variable's dominant type is None when it should exist
651    pub fn get_specialization_candidates(&self) -> Vec<SpecializationCandidate> {
652        let mut candidates = Vec::new();
653
654        // Find monomorphic operation sites
655        for (&site_id, feedback) in &self.operation_sites {
656            if feedback.left_types.len() == 1
657                && feedback.right_types.len() == 1
658                && feedback.total_count > 10
659            {
660                candidates.push(SpecializationCandidate {
661                    kind: SpecializationKind::BinaryOperation {
662                        site_id,
663                        left_type: feedback.left_types[0],
664                        right_type: feedback.right_types[0],
665                    },
666                    confidence: 1.0,
667                    benefit_score: f64::from(feedback.total_count),
668                });
669            }
670        }
671
672        // Find stable variables
673        for (var_name, feedback) in &self.variable_types {
674            if feedback.stability_score > 0.8 && feedback.dominant_type.is_some() {
675                candidates.push(SpecializationCandidate {
676                    kind: SpecializationKind::Variable {
677                        name: var_name.clone(),
678                        #[allow(clippy::expect_used)] // Safe: we just checked is_some() above
679                        specialized_type: feedback.dominant_type.expect("Dominant type should exist for stable variables"),
680                    },
681                    confidence: feedback.stability_score,
682                    benefit_score: feedback.stability_score * 100.0,
683                });
684            }
685        }
686
687        // Find monomorphic call sites
688        for (&site_id, feedback) in &self.call_sites {
689            if feedback.arg_type_patterns.len() == 1
690                && feedback.return_types.len() == 1
691                && feedback.call_count > 5
692            {
693                candidates.push(SpecializationCandidate {
694                    kind: SpecializationKind::FunctionCall {
695                        site_id,
696                        arg_types: feedback.arg_type_patterns[0].clone(),
697                        return_type: feedback.return_types[0],
698                    },
699                    confidence: 1.0,
700                    benefit_score: f64::from(feedback.call_count * 10),
701                });
702            }
703        }
704
705        // Sort by benefit score (highest first)
706        candidates.sort_by(|a, b| {
707            b.benefit_score
708                .partial_cmp(&a.benefit_score)
709                .unwrap_or(std::cmp::Ordering::Equal)
710        });
711        candidates
712    }
713
714    /// Get overall type feedback statistics
715    pub fn get_statistics(&self) -> TypeFeedbackStats {
716        let monomorphic_sites = self
717            .operation_sites
718            .values()
719            .filter(|f| f.left_types.len() == 1 && f.right_types.len() == 1)
720            .count();
721
722        let stable_variables = self
723            .variable_types
724            .values()
725            .filter(|f| f.stability_score > 0.8)
726            .count();
727
728        let monomorphic_calls = self
729            .call_sites
730            .values()
731            .filter(|f| f.arg_type_patterns.len() == 1)
732            .count();
733
734        TypeFeedbackStats {
735            total_operation_sites: self.operation_sites.len(),
736            monomorphic_operation_sites: monomorphic_sites,
737            total_variables: self.variable_types.len(),
738            stable_variables,
739            total_call_sites: self.call_sites.len(),
740            monomorphic_call_sites: monomorphic_calls,
741            total_samples: self.total_samples,
742        }
743    }
744}
745
746impl Default for TypeFeedback {
747    fn default() -> Self {
748        Self::new()
749    }
750}
751
752/// Specialization candidate for JIT compilation
753#[derive(Clone, Debug)]
754#[allow(dead_code)] // Will be used by future JIT implementation
755pub struct SpecializationCandidate {
756    /// Type of specialization
757    kind: SpecializationKind,
758    /// Confidence level (0.0 - 1.0)
759    confidence: f64,
760    /// Expected benefit score
761    benefit_score: f64,
762}
763
764#[derive(Clone, Debug)]
765pub enum SpecializationKind {
766    BinaryOperation {
767        site_id: usize,
768        left_type: std::any::TypeId,
769        right_type: std::any::TypeId,
770    },
771    Variable {
772        name: String,
773        specialized_type: std::any::TypeId,
774    },
775    FunctionCall {
776        site_id: usize,
777        arg_types: Vec<std::any::TypeId>,
778        return_type: std::any::TypeId,
779    },
780}
781
782/// Type feedback statistics for profiling
783#[derive(Clone, Debug)]
784pub struct TypeFeedbackStats {
785    /// Total operation sites recorded
786    pub total_operation_sites: usize,
787    /// Monomorphic operation sites (candidates for specialization)
788    pub monomorphic_operation_sites: usize,
789    /// Total variables tracked
790    pub total_variables: usize,
791    /// Variables with stable types
792    pub stable_variables: usize,
793    /// Total function call sites
794    pub total_call_sites: usize,
795    /// Monomorphic call sites
796    pub monomorphic_call_sites: usize,
797    /// Total feedback samples collected
798    pub total_samples: u64,
799}
800
801// Re-export GC implementation from gc_impl module
802// EXTREME TDD: Eliminated 318 lines of duplicate GC code (massive entropy reduction)
803pub use super::gc_impl::{ConservativeGC, GCInfo, GCObject, GCStats};
804
805// Re-export compilation implementation from compilation module
806// EXTREME TDD: Eliminated 669 lines of compilation code (massive entropy reduction)
807pub use super::compilation::{
808    DirectThreadedInterpreter, InstructionResult, InterpreterState, ThreadedInstruction,
809};
810
811impl Interpreter {
812    /// Create a new interpreter instance.
813    ///
814    /// Initializes the interpreter with:
815    /// - Pre-allocated stack for performance
816    /// - Global environment with builtin functions (max, min, floor, ceil, etc.)
817    /// - Type feedback collection for future JIT compilation
818    /// - Conservative garbage collector
819    ///
820    /// # Examples
821    ///
822    /// ```
823    /// use ruchy::runtime::interpreter::Interpreter;
824    ///
825    /// let mut interpreter = Interpreter::new();
826    /// // Interpreter is ready to evaluate expressions
827    /// ```
828    pub fn new() -> Self {
829        // EXTREME TDD: Delegate builtin initialization to eliminate 62 lines of entropy
830        let global_env = crate::runtime::builtin_init::init_global_environment();
831
832        Self {
833            stack: Vec::with_capacity(1024), // Pre-allocate stack
834            env_stack: vec![global_env],     // Start with global environment containing builtins
835            frames: Vec::new(),
836            execution_counts: HashMap::new(),
837            field_caches: HashMap::new(),
838            type_feedback: TypeFeedback::new(),
839            gc: ConservativeGC::new(),
840            error_scopes: Vec::new(),
841            stdout_buffer: Vec::new(),       // Initialize empty stdout buffer
842        }
843    }
844
845    /// Evaluate an AST expression directly.
846    ///
847    /// This is the main entry point for interpreting Ruchy expressions. It walks
848    /// the AST recursively, evaluating expressions and returning their values.
849    ///
850    /// # Examples
851    ///
852    /// ```
853    /// use ruchy::runtime::interpreter::Interpreter;
854    /// use ruchy::frontend::parser::Parser;
855    ///
856    /// let mut interpreter = Interpreter::new();
857    /// let mut parser = Parser::new("42");
858    /// let expr = parser.parse().unwrap();
859    /// let result = interpreter.eval_expr(&expr).unwrap();
860    /// assert_eq!(result.to_string(), "42");
861    /// ```
862    ///
863    /// ```
864    /// use ruchy::runtime::interpreter::Interpreter;
865    /// use ruchy::frontend::parser::Parser;
866    ///
867    /// let mut interpreter = Interpreter::new();
868    /// let mut parser = Parser::new("2 + 3");
869    /// let expr = parser.parse().unwrap();
870    /// let result = interpreter.eval_expr(&expr).unwrap();
871    /// assert_eq!(result.to_string(), "5");
872    /// ```
873    ///
874    /// # Errors
875    ///
876    /// Returns an error when:
877    /// - Type error (e.g., adding string to number)
878    /// - Runtime error (e.g., undefined variable)
879    /// - Stack overflow/underflow
880    /// - Division by zero
881    pub fn eval_expr(&mut self, expr: &Expr) -> Result<Value, InterpreterError> {
882        self.eval_expr_kind(&expr.kind)
883    }
884
885    /// Evaluate an expression kind directly.
886    ///
887    /// This is the core dispatch function for the interpreter. It pattern-matches
888    /// on the `ExprKind` and delegates to specialized evaluation functions.
889    ///
890    /// The function is organized into logical groups:
891    /// - Basic expressions (literals, identifiers)
892    /// - Operations (binary, unary, calls)
893    /// - Functions (definitions, lambdas)
894    /// - Control flow (if, for, while, match)
895    /// - Data structures (lists, tuples, arrays)
896    /// - Assignments
897    ///
898    /// # Errors
899    ///
900    /// Returns an error if the expression evaluation fails or if the expression
901    /// type is not yet implemented.
902    fn eval_expr_kind(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
903        match expr_kind {
904            // Simple expressions (complexity: 2)
905            ExprKind::Literal(_) | ExprKind::Identifier(_) => self.eval_simple_expr(expr_kind),
906
907            // Operations (complexity: 2)
908            ExprKind::Binary { .. }
909            | ExprKind::Unary { .. }
910            | ExprKind::Call { .. }
911            | ExprKind::MethodCall { .. }
912            | ExprKind::DataFrameOperation { .. }
913            | ExprKind::IndexAccess { .. }
914            | ExprKind::FieldAccess { .. }
915            | ExprKind::TypeCast { .. } => self.eval_operation_expr(expr_kind),
916
917            // Functions (complexity: 2)
918            ExprKind::Function { .. } | ExprKind::Lambda { .. } => {
919                self.eval_function_expr(expr_kind)
920            }
921
922            // Control flow (complexity: 1)
923            kind if Self::is_control_flow_expr(kind) => self.eval_control_flow_expr(kind),
924
925            // Data structures (complexity: 1)
926            kind if Self::is_data_structure_expr(kind) => self.eval_data_structure_expr(kind),
927
928            // Assignments (complexity: 1)
929            kind if Self::is_assignment_expr(kind) => self.eval_assignment_expr(kind),
930
931            // Other expressions (complexity: 1)
932            _ => self.eval_misc_expr(expr_kind),
933        }
934    }
935
936    // Helper methods for expression type categorization and evaluation (complexity <10 each)
937
938    /// Evaluate simple expressions (literals and identifiers)
939    /// Complexity: 3
940    fn eval_simple_expr(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
941        match expr_kind {
942            ExprKind::Literal(lit) => Ok(eval_literal::eval_literal(lit)),
943            ExprKind::Identifier(name) => self.lookup_variable(name),
944            _ => unreachable!("eval_simple_expr called with non-simple expression"),
945        }
946    }
947
948    /// Evaluate operation expressions (binary, unary, calls, method calls, type casts, etc.)
949    /// Complexity: 9
950    fn eval_operation_expr(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
951        match expr_kind {
952            ExprKind::Binary { left, op, right } => self.eval_binary_expr(left, *op, right),
953            ExprKind::Unary { op, operand } => self.eval_unary_expr(*op, operand),
954            ExprKind::Call { func, args } => self.eval_function_call(func, args),
955            ExprKind::MethodCall {
956                receiver,
957                method,
958                args,
959            } => self.eval_method_call(receiver, method, args),
960            ExprKind::DataFrameOperation { source, operation } => {
961                self.eval_dataframe_operation(source, operation)
962            }
963            ExprKind::IndexAccess { object, index } => self.eval_index_access(object, index),
964            ExprKind::FieldAccess { object, field } => self.eval_field_access(object, field),
965            ExprKind::TypeCast { expr, target_type } => self.eval_type_cast(expr, target_type),
966            _ => unreachable!("eval_operation_expr called with non-operation expression"),
967        }
968    }
969
970    /// Evaluate function expressions (function definitions and lambdas)
971    /// Complexity: 3
972    fn eval_function_expr(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
973        match expr_kind {
974            ExprKind::Function {
975                name, params, body, ..
976            } => self.eval_function(name, params, body),
977            ExprKind::Lambda { params, body } => self.eval_lambda(params, body),
978            _ => unreachable!("eval_function_expr called with non-function expression"),
979        }
980    }
981
982    /// Helper: Check if expression is a type definition
983    /// Complexity: 2
984    fn is_type_definition(expr_kind: &ExprKind) -> bool {
985        matches!(
986            expr_kind,
987            ExprKind::Actor { .. }
988                | ExprKind::Enum { .. }
989                | ExprKind::Struct { .. }
990                | ExprKind::TupleStruct { .. }
991                | ExprKind::Class { .. }
992                | ExprKind::Impl { .. }
993        )
994    }
995
996    /// Helper: Check if expression is an actor operation
997    /// Complexity: 2
998    fn is_actor_operation(expr_kind: &ExprKind) -> bool {
999        matches!(
1000            expr_kind,
1001            ExprKind::Spawn { .. } | ExprKind::ActorSend { .. } | ExprKind::ActorQuery { .. }
1002        )
1003    }
1004
1005    /// Helper: Check if expression is a special form
1006    /// Complexity: 2
1007    fn is_special_form(expr_kind: &ExprKind) -> bool {
1008        matches!(
1009            expr_kind,
1010            ExprKind::None
1011                | ExprKind::Some { .. }
1012                | ExprKind::Set(_)
1013                | ExprKind::LetPattern { .. }
1014                | ExprKind::StringInterpolation { .. }
1015                | ExprKind::QualifiedName { .. }
1016                | ExprKind::ObjectLiteral { .. }
1017                | ExprKind::StructLiteral { .. }
1018        )
1019    }
1020
1021    /// Evaluate type definition expressions (Actor, Struct, Class, Impl)
1022    /// Complexity: 6
1023    fn eval_type_definition(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
1024        match expr_kind {
1025            ExprKind::Actor {
1026                name,
1027                state,
1028                handlers,
1029            } => self.eval_actor_definition(name, state, handlers),
1030            ExprKind::Enum {
1031                name,
1032                type_params,
1033                variants,
1034                is_pub,
1035            } => self.eval_enum_definition(name, type_params, variants, *is_pub),
1036            ExprKind::Struct {
1037                name,
1038                type_params,
1039                fields,
1040                derives: _,
1041                is_pub,
1042            } => self.eval_struct_definition(name, type_params, fields, *is_pub),
1043            ExprKind::TupleStruct { .. } => {
1044                // Tuple structs are transpilation feature, return Nil at runtime
1045                Ok(Value::Nil)
1046            }
1047            ExprKind::Class {
1048                name,
1049                type_params,
1050                superclass,
1051                traits,
1052                fields,
1053                constructors,
1054                methods,
1055                constants,
1056                properties: _,
1057                derives,
1058                is_pub,
1059                is_sealed: _,
1060                is_abstract: _,
1061                decorators: _,
1062            } => self.eval_class_definition(
1063                name,
1064                type_params,
1065                superclass.as_ref(),
1066                traits,
1067                fields,
1068                constructors,
1069                methods,
1070                constants,
1071                derives,
1072                *is_pub,
1073            ),
1074            ExprKind::Impl {
1075                trait_name: _,
1076                for_type,
1077                methods,
1078                ..
1079            } => self.eval_impl_block(for_type, methods),
1080            _ => unreachable!("eval_type_definition called with non-type-definition"),
1081        }
1082    }
1083
1084    /// Evaluate actor operation expressions (Spawn, `ActorSend`, `ActorQuery`)
1085    /// Complexity: 4
1086    fn eval_actor_operation(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
1087        match expr_kind {
1088            ExprKind::Spawn { actor } => self.eval_spawn_actor(actor),
1089            ExprKind::ActorSend { actor, message } => self.eval_actor_send(actor, message),
1090            ExprKind::ActorQuery { actor, message } => self.eval_actor_query(actor, message),
1091            _ => unreachable!("eval_actor_operation called with non-actor-operation"),
1092        }
1093    }
1094
1095    /// Evaluate special form expressions (None, Some, Set, patterns, literals)
1096    /// Complexity: 9
1097    fn eval_special_form(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
1098        match expr_kind {
1099            ExprKind::None => Ok(Value::EnumVariant {
1100                enum_name: "Option".to_string(),
1101                variant_name: "None".to_string(),
1102                data: None,
1103            }),
1104            ExprKind::Some { value } => Ok(Value::EnumVariant {
1105                enum_name: "Option".to_string(),
1106                variant_name: "Some".to_string(),
1107                data: Some(vec![self.eval_expr(value)?]),
1108            }),
1109            ExprKind::Set(statements) => {
1110                let mut result = Value::Nil;
1111                for stmt in statements {
1112                    result = self.eval_expr(stmt)?;
1113                }
1114                Ok(result)
1115            }
1116            ExprKind::LetPattern {
1117                pattern,
1118                value,
1119                body,
1120                ..
1121            } => self.eval_let_pattern(pattern, value, body),
1122            ExprKind::StringInterpolation { parts } => self.eval_string_interpolation(parts),
1123            ExprKind::QualifiedName { module, name } => self.eval_qualified_name(module, name),
1124            ExprKind::ObjectLiteral { fields } => self.eval_object_literal(fields),
1125            ExprKind::StructLiteral {
1126                name,
1127                fields,
1128                base: _,
1129            } => self.eval_struct_literal(name, fields),
1130            _ => unreachable!("eval_special_form called with non-special-form"),
1131        }
1132    }
1133
1134    /// Evaluate miscellaneous expressions
1135    /// Complexity: 7 (was 5, added import handling)
1136    fn eval_misc_expr(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
1137        if Self::is_type_definition(expr_kind) {
1138            return self.eval_type_definition(expr_kind);
1139        }
1140        if Self::is_actor_operation(expr_kind) {
1141            return self.eval_actor_operation(expr_kind);
1142        }
1143        if Self::is_special_form(expr_kind) {
1144            return self.eval_special_form(expr_kind);
1145        }
1146
1147        // Handle import statements (GitHub Issue #59)
1148        // Issue #82: Implement basic module resolution for use statements
1149        match expr_kind {
1150            ExprKind::ImportAll { module, alias } => {
1151                // Extract symbol from global environment using module path
1152                // Example: "chrono::Utc" → ["chrono", "Utc"]
1153                let parts: Vec<&str> = module.split("::").collect();
1154
1155                // Navigate through nested objects to find the symbol
1156                let mut current_value: Option<Value> = None;
1157                if let Some(first_part) = parts.first() {
1158                    // Access global environment (first element of env_stack)
1159                    if let Some(global_env) = self.env_stack.first() {
1160                        if let Some(root) = global_env.get(*first_part) {
1161                            current_value = Some(root.clone());
1162
1163                            // Navigate through remaining parts
1164                            for &part in parts.iter().skip(1) {
1165                                if let Some(Value::Object(obj)) = current_value {
1166                                    if let Some(next_val) = obj.get(part) {
1167                                        current_value = Some(next_val.clone());
1168                                    } else {
1169                                        current_value = None;
1170                                        break;
1171                                    }
1172                                } else {
1173                                    current_value = None;
1174                                    break;
1175                                }
1176                            }
1177                        }
1178                    }
1179                }
1180
1181                // Import the symbol into current environment with the appropriate name
1182                if let Some(value) = current_value {
1183                    // Determine the name to use: alias if provided, otherwise last part of path
1184                    let import_name = if alias == "*" {
1185                        // Wildcard import - not yet implemented
1186                        return Ok(Value::Nil);
1187                    } else if !alias.is_empty() && alias != "*" {
1188                        alias.clone()
1189                    } else {
1190                        parts.last().unwrap_or(&"").to_string()
1191                    };
1192
1193                    // Add to global environment (first element of env_stack)
1194                    // This makes imports available across all scopes
1195                    if let Some(global_env) = self.env_stack.first_mut() {
1196                        global_env.insert(import_name, value);
1197                    }
1198                }
1199
1200                Ok(Value::Nil)
1201            }
1202            ExprKind::Import { .. } | ExprKind::ImportDefault { .. } => {
1203                // TODO: Implement other import variants
1204                Ok(Value::Nil)
1205            }
1206            // Handle vec! macro (GitHub Issue #62)
1207            ExprKind::Macro { name, args } => {
1208                if name == "vec" {
1209                    // vec![...] expands to an array with evaluated arguments
1210                    let mut elements = Vec::new();
1211                    for arg in args {
1212                        let value = self.eval_expr(arg)?;
1213                        elements.push(value);
1214                    }
1215                    Ok(Value::Array(elements.into()))
1216                } else if name == "println" {
1217                    // println!() macro: Evaluate arguments, print with newline
1218                    // PARSER-085: Supports format strings like println!("x: {}", value)
1219                    if args.is_empty() {
1220                        println!();
1221                    } else if args.len() == 1 {
1222                        // Single argument: print directly
1223                        let value = self.eval_expr(&args[0])?;
1224                        println!("{}", value);
1225                    } else {
1226                        // Multiple arguments: use format! logic (Issue #82, #83)
1227                        let format_val = self.eval_expr(&args[0])?;
1228                        let format_str = format_val.to_string();
1229
1230                        let mut values = Vec::new();
1231                        for arg in &args[1..] {
1232                            values.push(self.eval_expr(arg)?);
1233                        }
1234
1235                        // Apply same format logic as format! macro
1236                        let mut result = String::new();
1237                        let mut chars = format_str.chars().peekable();
1238                        let mut value_index = 0;
1239
1240                        while let Some(ch) = chars.next() {
1241                            if ch == '{' {
1242                                if chars.peek() == Some(&':') {
1243                                    chars.next();
1244                                    if chars.peek() == Some(&'?') {
1245                                        chars.next();
1246                                        if chars.peek() == Some(&'}') {
1247                                            chars.next();
1248                                            if value_index < values.len() {
1249                                                result.push_str(&format!("{:?}", values[value_index]));
1250                                                value_index += 1;
1251                                            } else {
1252                                                result.push_str("{:?}");
1253                                            }
1254                                        } else {
1255                                            result.push_str("{:?");
1256                                        }
1257                                    } else {
1258                                        result.push_str("{:");
1259                                    }
1260                                } else if chars.peek() == Some(&'}') {
1261                                    chars.next();
1262                                    if value_index < values.len() {
1263                                        result.push_str(&values[value_index].to_string());
1264                                        value_index += 1;
1265                                    } else {
1266                                        result.push_str("{}");
1267                                    }
1268                                } else {
1269                                    result.push(ch);
1270                                }
1271                            } else {
1272                                result.push(ch);
1273                            }
1274                        }
1275
1276                        println!("{}", result);
1277                    }
1278                    Ok(Value::Nil)
1279                } else if name == "format" {
1280                    // format!() macro: Format string with placeholders (Issue #83)
1281                    if args.is_empty() {
1282                        return Err(InterpreterError::RuntimeError(
1283                            "format!() requires at least one argument".to_string()
1284                        ));
1285                    }
1286
1287                    // Evaluate format string
1288                    let format_val = self.eval_expr(&args[0])?;
1289                    let format_str = format_val.to_string();
1290
1291                    // Evaluate remaining arguments
1292                    let mut values = Vec::new();
1293                    for arg in &args[1..] {
1294                        values.push(self.eval_expr(arg)?);
1295                    }
1296
1297                    // Replace {} and {:?} placeholders with values
1298                    let mut result = String::new();
1299                    let mut chars = format_str.chars().peekable();
1300                    let mut value_index = 0;
1301
1302                    while let Some(ch) = chars.next() {
1303                        if ch == '{' {
1304                            // Check for {:?} debug format
1305                            if chars.peek() == Some(&':') {
1306                                chars.next(); // consume ':'
1307                                if chars.peek() == Some(&'?') {
1308                                    chars.next(); // consume '?'
1309                                    if chars.peek() == Some(&'}') {
1310                                        chars.next(); // consume '}'
1311                                        if value_index < values.len() {
1312                                            result.push_str(&format!("{:?}", values[value_index]));
1313                                            value_index += 1;
1314                                        } else {
1315                                            result.push_str("{:?}"); // preserve placeholder
1316                                        }
1317                                    } else {
1318                                        result.push_str("{:?"); // not a complete placeholder
1319                                    }
1320                                } else {
1321                                    result.push_str("{:"); // not {:?}
1322                                }
1323                            } else if chars.peek() == Some(&'}') {
1324                                chars.next(); // consume '}'
1325                                if value_index < values.len() {
1326                                    result.push_str(&values[value_index].to_string());
1327                                    value_index += 1;
1328                                } else {
1329                                    result.push_str("{}"); // preserve placeholder if no value
1330                                }
1331                            } else {
1332                                result.push(ch);
1333                            }
1334                        } else {
1335                            result.push(ch);
1336                        }
1337                    }
1338
1339                    Ok(Value::from_string(result))
1340                } else {
1341                    // Other macros not yet implemented
1342                    Err(InterpreterError::RuntimeError(format!(
1343                        "Macro '{}!' not yet implemented", name
1344                    )))
1345                }
1346            }
1347            // RUNTIME-001: Handle MacroInvocation (FORMATTER-088 changed parser output)
1348            // MacroInvocation is the correct AST variant for macro CALLS (not definitions)
1349            // Delegate to same logic as Macro for backward compatibility (GitHub Issue #74)
1350            ExprKind::MacroInvocation { name, args } => {
1351                if name == "vec" {
1352                    let mut elements = Vec::new();
1353                    for arg in args {
1354                        let value = self.eval_expr(arg)?;
1355                        elements.push(value);
1356                    }
1357                    Ok(Value::Array(elements.into()))
1358                } else if name == "println" {
1359                    // println!() macro: Evaluate arguments, print with newline
1360                    // PARSER-085: Supports format strings like println!("x: {}", value)
1361                    if args.is_empty() {
1362                        println!();
1363                    } else if args.len() == 1 {
1364                        // Single argument: print directly
1365                        let value = self.eval_expr(&args[0])?;
1366                        println!("{}", value);
1367                    } else {
1368                        // Multiple arguments: use format! logic (Issue #82, #83)
1369                        let format_val = self.eval_expr(&args[0])?;
1370                        let format_str = format_val.to_string();
1371
1372                        let mut values = Vec::new();
1373                        for arg in &args[1..] {
1374                            values.push(self.eval_expr(arg)?);
1375                        }
1376
1377                        // Apply same format logic as format! macro
1378                        let mut result = String::new();
1379                        let mut chars = format_str.chars().peekable();
1380                        let mut value_index = 0;
1381
1382                        while let Some(ch) = chars.next() {
1383                            if ch == '{' {
1384                                if chars.peek() == Some(&':') {
1385                                    chars.next();
1386                                    if chars.peek() == Some(&'?') {
1387                                        chars.next();
1388                                        if chars.peek() == Some(&'}') {
1389                                            chars.next();
1390                                            if value_index < values.len() {
1391                                                result.push_str(&format!("{:?}", values[value_index]));
1392                                                value_index += 1;
1393                                            } else {
1394                                                result.push_str("{:?}");
1395                                            }
1396                                        } else {
1397                                            result.push_str("{:?");
1398                                        }
1399                                    } else {
1400                                        result.push_str("{:");
1401                                    }
1402                                } else if chars.peek() == Some(&'}') {
1403                                    chars.next();
1404                                    if value_index < values.len() {
1405                                        result.push_str(&values[value_index].to_string());
1406                                        value_index += 1;
1407                                    } else {
1408                                        result.push_str("{}");
1409                                    }
1410                                } else {
1411                                    result.push(ch);
1412                                }
1413                            } else {
1414                                result.push(ch);
1415                            }
1416                        }
1417
1418                        println!("{}", result);
1419                    }
1420                    Ok(Value::Nil)
1421                } else if name == "format" {
1422                    // format!() macro: Format string with placeholders (Issue #83)
1423                    if args.is_empty() {
1424                        return Err(InterpreterError::RuntimeError(
1425                            "format!() requires at least one argument".to_string()
1426                        ));
1427                    }
1428
1429                    // Evaluate format string
1430                    let format_val = self.eval_expr(&args[0])?;
1431                    let format_str = format_val.to_string();
1432
1433                    // Evaluate remaining arguments
1434                    let mut values = Vec::new();
1435                    for arg in &args[1..] {
1436                        values.push(self.eval_expr(arg)?);
1437                    }
1438
1439                    // Replace {} and {:?} placeholders with values
1440                    let mut result = String::new();
1441                    let mut chars = format_str.chars().peekable();
1442                    let mut value_index = 0;
1443
1444                    while let Some(ch) = chars.next() {
1445                        if ch == '{' {
1446                            // Check for {:?} debug format
1447                            if chars.peek() == Some(&':') {
1448                                chars.next(); // consume ':'
1449                                if chars.peek() == Some(&'?') {
1450                                    chars.next(); // consume '?'
1451                                    if chars.peek() == Some(&'}') {
1452                                        chars.next(); // consume '}'
1453                                        if value_index < values.len() {
1454                                            result.push_str(&format!("{:?}", values[value_index]));
1455                                            value_index += 1;
1456                                        } else {
1457                                            result.push_str("{:?}"); // preserve placeholder
1458                                        }
1459                                    } else {
1460                                        result.push_str("{:?"); // not a complete placeholder
1461                                    }
1462                                } else {
1463                                    result.push_str("{:"); // not {:?}
1464                                }
1465                            } else if chars.peek() == Some(&'}') {
1466                                chars.next(); // consume '}'
1467                                if value_index < values.len() {
1468                                    result.push_str(&values[value_index].to_string());
1469                                    value_index += 1;
1470                                } else {
1471                                    result.push_str("{}"); // preserve placeholder if no value
1472                                }
1473                            } else {
1474                                result.push(ch);
1475                            }
1476                        } else {
1477                            result.push(ch);
1478                        }
1479                    }
1480
1481                    Ok(Value::from_string(result))
1482                } else {
1483                    Err(InterpreterError::RuntimeError(format!(
1484                        "Macro '{}!' not yet implemented", name
1485                    )))
1486                }
1487            }
1488            _ => {
1489                // Fallback for unimplemented expressions
1490                Err(InterpreterError::RuntimeError(format!(
1491                    "Expression type not yet implemented: {expr_kind:?}"
1492                )))
1493            }
1494        }
1495    }
1496
1497    /// Helper: Evaluate spawn actor expression with proper nesting handling
1498    /// Complexity: 10 (extracted from inline code)
1499    fn eval_spawn_actor(&mut self, actor: &Expr) -> Result<Value, InterpreterError> {
1500        // Handle: spawn ActorName (no args)
1501        if let ExprKind::Identifier(name) = &actor.kind {
1502            if let Ok(def_value) = self.lookup_variable(name) {
1503                if let Value::Object(ref obj) = def_value {
1504                    if let Some(Value::String(type_str)) = obj.get("__type") {
1505                        if type_str.as_ref() == "Actor" {
1506                            let constructor_marker =
1507                                Value::from_string(format!("__actor_constructor__:{}", name));
1508                            return self.call_function(constructor_marker, &[]);
1509                        }
1510                    }
1511                }
1512            }
1513        }
1514
1515        // Handle: spawn ActorName(args...)
1516        if let ExprKind::Call { func, args } = &actor.kind {
1517            if let ExprKind::Identifier(name) = &func.kind {
1518                if let Ok(def_value) = self.lookup_variable(name) {
1519                    if let Value::Object(ref obj) = def_value {
1520                        if let Some(Value::String(type_str)) = obj.get("__type") {
1521                            if type_str.as_ref() == "Actor" {
1522                                let constructor_marker =
1523                                    Value::from_string(format!("__actor_constructor__:{}", name));
1524                                let arg_vals: Result<Vec<Value>, _> =
1525                                    args.iter().map(|arg| self.eval_expr(arg)).collect();
1526                                let arg_vals = arg_vals?;
1527                                return self.call_function(constructor_marker, &arg_vals);
1528                            }
1529                        }
1530                    }
1531                }
1532            }
1533        }
1534
1535        // Default: evaluate the actor expression normally
1536        let actor_value = self.eval_expr(actor)?;
1537        Ok(actor_value)
1538    }
1539
1540    /// Helper: Evaluate actor send expression (fire-and-forget)
1541    /// Complexity: 4
1542    fn eval_actor_send(&mut self, actor: &Expr, message: &Expr) -> Result<Value, InterpreterError> {
1543        let actor_value = self.eval_expr(actor)?;
1544        let message_value = self.eval_message_expr(message)?;
1545
1546        if let Value::ObjectMut(cell_rc) = actor_value {
1547            self.process_actor_message_sync_mut(&cell_rc, &message_value)?;
1548            Ok(Value::Nil)
1549        } else {
1550            Err(InterpreterError::RuntimeError(format!(
1551                "ActorSend requires an actor instance, got {}",
1552                actor_value.type_name()
1553            )))
1554        }
1555    }
1556
1557    /// Helper: Evaluate actor query expression (ask pattern)
1558    /// Complexity: 4
1559    fn eval_actor_query(
1560        &mut self,
1561        actor: &Expr,
1562        message: &Expr,
1563    ) -> Result<Value, InterpreterError> {
1564        let actor_value = self.eval_expr(actor)?;
1565        let message_value = self.eval_message_expr(message)?;
1566
1567        if let Value::ObjectMut(cell_rc) = actor_value {
1568            self.process_actor_message_sync_mut(&cell_rc, &message_value)
1569        } else {
1570            Err(InterpreterError::RuntimeError(format!(
1571                "ActorQuery requires an actor instance, got {}",
1572                actor_value.type_name()
1573            )))
1574        }
1575    }
1576
1577    fn is_control_flow_expr(expr_kind: &ExprKind) -> bool {
1578        eval_expr::is_control_flow_expr(expr_kind)
1579    }
1580
1581    fn is_data_structure_expr(expr_kind: &ExprKind) -> bool {
1582        eval_expr::is_data_structure_expr(expr_kind)
1583    }
1584
1585    fn is_assignment_expr(expr_kind: &ExprKind) -> bool {
1586        eval_expr::is_assignment_expr(expr_kind)
1587    }
1588
1589    fn eval_control_flow_expr(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
1590        match expr_kind {
1591            ExprKind::If {
1592                condition,
1593                then_branch,
1594                else_branch,
1595            } => self.eval_if_expr(condition, then_branch, else_branch.as_deref()),
1596            ExprKind::Ternary {
1597                condition,
1598                true_expr,
1599                false_expr,
1600            } => {
1601                // Evaluate condition
1602                let cond_value = self.eval_expr(condition)?;
1603                // Check if condition is truthy
1604                if cond_value.is_truthy() {
1605                    self.eval_expr(true_expr)
1606                } else {
1607                    self.eval_expr(false_expr)
1608                }
1609            }
1610            ExprKind::Let {
1611                name, value, body, ..
1612            } => self.eval_let_expr(name, value, body),
1613            ExprKind::For {
1614                label,
1615                var,
1616                pattern,
1617                iter,
1618                body,
1619            } => self.eval_for_loop(label.as_ref(), var, pattern.as_ref(), iter, body),
1620            ExprKind::While {
1621                label,
1622                condition,
1623                body,
1624            } => self.eval_while_loop(label.as_ref(), condition, body),
1625            ExprKind::Loop { label, body } => self.eval_loop(label.as_ref(), body),
1626            ExprKind::Match { expr, arms } => self.eval_match(expr, arms),
1627            ExprKind::Break { label, value } => {
1628                // Evaluate the break value (default to Nil if not provided)
1629                let break_val = if let Some(expr) = value {
1630                    self.eval_expr(expr)?
1631                } else {
1632                    Value::Nil
1633                };
1634                Err(InterpreterError::Break(label.clone(), break_val))
1635            }
1636            ExprKind::Continue { label } => Err(InterpreterError::Continue(label.clone())),
1637            ExprKind::Return { value } => self.eval_return_expr(value.as_deref()),
1638            ExprKind::TryCatch {
1639                try_block,
1640                catch_clauses,
1641                finally_block,
1642            } => crate::runtime::eval_try_catch::eval_try_catch(
1643                self,
1644                try_block,
1645                catch_clauses,
1646                finally_block.as_deref(),
1647            ),
1648            ExprKind::Throw { expr } => crate::runtime::eval_try_catch::eval_throw(self, expr),
1649            _ => unreachable!("Non-control-flow expression passed to eval_control_flow_expr"),
1650        }
1651    }
1652
1653    fn eval_data_structure_expr(
1654        &mut self,
1655        expr_kind: &ExprKind,
1656    ) -> Result<Value, InterpreterError> {
1657        match expr_kind {
1658            ExprKind::List(elements) => self.eval_list_expr(elements),
1659            ExprKind::Block(statements) => self.eval_block_expr(statements),
1660            ExprKind::Tuple(elements) => self.eval_tuple_expr(elements),
1661            ExprKind::Range {
1662                start,
1663                end,
1664                inclusive,
1665            } => self.eval_range_expr(start, end, *inclusive),
1666            ExprKind::ArrayInit { value, size } => self.eval_array_init_expr(value, size),
1667            ExprKind::DataFrame { columns } => self.eval_dataframe_literal(columns),
1668            _ => unreachable!("Non-data-structure expression passed to eval_data_structure_expr"),
1669        }
1670    }
1671
1672    fn eval_assignment_expr(&mut self, expr_kind: &ExprKind) -> Result<Value, InterpreterError> {
1673        match expr_kind {
1674            ExprKind::Assign { target, value } => self.eval_assign(target, value),
1675            ExprKind::CompoundAssign { target, op, value } => {
1676                self.eval_compound_assign(target, *op, value)
1677            }
1678            _ => unreachable!("Non-assignment expression passed to eval_assignment_expr"),
1679        }
1680    }
1681
1682    fn eval_index_access(
1683        &mut self,
1684        object: &Expr,
1685        index: &Expr,
1686    ) -> Result<Value, InterpreterError> {
1687        let object_value = self.eval_expr(object)?;
1688        let index_value = self.eval_expr(index)?;
1689
1690        match (&object_value, &index_value) {
1691            (Value::Array(ref array), Value::Integer(idx)) => Self::index_array(array, *idx),
1692            (Value::String(ref s), Value::Integer(idx)) => Self::index_string(s, *idx),
1693            (Value::Tuple(ref tuple), Value::Integer(idx)) => Self::index_tuple(tuple, *idx),
1694            (Value::Object(ref fields), Value::String(ref key)) => Self::index_object(fields, key),
1695            (Value::ObjectMut(ref cell), Value::String(ref key)) => {
1696                Self::index_object_mut(cell, key)
1697            }
1698            (Value::DataFrame { columns }, Value::Integer(idx)) => {
1699                Self::index_dataframe_row(columns, *idx)
1700            }
1701            (Value::DataFrame { columns }, Value::String(ref col_name)) => {
1702                Self::index_dataframe_column(columns, col_name)
1703            }
1704            _ => Err(InterpreterError::RuntimeError(format!(
1705                "Cannot index {} with {}",
1706                object_value.type_name(),
1707                index_value.type_name()
1708            ))),
1709        }
1710    }
1711
1712    /// Index into an array (complexity: 5 - added negative indexing support)
1713    /// FEATURE-042 (GitHub Issue #46): Support Python/Ruby-style negative indexing
1714    fn index_array(array: &[Value], idx: i64) -> Result<Value, InterpreterError> {
1715        let len = array.len() as i64;
1716        let actual_index = if idx < 0 {
1717            // Negative index: count from the end
1718            // -1 => len-1 (last), -2 => len-2 (second-to-last), etc.
1719            len + idx
1720        } else {
1721            idx
1722        };
1723
1724        // Check bounds (actual_index must be in range [0, len))
1725        if actual_index < 0 || actual_index >= len {
1726            return Err(InterpreterError::RuntimeError(format!(
1727                "Index {idx} out of bounds for array of length {len}"
1728            )));
1729        }
1730
1731        #[allow(clippy::cast_sign_loss)] // Safe: we've verified actual_index >= 0
1732        Ok(array[actual_index as usize].clone())
1733    }
1734
1735    /// Index into a string (complexity: 5 - added negative indexing support)
1736    /// FEATURE-042 (GitHub Issue #46): Support Python/Ruby-style negative indexing
1737    fn index_string(s: &str, idx: i64) -> Result<Value, InterpreterError> {
1738        let chars: Vec<char> = s.chars().collect();
1739        let len = chars.len() as i64;
1740        let actual_index = if idx < 0 {
1741            // Negative index: count from the end
1742            len + idx
1743        } else {
1744            idx
1745        };
1746
1747        // Check bounds
1748        if actual_index < 0 || actual_index >= len {
1749            return Err(InterpreterError::RuntimeError(format!(
1750                "Index {idx} out of bounds for string of length {len}"
1751            )));
1752        }
1753
1754        #[allow(clippy::cast_sign_loss)] // Safe: we've verified actual_index >= 0
1755        Ok(Value::from_string(chars[actual_index as usize].to_string()))
1756    }
1757
1758    /// Index into a tuple (complexity: 5 - added negative indexing support)
1759    /// FEATURE-042 (GitHub Issue #46): Support Python/Ruby-style negative indexing
1760    fn index_tuple(tuple: &[Value], idx: i64) -> Result<Value, InterpreterError> {
1761        let len = tuple.len() as i64;
1762        let actual_index = if idx < 0 {
1763            // Negative index: count from the end
1764            len + idx
1765        } else {
1766            idx
1767        };
1768
1769        // Check bounds
1770        if actual_index < 0 || actual_index >= len {
1771            return Err(InterpreterError::RuntimeError(format!(
1772                "Index {idx} out of bounds for tuple of length {len}"
1773            )));
1774        }
1775
1776        #[allow(clippy::cast_sign_loss)] // Safe: we've verified actual_index >= 0
1777        Ok(tuple[actual_index as usize].clone())
1778    }
1779
1780    /// Index into an object with string key (complexity: 1)
1781    fn index_object(fields: &HashMap<String, Value>, key: &str) -> Result<Value, InterpreterError> {
1782        fields.get(key).cloned().ok_or_else(|| {
1783            InterpreterError::RuntimeError(format!("Key '{key}' not found in object"))
1784        })
1785    }
1786
1787    /// Index into a mutable object with string key (complexity: 1)
1788    fn index_object_mut(
1789        cell: &Arc<std::sync::Mutex<HashMap<String, Value>>>,
1790        key: &str,
1791    ) -> Result<Value, InterpreterError> {
1792        cell.lock().unwrap().get(key).cloned().ok_or_else(|| {
1793            InterpreterError::RuntimeError(format!("Key '{key}' not found in object"))
1794        })
1795    }
1796
1797    /// Index into a `DataFrame` by row index (complexity: 5)
1798    /// Returns a row as an Object with column names as keys
1799    fn index_dataframe_row(
1800        columns: &[DataFrameColumn],
1801        row_idx: i64,
1802    ) -> Result<Value, InterpreterError> {
1803        if columns.is_empty() {
1804            return Err(InterpreterError::RuntimeError(
1805                "Cannot index empty DataFrame".to_string(),
1806            ));
1807        }
1808
1809        let index = row_idx as usize;
1810        let num_rows = columns[0].values.len();
1811
1812        if index >= num_rows {
1813            return Err(InterpreterError::RuntimeError(format!(
1814                "Row index {index} out of bounds for DataFrame with {num_rows} rows"
1815            )));
1816        }
1817
1818        // Build row as Object with column names as keys
1819        let mut row = HashMap::new();
1820        for col in columns {
1821            row.insert(col.name.clone(), col.values[index].clone());
1822        }
1823
1824        Ok(Value::Object(Arc::new(row)))
1825    }
1826
1827    /// Index into a `DataFrame` by column name (complexity: 3)
1828    /// Returns a column as an Array
1829    fn index_dataframe_column(
1830        columns: &[DataFrameColumn],
1831        col_name: &str,
1832    ) -> Result<Value, InterpreterError> {
1833        columns
1834            .iter()
1835            .find(|col| col.name == col_name)
1836            .map(|col| Value::Array(Arc::from(col.values.clone())))
1837            .ok_or_else(|| {
1838                InterpreterError::RuntimeError(format!("Column '{col_name}' not found in DataFrame"))
1839            })
1840    }
1841
1842    /// Check if a field is accessible based on visibility rules
1843    /// Complexity: 5
1844    fn check_field_visibility(
1845        &self,
1846        struct_name: &str,
1847        field: &str,
1848    ) -> Result<(), InterpreterError> {
1849        // Look up struct type definition
1850        let struct_type = self.lookup_variable(struct_name).ok();
1851        if let Some(Value::Object(struct_obj)) = struct_type {
1852            if let Some(Value::Object(fields)) = struct_obj.get("__fields") {
1853                if let Some(Value::Object(field_info)) = fields.get(field) {
1854                    if let Some(Value::String(visibility)) = field_info.get("visibility") {
1855                        if visibility.as_ref() == "private" {
1856                            return Err(InterpreterError::RuntimeError(format!(
1857                                "Field '{}' is private and cannot be accessed outside the struct",
1858                                field
1859                            )));
1860                        }
1861                    }
1862                }
1863            }
1864        }
1865        Ok(())
1866    }
1867
1868    fn eval_field_access(&mut self, object: &Expr, field: &str) -> Result<Value, InterpreterError> {
1869        let object_value = self.eval_expr(object)?;
1870
1871        match object_value {
1872            Value::Object(ref object_map) => {
1873                // Check if this is an enum type trying to construct a variant
1874                if let Some(Value::String(type_str)) = object_map.get("__type") {
1875                    if type_str.as_ref() == "Enum" {
1876                        // Extract enum name from the AST expression
1877                        let enum_name = if let ExprKind::Identifier(name) = &object.kind {
1878                            name.clone()
1879                        } else {
1880                            "UnknownEnum".to_string()
1881                        };
1882                        // This is enum variant construction: EnumName::VariantName
1883                        return Ok(Value::EnumVariant {
1884                            enum_name,
1885                            variant_name: field.to_string(),
1886                            data: None, // Unit variant (no data)
1887                        });
1888                    }
1889                }
1890                self.access_object_field(object_map, field)
1891            }
1892            Value::ObjectMut(ref cell) => self.access_object_mut_field(cell, field),
1893            Value::Struct { ref name, ref fields } => {
1894                // Struct field access
1895                fields.get(field).cloned().ok_or_else(|| {
1896                    InterpreterError::RuntimeError(format!(
1897                        "Field '{field}' not found in struct {name}"
1898                    ))
1899                })
1900            }
1901            Value::Class {
1902                ref class_name,
1903                ref fields,
1904                ..
1905            } => {
1906                // Class field access
1907                let fields_read = fields.read().unwrap();
1908                fields_read.get(field).cloned().ok_or_else(|| {
1909                    InterpreterError::RuntimeError(format!(
1910                        "Field '{field}' not found in class {class_name}"
1911                    ))
1912                })
1913            }
1914            Value::Tuple(ref elements) => {
1915                // Tuple field access (e.g., tuple.0, tuple.1)
1916                crate::runtime::eval_data_structures::eval_tuple_field_access(elements, field)
1917            }
1918            Value::DataFrame { ref columns } => {
1919                // DataFrame field access (df.column_name returns column as array)
1920                Self::index_dataframe_column(columns, field)
1921            }
1922            _ => Err(InterpreterError::RuntimeError(format!(
1923                "Cannot access field '{}' on type {}",
1924                field,
1925                object_value.type_name()
1926            ))),
1927        }
1928    }
1929
1930    /// Access field on immutable object (complexity: 5)
1931    fn access_object_field(
1932        &self,
1933        object_map: &HashMap<String, Value>,
1934        field: &str,
1935    ) -> Result<Value, InterpreterError> {
1936        // Check for constructor access (.new)
1937        if let Some(constructor) = Self::check_constructor_access(object_map, field) {
1938            return Ok(constructor);
1939        }
1940
1941        // Check for actor field access
1942        if let Some(actor_field) = Self::check_actor_field_access(object_map, field)? {
1943            return Ok(actor_field);
1944        }
1945
1946        // Check struct visibility
1947        self.check_struct_visibility(object_map, field)?;
1948
1949        // Regular field access
1950        Self::get_object_field(object_map, field)
1951    }
1952
1953    /// Access field on mutable object (complexity: 4)
1954    fn access_object_mut_field(
1955        &self,
1956        cell: &Arc<std::sync::Mutex<HashMap<String, Value>>>,
1957        field: &str,
1958    ) -> Result<Value, InterpreterError> {
1959        let object_map = cell.lock().unwrap();
1960
1961        // Check for actor field access
1962        if let Some(actor_field) = Self::check_actor_field_access(&object_map, field)? {
1963            return Ok(actor_field);
1964        }
1965
1966        // Check struct visibility
1967        self.check_struct_visibility(&object_map, field)?;
1968
1969        // Regular field access
1970        Self::get_object_field(&object_map, field)
1971    }
1972
1973    /// Check for constructor access (.new on type definitions) (complexity: 4)
1974    fn check_constructor_access(object_map: &HashMap<String, Value>, field: &str) -> Option<Value> {
1975        if field != "new" {
1976            return None;
1977        }
1978
1979        if let Some(Value::String(ref type_str)) = object_map.get("__type") {
1980            if let Some(Value::String(ref name)) = object_map.get("__name") {
1981                return match type_str.as_ref() {
1982                    "Actor" => Some(Value::from_string(format!("__actor_constructor__:{name}"))),
1983                    "Struct" => Some(Value::from_string(format!("__struct_constructor__:{name}"))),
1984                    "Class" => Some(Value::from_string(format!(
1985                        "__class_constructor__:{name}:new"
1986                    ))),
1987                    _ => None,
1988                };
1989            }
1990        }
1991        None
1992    }
1993
1994    /// Check for actor field access (complexity: 2)
1995    fn check_actor_field_access(
1996        object_map: &HashMap<String, Value>,
1997        field: &str,
1998    ) -> Result<Option<Value>, InterpreterError> {
1999        if let Some(Value::String(actor_id)) = object_map.get("__actor_id") {
2000            use crate::runtime::actor_runtime::ACTOR_RUNTIME;
2001            let field_value = ACTOR_RUNTIME.get_actor_field(actor_id.as_ref(), field)?;
2002            Ok(Some(field_value.to_value()))
2003        } else {
2004            Ok(None)
2005        }
2006    }
2007
2008    /// Check struct field visibility (complexity: 2)
2009    fn check_struct_visibility(
2010        &self,
2011        object_map: &HashMap<String, Value>,
2012        field: &str,
2013    ) -> Result<(), InterpreterError> {
2014        if let Some(Value::String(struct_name)) = object_map.get("__struct_type") {
2015            self.check_field_visibility(struct_name.as_ref(), field)?;
2016        }
2017        Ok(())
2018    }
2019
2020    /// Get field from object map (complexity: 2)
2021    fn get_object_field(
2022        object_map: &HashMap<String, Value>,
2023        field: &str,
2024    ) -> Result<Value, InterpreterError> {
2025        object_map.get(field).cloned().ok_or_else(|| {
2026            InterpreterError::RuntimeError(format!("Object has no field named '{field}'"))
2027        })
2028    }
2029
2030    fn eval_object_literal(
2031        &mut self,
2032        fields: &[crate::frontend::ast::ObjectField],
2033    ) -> Result<Value, InterpreterError> {
2034        let mut object = HashMap::new();
2035
2036        for field in fields {
2037            match field {
2038                crate::frontend::ast::ObjectField::KeyValue { key, value } => {
2039                    let eval_value = self.eval_expr(value)?;
2040                    object.insert(key.clone(), eval_value);
2041                }
2042                crate::frontend::ast::ObjectField::Spread { expr: _ } => {
2043                    return Err(InterpreterError::RuntimeError(
2044                        "Spread operator in object literals not yet implemented".to_string(),
2045                    ));
2046                }
2047            }
2048        }
2049
2050        Ok(Value::Object(Arc::new(object)))
2051    }
2052
2053    fn eval_qualified_name(&self, module: &str, name: &str) -> Result<Value, InterpreterError> {
2054        if module == "HashMap" && name == "new" {
2055            Ok(Value::from_string("__builtin_hashmap__".to_string()))
2056        } else if module == "String" && (name == "new" || name == "from") {
2057            // REGRESSION-077: Route String::new() and String::from() to builtin handlers
2058            Ok(Value::from_string(format!("__builtin_String_{}__", name)))
2059        } else if name == "new" {
2060            // Check if this is a class constructor call
2061            if let Ok(class_value) = self.lookup_variable(module) {
2062                if let Value::Object(ref class_info) = class_value {
2063                    // Check if it's a class definition
2064                    if let Some(Value::String(ref type_str)) = class_info.get("__type") {
2065                        if type_str.as_ref() == "Class" {
2066                            // Return a special marker for class instantiation
2067                            return Ok(Value::from_string(format!(
2068                                "__class_constructor__:{}",
2069                                module
2070                            )));
2071                        }
2072                    }
2073                }
2074            }
2075            // Check if this is a struct constructor call
2076            if let Ok(struct_value) = self.lookup_variable(module) {
2077                if let Value::Object(ref struct_info) = struct_value {
2078                    // Check if it's a struct definition
2079                    if let Some(Value::String(ref type_str)) = struct_info.get("__type") {
2080                        if type_str.as_ref() == "Struct" {
2081                            // Return a special marker for struct instantiation
2082                            return Ok(Value::from_string(format!(
2083                                "__struct_constructor__:{}",
2084                                module
2085                            )));
2086                        }
2087                    }
2088                }
2089            }
2090            // Check if this is an actor constructor call
2091            if let Ok(actor_value) = self.lookup_variable(module) {
2092                if let Value::Object(ref actor_info) = actor_value {
2093                    // Check if it's an actor definition
2094                    if let Some(Value::String(ref type_str)) = actor_info.get("__type") {
2095                        if type_str.as_ref() == "Actor" {
2096                            // Return a special marker for actor instantiation
2097                            return Ok(Value::from_string(format!(
2098                                "__actor_constructor__:{}",
2099                                module
2100                            )));
2101                        }
2102                    }
2103                }
2104            }
2105            Err(InterpreterError::RuntimeError(format!(
2106                "Unknown qualified name: {}::{}",
2107                module, name
2108            )))
2109        } else {
2110            // REGRESSION-077: Check if this is an impl method (stored with qualified name)
2111            // Example: Logger::new_with_options stored as "Logger::new_with_options"
2112            let qualified_method_name = format!("{}::{}", module, name);
2113            if let Ok(method_value) = self.lookup_variable(&qualified_method_name) {
2114                Ok(method_value)
2115            } else {
2116                Err(InterpreterError::RuntimeError(format!(
2117                    "Unknown qualified name: {}::{}",
2118                    module, name
2119                )))
2120            }
2121        }
2122    }
2123
2124    /// Evaluate a literal value
2125    fn eval_literal(&self, lit: &Literal) -> Value {
2126        match lit {
2127            Literal::Integer(i, _) => Value::from_i64(*i),
2128            Literal::Float(f) => Value::from_f64(*f),
2129            Literal::String(s) => Value::from_string(s.clone()),
2130            Literal::Bool(b) => Value::from_bool(*b),
2131            Literal::Char(c) => Value::from_string(c.to_string()),
2132            Literal::Byte(b) => Value::Byte(*b),
2133            Literal::Unit => Value::nil(),
2134            Literal::Null => Value::nil(),
2135        }
2136    }
2137
2138    /// Look up a variable in the environment (searches from innermost to outermost)
2139    fn lookup_variable(&self, name: &str) -> Result<Value, InterpreterError> {
2140        // REGRESSION-077: Handle Option enum variants (Option::None, Option::Some)
2141        if name == "Option::None" {
2142            return Ok(Value::EnumVariant {
2143                enum_name: "Option".to_string(),
2144                variant_name: "None".to_string(),
2145                data: None,
2146            });
2147        }
2148
2149        // Check if this is a qualified name (e.g., "Point::new" or "Rectangle::square")
2150        if name.contains("::") {
2151            let parts: Vec<&str> = name.split("::").collect();
2152            if parts.len() == 2 {
2153                let type_name = parts[0];
2154                let method_name = parts[1];
2155
2156                // Look up the class or struct
2157                for env in self.env_stack.iter().rev() {
2158                    if let Some(value) = env.get(type_name) {
2159                        if let Value::Object(ref info) = value {
2160                            // Check if it's a class or struct
2161                            if let Some(Value::String(ref type_str)) = info.get("__type") {
2162                                if type_str.as_ref() == "Class" {
2163                                    // Check if it's a static method
2164                                    if let Some(Value::Object(ref methods)) = info.get("__methods")
2165                                    {
2166                                        if let Some(Value::Object(ref method_meta)) =
2167                                            methods.get(method_name)
2168                                        {
2169                                            if let Some(Value::Bool(true)) =
2170                                                method_meta.get("is_static")
2171                                            {
2172                                                // Return marker for static method
2173                                                return Ok(Value::from_string(format!(
2174                                                    "__class_static_method__:{}:{}",
2175                                                    type_name, method_name
2176                                                )));
2177                                            }
2178                                        }
2179                                    }
2180
2181                                    // Check if it's a constructor
2182                                    if let Some(Value::Object(ref constructors)) =
2183                                        info.get("__constructors")
2184                                    {
2185                                        if constructors.contains_key(method_name) {
2186                                            // Return marker for class constructor
2187                                            return Ok(Value::from_string(format!(
2188                                                "__class_constructor__:{}:{}",
2189                                                type_name, method_name
2190                                            )));
2191                                        }
2192                                    }
2193                                } else if type_str.as_ref() == "Struct" && method_name == "new" {
2194                                    return Ok(Value::from_string(format!(
2195                                        "__struct_constructor__:{}",
2196                                        type_name
2197                                    )));
2198                                } else if type_str.as_ref() == "Actor" && method_name == "new" {
2199                                    return Ok(Value::from_string(format!(
2200                                        "__actor_constructor__:{}",
2201                                        type_name
2202                                    )));
2203                                }
2204                            }
2205                        }
2206                    }
2207                }
2208            }
2209        }
2210
2211        // Normal variable lookup
2212        for env in self.env_stack.iter().rev() {
2213            if let Some(value) = env.get(name) {
2214                return Ok(value.clone());
2215            }
2216        }
2217        Err(InterpreterError::RuntimeError(format!(
2218            "Undefined variable: {name}"
2219        )))
2220    }
2221
2222    /// Get the current (innermost) environment
2223    #[allow(clippy::expect_used)] // Environment stack invariant ensures this never panics
2224    pub fn current_env(&self) -> &HashMap<String, Value> {
2225        self.env_stack
2226            .last()
2227            .expect("Environment stack should never be empty")
2228    }
2229
2230    /// Set a variable in the current environment
2231    #[allow(clippy::expect_used)] // Environment stack invariant ensures this never panics
2232    /// Create a new variable binding in the current scope (for `let` bindings)
2233    ///
2234    /// RUNTIME-038 FIX: `let` bindings create NEW variables in current scope (shadowing),
2235    /// they do NOT update variables in parent scopes. This prevents variable collision
2236    /// in nested function calls.
2237    ///
2238    /// # Complexity
2239    /// Cyclomatic complexity: 1 (within Toyota Way limits)
2240    fn env_set(&mut self, name: String, value: Value) {
2241        // Record type feedback for optimization
2242        self.record_variable_assignment_feedback(&name, &value);
2243
2244        // ALWAYS create in current scope - `let` bindings shadow outer scopes
2245        // Do NOT search parent scopes (that's for reassignments without `let`)
2246        let env = self
2247            .env_stack
2248            .last_mut()
2249            .expect("Environment stack should never be empty");
2250        env.insert(name, value);
2251    }
2252
2253    /// Set a mutable variable in the environment
2254    /// ISSUE-040 FIX: Searches parent scopes for existing variable and mutates it.
2255    /// Falls back to creating new binding in current scope if variable doesn't exist.
2256    ///
2257    /// # Complexity
2258    /// Cyclomatic complexity: 4 (within Toyota Way limits ≤10)
2259    fn env_set_mut(&mut self, name: String, value: Value) {
2260        // Record type feedback for optimization
2261        self.record_variable_assignment_feedback(&name, &value);
2262
2263        // Search from innermost to outermost scope for existing variable
2264        for env in self.env_stack.iter_mut().rev() {
2265            if let std::collections::hash_map::Entry::Occupied(mut e) = env.entry(name.clone()) {
2266                // Found existing variable - mutate it in place
2267                e.insert(value);
2268                return;
2269            }
2270        }
2271
2272        // Variable doesn't exist in any scope - create new binding in current scope
2273        let env = self
2274            .env_stack
2275            .last_mut()
2276            .expect("Environment stack should never be empty");
2277        env.insert(name, value);
2278    }
2279
2280    /// Push a new environment onto the stack
2281    fn env_push(&mut self, env: HashMap<String, Value>) {
2282        self.env_stack.push(env);
2283    }
2284
2285    /// Pop the current environment from the stack
2286    fn env_pop(&mut self) -> Option<HashMap<String, Value>> {
2287        if self.env_stack.len() > 1 {
2288            // Keep at least the global environment
2289            self.env_stack.pop()
2290        } else {
2291            None
2292        }
2293    }
2294
2295    /// Helper method to call a Value function with arguments (for array methods)
2296    fn eval_function_call_value(
2297        &mut self,
2298        func: &Value,
2299        args: &[Value],
2300    ) -> Result<Value, InterpreterError> {
2301        self.call_function(func.clone(), args)
2302    }
2303
2304    /// Call a function with given arguments
2305    fn call_function(&mut self, func: Value, args: &[Value]) -> Result<Value, InterpreterError> {
2306        match func {
2307            Value::String(ref s) if s.starts_with("__class_constructor__:") => {
2308                // Extract class name and constructor name from the marker
2309                let parts: Vec<&str> = s
2310                    .strip_prefix("__class_constructor__:")
2311                    .unwrap()
2312                    .split(':')
2313                    .collect();
2314
2315                if parts.len() == 2 {
2316                    let class_name = parts[0];
2317                    let constructor_name = parts[1];
2318                    self.instantiate_class_with_constructor(class_name, constructor_name, args)
2319                } else {
2320                    // Legacy format for backward compatibility
2321                    self.instantiate_class_with_constructor(parts[0], "new", args)
2322                }
2323            }
2324            Value::String(ref s) if s.starts_with("__class_static_method__:") => {
2325                // Extract class name and method name from the marker
2326                let parts: Vec<&str> = s
2327                    .strip_prefix("__class_static_method__:")
2328                    .unwrap()
2329                    .split(':')
2330                    .collect();
2331
2332                if parts.len() == 2 {
2333                    let class_name = parts[0];
2334                    let method_name = parts[1];
2335                    self.call_static_method(class_name, method_name, args)
2336                } else {
2337                    Err(InterpreterError::RuntimeError(
2338                        "Invalid static method marker".to_string(),
2339                    ))
2340                }
2341            }
2342            Value::String(ref s) if s.starts_with("__struct_constructor__:") => {
2343                // Extract struct name from the marker
2344                let struct_name = s.strip_prefix("__struct_constructor__:").unwrap();
2345                self.instantiate_struct_with_args(struct_name, args)
2346            }
2347            Value::String(ref s) if s.starts_with("__actor_constructor__:") => {
2348                // Extract actor name from the marker
2349                let actor_name = s.strip_prefix("__actor_constructor__:").unwrap();
2350                self.instantiate_actor_with_args(actor_name, args)
2351            }
2352            Value::String(s) if s.starts_with("__builtin_") => {
2353                // Delegate to extracted builtin module
2354                match crate::runtime::eval_builtin::eval_builtin_function(&s, args)? {
2355                    Some(result) => Ok(result),
2356                    None => Err(InterpreterError::RuntimeError(format!(
2357                        "Unknown builtin function: {}",
2358                        s
2359                    ))),
2360                }
2361            }
2362            Value::Closure { params, body, env } => {
2363                // [RUNTIME-001] CHECK RECURSION DEPTH BEFORE ENTERING
2364                crate::runtime::eval_function::check_recursion_depth()?;
2365
2366                // Check argument count
2367                if args.len() != params.len() {
2368                    crate::runtime::eval_function::decrement_depth();
2369                    return Err(InterpreterError::RuntimeError(format!(
2370                        "Function expects {} arguments, got {}",
2371                        params.len(),
2372                        args.len()
2373                    )));
2374                }
2375
2376                // Create new environment with captured environment as base
2377                let mut new_env = env.as_ref().clone();
2378
2379                // Bind parameters to arguments
2380                for (param, arg) in params.iter().zip(args) {
2381                    new_env.insert(param.clone(), arg.clone());
2382                }
2383
2384                // Push new environment
2385                self.env_push(new_env);
2386
2387                // Evaluate function body
2388                // Catch InterpreterError::Return and extract value (early return support)
2389                let result = match self.eval_expr(&body) {
2390                    Err(InterpreterError::Return(val)) => Ok(val),
2391                    other => other,
2392                };
2393
2394                // Pop environment
2395                self.env_pop();
2396
2397                // [RUNTIME-001] ALWAYS DECREMENT, EVEN ON ERROR
2398                crate::runtime::eval_function::decrement_depth();
2399
2400                result
2401            }
2402            Value::Object(ref obj) => {
2403                // Check if this is a struct or actor definition being called as a constructor
2404                if let Some(Value::String(type_str)) = obj.get("__type") {
2405                    match type_str.as_ref() {
2406                        "Struct" => {
2407                            // Get struct name and instantiate
2408                            if let Some(Value::String(name)) = obj.get("__name") {
2409                                self.instantiate_struct_with_args(name.as_ref(), args)
2410                            } else {
2411                                Err(InterpreterError::RuntimeError(
2412                                    "Struct missing __name field".to_string(),
2413                                ))
2414                            }
2415                        }
2416                        "Actor" => {
2417                            // Get actor name and instantiate
2418                            if let Some(Value::String(name)) = obj.get("__name") {
2419                                self.instantiate_actor_with_args(name.as_ref(), args)
2420                            } else {
2421                                Err(InterpreterError::RuntimeError(
2422                                    "Actor missing __name field".to_string(),
2423                                ))
2424                            }
2425                        }
2426                        "Class" => {
2427                            // Get class name and instantiate
2428                            if let Some(Value::String(name)) = obj.get("__name") {
2429                                self.instantiate_class_with_args(name.as_ref(), args)
2430                            } else {
2431                                Err(InterpreterError::RuntimeError(
2432                                    "Class missing __name field".to_string(),
2433                                ))
2434                            }
2435                        }
2436                        _ => Err(InterpreterError::TypeError(format!(
2437                            "Cannot call object of type: {}",
2438                            type_str
2439                        ))),
2440                    }
2441                } else {
2442                    Err(InterpreterError::TypeError(format!(
2443                        "Cannot call non-function value: {}",
2444                        func.type_name()
2445                    )))
2446                }
2447            }
2448            _ => Err(InterpreterError::TypeError(format!(
2449                "Cannot call non-function value: {}",
2450                func.type_name()
2451            ))),
2452        }
2453    }
2454
2455    /// Evaluate a binary operation from AST.
2456    ///
2457    /// Dispatches to specialized evaluation functions based on operator type:
2458    /// - Arithmetic: `+`, `-`, `*`, `/`, `%`, `**`
2459    /// - Comparison: `==`, `!=`, `<`, `>`, `<=`, `>=`
2460    /// - Logical: `&&`, `||`
2461    ///
2462    /// # Errors
2463    ///
2464    /// Returns an error if:
2465    /// - Type mismatch (e.g., adding string to number)
2466    /// - Division by zero
2467    /// - Unsupported operator
2468    fn eval_binary_op(
2469        &self,
2470        op: AstBinaryOp,
2471        left: &Value,
2472        right: &Value,
2473    ) -> Result<Value, InterpreterError> {
2474        crate::runtime::eval_operations::eval_binary_op(op, left, right)
2475    }
2476
2477    fn eval_unary_op(
2478        &self,
2479        op: crate::frontend::ast::UnaryOp,
2480        operand: &Value,
2481    ) -> Result<Value, InterpreterError> {
2482        crate::runtime::eval_operations::eval_unary_op(op, operand)
2483    }
2484
2485    /// Evaluate binary expression
2486    fn eval_binary_expr(
2487        &mut self,
2488        left: &Expr,
2489        op: crate::frontend::ast::BinaryOp,
2490        right: &Expr,
2491    ) -> Result<Value, InterpreterError> {
2492        // Handle short-circuit operators and special operators
2493        match op {
2494            crate::frontend::ast::BinaryOp::Send => {
2495                // Actor send operator: actor ! message
2496                let left_val = self.eval_expr(left)?;
2497                let message_val = self.eval_message_expr(right)?;
2498
2499                // Extract the ObjectMut from the actor
2500                if let Value::ObjectMut(cell_rc) = left_val {
2501                    // Process the message synchronously
2502                    self.process_actor_message_sync_mut(&cell_rc, &message_val)?;
2503                    // Fire-and-forget returns Nil
2504                    Ok(Value::Nil)
2505                } else {
2506                    Err(InterpreterError::RuntimeError(format!(
2507                        "Send operator requires an actor instance, got {}",
2508                        left_val.type_name()
2509                    )))
2510                }
2511            }
2512            crate::frontend::ast::BinaryOp::NullCoalesce => {
2513                let left_val = self.eval_expr(left)?;
2514                if matches!(left_val, Value::Nil) {
2515                    self.eval_expr(right)
2516                } else {
2517                    Ok(left_val)
2518                }
2519            }
2520            crate::frontend::ast::BinaryOp::And => {
2521                let left_val = self.eval_expr(left)?;
2522                if left_val.is_truthy() {
2523                    self.eval_expr(right)
2524                } else {
2525                    Ok(left_val)
2526                }
2527            }
2528            crate::frontend::ast::BinaryOp::Or => {
2529                let left_val = self.eval_expr(left)?;
2530                if left_val.is_truthy() {
2531                    Ok(left_val)
2532                } else {
2533                    self.eval_expr(right)
2534                }
2535            }
2536            _ => {
2537                let left_val = self.eval_expr(left)?;
2538                let right_val = self.eval_expr(right)?;
2539                let result = self.eval_binary_op(op, &left_val, &right_val)?;
2540
2541                // Record type feedback for optimization
2542                let site_id = left.span.start; // Use span start as site ID
2543                self.record_binary_op_feedback(site_id, &left_val, &right_val, &result);
2544
2545                Ok(result)
2546            }
2547        }
2548    }
2549
2550    /// Evaluate unary expression
2551    fn eval_unary_expr(
2552        &mut self,
2553        op: crate::frontend::ast::UnaryOp,
2554        operand: &Expr,
2555    ) -> Result<Value, InterpreterError> {
2556        let operand_val = self.eval_expr(operand)?;
2557        self.eval_unary_op(op, &operand_val)
2558    }
2559
2560    /// Evaluate type cast expression (as operator)
2561    ///
2562    /// # Complexity
2563    /// Cyclomatic complexity: 8 (within Toyota Way limits)
2564    fn eval_type_cast(
2565        &mut self,
2566        expr: &Expr,
2567        target_type: &str,
2568    ) -> Result<Value, InterpreterError> {
2569        // Special case: Enum variant to integer (Issue #79)
2570        // Must extract enum name from AST BEFORE evaluating expression
2571        if matches!(target_type, "i32" | "i64" | "isize") {
2572            if let ExprKind::FieldAccess { object, field } = &expr.kind {
2573                if let ExprKind::Identifier(enum_name) = &object.kind {
2574                    // Direct enum literal: LogLevel::Info as i32
2575                    let variant_name = field;
2576
2577                    // Lookup enum definition in environment
2578                    if let Some(Value::Object(enum_def)) = self.get_variable(enum_name) {
2579                        if let Some(Value::Object(variants)) = enum_def.get("__variants") {
2580                            if let Some(Value::Object(variant_info)) = variants.get(variant_name) {
2581                                if let Some(Value::Integer(disc)) =
2582                                    variant_info.get("discriminant")
2583                                {
2584                                    return Ok(Value::Integer(*disc));
2585                                }
2586                            }
2587                        }
2588                    }
2589                }
2590            }
2591        }
2592
2593        // Standard case: Evaluate expression first, then cast
2594        let value = self.eval_expr(expr)?;
2595
2596        match (value, target_type) {
2597            // Integer to Float
2598            (Value::Integer(i), "f64" | "f32") => Ok(Value::Float(i as f64)),
2599
2600            // Float to Integer (truncation)
2601            (Value::Float(f), "i32" | "i64" | "isize") => Ok(Value::Integer(f as i64)),
2602
2603            // Integer to Integer (identity for i32/i64)
2604            (Value::Integer(i), "i32" | "i64" | "isize") => Ok(Value::Integer(i)),
2605
2606            // Float to Float (identity)
2607            (Value::Float(f), "f64" | "f32") => Ok(Value::Float(f)),
2608
2609            // Enum variant to Integer - variable case (e.g., level as i32)
2610            // Now supported via discriminant lookup using stored enum_name
2611            (Value::EnumVariant { enum_name, variant_name, .. }, "i32" | "i64" | "isize") => {
2612                // Lookup enum definition in environment
2613                if let Some(Value::Object(enum_def)) = self.get_variable(&enum_name) {
2614                    if let Some(Value::Object(variants)) = enum_def.get("__variants") {
2615                        if let Some(Value::Object(variant_info)) = variants.get(&variant_name) {
2616                            if let Some(Value::Integer(disc)) = variant_info.get("discriminant") {
2617                                return Ok(Value::Integer(*disc));
2618                            }
2619                        }
2620                    }
2621                }
2622                Err(InterpreterError::TypeError(format!(
2623                    "Cannot cast enum variant {}::{} to integer: enum definition not found",
2624                    enum_name, variant_name
2625                )))
2626            }
2627
2628            // Unsupported cast
2629            (val, target) => Err(InterpreterError::TypeError(format!(
2630                "Cannot cast {} to {}",
2631                val.type_name(),
2632                target
2633            ))),
2634        }
2635    }
2636
2637    /// Evaluate if expression
2638    fn eval_if_expr(
2639        &mut self,
2640        condition: &Expr,
2641        then_branch: &Expr,
2642        else_branch: Option<&Expr>,
2643    ) -> Result<Value, InterpreterError> {
2644        crate::runtime::eval_control_flow_new::eval_if_expr(
2645            condition,
2646            then_branch,
2647            else_branch,
2648            |e| self.eval_expr(e),
2649        )
2650    }
2651
2652    /// Evaluate let expression
2653    fn eval_let_expr(
2654        &mut self,
2655        name: &str,
2656        value: &Expr,
2657        body: &Expr,
2658    ) -> Result<Value, InterpreterError> {
2659        let val = self.eval_expr(value)?;
2660        self.env_set(name.to_string(), val.clone());
2661
2662        // If body is unit (empty), return the value like REPL does
2663        // This makes `let x = 42` return 42 instead of nil
2664        match &body.kind {
2665            ExprKind::Literal(Literal::Unit) => Ok(val),
2666            _ => self.eval_expr(body),
2667        }
2668    }
2669
2670    /// Evaluate return expression
2671    fn eval_return_expr(&mut self, value: Option<&Expr>) -> Result<Value, InterpreterError> {
2672        crate::runtime::eval_control_flow_new::eval_return_expr(value, |e| self.eval_expr(e))
2673    }
2674
2675    /// Evaluate list expression
2676    fn eval_list_expr(&mut self, elements: &[Expr]) -> Result<Value, InterpreterError> {
2677        crate::runtime::eval_control_flow_new::eval_list_expr(elements, |e| self.eval_expr(e))
2678    }
2679
2680    /// Evaluate array initialization expression [value; size]
2681    fn eval_array_init_expr(
2682        &mut self,
2683        value_expr: &Expr,
2684        size_expr: &Expr,
2685    ) -> Result<Value, InterpreterError> {
2686        crate::runtime::eval_control_flow_new::eval_array_init_expr(value_expr, size_expr, |e| {
2687            self.eval_expr(e)
2688        })
2689    }
2690
2691    /// Evaluate block expression
2692    fn eval_block_expr(&mut self, statements: &[Expr]) -> Result<Value, InterpreterError> {
2693        crate::runtime::eval_control_flow_new::eval_block_expr(statements, |e| self.eval_expr(e))
2694    }
2695
2696    /// Evaluate tuple expression
2697    fn eval_tuple_expr(&mut self, elements: &[Expr]) -> Result<Value, InterpreterError> {
2698        crate::runtime::eval_control_flow_new::eval_tuple_expr(elements, |e| self.eval_expr(e))
2699    }
2700
2701    /// Evaluate `DataFrame` literal expression
2702    /// Complexity: 5 (within Toyota Way limits)
2703    fn eval_dataframe_literal(
2704        &mut self,
2705        columns: &[crate::frontend::ast::DataFrameColumn],
2706    ) -> Result<Value, InterpreterError> {
2707        let mut evaluated_columns = Vec::new();
2708
2709        for col in columns {
2710            // Evaluate each value expression in the column
2711            let mut evaluated_values = Vec::new();
2712            for value_expr in &col.values {
2713                evaluated_values.push(self.eval_expr(value_expr)?);
2714            }
2715
2716            // Create runtime DataFrameColumn
2717            evaluated_columns.push(DataFrameColumn {
2718                name: col.name.clone(),
2719                values: evaluated_values,
2720            });
2721        }
2722
2723        Ok(Value::DataFrame {
2724            columns: evaluated_columns,
2725        })
2726    }
2727
2728    /// Evaluate range expression
2729    fn eval_range_expr(
2730        &mut self,
2731        start: &Expr,
2732        end: &Expr,
2733        inclusive: bool,
2734    ) -> Result<Value, InterpreterError> {
2735        crate::runtime::eval_control_flow_new::eval_range_expr(start, end, inclusive, |e| {
2736            self.eval_expr(e)
2737        })
2738    }
2739
2740    /// Helper function for testing - evaluate a string expression via parser
2741    /// # Errors
2742    /// Returns error if parsing or evaluation fails
2743    #[cfg(test)]
2744    /// Evaluate a string of Ruchy code.
2745    ///
2746    /// This convenience function parses and evaluates a string in one step.
2747    /// It's useful for REPL implementations and testing.
2748    ///
2749    /// # Examples
2750    ///
2751    /// ```
2752    /// use ruchy::runtime::interpreter::Interpreter;
2753    ///
2754    /// let mut interpreter = Interpreter::new();
2755    /// let result = interpreter.eval_string("2 * 21").unwrap();
2756    /// assert_eq!(result.to_string(), "42");
2757    /// ```
2758    ///
2759    /// # Errors
2760    ///
2761    /// Returns an error if parsing fails or if evaluation fails.
2762    pub fn eval_string(&mut self, input: &str) -> Result<Value, Box<dyn std::error::Error>> {
2763        use crate::frontend::parser::Parser;
2764
2765        let mut parser = Parser::new(input);
2766        let expr = parser.parse_expr()?;
2767
2768        Ok(self.eval_expr(&expr)?)
2769    }
2770
2771    /// Push value onto stack
2772    /// # Errors
2773    /// Returns error if stack overflow occurs
2774    pub fn push(&mut self, value: Value) -> Result<(), InterpreterError> {
2775        if self.stack.len() >= 10_000 {
2776            // Stack limit from spec
2777            return Err(InterpreterError::StackOverflow);
2778        }
2779        self.stack.push(value);
2780        Ok(())
2781    }
2782
2783    /// Pop value from stack
2784    /// # Errors
2785    /// Returns error if stack underflow occurs
2786    pub fn pop(&mut self) -> Result<Value, InterpreterError> {
2787        self.stack.pop().ok_or(InterpreterError::StackUnderflow)
2788    }
2789
2790    /// Peek at top of stack without popping
2791    /// # Errors
2792    /// Returns error if stack underflow occurs
2793    pub fn peek(&self, depth: usize) -> Result<Value, InterpreterError> {
2794        let index = self
2795            .stack
2796            .len()
2797            .checked_sub(depth + 1)
2798            .ok_or(InterpreterError::StackUnderflow)?;
2799        Ok(self.stack[index].clone())
2800    }
2801
2802    /// Binary arithmetic operation with type checking
2803    /// # Errors
2804    /// Returns error if stack underflow, type mismatch, or arithmetic error occurs
2805    pub fn binary_op(&mut self, op: BinaryOp) -> Result<(), InterpreterError> {
2806        let right = self.pop()?;
2807        let left = self.pop()?;
2808
2809        let result = match op {
2810            BinaryOp::Add => eval_operations::eval_binary_op(AstBinaryOp::Add, &left, &right)?,
2811            BinaryOp::Sub => eval_operations::eval_binary_op(AstBinaryOp::Subtract, &left, &right)?,
2812            BinaryOp::Mul => eval_operations::eval_binary_op(AstBinaryOp::Multiply, &left, &right)?,
2813            BinaryOp::Div => eval_operations::eval_binary_op(AstBinaryOp::Divide, &left, &right)?,
2814            BinaryOp::Eq => eval_operations::eval_binary_op(AstBinaryOp::Equal, &left, &right)?,
2815            BinaryOp::Lt => eval_operations::eval_binary_op(AstBinaryOp::Less, &left, &right)?,
2816            BinaryOp::Gt => eval_operations::eval_binary_op(AstBinaryOp::Greater, &left, &right)?,
2817        };
2818
2819        self.push(result)?;
2820        Ok(())
2821    }
2822
2823    /// Set a variable in the current scope (public for try/catch)
2824    pub fn set_variable_string(&mut self, name: String, value: Value) {
2825        self.env_set(name, value);
2826    }
2827
2828    /// Apply a binary operation to two values
2829    fn apply_binary_op(
2830        &self,
2831        left: &Value,
2832        op: AstBinaryOp,
2833        right: &Value,
2834    ) -> Result<Value, InterpreterError> {
2835        // Delegate to existing binary operation evaluation
2836        self.eval_binary_op(op, left, right)
2837    }
2838
2839    /// Check if a pattern matches a value
2840    /// # Errors
2841    /// Returns error if pattern matching fails
2842    /// Try to match a pattern against a value, returning bindings if successful
2843    fn try_pattern_match(
2844        &self,
2845        pattern: &Pattern,
2846        value: &Value,
2847    ) -> Result<Option<Vec<(String, Value)>>, InterpreterError> {
2848        crate::runtime::eval_pattern_match::try_pattern_match(pattern, value, &|lit| {
2849            self.eval_literal(lit)
2850        })
2851    }
2852
2853    /// Legacy method for backwards compatibility
2854    fn pattern_matches_internal(
2855        &self,
2856        pattern: &Pattern,
2857        value: &Value,
2858    ) -> Result<bool, InterpreterError> {
2859        crate::runtime::eval_pattern_match::pattern_matches(pattern, value, &|lit| {
2860            self.eval_literal(lit)
2861        })
2862    }
2863
2864    /// Scope management for pattern bindings
2865    pub fn push_scope(&mut self) {
2866        let new_env = HashMap::new();
2867        self.env_push(new_env);
2868    }
2869
2870    pub fn pop_scope(&mut self) {
2871        self.env_pop();
2872    }
2873
2874    /// New pattern matching methods that return bindings
2875
2876    // Helper methods for pattern matching (complexity <10 each)
2877
2878    fn match_tuple_pattern(
2879        &self,
2880        patterns: &[Pattern],
2881        value: &Value,
2882    ) -> Result<bool, InterpreterError> {
2883        crate::runtime::eval_pattern_match::match_tuple_pattern(patterns, value, |lit| {
2884            self.eval_literal(lit)
2885        })
2886    }
2887
2888    fn match_list_pattern(
2889        &self,
2890        patterns: &[Pattern],
2891        value: &Value,
2892    ) -> Result<bool, InterpreterError> {
2893        crate::runtime::eval_pattern_match::match_list_pattern(patterns, value, |lit| {
2894            self.eval_literal(lit)
2895        })
2896    }
2897
2898    fn match_or_pattern(
2899        &self,
2900        patterns: &[Pattern],
2901        value: &Value,
2902    ) -> Result<bool, InterpreterError> {
2903        crate::runtime::eval_pattern_match::match_or_pattern(patterns, value, |lit| {
2904            self.eval_literal(lit)
2905        })
2906    }
2907
2908    /// Access field with inline caching optimization
2909    /// # Errors
2910    /// Returns error if field access fails
2911    pub fn get_field_cached(
2912        &mut self,
2913        obj: &Value,
2914        field_name: &str,
2915    ) -> Result<Value, InterpreterError> {
2916        // Create cache key combining object type and field name
2917        let cache_key = format!("{:?}::{}", obj.type_id(), field_name);
2918
2919        // Check inline cache first
2920        if let Some(cache) = self.field_caches.get_mut(&cache_key) {
2921            if let Some(cached_result) = cache.lookup(obj, field_name) {
2922                return Ok(cached_result);
2923            }
2924        }
2925
2926        // Cache miss - compute result and update cache
2927        let result = self.compute_field_access(obj, field_name)?;
2928
2929        // Update or create cache entry
2930        let cache = self.field_caches.entry(cache_key).or_default();
2931        cache.insert(obj, field_name.to_string(), result.clone());
2932
2933        Ok(result)
2934    }
2935
2936    /// Compute field access result (detailed path)
2937    fn compute_field_access(
2938        &self,
2939        obj: &Value,
2940        field_name: &str,
2941    ) -> Result<Value, InterpreterError> {
2942        match (obj, field_name) {
2943            // String methods
2944            (Value::String(s), "len") => Ok(Value::Integer(s.len().try_into().unwrap_or(i64::MAX))),
2945            (Value::String(s), "to_upper") => Ok(Value::from_string(s.to_uppercase())),
2946            (Value::String(s), "to_lower") => Ok(Value::from_string(s.to_lowercase())),
2947            (Value::String(s), "trim") => Ok(Value::from_string(s.trim().to_string())),
2948
2949            // Array methods
2950            (Value::Array(arr), "len") => {
2951                Ok(Value::Integer(arr.len().try_into().unwrap_or(i64::MAX)))
2952            }
2953            (Value::Array(arr), "first") => arr
2954                .first()
2955                .cloned()
2956                .ok_or_else(|| InterpreterError::RuntimeError("Array is empty".to_string())),
2957            (Value::Array(arr), "last") => arr
2958                .last()
2959                .cloned()
2960                .ok_or_else(|| InterpreterError::RuntimeError("Array is empty".to_string())),
2961            (Value::Array(arr), "is_empty") => Ok(Value::from_bool(arr.is_empty())),
2962
2963            // Type information
2964            (obj, "type") => Ok(Value::from_string(obj.type_name().to_string())),
2965
2966            _ => Err(InterpreterError::RuntimeError(format!(
2967                "Field '{}' not found on type '{}'",
2968                field_name,
2969                obj.type_name()
2970            ))),
2971        }
2972    }
2973
2974    /// Get inline cache statistics for profiling
2975    pub fn get_cache_stats(&self) -> HashMap<String, f64> {
2976        let mut stats = HashMap::new();
2977        for (key, cache) in &self.field_caches {
2978            stats.insert(key.clone(), cache.hit_rate());
2979        }
2980        stats
2981    }
2982
2983    /// Clear all inline caches (for testing)
2984    pub fn clear_caches(&mut self) {
2985        self.field_caches.clear();
2986    }
2987
2988    /// Record type feedback for binary operations
2989    #[allow(dead_code)] // Used by tests and type feedback system
2990    fn record_binary_op_feedback(
2991        &mut self,
2992        site_id: usize,
2993        left: &Value,
2994        right: &Value,
2995        result: &Value,
2996    ) {
2997        self.type_feedback
2998            .record_binary_op(site_id, left, right, result);
2999    }
3000
3001    /// Record type feedback for variable assignments
3002    #[allow(dead_code)] // Used by tests and type feedback system
3003    fn record_variable_assignment_feedback(&mut self, var_name: &str, value: &Value) {
3004        let type_id = value.type_id();
3005        self.type_feedback
3006            .record_variable_assignment(var_name, type_id);
3007    }
3008
3009    /// Record type feedback for function calls
3010    fn record_function_call_feedback(
3011        &mut self,
3012        site_id: usize,
3013        func_name: &str,
3014        args: &[Value],
3015        result: &Value,
3016    ) {
3017        self.type_feedback
3018            .record_function_call(site_id, func_name, args, result);
3019    }
3020
3021    /// Get type feedback statistics
3022    pub fn get_type_feedback_stats(&self) -> TypeFeedbackStats {
3023        self.type_feedback.get_statistics()
3024    }
3025
3026    /// Get specialization candidates for JIT compilation
3027    pub fn get_specialization_candidates(&self) -> Vec<SpecializationCandidate> {
3028        self.type_feedback.get_specialization_candidates()
3029    }
3030
3031    /// Clear type feedback data (for testing)
3032    pub fn clear_type_feedback(&mut self) {
3033        self.type_feedback = TypeFeedback::new();
3034    }
3035
3036    /// Track a value in the garbage collector
3037    pub fn gc_track(&mut self, value: Value) -> usize {
3038        self.gc.track_object(value)
3039    }
3040
3041    /// Force garbage collection
3042    pub fn gc_collect(&mut self) -> GCStats {
3043        self.gc.force_collect()
3044    }
3045
3046    /// Get garbage collection statistics
3047    pub fn gc_stats(&self) -> GCStats {
3048        self.gc.get_stats()
3049    }
3050
3051    /// Get detailed garbage collection information
3052    pub fn gc_info(&self) -> GCInfo {
3053        self.gc.get_info()
3054    }
3055
3056    /// Set garbage collection threshold
3057    pub fn gc_set_threshold(&mut self, threshold: usize) {
3058        self.gc.set_collection_threshold(threshold);
3059    }
3060
3061    /// Enable or disable automatic garbage collection
3062    pub fn gc_set_auto_collect(&mut self, enabled: bool) {
3063        self.gc.set_auto_collect(enabled);
3064    }
3065
3066    /// Clear all GC-tracked objects (for testing)
3067    pub fn gc_clear(&mut self) {
3068        self.gc.clear();
3069    }
3070
3071    /// Allocate a new array and track it in GC
3072    pub fn gc_alloc_array(&mut self, elements: Vec<Value>) -> Value {
3073        let array_value = Value::from_array(elements);
3074        self.gc.track_object(array_value.clone());
3075        array_value
3076    }
3077
3078    /// Allocate a new string and track it in GC
3079    pub fn gc_alloc_string(&mut self, content: String) -> Value {
3080        let string_value = Value::from_string(content);
3081        self.gc.track_object(string_value.clone());
3082        string_value
3083    }
3084
3085    /// Allocate a new closure and track it in GC
3086    pub fn gc_alloc_closure(
3087        &mut self,
3088        params: Vec<String>,
3089        body: Arc<Expr>,
3090        env: Arc<HashMap<String, Value>>,
3091    ) -> Value {
3092        let closure_value = Value::Closure { params, body, env };
3093        self.gc.track_object(closure_value.clone());
3094        closure_value
3095    }
3096
3097    // ========================================================================
3098    // Public methods for SharedSession integration
3099    // ========================================================================
3100
3101    /// Get all bindings from the global environment (for `SharedSession` state persistence)
3102    pub fn get_global_bindings(&self) -> HashMap<String, Value> {
3103        if let Some(global_env) = self.env_stack.first() {
3104            global_env.clone()
3105        } else {
3106            HashMap::new()
3107        }
3108    }
3109
3110    /// Set a binding in the global environment (for `SharedSession` state restoration)
3111    pub fn set_global_binding(&mut self, name: String, value: Value) {
3112        if let Some(global_env) = self.env_stack.first_mut() {
3113            global_env.insert(name, value);
3114        }
3115    }
3116
3117    /// Clear all user variables from global environment, keeping only builtins
3118    pub fn clear_user_variables(&mut self) {
3119        if let Some(global_env) = self.env_stack.first_mut() {
3120            // Keep only builtin functions (those starting with "__builtin_") and nil
3121            global_env.retain(|name, _| name.starts_with("__builtin_") || name == "nil");
3122        }
3123    }
3124
3125    /// Get all bindings from the current environment (for `SharedSession` extraction)
3126    pub fn get_current_bindings(&self) -> HashMap<String, Value> {
3127        if let Some(current_env) = self.env_stack.last() {
3128            current_env.clone()
3129        } else {
3130            HashMap::new()
3131        }
3132    }
3133
3134    /// Evaluate a for loop
3135    fn eval_for_loop(
3136        &mut self,
3137        label: Option<&String>,
3138        var: &str,
3139        _pattern: Option<&Pattern>,
3140        iter: &Expr,
3141        body: &Expr,
3142    ) -> Result<Value, InterpreterError> {
3143        let iter_value = self.eval_expr(iter)?;
3144
3145        match iter_value {
3146            Value::Array(ref arr) => self.eval_for_array_iteration(label, var, arr, body),
3147            Value::Range {
3148                ref start,
3149                ref end,
3150                inclusive,
3151            } => self.eval_for_range_iteration(label, var, start, end, inclusive, body),
3152            _ => Err(InterpreterError::TypeError(
3153                "For loop requires an iterable".to_string(),
3154            )),
3155        }
3156    }
3157
3158    /// Evaluate for loop iteration over an array
3159    /// Complexity: ≤8
3160    fn eval_for_array_iteration(
3161        &mut self,
3162        label: Option<&String>,
3163        loop_var: &str,
3164        arr: &[Value],
3165        body: &Expr,
3166    ) -> Result<Value, InterpreterError> {
3167        let mut last_value = Value::nil();
3168
3169        for item in arr {
3170            self.set_variable(loop_var, item.clone());
3171            match self.eval_loop_body_with_control_flow(body) {
3172                Ok(value) => last_value = value,
3173                Err(LoopControlOrError::Break(break_label, break_val)) => {
3174                    // If break has no label or matches this loop's label, break here
3175                    if break_label.is_none() || break_label.as_deref() == label.map(String::as_str)
3176                    {
3177                        return Ok(break_val);
3178                    }
3179                    // Otherwise, propagate to outer loop
3180                    return Err(InterpreterError::Break(break_label, break_val));
3181                }
3182                Err(LoopControlOrError::Continue(continue_label)) => {
3183                    // If continue has no label or matches this loop's label, continue here
3184                    if continue_label.is_none()
3185                        || continue_label.as_deref() == label.map(String::as_str)
3186                    {
3187                        continue;
3188                    }
3189                    // Otherwise, propagate to outer loop
3190                    return Err(InterpreterError::Continue(continue_label));
3191                }
3192                Err(LoopControlOrError::Return(return_val)) => {
3193                    return Err(InterpreterError::Return(return_val))
3194                }
3195                Err(LoopControlOrError::Error(e)) => return Err(e),
3196            }
3197        }
3198
3199        Ok(last_value)
3200    }
3201
3202    /// Evaluate for loop iteration over a range
3203    /// Complexity: ≤9
3204    fn eval_for_range_iteration(
3205        &mut self,
3206        label: Option<&String>,
3207        loop_var: &str,
3208        start: &Value,
3209        end: &Value,
3210        inclusive: bool,
3211        body: &Expr,
3212    ) -> Result<Value, InterpreterError> {
3213        let (start_val, end_val) = self.extract_range_bounds(start, end)?;
3214        let mut last_value = Value::nil();
3215
3216        for i in self.create_range_iterator(start_val, end_val, inclusive) {
3217            self.set_variable(loop_var, Value::Integer(i));
3218            match self.eval_loop_body_with_control_flow(body) {
3219                Ok(value) => last_value = value,
3220                Err(LoopControlOrError::Break(break_label, break_val)) => {
3221                    if break_label.is_none() || break_label.as_deref() == label.map(String::as_str)
3222                    {
3223                        return Ok(break_val);
3224                    }
3225                    return Err(InterpreterError::Break(break_label, break_val));
3226                }
3227                Err(LoopControlOrError::Continue(continue_label)) => {
3228                    if continue_label.is_none()
3229                        || continue_label.as_deref() == label.map(String::as_str)
3230                    {
3231                        continue;
3232                    }
3233                    return Err(InterpreterError::Continue(continue_label));
3234                }
3235                Err(LoopControlOrError::Return(return_val)) => {
3236                    return Err(InterpreterError::Return(return_val))
3237                }
3238                Err(LoopControlOrError::Error(e)) => return Err(e),
3239            }
3240        }
3241
3242        Ok(last_value)
3243    }
3244
3245    /// Extract integer bounds from range values
3246    /// Complexity: ≤3
3247    fn extract_range_bounds(
3248        &self,
3249        start: &Value,
3250        end: &Value,
3251    ) -> Result<(i64, i64), InterpreterError> {
3252        match (start, end) {
3253            (Value::Integer(s), Value::Integer(e)) => Ok((*s, *e)),
3254            _ => Err(InterpreterError::TypeError(
3255                "Range bounds must be integers".to_string(),
3256            )),
3257        }
3258    }
3259
3260    /// Create range iterator based on inclusive flag
3261    /// Complexity: ≤2
3262    fn create_range_iterator(
3263        &self,
3264        start: i64,
3265        end: i64,
3266        inclusive: bool,
3267    ) -> Box<dyn Iterator<Item = i64>> {
3268        if inclusive {
3269            Box::new(start..=end)
3270        } else {
3271            Box::new(start..end)
3272        }
3273    }
3274
3275    /// Evaluate loop body with control flow handling
3276    /// Complexity: ≤5
3277    fn eval_loop_body_with_control_flow(
3278        &mut self,
3279        body: &Expr,
3280    ) -> Result<Value, LoopControlOrError> {
3281        match self.eval_expr(body) {
3282            Ok(value) => Ok(value),
3283            Err(InterpreterError::Break(label, val)) => Err(LoopControlOrError::Break(label, val)),
3284            Err(InterpreterError::Continue(label)) => Err(LoopControlOrError::Continue(label)),
3285            Err(InterpreterError::Return(val)) => Err(LoopControlOrError::Return(val)),
3286            Err(e) => Err(LoopControlOrError::Error(e)),
3287        }
3288    }
3289
3290    /// Evaluate a while loop
3291    fn eval_while_loop(
3292        &mut self,
3293        label: Option<&String>,
3294        condition: &Expr,
3295        body: &Expr,
3296    ) -> Result<Value, InterpreterError> {
3297        let mut last_value = Value::Nil;
3298        loop {
3299            let cond_value = self.eval_expr(condition)?;
3300            if !matches!(cond_value, Value::Bool(true)) && cond_value != Value::Integer(1) {
3301                break;
3302            }
3303
3304            match self.eval_loop_body_with_control_flow(body) {
3305                Ok(value) => last_value = value,
3306                Err(LoopControlOrError::Break(break_label, break_val)) => {
3307                    if break_label.is_none() || break_label.as_deref() == label.map(String::as_str)
3308                    {
3309                        return Ok(break_val);
3310                    }
3311                    return Err(InterpreterError::Break(break_label, break_val));
3312                }
3313                Err(LoopControlOrError::Continue(continue_label)) => {
3314                    if continue_label.is_none()
3315                        || continue_label.as_deref() == label.map(String::as_str)
3316                    {
3317                        continue;
3318                    }
3319                    return Err(InterpreterError::Continue(continue_label));
3320                }
3321                Err(LoopControlOrError::Return(return_val)) => {
3322                    return Err(InterpreterError::Return(return_val))
3323                }
3324                Err(LoopControlOrError::Error(e)) => return Err(e),
3325            }
3326        }
3327        Ok(last_value)
3328    }
3329
3330    /// Evaluate an infinite loop (loop { ... })
3331    fn eval_loop(
3332        &mut self,
3333        label: Option<&String>,
3334        body: &Expr,
3335    ) -> Result<Value, InterpreterError> {
3336        loop {
3337            match self.eval_loop_body_with_control_flow(body) {
3338                Ok(_) => {}
3339                Err(LoopControlOrError::Break(break_label, break_val)) => {
3340                    if break_label.is_none() || break_label.as_deref() == label.map(String::as_str)
3341                    {
3342                        return Ok(break_val);
3343                    }
3344                    return Err(InterpreterError::Break(break_label, break_val));
3345                }
3346                Err(LoopControlOrError::Continue(continue_label)) => {
3347                    if continue_label.is_none()
3348                        || continue_label.as_deref() == label.map(String::as_str)
3349                    {
3350                        continue;
3351                    }
3352                    return Err(InterpreterError::Continue(continue_label));
3353                }
3354                Err(LoopControlOrError::Return(return_val)) => {
3355                    return Err(InterpreterError::Return(return_val))
3356                }
3357                Err(LoopControlOrError::Error(e)) => return Err(e),
3358            }
3359        }
3360    }
3361
3362    /// Evaluate a match expression
3363    pub fn eval_match(&mut self, expr: &Expr, arms: &[MatchArm]) -> Result<Value, InterpreterError> {
3364        let value = self.eval_expr(expr)?;
3365
3366        for arm in arms {
3367            // First check if pattern matches
3368            if let Some(bindings) = self.try_pattern_match(&arm.pattern, &value)? {
3369                // Create new scope for pattern bindings
3370                self.push_scope();
3371
3372                // Bind pattern variables
3373                for (name, val) in bindings {
3374                    self.env_set(name, val);
3375                }
3376
3377                // Check guard condition if present
3378                let guard_passed = if let Some(guard) = &arm.guard {
3379                    match self.eval_expr(guard)? {
3380                        Value::Bool(true) => true,
3381                        Value::Bool(false) => false,
3382                        _ => {
3383                            self.pop_scope();
3384                            return Err(InterpreterError::RuntimeError(
3385                                "Guard condition must evaluate to a boolean".to_string(),
3386                            ));
3387                        }
3388                    }
3389                } else {
3390                    true // No guard means always pass
3391                };
3392
3393                if guard_passed {
3394                    // Evaluate body with bindings in scope
3395                    let result = self.eval_expr(&arm.body);
3396                    self.pop_scope();
3397                    return result;
3398                }
3399                // Guard failed, restore scope and try next arm
3400                self.pop_scope();
3401            }
3402        }
3403
3404        Err(InterpreterError::RuntimeError(
3405            "No match arm matched the value".to_string(),
3406        ))
3407    }
3408
3409    /// Evaluate a let pattern expression (array/tuple destructuring)
3410    /// Extract names of identifiers marked as mutable in a pattern
3411    /// Complexity: 4 (within Toyota Way limits)
3412    fn extract_mut_names(pattern: &Pattern) -> std::collections::HashSet<String> {
3413        let mut mut_names = std::collections::HashSet::new();
3414
3415        fn walk_pattern(
3416            p: &Pattern,
3417            mut_names: &mut std::collections::HashSet<String>,
3418            is_mut: bool,
3419        ) {
3420            match p {
3421                Pattern::Mut(inner) => walk_pattern(inner, mut_names, true),
3422                Pattern::Identifier(name) if is_mut => {
3423                    mut_names.insert(name.clone());
3424                }
3425                Pattern::Tuple(patterns) | Pattern::List(patterns) => {
3426                    for pat in patterns {
3427                        walk_pattern(pat, mut_names, is_mut);
3428                    }
3429                }
3430                Pattern::Struct { fields, .. } => {
3431                    for field in fields {
3432                        if let Some(ref pat) = field.pattern {
3433                            walk_pattern(pat, mut_names, is_mut);
3434                        }
3435                    }
3436                }
3437                Pattern::AtBinding { pattern, .. } => walk_pattern(pattern, mut_names, is_mut),
3438                _ => {}
3439            }
3440        }
3441
3442        walk_pattern(pattern, &mut mut_names, false);
3443        mut_names
3444    }
3445
3446    /// Evaluate let pattern with support for mut destructuring
3447    /// Complexity: 6 (within Toyota Way limits)
3448    fn eval_let_pattern(
3449        &mut self,
3450        pattern: &Pattern,
3451        value: &Expr,
3452        body: &Expr,
3453    ) -> Result<Value, InterpreterError> {
3454        // Evaluate the right-hand side value
3455        let rhs_value = self.eval_expr(value)?;
3456
3457        // Extract names marked as mutable in the pattern
3458        let mut_names = Self::extract_mut_names(pattern);
3459
3460        // Try to match the pattern against the value
3461        if let Some(bindings) = self.try_pattern_match(pattern, &rhs_value)? {
3462            // Bind pattern variables, using mutable binding for names wrapped in Pattern::Mut
3463            for (name, val) in bindings {
3464                if mut_names.contains(&name) {
3465                    self.env_set_mut(name.clone(), val);
3466                } else {
3467                    self.env_set(name, val);
3468                }
3469            }
3470
3471            // If body is unit (empty), return the value like REPL does
3472            // This makes `let [a, b] = [1, 2]` return [1, 2] instead of nil
3473            match &body.kind {
3474                ExprKind::Literal(Literal::Unit) => Ok(rhs_value),
3475                _ => self.eval_expr(body),
3476            }
3477        } else {
3478            Err(InterpreterError::RuntimeError(
3479                "Pattern did not match the value".to_string(),
3480            ))
3481        }
3482    }
3483
3484    /// Evaluate an assignment
3485    /// Evaluates assignment expressions including field assignments.
3486    ///
3487    /// This method handles variable assignments (`x = value`) and field assignments (`obj.field = value`).
3488    /// For field assignments, it creates a new object with the updated field value.
3489    ///
3490    /// # Examples
3491    ///
3492    /// ```
3493    /// use ruchy::frontend::parser::Parser;
3494    /// use ruchy::runtime::interpreter::{Interpreter, Value};
3495    ///
3496    /// let mut interpreter = Interpreter::new();
3497    /// let code = r#"
3498    ///     class Point {
3499    ///         x: i32,
3500    ///         y: i32
3501    ///
3502    ///         new(x: i32, y: i32) {
3503    ///             self.x = x
3504    ///             self.y = y
3505    ///         }
3506    ///     }
3507    ///
3508    ///     fn main() {
3509    ///         let p = Point::new(10, 20)
3510    ///         p.x
3511    ///     }
3512    /// "#;
3513    ///
3514    /// let mut parser = Parser::new(code);
3515    /// let expr = parser.parse().unwrap();
3516    /// interpreter.eval_expr(&expr).unwrap();
3517    /// let main_call = Parser::new("main()").parse().unwrap();
3518    /// let result = interpreter.eval_expr(&main_call).unwrap();
3519    /// assert!(matches!(result, Value::Integer(10)));
3520    /// ```
3521    fn eval_assign(&mut self, target: &Expr, value: &Expr) -> Result<Value, InterpreterError> {
3522        let val = self.eval_expr(value)?;
3523
3524        // Handle different assignment targets
3525        match &target.kind {
3526            ExprKind::Identifier(name) => {
3527                self.set_variable(name, val.clone());
3528                Ok(val)
3529            }
3530            ExprKind::FieldAccess { object, field } => {
3531                // Handle field assignment like: obj.field = value
3532                // We need to get the object, update it, and reassign it
3533                match &object.kind {
3534                    ExprKind::Identifier(obj_name) => {
3535                        // Get the object
3536                        let obj = self.lookup_variable(obj_name)?;
3537
3538                        // Update the field based on object type
3539                        match obj {
3540                            Value::Object(ref map) => {
3541                                // Immutable object: create new copy with updated field
3542                                let mut new_map = (**map).clone();
3543                                new_map.insert(field.clone(), val.clone());
3544                                let new_obj = Value::Object(Arc::new(new_map));
3545
3546                                // Update the variable with the modified object
3547                                self.set_variable(obj_name, new_obj);
3548                                Ok(val)
3549                            }
3550                            Value::ObjectMut(ref cell) => {
3551                                // Mutable object: update in place via RefCell
3552                                cell.lock().unwrap().insert(field.clone(), val.clone());
3553                                Ok(val)
3554                            }
3555                            Value::Class { ref fields, .. } => {
3556                                // Class: update field in place via RwLock
3557                                let mut fields_write = fields.write().unwrap();
3558                                fields_write.insert(field.clone(), val.clone());
3559                                Ok(val)
3560                            }
3561                            Value::Struct { ref name, ref fields } => {
3562                                // Struct: create new copy with updated field (value semantics)
3563                                let mut new_fields = (**fields).clone();
3564                                new_fields.insert(field.clone(), val.clone());
3565                                let new_struct = Value::Struct {
3566                                    name: name.clone(),
3567                                    fields: Arc::new(new_fields),
3568                                };
3569
3570                                // Update the variable with the modified struct
3571                                self.set_variable(obj_name, new_struct);
3572                                Ok(val)
3573                            }
3574                            _ => Err(InterpreterError::RuntimeError(format!(
3575                                "Cannot access field '{}' on non-object",
3576                                field
3577                            ))),
3578                        }
3579                    }
3580                    _ => Err(InterpreterError::RuntimeError(
3581                        "Complex assignment targets not yet supported".to_string(),
3582                    )),
3583                }
3584            }
3585            _ => Err(InterpreterError::RuntimeError(
3586                "Invalid assignment target".to_string(),
3587            )),
3588        }
3589    }
3590
3591    /// Evaluate a compound assignment
3592    fn eval_compound_assign(
3593        &mut self,
3594        target: &Expr,
3595        op: AstBinaryOp,
3596        value: &Expr,
3597    ) -> Result<Value, InterpreterError> {
3598        // Get current value
3599        let current = match &target.kind {
3600            ExprKind::Identifier(name) => self.lookup_variable(name)?,
3601            _ => {
3602                return Err(InterpreterError::RuntimeError(
3603                    "Invalid compound assignment target".to_string(),
3604                ))
3605            }
3606        };
3607
3608        // Compute new value
3609        let rhs = self.eval_expr(value)?;
3610        let new_val = self.apply_binary_op(&current, op, &rhs)?;
3611
3612        // Assign back
3613        if let ExprKind::Identifier(name) = &target.kind {
3614            self.set_variable(name, new_val.clone());
3615        }
3616
3617        Ok(new_val)
3618    }
3619
3620    /// Evaluate string methods
3621    fn eval_string_method(
3622        &mut self,
3623        s: &Arc<str>,
3624        method: &str,
3625        args: &[Value],
3626    ) -> Result<Value, InterpreterError> {
3627        super::eval_string_methods::eval_string_method(s, method, args)
3628    }
3629
3630    /// Evaluate array methods
3631    #[allow(clippy::rc_buffer)]
3632    fn eval_array_method(
3633        &mut self,
3634        arr: &Arc<[Value]>,
3635        method: &str,
3636        args: &[Value],
3637    ) -> Result<Value, InterpreterError> {
3638        // Delegate to extracted array module with function call capability
3639        crate::runtime::eval_array::eval_array_method(arr, method, args, |func, args| {
3640            self.eval_function_call_value(func, args)
3641        })
3642    }
3643
3644    /// Evaluate a method call
3645    pub fn eval_method_call(
3646        &mut self,
3647        receiver: &Expr,
3648        method: &str,
3649        args: &[Expr],
3650    ) -> Result<Value, InterpreterError> {
3651        // Special handling for stdlib namespace methods (e.g., Html.parse())
3652        if let ExprKind::Identifier(namespace) = &receiver.kind {
3653            // Check if this is a stdlib namespace call before trying to look it up as a variable
3654            let namespace_method = format!("{namespace}_{method}");
3655
3656            // Try to evaluate as builtin function first
3657            let arg_values: Result<Vec<_>, _> = args.iter().map(|arg| self.eval_expr(arg)).collect();
3658            let arg_values = arg_values?;
3659
3660            if let Ok(Some(result)) = crate::runtime::eval_builtin::eval_builtin_function(&namespace_method, &arg_values) {
3661                return Ok(result);
3662            }
3663        }
3664
3665        // Special handling for mutating array methods on simple identifiers
3666        // e.g., messages.push(item)
3667        if let ExprKind::Identifier(var_name) = &receiver.kind {
3668            if method == "push" && args.len() == 1 {
3669                // Get current array value
3670                if let Ok(Value::Array(arr)) = self.lookup_variable(var_name) {
3671                    // Evaluate the argument
3672                    let arg_value = self.eval_expr(&args[0])?;
3673
3674                    // Create new array with item added
3675                    let mut new_arr = arr.to_vec();
3676                    new_arr.push(arg_value);
3677
3678                    // Update the variable binding
3679                    self.env_set(var_name.clone(), Value::Array(Arc::from(new_arr)));
3680
3681                    return Ok(Value::Nil); // push returns nil
3682                }
3683            } else if method == "pop" && args.is_empty() {
3684                // Get current array value
3685                if let Ok(Value::Array(arr)) = self.lookup_variable(var_name) {
3686                    // Create new array with last item removed
3687                    let mut new_arr = arr.to_vec();
3688                    let popped_value = new_arr.pop().unwrap_or(Value::Nil);
3689
3690                    // Update the variable binding
3691                    self.env_set(var_name.clone(), Value::Array(Arc::from(new_arr)));
3692
3693                    return Ok(popped_value); // pop returns the removed item
3694                }
3695            }
3696        }
3697
3698        // Special handling for mutating array methods on ObjectMut fields
3699        // e.g., self.messages.push(item)
3700        if let ExprKind::FieldAccess { object, field } = &receiver.kind {
3701            if let Ok(object_value) = self.eval_expr(object) {
3702                if let Value::ObjectMut(cell_rc) = object_value {
3703                    // Check if this is a mutating array method
3704                    if method == "push" && args.len() == 1 {
3705                        // Evaluate the argument
3706                        let arg_value = self.eval_expr(&args[0])?;
3707
3708                        // Get mutable access to the object
3709                        let mut obj = cell_rc.lock().unwrap();
3710
3711                        // Get the field value
3712                        if let Some(field_value) = obj.get(field) {
3713                            // If it's an array, push to it
3714                            if let Value::Array(arr) = field_value {
3715                                let mut new_arr = arr.to_vec();
3716                                new_arr.push(arg_value);
3717                                obj.insert(field.clone(), Value::Array(Arc::from(new_arr)));
3718                                return Ok(Value::Nil); // push returns nil
3719                            }
3720                        }
3721                    }
3722                }
3723            }
3724        }
3725
3726        let receiver_value = self.eval_expr(receiver)?;
3727
3728        // Special handling for DataFrame methods with closures - don't pre-evaluate the closure argument
3729        if matches!(receiver_value, Value::DataFrame { .. }) {
3730            match method {
3731                "filter" => return self.eval_dataframe_filter_method(&receiver_value, args),
3732                "with_column" => {
3733                    return self.eval_dataframe_with_column_method(&receiver_value, args)
3734                }
3735                "transform" => return self.eval_dataframe_transform_method(&receiver_value, args),
3736                _ => {}
3737            }
3738        }
3739
3740        // Special handling for actor send/ask methods - convert undefined identifiers to messages
3741        if (method == "send" || method == "ask") && args.len() == 1 {
3742            // Check if receiver is an actor instance (immutable or mutable)
3743            let is_actor = match &receiver_value {
3744                Value::Object(ref obj) => obj.contains_key("__actor"),
3745                Value::ObjectMut(ref cell) => cell.lock().unwrap().contains_key("__actor"),
3746                _ => false,
3747            };
3748
3749            if is_actor {
3750                // Try to evaluate the argument as a message
3751                let arg_value = match &args[0].kind {
3752                    ExprKind::Identifier(name) => {
3753                        // Try to evaluate as variable first
3754                        if let Ok(val) = self.lookup_variable(name) {
3755                            val
3756                        } else {
3757                            // Treat as a zero-argument message constructor
3758                            let mut message = HashMap::new();
3759                            message.insert(
3760                                "__type".to_string(),
3761                                Value::from_string("Message".to_string()),
3762                            );
3763                            message.insert("type".to_string(), Value::from_string(name.clone()));
3764                            message.insert("data".to_string(), Value::Array(Arc::from(vec![])));
3765                            Value::Object(Arc::new(message))
3766                        }
3767                    }
3768                    _ => self.eval_expr(&args[0])?,
3769                };
3770                return self.dispatch_method_call(&receiver_value, method, &[arg_value], false);
3771            }
3772        }
3773
3774        let arg_values: Result<Vec<_>, _> = args.iter().map(|arg| self.eval_expr(arg)).collect();
3775        let arg_values = arg_values?;
3776
3777        self.dispatch_method_call(&receiver_value, method, &arg_values, args.is_empty())
3778    }
3779
3780    // Helper methods for method dispatch (complexity <10 each)
3781
3782    /// Evaluate a message expression - if it's an undefined identifier, treat as message name
3783    /// Complexity: ≤5
3784    fn eval_message_expr(&mut self, message: &Expr) -> Result<Value, InterpreterError> {
3785        match &message.kind {
3786            ExprKind::Identifier(name) => {
3787                // Try to evaluate as variable first
3788                if let Ok(val) = self.lookup_variable(name) {
3789                    Ok(val)
3790                } else {
3791                    // Treat as a zero-argument message constructor
3792                    let mut msg_obj = HashMap::new();
3793                    msg_obj.insert(
3794                        "__type".to_string(),
3795                        Value::from_string("Message".to_string()),
3796                    );
3797                    msg_obj.insert("type".to_string(), Value::from_string(name.clone()));
3798                    msg_obj.insert("data".to_string(), Value::Array(Arc::from(vec![])));
3799                    Ok(Value::Object(Arc::new(msg_obj)))
3800                }
3801            }
3802            _ => self.eval_expr(message),
3803        }
3804    }
3805
3806    fn dispatch_method_call(
3807        &mut self,
3808        receiver: &Value,
3809        method: &str,
3810        arg_values: &[Value],
3811        args_empty: bool,
3812    ) -> Result<Value, InterpreterError> {
3813        // EVALUATOR-001: Strip turbofish syntax from method names
3814        // Example: "parse::<i32>" becomes "parse"
3815        // Turbofish is for type hints only, not used in runtime method lookup
3816        let base_method = if let Some(pos) = method.find("::") {
3817            &method[..pos]
3818        } else {
3819            method
3820        };
3821
3822        match receiver {
3823            Value::String(s) => self.eval_string_method(s, base_method, arg_values),
3824            Value::Array(arr) => self.eval_array_method(arr, base_method, arg_values),
3825            Value::Float(f) => self.eval_float_method(*f, base_method, args_empty),
3826            Value::Integer(n) => self.eval_integer_method(*n, base_method, arg_values),
3827            Value::DataFrame { columns } => self.eval_dataframe_method(columns, base_method, arg_values),
3828            Value::Object(obj) => {
3829                // Check if this is a type definition with constructor
3830                if base_method == "new" {
3831                    if let Some(Value::String(ref type_str)) = obj.get("__type") {
3832                        if let Some(Value::String(ref name)) = obj.get("__name") {
3833                            match type_str.as_ref() {
3834                                "Actor" => {
3835                                    return self.instantiate_actor_with_args(name, arg_values);
3836                                }
3837                                "Struct" => {
3838                                    return self.instantiate_struct_with_args(name, arg_values);
3839                                }
3840                                "Class" => {
3841                                    return self.instantiate_class_with_constructor(
3842                                        name, "new", arg_values,
3843                                    );
3844                                }
3845                                _ => {}
3846                            }
3847                        }
3848                    }
3849                }
3850
3851                // Check if this is an actor instance
3852                if let Some(Value::String(actor_name)) = obj.get("__actor") {
3853                    self.eval_actor_instance_method(obj, actor_name.as_ref(), base_method, arg_values)
3854                }
3855                // Check if this is a class instance
3856                else if let Some(Value::String(class_name)) = obj.get("__class") {
3857                    self.eval_class_instance_method(obj, class_name.as_ref(), base_method, arg_values)
3858                }
3859                // Check if this is a struct instance with impl methods
3860                else if let Some(Value::String(struct_name)) =
3861                    obj.get("__struct_type").or_else(|| obj.get("__struct"))
3862                {
3863                    self.eval_struct_instance_method(obj, struct_name.as_ref(), base_method, arg_values)
3864                }
3865                // Check if this is a `DataFrame` builder
3866                else if let Some(Value::String(type_str)) = obj.get("__type") {
3867                    if type_str.as_ref() == "DataFrameBuilder" {
3868                        self.eval_dataframe_builder_method(obj, base_method, arg_values)
3869                    } else {
3870                        self.eval_object_method(obj, base_method, arg_values, args_empty)
3871                    }
3872                } else {
3873                    self.eval_object_method(obj, base_method, arg_values, args_empty)
3874                }
3875            }
3876            Value::ObjectMut(cell_rc) => {
3877                // Dispatch mutable objects the same way as immutable ones
3878                // Safe borrow: We only read metadata fields to determine dispatch
3879                let obj = cell_rc.lock().unwrap();
3880
3881                // Check if this is an actor instance
3882                if let Some(Value::String(actor_name)) = obj.get("__actor") {
3883                    let actor_name = actor_name.clone();
3884                    drop(obj); // Release borrow before recursive call
3885                    self.eval_actor_instance_method_mut(
3886                        cell_rc,
3887                        actor_name.as_ref(),
3888                        base_method,
3889                        arg_values,
3890                    )
3891                }
3892                // Check if this is a class instance
3893                else if let Some(Value::String(class_name)) = obj.get("__class") {
3894                    let class_name = class_name.clone();
3895                    drop(obj); // Release borrow before recursive call
3896                    self.eval_class_instance_method_mut(
3897                        cell_rc,
3898                        class_name.as_ref(),
3899                        base_method,
3900                        arg_values,
3901                    )
3902                }
3903                // Check if this is a struct instance with impl methods
3904                else if let Some(Value::String(struct_name)) =
3905                    obj.get("__struct_type").or_else(|| obj.get("__struct"))
3906                {
3907                    let struct_name = struct_name.clone();
3908                    drop(obj); // Release borrow before recursive call
3909                    self.eval_struct_instance_method_mut(
3910                        cell_rc,
3911                        struct_name.as_ref(),
3912                        base_method,
3913                        arg_values,
3914                    )
3915                } else {
3916                    drop(obj); // Release borrow before recursive call
3917                    self.eval_object_method_mut(cell_rc, base_method, arg_values, args_empty)
3918                }
3919            }
3920            Value::Struct { name, fields } => {
3921                // Dispatch struct instance method call
3922                self.eval_struct_instance_method(fields, name, base_method, arg_values)
3923            }
3924            Value::Class {
3925                class_name,
3926                fields,
3927                methods,
3928            } => {
3929                // Dispatch instance method call on Class
3930                self.eval_class_instance_method_on_class(class_name, fields, methods, base_method, arg_values)
3931            }
3932            #[cfg(not(target_arch = "wasm32"))]
3933            Value::HtmlDocument(doc) => self.eval_html_document_method(doc, base_method, arg_values),
3934            #[cfg(not(target_arch = "wasm32"))]
3935            Value::HtmlElement(elem) => self.eval_html_element_method(elem, base_method, arg_values),
3936            _ => self.eval_generic_method(receiver, base_method, args_empty),
3937        }
3938    }
3939
3940    fn eval_float_method(
3941        &self,
3942        f: f64,
3943        method: &str,
3944        args_empty: bool,
3945    ) -> Result<Value, InterpreterError> {
3946        eval_method::eval_float_method(f, method, args_empty)
3947    }
3948
3949    fn eval_integer_method(
3950        &self,
3951        n: i64,
3952        method: &str,
3953        arg_values: &[Value],
3954    ) -> Result<Value, InterpreterError> {
3955        eval_method::eval_integer_method(n, method, arg_values)
3956    }
3957
3958    fn eval_generic_method(
3959        &self,
3960        receiver: &Value,
3961        method: &str,
3962        args_empty: bool,
3963    ) -> Result<Value, InterpreterError> {
3964        eval_method::eval_generic_method(receiver, method, args_empty)
3965    }
3966
3967    /// Evaluate `HtmlDocument` methods (HTTP-002-C)
3968    /// Complexity: 4 (within Toyota Way limits)
3969    #[cfg(not(target_arch = "wasm32"))]
3970    fn eval_html_document_method(
3971        &self,
3972        doc: &crate::stdlib::html::HtmlDocument,
3973        method: &str,
3974        arg_values: &[Value],
3975    ) -> Result<Value, InterpreterError> {
3976        match method {
3977            "select" => {
3978                if arg_values.len() != 1 {
3979                    return Err(InterpreterError::RuntimeError(
3980                        "select() expects 1 argument (selector)".to_string(),
3981                    ));
3982                }
3983                match &arg_values[0] {
3984                    Value::String(selector) => {
3985                        let elements = doc
3986                            .select(selector.as_ref())
3987                            .map_err(|e| InterpreterError::RuntimeError(format!("select() failed: {e}")))?;
3988                        let values: Vec<Value> = elements
3989                            .into_iter()
3990                            .map(Value::HtmlElement)
3991                            .collect();
3992                        Ok(Value::Array(values.into()))
3993                    }
3994                    _ => Err(InterpreterError::RuntimeError(
3995                        "select() expects a string selector".to_string(),
3996                    )),
3997                }
3998            }
3999            "query_selector" => {
4000                if arg_values.len() != 1 {
4001                    return Err(InterpreterError::RuntimeError(
4002                        "query_selector() expects 1 argument (selector)".to_string(),
4003                    ));
4004                }
4005                match &arg_values[0] {
4006                    Value::String(selector) => {
4007                        let element = doc
4008                            .query_selector(selector.as_ref())
4009                            .map_err(|e| InterpreterError::RuntimeError(format!("query_selector() failed: {e}")))?;
4010                        Ok(element.map_or(Value::Nil, Value::HtmlElement))
4011                    }
4012                    _ => Err(InterpreterError::RuntimeError(
4013                        "query_selector() expects a string selector".to_string(),
4014                    )),
4015                }
4016            }
4017            "query_selector_all" => {
4018                if arg_values.len() != 1 {
4019                    return Err(InterpreterError::RuntimeError(
4020                        "query_selector_all() expects 1 argument (selector)".to_string(),
4021                    ));
4022                }
4023                match &arg_values[0] {
4024                    Value::String(selector) => {
4025                        let elements = doc
4026                            .query_selector_all(selector.as_ref())
4027                            .map_err(|e| InterpreterError::RuntimeError(format!("query_selector_all() failed: {e}")))?;
4028                        let values: Vec<Value> = elements
4029                            .into_iter()
4030                            .map(Value::HtmlElement)
4031                            .collect();
4032                        Ok(Value::Array(values.into()))
4033                    }
4034                    _ => Err(InterpreterError::RuntimeError(
4035                        "query_selector_all() expects a string selector".to_string(),
4036                    )),
4037                }
4038            }
4039            _ => Err(InterpreterError::RuntimeError(format!(
4040                "Unknown method '{}' on HtmlDocument",
4041                method
4042            ))),
4043        }
4044    }
4045
4046    /// Evaluate `HtmlElement` methods (HTTP-002-C)
4047    /// Complexity: 4 (within Toyota Way limits)
4048    #[cfg(not(target_arch = "wasm32"))]
4049    fn eval_html_element_method(
4050        &self,
4051        elem: &crate::stdlib::html::HtmlElement,
4052        method: &str,
4053        arg_values: &[Value],
4054    ) -> Result<Value, InterpreterError> {
4055        match method {
4056            "text" => {
4057                if !arg_values.is_empty() {
4058                    return Err(InterpreterError::RuntimeError(
4059                        "text() expects no arguments".to_string(),
4060                    ));
4061                }
4062                Ok(Value::from_string(elem.text()))
4063            }
4064            "attr" => {
4065                if arg_values.len() != 1 {
4066                    return Err(InterpreterError::RuntimeError(
4067                        "attr() expects 1 argument (attribute name)".to_string(),
4068                    ));
4069                }
4070                match &arg_values[0] {
4071                    Value::String(attr_name) => {
4072                        let value = elem.attr(attr_name.as_ref());
4073                        Ok(value.map_or(Value::Nil, Value::from_string))
4074                    }
4075                    _ => Err(InterpreterError::RuntimeError(
4076                        "attr() expects a string attribute name".to_string(),
4077                    )),
4078                }
4079            }
4080            "html" => {
4081                if !arg_values.is_empty() {
4082                    return Err(InterpreterError::RuntimeError(
4083                        "html() expects no arguments".to_string(),
4084                    ));
4085                }
4086                Ok(Value::from_string(elem.html()))
4087            }
4088            _ => Err(InterpreterError::RuntimeError(format!(
4089                "Unknown method '{}' on HtmlElement",
4090                method
4091            ))),
4092        }
4093    }
4094
4095    // ObjectMut adapter methods - delegate to immutable versions via borrow
4096    // Complexity: 2 each (simple delegation)
4097
4098    fn eval_actor_instance_method_mut(
4099        &mut self,
4100        cell_rc: &Arc<std::sync::Mutex<std::collections::HashMap<String, Value>>>,
4101        actor_name: &str,
4102        method: &str,
4103        arg_values: &[Value],
4104    ) -> Result<Value, InterpreterError> {
4105        // Special handling for send method - needs mutable state access
4106        if method == "send" {
4107            if arg_values.is_empty() {
4108                return Err(InterpreterError::RuntimeError(
4109                    "send() requires a message argument".to_string(),
4110                ));
4111            }
4112            return self.process_actor_message_sync_mut(cell_rc, &arg_values[0]);
4113        }
4114
4115        // For other methods, delegate to non-mut version
4116        let instance = cell_rc.lock().unwrap();
4117        self.eval_actor_instance_method(&instance, actor_name, method, arg_values)
4118    }
4119
4120    fn eval_class_instance_method_mut(
4121        &mut self,
4122        cell_rc: &Arc<std::sync::Mutex<std::collections::HashMap<String, Value>>>,
4123        class_name: &str,
4124        method: &str,
4125        arg_values: &[Value],
4126    ) -> Result<Value, InterpreterError> {
4127        // For mutable instances, we need to pass ObjectMut as self (not a copy)
4128        // This allows &mut self methods to mutate the instance in place
4129
4130        // Look up the class definition
4131        let class_def = self.lookup_variable(class_name)?;
4132
4133        if let Value::Object(ref class_info) = class_def {
4134            // Look for the method in the class definition
4135            if let Some(Value::Object(ref methods)) = class_info.get("__methods") {
4136                if let Some(Value::Object(ref method_meta)) = methods.get(method) {
4137                    // Get the method closure
4138                    if let Some(Value::Closure { params, body, .. }) = method_meta.get("closure") {
4139                        // Check if it's a static method
4140                        let is_static = method_meta
4141                            .get("is_static")
4142                            .and_then(|v| {
4143                                if let Value::Bool(b) = v {
4144                                    Some(*b)
4145                                } else {
4146                                    None
4147                                }
4148                            })
4149                            .unwrap_or(false);
4150
4151                        if is_static {
4152                            return Err(InterpreterError::RuntimeError(format!(
4153                                "Cannot call static method {} on instance",
4154                                method
4155                            )));
4156                        }
4157
4158                        // Create environment for method execution
4159                        let mut method_env = HashMap::new();
4160
4161                        // CRITICAL: Pass ObjectMut as self, using the SAME Arc<RefCell<>>
4162                        // This enables &mut self methods to mutate the shared instance
4163                        method_env
4164                            .insert("self".to_string(), Value::ObjectMut(Arc::clone(cell_rc)));
4165
4166                        // Bind method parameters to arguments
4167                        if arg_values.len() != params.len() {
4168                            return Err(InterpreterError::RuntimeError(format!(
4169                                "Method {} expects {} arguments, got {}",
4170                                method,
4171                                params.len(),
4172                                arg_values.len()
4173                            )));
4174                        }
4175
4176                        for (param, arg) in params.iter().zip(arg_values) {
4177                            method_env.insert(param.clone(), arg.clone());
4178                        }
4179
4180                        // Push method environment
4181                        self.env_push(method_env);
4182
4183                        // Execute method body
4184                        let result = self.eval_expr(body)?;
4185
4186                        // Pop environment
4187                        self.env_pop();
4188
4189                        return Ok(result);
4190                    }
4191                }
4192            }
4193
4194            // Method not found
4195            Err(InterpreterError::RuntimeError(format!(
4196                "Class {} has no method named {}",
4197                class_name, method
4198            )))
4199        } else {
4200            Err(InterpreterError::RuntimeError(format!(
4201                "{} is not a class",
4202                class_name
4203            )))
4204        }
4205    }
4206
4207    /// Evaluate instance method on `Value::Class` variant
4208    /// This is for the new Class implementation with Arc<`RwLock`<HashMap>>
4209    fn eval_class_instance_method_on_class(
4210        &mut self,
4211        class_name: &str,
4212        fields: &Arc<std::sync::RwLock<HashMap<String, Value>>>,
4213        methods: &Arc<HashMap<String, Value>>,
4214        method: &str,
4215        arg_values: &[Value],
4216    ) -> Result<Value, InterpreterError> {
4217        // Look up the method in the methods map
4218        if let Some(method_closure) = methods.get(method) {
4219            if let Value::Closure { params, body, .. } = method_closure {
4220                // Check argument count
4221                if arg_values.len() != params.len() {
4222                    return Err(InterpreterError::RuntimeError(format!(
4223                        "Method {} expects {} arguments, got {}",
4224                        method,
4225                        params.len(),
4226                        arg_values.len()
4227                    )));
4228                }
4229
4230                // Create environment for method execution
4231                let mut method_env = HashMap::new();
4232
4233                // Bind 'self' to the class instance
4234                method_env.insert(
4235                    "self".to_string(),
4236                    Value::Class {
4237                        class_name: class_name.to_string(),
4238                        fields: Arc::clone(fields),
4239                        methods: Arc::clone(methods),
4240                    },
4241                );
4242
4243                // Bind method parameters to arguments
4244                for (param, arg) in params.iter().zip(arg_values) {
4245                    method_env.insert(param.clone(), arg.clone());
4246                }
4247
4248                // Push method environment
4249                self.env_push(method_env);
4250
4251                // Execute method body
4252                let result = self.eval_expr(body)?;
4253
4254                // Pop environment
4255                self.env_pop();
4256
4257                Ok(result)
4258            } else {
4259                Err(InterpreterError::RuntimeError(format!(
4260                    "Method {} is not a closure",
4261                    method
4262                )))
4263            }
4264        } else {
4265            Err(InterpreterError::RuntimeError(format!(
4266                "Method '{}' not found for type class",
4267                method
4268            )))
4269        }
4270    }
4271
4272    fn eval_struct_instance_method_mut(
4273        &mut self,
4274        cell_rc: &Arc<std::sync::Mutex<std::collections::HashMap<String, Value>>>,
4275        struct_name: &str,
4276        method: &str,
4277        arg_values: &[Value],
4278    ) -> Result<Value, InterpreterError> {
4279        let instance = cell_rc.lock().unwrap();
4280        self.eval_struct_instance_method(&instance, struct_name, method, arg_values)
4281    }
4282
4283    fn eval_object_method_mut(
4284        &mut self,
4285        cell_rc: &Arc<std::sync::Mutex<std::collections::HashMap<String, Value>>>,
4286        method: &str,
4287        arg_values: &[Value],
4288        args_empty: bool,
4289    ) -> Result<Value, InterpreterError> {
4290        let instance = cell_rc.lock().unwrap();
4291        self.eval_object_method(&instance, method, arg_values, args_empty)
4292    }
4293
4294    /// Evaluates actor instance methods like `send()` and `ask()`.
4295    ///
4296    /// This method handles message passing to actors using the `!` (send) and `<?` (ask) operators.
4297    ///
4298    /// # Examples
4299    ///
4300    /// ```
4301    /// use ruchy::frontend::parser::Parser;
4302    /// use ruchy::runtime::interpreter::Interpreter;
4303    ///
4304    /// let mut interpreter = Interpreter::new();
4305    /// let code = r#"
4306    ///     actor Counter {
4307    ///         count: i32 = 0
4308    ///
4309    ///         receive {
4310    ///             Increment => 42
4311    ///         }
4312    ///     }
4313    ///
4314    ///     fn main() {
4315    ///         let counter = spawn Counter
4316    ///         counter ! Increment
4317    ///         counter
4318    ///     }
4319    /// "#;
4320    ///
4321    /// let mut parser = Parser::new(code);
4322    /// let expr = parser.parse().unwrap();
4323    /// interpreter.eval_expr(&expr).unwrap();
4324    /// let main_call = Parser::new("main()").parse().unwrap();
4325    /// let result = interpreter.eval_expr(&main_call).unwrap();
4326    /// // Actor instance returned
4327    /// ```
4328    fn eval_actor_instance_method(
4329        &mut self,
4330        instance: &std::collections::HashMap<String, Value>,
4331        _actor_name: &str,
4332        method: &str,
4333        arg_values: &[Value],
4334    ) -> Result<Value, InterpreterError> {
4335        match method {
4336            "send" => {
4337                // Send a message to the actor (fire-and-forget)
4338                if arg_values.is_empty() {
4339                    return Err(InterpreterError::RuntimeError(
4340                        "send() requires a message argument".to_string(),
4341                    ));
4342                }
4343
4344                // Check if this is an async actor with runtime ID
4345                if let Some(Value::String(actor_id)) = instance.get("__actor_id") {
4346                    use crate::runtime::actor_runtime::{ActorMessage, ACTOR_RUNTIME};
4347
4348                    // Extract message type and data
4349                    let message = &arg_values[0];
4350                    let (msg_type, msg_data) = if let Value::Object(msg_obj) = message {
4351                        if let Some(Value::String(type_str)) = msg_obj.get("__type") {
4352                            if type_str.as_ref() == "Message" {
4353                                let msg_type = msg_obj
4354                                    .get("type")
4355                                    .and_then(|v| {
4356                                        if let Value::String(s) = v {
4357                                            Some(s.to_string())
4358                                        } else {
4359                                            None
4360                                        }
4361                                    })
4362                                    .unwrap_or_else(|| "Unknown".to_string());
4363                                let msg_data = msg_obj
4364                                    .get("data")
4365                                    .and_then(|v| {
4366                                        if let Value::Array(arr) = v {
4367                                            Some(arr.to_vec())
4368                                        } else {
4369                                            None
4370                                        }
4371                                    })
4372                                    .unwrap_or_else(Vec::new);
4373                                (msg_type, msg_data)
4374                            } else {
4375                                ("Unknown".to_string(), vec![])
4376                            }
4377                        } else {
4378                            ("Unknown".to_string(), vec![])
4379                        }
4380                    } else {
4381                        // Simple message value
4382                        ("Message".to_string(), vec![message.clone()])
4383                    };
4384
4385                    // Convert data to strings for thread safety
4386                    let str_data: Vec<String> =
4387                        msg_data.iter().map(|v| format!("{:?}", v)).collect();
4388
4389                    // Send the message to the actor
4390                    let actor_msg = ActorMessage {
4391                        message_type: msg_type,
4392                        data: str_data,
4393                    };
4394
4395                    ACTOR_RUNTIME.send_message(actor_id.as_ref(), actor_msg)?;
4396                    return Ok(Value::Nil);
4397                }
4398
4399                // Synchronous actor - process message immediately
4400                self.process_actor_message_sync(instance, &arg_values[0])
4401            }
4402            "stop" => {
4403                // Stop the actor
4404                // In a real actor system, this would terminate the actor's mailbox processing
4405                Ok(Value::Bool(true))
4406            }
4407            "ask" => {
4408                // Send a message and wait for response
4409                // For now, we'll process the message synchronously
4410                if arg_values.is_empty() {
4411                    return Err(InterpreterError::RuntimeError(
4412                        "ask() requires a message argument".to_string(),
4413                    ));
4414                }
4415
4416                // Get the message
4417                let message = &arg_values[0];
4418
4419                // Try to extract message type and data
4420                if let Value::Object(msg_obj) = message {
4421                    // Check if this is a Message object we created
4422                    if let Some(Value::String(type_str)) = msg_obj.get("__type") {
4423                        if type_str.as_ref() == "Message" {
4424                            // Extract message type and data
4425                            if let Some(Value::String(msg_type)) = msg_obj.get("type") {
4426                                if let Some(Value::Array(data)) = msg_obj.get("data") {
4427                                    // Look up the handler for this message type
4428                                    if let Some(handlers) = instance.get("__handlers") {
4429                                        if let Value::Array(handler_list) = handlers {
4430                                            // Find matching handler
4431                                            for handler in handler_list.iter() {
4432                                                if let Value::Object(h) = handler {
4433                                                    if let Some(Value::String(h_type)) =
4434                                                        h.get("message_type")
4435                                                    {
4436                                                        if h_type.as_ref() == msg_type.as_ref() {
4437                                                            // Found matching handler - execute it
4438                                                            if let Some(Value::Closure {
4439                                                                params,
4440                                                                body,
4441                                                                env,
4442                                                            }) = h.get("handler")
4443                                                            {
4444                                                                // Push a new environment for handler execution
4445                                                                let mut handler_env =
4446                                                                    (**env).clone();
4447
4448                                                                // Bind message parameters
4449                                                                for (i, param_name) in
4450                                                                    params.iter().enumerate()
4451                                                                {
4452                                                                    if let Some(value) = data.get(i)
4453                                                                    {
4454                                                                        handler_env.insert(
4455                                                                            param_name.clone(),
4456                                                                            value.clone(),
4457                                                                        );
4458                                                                    }
4459                                                                }
4460
4461                                                                // Also bind 'self' to the actor instance
4462                                                                handler_env.insert(
4463                                                                    "self".to_string(),
4464                                                                    Value::Object(Arc::new(
4465                                                                        instance.clone(),
4466                                                                    )),
4467                                                                );
4468
4469                                                                // Execute handler body
4470                                                                self.env_push(handler_env);
4471                                                                let result =
4472                                                                    self.eval_expr(body)?;
4473                                                                self.env_pop();
4474
4475                                                                return Ok(result);
4476                                                            }
4477                                                        }
4478                                                    }
4479                                                }
4480                                            }
4481                                        }
4482                                    }
4483
4484                                    // No handler found - return a default response
4485                                    return Ok(Value::from_string(format!(
4486                                        "Received: {}",
4487                                        msg_type.as_ref()
4488                                    )));
4489                                }
4490                            }
4491                        }
4492                    }
4493                }
4494
4495                // Default: return the message itself (echo)
4496                Ok(message.clone())
4497            }
4498            _ => Err(InterpreterError::RuntimeError(format!(
4499                "Unknown actor method: {}",
4500                method
4501            ))),
4502        }
4503    }
4504
4505    /// Process a message for a synchronous (interpreted) actor.
4506    ///
4507    /// This method executes the appropriate message handler based on the message type.
4508    /// Complexity: 9
4509    ///
4510    /// # Examples
4511    ///
4512    /// ```
4513    /// use ruchy::frontend::parser::Parser;
4514    /// use ruchy::runtime::interpreter::Interpreter;
4515    ///
4516    /// let mut interpreter = Interpreter::new();
4517    /// let code = r#"
4518    ///     actor Greeter {
4519    ///         greeting: String = "Hello"
4520    ///
4521    ///         receive {
4522    ///             Greet(name: String) => {
4523    ///                 "Hello, World!"
4524    ///             }
4525    ///         }
4526    ///     }
4527    ///
4528    ///     fn main() {
4529    ///         let greeter = spawn Greeter
4530    ///         greeter ! Greet("Alice")
4531    ///         greeter
4532    ///     }
4533    /// "#;
4534    ///
4535    /// let mut parser = Parser::new(code);
4536    /// let expr = parser.parse().unwrap();
4537    /// interpreter.eval_expr(&expr).unwrap();
4538    /// let main_call = Parser::new("main()").parse().unwrap();
4539    /// let result = interpreter.eval_expr(&main_call);
4540    /// assert!(result.is_ok());
4541    /// ```
4542    fn process_actor_message_sync(
4543        &mut self,
4544        instance: &std::collections::HashMap<String, Value>,
4545        message: &Value,
4546    ) -> Result<Value, InterpreterError> {
4547        // Parse the message to extract type and arguments
4548        // Messages come as function calls like Push(1) or SetCount(5)
4549        let (msg_type, msg_args) = if let Value::Object(msg_obj) = message {
4550            // Check if it's a Message object
4551            if let Some(Value::String(type_str)) = msg_obj.get("__type") {
4552                if type_str.as_ref() == "Message" {
4553                    let msg_type = msg_obj
4554                        .get("type")
4555                        .and_then(|v| {
4556                            if let Value::String(s) = v {
4557                                Some(s.to_string())
4558                            } else {
4559                                None
4560                            }
4561                        })
4562                        .unwrap_or_else(|| "Unknown".to_string());
4563                    let msg_args = msg_obj
4564                        .get("data")
4565                        .and_then(|v| {
4566                            if let Value::Array(arr) = v {
4567                                Some(arr.to_vec())
4568                            } else {
4569                                None
4570                            }
4571                        })
4572                        .unwrap_or_else(Vec::new);
4573                    (msg_type, msg_args)
4574                } else {
4575                    return Err(InterpreterError::RuntimeError(
4576                        "Invalid message format".to_string(),
4577                    ));
4578                }
4579            } else {
4580                return Err(InterpreterError::RuntimeError(
4581                    "Invalid message format".to_string(),
4582                ));
4583            }
4584        } else {
4585            return Err(InterpreterError::RuntimeError(
4586                "Message must be an object".to_string(),
4587            ));
4588        };
4589
4590        // Find the matching handler
4591        if let Some(Value::Array(handlers)) = instance.get("__handlers") {
4592            for handler in handlers.iter() {
4593                if let Value::Object(handler_obj) = handler {
4594                    if let Some(Value::String(handler_type)) = handler_obj.get("message_type") {
4595                        if handler_type.as_ref() == msg_type {
4596                            // Found matching handler - execute it
4597                            if let Some(Value::Closure { params, body, env }) =
4598                                handler_obj.get("body")
4599                            {
4600                                // Create a new environment for handler execution
4601                                let mut handler_env = (**env).clone();
4602
4603                                // Bind message parameters
4604                                for (i, param_name) in params.iter().enumerate() {
4605                                    if let Some(value) = msg_args.get(i) {
4606                                        handler_env.insert(param_name.clone(), value.clone());
4607                                    }
4608                                }
4609
4610                                // Bind 'self' to the actor instance
4611                                // Create a mutable object for self that includes all fields
4612                                let mut self_obj = HashMap::new();
4613                                for (key, value) in instance {
4614                                    if !key.starts_with("__") {
4615                                        self_obj.insert(key.clone(), value.clone());
4616                                    }
4617                                }
4618                                handler_env
4619                                    .insert("self".to_string(), Value::Object(Arc::new(self_obj)));
4620
4621                                // Execute the handler body
4622                                self.env_stack.push(handler_env);
4623                                let result = self.eval_expr(body);
4624                                self.env_stack.pop();
4625
4626                                return result;
4627                            }
4628                        }
4629                    }
4630                }
4631            }
4632        }
4633
4634        Err(InterpreterError::RuntimeError(format!(
4635            "No handler found for message type: {}",
4636            msg_type
4637        )))
4638    }
4639
4640    /// Process a message for a synchronous (interpreted) actor with mutable state.
4641    ///
4642    /// This version accepts `Arc<Mutex<HashMap>>` and passes `ObjectMut` as self to enable mutations.
4643    /// Complexity: 9
4644    fn process_actor_message_sync_mut(
4645        &mut self,
4646        cell_rc: &Arc<std::sync::Mutex<std::collections::HashMap<String, Value>>>,
4647        message: &Value,
4648    ) -> Result<Value, InterpreterError> {
4649        let instance = cell_rc.lock().unwrap();
4650
4651        // Parse the message to extract type and arguments
4652        let (msg_type, msg_args) = if let Value::Object(msg_obj) = message {
4653            if let Some(Value::String(type_str)) = msg_obj.get("__type") {
4654                if type_str.as_ref() == "Message" {
4655                    let msg_type = msg_obj
4656                        .get("type")
4657                        .and_then(|v| {
4658                            if let Value::String(s) = v {
4659                                Some(s.to_string())
4660                            } else {
4661                                None
4662                            }
4663                        })
4664                        .unwrap_or_else(|| "Unknown".to_string());
4665                    let msg_args = msg_obj
4666                        .get("data")
4667                        .and_then(|v| {
4668                            if let Value::Array(arr) = v {
4669                                Some(arr.to_vec())
4670                            } else {
4671                                None
4672                            }
4673                        })
4674                        .unwrap_or_else(Vec::new);
4675                    (msg_type, msg_args)
4676                } else {
4677                    return Err(InterpreterError::RuntimeError(
4678                        "Invalid message format".to_string(),
4679                    ));
4680                }
4681            } else {
4682                return Err(InterpreterError::RuntimeError(
4683                    "Invalid message format".to_string(),
4684                ));
4685            }
4686        } else {
4687            return Err(InterpreterError::RuntimeError(
4688                "Message must be an object".to_string(),
4689            ));
4690        };
4691
4692        // Find the matching handler
4693        if let Some(Value::Array(handlers)) = instance.get("__handlers") {
4694            for handler in handlers.iter() {
4695                if let Value::Object(handler_obj) = handler {
4696                    if let Some(Value::String(handler_type)) = handler_obj.get("message_type") {
4697                        if handler_type.as_ref() == msg_type {
4698                            // Found matching handler - execute it
4699                            if let Some(Value::Closure { params, body, env }) =
4700                                handler_obj.get("body")
4701                            {
4702                                // Clone data before dropping instance borrow
4703                                let params_clone = params.clone();
4704                                let body_clone = body.clone();
4705                                let env_clone = env.clone();
4706
4707                                // Get parameter types for validation
4708                                let param_types = handler_obj.get("param_types").and_then(|v| {
4709                                    if let Value::Array(types) = v {
4710                                        Some(types.clone())
4711                                    } else {
4712                                        None
4713                                    }
4714                                });
4715
4716                                drop(instance); // Release borrow before executing handler
4717
4718                                // Validate parameter types before execution
4719                                if let Some(types) = param_types {
4720                                    for (i, expected_type_val) in types.iter().enumerate() {
4721                                        if let Value::String(expected_type) = expected_type_val {
4722                                            if let Some(actual_value) = msg_args.get(i) {
4723                                                let actual_type = actual_value.type_name();
4724                                                // Map Ruchy type names to runtime type names
4725                                                let expected_runtime_type =
4726                                                    match expected_type.as_ref() {
4727                                                        "i32" | "i64" | "int" => "integer",
4728                                                        "f32" | "f64" | "float" => "float",
4729                                                        "String" | "string" | "str" => "string",
4730                                                        "bool" => "boolean",
4731                                                        _ => expected_type.as_ref(),
4732                                                    };
4733
4734                                                if actual_type != expected_runtime_type
4735                                                    && expected_runtime_type != "Any"
4736                                                {
4737                                                    return Err(InterpreterError::RuntimeError(format!(
4738                                                        "Type error in message {}: parameter {} expects type '{}', got '{}'",
4739                                                        msg_type, i, expected_runtime_type, actual_type
4740                                                    )));
4741                                                }
4742                                            }
4743                                        }
4744                                    }
4745                                }
4746
4747                                // Create a new environment for handler execution
4748                                let mut handler_env = (*env_clone).clone();
4749
4750                                // Bind message parameters
4751                                for (i, param_name) in params_clone.iter().enumerate() {
4752                                    if let Some(value) = msg_args.get(i) {
4753                                        handler_env.insert(param_name.clone(), value.clone());
4754                                    }
4755                                }
4756
4757                                // CRITICAL: Bind 'self' to ObjectMut (not immutable Object)
4758                                // This allows mutations in the handler to persist
4759                                handler_env.insert(
4760                                    "self".to_string(),
4761                                    Value::ObjectMut(Arc::clone(cell_rc)),
4762                                );
4763
4764                                // Execute the handler body
4765                                self.env_stack.push(handler_env);
4766                                let result = self.eval_expr(&body_clone);
4767                                self.env_stack.pop();
4768
4769                                return result;
4770                            }
4771                        }
4772                    }
4773                }
4774            }
4775        }
4776
4777        Err(InterpreterError::RuntimeError(format!(
4778            "No handler found for message type: {}",
4779            msg_type
4780        )))
4781    }
4782
4783    fn eval_struct_instance_method(
4784        &mut self,
4785        instance: &std::collections::HashMap<String, Value>,
4786        struct_name: &str,
4787        method: &str,
4788        arg_values: &[Value],
4789    ) -> Result<Value, InterpreterError> {
4790        // Look up impl method with qualified name
4791        let qualified_method_name = format!("{}::{}", struct_name, method);
4792
4793        if let Ok(method_closure) = self.lookup_variable(&qualified_method_name) {
4794            if let Value::Closure { params, body, env } = method_closure {
4795                // Check argument count (including self)
4796                let expected_args = params.len();
4797                let provided_args = arg_values.len() + 1; // +1 for self
4798
4799                if provided_args != expected_args {
4800                    return Err(InterpreterError::RuntimeError(format!(
4801                        "Method {} expects {} arguments, got {}",
4802                        method,
4803                        expected_args - 1, // -1 because self is implicit
4804                        arg_values.len()
4805                    )));
4806                }
4807
4808                // Create new environment with method's captured environment as base
4809                let mut new_env = (*env).clone();
4810
4811                // Bind self parameter (first parameter)
4812                // RUNTIME-094: Bind as Value::Struct to preserve struct type for nested method calls
4813                if let Some(self_param) = params.first() {
4814                    new_env.insert(
4815                        self_param.clone(),
4816                        Value::Struct {
4817                            name: struct_name.to_string(),
4818                            fields: std::sync::Arc::new(instance.clone()),
4819                        },
4820                    );
4821                }
4822
4823                // Bind other parameters
4824                for (i, arg_value) in arg_values.iter().enumerate() {
4825                    if let Some(param_name) = params.get(i + 1) {
4826                        // +1 to skip self
4827                        new_env.insert(param_name.clone(), arg_value.clone());
4828                    }
4829                }
4830
4831                // Execute method body with new environment
4832                self.env_stack.push(new_env);
4833                let result = self.eval_expr(&body);
4834                self.env_stack.pop();
4835
4836                result
4837            } else {
4838                Err(InterpreterError::RuntimeError(format!(
4839                    "Found {} but it's not a method closure",
4840                    qualified_method_name
4841                )))
4842            }
4843        } else {
4844            // Fall back to generic method handling
4845            self.eval_generic_method(
4846                &Value::Object(std::sync::Arc::new(instance.clone())),
4847                method,
4848                arg_values.is_empty(),
4849            )
4850        }
4851    }
4852
4853    fn eval_object_method(
4854        &self,
4855        obj: &std::collections::HashMap<String, Value>,
4856        method: &str,
4857        arg_values: &[Value],
4858        args_empty: bool,
4859    ) -> Result<Value, InterpreterError> {
4860        use crate::runtime::eval_method_dispatch;
4861        eval_method_dispatch::eval_method_call(
4862            &Value::Object(std::sync::Arc::new(obj.clone())),
4863            method,
4864            arg_values,
4865            args_empty,
4866            |_receiver, _args| {
4867                Err(InterpreterError::RuntimeError(
4868                    "Function call not implemented in actor context".to_string(),
4869                ))
4870            },
4871            |_receiver, _args| {
4872                Err(InterpreterError::RuntimeError(
4873                    "DataFrame filter not implemented in actor context".to_string(),
4874                ))
4875            },
4876            |_expr, _columns, _index| {
4877                Err(InterpreterError::RuntimeError(
4878                    "Column context not implemented in actor context".to_string(),
4879                ))
4880            },
4881        )
4882    }
4883
4884    /// Evaluate actor definition
4885    ///
4886    /// Actors are first-class values that can be instantiated and receive messages.
4887    /// For now, we return an actor type object that can be used to create instances.
4888    fn eval_actor_definition(
4889        &mut self,
4890        name: &str,
4891        state: &[crate::frontend::ast::StructField],
4892        handlers: &[crate::frontend::ast::ActorHandler],
4893    ) -> Result<Value, InterpreterError> {
4894        use std::collections::HashMap;
4895
4896        // Create an actor type object
4897        let mut actor_type = HashMap::new();
4898
4899        // Store actor metadata
4900        actor_type.insert(
4901            "__type".to_string(),
4902            Value::from_string("Actor".to_string()),
4903        );
4904        actor_type.insert("__name".to_string(), Value::from_string(name.to_string()));
4905
4906        // Store state field definitions with default values
4907        let mut fields = HashMap::new();
4908        for field in state {
4909            let type_name = match &field.ty.kind {
4910                crate::frontend::ast::TypeKind::Named(n) => n.clone(),
4911                _ => "Any".to_string(),
4912            };
4913
4914            // Create field metadata object
4915            let mut field_meta = HashMap::new();
4916            field_meta.insert("type".to_string(), Value::from_string(type_name));
4917            field_meta.insert("is_mut".to_string(), Value::Bool(field.is_mut));
4918
4919            // Evaluate default value if present
4920            if let Some(ref default_expr) = field.default_value {
4921                match self.eval_expr(default_expr) {
4922                    Ok(default_val) => {
4923                        field_meta.insert("default".to_string(), default_val);
4924                    }
4925                    Err(_) => {
4926                        // If evaluation fails, use type default
4927                        field_meta.insert("default".to_string(), Value::Nil);
4928                    }
4929                }
4930            } else {
4931                // No default value specified, use Nil
4932                field_meta.insert("default".to_string(), Value::Nil);
4933            }
4934
4935            fields.insert(field.name.clone(), Value::Object(Arc::new(field_meta)));
4936        }
4937        actor_type.insert(
4938            "__fields".to_string(),
4939            Value::Object(std::sync::Arc::new(fields)),
4940        );
4941
4942        // Store message handlers as closures
4943        let mut handlers_array = Vec::new();
4944        for handler in handlers {
4945            // Create a closure for each handler
4946            let mut handler_obj = HashMap::new();
4947            handler_obj.insert(
4948                "message_type".to_string(),
4949                Value::from_string(handler.message_type.clone()),
4950            );
4951
4952            // Store params as strings
4953            let param_names: Vec<String> = handler
4954                .params
4955                .iter()
4956                .map(crate::frontend::ast::Param::name)
4957                .collect();
4958            handler_obj.insert(
4959                "params".to_string(),
4960                Value::Array(Arc::from(
4961                    param_names
4962                        .iter()
4963                        .map(|n| Value::from_string(n.clone()))
4964                        .collect::<Vec<_>>(),
4965                )),
4966            );
4967
4968            // Store parameter types for runtime type checking
4969            let param_types: Vec<String> = handler
4970                .params
4971                .iter()
4972                .map(|p| match &p.ty.kind {
4973                    crate::frontend::ast::TypeKind::Named(name) => name.clone(),
4974                    _ => "Any".to_string(),
4975                })
4976                .collect();
4977            handler_obj.insert(
4978                "param_types".to_string(),
4979                Value::Array(Arc::from(
4980                    param_types
4981                        .iter()
4982                        .map(|t| Value::from_string(t.clone()))
4983                        .collect::<Vec<_>>(),
4984                )),
4985            );
4986
4987            // Store the handler body AST node (we'll evaluate it later)
4988            // For now, store as a closure with the current environment
4989            handler_obj.insert(
4990                "body".to_string(),
4991                Value::Closure {
4992                    params: param_names,
4993                    body: Arc::new(*handler.body.clone()),
4994                    env: Arc::new(self.current_env().clone()),
4995                },
4996            );
4997
4998            handlers_array.push(Value::Object(Arc::new(handler_obj)));
4999        }
5000        actor_type.insert(
5001            "__handlers".to_string(),
5002            Value::Array(Arc::from(handlers_array)),
5003        );
5004
5005        // Register this actor type in the environment
5006        let actor_obj = Value::Object(std::sync::Arc::new(actor_type));
5007        self.set_variable(name, actor_obj.clone());
5008
5009        Ok(actor_obj)
5010    }
5011
5012    /// Evaluate struct definition
5013    /// Creates a struct type descriptor that can be used for instantiation
5014    /// Complexity: 7
5015    fn eval_struct_definition(
5016        &mut self,
5017        name: &str,
5018        _type_params: &[String], // Generic type parameters (not yet used in runtime)
5019        fields: &[crate::frontend::ast::StructField],
5020        _is_pub: bool,
5021    ) -> Result<Value, InterpreterError> {
5022        use std::collections::HashMap;
5023
5024        // Create a struct type object
5025        let mut struct_type = HashMap::new();
5026
5027        // Store struct metadata
5028        struct_type.insert(
5029            "__type".to_string(),
5030            Value::from_string("Struct".to_string()),
5031        );
5032        struct_type.insert("__name".to_string(), Value::from_string(name.to_string()));
5033
5034        // Store field definitions
5035        let mut field_defs = HashMap::new();
5036        for field in fields {
5037            // Store field type information
5038            let type_name = match &field.ty.kind {
5039                crate::frontend::ast::TypeKind::Named(n) => n.clone(),
5040                crate::frontend::ast::TypeKind::Array { .. } => "Array".to_string(),
5041                crate::frontend::ast::TypeKind::Optional(_) => "Option".to_string(),
5042                crate::frontend::ast::TypeKind::List(_) => "List".to_string(),
5043                crate::frontend::ast::TypeKind::Tuple(_) => "Tuple".to_string(),
5044                _ => "Any".to_string(),
5045            };
5046
5047            let mut field_info = HashMap::new();
5048            field_info.insert("type".to_string(), Value::from_string(type_name));
5049            field_info.insert(
5050                "is_pub".to_string(),
5051                Value::from_bool(field.visibility.is_public()),
5052            );
5053            field_info.insert("is_mut".to_string(), Value::from_bool(field.is_mut));
5054            // Store visibility for access control
5055            let visibility_str = match field.visibility {
5056                crate::frontend::ast::Visibility::Public => "pub",
5057                crate::frontend::ast::Visibility::PubCrate => "pub(crate)",
5058                crate::frontend::ast::Visibility::PubSuper => "pub(super)",
5059                crate::frontend::ast::Visibility::Private => "private",
5060                crate::frontend::ast::Visibility::Protected => "protected",
5061            };
5062            field_info.insert(
5063                "visibility".to_string(),
5064                Value::from_string(visibility_str.to_string()),
5065            );
5066
5067            // Store default value if present
5068            if let Some(default_expr) = &field.default_value {
5069                let default_val = self.eval_expr(default_expr)?;
5070                field_info.insert("default".to_string(), default_val);
5071            }
5072
5073            field_defs.insert(
5074                field.name.clone(),
5075                Value::Object(std::sync::Arc::new(field_info)),
5076            );
5077        }
5078
5079        struct_type.insert(
5080            "__fields".to_string(),
5081            Value::Object(std::sync::Arc::new(field_defs)),
5082        );
5083
5084        // Register this struct type in the environment
5085        let struct_obj = Value::Object(std::sync::Arc::new(struct_type));
5086        self.set_variable(name, struct_obj.clone());
5087
5088        Ok(struct_obj)
5089    }
5090
5091    /// Evaluate enum definition
5092    /// Stores enum type with variant definitions in the environment
5093    /// Complexity: 6
5094    fn eval_enum_definition(
5095        &mut self,
5096        name: &str,
5097        _type_params: &[String], // Generic type parameters (not yet used in runtime)
5098        variants: &[crate::frontend::ast::EnumVariant],
5099        _is_pub: bool,
5100    ) -> Result<Value, InterpreterError> {
5101        use std::collections::HashMap;
5102
5103        // Create an enum type object
5104        let mut enum_type = HashMap::new();
5105
5106        // Store enum metadata
5107        enum_type.insert(
5108            "__type".to_string(),
5109            Value::from_string("Enum".to_string()),
5110        );
5111        enum_type.insert("__name".to_string(), Value::from_string(name.to_string()));
5112
5113        // Store variant definitions
5114        let mut variant_defs = HashMap::new();
5115        for variant in variants {
5116            let mut variant_info = HashMap::new();
5117
5118            // Store variant kind
5119            let kind_str = match &variant.kind {
5120                crate::frontend::ast::EnumVariantKind::Unit => "Unit",
5121                crate::frontend::ast::EnumVariantKind::Tuple(_) => "Tuple",
5122                crate::frontend::ast::EnumVariantKind::Struct(_) => "Struct",
5123            };
5124            variant_info.insert("kind".to_string(), Value::from_string(kind_str.to_string()));
5125
5126            // Store discriminant if present
5127            if let Some(disc) = variant.discriminant {
5128                variant_info.insert("discriminant".to_string(), Value::Integer(disc));
5129            }
5130
5131            variant_defs.insert(
5132                variant.name.clone(),
5133                Value::Object(std::sync::Arc::new(variant_info)),
5134            );
5135        }
5136
5137        enum_type.insert(
5138            "__variants".to_string(),
5139            Value::Object(std::sync::Arc::new(variant_defs)),
5140        );
5141
5142        // Register this enum type in the environment
5143        let enum_obj = Value::Object(std::sync::Arc::new(enum_type));
5144        self.set_variable(name, enum_obj.clone());
5145
5146        Ok(enum_obj)
5147    }
5148
5149    /// Evaluate struct literal (instantiation)
5150    /// Creates an instance of a struct with provided field values
5151    /// Complexity: 8
5152    fn eval_struct_literal(
5153        &mut self,
5154        name: &str,
5155        fields: &[(String, crate::frontend::ast::Expr)],
5156    ) -> Result<Value, InterpreterError> {
5157        use std::collections::HashMap;
5158
5159        // Look up the struct type definition
5160        let struct_type = self.lookup_variable(name).map_err(|_| {
5161            InterpreterError::RuntimeError(format!("Undefined struct type: {name}"))
5162        })?;
5163
5164        // Verify it's actually a struct type
5165        let struct_type_obj = if let Value::Object(obj) = &struct_type {
5166            obj
5167        } else {
5168            return Err(InterpreterError::RuntimeError(format!(
5169                "{name} is not a struct type"
5170            )));
5171        };
5172
5173        // Verify it's a struct type (not actor or other type)
5174        let type_name = struct_type_obj
5175            .get("__type")
5176            .and_then(|v| {
5177                if let Value::String(s) = v {
5178                    Some(s.as_ref())
5179                } else {
5180                    None
5181                }
5182            })
5183            .unwrap_or("");
5184
5185        // Handle Actor types differently
5186        if type_name == "Actor" {
5187            // Convert field expressions to values for actor instantiation
5188            let mut field_values = Vec::new();
5189            for (field_name, field_expr) in fields {
5190                let value = self.eval_expr(field_expr)?;
5191                field_values.push((field_name.clone(), value));
5192            }
5193
5194            // Create an object with the named fields to pass to actor instantiation
5195            let mut args_obj = HashMap::new();
5196            for (name, value) in field_values {
5197                args_obj.insert(name, value);
5198            }
5199
5200            // Call the actor instantiation function
5201            return self.instantiate_actor_with_args(name, &[Value::Object(Arc::new(args_obj))]);
5202        }
5203
5204        if type_name != "Struct" {
5205            return Err(InterpreterError::RuntimeError(format!(
5206                "{name} is not a struct type (it's a {type_name})"
5207            )));
5208        }
5209
5210        // Get field definitions
5211        let field_defs = struct_type_obj
5212            .get("__fields")
5213            .and_then(|v| {
5214                if let Value::Object(obj) = v {
5215                    Some(obj)
5216                } else {
5217                    None
5218                }
5219            })
5220            .ok_or_else(|| {
5221                InterpreterError::RuntimeError(format!("Invalid struct type definition for {name}"))
5222            })?;
5223
5224        // Create struct instance fields (without metadata)
5225        let mut instance_fields = HashMap::new();
5226
5227        // Evaluate and set field values
5228        for (field_name, field_expr) in fields {
5229            // Verify field exists in struct definition
5230            if !field_defs.contains_key(field_name) {
5231                return Err(InterpreterError::RuntimeError(format!(
5232                    "Struct {name} does not have field '{field_name}'"
5233                )));
5234            }
5235
5236            // Evaluate field value
5237            let field_value = self.eval_expr(field_expr)?;
5238            instance_fields.insert(field_name.clone(), field_value);
5239        }
5240
5241        // Check that all required fields are provided or have defaults
5242        for (field_name, field_def_value) in field_defs.iter() {
5243            if !instance_fields.contains_key(field_name) {
5244                // Check if this field has a default value
5245                if let Value::Object(field_info) = field_def_value {
5246                    if let Some(default_val) = field_info.get("default") {
5247                        // Use default value
5248                        instance_fields.insert(field_name.clone(), default_val.clone());
5249                    } else {
5250                        // No default, field is required
5251                        return Err(InterpreterError::RuntimeError(format!(
5252                            "Missing required field '{field_name}' for struct {name}"
5253                        )));
5254                    }
5255                } else {
5256                    return Err(InterpreterError::RuntimeError(format!(
5257                        "Invalid field definition for '{field_name}' in struct {name}"
5258                    )));
5259                }
5260            }
5261        }
5262
5263        // Return Value::Struct variant (not Object)
5264        Ok(Value::Struct {
5265            name: name.to_string(),
5266            fields: Arc::new(instance_fields),
5267        })
5268    }
5269
5270    /// Evaluate class definition
5271    ///
5272    /// Supports:
5273    /// - Class fields with types and defaults
5274    /// - Multiple constructors (including named constructors)
5275    /// - Instance methods with self binding
5276    /// - Static methods (no self binding)
5277    /// - Inheritance metadata (superclass stored but not fully implemented)
5278    ///
5279    /// Limitations:
5280    /// - Instance mutations don't persist between method calls (needs `RefCell`)
5281    /// - Inheritance not fully implemented (no `super()` calls or field merging)
5282    /// - Method overriding not implemented
5283    ///
5284    /// Complexity: 8
5285    fn eval_class_definition(
5286        &mut self,
5287        name: &str,
5288        _type_params: &[String],
5289        superclass: Option<&String>,
5290        _traits: &[String],
5291        fields: &[crate::frontend::ast::StructField],
5292        constructors: &[crate::frontend::ast::Constructor],
5293        methods: &[crate::frontend::ast::ClassMethod],
5294        constants: &[crate::frontend::ast::ClassConstant],
5295        _derives: &[String],
5296        _is_pub: bool,
5297    ) -> Result<Value, InterpreterError> {
5298        use std::collections::HashMap;
5299        use std::sync::Arc;
5300
5301        // Create class metadata object
5302        let mut class_info = HashMap::new();
5303
5304        // Mark as class type
5305        class_info.insert(
5306            "__type".to_string(),
5307            Value::from_string("Class".to_string()),
5308        );
5309        class_info.insert("__name".to_string(), Value::from_string(name.to_string()));
5310
5311        // Store superclass if present
5312        if let Some(parent) = superclass {
5313            class_info.insert(
5314                "__superclass".to_string(),
5315                Value::from_string(parent.clone()),
5316            );
5317        }
5318
5319        // Store field definitions (similar to struct)
5320        let mut field_defs = HashMap::new();
5321        for field in fields {
5322            let mut field_info = HashMap::new();
5323
5324            // Store field type
5325            let type_str = format!("{:?}", field.ty);
5326            field_info.insert("type".to_string(), Value::from_string(type_str));
5327
5328            // Store visibility
5329            field_info.insert(
5330                "is_pub".to_string(),
5331                Value::Bool(field.visibility.is_public()),
5332            );
5333            field_info.insert("is_mut".to_string(), Value::Bool(field.is_mut));
5334
5335            // Store default value if present
5336            if let Some(ref default) = field.default_value {
5337                // Evaluate default value
5338                let default_val = self.eval_expr(default)?;
5339                field_info.insert("default".to_string(), default_val);
5340            }
5341
5342            field_defs.insert(
5343                field.name.clone(),
5344                Value::Object(std::sync::Arc::new(field_info)),
5345            );
5346        }
5347        class_info.insert("__fields".to_string(), Value::Object(Arc::new(field_defs)));
5348
5349        // Store constructors as closures
5350        let mut constructor_info = HashMap::new();
5351        for constructor in constructors {
5352            // Store constructor by name (default name is "new")
5353            let ctor_name = constructor
5354                .name
5355                .as_ref()
5356                .unwrap_or(&"new".to_string())
5357                .clone();
5358
5359            // Extract parameter names from the constructor params
5360            let param_names: Vec<String> = constructor
5361                .params
5362                .iter()
5363                .map(|p| match &p.pattern {
5364                    crate::frontend::ast::Pattern::Identifier(name) => name.clone(),
5365                    _ => "_".to_string(),
5366                })
5367                .collect();
5368
5369            // Create a closure for the constructor
5370            let ctor_closure = Value::Closure {
5371                params: param_names,
5372                body: Arc::new((*constructor.body).clone()),
5373                env: Arc::new(HashMap::new()), // Empty env for now
5374            };
5375
5376            constructor_info.insert(ctor_name, ctor_closure);
5377        }
5378
5379        // If no constructors defined, create a default "new" constructor
5380        if constructor_info.is_empty() {
5381            // Create a default constructor that initializes fields with defaults
5382            let default_body = Expr::new(
5383                ExprKind::Block(Vec::new()), // Empty block - fields get initialized with defaults
5384                crate::frontend::ast::Span::new(0, 0),
5385            );
5386
5387            let default_constructor = Value::Closure {
5388                params: Vec::new(), // No parameters
5389                body: Arc::new(default_body),
5390                env: Arc::new(HashMap::new()),
5391            };
5392
5393            constructor_info.insert("new".to_string(), default_constructor);
5394        }
5395
5396        class_info.insert(
5397            "__constructors".to_string(),
5398            Value::Object(Arc::new(constructor_info)),
5399        );
5400
5401        // Store methods as closures with metadata
5402        let mut method_info = HashMap::new();
5403        for method in methods {
5404            // Extract parameter names from the method params (excluding 'self')
5405            let param_names: Vec<String> = method
5406                .params
5407                .iter()
5408                .filter_map(|p| match &p.pattern {
5409                    crate::frontend::ast::Pattern::Identifier(name) if name != "self" => {
5410                        Some(name.clone())
5411                    }
5412                    crate::frontend::ast::Pattern::Identifier(_) => None, // Skip 'self'
5413                    _ => Some("_".to_string()),
5414                })
5415                .collect();
5416
5417            // Create a closure for the method
5418            let method_closure = Value::Closure {
5419                params: param_names,
5420                body: Arc::new((*method.body).clone()),
5421                env: Arc::new(HashMap::new()),
5422            };
5423
5424            // Store method with metadata
5425            let mut method_meta = HashMap::new();
5426            method_meta.insert("closure".to_string(), method_closure);
5427            method_meta.insert("is_static".to_string(), Value::Bool(method.is_static));
5428            method_meta.insert("is_override".to_string(), Value::Bool(method.is_override));
5429
5430            method_info.insert(method.name.clone(), Value::Object(Arc::new(method_meta)));
5431        }
5432        class_info.insert(
5433            "__methods".to_string(),
5434            Value::Object(Arc::new(method_info)),
5435        );
5436
5437        // Store class constants
5438        let mut constants_info = HashMap::new();
5439        for constant in constants {
5440            // Evaluate the constant value
5441            let const_value = self.eval_expr(&constant.value)?;
5442
5443            // Store constant with metadata
5444            let mut const_meta = HashMap::new();
5445            const_meta.insert("value".to_string(), const_value.clone());
5446            const_meta.insert(
5447                "type".to_string(),
5448                Value::from_string(format!("{:?}", constant.ty)),
5449            );
5450            const_meta.insert("is_pub".to_string(), Value::Bool(constant.is_pub));
5451
5452            constants_info.insert(constant.name.clone(), Value::Object(Arc::new(const_meta)));
5453
5454            // Also store the constant directly on the class for easy access
5455            // e.g., MyClass::CONSTANT_NAME
5456            let qualified_name = format!("{}::{}", name, constant.name);
5457            self.set_variable(&qualified_name, const_value);
5458        }
5459        class_info.insert(
5460            "__constants".to_string(),
5461            Value::Object(Arc::new(constants_info)),
5462        );
5463
5464        // Store the class definition in the environment
5465        let class_value = Value::Object(Arc::new(class_info));
5466        self.set_variable(name, class_value.clone());
5467
5468        Ok(class_value)
5469    }
5470
5471    fn eval_impl_block(
5472        &mut self,
5473        for_type: &str,
5474        methods: &[crate::frontend::ast::ImplMethod],
5475    ) -> Result<Value, InterpreterError> {
5476        use std::collections::HashMap;
5477        use std::sync::Arc;
5478
5479        // For struct impl blocks, we need to register methods that can be called on instances
5480        // We'll store them in a special registry keyed by type name
5481        let mut impl_methods = HashMap::new();
5482
5483        for method in methods {
5484            // Extract parameter names from Param structs
5485            let param_names: Vec<String> = method
5486                .params
5487                .iter()
5488                .map(|p| match &p.pattern {
5489                    crate::frontend::ast::Pattern::Identifier(name) => name.clone(),
5490                    _ => "_".to_string(), // For other patterns, use placeholder
5491                })
5492                .collect();
5493
5494            // Convert ImplMethod to a Value::Closure
5495            let closure = Value::Closure {
5496                params: param_names,
5497                body: Arc::new(*method.body.clone()),
5498                env: Arc::new(HashMap::new()),
5499            };
5500            impl_methods.insert(method.name.clone(), closure);
5501        }
5502
5503        // Store the impl methods in a global registry
5504        // For now, we'll just add them to the environment with qualified names
5505        for (method_name, method_closure) in impl_methods {
5506            let qualified_name = format!("{}::{}", for_type, method_name);
5507            self.set_variable(&qualified_name, method_closure);
5508        }
5509
5510        Ok(Value::Nil) // impl blocks don't return values
5511    }
5512
5513    /// Instantiates a class by calling its constructor.
5514    ///
5515    /// This method creates a new class instance, initializes fields with default values,
5516    /// and executes the constructor body to set field values from arguments.
5517    ///
5518    /// # Examples
5519    ///
5520    /// ```
5521    /// use ruchy::frontend::parser::Parser;
5522    /// use ruchy::runtime::interpreter::{Interpreter, Value};
5523    ///
5524    /// let mut interpreter = Interpreter::new();
5525    /// let code = r#"
5526    ///     class Point {
5527    ///         x: i32,
5528    ///         y: i32
5529    ///
5530    ///         new(x: i32, y: i32) {
5531    ///             self.x = x
5532    ///             self.y = y
5533    ///         }
5534    ///
5535    ///         fn get_x(&self) -> i32 {
5536    ///             self.x
5537    ///         }
5538    ///     }
5539    ///
5540    ///     fn main() {
5541    ///         let p = Point::new(3, 4)
5542    ///         p.get_x()
5543    ///     }
5544    /// "#;
5545    ///
5546    /// let mut parser = Parser::new(code);
5547    /// let expr = parser.parse().unwrap();
5548    /// interpreter.eval_expr(&expr).unwrap();
5549    /// let main_call = Parser::new("main()").parse().unwrap();
5550    /// let result = interpreter.eval_expr(&main_call).unwrap();
5551    /// assert!(matches!(result, Value::Integer(3)));
5552    /// ```
5553    fn instantiate_class_with_constructor(
5554        &mut self,
5555        class_name: &str,
5556        constructor_name: &str,
5557        args: &[Value],
5558    ) -> Result<Value, InterpreterError> {
5559        // Look up the class definition
5560        let class_def = self.lookup_variable(class_name)?;
5561
5562        if let Value::Object(ref class_info) = class_def {
5563            // Verify this is a class
5564            if let Some(Value::String(ref type_str)) = class_info.get("__type") {
5565                if type_str.as_ref() != "Class" {
5566                    return Err(InterpreterError::RuntimeError(format!(
5567                        "{} is not a class",
5568                        class_name
5569                    )));
5570                }
5571            }
5572
5573            // Create instance object
5574            let mut instance = HashMap::new();
5575            instance.insert(
5576                "__class".to_string(),
5577                Value::from_string(class_name.to_string()),
5578            );
5579
5580            // Helper function to collect fields from class and its parents
5581            fn collect_all_fields(
5582                class_info: &HashMap<String, Value>,
5583                interpreter: &Interpreter,
5584            ) -> HashMap<String, Value> {
5585                let mut all_fields = HashMap::new();
5586
5587                // First, get parent fields if there's a superclass
5588                if let Some(Value::String(ref parent_name)) = class_info.get("__superclass") {
5589                    if let Ok(Value::Object(ref parent_info)) =
5590                        interpreter.lookup_variable(parent_name)
5591                    {
5592                        let parent_fields = collect_all_fields(parent_info, interpreter);
5593                        all_fields.extend(parent_fields);
5594                    }
5595                }
5596
5597                // Then add this class's fields (overriding parent fields if they exist)
5598                if let Some(Value::Object(ref fields)) = class_info.get("__fields") {
5599                    for (field_name, field_info) in fields.iter() {
5600                        if let Value::Object(ref field_meta) = field_info {
5601                            // Use default value if present
5602                            if let Some(default) = field_meta.get("default") {
5603                                all_fields.insert(field_name.clone(), default.clone());
5604                            } else {
5605                                // Initialize with nil
5606                                all_fields.insert(field_name.clone(), Value::Nil);
5607                            }
5608                        }
5609                    }
5610                }
5611
5612                all_fields
5613            }
5614
5615            // Initialize fields with default values from this class and all parent classes
5616            let all_fields = collect_all_fields(class_info, self);
5617            for (field_name, field_value) in all_fields {
5618                instance.insert(field_name, field_value);
5619            }
5620
5621            // Execute the constructor if present
5622            if let Some(Value::Object(ref constructors)) = class_info.get("__constructors") {
5623                // Look for the specified constructor
5624                if let Some(constructor) = constructors.get(constructor_name) {
5625                    if let Value::Closure {
5626                        params,
5627                        body,
5628                        env: _,
5629                    } = constructor
5630                    {
5631                        // Check argument count
5632                        if args.len() != params.len() {
5633                            return Err(InterpreterError::RuntimeError(format!(
5634                                "constructor expects {} arguments, got {}",
5635                                params.len(),
5636                                args.len()
5637                            )));
5638                        }
5639
5640                        // Create environment for constructor
5641                        let mut ctor_env = HashMap::new();
5642
5643                        // Bind 'self' to mutable instance for constructor
5644                        ctor_env.insert(
5645                            "self".to_string(),
5646                            Value::Object(Arc::new(instance.clone())),
5647                        );
5648
5649                        // Bind constructor parameters
5650                        for (param, arg) in params.iter().zip(args) {
5651                            ctor_env.insert(param.clone(), arg.clone());
5652                        }
5653
5654                        // Push constructor environment
5655                        self.env_stack.push(ctor_env);
5656
5657                        // Execute constructor body
5658                        let _result = self.eval_expr(body)?;
5659
5660                        // Extract updated self from environment after constructor execution
5661                        // Note: Handles immutability by copying updated fields back to instance
5662                        let updated_self = self.lookup_variable("self")?;
5663                        if let Value::Object(ref updated_instance) = updated_self {
5664                            // Copy all non-metadata fields from updated self back to instance
5665                            for (key, value) in updated_instance.iter() {
5666                                if !key.starts_with("__") {
5667                                    instance.insert(key.clone(), value.clone());
5668                                }
5669                            }
5670                        }
5671
5672                        // Pop environment
5673                        self.env_stack.pop();
5674                    }
5675                }
5676            }
5677
5678            // Return ObjectMut for mutable class instances (support &mut self methods)
5679            Ok(crate::runtime::object_helpers::new_mutable_object(instance))
5680        } else {
5681            Err(InterpreterError::RuntimeError(format!(
5682                "{} is not a class definition",
5683                class_name
5684            )))
5685        }
5686    }
5687
5688    /// Instantiate a class with arguments (calls init constructor)
5689    /// Returns `Value::Class` with reference semantics
5690    fn instantiate_class_with_args(
5691        &mut self,
5692        class_name: &str,
5693        args: &[Value],
5694    ) -> Result<Value, InterpreterError> {
5695        use std::sync::RwLock;
5696
5697        // Look up the class definition
5698        let class_def = self.lookup_variable(class_name)?;
5699
5700        if let Value::Object(ref class_info) = class_def {
5701            // Verify this is a class
5702            if let Some(Value::String(ref type_str)) = class_info.get("__type") {
5703                if type_str.as_ref() != "Class" {
5704                    return Err(InterpreterError::RuntimeError(format!(
5705                        "{} is not a class",
5706                        class_name
5707                    )));
5708                }
5709            }
5710
5711            // Collect methods from the class definition
5712            let mut methods_map = HashMap::new();
5713            if let Some(Value::Object(ref methods_obj)) = class_info.get("__methods") {
5714                for (method_name, method_value) in methods_obj.iter() {
5715                    // Extract the closure from method metadata
5716                    if let Value::Object(ref method_meta) = method_value {
5717                        if let Some(closure) = method_meta.get("closure") {
5718                            methods_map.insert(method_name.clone(), closure.clone());
5719                        }
5720                    }
5721                }
5722            }
5723
5724            // Create instance fields with default values
5725            let mut instance_fields = HashMap::new();
5726            if let Some(Value::Object(ref fields)) = class_info.get("__fields") {
5727                for (field_name, field_info) in fields.iter() {
5728                    if let Value::Object(ref field_meta) = field_info {
5729                        // Use default value if present
5730                        if let Some(default) = field_meta.get("default") {
5731                            instance_fields.insert(field_name.clone(), default.clone());
5732                        } else {
5733                            // Initialize with nil
5734                            instance_fields.insert(field_name.clone(), Value::Nil);
5735                        }
5736                    }
5737                }
5738            }
5739
5740            // Create the Class instance
5741            let class_instance = Value::Class {
5742                class_name: class_name.to_string(),
5743                fields: Arc::new(RwLock::new(instance_fields.clone())),
5744                methods: Arc::new(methods_map),
5745            };
5746
5747            // Execute the init constructor if present
5748            if let Some(Value::Object(ref constructors)) = class_info.get("__constructors") {
5749                // Look for "init" or "new" constructor
5750                let constructor = constructors
5751                    .get("init")
5752                    .or_else(|| constructors.get("new"));
5753
5754                if let Some(constructor) = constructor {
5755                    if let Value::Closure {
5756                        params,
5757                        body,
5758                        env: _,
5759                    } = constructor
5760                    {
5761                        // Check argument count
5762                        if args.len() != params.len() {
5763                            return Err(InterpreterError::RuntimeError(format!(
5764                                "constructor expects {} arguments, got {}",
5765                                params.len(),
5766                                args.len()
5767                            )));
5768                        }
5769
5770                        // Create environment for constructor
5771                        let mut ctor_env = HashMap::new();
5772
5773                        // Bind 'self' to the class instance
5774                        ctor_env.insert("self".to_string(), class_instance.clone());
5775
5776                        // Bind constructor parameters
5777                        for (param, arg) in params.iter().zip(args) {
5778                            ctor_env.insert(param.clone(), arg.clone());
5779                        }
5780
5781                        // Push constructor environment
5782                        self.env_stack.push(ctor_env);
5783
5784                        // Execute constructor body
5785                        let _result = self.eval_expr(body)?;
5786
5787                        // Pop environment
5788                        self.env_stack.pop();
5789                    }
5790                }
5791            }
5792
5793            Ok(class_instance)
5794        } else {
5795            Err(InterpreterError::RuntimeError(format!(
5796                "{} is not a class definition",
5797                class_name
5798            )))
5799        }
5800    }
5801
5802    fn instantiate_struct_with_args(
5803        &mut self,
5804        struct_name: &str,
5805        args: &[Value],
5806    ) -> Result<Value, InterpreterError> {
5807        // Look up the struct definition
5808        let struct_def = self.lookup_variable(struct_name)?;
5809
5810        if let Value::Object(ref struct_info) = struct_def {
5811            // Verify this is a struct
5812            if let Some(Value::String(ref type_str)) = struct_info.get("__type") {
5813                if type_str.as_ref() != "Struct" {
5814                    return Err(InterpreterError::RuntimeError(format!(
5815                        "{} is not a struct",
5816                        struct_name
5817                    )));
5818                }
5819            }
5820
5821            // For structs with positional arguments, we need to map them to fields
5822            // This is a simplified version - real implementation would need parameter names
5823            // For now, create an empty struct instance
5824            let mut instance = HashMap::new();
5825            instance.insert(
5826                "__struct".to_string(),
5827                Value::from_string(struct_name.to_string()),
5828            );
5829
5830            // Initialize fields with default values
5831            if let Some(Value::Object(ref fields)) = struct_info.get("__fields") {
5832                // Map positional arguments to fields (assuming order matches definition)
5833                for (i, (field_name, field_info)) in fields.iter().enumerate() {
5834                    if i < args.len() {
5835                        instance.insert(field_name.clone(), args[i].clone());
5836                    } else if let Value::Object(ref field_meta) = field_info {
5837                        // Use default value if present
5838                        if let Some(default) = field_meta.get("default") {
5839                            instance.insert(field_name.clone(), default.clone());
5840                        } else {
5841                            // Initialize with default for type
5842                            instance.insert(field_name.clone(), Value::Nil);
5843                        }
5844                    }
5845                }
5846            }
5847
5848            Ok(Value::Object(Arc::new(instance)))
5849        } else {
5850            Err(InterpreterError::RuntimeError(format!(
5851                "{} is not a struct definition",
5852                struct_name
5853            )))
5854        }
5855    }
5856
5857    /// Instantiates an actor with initial field values.
5858    ///
5859    /// This method creates a new actor instance, initializes fields with default or provided values,
5860    /// and stores the message handlers for later use.
5861    ///
5862    /// # Examples
5863    ///
5864    /// ```
5865    /// use ruchy::frontend::parser::Parser;
5866    /// use ruchy::runtime::interpreter::Interpreter;
5867    ///
5868    /// let mut interpreter = Interpreter::new();
5869    /// let code = r#"
5870    ///     actor Counter {
5871    ///         count: i32 = 0
5872    ///
5873    ///         receive {
5874    ///             Increment => 42
5875    ///         }
5876    ///     }
5877    ///
5878    ///     fn main() {
5879    ///         let counter = spawn Counter
5880    ///         counter
5881    ///     }
5882    /// "#;
5883    ///
5884    /// let mut parser = Parser::new(code);
5885    /// let expr = parser.parse().unwrap();
5886    /// interpreter.eval_expr(&expr).unwrap();
5887    /// let main_call = Parser::new("main()").parse().unwrap();
5888    /// let result = interpreter.eval_expr(&main_call);
5889    /// assert!(result.is_ok());
5890    /// ```
5891    fn instantiate_actor_with_args(
5892        &mut self,
5893        actor_name: &str,
5894        args: &[Value],
5895    ) -> Result<Value, InterpreterError> {
5896        // Look up the actor definition
5897        let actor_def = self.lookup_variable(actor_name)?;
5898
5899        if let Value::Object(ref actor_info) = actor_def {
5900            // Verify this is an actor
5901            if let Some(Value::String(ref type_str)) = actor_info.get("__type") {
5902                if type_str.as_ref() != "Actor" {
5903                    return Err(InterpreterError::RuntimeError(format!(
5904                        "{} is not an actor",
5905                        actor_name
5906                    )));
5907                }
5908            }
5909
5910            // Create actor instance
5911            let mut instance = HashMap::new();
5912            instance.insert(
5913                "__actor".to_string(),
5914                Value::from_string(actor_name.to_string()),
5915            );
5916
5917            // Check if args is a single object literal (named arguments)
5918            let named_args = if args.len() == 1 {
5919                if let Value::Object(ref obj) = args[0] {
5920                    Some(obj)
5921                } else {
5922                    None
5923                }
5924            } else {
5925                None
5926            };
5927
5928            // Initialize state fields with default values
5929            // Actors use __fields just like structs
5930            if let Some(Value::Object(ref fields)) = actor_info.get("__fields") {
5931                if let Some(named) = named_args {
5932                    // Use named arguments
5933                    for (field_name, _field_info) in fields.iter() {
5934                        if let Some(value) = named.get(field_name) {
5935                            instance.insert(field_name.clone(), value.clone());
5936                        } else {
5937                            // Initialize with default for type
5938                            instance.insert(field_name.clone(), Value::Nil);
5939                        }
5940                    }
5941                } else {
5942                    // Map positional arguments to fields (assuming order matches definition)
5943                    for (i, (field_name, field_info)) in fields.iter().enumerate() {
5944                        if i < args.len() {
5945                            instance.insert(field_name.clone(), args[i].clone());
5946                        } else if let Value::Object(ref field_meta) = field_info {
5947                            // Use default value if present
5948                            if let Some(default) = field_meta.get("default") {
5949                                instance.insert(field_name.clone(), default.clone());
5950                            } else {
5951                                // Initialize with default for type
5952                                instance.insert(field_name.clone(), Value::Nil);
5953                            }
5954                        } else {
5955                            // Simple field without metadata
5956                            instance.insert(field_name.clone(), Value::Nil);
5957                        }
5958                    }
5959                }
5960            }
5961
5962            // Store the actor's handlers for later message processing
5963            if let Some(handlers) = actor_info.get("__handlers") {
5964                instance.insert("__handlers".to_string(), handlers.clone());
5965            }
5966
5967            // For simple interpreted actors, don't use async runtime - just store state directly
5968            // This allows synchronous message processing which is simpler and works for tests
5969            // Return ObjectMut for mutable actor state
5970            Ok(crate::runtime::object_helpers::new_mutable_object(instance))
5971        } else {
5972            Err(InterpreterError::RuntimeError(format!(
5973                "{} is not an actor definition",
5974                actor_name
5975            )))
5976        }
5977    }
5978
5979    fn eval_class_instance_method(
5980        &mut self,
5981        instance: &HashMap<String, Value>,
5982        class_name: &str,
5983        method: &str,
5984        arg_values: &[Value],
5985    ) -> Result<Value, InterpreterError> {
5986        // Look up the class definition
5987        let class_def = self.lookup_variable(class_name)?;
5988
5989        if let Value::Object(ref class_info) = class_def {
5990            // Look for the method in the class definition
5991            if let Some(Value::Object(ref methods)) = class_info.get("__methods") {
5992                if let Some(Value::Object(ref method_meta)) = methods.get(method) {
5993                    // Get the method closure
5994                    if let Some(Value::Closure { params, body, .. }) = method_meta.get("closure") {
5995                        // Check if it's a static method
5996                        let is_static = method_meta
5997                            .get("is_static")
5998                            .and_then(|v| {
5999                                if let Value::Bool(b) = v {
6000                                    Some(*b)
6001                                } else {
6002                                    None
6003                                }
6004                            })
6005                            .unwrap_or(false);
6006
6007                        if is_static {
6008                            return Err(InterpreterError::RuntimeError(format!(
6009                                "Cannot call static method {} on instance",
6010                                method
6011                            )));
6012                        }
6013
6014                        // Create environment for method execution
6015                        let mut method_env = HashMap::new();
6016
6017                        // Add 'self' to the environment
6018                        method_env.insert(
6019                            "self".to_string(),
6020                            Value::Object(Arc::new(instance.clone())),
6021                        );
6022
6023                        // Bind method parameters to arguments
6024                        // Note: We're not including 'self' in params count here
6025                        if arg_values.len() != params.len() {
6026                            return Err(InterpreterError::RuntimeError(format!(
6027                                "Method {} expects {} arguments, got {}",
6028                                method,
6029                                params.len(),
6030                                arg_values.len()
6031                            )));
6032                        }
6033
6034                        for (param, arg) in params.iter().zip(arg_values) {
6035                            method_env.insert(param.clone(), arg.clone());
6036                        }
6037
6038                        // Push method environment
6039                        self.env_push(method_env);
6040
6041                        // Execute method body
6042                        let result = self.eval_expr(body)?;
6043
6044                        // Pop environment
6045                        self.env_pop();
6046
6047                        return Ok(result);
6048                    }
6049                }
6050            }
6051
6052            // Method not found
6053            Err(InterpreterError::RuntimeError(format!(
6054                "Class {} has no method named {}",
6055                class_name, method
6056            )))
6057        } else {
6058            Err(InterpreterError::RuntimeError(format!(
6059                "{} is not a class",
6060                class_name
6061            )))
6062        }
6063    }
6064
6065    fn call_static_method(
6066        &mut self,
6067        class_name: &str,
6068        method_name: &str,
6069        args: &[Value],
6070    ) -> Result<Value, InterpreterError> {
6071        // Look up the class definition
6072        let class_def = self.lookup_variable(class_name)?;
6073
6074        if let Value::Object(ref class_info) = class_def {
6075            // Look for the method in the class definition
6076            if let Some(Value::Object(ref methods)) = class_info.get("__methods") {
6077                if let Some(Value::Object(ref method_meta)) = methods.get(method_name) {
6078                    // Verify it's a static method
6079                    let is_static = method_meta
6080                        .get("is_static")
6081                        .and_then(|v| {
6082                            if let Value::Bool(b) = v {
6083                                Some(*b)
6084                            } else {
6085                                None
6086                            }
6087                        })
6088                        .unwrap_or(false);
6089
6090                    if !is_static {
6091                        return Err(InterpreterError::RuntimeError(format!(
6092                            "{} is not a static method",
6093                            method_name
6094                        )));
6095                    }
6096
6097                    // Get the method closure
6098                    if let Some(Value::Closure { params, body, .. }) = method_meta.get("closure") {
6099                        // Check parameter count
6100                        if args.len() != params.len() {
6101                            return Err(InterpreterError::RuntimeError(format!(
6102                                "Static method {} expects {} arguments, got {}",
6103                                method_name,
6104                                params.len(),
6105                                args.len()
6106                            )));
6107                        }
6108
6109                        // Create environment for static method execution
6110                        let mut method_env = HashMap::new();
6111
6112                        // Bind parameters to arguments (no self for static methods)
6113                        for (i, param) in params.iter().enumerate() {
6114                            method_env.insert(param.clone(), args[i].clone());
6115                        }
6116
6117                        // Push the method environment
6118                        self.env_stack.push(method_env);
6119
6120                        // Execute the method body
6121                        let result = self.eval_expr(body);
6122
6123                        // Pop the method environment
6124                        self.env_stack.pop();
6125
6126                        return result;
6127                    }
6128                }
6129            }
6130
6131            Err(InterpreterError::RuntimeError(format!(
6132                "Static method {} not found in class {}",
6133                method_name, class_name
6134            )))
6135        } else {
6136            Err(InterpreterError::RuntimeError(format!(
6137                "{} is not a class",
6138                class_name
6139            )))
6140        }
6141    }
6142
6143    /// Evaluate `DataFrame` builder methods (.column, .build)
6144    /// Complexity: 8 (within Toyota Way limits)
6145    fn eval_dataframe_builder_method(
6146        &self,
6147        builder: &std::collections::HashMap<String, Value>,
6148        method: &str,
6149        arg_values: &[Value],
6150    ) -> Result<Value, InterpreterError> {
6151        match method {
6152            "column" => {
6153                // .column(name, values) - add a column to the builder
6154                if arg_values.len() != 2 {
6155                    return Err(InterpreterError::RuntimeError(
6156                        "DataFrame builder .column() requires 2 arguments (name, values)"
6157                            .to_string(),
6158                    ));
6159                }
6160
6161                // Extract column name
6162                let name = match &arg_values[0] {
6163                    Value::String(s) => s.to_string(),
6164                    _ => {
6165                        return Err(InterpreterError::RuntimeError(
6166                            "Column name must be a string".to_string(),
6167                        ))
6168                    }
6169                };
6170
6171                // Extract values array
6172                let values = match &arg_values[1] {
6173                    Value::Array(arr) => arr.to_vec(),
6174                    _ => {
6175                        return Err(InterpreterError::RuntimeError(
6176                            "Column values must be an array".to_string(),
6177                        ))
6178                    }
6179                };
6180
6181                // Get current columns
6182                let current_columns = match builder.get("__columns") {
6183                    Some(Value::Array(cols)) => cols.to_vec(),
6184                    _ => vec![],
6185                };
6186
6187                // Create new column object
6188                let mut col_obj = std::collections::HashMap::new();
6189                col_obj.insert("name".to_string(), Value::from_string(name));
6190                col_obj.insert("values".to_string(), Value::from_array(values));
6191
6192                // Add to columns array
6193                let mut new_columns = current_columns;
6194                new_columns.push(Value::Object(std::sync::Arc::new(col_obj)));
6195
6196                // Create new builder with updated columns
6197                let mut new_builder = builder.clone();
6198                new_builder.insert("__columns".to_string(), Value::from_array(new_columns));
6199
6200                Ok(Value::Object(std::sync::Arc::new(new_builder)))
6201            }
6202            "build" => {
6203                // .build() - convert builder to `DataFrame`
6204                if !arg_values.is_empty() {
6205                    return Err(InterpreterError::RuntimeError(
6206                        "DataFrame builder .build() takes no arguments".to_string(),
6207                    ));
6208                }
6209
6210                // Extract columns from builder
6211                let columns_array = match builder.get("__columns") {
6212                    Some(Value::Array(cols)) => cols,
6213                    _ => return Ok(Value::DataFrame { columns: vec![] }),
6214                };
6215
6216                // Convert column objects to `DataFrameColumn` structs
6217                let mut df_columns = Vec::new();
6218                for col_val in columns_array.as_ref() {
6219                    if let Value::Object(col_obj) = col_val {
6220                        let name = match col_obj.get("name") {
6221                            Some(Value::String(s)) => s.to_string(),
6222                            _ => continue,
6223                        };
6224                        let values = match col_obj.get("values") {
6225                            Some(Value::Array(vals)) => vals.to_vec(),
6226                            _ => vec![],
6227                        };
6228                        df_columns.push(DataFrameColumn { name, values });
6229                    }
6230                }
6231
6232                Ok(Value::DataFrame {
6233                    columns: df_columns,
6234                })
6235            }
6236            _ => Err(InterpreterError::RuntimeError(format!(
6237                "Unknown builder method: {method}"
6238            ))),
6239        }
6240    }
6241
6242    fn eval_dataframe_method(
6243        &self,
6244        columns: &[DataFrameColumn],
6245        method: &str,
6246        arg_values: &[Value],
6247    ) -> Result<Value, InterpreterError> {
6248        crate::runtime::eval_dataframe_ops::eval_dataframe_method(columns, method, arg_values)
6249    }
6250
6251    /// Special handler for `DataFrame` filter method
6252    /// Complexity: 8 (within Toyota Way limits)
6253    fn eval_dataframe_filter_method(
6254        &mut self,
6255        receiver: &Value,
6256        args: &[Expr],
6257    ) -> Result<Value, InterpreterError> {
6258        if args.len() != 1 {
6259            return Err(InterpreterError::RuntimeError(
6260                "DataFrame.filter() requires exactly 1 argument (closure)".to_string(),
6261            ));
6262        }
6263
6264        if let Value::DataFrame { columns } = receiver {
6265            let closure = &args[0];
6266
6267            // Validate closure structure
6268            if !matches!(closure.kind, ExprKind::Lambda { .. }) {
6269                return Err(InterpreterError::RuntimeError(
6270                    "DataFrame.filter() expects a lambda expression".to_string(),
6271                ));
6272            }
6273
6274            // Build keep_mask by evaluating closure for each row
6275            let num_rows = columns.first().map_or(0, |c| c.values.len());
6276            let mut keep_mask = Vec::with_capacity(num_rows);
6277
6278            for row_idx in 0..num_rows {
6279                // Create row object with all column values for this row
6280                let mut row = HashMap::new();
6281                for col in columns {
6282                    if let Some(value) = col.values.get(row_idx) {
6283                        row.insert(col.name.clone(), value.clone());
6284                    }
6285                }
6286                let row_value = Value::Object(std::sync::Arc::new(row));
6287
6288                // Evaluate closure with row object
6289                let result = self.eval_closure_with_value(closure, &row_value)?;
6290
6291                // Check if result is boolean
6292                let keep = match result {
6293                    Value::Bool(b) => b,
6294                    _ => {
6295                        return Err(InterpreterError::RuntimeError(
6296                            "DataFrame.filter() closure must return boolean".to_string(),
6297                        ))
6298                    }
6299                };
6300
6301                keep_mask.push(keep);
6302            }
6303
6304            // Create new DataFrame with filtered rows
6305            let mut new_columns = Vec::new();
6306            for col in columns {
6307                let mut filtered_values = Vec::new();
6308                for (idx, &keep) in keep_mask.iter().enumerate() {
6309                    if keep {
6310                        if let Some(val) = col.values.get(idx) {
6311                            filtered_values.push(val.clone());
6312                        }
6313                    }
6314                }
6315                new_columns.push(DataFrameColumn {
6316                    name: col.name.clone(),
6317                    values: filtered_values,
6318                });
6319            }
6320
6321            Ok(Value::DataFrame {
6322                columns: new_columns,
6323            })
6324        } else {
6325            Err(InterpreterError::RuntimeError(
6326                "filter method can only be called on DataFrame".to_string(),
6327            ))
6328        }
6329    }
6330
6331    /// Special handler for `DataFrame` `with_column` method
6332    /// Complexity: 9 (within Toyota Way limits)
6333    fn eval_dataframe_with_column_method(
6334        &mut self,
6335        receiver: &Value,
6336        args: &[Expr],
6337    ) -> Result<Value, InterpreterError> {
6338        if args.len() != 2 {
6339            return Err(InterpreterError::RuntimeError(
6340                "DataFrame.with_column() requires exactly 2 arguments (name, closure)".to_string(),
6341            ));
6342        }
6343
6344        // Evaluate the column name
6345        let col_name = match self.eval_expr(&args[0])? {
6346            Value::String(s) => s.to_string(),
6347            _ => {
6348                return Err(InterpreterError::RuntimeError(
6349                    "DataFrame.with_column() expects string column name".to_string(),
6350                ))
6351            }
6352        };
6353
6354        if let Value::DataFrame { columns } = receiver {
6355            let closure = &args[1];
6356
6357            // Extract parameter name from closure
6358            let param_name = if let ExprKind::Lambda { params, .. } = &closure.kind {
6359                if params.len() != 1 {
6360                    return Err(InterpreterError::RuntimeError(
6361                        "with_column closure must have exactly 1 parameter".to_string(),
6362                    ));
6363                }
6364                match &params[0].pattern {
6365                    crate::frontend::ast::Pattern::Identifier(name) => name.clone(),
6366                    _ => {
6367                        return Err(InterpreterError::RuntimeError(
6368                            "with_column closure must have simple identifier parameter".to_string(),
6369                        ))
6370                    }
6371                }
6372            } else {
6373                return Err(InterpreterError::RuntimeError(
6374                    "Expected lambda expression".to_string(),
6375                ));
6376            };
6377
6378            // Check if parameter name matches a column
6379            let matching_col = columns.iter().find(|c| c.name == param_name);
6380
6381            let mut new_values = Vec::new();
6382            let num_rows = columns.first().map_or(0, |c| c.values.len());
6383
6384            for row_idx in 0..num_rows {
6385                let value_to_bind = if let Some(col) = matching_col {
6386                    // Parameter name matches a column - bind that column's value
6387                    col.values.get(row_idx).cloned().unwrap_or(Value::Nil)
6388                } else {
6389                    // Parameter name doesn't match - bind full row object
6390                    let mut row = HashMap::new();
6391                    for col in columns {
6392                        if let Some(value) = col.values.get(row_idx) {
6393                            row.insert(col.name.clone(), value.clone());
6394                        }
6395                    }
6396                    Value::Object(std::sync::Arc::new(row))
6397                };
6398
6399                // Evaluate closure with the appropriate value
6400                let result = self.eval_closure_with_value(closure, &value_to_bind)?;
6401                new_values.push(result);
6402            }
6403
6404            // Create new DataFrame with additional column
6405            let mut new_columns = columns.clone();
6406            new_columns.push(crate::runtime::DataFrameColumn {
6407                name: col_name,
6408                values: new_values,
6409            });
6410
6411            Ok(Value::DataFrame {
6412                columns: new_columns,
6413            })
6414        } else {
6415            Err(InterpreterError::RuntimeError(
6416                "with_column method can only be called on DataFrame".to_string(),
6417            ))
6418        }
6419    }
6420
6421    /// Special handler for `DataFrame` transform method
6422    /// Complexity: 9 (within Toyota Way limits)
6423    fn eval_dataframe_transform_method(
6424        &mut self,
6425        receiver: &Value,
6426        args: &[Expr],
6427    ) -> Result<Value, InterpreterError> {
6428        if args.len() != 2 {
6429            return Err(InterpreterError::RuntimeError(
6430                "DataFrame.transform() requires exactly 2 arguments (column, closure)".to_string(),
6431            ));
6432        }
6433
6434        // Evaluate the column name
6435        let col_name = match self.eval_expr(&args[0])? {
6436            Value::String(s) => s.to_string(),
6437            _ => {
6438                return Err(InterpreterError::RuntimeError(
6439                    "DataFrame.transform() expects string column name".to_string(),
6440                ))
6441            }
6442        };
6443
6444        if let Value::DataFrame { columns } = receiver {
6445            // Find the column to transform
6446            let col_idx = columns
6447                .iter()
6448                .position(|c| c.name == col_name)
6449                .ok_or_else(|| {
6450                    InterpreterError::RuntimeError(format!(
6451                        "Column '{col_name}' not found in DataFrame"
6452                    ))
6453                })?;
6454
6455            let closure = &args[1];
6456            let mut new_columns = columns.clone();
6457
6458            // Transform each value in the column
6459            let mut transformed_values = Vec::new();
6460            for value in &columns[col_idx].values {
6461                // Create a temporary environment with the value bound to the parameter
6462                let result = self.eval_closure_with_value(closure, value)?;
6463                transformed_values.push(result);
6464            }
6465
6466            new_columns[col_idx].values = transformed_values;
6467
6468            Ok(Value::DataFrame {
6469                columns: new_columns,
6470            })
6471        } else {
6472            Err(InterpreterError::RuntimeError(
6473                "transform method can only be called on DataFrame".to_string(),
6474            ))
6475        }
6476    }
6477
6478    /// Evaluate a closure with a single value argument
6479    /// Complexity: 7 (within Toyota Way limits)
6480    fn eval_closure_with_value(
6481        &mut self,
6482        closure_expr: &Expr,
6483        value: &Value,
6484    ) -> Result<Value, InterpreterError> {
6485        match &closure_expr.kind {
6486            ExprKind::Lambda { params, body, .. } => {
6487                if params.len() != 1 {
6488                    return Err(InterpreterError::RuntimeError(
6489                        "Transform closure must have exactly 1 parameter".to_string(),
6490                    ));
6491                }
6492
6493                // Extract parameter name from pattern
6494                let param_name = match &params[0].pattern {
6495                    crate::frontend::ast::Pattern::Identifier(name) => name.clone(),
6496                    _ => {
6497                        return Err(InterpreterError::RuntimeError(
6498                            "Transform closure must have simple identifier parameter".to_string(),
6499                        ))
6500                    }
6501                };
6502
6503                // Create new environment with parameter binding
6504                let mut new_env = HashMap::new();
6505                new_env.insert(param_name, value.clone());
6506
6507                // Push environment
6508                self.env_push(new_env);
6509
6510                // Evaluate the body
6511                let result = self.eval_expr(body)?;
6512
6513                // Pop environment
6514                self.env_pop();
6515
6516                Ok(result)
6517            }
6518            _ => Err(InterpreterError::RuntimeError(
6519                "Expected lambda expression".to_string(),
6520            )),
6521        }
6522    }
6523
6524    /// Compare two values using a comparison function
6525    fn compare_values<F>(
6526        &self,
6527        left: &Value,
6528        right: &Value,
6529        cmp: F,
6530    ) -> Result<Value, InterpreterError>
6531    where
6532        F: Fn(i64, i64) -> bool,
6533    {
6534        match (left, right) {
6535            (Value::Integer(a), Value::Integer(b)) => Ok(Value::Bool(cmp(*a, *b))),
6536            (Value::Float(a), Value::Float(b)) => {
6537                // Convert float comparison to integer-like for simplicity
6538                let a_int = *a as i64;
6539                let b_int = *b as i64;
6540                Ok(Value::Bool(cmp(a_int, b_int)))
6541            }
6542            (Value::Integer(a), Value::Float(b)) => {
6543                let b_int = *b as i64;
6544                Ok(Value::Bool(cmp(*a, b_int)))
6545            }
6546            (Value::Float(a), Value::Integer(b)) => {
6547                let a_int = *a as i64;
6548                Ok(Value::Bool(cmp(a_int, *b)))
6549            }
6550            _ => Err(InterpreterError::RuntimeError(format!(
6551                "Cannot compare {} and {}",
6552                left.type_name(),
6553                right.type_name()
6554            ))),
6555        }
6556    }
6557
6558    /// Check if two values are equal
6559    fn values_equal(&self, left: &Value, right: &Value) -> bool {
6560        match (left, right) {
6561            (Value::Integer(a), Value::Integer(b)) => a == b,
6562            (Value::Float(a), Value::Float(b)) => (a - b).abs() < f64::EPSILON,
6563            (Value::Bool(a), Value::Bool(b)) => a == b,
6564            (Value::String(a), Value::String(b)) => a == b,
6565            (Value::Nil, Value::Nil) => true,
6566            _ => false,
6567        }
6568    }
6569
6570    /// Evaluate an expression with column context (for `DataFrame` filtering)
6571    fn eval_expr_with_column_context(
6572        &mut self,
6573        expr: &Expr,
6574        columns: &[DataFrameColumn],
6575        row_idx: usize,
6576    ) -> Result<Value, InterpreterError> {
6577        match &expr.kind {
6578            // Special handling for function calls that might be col() references
6579            ExprKind::Call { func, args } => {
6580                if let ExprKind::Identifier(name) = &func.kind {
6581                    if name == "col" && args.len() == 1 {
6582                        // This is a col("column_name") call - resolve to actual column value
6583                        let col_name_expr = &args[0];
6584                        if let ExprKind::Literal(crate::frontend::ast::Literal::String(col_name)) =
6585                            &col_name_expr.kind
6586                        {
6587                            // Find the column and return the value for this row
6588                            for col in columns {
6589                                if col.name == *col_name {
6590                                    if let Some(value) = col.values.get(row_idx) {
6591                                        return Ok(value.clone());
6592                                    }
6593                                    return Err(InterpreterError::RuntimeError(format!(
6594                                        "Row index {} out of bounds for column '{}'",
6595                                        row_idx, col_name
6596                                    )));
6597                                }
6598                            }
6599                            return Err(InterpreterError::RuntimeError(format!(
6600                                "Column '{}' not found",
6601                                col_name
6602                            )));
6603                        }
6604                    }
6605                }
6606                // Fall back to normal function call evaluation
6607                self.eval_expr(expr)
6608            }
6609            // Handle binary expressions that might need column context
6610            ExprKind::Binary { left, right, .. } => {
6611                let left_val = self.eval_expr_with_column_context(left, columns, row_idx)?;
6612                let right_val = self.eval_expr_with_column_context(right, columns, row_idx)?;
6613
6614                // Rebuild the binary expression with resolved values and evaluate
6615                // For simplicity, handle common comparison operations directly
6616                if let ExprKind::Binary { op, .. } = &expr.kind {
6617                    match op {
6618                        crate::frontend::ast::BinaryOp::Greater => {
6619                            self.compare_values(&left_val, &right_val, |a, b| a > b)
6620                        }
6621                        crate::frontend::ast::BinaryOp::Less => {
6622                            self.compare_values(&left_val, &right_val, |a, b| a < b)
6623                        }
6624                        crate::frontend::ast::BinaryOp::Equal => {
6625                            Ok(Value::Bool(self.values_equal(&left_val, &right_val)))
6626                        }
6627                        crate::frontend::ast::BinaryOp::NotEqual => {
6628                            Ok(Value::Bool(!self.values_equal(&left_val, &right_val)))
6629                        }
6630                        _ => self.eval_expr(expr), // Use regular evaluation for other operators
6631                    }
6632                } else {
6633                    unreachable!()
6634                }
6635            }
6636            // For all other expressions, use normal evaluation
6637            _ => self.eval_expr(expr),
6638        }
6639    }
6640
6641    fn eval_dataframe_operation(
6642        &mut self,
6643        source: &Expr,
6644        operation: &crate::frontend::ast::DataFrameOp,
6645    ) -> Result<Value, InterpreterError> {
6646        let source_value = self.eval_expr(source)?;
6647
6648        if let Value::DataFrame { columns } = source_value {
6649            crate::runtime::eval_dataframe_ops::eval_dataframe_operation(
6650                columns,
6651                operation,
6652                |expr, cols, idx| self.eval_expr_with_column_context(expr, cols, idx),
6653            )
6654        } else {
6655            Err(InterpreterError::RuntimeError(
6656                "DataFrameOperation can only be applied to DataFrame values".to_string(),
6657            ))
6658        }
6659    }
6660
6661    /// Evaluate string interpolation
6662    fn eval_string_interpolation(
6663        &mut self,
6664        parts: &[StringPart],
6665    ) -> Result<Value, InterpreterError> {
6666        use crate::runtime::eval_string_interpolation::format_value_for_interpolation;
6667
6668        let mut result = String::new();
6669        for part in parts {
6670            match part {
6671                StringPart::Text(text) => result.push_str(text),
6672                StringPart::Expr(expr) => {
6673                    let value = self.eval_expr(expr)?;
6674                    // Use format_value_for_interpolation to avoid adding quotes to strings
6675                    result.push_str(&format_value_for_interpolation(&value));
6676                }
6677                StringPart::ExprWithFormat { expr, format_spec } => {
6678                    let value = self.eval_expr(expr)?;
6679                    // Apply format specifier for interpreter
6680                    let formatted = Self::format_value_with_spec(&value, format_spec);
6681                    result.push_str(&formatted);
6682                }
6683            }
6684        }
6685        Ok(Value::from_string(result))
6686    }
6687
6688    /// Format a value with a format specifier like :.2 for floats
6689    fn format_value_with_spec(value: &Value, spec: &str) -> String {
6690        // Parse format specifier (e.g., ":.2" -> precision 2)
6691        if let Some(stripped) = spec.strip_prefix(":.") {
6692            if let Ok(precision) = stripped.parse::<usize>() {
6693                match value {
6694                    Value::Float(f) => return format!("{:.precision$}", f, precision = precision),
6695                    Value::Integer(i) => {
6696                        return format!("{:.precision$}", *i as f64, precision = precision)
6697                    }
6698                    _ => {}
6699                }
6700            }
6701        }
6702        // Default formatting if spec doesn't match or isn't supported
6703        value.to_string()
6704    }
6705
6706    /// Evaluate function definition
6707    fn eval_function(
6708        &mut self,
6709        name: &str,
6710        params: &[Param],
6711        body: &Expr,
6712    ) -> Result<Value, InterpreterError> {
6713        let param_names: Vec<String> = params
6714            .iter()
6715            .map(crate::frontend::ast::Param::name)
6716            .collect();
6717
6718        let closure = Value::Closure {
6719            params: param_names,
6720            body: Arc::new(body.clone()),
6721            env: Arc::new(self.current_env().clone()),
6722        };
6723
6724        // Bind function name in environment for recursion
6725        self.env_set(name.to_string(), closure.clone());
6726        Ok(closure)
6727    }
6728
6729    /// Evaluate lambda expression
6730    fn eval_lambda(&mut self, params: &[Param], body: &Expr) -> Result<Value, InterpreterError> {
6731        eval_func::eval_lambda(params, body, self.current_env())
6732    }
6733
6734    /// Evaluate function call
6735    fn eval_function_call(
6736        &mut self,
6737        func: &Expr,
6738        args: &[Expr],
6739    ) -> Result<Value, InterpreterError> {
6740        // Handle static method calls: Type::method(args)
6741        // Parser represents these as Call { func: FieldAccess { object: Identifier("Type"), field: "method" }, args }
6742        if let ExprKind::FieldAccess { object, field } = &func.kind {
6743            if let ExprKind::Identifier(type_name) = &object.kind {
6744                // Detect Box::new(value) static method
6745                if type_name == "Box" && field == "new" {
6746                    if args.len() != 1 {
6747                        return Err(InterpreterError::RuntimeError(format!(
6748                            "Box::new() requires exactly 1 argument, got {}",
6749                            args.len()
6750                        )));
6751                    }
6752                    // Box::new(value) → just return the value (Box is transparent in Ruchy)
6753                    return self.eval_expr(&args[0]);
6754                }
6755                // Detect Vec::new() static method
6756                if type_name == "Vec" && field == "new" {
6757                    if !args.is_empty() {
6758                        return Err(InterpreterError::RuntimeError(format!(
6759                            "Vec::new() takes no arguments, got {}",
6760                            args.len()
6761                        )));
6762                    }
6763                    // Vec::new() → empty array
6764                    return Ok(Value::Array(Arc::from([])));
6765                }
6766
6767                // REGRESSION-077: Check for user-defined struct impl methods
6768                // impl methods are stored with qualified names like "Logger::new_with_options"
6769                let qualified_method = format!("{}::{}", type_name, field);
6770                if let Ok(method_value) = self.lookup_variable(&qualified_method) {
6771                    // Found impl method - evaluate args and call it
6772                    let arg_vals: Result<Vec<Value>, InterpreterError> =
6773                        args.iter().map(|arg| self.eval_expr(arg)).collect();
6774                    let arg_vals = arg_vals?;
6775                    return self.call_function(method_value, &arg_vals);
6776                }
6777            }
6778        }
6779
6780        // Try to evaluate the function normally
6781        let func_val_result = self.eval_expr(func);
6782
6783        // If function lookup fails and it's an identifier, treat it as a message constructor
6784        let func_val = match func_val_result {
6785            Ok(val) => val,
6786            Err(InterpreterError::RuntimeError(msg)) if msg.starts_with("Undefined variable:") => {
6787                // Check if this is an identifier that could be a message constructor
6788                if let ExprKind::Identifier(name) = &func.kind {
6789                    // Create a message object
6790                    let arg_vals: Result<Vec<Value>, InterpreterError> =
6791                        args.iter().map(|arg| self.eval_expr(arg)).collect();
6792                    let arg_vals = arg_vals?;
6793
6794                    let mut message = HashMap::new();
6795                    message.insert(
6796                        "__type".to_string(),
6797                        Value::from_string("Message".to_string()),
6798                    );
6799                    message.insert("type".to_string(), Value::from_string(name.clone()));
6800                    message.insert("data".to_string(), Value::Array(Arc::from(arg_vals)));
6801
6802                    return Ok(Value::Object(Arc::new(message)));
6803                }
6804                return Err(InterpreterError::RuntimeError(msg));
6805            }
6806            Err(e) => return Err(e),
6807        };
6808
6809        let arg_vals: Result<Vec<Value>, InterpreterError> =
6810            args.iter().map(|arg| self.eval_expr(arg)).collect();
6811        let arg_vals = arg_vals?;
6812
6813        // Special handling for enum variant construction with arguments (tuple variants)
6814        if let Value::EnumVariant { enum_name, variant_name, data: _ } = func_val {
6815            // This is a tuple variant constructor: Response::Error("msg")
6816            return Ok(Value::EnumVariant {
6817                enum_name,
6818                variant_name,
6819                data: Some(arg_vals),
6820            });
6821        }
6822
6823        let result = self.call_function(func_val, &arg_vals)?;
6824
6825        // Collect type feedback for function call
6826        let site_id = func.span.start; // Use func span start as site ID
6827        let func_name = match &func.kind {
6828            ExprKind::Identifier(name) => name.clone(),
6829            _ => "anonymous".to_string(),
6830        };
6831        self.record_function_call_feedback(site_id, &func_name, &arg_vals, &result);
6832        Ok(result)
6833    }
6834
6835    /// Push an error handling scope for try/catch blocks
6836    ///
6837    /// # Complexity
6838    /// Cyclomatic complexity: 1
6839    pub fn push_error_scope(&mut self) {
6840        self.error_scopes.push(ErrorScope {
6841            env_depth: self.env_stack.len(),
6842        });
6843    }
6844
6845    /// Pop an error handling scope
6846    ///
6847    /// # Complexity
6848    /// Cyclomatic complexity: 1
6849    pub fn pop_error_scope(&mut self) {
6850        self.error_scopes.pop();
6851    }
6852
6853    /// Set a variable in the current scope
6854    ///
6855    /// # Complexity
6856    /// Cyclomatic complexity: 1
6857    pub fn set_variable(&mut self, name: &str, value: Value) {
6858        // ISSUE-040 FIX: Use env_set_mut to search parent scopes for existing variables
6859        self.env_set_mut(name.to_string(), value);
6860    }
6861
6862    /// Get a variable from the environment stack
6863    ///
6864    /// Searches the environment stack from innermost to outermost scope.
6865    /// Returns None if the variable is not found.
6866    pub fn get_variable(&self, name: &str) -> Option<Value> {
6867        // Search from innermost to outermost scope
6868        for env in self.env_stack.iter().rev() {
6869            if let Some(value) = env.get(name) {
6870                return Some(value.clone());
6871            }
6872        }
6873        None
6874    }
6875
6876    /// Pattern matching for try/catch
6877    ///
6878    /// # Complexity
6879    /// Cyclomatic complexity: 8 (delegates to existing pattern matcher)
6880    pub fn pattern_matches(
6881        &mut self,
6882        pattern: &Pattern,
6883        value: &Value,
6884    ) -> Result<bool, InterpreterError> {
6885        // Simplified pattern matching for try/catch
6886        match pattern {
6887            Pattern::Identifier(_) => Ok(true), // Always matches
6888            Pattern::Wildcard => Ok(true),
6889            Pattern::Literal(literal) => Ok(self.literal_matches(literal, value)),
6890            _ => Ok(false), // Other patterns not yet supported
6891        }
6892    }
6893
6894    fn literal_matches(&self, literal: &Literal, value: &Value) -> bool {
6895        match (literal, value) {
6896            (Literal::Integer(a, _), Value::Integer(b)) => a == b,
6897            (Literal::Float(a), Value::Float(b)) => (a - b).abs() < f64::EPSILON,
6898            (Literal::String(a), Value::String(b)) => a == b.as_ref(),
6899            (Literal::Bool(a), Value::Bool(b)) => a == b,
6900            _ => false,
6901        }
6902    }
6903
6904    // ========================================================================
6905    // EXTREME TDD: stdout Capture for WASM/REPL
6906    // Bug: https://github.com/paiml/ruchy/issues/PRINTLN_STDOUT
6907    // ========================================================================
6908
6909    /// Capture println output to stdout buffer
6910    /// Complexity: 1 (single operation)
6911    ///
6912    /// # Examples
6913    ///
6914    /// ```
6915    /// use ruchy::runtime::interpreter::Interpreter;
6916    ///
6917    /// let mut interpreter = Interpreter::new();
6918    /// interpreter.capture_stdout("Hello, World!".to_string());
6919    /// assert_eq!(interpreter.get_stdout(), "Hello, World!");
6920    /// ```
6921    pub fn capture_stdout(&mut self, output: String) {
6922        self.stdout_buffer.push(output);
6923    }
6924
6925    /// Get captured stdout as a single string with newlines
6926    /// Complexity: 2 (join + conditional)
6927    ///
6928    /// # Examples
6929    ///
6930    /// ```
6931    /// use ruchy::runtime::interpreter::Interpreter;
6932    ///
6933    /// let mut interpreter = Interpreter::new();
6934    /// interpreter.capture_stdout("Line 1".to_string());
6935    /// interpreter.capture_stdout("Line 2".to_string());
6936    /// assert_eq!(interpreter.get_stdout(), "Line 1\nLine 2");
6937    /// ```
6938    pub fn get_stdout(&self) -> String {
6939        self.stdout_buffer.join("\n")
6940    }
6941
6942    /// Clear stdout buffer
6943    /// Complexity: 1 (single operation)
6944    ///
6945    /// # Examples
6946    ///
6947    /// ```
6948    /// use ruchy::runtime::interpreter::Interpreter;
6949    ///
6950    /// let mut interpreter = Interpreter::new();
6951    /// interpreter.capture_stdout("test".to_string());
6952    /// interpreter.clear_stdout();
6953    /// assert_eq!(interpreter.get_stdout(), "");
6954    /// ```
6955    pub fn clear_stdout(&mut self) {
6956        self.stdout_buffer.clear();
6957    }
6958
6959    /// Check if stdout has any captured output
6960    /// Complexity: 1 (single check)
6961    pub fn has_stdout(&self) -> bool {
6962        !self.stdout_buffer.is_empty()
6963    }
6964}
6965
6966impl Default for Interpreter {
6967    fn default() -> Self {
6968        Self::new()
6969    }
6970}
6971
6972/// Binary operations
6973#[derive(Debug, Clone, Copy)]
6974pub enum BinaryOp {
6975    Add,
6976    Sub,
6977    Mul,
6978    Div,
6979    Eq,
6980    Lt,
6981    Gt,
6982}
6983
6984#[cfg(test)]
6985#[allow(clippy::expect_used)] // Tests can use expect for clarity
6986#[allow(clippy::bool_assert_comparison)] // Clear test assertions
6987#[allow(clippy::approx_constant)] // Test constants are acceptable
6988#[allow(clippy::panic)] // Tests can panic on assertion failures
6989mod tests {
6990    use super::*;
6991
6992    #[test]
6993    fn test_value_creation() {
6994        let int_val = Value::from_i64(42);
6995        assert_eq!(int_val.as_i64().expect("Should be integer"), 42);
6996        assert_eq!(int_val.type_name(), "integer");
6997
6998        let bool_val = Value::from_bool(true);
6999        assert_eq!(bool_val.as_bool().expect("Should be boolean"), true);
7000        assert_eq!(bool_val.type_name(), "boolean");
7001
7002        let nil_val = Value::nil();
7003        assert!(nil_val.is_nil());
7004        assert_eq!(nil_val.type_name(), "nil");
7005
7006        let float_val = Value::from_f64(3.14);
7007        let f_value = float_val.as_f64().expect("Should be float");
7008        assert!((f_value - 3.14).abs() < f64::EPSILON);
7009        assert_eq!(float_val.type_name(), "float");
7010
7011        let string_val = Value::from_string("hello".to_string());
7012        assert_eq!(string_val.type_name(), "string");
7013    }
7014
7015    #[test]
7016    fn test_arithmetic() {
7017        let mut interp = Interpreter::new();
7018
7019        // Test 2 + 3 = 5
7020        assert!(interp.push(Value::from_i64(2)).is_ok());
7021        assert!(interp.push(Value::from_i64(3)).is_ok());
7022        assert!(interp.binary_op(BinaryOp::Add).is_ok());
7023
7024        let result = interp.pop().expect("Stack should not be empty");
7025        assert_eq!(result, Value::Integer(5));
7026    }
7027
7028    #[test]
7029    fn test_mixed_arithmetic() {
7030        let mut interp = Interpreter::new();
7031
7032        // Test 2 + 3.5 = 5.5 (int + float -> float)
7033        assert!(interp.push(Value::from_i64(2)).is_ok());
7034        assert!(interp.push(Value::from_f64(3.5)).is_ok());
7035        assert!(interp.binary_op(BinaryOp::Add).is_ok());
7036
7037        let result = interp.pop().expect("Stack should not be empty");
7038        match result {
7039            Value::Float(f) => assert!((f - 5.5).abs() < f64::EPSILON),
7040            _ => unreachable!("Expected float, got {result:?}"),
7041        }
7042    }
7043}
7044
7045#[cfg(test)]
7046mod lambda_tests {
7047    use super::*;
7048
7049    #[test]
7050    fn test_lambda_variable_assignment_and_call() {
7051        let code = r"
7052            let double = x => x * 2
7053            double(5)
7054        ";
7055        let mut parser = crate::frontend::parser::Parser::new(code);
7056        let ast = parser.parse().expect("Parse failed");
7057        let mut interpreter = Interpreter::new();
7058        let result = interpreter.eval_expr(&ast).expect("Eval failed");
7059        assert_eq!(result, Value::Integer(10));
7060    }
7061
7062    #[test]
7063    fn test_lambda_pipe_syntax_variable_call() {
7064        let code = r"
7065            let triple = |x| x * 3
7066            triple(4)
7067        ";
7068        let mut parser = crate::frontend::parser::Parser::new(code);
7069        let ast = parser.parse().expect("Parse failed");
7070        let mut interpreter = Interpreter::new();
7071        let result = interpreter.eval_expr(&ast).expect("Eval failed");
7072        assert_eq!(result, Value::Integer(12));
7073    }
7074}
7075
7076#[cfg(test)]
7077mod negative_indexing_tests {
7078    use super::*;
7079
7080    // FEATURE-042 (GitHub Issue #46): Negative indexing tests
7081
7082    #[test]
7083    fn test_negative_array_indexing_last_element() {
7084        let code = r#"
7085            let fruits = ["apple", "banana", "cherry"]
7086            fruits[-1]
7087        "#;
7088        let mut parser = crate::frontend::parser::Parser::new(code);
7089        let ast = parser.parse().expect("Parse failed");
7090        let mut interpreter = Interpreter::new();
7091        let result = interpreter.eval_expr(&ast).expect("Eval failed");
7092        assert_eq!(result, Value::from_string("cherry".to_string()));
7093    }
7094
7095    #[test]
7096    fn test_negative_array_indexing_second_to_last() {
7097        let code = r#"
7098            let fruits = ["apple", "banana", "cherry"]
7099            fruits[-2]
7100        "#;
7101        let mut parser = crate::frontend::parser::Parser::new(code);
7102        let ast = parser.parse().expect("Parse failed");
7103        let mut interpreter = Interpreter::new();
7104        let result = interpreter.eval_expr(&ast).expect("Eval failed");
7105        assert_eq!(result, Value::from_string("banana".to_string()));
7106    }
7107
7108    #[test]
7109    fn test_negative_array_indexing_first_element() {
7110        let code = r#"
7111            let fruits = ["apple", "banana", "cherry"]
7112            fruits[-3]
7113        "#;
7114        let mut parser = crate::frontend::parser::Parser::new(code);
7115        let ast = parser.parse().expect("Parse failed");
7116        let mut interpreter = Interpreter::new();
7117        let result = interpreter.eval_expr(&ast).expect("Eval failed");
7118        assert_eq!(result, Value::from_string("apple".to_string()));
7119    }
7120
7121    #[test]
7122    fn test_negative_array_indexing_out_of_bounds() {
7123        let code = r#"
7124            let fruits = ["apple", "banana"]
7125            fruits[-5]
7126        "#;
7127        let mut parser = crate::frontend::parser::Parser::new(code);
7128        let ast = parser.parse().expect("Parse failed");
7129        let mut interpreter = Interpreter::new();
7130        let result = interpreter.eval_expr(&ast);
7131        assert!(result.is_err(), "Should fail for out-of-bounds negative index");
7132    }
7133
7134    #[test]
7135    fn test_negative_string_indexing() {
7136        let code = r#"
7137            let word = "hello"
7138            word[-1]
7139        "#;
7140        let mut parser = crate::frontend::parser::Parser::new(code);
7141        let ast = parser.parse().expect("Parse failed");
7142        let mut interpreter = Interpreter::new();
7143        let result = interpreter.eval_expr(&ast).expect("Eval failed");
7144        assert_eq!(result, Value::from_string("o".to_string()));
7145    }
7146
7147    #[test]
7148    fn test_negative_tuple_indexing() {
7149        let code = r#"
7150            let point = (10, 20, 30)
7151            point[-1]
7152        "#;
7153        let mut parser = crate::frontend::parser::Parser::new(code);
7154        let ast = parser.parse().expect("Parse failed");
7155        let mut interpreter = Interpreter::new();
7156        let result = interpreter.eval_expr(&ast).expect("Eval failed");
7157        assert_eq!(result, Value::Integer(30));
7158    }
7159
7160    #[test]
7161    fn test_negative_indexing_with_integers() {
7162        let code = r#"
7163            let numbers = [100, 200, 300, 400]
7164            numbers[-2]
7165        "#;
7166        let mut parser = crate::frontend::parser::Parser::new(code);
7167        let ast = parser.parse().expect("Parse failed");
7168        let mut interpreter = Interpreter::new();
7169        let result = interpreter.eval_expr(&ast).expect("Eval failed");
7170        assert_eq!(result, Value::Integer(300));
7171    }
7172}
7173
7174// Tests removed - moved to separate test files