1use 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#[derive(Debug, Clone, PartialEq)]
150pub enum RuntimeError {
151 UndefinedVariable(String),
153
154 TypeError(String),
156
157 TypeErrorDetailed { expected: String, got: String },
159
160 InvalidOperation(String),
162
163 DivisionByZero,
165
166 NotCallable(String),
168
169 WrongArity { expected: usize, got: usize },
171
172 Return(Value),
174
175 Yield(Value),
177
178 Break,
180
181 Continue,
183
184 Throw(Value),
186
187 ImportError(Box<ImportError>),
189
190 WithCallStack {
192 error: Box<RuntimeError>,
193 call_stack: Vec<CallFrame>,
194 },
195
196 ExecutionLimit(crate::runtime::ExecutionLimitError),
198
199 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#[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
462pub struct Evaluator {
464 env: Rc<RefCell<Environment>>,
466 registry: BuiltInRegistry,
468 trace: VecDeque<String>,
470 trace_seq: u64,
472 trace_entries: VecDeque<crate::runtime::TraceEntry>,
474
475 module_resolver: Box<dyn ModuleResolver>,
477 module_cache: HashMap<String, HashMap<String, Value>>,
479 module_stack: Vec<String>,
481 export_stack: Vec<HashMap<String, Value>>,
483 import_base_stack: Vec<ModuleContext>,
485
486 call_stack: Vec<CallFrame>,
488
489 limits: crate::runtime::ExecutionLimits,
491 step_counter: std::cell::Cell<usize>,
493 call_stack_depth: std::cell::Cell<usize>,
495 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 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 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 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 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 pub fn set_limits(&mut self, limits: crate::runtime::ExecutionLimits) {
565 self.limits = limits;
566 }
567
568 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 pub fn new() -> Self {
598 Self::with_permissions(crate::builtins::IOPermissions::default())
599 }
600
601 pub fn with_permissions(permissions: crate::builtins::IOPermissions) -> Self {
603 let env = Rc::new(RefCell::new(Environment::new()));
604
605 let registry = BuiltInRegistry::with_permissions(permissions);
607 Self::register_builtins_into_env(®istry, &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 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 pub fn clear_call_stack(&mut self) {
658 self.call_stack.clear();
659 }
660
661 pub fn set_module_resolver(&mut self, resolver: Box<dyn ModuleResolver>) {
663 self.module_resolver = resolver;
664 }
665
666 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 pub fn pop_import_base(&mut self) {
678 self.import_base_stack.pop();
679 }
680
681 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 fn trace_push_entry(&mut self, entry: crate::runtime::TraceEntry) {
694 self.trace_seq = self.trace_seq.saturating_add(1);
695
696 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 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 pub fn take_trace(&mut self) -> Vec<String> {
713 std::mem::take(&mut self.trace).into_iter().collect()
714 }
715
716 pub fn trace_records(&self) -> Vec<crate::runtime::TraceEntry> {
718 self.trace_entries.iter().cloned().collect()
719 }
720
721 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 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 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 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 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 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 pub fn clear_trace(&mut self) {
795 self.trace.clear();
796 self.trace_entries.clear();
797 self.trace_seq = 0;
798 }
799
800 pub fn reset_env(&mut self) {
805 self.env = Rc::new(RefCell::new(Environment::new()));
807
808 self.trace.clear();
810 self.trace_entries.clear();
811 self.trace_seq = 0;
812
813 self.import_base_stack.clear();
815 self.export_stack.clear();
816 self.module_stack.clear();
817
818 self.call_stack.clear();
820
821 Self::register_builtins_into_env(&self.registry, &mut self.env.borrow_mut());
823 }
824
825 pub fn set_global(&mut self, name: impl Into<String>, value: Value) {
827 self.env.borrow_mut().set(name.into(), value);
828 }
829
830 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 pub fn restore_env(&mut self, prev: Rc<RefCell<Environment>>) {
842 self.env = prev;
843 }
844
845 pub fn eval_program(&mut self, program: &Program) -> EvalResult {
847 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 pub fn eval_statement(&mut self, stmt: &Stmt) -> EvalResult {
863 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 let val = self.eval_expression(value)?;
881
882 if let Expr::Identifier(name) = object.as_ref() {
884 let obj = self
886 .env
887 .borrow()
888 .get(name)
889 .ok_or_else(|| RuntimeError::UndefinedVariable(name.clone()))?;
890
891 let idx_val = self.eval_expression(index)?;
893
894 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 self.env.borrow_mut().set(name.clone(), new_obj);
923 Ok(val)
924 } else {
925 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 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 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 match op {
1174 BinOp::And => {
1175 let left_val = self.eval_expression(left)?;
1176 if !left_val.is_truthy() {
1177 Ok(left_val)
1179 } else {
1180 self.eval_expression(right)
1182 }
1183 }
1184 BinOp::Or => {
1185 let left_val = self.eval_expression(left)?;
1186 if left_val.is_truthy() {
1187 Ok(left_val)
1189 } else {
1190 self.eval_expression(right)
1192 }
1193 }
1194 _ => {
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 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 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 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 if a.fract() == 0.0 && b.fract() == 0.0 {
1393 let max_safe = 9007199254740992.0; if a.abs() > max_safe || b.abs() > max_safe {
1396 use num_bigint::BigInt;
1398 use num_rational::Ratio;
1399
1400 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 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 fn call_function(
1579 &mut self,
1580 name_hint: Option<&str>,
1581 func: &Value,
1582 args: Vec<Value>,
1583 ) -> EvalResult {
1584 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 let func_env = Rc::new(RefCell::new(Environment::with_parent(Rc::clone(env))));
1641
1642 for (param, arg) in params.iter().zip(args.iter()) {
1644 func_env.borrow_mut().set(param.clone(), arg.clone());
1645 }
1646
1647 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 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 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 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 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 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 let values = args[1..].to_vec();
1761
1762 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 if let Some((func, _arity)) = self.registry.get(name) {
1774 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 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 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 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 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 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 self.import_base_stack.push(ModuleContext {
2015 module_id: resolved.module_id.clone(),
2016 base_dir: resolved.base_dir.clone(),
2017 });
2018
2019 self.export_stack.push(HashMap::new());
2021
2022 let eval_res = self.eval_program(&program);
2023
2024 let exports = self.export_stack.pop().unwrap_or_default();
2026 self.import_base_stack.pop();
2027 self.env = prev_env;
2028
2029 let _ = self.module_stack.pop();
2031
2032 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}