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    /// Enter a child scope (new environment whose parent is the current env).
831    ///
832    /// Returns the previous environment handle; pass it back to `restore_env()`.
833    pub fn enter_child_scope(&mut self) -> Rc<RefCell<Environment>> {
834        let prev = Rc::clone(&self.env);
835        let child = Rc::new(RefCell::new(Environment::with_parent(Rc::clone(&prev))));
836        self.env = child;
837        prev
838    }
839
840    /// Restore a previously saved environment handle (typically from `enter_child_scope()`).
841    pub fn restore_env(&mut self, prev: Rc<RefCell<Environment>>) {
842        self.env = prev;
843    }
844
845    /// Evaluate a program
846    pub fn eval_program(&mut self, program: &Program) -> EvalResult {
847        // Record start time for timeout checking
848        if self.limits.max_duration_ms.is_some() {
849            self.start_time.set(Some(std::time::Instant::now()));
850        }
851
852        let mut result = Value::Null;
853
854        for stmt in program {
855            result = self.eval_statement(stmt)?;
856        }
857
858        Ok(result)
859    }
860
861    /// Evaluate a statement
862    pub fn eval_statement(&mut self, stmt: &Stmt) -> EvalResult {
863        // Check execution limits before each statement
864        self.eval_step()?;
865        self.check_timeout()?;
866
867        match stmt {
868            Stmt::Set { name, value } => {
869                let val = self.eval_expression(value)?;
870                self.env.borrow_mut().set(name.clone(), val.clone());
871                Ok(val)
872            }
873
874            Stmt::SetIndex {
875                object,
876                index,
877                value,
878            } => {
879                // Evaluate the value to be assigned
880                let val = self.eval_expression(value)?;
881
882                // For simple identifier objects, we can modify in place
883                if let Expr::Identifier(name) = object.as_ref() {
884                    // Get the object from environment
885                    let obj = self
886                        .env
887                        .borrow()
888                        .get(name)
889                        .ok_or_else(|| RuntimeError::UndefinedVariable(name.clone()))?;
890
891                    // Evaluate the index
892                    let idx_val = self.eval_expression(index)?;
893
894                    // Modify based on object type
895                    let new_obj = match (obj, idx_val) {
896                        (Value::Array(mut arr), Value::Number(n)) => {
897                            let idx = n as usize;
898                            if idx >= arr.len() {
899                                return Err(RuntimeError::InvalidOperation(format!(
900                                    "Index {} out of bounds (array length: {})",
901                                    idx,
902                                    arr.len()
903                                )));
904                            }
905                            arr[idx] = val.clone();
906                            Value::Array(arr)
907                        }
908                        (Value::Dict(mut dict), Value::String(key)) => {
909                            dict.insert(key, val.clone());
910                            Value::Dict(dict)
911                        }
912                        (obj, idx) => {
913                            return Err(RuntimeError::TypeError(format!(
914                                "Cannot index {} with {}",
915                                obj.type_name(),
916                                idx.type_name()
917                            )));
918                        }
919                    };
920
921                    // Update the variable in environment
922                    self.env.borrow_mut().set(name.clone(), new_obj);
923                    Ok(val)
924                } else {
925                    // For complex expressions, we can't modify in place
926                    Err(RuntimeError::InvalidOperation(
927                        "Can only assign to simple variable indices (e.g., dict[key], not expr[key])"
928                            .to_string(),
929                    ))
930                }
931            }
932
933            Stmt::FuncDef { name, params, body } => {
934                let func = Value::Function {
935                    name: Some(name.clone()),
936                    params: params.clone(),
937                    body: body.clone(),
938                    env: Rc::clone(&self.env),
939                };
940                self.env.borrow_mut().set(name.clone(), func.clone());
941                Ok(func)
942            }
943
944            Stmt::GeneratorDef { name, params, body } => {
945                let r#gen = Value::Generator {
946                    params: params.clone(),
947                    body: body.clone(),
948                    env: Rc::clone(&self.env),
949                    state: GeneratorState::NotStarted,
950                };
951                self.env.borrow_mut().set(name.clone(), r#gen.clone());
952                Ok(r#gen)
953            }
954
955            Stmt::LazyDef { name, expr } => {
956                let lazy = Value::Lazy {
957                    expr: expr.clone(),
958                    env: Rc::clone(&self.env),
959                    cached: None,
960                };
961                self.env.borrow_mut().set(name.clone(), lazy.clone());
962                Ok(lazy)
963            }
964
965            Stmt::Return(expr) => {
966                let val = self.eval_expression(expr)?;
967                Err(RuntimeError::Return(val))
968            }
969
970            Stmt::Yield(expr) => {
971                let val = self.eval_expression(expr)?;
972                Err(RuntimeError::Yield(val))
973            }
974
975            Stmt::Break => Err(RuntimeError::Break),
976
977            Stmt::Continue => Err(RuntimeError::Continue),
978
979            Stmt::While { condition, body } => {
980                let mut result = Value::Null;
981
982                loop {
983                    let cond = self.eval_expression(condition)?;
984                    if !cond.is_truthy() {
985                        break;
986                    }
987
988                    let mut should_break = false;
989                    for stmt in body {
990                        match self.eval_statement(stmt) {
991                            Ok(val) => result = val,
992                            Err(RuntimeError::Break) => {
993                                should_break = true;
994                                break;
995                            }
996                            Err(RuntimeError::Continue) => break,
997                            Err(e) => return Err(e),
998                        }
999                    }
1000
1001                    if should_break {
1002                        break;
1003                    }
1004                }
1005
1006                Ok(result)
1007            }
1008
1009            Stmt::For {
1010                var,
1011                iterable,
1012                body,
1013            } => {
1014                let iter_val = self.eval_expression(iterable)?;
1015                let mut result = Value::Null;
1016
1017                match iter_val {
1018                    Value::Array(arr) => {
1019                        let mut should_break = false;
1020                        for item in arr {
1021                            self.env.borrow_mut().set(var.clone(), item);
1022                            for stmt in body {
1023                                match self.eval_statement(stmt) {
1024                                    Ok(val) => result = val,
1025                                    Err(RuntimeError::Break) => {
1026                                        should_break = true;
1027                                        break;
1028                                    }
1029                                    Err(RuntimeError::Continue) => break,
1030                                    Err(e) => return Err(e),
1031                                }
1032                            }
1033                            if should_break {
1034                                break;
1035                            }
1036                        }
1037                    }
1038                    _ => {
1039                        return Err(RuntimeError::TypeError(format!(
1040                            "Cannot iterate over {}",
1041                            iter_val.type_name()
1042                        )));
1043                    }
1044                }
1045
1046                Ok(result)
1047            }
1048
1049            Stmt::ForIndexed {
1050                index_var,
1051                value_var,
1052                iterable,
1053                body,
1054            } => {
1055                let iter_val = self.eval_expression(iterable)?;
1056                let mut result = Value::Null;
1057
1058                match iter_val {
1059                    Value::Array(arr) => {
1060                        let mut should_break = false;
1061                        for (idx, item) in arr.iter().enumerate() {
1062                            self.env
1063                                .borrow_mut()
1064                                .set(index_var.clone(), Value::Number(idx as f64));
1065                            self.env.borrow_mut().set(value_var.clone(), item.clone());
1066                            for stmt in body {
1067                                match self.eval_statement(stmt) {
1068                                    Ok(val) => result = val,
1069                                    Err(RuntimeError::Break) => {
1070                                        should_break = true;
1071                                        break;
1072                                    }
1073                                    Err(RuntimeError::Continue) => break,
1074                                    Err(e) => return Err(e),
1075                                }
1076                            }
1077                            if should_break {
1078                                break;
1079                            }
1080                        }
1081                    }
1082                    _ => {
1083                        return Err(RuntimeError::TypeError(format!(
1084                            "Cannot iterate over {}",
1085                            iter_val.type_name()
1086                        )));
1087                    }
1088                }
1089
1090                Ok(result)
1091            }
1092
1093            Stmt::Switch {
1094                expr,
1095                cases,
1096                default,
1097            } => {
1098                let val = self.eval_expression(expr)?;
1099
1100                for (case_expr, case_body) in cases {
1101                    let case_val = self.eval_expression(case_expr)?;
1102                    if val.equals(&case_val) {
1103                        let mut result = Value::Null;
1104                        for stmt in case_body {
1105                            result = self.eval_statement(stmt)?;
1106                        }
1107                        return Ok(result);
1108                    }
1109                }
1110
1111                if let Some(default_body) = default {
1112                    let mut result = Value::Null;
1113                    for stmt in default_body {
1114                        result = self.eval_statement(stmt)?;
1115                    }
1116                    return Ok(result);
1117                }
1118
1119                Ok(Value::Null)
1120            }
1121
1122            Stmt::Import {
1123                names,
1124                path,
1125                aliases,
1126                namespace,
1127            } => self.eval_import(names, path, aliases, namespace.as_ref()),
1128
1129            Stmt::Export(name) => self.eval_export(name),
1130
1131            Stmt::Throw(expr) => {
1132                let val = self.eval_expression(expr)?;
1133                Err(RuntimeError::Throw(val))
1134            }
1135
1136            Stmt::Expression(expr) => self.eval_expression(expr),
1137        }
1138    }
1139
1140    /// Evaluate an expression
1141    pub fn eval_expression(&mut self, expr: &Expr) -> EvalResult {
1142        match expr {
1143            Expr::Number(n) => Ok(Value::Number(*n)),
1144
1145            Expr::BigInteger(s) => {
1146                // 将大整数字符串转换为 Fraction (分母为1的分数)
1147                use num_bigint::BigInt;
1148                use num_rational::Ratio;
1149
1150                match s.parse::<BigInt>() {
1151                    Ok(big_int) => Ok(Value::Fraction(Ratio::new(big_int, BigInt::from(1)))),
1152                    Err(_) => Err(RuntimeError::InvalidOperation(format!(
1153                        "Invalid big integer: {}",
1154                        s
1155                    ))),
1156                }
1157            }
1158
1159            Expr::String(s) => Ok(Value::String(s.clone())),
1160
1161            Expr::Boolean(b) => Ok(Value::Boolean(*b)),
1162
1163            Expr::Null => Ok(Value::Null),
1164
1165            Expr::Identifier(name) => self
1166                .env
1167                .borrow()
1168                .get(name)
1169                .ok_or_else(|| RuntimeError::UndefinedVariable(name.clone())),
1170
1171            Expr::Binary { left, op, right } => {
1172                // Short-circuit evaluation for And and Or
1173                match op {
1174                    BinOp::And => {
1175                        let left_val = self.eval_expression(left)?;
1176                        if !left_val.is_truthy() {
1177                            // Short-circuit: left is falsy, return left without evaluating right
1178                            Ok(left_val)
1179                        } else {
1180                            // left is truthy, return right value
1181                            self.eval_expression(right)
1182                        }
1183                    }
1184                    BinOp::Or => {
1185                        let left_val = self.eval_expression(left)?;
1186                        if left_val.is_truthy() {
1187                            // Short-circuit: left is truthy, return left without evaluating right
1188                            Ok(left_val)
1189                        } else {
1190                            // left is falsy, return right value
1191                            self.eval_expression(right)
1192                        }
1193                    }
1194                    // For other operators, evaluate both sides
1195                    _ => {
1196                        let left_val = self.eval_expression(left)?;
1197                        let right_val = self.eval_expression(right)?;
1198                        self.eval_binary_op(&left_val, op, &right_val)
1199                    }
1200                }
1201            }
1202
1203            Expr::Unary { op, expr } => {
1204                let val = self.eval_expression(expr)?;
1205                self.eval_unary_op(op, &val)
1206            }
1207
1208            Expr::Call { func, args } => {
1209                let name_hint = match func.as_ref() {
1210                    Expr::Identifier(name) => Some(name.clone()),
1211                    _ => None,
1212                };
1213                let func_val = self.eval_expression(func)?;
1214                let arg_vals: Result<Vec<_>, _> =
1215                    args.iter().map(|arg| self.eval_expression(arg)).collect();
1216                let arg_vals = arg_vals?;
1217
1218                self.call_function(name_hint.as_deref(), &func_val, arg_vals)
1219            }
1220
1221            Expr::Array(elements) => {
1222                let vals: Result<Vec<_>, _> =
1223                    elements.iter().map(|e| self.eval_expression(e)).collect();
1224                Ok(Value::Array(vals?))
1225            }
1226
1227            Expr::Dict(pairs) => {
1228                let mut map = std::collections::HashMap::new();
1229                for (key, value_expr) in pairs {
1230                    let value = self.eval_expression(value_expr)?;
1231                    map.insert(key.clone(), value);
1232                }
1233                Ok(Value::Dict(map))
1234            }
1235
1236            Expr::Index { object, index } => {
1237                let obj_val = self.eval_expression(object)?;
1238                let idx_val = self.eval_expression(index)?;
1239
1240                match (obj_val, idx_val) {
1241                    (Value::Array(arr), Value::Number(n)) => {
1242                        let idx = n as usize;
1243                        arr.get(idx).cloned().ok_or_else(|| {
1244                            RuntimeError::InvalidOperation(format!("Index {} out of bounds", idx))
1245                        })
1246                    }
1247                    (Value::String(s), Value::Number(n)) => {
1248                        let idx = n as usize;
1249                        let chars: Vec<char> = s.chars().collect();
1250                        chars
1251                            .get(idx)
1252                            .cloned()
1253                            .map(|ch| Value::String(ch.to_string()))
1254                            .ok_or_else(|| {
1255                                RuntimeError::InvalidOperation(format!(
1256                                    "Index {} out of bounds (string length: {})",
1257                                    idx,
1258                                    chars.len()
1259                                ))
1260                            })
1261                    }
1262                    (Value::Dict(dict), Value::String(key)) => {
1263                        dict.get(&key).cloned().ok_or_else(|| {
1264                            RuntimeError::InvalidOperation(format!("Key '{}' not found", key))
1265                        })
1266                    }
1267                    (obj, idx) => Err(RuntimeError::TypeError(format!(
1268                        "Cannot index {} with {}",
1269                        obj.type_name(),
1270                        idx.type_name()
1271                    ))),
1272                }
1273            }
1274
1275            Expr::If {
1276                condition,
1277                then_branch,
1278                elif_branches,
1279                else_branch,
1280            } => {
1281                let cond = self.eval_expression(condition)?;
1282
1283                if cond.is_truthy() {
1284                    let mut result = Value::Null;
1285                    for stmt in then_branch {
1286                        result = self.eval_statement(stmt)?;
1287                    }
1288                    return Ok(result);
1289                }
1290
1291                for (elif_cond, elif_body) in elif_branches {
1292                    let cond = self.eval_expression(elif_cond)?;
1293                    if cond.is_truthy() {
1294                        let mut result = Value::Null;
1295                        for stmt in elif_body {
1296                            result = self.eval_statement(stmt)?;
1297                        }
1298                        return Ok(result);
1299                    }
1300                }
1301
1302                if let Some(else_body) = else_branch {
1303                    let mut result = Value::Null;
1304                    for stmt in else_body {
1305                        result = self.eval_statement(stmt)?;
1306                    }
1307                    return Ok(result);
1308                }
1309
1310                Ok(Value::Null)
1311            }
1312
1313            Expr::Lambda { params, body } => {
1314                // Create a closure by capturing the current environment
1315                Ok(Value::Function {
1316                    name: None,
1317                    params: params.clone(),
1318                    body: body.clone(),
1319                    env: Rc::clone(&self.env),
1320                })
1321            }
1322        }
1323    }
1324
1325    /// Evaluate binary operation
1326    fn eval_binary_op(&self, left: &Value, op: &BinOp, right: &Value) -> EvalResult {
1327        match op {
1328            BinOp::Add => match (left, right) {
1329                (Value::Number(a), Value::Number(b)) => Ok(Value::Number(a + b)),
1330                (Value::String(a), Value::String(b)) => Ok(Value::String(format!("{}{}", a, b))),
1331                (Value::Fraction(a), Value::Fraction(b)) => Ok(Value::Fraction(a + b)),
1332                (Value::Number(a), Value::Fraction(b)) | (Value::Fraction(b), Value::Number(a)) => {
1333                    use num_bigint::BigInt;
1334                    use num_rational::Ratio;
1335                    if a.fract() == 0.0 {
1336                        let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
1337                        Ok(Value::Fraction(a_frac + b))
1338                    } else {
1339                        // 浮点数和分数混合运算,转换为浮点数
1340                        use num_traits::ToPrimitive;
1341                        let b_float =
1342                            b.numer().to_f64().unwrap_or(0.0) / b.denom().to_f64().unwrap_or(1.0);
1343                        Ok(Value::Number(a + b_float))
1344                    }
1345                }
1346                _ => Err(RuntimeError::TypeError(format!(
1347                    "Cannot add {} and {}",
1348                    left.type_name(),
1349                    right.type_name()
1350                ))),
1351            },
1352
1353            BinOp::Subtract => match (left, right) {
1354                (Value::Number(a), Value::Number(b)) => Ok(Value::Number(a - b)),
1355                (Value::Fraction(a), Value::Fraction(b)) => Ok(Value::Fraction(a - b)),
1356                (Value::Number(a), Value::Fraction(b)) => {
1357                    use num_bigint::BigInt;
1358                    use num_rational::Ratio;
1359                    if a.fract() == 0.0 {
1360                        let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
1361                        Ok(Value::Fraction(a_frac - b))
1362                    } else {
1363                        use num_traits::ToPrimitive;
1364                        let b_float =
1365                            b.numer().to_f64().unwrap_or(0.0) / b.denom().to_f64().unwrap_or(1.0);
1366                        Ok(Value::Number(a - b_float))
1367                    }
1368                }
1369                (Value::Fraction(a), Value::Number(b)) => {
1370                    use num_bigint::BigInt;
1371                    use num_rational::Ratio;
1372                    if b.fract() == 0.0 {
1373                        let b_frac = Ratio::new(BigInt::from(*b as i64), BigInt::from(1));
1374                        Ok(Value::Fraction(a - b_frac))
1375                    } else {
1376                        use num_traits::ToPrimitive;
1377                        let a_float =
1378                            a.numer().to_f64().unwrap_or(0.0) / a.denom().to_f64().unwrap_or(1.0);
1379                        Ok(Value::Number(a_float - b))
1380                    }
1381                }
1382                _ => Err(RuntimeError::TypeError(format!(
1383                    "Cannot subtract {} from {}",
1384                    right.type_name(),
1385                    left.type_name()
1386                ))),
1387            },
1388
1389            BinOp::Multiply => match (left, right) {
1390                (Value::Number(a), Value::Number(b)) => {
1391                    // 如果两个数都是整数,且足够大,使用精确计算
1392                    if a.fract() == 0.0 && b.fract() == 0.0 {
1393                        // 检查是否超过 f64 的安全整数范围 (2^53)
1394                        let max_safe = 9007199254740992.0; // 2^53
1395                        if a.abs() > max_safe || b.abs() > max_safe {
1396                            // 使用 Fraction (BigInt) 进行精确计算
1397                            use num_bigint::BigInt;
1398                            use num_rational::Ratio;
1399
1400                            // 将 f64 转换为字符串再转为 BigInt,避免精度损失
1401                            let a_str = format!("{:.0}", a);
1402                            let b_str = format!("{:.0}", b);
1403
1404                            if let (Ok(a_big), Ok(b_big)) =
1405                                (a_str.parse::<BigInt>(), b_str.parse::<BigInt>())
1406                            {
1407                                let result_big = a_big * b_big;
1408                                let frac = Ratio::new(result_big, BigInt::from(1));
1409                                return Ok(Value::Fraction(frac));
1410                            }
1411                        }
1412                    }
1413                    Ok(Value::Number(a * b))
1414                }
1415                (Value::Fraction(a), Value::Fraction(b)) => Ok(Value::Fraction(a * b)),
1416                (Value::Number(a), Value::Fraction(b)) | (Value::Fraction(b), Value::Number(a)) => {
1417                    use num_bigint::BigInt;
1418                    use num_rational::Ratio;
1419                    if a.fract() == 0.0 {
1420                        let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
1421                        Ok(Value::Fraction(a_frac * b))
1422                    } else {
1423                        Err(RuntimeError::TypeError(
1424                            "Cannot multiply non-integer Number with Fraction".to_string(),
1425                        ))
1426                    }
1427                }
1428                _ => Err(RuntimeError::TypeError(format!(
1429                    "Cannot multiply {} and {}",
1430                    left.type_name(),
1431                    right.type_name()
1432                ))),
1433            },
1434
1435            BinOp::Divide => match (left, right) {
1436                (Value::Number(a), Value::Number(b)) => {
1437                    if *b == 0.0 {
1438                        Err(RuntimeError::DivisionByZero)
1439                    } else {
1440                        Ok(Value::Number(a / b))
1441                    }
1442                }
1443                (Value::Fraction(a), Value::Fraction(b)) => {
1444                    use num_traits::Zero;
1445                    if b.is_zero() {
1446                        Err(RuntimeError::DivisionByZero)
1447                    } else {
1448                        Ok(Value::Fraction(a / b))
1449                    }
1450                }
1451                (Value::Number(a), Value::Fraction(b)) => {
1452                    use num_bigint::BigInt;
1453                    use num_rational::Ratio;
1454                    use num_traits::Zero;
1455                    if b.is_zero() {
1456                        Err(RuntimeError::DivisionByZero)
1457                    } else if a.fract() == 0.0 {
1458                        let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
1459                        Ok(Value::Fraction(a_frac / b))
1460                    } else {
1461                        use num_traits::ToPrimitive;
1462                        let b_float =
1463                            b.numer().to_f64().unwrap_or(0.0) / b.denom().to_f64().unwrap_or(1.0);
1464                        Ok(Value::Number(a / b_float))
1465                    }
1466                }
1467                (Value::Fraction(a), Value::Number(b)) => {
1468                    use num_bigint::BigInt;
1469                    use num_rational::Ratio;
1470                    if *b == 0.0 {
1471                        Err(RuntimeError::DivisionByZero)
1472                    } else if b.fract() == 0.0 {
1473                        let b_frac = Ratio::new(BigInt::from(*b as i64), BigInt::from(1));
1474                        Ok(Value::Fraction(a / b_frac))
1475                    } else {
1476                        use num_traits::ToPrimitive;
1477                        let a_float =
1478                            a.numer().to_f64().unwrap_or(0.0) / a.denom().to_f64().unwrap_or(1.0);
1479                        Ok(Value::Number(a_float / b))
1480                    }
1481                }
1482                _ => Err(RuntimeError::TypeError(format!(
1483                    "Cannot divide {} by {}",
1484                    left.type_name(),
1485                    right.type_name()
1486                ))),
1487            },
1488
1489            BinOp::Modulo => match (left, right) {
1490                (Value::Number(a), Value::Number(b)) => {
1491                    if *b == 0.0 {
1492                        Err(RuntimeError::DivisionByZero)
1493                    } else {
1494                        Ok(Value::Number(a % b))
1495                    }
1496                }
1497                _ => Err(RuntimeError::TypeError(format!(
1498                    "Cannot modulo {} by {}",
1499                    left.type_name(),
1500                    right.type_name()
1501                ))),
1502            },
1503
1504            BinOp::Equal => Ok(Value::Boolean(left.equals(right))),
1505
1506            BinOp::NotEqual => Ok(Value::Boolean(!left.equals(right))),
1507
1508            BinOp::Less => match left.compare(right) {
1509                Some(ord) => Ok(Value::Boolean(ord == std::cmp::Ordering::Less)),
1510                None => Err(RuntimeError::TypeError(format!(
1511                    "Cannot compare {} and {}",
1512                    left.type_name(),
1513                    right.type_name()
1514                ))),
1515            },
1516
1517            BinOp::LessEqual => match left.compare(right) {
1518                Some(ord) => Ok(Value::Boolean(ord != std::cmp::Ordering::Greater)),
1519                None => Err(RuntimeError::TypeError(format!(
1520                    "Cannot compare {} and {}",
1521                    left.type_name(),
1522                    right.type_name()
1523                ))),
1524            },
1525
1526            BinOp::Greater => match left.compare(right) {
1527                Some(ord) => Ok(Value::Boolean(ord == std::cmp::Ordering::Greater)),
1528                None => Err(RuntimeError::TypeError(format!(
1529                    "Cannot compare {} and {}",
1530                    left.type_name(),
1531                    right.type_name()
1532                ))),
1533            },
1534
1535            BinOp::GreaterEqual => match left.compare(right) {
1536                Some(ord) => Ok(Value::Boolean(ord != std::cmp::Ordering::Less)),
1537                None => Err(RuntimeError::TypeError(format!(
1538                    "Cannot compare {} and {}",
1539                    left.type_name(),
1540                    right.type_name()
1541                ))),
1542            },
1543
1544            BinOp::And => {
1545                if !left.is_truthy() {
1546                    Ok(left.clone())
1547                } else {
1548                    Ok(right.clone())
1549                }
1550            }
1551
1552            BinOp::Or => {
1553                if left.is_truthy() {
1554                    Ok(left.clone())
1555                } else {
1556                    Ok(right.clone())
1557                }
1558            }
1559        }
1560    }
1561
1562    /// Evaluate unary operation
1563    fn eval_unary_op(&self, op: &UnaryOp, val: &Value) -> EvalResult {
1564        match op {
1565            UnaryOp::Minus => match val {
1566                Value::Number(n) => Ok(Value::Number(-n)),
1567                _ => Err(RuntimeError::TypeError(format!(
1568                    "Cannot negate {}",
1569                    val.type_name()
1570                ))),
1571            },
1572
1573            UnaryOp::Not => Ok(Value::Boolean(!val.is_truthy())),
1574        }
1575    }
1576
1577    /// Call a function with arguments
1578    fn call_function(
1579        &mut self,
1580        name_hint: Option<&str>,
1581        func: &Value,
1582        args: Vec<Value>,
1583    ) -> EvalResult {
1584        // Check recursion depth limit
1585        self.enter_call()?;
1586
1587        let frame = match func {
1588            Value::Function { name, params, .. } => {
1589                let display_name = name_hint
1590                    .map(|s| s.to_string())
1591                    .or_else(|| name.clone())
1592                    .unwrap_or_else(|| "<lambda>".to_string());
1593                let signature = format!("{}({})", display_name, params.join(", "));
1594                CallFrame {
1595                    name: display_name.clone(),
1596                    signature,
1597                }
1598            }
1599            Value::BuiltIn { name, .. } => {
1600                let arity = self.registry.get(name).map(|(_, a)| a).unwrap_or(0);
1601                let params = if arity == 0 {
1602                    String::new()
1603                } else {
1604                    (1..=arity)
1605                        .map(|i| format!("arg{}", i))
1606                        .collect::<Vec<_>>()
1607                        .join(", ")
1608                };
1609                let signature = format!("{}({})", name, params);
1610                CallFrame {
1611                    name: name.clone(),
1612                    signature,
1613                }
1614            }
1615            other => {
1616                let name = name_hint.unwrap_or("<call>").to_string();
1617                let signature = format!("{}(<{}>)", name, other.type_name());
1618                CallFrame { name, signature }
1619            }
1620        };
1621
1622        self.call_stack.push(frame);
1623
1624        match func {
1625            Value::Function {
1626                params, body, env, ..
1627            } => {
1628                if params.len() != args.len() {
1629                    let err = RuntimeError::WrongArity {
1630                        expected: params.len(),
1631                        got: args.len(),
1632                    };
1633                    let err = self.attach_call_stack_if_absent(err);
1634                    let _ = self.call_stack.pop();
1635                    self.exit_call();
1636                    return Err(err);
1637                }
1638
1639                // Create new environment for function execution
1640                let func_env = Rc::new(RefCell::new(Environment::with_parent(Rc::clone(env))));
1641
1642                // Bind parameters
1643                for (param, arg) in params.iter().zip(args.iter()) {
1644                    func_env.borrow_mut().set(param.clone(), arg.clone());
1645                }
1646
1647                // Execute function body
1648                let prev_env = Rc::clone(&self.env);
1649                self.env = func_env;
1650
1651                let mut result = Value::Null;
1652                for stmt in body {
1653                    match self.eval_statement(stmt) {
1654                        Ok(val) => result = val,
1655                        Err(RuntimeError::Return(val)) => {
1656                            result = val;
1657                            break;
1658                        }
1659                        Err(e) => {
1660                            self.env = prev_env;
1661                            let e = self.attach_call_stack_if_absent(e);
1662                            let _ = self.call_stack.pop();
1663                            self.exit_call();
1664                            return Err(e);
1665                        }
1666                    }
1667                }
1668
1669                self.env = prev_env;
1670                let _ = self.call_stack.pop();
1671                self.exit_call();
1672                Ok(result)
1673            }
1674
1675            Value::BuiltIn { name, .. } => {
1676                // Special handling for TRACE functions
1677                let res = match name.as_str() {
1678                    "TRACE" => {
1679                        if args.is_empty() {
1680                            return {
1681                                let err = RuntimeError::WrongArity {
1682                                    expected: 1,
1683                                    got: 0,
1684                                };
1685                                let err = self.attach_call_stack_if_absent(err);
1686                                let _ = self.call_stack.pop();
1687                                self.exit_call();
1688                                Err(err)
1689                            };
1690                        }
1691
1692                        // Optional label: TRACE("label", x, y)
1693                        // If only one argument is provided, treat it as the payload (backward compatible).
1694                        let (label, payload_args) = if args.len() >= 2 {
1695                            match &args[0] {
1696                                Value::String(s) => (Some(s.as_str()), &args[1..]),
1697                                _ => (None, args.as_slice()),
1698                            }
1699                        } else {
1700                            (None, args.as_slice())
1701                        };
1702
1703                        let payload = payload_args
1704                            .iter()
1705                            .map(|v| v.to_string())
1706                            .collect::<Vec<_>>()
1707                            .join(" ");
1708
1709                        let msg = match label {
1710                            Some(l) => format!("[{}] {}", l, payload),
1711                            None => payload,
1712                        };
1713
1714                        self.trace_push(msg);
1715                        Ok(Value::Null)
1716                    }
1717                    "TRACE_DEBUG" | "TRACE_INFO" | "TRACE_WARN" | "TRACE_ERROR" => {
1718                        // Structured TRACE functions (Stage 3.2)
1719                        // Usage: TRACE_DEBUG("category", value1, value2, ...)
1720                        if args.len() < 2 {
1721                            return {
1722                                let err = RuntimeError::WrongArity {
1723                                    expected: 2,
1724                                    got: args.len(),
1725                                };
1726                                let err = self.attach_call_stack_if_absent(err);
1727                                let _ = self.call_stack.pop();
1728                                self.exit_call();
1729                                Err(err)
1730                            };
1731                        }
1732
1733                        // Parse level from function name
1734                        let level = match name.as_str() {
1735                            "TRACE_DEBUG" => crate::runtime::TraceLevel::Debug,
1736                            "TRACE_INFO" => crate::runtime::TraceLevel::Info,
1737                            "TRACE_WARN" => crate::runtime::TraceLevel::Warn,
1738                            "TRACE_ERROR" => crate::runtime::TraceLevel::Error,
1739                            _ => unreachable!(),
1740                        };
1741
1742                        // Parse category
1743                        let category = match &args[0] {
1744                            Value::String(s) => s.clone(),
1745                            _ => {
1746                                return {
1747                                    let err = RuntimeError::CustomError(format!(
1748                                        "TRACE category must be a string, got {}",
1749                                        args[0].type_name()
1750                                    ));
1751                                    let err = self.attach_call_stack_if_absent(err);
1752                                    let _ = self.call_stack.pop();
1753                                    self.exit_call();
1754                                    Err(err)
1755                                };
1756                            }
1757                        };
1758
1759                        // Collect values (args[1..])
1760                        let values = args[1..].to_vec();
1761
1762                        // Create and push structured entry
1763                        let entry = crate::runtime::TraceEntry::new(level, category, values);
1764                        self.trace_push_entry(entry);
1765
1766                        Ok(Value::Null)
1767                    }
1768                    "MAP" => self.builtin_map(&args),
1769                    "FILTER" => self.builtin_filter(&args),
1770                    "REDUCE" => self.builtin_reduce(&args),
1771                    _ => {
1772                        // Get the built-in function from the registry
1773                        if let Some((func, _arity)) = self.registry.get(name) {
1774                            // Call the built-in function
1775                            func(&args)
1776                        } else {
1777                            Err(RuntimeError::NotCallable(format!(
1778                                "Built-in function '{}' not found",
1779                                name
1780                            )))
1781                        }
1782                    }
1783                };
1784
1785                let _ = self.call_stack.pop();
1786                self.exit_call();
1787                match res {
1788                    Ok(v) => Ok(v),
1789                    Err(e) => Err(self.attach_call_stack_if_absent(e)),
1790                }
1791            }
1792
1793            _ => {
1794                let err = RuntimeError::NotCallable(func.type_name().to_string());
1795                let err = self.attach_call_stack_if_absent(err);
1796                let _ = self.call_stack.pop();
1797                self.exit_call();
1798                Err(err)
1799            }
1800        }
1801    }
1802
1803    // 实现 MAP 内置函数
1804    fn builtin_map(&mut self, args: &[Value]) -> EvalResult {
1805        if args.len() != 2 {
1806            return Err(RuntimeError::WrongArity {
1807                expected: 2,
1808                got: args.len(),
1809            });
1810        }
1811
1812        let arr = match &args[0] {
1813            Value::Array(a) => a,
1814            other => {
1815                return Err(RuntimeError::TypeErrorDetailed {
1816                    expected: "Array".to_string(),
1817                    got: format!("{:?}", other),
1818                });
1819            }
1820        };
1821
1822        let func = &args[1];
1823
1824        let mut result = Vec::new();
1825        for item in arr {
1826            let mapped = self.call_function(None, func, vec![item.clone()])?;
1827            result.push(mapped);
1828        }
1829
1830        Ok(Value::Array(result))
1831    }
1832
1833    // 实现 FILTER 内置函数
1834    fn builtin_filter(&mut self, args: &[Value]) -> EvalResult {
1835        if args.len() != 2 {
1836            return Err(RuntimeError::WrongArity {
1837                expected: 2,
1838                got: args.len(),
1839            });
1840        }
1841
1842        let arr = match &args[0] {
1843            Value::Array(a) => a,
1844            other => {
1845                return Err(RuntimeError::TypeErrorDetailed {
1846                    expected: "Array".to_string(),
1847                    got: format!("{:?}", other),
1848                });
1849            }
1850        };
1851
1852        let predicate = &args[1];
1853
1854        let mut result = Vec::new();
1855        for item in arr {
1856            let test_result = self.call_function(None, predicate, vec![item.clone()])?;
1857            if test_result.is_truthy() {
1858                result.push(item.clone());
1859            }
1860        }
1861
1862        Ok(Value::Array(result))
1863    }
1864
1865    // 实现 REDUCE 内置函数
1866    fn builtin_reduce(&mut self, args: &[Value]) -> EvalResult {
1867        if args.len() != 3 {
1868            return Err(RuntimeError::WrongArity {
1869                expected: 3,
1870                got: args.len(),
1871            });
1872        }
1873
1874        let arr = match &args[0] {
1875            Value::Array(a) => a,
1876            other => {
1877                return Err(RuntimeError::TypeErrorDetailed {
1878                    expected: "Array".to_string(),
1879                    got: format!("{:?}", other),
1880                });
1881            }
1882        };
1883
1884        let mut accumulator = args[1].clone();
1885        let func = &args[2];
1886
1887        for item in arr {
1888            accumulator = self.call_function(None, func, vec![accumulator, item.clone()])?;
1889        }
1890
1891        Ok(accumulator)
1892    }
1893}
1894
1895impl Evaluator {
1896    fn import_chain(&self) -> Vec<String> {
1897        self.import_base_stack
1898            .iter()
1899            .map(|c| c.module_id.clone())
1900            .collect()
1901    }
1902
1903    fn import_chain_with(&self, leaf: impl Into<String>) -> Vec<String> {
1904        let mut chain = self.import_chain();
1905        chain.push(leaf.into());
1906        chain
1907    }
1908
1909    fn current_import_context(&self) -> Option<&ModuleContext> {
1910        self.import_base_stack.last()
1911    }
1912
1913    fn eval_import(
1914        &mut self,
1915        names: &[String],
1916        specifier: &str,
1917        aliases: &[Option<String>],
1918        namespace: Option<&String>,
1919    ) -> EvalResult {
1920        let from_ctx = self.current_import_context();
1921
1922        let chain_for_resolve = self.import_chain_with(specifier.to_string());
1923
1924        let resolved = self
1925            .module_resolver
1926            .resolve(specifier, from_ctx)
1927            .map_err(|e| {
1928                RuntimeError::ImportError(Box::new(ImportError::from_resolve_error(
1929                    specifier,
1930                    e,
1931                    chain_for_resolve,
1932                )))
1933            })?;
1934
1935        let exports = self.load_module(resolved)?;
1936
1937        if let Some(ns) = namespace {
1938            self.env.borrow_mut().set(ns.clone(), Value::Dict(exports));
1939            return Ok(Value::Null);
1940        }
1941
1942        for (i, name) in names.iter().enumerate() {
1943            let alias = aliases
1944                .get(i)
1945                .and_then(|a| a.clone())
1946                .unwrap_or_else(|| name.clone());
1947            let v = exports.get(name).cloned().ok_or_else(|| {
1948                RuntimeError::ImportError(Box::new(ImportError::not_exported(
1949                    specifier,
1950                    name,
1951                    self.import_chain_with(specifier.to_string()),
1952                )))
1953            })?;
1954            self.env.borrow_mut().set(alias, v);
1955        }
1956
1957        Ok(Value::Null)
1958    }
1959
1960    fn eval_export(&mut self, name: &str) -> EvalResult {
1961        let exports = self.export_stack.last_mut().ok_or_else(|| {
1962            RuntimeError::CustomError("Export error: Export used outside of a module".to_string())
1963        })?;
1964
1965        let val = self.env.borrow().get(name).ok_or_else(|| {
1966            RuntimeError::CustomError(format!("Export error: '{}' is not defined", name))
1967        })?;
1968
1969        exports.insert(name.to_string(), val);
1970        Ok(Value::Null)
1971    }
1972
1973    fn load_module(
1974        &mut self,
1975        resolved: ResolvedModule,
1976    ) -> Result<HashMap<String, Value>, RuntimeError> {
1977        let import_chain = self.import_chain_with(resolved.module_id.clone());
1978
1979        if let Some(cached) = self.module_cache.get(&resolved.module_id) {
1980            return Ok(cached.clone());
1981        }
1982
1983        if self.module_stack.contains(&resolved.module_id) {
1984            let mut chain = self.module_stack.clone();
1985            chain.push(resolved.module_id.clone());
1986            return Err(RuntimeError::ImportError(Box::new(ImportError::circular(
1987                &resolved.module_id,
1988                chain,
1989                import_chain,
1990            ))));
1991        }
1992
1993        self.module_stack.push(resolved.module_id.clone());
1994
1995        // Parse module
1996        let mut parser = crate::parser::Parser::new(&resolved.source);
1997        let program = match parser.parse_program() {
1998            Ok(p) => p,
1999            Err(e) => {
2000                let _ = self.module_stack.pop();
2001                return Err(RuntimeError::ImportError(Box::new(
2002                    ImportError::parse_failed(&resolved.module_id, e.to_string(), import_chain),
2003                )));
2004            }
2005        };
2006
2007        // Evaluate in an isolated environment with builtins registered.
2008        let prev_env = Rc::clone(&self.env);
2009        let module_env = Rc::new(RefCell::new(Environment::new()));
2010        Self::register_builtins_into_env(&self.registry, &mut module_env.borrow_mut());
2011        self.env = module_env;
2012
2013        // Push module import base (for relative imports inside the module)
2014        self.import_base_stack.push(ModuleContext {
2015            module_id: resolved.module_id.clone(),
2016            base_dir: resolved.base_dir.clone(),
2017        });
2018
2019        // Push export table
2020        self.export_stack.push(HashMap::new());
2021
2022        let eval_res = self.eval_program(&program);
2023
2024        // Pop stacks and restore env (must happen even on error)
2025        let exports = self.export_stack.pop().unwrap_or_default();
2026        self.import_base_stack.pop();
2027        self.env = prev_env;
2028
2029        // Pop module stack
2030        let _ = self.module_stack.pop();
2031
2032        // Propagate module evaluation error (cleanup already done)
2033        let _ = eval_res.map_err(|e| self.attach_call_stack_if_absent(e))?;
2034
2035        self.module_cache
2036            .insert(resolved.module_id.clone(), exports.clone());
2037        Ok(exports)
2038    }
2039}
2040
2041impl Default for Evaluator {
2042    fn default() -> Self {
2043        Self::new()
2044    }
2045}
2046
2047#[cfg(test)]
2048mod tests {
2049    use super::*;
2050    use crate::parser::Parser;
2051
2052    fn eval(code: &str) -> EvalResult {
2053        let mut parser = Parser::new(code);
2054        let program = parser.parse_program().unwrap();
2055        let mut evaluator = Evaluator::new();
2056        evaluator.eval_program(&program)
2057    }
2058
2059    #[test]
2060    fn test_eval_numbers() {
2061        assert_eq!(eval("42").unwrap(), Value::Number(42.0));
2062        #[allow(clippy::approx_constant)]
2063        {
2064            assert_eq!(eval("3.14").unwrap(), Value::Number(3.14));
2065        }
2066    }
2067
2068    #[test]
2069    fn test_eval_strings() {
2070        assert_eq!(
2071            eval(r#""hello""#).unwrap(),
2072            Value::String("hello".to_string())
2073        );
2074    }
2075
2076    #[test]
2077    fn test_eval_booleans() {
2078        assert_eq!(eval("True").unwrap(), Value::Boolean(true));
2079        assert_eq!(eval("False").unwrap(), Value::Boolean(false));
2080    }
2081
2082    #[test]
2083    fn test_eval_arithmetic() {
2084        assert_eq!(eval("(5 + 3)").unwrap(), Value::Number(8.0));
2085        assert_eq!(eval("(10 - 3)").unwrap(), Value::Number(7.0));
2086        assert_eq!(eval("(4 * 3)").unwrap(), Value::Number(12.0));
2087        assert_eq!(eval("(10 / 2)").unwrap(), Value::Number(5.0));
2088        assert_eq!(eval("(10 % 3)").unwrap(), Value::Number(1.0));
2089    }
2090
2091    #[test]
2092    fn test_eval_arithmetic_precedence() {
2093        assert_eq!(eval("(5 + 3 * 2)").unwrap(), Value::Number(11.0));
2094        assert_eq!(eval("((5 + 3) * 2)").unwrap(), Value::Number(16.0));
2095    }
2096
2097    #[test]
2098    fn test_eval_comparison() {
2099        assert_eq!(eval("(5 < 10)").unwrap(), Value::Boolean(true));
2100        assert_eq!(eval("(10 < 5)").unwrap(), Value::Boolean(false));
2101        assert_eq!(eval("(5 == 5)").unwrap(), Value::Boolean(true));
2102        assert_eq!(eval("(5 != 3)").unwrap(), Value::Boolean(true));
2103    }
2104
2105    #[test]
2106    fn test_eval_logical() {
2107        assert_eq!(eval("(True && False)").unwrap(), Value::Boolean(false));
2108        assert_eq!(eval("(True || False)").unwrap(), Value::Boolean(true));
2109        assert_eq!(eval("(!True)").unwrap(), Value::Boolean(false));
2110    }
2111
2112    #[test]
2113    fn test_eval_set() {
2114        let code = r#"
2115            Set X 42
2116            X
2117        "#;
2118        assert_eq!(eval(code).unwrap(), Value::Number(42.0));
2119    }
2120
2121    #[test]
2122    fn test_eval_function() {
2123        let code = r#"
2124            Func ADD (A, B) {
2125                Return (A + B)
2126            }
2127            ADD(5, 3)
2128        "#;
2129        assert_eq!(eval(code).unwrap(), Value::Number(8.0));
2130    }
2131
2132    #[test]
2133    fn test_eval_array() {
2134        let code = "[1, 2, 3]";
2135        let result = eval(code).unwrap();
2136        match result {
2137            Value::Array(arr) => {
2138                assert_eq!(arr.len(), 3);
2139                assert_eq!(arr[0], Value::Number(1.0));
2140                assert_eq!(arr[1], Value::Number(2.0));
2141                assert_eq!(arr[2], Value::Number(3.0));
2142            }
2143            _ => panic!("Expected array"),
2144        }
2145    }
2146
2147    #[test]
2148    fn test_eval_array_index() {
2149        let code = r#"
2150            Set ARR [10, 20, 30]
2151            ARR[1]
2152        "#;
2153        assert_eq!(eval(code).unwrap(), Value::Number(20.0));
2154    }
2155
2156    #[test]
2157    fn test_eval_if() {
2158        let code = r#"
2159            If (True) {
2160                Set X 42
2161            } Else {
2162                Set X 0
2163            }
2164            X
2165        "#;
2166        assert_eq!(eval(code).unwrap(), Value::Number(42.0));
2167    }
2168
2169    #[test]
2170    fn test_eval_for() {
2171        let code = r#"
2172            Set SUM 0
2173            For I In [1, 2, 3] {
2174                Set SUM (SUM + I)
2175            }
2176            SUM
2177        "#;
2178        assert_eq!(eval(code).unwrap(), Value::Number(6.0));
2179    }
2180}