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