aether/
evaluator.rs

1// src/evaluator.rs
2//! Evaluator for executing Aether AST
3
4use crate::ast::{BinOp, Expr, Program, Stmt, UnaryOp};
5use crate::builtins::BuiltInRegistry;
6use crate::environment::Environment;
7use crate::module_system::{
8    DisabledModuleResolver, ModuleContext, ModuleResolveError, ModuleResolver, ResolvedModule,
9};
10use crate::value::{GeneratorState, Value};
11use serde_json::{Value as JsonValue, json};
12use std::cell::RefCell;
13use std::collections::HashMap;
14use std::collections::VecDeque;
15use std::rc::Rc;
16
17#[derive(Debug, Clone, PartialEq)]
18pub struct CallFrame {
19    pub name: String,
20    pub signature: String,
21}
22
23#[derive(Debug, Clone, PartialEq)]
24pub enum ImportErrorKind {
25    ImportDisabled,
26    InvalidSpecifier,
27    NoBaseDir,
28    NotFound,
29    AccessDenied,
30    IoError,
31    NotExported,
32    CircularImport,
33    ParseFailed,
34}
35
36#[derive(Debug, Clone, PartialEq)]
37pub struct ImportError {
38    pub kind: ImportErrorKind,
39    pub specifier: String,
40    pub detail: Option<String>,
41    pub symbol: Option<String>,
42    pub module_id: Option<String>,
43    pub import_chain: Vec<String>,
44    pub cycle: Option<Vec<String>>,
45}
46
47impl ImportError {
48    fn from_resolve_error(
49        specifier: &str,
50        err: ModuleResolveError,
51        import_chain: Vec<String>,
52    ) -> Self {
53        match err {
54            ModuleResolveError::ImportDisabled => ImportError {
55                kind: ImportErrorKind::ImportDisabled,
56                specifier: specifier.to_string(),
57                detail: None,
58                symbol: None,
59                module_id: None,
60                import_chain,
61                cycle: None,
62            },
63            ModuleResolveError::InvalidSpecifier(s) => ImportError {
64                kind: ImportErrorKind::InvalidSpecifier,
65                specifier: specifier.to_string(),
66                detail: Some(s),
67                symbol: None,
68                module_id: None,
69                import_chain,
70                cycle: None,
71            },
72            ModuleResolveError::NoBaseDir(s) => ImportError {
73                kind: ImportErrorKind::NoBaseDir,
74                specifier: specifier.to_string(),
75                detail: Some(s),
76                symbol: None,
77                module_id: None,
78                import_chain,
79                cycle: None,
80            },
81            ModuleResolveError::NotFound(s) => ImportError {
82                kind: ImportErrorKind::NotFound,
83                specifier: specifier.to_string(),
84                detail: Some(s),
85                symbol: None,
86                module_id: None,
87                import_chain,
88                cycle: None,
89            },
90            ModuleResolveError::AccessDenied(s) => ImportError {
91                kind: ImportErrorKind::AccessDenied,
92                specifier: specifier.to_string(),
93                detail: Some(s),
94                symbol: None,
95                module_id: None,
96                import_chain,
97                cycle: None,
98            },
99            ModuleResolveError::IoError(s) => ImportError {
100                kind: ImportErrorKind::IoError,
101                specifier: specifier.to_string(),
102                detail: Some(s),
103                symbol: None,
104                module_id: None,
105                import_chain,
106                cycle: None,
107            },
108        }
109    }
110
111    fn not_exported(specifier: &str, symbol: &str, import_chain: Vec<String>) -> Self {
112        ImportError {
113            kind: ImportErrorKind::NotExported,
114            specifier: specifier.to_string(),
115            detail: None,
116            symbol: Some(symbol.to_string()),
117            module_id: None,
118            import_chain,
119            cycle: None,
120        }
121    }
122
123    fn circular(module_id: &str, cycle: Vec<String>, import_chain: Vec<String>) -> Self {
124        ImportError {
125            kind: ImportErrorKind::CircularImport,
126            specifier: module_id.to_string(),
127            detail: None,
128            symbol: None,
129            module_id: Some(module_id.to_string()),
130            import_chain,
131            cycle: Some(cycle),
132        }
133    }
134
135    fn parse_failed(module_id: &str, detail: String, import_chain: Vec<String>) -> Self {
136        ImportError {
137            kind: ImportErrorKind::ParseFailed,
138            specifier: module_id.to_string(),
139            detail: Some(detail),
140            symbol: None,
141            module_id: Some(module_id.to_string()),
142            import_chain,
143            cycle: None,
144        }
145    }
146}
147
148/// Runtime errors
149#[derive(Debug, Clone, PartialEq)]
150pub enum RuntimeError {
151    /// Variable not found
152    UndefinedVariable(String),
153
154    /// Type mismatch - simple message
155    TypeError(String),
156
157    /// Type mismatch - detailed version
158    TypeErrorDetailed { expected: String, got: String },
159
160    /// Invalid operation
161    InvalidOperation(String),
162
163    /// Division by zero
164    DivisionByZero,
165
166    /// Function not found or not callable
167    NotCallable(String),
168
169    /// Wrong number of arguments
170    WrongArity { expected: usize, got: usize },
171
172    /// Return statement (used for control flow)
173    Return(Value),
174
175    /// Yield statement (used for generators)
176    Yield(Value),
177
178    /// Break statement (used for loop control)
179    Break,
180
181    /// Continue statement (used for loop control)
182    Continue,
183
184    /// Throw statement (user-thrown error)
185    Throw(Value),
186
187    /// Structured Import/Export module errors (with import chain)
188    ImportError(Box<ImportError>),
189
190    /// Attach a captured call stack to an error.
191    WithCallStack {
192        error: Box<RuntimeError>,
193        call_stack: Vec<CallFrame>,
194    },
195
196    /// Execution limit exceeded
197    ExecutionLimit(crate::runtime::ExecutionLimitError),
198
199    /// Custom error message (用于IO操作等)
200    CustomError(String),
201}
202
203impl std::fmt::Display for RuntimeError {
204    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
205        match self {
206            RuntimeError::UndefinedVariable(name) => write!(f, "Undefined variable: {}", name),
207            RuntimeError::TypeError(msg) => write!(f, "Type error: {}", msg),
208            RuntimeError::TypeErrorDetailed { expected, got } => {
209                write!(f, "Type error: expected {}, got {}", expected, got)
210            }
211            RuntimeError::InvalidOperation(msg) => write!(f, "Invalid operation: {}", msg),
212            RuntimeError::DivisionByZero => write!(f, "Division by zero"),
213            RuntimeError::NotCallable(name) => write!(f, "Not callable: {}", name),
214            RuntimeError::WrongArity { expected, got } => {
215                write!(
216                    f,
217                    "Wrong number of arguments: expected {}, got {}",
218                    expected, got
219                )
220            }
221            RuntimeError::Return(val) => write!(f, "Return: {}", val),
222            RuntimeError::Yield(val) => write!(f, "Yield: {}", val),
223            RuntimeError::Break => write!(f, "Break outside of loop"),
224            RuntimeError::Continue => write!(f, "Continue outside of loop"),
225            RuntimeError::Throw(val) => write!(f, "Throw: {}", val),
226            RuntimeError::ImportError(e) => {
227                let msg = match e.kind {
228                    ImportErrorKind::ImportDisabled => "Import is disabled".to_string(),
229                    ImportErrorKind::InvalidSpecifier => format!(
230                        "Invalid module specifier: {}",
231                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
232                    ),
233                    ImportErrorKind::NoBaseDir => format!(
234                        "No base directory to resolve specifier: {}",
235                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
236                    ),
237                    ImportErrorKind::NotFound => format!(
238                        "Module not found: {}",
239                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
240                    ),
241                    ImportErrorKind::AccessDenied => format!(
242                        "Module access denied: {}",
243                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
244                    ),
245                    ImportErrorKind::IoError => format!(
246                        "Module IO error: {}",
247                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
248                    ),
249                    ImportErrorKind::NotExported => format!(
250                        "'{}' is not exported by module {}",
251                        e.symbol.clone().unwrap_or_else(|| "<unknown>".to_string()),
252                        e.specifier
253                    ),
254                    ImportErrorKind::CircularImport => {
255                        let cycle = e.cycle.clone().unwrap_or_else(|| vec![e.specifier.clone()]);
256                        format!("circular import detected: {}", cycle.join(" -> "))
257                    }
258                    ImportErrorKind::ParseFailed => format!(
259                        "parse failed for module {}: {}",
260                        e.module_id.clone().unwrap_or_else(|| e.specifier.clone()),
261                        e.detail.clone().unwrap_or_else(|| "<unknown>".to_string())
262                    ),
263                };
264
265                write!(f, "Import error: {}", msg)?;
266                if !e.import_chain.is_empty() {
267                    write!(f, "\nImport chain: {}", e.import_chain.join(" -> "))?;
268                }
269                Ok(())
270            }
271            RuntimeError::WithCallStack { error, call_stack } => {
272                write!(f, "{}", error)?;
273                if !call_stack.is_empty() {
274                    let frames = call_stack
275                        .iter()
276                        .map(|fr| fr.signature.as_str())
277                        .collect::<Vec<_>>()
278                        .join(" -> ");
279                    write!(f, "\nCall stack: {}", frames)?;
280                }
281                Ok(())
282            }
283            RuntimeError::CustomError(msg) => write!(f, "{}", msg),
284            RuntimeError::ExecutionLimit(e) => write!(f, "{}", e),
285        }
286    }
287}
288
289impl std::error::Error for RuntimeError {}
290
291pub type EvalResult = Result<Value, RuntimeError>;
292
293/// A structured, machine-readable error report.
294///
295/// This is intended for CLI/host integrations that need stable fields
296/// (instead of parsing human-readable error strings).
297#[derive(Debug, Clone, PartialEq)]
298pub struct ErrorReport {
299    pub phase: String,
300    pub kind: String,
301    pub message: String,
302    pub import_chain: Vec<String>,
303    pub call_stack: Vec<CallFrame>,
304}
305
306impl ErrorReport {
307    pub fn io_error(message: impl Into<String>) -> Self {
308        ErrorReport {
309            phase: "io".to_string(),
310            kind: "IoError".to_string(),
311            message: message.into(),
312            import_chain: Vec::new(),
313            call_stack: Vec::new(),
314        }
315    }
316
317    pub fn parse_error(message: impl Into<String>) -> Self {
318        ErrorReport {
319            phase: "parse".to_string(),
320            kind: "ParseError".to_string(),
321            message: message.into(),
322            import_chain: Vec::new(),
323            call_stack: Vec::new(),
324        }
325    }
326
327    pub fn to_json_value(&self) -> JsonValue {
328        let call_stack = self
329            .call_stack
330            .iter()
331            .map(|fr| json!({"name": fr.name, "signature": fr.signature}))
332            .collect::<Vec<_>>();
333
334        json!({
335            "phase": self.phase,
336            "kind": self.kind,
337            "message": self.message,
338            "import_chain": self.import_chain,
339            "call_stack": call_stack,
340        })
341    }
342
343    pub fn to_json_pretty(&self) -> String {
344        serde_json::to_string_pretty(&self.to_json_value()).unwrap_or_else(|_| {
345            "{\n  \"error\": \"failed to serialize ErrorReport\"\n}".to_string()
346        })
347    }
348}
349
350impl RuntimeError {
351    fn peel_call_stack(&self) -> (&RuntimeError, Vec<CallFrame>) {
352        let mut current = self;
353        let mut frames: Vec<CallFrame> = Vec::new();
354
355        while let RuntimeError::WithCallStack { error, call_stack } = current {
356            if frames.is_empty() {
357                frames = call_stack.clone();
358            }
359            current = error.as_ref();
360        }
361
362        (current, frames)
363    }
364
365    fn kind_name(&self) -> String {
366        match self {
367            RuntimeError::UndefinedVariable(_) => "UndefinedVariable",
368            RuntimeError::TypeError(_) | RuntimeError::TypeErrorDetailed { .. } => "TypeError",
369            RuntimeError::InvalidOperation(_) => "InvalidOperation",
370            RuntimeError::DivisionByZero => "DivisionByZero",
371            RuntimeError::NotCallable(_) => "NotCallable",
372            RuntimeError::WrongArity { .. } => "WrongArity",
373            RuntimeError::Return(_) => "Return",
374            RuntimeError::Yield(_) => "Yield",
375            RuntimeError::Break => "Break",
376            RuntimeError::Continue => "Continue",
377            RuntimeError::Throw(_) => "Throw",
378            RuntimeError::ImportError(e) => match e.kind {
379                ImportErrorKind::ImportDisabled => "ImportDisabled",
380                ImportErrorKind::InvalidSpecifier => "InvalidSpecifier",
381                ImportErrorKind::NoBaseDir => "NoBaseDir",
382                ImportErrorKind::NotFound => "NotFound",
383                ImportErrorKind::AccessDenied => "AccessDenied",
384                ImportErrorKind::IoError => "IoError",
385                ImportErrorKind::NotExported => "NotExported",
386                ImportErrorKind::CircularImport => "CircularImport",
387                ImportErrorKind::ParseFailed => "ParseFailed",
388            },
389            RuntimeError::WithCallStack { .. } => "WithCallStack",
390            RuntimeError::ExecutionLimit(_) => "ExecutionLimit",
391            RuntimeError::CustomError(_) => "CustomError",
392        }
393        .to_string()
394    }
395
396    fn base_message(&self) -> String {
397        match self {
398            RuntimeError::WithCallStack { error, .. } => error.base_message(),
399            RuntimeError::ImportError(e) => {
400                let msg = match e.kind {
401                    ImportErrorKind::ImportDisabled => "Import is disabled".to_string(),
402                    ImportErrorKind::InvalidSpecifier => format!(
403                        "Invalid module specifier: {}",
404                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
405                    ),
406                    ImportErrorKind::NoBaseDir => format!(
407                        "No base directory to resolve specifier: {}",
408                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
409                    ),
410                    ImportErrorKind::NotFound => format!(
411                        "Module not found: {}",
412                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
413                    ),
414                    ImportErrorKind::AccessDenied => format!(
415                        "Module access denied: {}",
416                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
417                    ),
418                    ImportErrorKind::IoError => format!(
419                        "Module IO error: {}",
420                        e.detail.clone().unwrap_or_else(|| e.specifier.clone())
421                    ),
422                    ImportErrorKind::NotExported => format!(
423                        "'{}' is not exported by module {}",
424                        e.symbol.clone().unwrap_or_else(|| "<unknown>".to_string()),
425                        e.specifier
426                    ),
427                    ImportErrorKind::CircularImport => {
428                        let cycle = e.cycle.clone().unwrap_or_else(|| vec![e.specifier.clone()]);
429                        format!("circular import detected: {}", cycle.join(" -> "))
430                    }
431                    ImportErrorKind::ParseFailed => format!(
432                        "parse failed for module {}: {}",
433                        e.module_id.clone().unwrap_or_else(|| e.specifier.clone()),
434                        e.detail.clone().unwrap_or_else(|| "<unknown>".to_string())
435                    ),
436                };
437
438                format!("Import error: {msg}")
439            }
440            other => other.to_string(),
441        }
442    }
443
444    pub fn to_error_report(&self) -> ErrorReport {
445        let (base, call_stack) = self.peel_call_stack();
446
447        let import_chain = match base {
448            RuntimeError::ImportError(e) => e.import_chain.clone(),
449            _ => Vec::new(),
450        };
451
452        ErrorReport {
453            phase: "runtime".to_string(),
454            kind: base.kind_name(),
455            message: base.base_message(),
456            import_chain,
457            call_stack,
458        }
459    }
460}
461
462/// Evaluator for Aether programs
463pub struct Evaluator {
464    /// Global environment
465    env: Rc<RefCell<Environment>>,
466    /// Built-in function registry
467    registry: BuiltInRegistry,
468    /// In-memory trace buffer (for DSL-safe debugging; no stdout/files/network)
469    trace: VecDeque<String>,
470    /// Monotonic sequence for trace entries (starts at 1)
471    trace_seq: u64,
472    /// Structured trace entries (new in Stage 3.2)
473    trace_entries: VecDeque<crate::runtime::TraceEntry>,
474
475    /// Module resolver (Import/Export). Defaults to disabled for DSL safety.
476    module_resolver: Box<dyn ModuleResolver>,
477    /// Module export cache: module_id -> exports
478    module_cache: HashMap<String, HashMap<String, Value>>,
479    /// Module load stack for cycle detection
480    module_stack: Vec<String>,
481    /// Current module export table stack (only when evaluating an imported module)
482    export_stack: Vec<HashMap<String, Value>>,
483    /// Optional base directory context for resolving relative imports (e.g. eval_file)
484    import_base_stack: Vec<ModuleContext>,
485
486    /// Call stack for better debugging (user functions + builtins)
487    call_stack: Vec<CallFrame>,
488
489    /// Execution limits configuration
490    limits: crate::runtime::ExecutionLimits,
491    /// Step counter (for step limit enforcement)
492    step_counter: std::cell::Cell<usize>,
493    /// Call stack depth counter (for recursion depth limit enforcement)
494    call_stack_depth: std::cell::Cell<usize>,
495    /// Execution start time (for timeout enforcement)
496    start_time: std::cell::Cell<Option<std::time::Instant>>,
497}
498
499impl Evaluator {
500    const TRACE_MAX_ENTRIES: usize = 1024;
501
502    fn register_builtins_into_env(registry: &BuiltInRegistry, env: &mut Environment) {
503        for name in registry.names() {
504            let arity = registry.get(&name).map(|(_, a)| a).unwrap_or(0);
505            env.set(name.clone(), Value::BuiltIn { name, arity });
506        }
507    }
508
509    /// Check and increment step counter
510    fn eval_step(&self) -> Result<(), RuntimeError> {
511        if let Some(limit) = self.limits.max_steps {
512            let steps = self.step_counter.get();
513            if steps >= limit {
514                return Err(RuntimeError::ExecutionLimit(
515                    crate::runtime::ExecutionLimitError::StepLimitExceeded { steps, limit },
516                ));
517            }
518            self.step_counter.set(steps + 1);
519        }
520        Ok(())
521    }
522
523    /// Check execution timeout
524    fn check_timeout(&self) -> Result<(), RuntimeError> {
525        if let Some(limit_ms) = self.limits.max_duration_ms
526            && let Some(start) = self.start_time.get()
527        {
528            let elapsed = start.elapsed().as_millis() as u64;
529            if elapsed >= limit_ms {
530                return Err(RuntimeError::ExecutionLimit(
531                    crate::runtime::ExecutionLimitError::DurationExceeded {
532                        duration_ms: elapsed,
533                        limit: limit_ms,
534                    },
535                ));
536            }
537        }
538        Ok(())
539    }
540
541    /// Enter function call (check recursion depth)
542    fn enter_call(&self) -> Result<(), RuntimeError> {
543        if let Some(limit) = self.limits.max_recursion_depth {
544            let depth = self.call_stack_depth.get();
545            if depth >= limit {
546                return Err(RuntimeError::ExecutionLimit(
547                    crate::runtime::ExecutionLimitError::RecursionDepthExceeded { depth, limit },
548                ));
549            }
550            self.call_stack_depth.set(depth + 1);
551        }
552        Ok(())
553    }
554
555    /// Exit function call (decrement recursion depth)
556    fn exit_call(&self) {
557        if self.limits.max_recursion_depth.is_some() {
558            let depth = self.call_stack_depth.get();
559            self.call_stack_depth.set(depth.saturating_sub(1));
560        }
561    }
562
563    /// Set execution limits (public API)
564    pub fn set_limits(&mut self, limits: crate::runtime::ExecutionLimits) {
565        self.limits = limits;
566    }
567
568    /// Get execution limits (public API)
569    pub fn limits(&self) -> &crate::runtime::ExecutionLimits {
570        &self.limits
571    }
572
573    fn is_control_flow_error(err: &RuntimeError) -> bool {
574        matches!(
575            err,
576            RuntimeError::Return(_)
577                | RuntimeError::Yield(_)
578                | RuntimeError::Break
579                | RuntimeError::Continue
580        )
581    }
582
583    fn attach_call_stack_if_absent(&self, err: RuntimeError) -> RuntimeError {
584        if Self::is_control_flow_error(&err) {
585            return err;
586        }
587        match err {
588            RuntimeError::WithCallStack { .. } => err,
589            other => RuntimeError::WithCallStack {
590                error: Box::new(other),
591                call_stack: self.call_stack.clone(),
592            },
593        }
594    }
595
596    /// Create a new evaluator (默认禁用IO)
597    pub fn new() -> Self {
598        Self::with_permissions(crate::builtins::IOPermissions::default())
599    }
600
601    /// Create a new evaluator with custom IO permissions
602    pub fn with_permissions(permissions: crate::builtins::IOPermissions) -> Self {
603        let env = Rc::new(RefCell::new(Environment::new()));
604
605        // Register built-in functions with permissions
606        let registry = BuiltInRegistry::with_permissions(permissions);
607        Self::register_builtins_into_env(&registry, &mut env.borrow_mut());
608
609        Evaluator {
610            env,
611            registry,
612            trace: VecDeque::new(),
613            trace_seq: 0,
614            trace_entries: VecDeque::new(),
615
616            module_resolver: Box::new(DisabledModuleResolver),
617            module_cache: HashMap::new(),
618            module_stack: Vec::new(),
619            export_stack: Vec::new(),
620            import_base_stack: Vec::new(),
621
622            call_stack: Vec::new(),
623
624            limits: crate::runtime::ExecutionLimits::default(),
625            step_counter: std::cell::Cell::new(0),
626            call_stack_depth: std::cell::Cell::new(0),
627            start_time: std::cell::Cell::new(None),
628        }
629    }
630
631    /// Create evaluator with custom environment
632    pub fn with_env(env: Rc<RefCell<Environment>>) -> Self {
633        let registry = BuiltInRegistry::new();
634        Evaluator {
635            env,
636            registry,
637            trace: VecDeque::new(),
638            trace_seq: 0,
639            trace_entries: VecDeque::new(),
640
641            module_resolver: Box::new(DisabledModuleResolver),
642            module_cache: HashMap::new(),
643            module_stack: Vec::new(),
644            export_stack: Vec::new(),
645            import_base_stack: Vec::new(),
646
647            call_stack: Vec::new(),
648
649            limits: crate::runtime::ExecutionLimits::default(),
650            step_counter: std::cell::Cell::new(0),
651            call_stack_depth: std::cell::Cell::new(0),
652            start_time: std::cell::Cell::new(None),
653        }
654    }
655
656    /// Clear the call stack (used by top-level entry points like `Aether::eval`).
657    pub fn clear_call_stack(&mut self) {
658        self.call_stack.clear();
659    }
660
661    /// Configure the module resolver used for `Import/Export`.
662    pub fn set_module_resolver(&mut self, resolver: Box<dyn ModuleResolver>) {
663        self.module_resolver = resolver;
664    }
665
666    /// Push a base directory context for resolving relative imports.
667    ///
668    /// This is typically used by CLI `eval_file()` wrappers.
669    pub fn push_import_base(&mut self, module_id: String, base_dir: Option<std::path::PathBuf>) {
670        self.import_base_stack.push(ModuleContext {
671            module_id,
672            base_dir,
673        });
674    }
675
676    /// Pop the most recent base directory context.
677    pub fn pop_import_base(&mut self) {
678        self.import_base_stack.pop();
679    }
680
681    /// Append a trace entry (host-readable; no IO side effects).
682    pub fn trace_push(&mut self, msg: String) {
683        self.trace_seq = self.trace_seq.saturating_add(1);
684        let entry = format!("#{} {}", self.trace_seq, msg);
685
686        if self.trace.len() >= Self::TRACE_MAX_ENTRIES {
687            self.trace.pop_front();
688        }
689        self.trace.push_back(entry);
690    }
691
692    /// Push a structured trace entry (Stage 3.2)
693    fn trace_push_entry(&mut self, entry: crate::runtime::TraceEntry) {
694        self.trace_seq = self.trace_seq.saturating_add(1);
695
696        // Add to structured entries
697        if self.trace_entries.len() >= Self::TRACE_MAX_ENTRIES {
698            self.trace_entries.pop_front();
699        }
700        self.trace_entries.push_back(entry.clone());
701
702        // Also add to formatted trace (for backward compatibility)
703        let formatted = entry.format();
704        let msg = format!("#{} {}", self.trace_seq, formatted);
705        if self.trace.len() >= Self::TRACE_MAX_ENTRIES {
706            self.trace.pop_front();
707        }
708        self.trace.push_back(msg);
709    }
710
711    /// Drain the trace buffer.
712    pub fn take_trace(&mut self) -> Vec<String> {
713        std::mem::take(&mut self.trace).into_iter().collect()
714    }
715
716    /// Get all structured trace entries
717    pub fn trace_records(&self) -> Vec<crate::runtime::TraceEntry> {
718        self.trace_entries.iter().cloned().collect()
719    }
720
721    /// Filter trace entries by level
722    pub fn trace_by_level(
723        &self,
724        level: crate::runtime::TraceLevel,
725    ) -> Vec<crate::runtime::TraceEntry> {
726        self.trace_entries
727            .iter()
728            .filter(|e| e.level == level)
729            .cloned()
730            .collect()
731    }
732
733    /// Filter trace entries by category
734    pub fn trace_by_category(&self, category: &str) -> Vec<crate::runtime::TraceEntry> {
735        self.trace_entries
736            .iter()
737            .filter(|e| e.category == category)
738            .cloned()
739            .collect()
740    }
741
742    /// Filter trace entries by label
743    pub fn trace_by_label(&self, label: &str) -> Vec<crate::runtime::TraceEntry> {
744        self.trace_entries
745            .iter()
746            .filter(|e| e.label.as_deref() == Some(label))
747            .cloned()
748            .collect()
749    }
750
751    /// Filter trace entries by time range (since)
752    pub fn trace_since(&self, since: std::time::Instant) -> Vec<crate::runtime::TraceEntry> {
753        self.trace_entries
754            .iter()
755            .filter(|e| e.timestamp >= since)
756            .cloned()
757            .collect()
758    }
759
760    /// Apply complex filter to trace entries
761    pub fn trace_filter(
762        &self,
763        filter: &crate::runtime::TraceFilter,
764    ) -> Vec<crate::runtime::TraceEntry> {
765        self.trace_entries
766            .iter()
767            .filter(|e| filter.matches(e))
768            .cloned()
769            .collect()
770    }
771
772    /// Get trace statistics
773    pub fn trace_stats(&self) -> crate::runtime::TraceStats {
774        use std::collections::HashMap;
775
776        let mut by_level = HashMap::new();
777        let mut by_category = HashMap::new();
778
779        for entry in &self.trace_entries {
780            *by_level.entry(entry.level).or_insert(0) += 1;
781            *by_category.entry(entry.category.clone()).or_insert(0) += 1;
782        }
783
784        crate::runtime::TraceStats {
785            total_entries: self.trace_entries.len(),
786            by_level,
787            by_category,
788            buffer_size: Self::TRACE_MAX_ENTRIES,
789            buffer_full: self.trace_entries.len() >= Self::TRACE_MAX_ENTRIES,
790        }
791    }
792
793    /// Clear the trace buffer.
794    pub fn clear_trace(&mut self) {
795        self.trace.clear();
796        self.trace_entries.clear();
797        self.trace_seq = 0;
798    }
799
800    /// Reset the environment (clear all variables and re-register built-ins)
801    ///
802    /// This is useful for engine pooling and global singleton patterns
803    /// where you want to reuse an engine instance but ensure isolation.
804    pub fn reset_env(&mut self) {
805        // Create new environment
806        self.env = Rc::new(RefCell::new(Environment::new()));
807
808        // Avoid leaking trace across pooled executions
809        self.trace.clear();
810        self.trace_entries.clear();
811        self.trace_seq = 0;
812
813        // Reset module contexts (cache is kept; can be cleared explicitly by host if needed)
814        self.import_base_stack.clear();
815        self.export_stack.clear();
816        self.module_stack.clear();
817
818        // Avoid leaking call stack across pooled executions
819        self.call_stack.clear();
820
821        // Re-register built-in functions
822        Self::register_builtins_into_env(&self.registry, &mut self.env.borrow_mut());
823    }
824
825    /// Set a global variable from the host (without requiring `eval`).
826    pub fn set_global(&mut self, name: impl Into<String>, value: Value) {
827        self.env.borrow_mut().set(name.into(), value);
828    }
829
830    /// Get a global variable value from the environment
831    pub fn get_global(&self, name: &str) -> Option<Value> {
832        self.env.borrow().get(name)
833    }
834
835    /// Enter a child scope (new environment whose parent is the current env).
836    ///
837    /// Returns the previous environment handle; pass it back to `restore_env()`.
838    pub fn enter_child_scope(&mut self) -> Rc<RefCell<Environment>> {
839        let prev = Rc::clone(&self.env);
840        let child = Rc::new(RefCell::new(Environment::with_parent(Rc::clone(&prev))));
841        self.env = child;
842        prev
843    }
844
845    /// Restore a previously saved environment handle (typically from `enter_child_scope()`).
846    pub fn restore_env(&mut self, prev: Rc<RefCell<Environment>>) {
847        self.env = prev;
848    }
849
850    /// Evaluate a program
851    pub fn eval_program(&mut self, program: &Program) -> EvalResult {
852        // Record start time for timeout checking
853        if self.limits.max_duration_ms.is_some() {
854            self.start_time.set(Some(std::time::Instant::now()));
855        }
856
857        let mut result = Value::Null;
858
859        for stmt in program {
860            result = self.eval_statement(stmt)?;
861        }
862
863        Ok(result)
864    }
865
866    /// Evaluate a statement
867    pub fn eval_statement(&mut self, stmt: &Stmt) -> EvalResult {
868        // Check execution limits before each statement
869        self.eval_step()?;
870        self.check_timeout()?;
871
872        match stmt {
873            Stmt::Set { name, value } => {
874                let val = self.eval_expression(value)?;
875                self.env.borrow_mut().set(name.clone(), val.clone());
876                Ok(val)
877            }
878
879            Stmt::SetIndex {
880                object,
881                index,
882                value,
883            } => {
884                // Evaluate the value to be assigned
885                let val = self.eval_expression(value)?;
886
887                // For simple identifier objects, we can modify in place
888                if let Expr::Identifier(name) = object.as_ref() {
889                    // Get the object from environment
890                    let obj = self
891                        .env
892                        .borrow()
893                        .get(name)
894                        .ok_or_else(|| RuntimeError::UndefinedVariable(name.clone()))?;
895
896                    // Evaluate the index
897                    let idx_val = self.eval_expression(index)?;
898
899                    // Modify based on object type
900                    let new_obj = match (obj, idx_val) {
901                        (Value::Array(mut arr), Value::Number(n)) => {
902                            let idx = n as usize;
903                            if idx >= arr.len() {
904                                return Err(RuntimeError::InvalidOperation(format!(
905                                    "Index {} out of bounds (array length: {})",
906                                    idx,
907                                    arr.len()
908                                )));
909                            }
910                            arr[idx] = val.clone();
911                            Value::Array(arr)
912                        }
913                        (Value::Dict(mut dict), Value::String(key)) => {
914                            dict.insert(key, val.clone());
915                            Value::Dict(dict)
916                        }
917                        (obj, idx) => {
918                            return Err(RuntimeError::TypeError(format!(
919                                "Cannot index {} with {}",
920                                obj.type_name(),
921                                idx.type_name()
922                            )));
923                        }
924                    };
925
926                    // Update the variable in environment
927                    self.env.borrow_mut().set(name.clone(), new_obj);
928                    Ok(val)
929                } else {
930                    // For complex expressions, we can't modify in place
931                    Err(RuntimeError::InvalidOperation(
932                        "Can only assign to simple variable indices (e.g., dict[key], not expr[key])"
933                            .to_string(),
934                    ))
935                }
936            }
937
938            Stmt::FuncDef { name, params, body } => {
939                let func = Value::Function {
940                    name: Some(name.clone()),
941                    params: params.clone(),
942                    body: body.clone(),
943                    env: Rc::clone(&self.env),
944                };
945                self.env.borrow_mut().set(name.clone(), func.clone());
946                Ok(func)
947            }
948
949            Stmt::GeneratorDef { name, params, body } => {
950                let r#gen = Value::Generator {
951                    params: params.clone(),
952                    body: body.clone(),
953                    env: Rc::clone(&self.env),
954                    state: GeneratorState::NotStarted,
955                };
956                self.env.borrow_mut().set(name.clone(), r#gen.clone());
957                Ok(r#gen)
958            }
959
960            Stmt::LazyDef { name, expr } => {
961                let lazy = Value::Lazy {
962                    expr: expr.clone(),
963                    env: Rc::clone(&self.env),
964                    cached: None,
965                };
966                self.env.borrow_mut().set(name.clone(), lazy.clone());
967                Ok(lazy)
968            }
969
970            Stmt::Return(expr) => {
971                let val = self.eval_expression(expr)?;
972                Err(RuntimeError::Return(val))
973            }
974
975            Stmt::Yield(expr) => {
976                let val = self.eval_expression(expr)?;
977                Err(RuntimeError::Yield(val))
978            }
979
980            Stmt::Break => Err(RuntimeError::Break),
981
982            Stmt::Continue => Err(RuntimeError::Continue),
983
984            Stmt::While { condition, body } => {
985                let mut result = Value::Null;
986
987                loop {
988                    let cond = self.eval_expression(condition)?;
989                    if !cond.is_truthy() {
990                        break;
991                    }
992
993                    let mut should_break = false;
994                    for stmt in body {
995                        match self.eval_statement(stmt) {
996                            Ok(val) => result = val,
997                            Err(RuntimeError::Break) => {
998                                should_break = true;
999                                break;
1000                            }
1001                            Err(RuntimeError::Continue) => break,
1002                            Err(e) => return Err(e),
1003                        }
1004                    }
1005
1006                    if should_break {
1007                        break;
1008                    }
1009                }
1010
1011                Ok(result)
1012            }
1013
1014            Stmt::For {
1015                var,
1016                iterable,
1017                body,
1018            } => {
1019                let iter_val = self.eval_expression(iterable)?;
1020                let mut result = Value::Null;
1021
1022                match iter_val {
1023                    Value::Array(arr) => {
1024                        let mut should_break = false;
1025                        for item in arr {
1026                            self.env.borrow_mut().set(var.clone(), item);
1027                            for stmt in body {
1028                                match self.eval_statement(stmt) {
1029                                    Ok(val) => result = val,
1030                                    Err(RuntimeError::Break) => {
1031                                        should_break = true;
1032                                        break;
1033                                    }
1034                                    Err(RuntimeError::Continue) => break,
1035                                    Err(e) => return Err(e),
1036                                }
1037                            }
1038                            if should_break {
1039                                break;
1040                            }
1041                        }
1042                    }
1043                    _ => {
1044                        return Err(RuntimeError::TypeError(format!(
1045                            "Cannot iterate over {}",
1046                            iter_val.type_name()
1047                        )));
1048                    }
1049                }
1050
1051                Ok(result)
1052            }
1053
1054            Stmt::ForIndexed {
1055                index_var,
1056                value_var,
1057                iterable,
1058                body,
1059            } => {
1060                let iter_val = self.eval_expression(iterable)?;
1061                let mut result = Value::Null;
1062
1063                match iter_val {
1064                    Value::Array(arr) => {
1065                        let mut should_break = false;
1066                        for (idx, item) in arr.iter().enumerate() {
1067                            self.env
1068                                .borrow_mut()
1069                                .set(index_var.clone(), Value::Number(idx as f64));
1070                            self.env.borrow_mut().set(value_var.clone(), item.clone());
1071                            for stmt in body {
1072                                match self.eval_statement(stmt) {
1073                                    Ok(val) => result = val,
1074                                    Err(RuntimeError::Break) => {
1075                                        should_break = true;
1076                                        break;
1077                                    }
1078                                    Err(RuntimeError::Continue) => break,
1079                                    Err(e) => return Err(e),
1080                                }
1081                            }
1082                            if should_break {
1083                                break;
1084                            }
1085                        }
1086                    }
1087                    _ => {
1088                        return Err(RuntimeError::TypeError(format!(
1089                            "Cannot iterate over {}",
1090                            iter_val.type_name()
1091                        )));
1092                    }
1093                }
1094
1095                Ok(result)
1096            }
1097
1098            Stmt::Switch {
1099                expr,
1100                cases,
1101                default,
1102            } => {
1103                let val = self.eval_expression(expr)?;
1104
1105                for (case_expr, case_body) in cases {
1106                    let case_val = self.eval_expression(case_expr)?;
1107                    if val.equals(&case_val) {
1108                        let mut result = Value::Null;
1109                        for stmt in case_body {
1110                            result = self.eval_statement(stmt)?;
1111                        }
1112                        return Ok(result);
1113                    }
1114                }
1115
1116                if let Some(default_body) = default {
1117                    let mut result = Value::Null;
1118                    for stmt in default_body {
1119                        result = self.eval_statement(stmt)?;
1120                    }
1121                    return Ok(result);
1122                }
1123
1124                Ok(Value::Null)
1125            }
1126
1127            Stmt::Import {
1128                names,
1129                path,
1130                aliases,
1131                namespace,
1132            } => self.eval_import(names, path, aliases, namespace.as_ref()),
1133
1134            Stmt::Export(name) => self.eval_export(name),
1135
1136            Stmt::Throw(expr) => {
1137                let val = self.eval_expression(expr)?;
1138                Err(RuntimeError::Throw(val))
1139            }
1140
1141            Stmt::Expression(expr) => self.eval_expression(expr),
1142        }
1143    }
1144
1145    /// Evaluate an expression
1146    pub fn eval_expression(&mut self, expr: &Expr) -> EvalResult {
1147        match expr {
1148            Expr::Number(n) => Ok(Value::Number(*n)),
1149
1150            Expr::BigInteger(s) => {
1151                // 将大整数字符串转换为 Fraction (分母为1的分数)
1152                use num_bigint::BigInt;
1153                use num_rational::Ratio;
1154
1155                match s.parse::<BigInt>() {
1156                    Ok(big_int) => Ok(Value::Fraction(Ratio::new(big_int, BigInt::from(1)))),
1157                    Err(_) => Err(RuntimeError::InvalidOperation(format!(
1158                        "Invalid big integer: {}",
1159                        s
1160                    ))),
1161                }
1162            }
1163
1164            Expr::String(s) => Ok(Value::String(s.clone())),
1165
1166            Expr::Boolean(b) => Ok(Value::Boolean(*b)),
1167
1168            Expr::Null => Ok(Value::Null),
1169
1170            Expr::Identifier(name) => self
1171                .env
1172                .borrow()
1173                .get(name)
1174                .ok_or_else(|| RuntimeError::UndefinedVariable(name.clone())),
1175
1176            Expr::Binary { left, op, right } => {
1177                // Short-circuit evaluation for And and Or
1178                match op {
1179                    BinOp::And => {
1180                        let left_val = self.eval_expression(left)?;
1181                        if !left_val.is_truthy() {
1182                            // Short-circuit: left is falsy, return left without evaluating right
1183                            Ok(left_val)
1184                        } else {
1185                            // left is truthy, return right value
1186                            self.eval_expression(right)
1187                        }
1188                    }
1189                    BinOp::Or => {
1190                        let left_val = self.eval_expression(left)?;
1191                        if left_val.is_truthy() {
1192                            // Short-circuit: left is truthy, return left without evaluating right
1193                            Ok(left_val)
1194                        } else {
1195                            // left is falsy, return right value
1196                            self.eval_expression(right)
1197                        }
1198                    }
1199                    // For other operators, evaluate both sides
1200                    _ => {
1201                        let left_val = self.eval_expression(left)?;
1202                        let right_val = self.eval_expression(right)?;
1203                        self.eval_binary_op(&left_val, op, &right_val)
1204                    }
1205                }
1206            }
1207
1208            Expr::Unary { op, expr } => {
1209                let val = self.eval_expression(expr)?;
1210                self.eval_unary_op(op, &val)
1211            }
1212
1213            Expr::Call { func, args } => {
1214                let name_hint = match func.as_ref() {
1215                    Expr::Identifier(name) => Some(name.clone()),
1216                    _ => None,
1217                };
1218                let func_val = self.eval_expression(func)?;
1219                let arg_vals: Result<Vec<_>, _> =
1220                    args.iter().map(|arg| self.eval_expression(arg)).collect();
1221                let arg_vals = arg_vals?;
1222
1223                self.call_function(name_hint.as_deref(), &func_val, arg_vals)
1224            }
1225
1226            Expr::Array(elements) => {
1227                let vals: Result<Vec<_>, _> =
1228                    elements.iter().map(|e| self.eval_expression(e)).collect();
1229                Ok(Value::Array(vals?))
1230            }
1231
1232            Expr::Dict(pairs) => {
1233                let mut map = std::collections::HashMap::new();
1234                for (key, value_expr) in pairs {
1235                    let value = self.eval_expression(value_expr)?;
1236                    map.insert(key.clone(), value);
1237                }
1238                Ok(Value::Dict(map))
1239            }
1240
1241            Expr::Index { object, index } => {
1242                let obj_val = self.eval_expression(object)?;
1243                let idx_val = self.eval_expression(index)?;
1244
1245                match (obj_val, idx_val) {
1246                    (Value::Array(arr), Value::Number(n)) => {
1247                        let idx = n as usize;
1248                        arr.get(idx).cloned().ok_or_else(|| {
1249                            RuntimeError::InvalidOperation(format!("Index {} out of bounds", idx))
1250                        })
1251                    }
1252                    (Value::String(s), Value::Number(n)) => {
1253                        let idx = n as usize;
1254                        let chars: Vec<char> = s.chars().collect();
1255                        chars
1256                            .get(idx)
1257                            .cloned()
1258                            .map(|ch| Value::String(ch.to_string()))
1259                            .ok_or_else(|| {
1260                                RuntimeError::InvalidOperation(format!(
1261                                    "Index {} out of bounds (string length: {})",
1262                                    idx,
1263                                    chars.len()
1264                                ))
1265                            })
1266                    }
1267                    (Value::Dict(dict), Value::String(key)) => {
1268                        dict.get(&key).cloned().ok_or_else(|| {
1269                            RuntimeError::InvalidOperation(format!("Key '{}' not found", key))
1270                        })
1271                    }
1272                    (obj, idx) => Err(RuntimeError::TypeError(format!(
1273                        "Cannot index {} with {}",
1274                        obj.type_name(),
1275                        idx.type_name()
1276                    ))),
1277                }
1278            }
1279
1280            Expr::If {
1281                condition,
1282                then_branch,
1283                elif_branches,
1284                else_branch,
1285            } => {
1286                let cond = self.eval_expression(condition)?;
1287
1288                if cond.is_truthy() {
1289                    let mut result = Value::Null;
1290                    for stmt in then_branch {
1291                        result = self.eval_statement(stmt)?;
1292                    }
1293                    return Ok(result);
1294                }
1295
1296                for (elif_cond, elif_body) in elif_branches {
1297                    let cond = self.eval_expression(elif_cond)?;
1298                    if cond.is_truthy() {
1299                        let mut result = Value::Null;
1300                        for stmt in elif_body {
1301                            result = self.eval_statement(stmt)?;
1302                        }
1303                        return Ok(result);
1304                    }
1305                }
1306
1307                if let Some(else_body) = else_branch {
1308                    let mut result = Value::Null;
1309                    for stmt in else_body {
1310                        result = self.eval_statement(stmt)?;
1311                    }
1312                    return Ok(result);
1313                }
1314
1315                Ok(Value::Null)
1316            }
1317
1318            Expr::Lambda { params, body } => {
1319                // Create a closure by capturing the current environment
1320                Ok(Value::Function {
1321                    name: None,
1322                    params: params.clone(),
1323                    body: body.clone(),
1324                    env: Rc::clone(&self.env),
1325                })
1326            }
1327        }
1328    }
1329
1330    /// Evaluate binary operation
1331    fn eval_binary_op(&self, left: &Value, op: &BinOp, right: &Value) -> EvalResult {
1332        match op {
1333            BinOp::Add => match (left, right) {
1334                (Value::Number(a), Value::Number(b)) => Ok(Value::Number(a + b)),
1335                (Value::String(a), Value::String(b)) => Ok(Value::String(format!("{}{}", a, b))),
1336                (Value::Fraction(a), Value::Fraction(b)) => Ok(Value::Fraction(a + b)),
1337                (Value::Number(a), Value::Fraction(b)) | (Value::Fraction(b), Value::Number(a)) => {
1338                    use num_bigint::BigInt;
1339                    use num_rational::Ratio;
1340                    if a.fract() == 0.0 {
1341                        let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
1342                        Ok(Value::Fraction(a_frac + b))
1343                    } else {
1344                        // 浮点数和分数混合运算,转换为浮点数
1345                        use num_traits::ToPrimitive;
1346                        let b_float =
1347                            b.numer().to_f64().unwrap_or(0.0) / b.denom().to_f64().unwrap_or(1.0);
1348                        Ok(Value::Number(a + b_float))
1349                    }
1350                }
1351                _ => Err(RuntimeError::TypeError(format!(
1352                    "Cannot add {} and {}",
1353                    left.type_name(),
1354                    right.type_name()
1355                ))),
1356            },
1357
1358            BinOp::Subtract => match (left, right) {
1359                (Value::Number(a), Value::Number(b)) => Ok(Value::Number(a - b)),
1360                (Value::Fraction(a), Value::Fraction(b)) => Ok(Value::Fraction(a - b)),
1361                (Value::Number(a), Value::Fraction(b)) => {
1362                    use num_bigint::BigInt;
1363                    use num_rational::Ratio;
1364                    if a.fract() == 0.0 {
1365                        let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
1366                        Ok(Value::Fraction(a_frac - b))
1367                    } else {
1368                        use num_traits::ToPrimitive;
1369                        let b_float =
1370                            b.numer().to_f64().unwrap_or(0.0) / b.denom().to_f64().unwrap_or(1.0);
1371                        Ok(Value::Number(a - b_float))
1372                    }
1373                }
1374                (Value::Fraction(a), Value::Number(b)) => {
1375                    use num_bigint::BigInt;
1376                    use num_rational::Ratio;
1377                    if b.fract() == 0.0 {
1378                        let b_frac = Ratio::new(BigInt::from(*b as i64), BigInt::from(1));
1379                        Ok(Value::Fraction(a - b_frac))
1380                    } else {
1381                        use num_traits::ToPrimitive;
1382                        let a_float =
1383                            a.numer().to_f64().unwrap_or(0.0) / a.denom().to_f64().unwrap_or(1.0);
1384                        Ok(Value::Number(a_float - b))
1385                    }
1386                }
1387                _ => Err(RuntimeError::TypeError(format!(
1388                    "Cannot subtract {} from {}",
1389                    right.type_name(),
1390                    left.type_name()
1391                ))),
1392            },
1393
1394            BinOp::Multiply => match (left, right) {
1395                (Value::Number(a), Value::Number(b)) => {
1396                    // 如果两个数都是整数,且足够大,使用精确计算
1397                    if a.fract() == 0.0 && b.fract() == 0.0 {
1398                        // 检查是否超过 f64 的安全整数范围 (2^53)
1399                        let max_safe = 9007199254740992.0; // 2^53
1400                        if a.abs() > max_safe || b.abs() > max_safe {
1401                            // 使用 Fraction (BigInt) 进行精确计算
1402                            use num_bigint::BigInt;
1403                            use num_rational::Ratio;
1404
1405                            // 将 f64 转换为字符串再转为 BigInt,避免精度损失
1406                            let a_str = format!("{:.0}", a);
1407                            let b_str = format!("{:.0}", b);
1408
1409                            if let (Ok(a_big), Ok(b_big)) =
1410                                (a_str.parse::<BigInt>(), b_str.parse::<BigInt>())
1411                            {
1412                                let result_big = a_big * b_big;
1413                                let frac = Ratio::new(result_big, BigInt::from(1));
1414                                return Ok(Value::Fraction(frac));
1415                            }
1416                        }
1417                    }
1418                    Ok(Value::Number(a * b))
1419                }
1420                (Value::Fraction(a), Value::Fraction(b)) => Ok(Value::Fraction(a * b)),
1421                (Value::Number(a), Value::Fraction(b)) | (Value::Fraction(b), Value::Number(a)) => {
1422                    use num_bigint::BigInt;
1423                    use num_rational::Ratio;
1424                    if a.fract() == 0.0 {
1425                        let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
1426                        Ok(Value::Fraction(a_frac * b))
1427                    } else {
1428                        Err(RuntimeError::TypeError(
1429                            "Cannot multiply non-integer Number with Fraction".to_string(),
1430                        ))
1431                    }
1432                }
1433                _ => Err(RuntimeError::TypeError(format!(
1434                    "Cannot multiply {} and {}",
1435                    left.type_name(),
1436                    right.type_name()
1437                ))),
1438            },
1439
1440            BinOp::Divide => match (left, right) {
1441                (Value::Number(a), Value::Number(b)) => {
1442                    if *b == 0.0 {
1443                        Err(RuntimeError::DivisionByZero)
1444                    } else {
1445                        Ok(Value::Number(a / b))
1446                    }
1447                }
1448                (Value::Fraction(a), Value::Fraction(b)) => {
1449                    use num_traits::Zero;
1450                    if b.is_zero() {
1451                        Err(RuntimeError::DivisionByZero)
1452                    } else {
1453                        Ok(Value::Fraction(a / b))
1454                    }
1455                }
1456                (Value::Number(a), Value::Fraction(b)) => {
1457                    use num_bigint::BigInt;
1458                    use num_rational::Ratio;
1459                    use num_traits::Zero;
1460                    if b.is_zero() {
1461                        Err(RuntimeError::DivisionByZero)
1462                    } else if a.fract() == 0.0 {
1463                        let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
1464                        Ok(Value::Fraction(a_frac / b))
1465                    } else {
1466                        use num_traits::ToPrimitive;
1467                        let b_float =
1468                            b.numer().to_f64().unwrap_or(0.0) / b.denom().to_f64().unwrap_or(1.0);
1469                        Ok(Value::Number(a / b_float))
1470                    }
1471                }
1472                (Value::Fraction(a), Value::Number(b)) => {
1473                    use num_bigint::BigInt;
1474                    use num_rational::Ratio;
1475                    if *b == 0.0 {
1476                        Err(RuntimeError::DivisionByZero)
1477                    } else if b.fract() == 0.0 {
1478                        let b_frac = Ratio::new(BigInt::from(*b as i64), BigInt::from(1));
1479                        Ok(Value::Fraction(a / b_frac))
1480                    } else {
1481                        use num_traits::ToPrimitive;
1482                        let a_float =
1483                            a.numer().to_f64().unwrap_or(0.0) / a.denom().to_f64().unwrap_or(1.0);
1484                        Ok(Value::Number(a_float / b))
1485                    }
1486                }
1487                _ => Err(RuntimeError::TypeError(format!(
1488                    "Cannot divide {} by {}",
1489                    left.type_name(),
1490                    right.type_name()
1491                ))),
1492            },
1493
1494            BinOp::Modulo => match (left, right) {
1495                (Value::Number(a), Value::Number(b)) => {
1496                    if *b == 0.0 {
1497                        Err(RuntimeError::DivisionByZero)
1498                    } else {
1499                        Ok(Value::Number(a % b))
1500                    }
1501                }
1502                _ => Err(RuntimeError::TypeError(format!(
1503                    "Cannot modulo {} by {}",
1504                    left.type_name(),
1505                    right.type_name()
1506                ))),
1507            },
1508
1509            BinOp::Equal => Ok(Value::Boolean(left.equals(right))),
1510
1511            BinOp::NotEqual => Ok(Value::Boolean(!left.equals(right))),
1512
1513            BinOp::Less => match left.compare(right) {
1514                Some(ord) => Ok(Value::Boolean(ord == std::cmp::Ordering::Less)),
1515                None => Err(RuntimeError::TypeError(format!(
1516                    "Cannot compare {} and {}",
1517                    left.type_name(),
1518                    right.type_name()
1519                ))),
1520            },
1521
1522            BinOp::LessEqual => match left.compare(right) {
1523                Some(ord) => Ok(Value::Boolean(ord != std::cmp::Ordering::Greater)),
1524                None => Err(RuntimeError::TypeError(format!(
1525                    "Cannot compare {} and {}",
1526                    left.type_name(),
1527                    right.type_name()
1528                ))),
1529            },
1530
1531            BinOp::Greater => match left.compare(right) {
1532                Some(ord) => Ok(Value::Boolean(ord == std::cmp::Ordering::Greater)),
1533                None => Err(RuntimeError::TypeError(format!(
1534                    "Cannot compare {} and {}",
1535                    left.type_name(),
1536                    right.type_name()
1537                ))),
1538            },
1539
1540            BinOp::GreaterEqual => match left.compare(right) {
1541                Some(ord) => Ok(Value::Boolean(ord != std::cmp::Ordering::Less)),
1542                None => Err(RuntimeError::TypeError(format!(
1543                    "Cannot compare {} and {}",
1544                    left.type_name(),
1545                    right.type_name()
1546                ))),
1547            },
1548
1549            BinOp::And => {
1550                if !left.is_truthy() {
1551                    Ok(left.clone())
1552                } else {
1553                    Ok(right.clone())
1554                }
1555            }
1556
1557            BinOp::Or => {
1558                if left.is_truthy() {
1559                    Ok(left.clone())
1560                } else {
1561                    Ok(right.clone())
1562                }
1563            }
1564        }
1565    }
1566
1567    /// Evaluate unary operation
1568    fn eval_unary_op(&self, op: &UnaryOp, val: &Value) -> EvalResult {
1569        match op {
1570            UnaryOp::Minus => match val {
1571                Value::Number(n) => Ok(Value::Number(-n)),
1572                _ => Err(RuntimeError::TypeError(format!(
1573                    "Cannot negate {}",
1574                    val.type_name()
1575                ))),
1576            },
1577
1578            UnaryOp::Not => Ok(Value::Boolean(!val.is_truthy())),
1579        }
1580    }
1581
1582    /// Call a function with arguments
1583    fn call_function(
1584        &mut self,
1585        name_hint: Option<&str>,
1586        func: &Value,
1587        args: Vec<Value>,
1588    ) -> EvalResult {
1589        // Check recursion depth limit
1590        self.enter_call()?;
1591
1592        let frame = match func {
1593            Value::Function { name, params, .. } => {
1594                let display_name = name_hint
1595                    .map(|s| s.to_string())
1596                    .or_else(|| name.clone())
1597                    .unwrap_or_else(|| "<lambda>".to_string());
1598                let signature = format!("{}({})", display_name, params.join(", "));
1599                CallFrame {
1600                    name: display_name.clone(),
1601                    signature,
1602                }
1603            }
1604            Value::BuiltIn { name, .. } => {
1605                let arity = self.registry.get(name).map(|(_, a)| a).unwrap_or(0);
1606                let params = if arity == 0 {
1607                    String::new()
1608                } else {
1609                    (1..=arity)
1610                        .map(|i| format!("arg{}", i))
1611                        .collect::<Vec<_>>()
1612                        .join(", ")
1613                };
1614                let signature = format!("{}({})", name, params);
1615                CallFrame {
1616                    name: name.clone(),
1617                    signature,
1618                }
1619            }
1620            other => {
1621                let name = name_hint.unwrap_or("<call>").to_string();
1622                let signature = format!("{}(<{}>)", name, other.type_name());
1623                CallFrame { name, signature }
1624            }
1625        };
1626
1627        self.call_stack.push(frame);
1628
1629        match func {
1630            Value::Function {
1631                params, body, env, ..
1632            } => {
1633                if params.len() != args.len() {
1634                    let err = RuntimeError::WrongArity {
1635                        expected: params.len(),
1636                        got: args.len(),
1637                    };
1638                    let err = self.attach_call_stack_if_absent(err);
1639                    let _ = self.call_stack.pop();
1640                    self.exit_call();
1641                    return Err(err);
1642                }
1643
1644                // Create new environment for function execution
1645                let func_env = Rc::new(RefCell::new(Environment::with_parent(Rc::clone(env))));
1646
1647                // Bind parameters
1648                for (param, arg) in params.iter().zip(args.iter()) {
1649                    func_env.borrow_mut().set(param.clone(), arg.clone());
1650                }
1651
1652                // Execute function body
1653                let prev_env = Rc::clone(&self.env);
1654                self.env = func_env;
1655
1656                let mut result = Value::Null;
1657                for stmt in body {
1658                    match self.eval_statement(stmt) {
1659                        Ok(val) => result = val,
1660                        Err(RuntimeError::Return(val)) => {
1661                            result = val;
1662                            break;
1663                        }
1664                        Err(e) => {
1665                            self.env = prev_env;
1666                            let e = self.attach_call_stack_if_absent(e);
1667                            let _ = self.call_stack.pop();
1668                            self.exit_call();
1669                            return Err(e);
1670                        }
1671                    }
1672                }
1673
1674                self.env = prev_env;
1675                let _ = self.call_stack.pop();
1676                self.exit_call();
1677                Ok(result)
1678            }
1679
1680            Value::BuiltIn { name, .. } => {
1681                // Special handling for TRACE functions
1682                let res = match name.as_str() {
1683                    "TRACE" => {
1684                        if args.is_empty() {
1685                            return {
1686                                let err = RuntimeError::WrongArity {
1687                                    expected: 1,
1688                                    got: 0,
1689                                };
1690                                let err = self.attach_call_stack_if_absent(err);
1691                                let _ = self.call_stack.pop();
1692                                self.exit_call();
1693                                Err(err)
1694                            };
1695                        }
1696
1697                        // Optional label: TRACE("label", x, y)
1698                        // If only one argument is provided, treat it as the payload (backward compatible).
1699                        let (label, payload_args) = if args.len() >= 2 {
1700                            match &args[0] {
1701                                Value::String(s) => (Some(s.as_str()), &args[1..]),
1702                                _ => (None, args.as_slice()),
1703                            }
1704                        } else {
1705                            (None, args.as_slice())
1706                        };
1707
1708                        let payload = payload_args
1709                            .iter()
1710                            .map(|v| v.to_string())
1711                            .collect::<Vec<_>>()
1712                            .join(" ");
1713
1714                        let msg = match label {
1715                            Some(l) => format!("[{}] {}", l, payload),
1716                            None => payload,
1717                        };
1718
1719                        self.trace_push(msg);
1720                        Ok(Value::Null)
1721                    }
1722                    "TRACE_DEBUG" | "TRACE_INFO" | "TRACE_WARN" | "TRACE_ERROR" => {
1723                        // Structured TRACE functions (Stage 3.2)
1724                        // Usage: TRACE_DEBUG("category", value1, value2, ...)
1725                        if args.len() < 2 {
1726                            return {
1727                                let err = RuntimeError::WrongArity {
1728                                    expected: 2,
1729                                    got: args.len(),
1730                                };
1731                                let err = self.attach_call_stack_if_absent(err);
1732                                let _ = self.call_stack.pop();
1733                                self.exit_call();
1734                                Err(err)
1735                            };
1736                        }
1737
1738                        // Parse level from function name
1739                        let level = match name.as_str() {
1740                            "TRACE_DEBUG" => crate::runtime::TraceLevel::Debug,
1741                            "TRACE_INFO" => crate::runtime::TraceLevel::Info,
1742                            "TRACE_WARN" => crate::runtime::TraceLevel::Warn,
1743                            "TRACE_ERROR" => crate::runtime::TraceLevel::Error,
1744                            _ => unreachable!(),
1745                        };
1746
1747                        // Parse category
1748                        let category = match &args[0] {
1749                            Value::String(s) => s.clone(),
1750                            _ => {
1751                                return {
1752                                    let err = RuntimeError::CustomError(format!(
1753                                        "TRACE category must be a string, got {}",
1754                                        args[0].type_name()
1755                                    ));
1756                                    let err = self.attach_call_stack_if_absent(err);
1757                                    let _ = self.call_stack.pop();
1758                                    self.exit_call();
1759                                    Err(err)
1760                                };
1761                            }
1762                        };
1763
1764                        // Collect values (args[1..])
1765                        let values = args[1..].to_vec();
1766
1767                        // Create and push structured entry
1768                        let entry = crate::runtime::TraceEntry::new(level, category, values);
1769                        self.trace_push_entry(entry);
1770
1771                        Ok(Value::Null)
1772                    }
1773                    "MAP" => self.builtin_map(&args),
1774                    "FILTER" => self.builtin_filter(&args),
1775                    "REDUCE" => self.builtin_reduce(&args),
1776                    _ => {
1777                        // Get the built-in function from the registry
1778                        if let Some((func, _arity)) = self.registry.get(name) {
1779                            // Call the built-in function
1780                            func(&args)
1781                        } else {
1782                            Err(RuntimeError::NotCallable(format!(
1783                                "Built-in function '{}' not found",
1784                                name
1785                            )))
1786                        }
1787                    }
1788                };
1789
1790                let _ = self.call_stack.pop();
1791                self.exit_call();
1792                match res {
1793                    Ok(v) => Ok(v),
1794                    Err(e) => Err(self.attach_call_stack_if_absent(e)),
1795                }
1796            }
1797
1798            _ => {
1799                let err = RuntimeError::NotCallable(func.type_name().to_string());
1800                let err = self.attach_call_stack_if_absent(err);
1801                let _ = self.call_stack.pop();
1802                self.exit_call();
1803                Err(err)
1804            }
1805        }
1806    }
1807
1808    // 实现 MAP 内置函数
1809    fn builtin_map(&mut self, args: &[Value]) -> EvalResult {
1810        if args.len() != 2 {
1811            return Err(RuntimeError::WrongArity {
1812                expected: 2,
1813                got: args.len(),
1814            });
1815        }
1816
1817        let arr = match &args[0] {
1818            Value::Array(a) => a,
1819            other => {
1820                return Err(RuntimeError::TypeErrorDetailed {
1821                    expected: "Array".to_string(),
1822                    got: format!("{:?}", other),
1823                });
1824            }
1825        };
1826
1827        let func = &args[1];
1828
1829        let mut result = Vec::new();
1830        for item in arr {
1831            let mapped = self.call_function(None, func, vec![item.clone()])?;
1832            result.push(mapped);
1833        }
1834
1835        Ok(Value::Array(result))
1836    }
1837
1838    // 实现 FILTER 内置函数
1839    fn builtin_filter(&mut self, args: &[Value]) -> EvalResult {
1840        if args.len() != 2 {
1841            return Err(RuntimeError::WrongArity {
1842                expected: 2,
1843                got: args.len(),
1844            });
1845        }
1846
1847        let arr = match &args[0] {
1848            Value::Array(a) => a,
1849            other => {
1850                return Err(RuntimeError::TypeErrorDetailed {
1851                    expected: "Array".to_string(),
1852                    got: format!("{:?}", other),
1853                });
1854            }
1855        };
1856
1857        let predicate = &args[1];
1858
1859        let mut result = Vec::new();
1860        for item in arr {
1861            let test_result = self.call_function(None, predicate, vec![item.clone()])?;
1862            if test_result.is_truthy() {
1863                result.push(item.clone());
1864            }
1865        }
1866
1867        Ok(Value::Array(result))
1868    }
1869
1870    // 实现 REDUCE 内置函数
1871    fn builtin_reduce(&mut self, args: &[Value]) -> EvalResult {
1872        if args.len() != 3 {
1873            return Err(RuntimeError::WrongArity {
1874                expected: 3,
1875                got: args.len(),
1876            });
1877        }
1878
1879        let arr = match &args[0] {
1880            Value::Array(a) => a,
1881            other => {
1882                return Err(RuntimeError::TypeErrorDetailed {
1883                    expected: "Array".to_string(),
1884                    got: format!("{:?}", other),
1885                });
1886            }
1887        };
1888
1889        let mut accumulator = args[1].clone();
1890        let func = &args[2];
1891
1892        for item in arr {
1893            accumulator = self.call_function(None, func, vec![accumulator, item.clone()])?;
1894        }
1895
1896        Ok(accumulator)
1897    }
1898}
1899
1900impl Evaluator {
1901    fn import_chain(&self) -> Vec<String> {
1902        self.import_base_stack
1903            .iter()
1904            .map(|c| c.module_id.clone())
1905            .collect()
1906    }
1907
1908    fn import_chain_with(&self, leaf: impl Into<String>) -> Vec<String> {
1909        let mut chain = self.import_chain();
1910        chain.push(leaf.into());
1911        chain
1912    }
1913
1914    fn current_import_context(&self) -> Option<&ModuleContext> {
1915        self.import_base_stack.last()
1916    }
1917
1918    fn eval_import(
1919        &mut self,
1920        names: &[String],
1921        specifier: &str,
1922        aliases: &[Option<String>],
1923        namespace: Option<&String>,
1924    ) -> EvalResult {
1925        let from_ctx = self.current_import_context();
1926
1927        let chain_for_resolve = self.import_chain_with(specifier.to_string());
1928
1929        let resolved = self
1930            .module_resolver
1931            .resolve(specifier, from_ctx)
1932            .map_err(|e| {
1933                RuntimeError::ImportError(Box::new(ImportError::from_resolve_error(
1934                    specifier,
1935                    e,
1936                    chain_for_resolve,
1937                )))
1938            })?;
1939
1940        let exports = self.load_module(resolved)?;
1941
1942        if let Some(ns) = namespace {
1943            self.env.borrow_mut().set(ns.clone(), Value::Dict(exports));
1944            return Ok(Value::Null);
1945        }
1946
1947        for (i, name) in names.iter().enumerate() {
1948            let alias = aliases
1949                .get(i)
1950                .and_then(|a| a.clone())
1951                .unwrap_or_else(|| name.clone());
1952            let v = exports.get(name).cloned().ok_or_else(|| {
1953                RuntimeError::ImportError(Box::new(ImportError::not_exported(
1954                    specifier,
1955                    name,
1956                    self.import_chain_with(specifier.to_string()),
1957                )))
1958            })?;
1959            self.env.borrow_mut().set(alias, v);
1960        }
1961
1962        Ok(Value::Null)
1963    }
1964
1965    fn eval_export(&mut self, name: &str) -> EvalResult {
1966        let exports = self.export_stack.last_mut().ok_or_else(|| {
1967            RuntimeError::CustomError("Export error: Export used outside of a module".to_string())
1968        })?;
1969
1970        let val = self.env.borrow().get(name).ok_or_else(|| {
1971            RuntimeError::CustomError(format!("Export error: '{}' is not defined", name))
1972        })?;
1973
1974        exports.insert(name.to_string(), val);
1975        Ok(Value::Null)
1976    }
1977
1978    fn load_module(
1979        &mut self,
1980        resolved: ResolvedModule,
1981    ) -> Result<HashMap<String, Value>, RuntimeError> {
1982        let import_chain = self.import_chain_with(resolved.module_id.clone());
1983
1984        if let Some(cached) = self.module_cache.get(&resolved.module_id) {
1985            return Ok(cached.clone());
1986        }
1987
1988        if self.module_stack.contains(&resolved.module_id) {
1989            let mut chain = self.module_stack.clone();
1990            chain.push(resolved.module_id.clone());
1991            return Err(RuntimeError::ImportError(Box::new(ImportError::circular(
1992                &resolved.module_id,
1993                chain,
1994                import_chain,
1995            ))));
1996        }
1997
1998        self.module_stack.push(resolved.module_id.clone());
1999
2000        // Parse module
2001        let mut parser = crate::parser::Parser::new(&resolved.source);
2002        let program = match parser.parse_program() {
2003            Ok(p) => p,
2004            Err(e) => {
2005                let _ = self.module_stack.pop();
2006                return Err(RuntimeError::ImportError(Box::new(
2007                    ImportError::parse_failed(&resolved.module_id, e.to_string(), import_chain),
2008                )));
2009            }
2010        };
2011
2012        // Evaluate in an isolated environment with builtins registered.
2013        let prev_env = Rc::clone(&self.env);
2014        let module_env = Rc::new(RefCell::new(Environment::new()));
2015        Self::register_builtins_into_env(&self.registry, &mut module_env.borrow_mut());
2016        self.env = module_env;
2017
2018        // Push module import base (for relative imports inside the module)
2019        self.import_base_stack.push(ModuleContext {
2020            module_id: resolved.module_id.clone(),
2021            base_dir: resolved.base_dir.clone(),
2022        });
2023
2024        // Push export table
2025        self.export_stack.push(HashMap::new());
2026
2027        let eval_res = self.eval_program(&program);
2028
2029        // Pop stacks and restore env (must happen even on error)
2030        let exports = self.export_stack.pop().unwrap_or_default();
2031        self.import_base_stack.pop();
2032        self.env = prev_env;
2033
2034        // Pop module stack
2035        let _ = self.module_stack.pop();
2036
2037        // Propagate module evaluation error (cleanup already done)
2038        let _ = eval_res.map_err(|e| self.attach_call_stack_if_absent(e))?;
2039
2040        self.module_cache
2041            .insert(resolved.module_id.clone(), exports.clone());
2042        Ok(exports)
2043    }
2044}
2045
2046impl Default for Evaluator {
2047    fn default() -> Self {
2048        Self::new()
2049    }
2050}
2051
2052#[cfg(test)]
2053mod tests {
2054    use super::*;
2055    use crate::parser::Parser;
2056
2057    fn eval(code: &str) -> EvalResult {
2058        let mut parser = Parser::new(code);
2059        let program = parser.parse_program().unwrap();
2060        let mut evaluator = Evaluator::new();
2061        evaluator.eval_program(&program)
2062    }
2063
2064    #[test]
2065    fn test_eval_numbers() {
2066        assert_eq!(eval("42").unwrap(), Value::Number(42.0));
2067        #[allow(clippy::approx_constant)]
2068        {
2069            assert_eq!(eval("3.14").unwrap(), Value::Number(3.14));
2070        }
2071    }
2072
2073    #[test]
2074    fn test_eval_strings() {
2075        assert_eq!(
2076            eval(r#""hello""#).unwrap(),
2077            Value::String("hello".to_string())
2078        );
2079    }
2080
2081    #[test]
2082    fn test_eval_booleans() {
2083        assert_eq!(eval("True").unwrap(), Value::Boolean(true));
2084        assert_eq!(eval("False").unwrap(), Value::Boolean(false));
2085    }
2086
2087    #[test]
2088    fn test_eval_arithmetic() {
2089        assert_eq!(eval("(5 + 3)").unwrap(), Value::Number(8.0));
2090        assert_eq!(eval("(10 - 3)").unwrap(), Value::Number(7.0));
2091        assert_eq!(eval("(4 * 3)").unwrap(), Value::Number(12.0));
2092        assert_eq!(eval("(10 / 2)").unwrap(), Value::Number(5.0));
2093        assert_eq!(eval("(10 % 3)").unwrap(), Value::Number(1.0));
2094    }
2095
2096    #[test]
2097    fn test_eval_arithmetic_precedence() {
2098        assert_eq!(eval("(5 + 3 * 2)").unwrap(), Value::Number(11.0));
2099        assert_eq!(eval("((5 + 3) * 2)").unwrap(), Value::Number(16.0));
2100    }
2101
2102    #[test]
2103    fn test_eval_comparison() {
2104        assert_eq!(eval("(5 < 10)").unwrap(), Value::Boolean(true));
2105        assert_eq!(eval("(10 < 5)").unwrap(), Value::Boolean(false));
2106        assert_eq!(eval("(5 == 5)").unwrap(), Value::Boolean(true));
2107        assert_eq!(eval("(5 != 3)").unwrap(), Value::Boolean(true));
2108    }
2109
2110    #[test]
2111    fn test_eval_logical() {
2112        assert_eq!(eval("(True && False)").unwrap(), Value::Boolean(false));
2113        assert_eq!(eval("(True || False)").unwrap(), Value::Boolean(true));
2114        assert_eq!(eval("(!True)").unwrap(), Value::Boolean(false));
2115    }
2116
2117    #[test]
2118    fn test_eval_set() {
2119        let code = r#"
2120            Set X 42
2121            X
2122        "#;
2123        assert_eq!(eval(code).unwrap(), Value::Number(42.0));
2124    }
2125
2126    #[test]
2127    fn test_eval_function() {
2128        let code = r#"
2129            Func ADD (A, B) {
2130                Return (A + B)
2131            }
2132            ADD(5, 3)
2133        "#;
2134        assert_eq!(eval(code).unwrap(), Value::Number(8.0));
2135    }
2136
2137    #[test]
2138    fn test_eval_array() {
2139        let code = "[1, 2, 3]";
2140        let result = eval(code).unwrap();
2141        match result {
2142            Value::Array(arr) => {
2143                assert_eq!(arr.len(), 3);
2144                assert_eq!(arr[0], Value::Number(1.0));
2145                assert_eq!(arr[1], Value::Number(2.0));
2146                assert_eq!(arr[2], Value::Number(3.0));
2147            }
2148            _ => panic!("Expected array"),
2149        }
2150    }
2151
2152    #[test]
2153    fn test_eval_array_index() {
2154        let code = r#"
2155            Set ARR [10, 20, 30]
2156            ARR[1]
2157        "#;
2158        assert_eq!(eval(code).unwrap(), Value::Number(20.0));
2159    }
2160
2161    #[test]
2162    fn test_eval_if() {
2163        let code = r#"
2164            If (True) {
2165                Set X 42
2166            } Else {
2167                Set X 0
2168            }
2169            X
2170        "#;
2171        assert_eq!(eval(code).unwrap(), Value::Number(42.0));
2172    }
2173
2174    #[test]
2175    fn test_eval_for() {
2176        let code = r#"
2177            Set SUM 0
2178            For I In [1, 2, 3] {
2179                Set SUM (SUM + I)
2180            }
2181            SUM
2182        "#;
2183        assert_eq!(eval(code).unwrap(), Value::Number(6.0));
2184    }
2185}