1use crate::ast::{BinOp, Expr, Program, Stmt, UnaryOp};
5use crate::builtins::BuiltInRegistry;
6use crate::environment::Environment;
7use crate::module_system::{DisabledModuleResolver, ModuleContext, ModuleResolver, ResolvedModule};
8use crate::value::{GeneratorState, Value};
9use std::cell::RefCell;
10use std::collections::HashMap;
11use std::collections::VecDeque;
12use std::rc::Rc;
13
14#[derive(Debug, Clone, PartialEq)]
16pub enum RuntimeError {
17 UndefinedVariable(String),
19
20 TypeError(String),
22
23 TypeErrorDetailed { expected: String, got: String },
25
26 InvalidOperation(String),
28
29 DivisionByZero,
31
32 NotCallable(String),
34
35 WrongArity { expected: usize, got: usize },
37
38 Return(Value),
40
41 Yield(Value),
43
44 Break,
46
47 Continue,
49
50 Throw(Value),
52
53 CustomError(String),
55}
56
57impl std::fmt::Display for RuntimeError {
58 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
59 match self {
60 RuntimeError::UndefinedVariable(name) => write!(f, "Undefined variable: {}", name),
61 RuntimeError::TypeError(msg) => write!(f, "Type error: {}", msg),
62 RuntimeError::TypeErrorDetailed { expected, got } => {
63 write!(f, "Type error: expected {}, got {}", expected, got)
64 }
65 RuntimeError::InvalidOperation(msg) => write!(f, "Invalid operation: {}", msg),
66 RuntimeError::DivisionByZero => write!(f, "Division by zero"),
67 RuntimeError::NotCallable(name) => write!(f, "Not callable: {}", name),
68 RuntimeError::WrongArity { expected, got } => {
69 write!(
70 f,
71 "Wrong number of arguments: expected {}, got {}",
72 expected, got
73 )
74 }
75 RuntimeError::Return(val) => write!(f, "Return: {}", val),
76 RuntimeError::Yield(val) => write!(f, "Yield: {}", val),
77 RuntimeError::Break => write!(f, "Break outside of loop"),
78 RuntimeError::Continue => write!(f, "Continue outside of loop"),
79 RuntimeError::Throw(val) => write!(f, "Throw: {}", val),
80 RuntimeError::CustomError(msg) => write!(f, "{}", msg),
81 }
82 }
83}
84
85impl std::error::Error for RuntimeError {}
86
87pub type EvalResult = Result<Value, RuntimeError>;
88
89pub struct Evaluator {
91 env: Rc<RefCell<Environment>>,
93 registry: BuiltInRegistry,
95 trace: VecDeque<String>,
97 trace_seq: u64,
99
100 module_resolver: Box<dyn ModuleResolver>,
102 module_cache: HashMap<String, HashMap<String, Value>>,
104 module_stack: Vec<String>,
106 export_stack: Vec<HashMap<String, Value>>,
108 import_base_stack: Vec<ModuleContext>,
110}
111
112impl Evaluator {
113 const TRACE_MAX_ENTRIES: usize = 1024;
114
115 pub fn new() -> Self {
117 Self::with_permissions(crate::builtins::IOPermissions::default())
118 }
119
120 pub fn with_permissions(permissions: crate::builtins::IOPermissions) -> Self {
122 let env = Rc::new(RefCell::new(Environment::new()));
123
124 let registry = BuiltInRegistry::with_permissions(permissions);
126 for name in registry.names() {
127 env.borrow_mut()
128 .set(name.clone(), Value::BuiltIn { name, arity: 0 });
129 }
130
131 Evaluator {
132 env,
133 registry,
134 trace: VecDeque::new(),
135 trace_seq: 0,
136
137 module_resolver: Box::new(DisabledModuleResolver),
138 module_cache: HashMap::new(),
139 module_stack: Vec::new(),
140 export_stack: Vec::new(),
141 import_base_stack: Vec::new(),
142 }
143 }
144
145 pub fn with_env(env: Rc<RefCell<Environment>>) -> Self {
147 let registry = BuiltInRegistry::new();
148 Evaluator {
149 env,
150 registry,
151 trace: VecDeque::new(),
152 trace_seq: 0,
153
154 module_resolver: Box::new(DisabledModuleResolver),
155 module_cache: HashMap::new(),
156 module_stack: Vec::new(),
157 export_stack: Vec::new(),
158 import_base_stack: Vec::new(),
159 }
160 }
161
162 pub fn set_module_resolver(&mut self, resolver: Box<dyn ModuleResolver>) {
164 self.module_resolver = resolver;
165 }
166
167 pub fn push_import_base(&mut self, module_id: String, base_dir: Option<std::path::PathBuf>) {
171 self.import_base_stack.push(ModuleContext {
172 module_id,
173 base_dir,
174 });
175 }
176
177 pub fn pop_import_base(&mut self) {
179 self.import_base_stack.pop();
180 }
181
182 pub fn trace_push(&mut self, msg: String) {
184 self.trace_seq = self.trace_seq.saturating_add(1);
185 let entry = format!("#{} {}", self.trace_seq, msg);
186
187 if self.trace.len() >= Self::TRACE_MAX_ENTRIES {
188 self.trace.pop_front();
189 }
190 self.trace.push_back(entry);
191 }
192
193 pub fn take_trace(&mut self) -> Vec<String> {
195 std::mem::take(&mut self.trace).into_iter().collect()
196 }
197
198 pub fn clear_trace(&mut self) {
200 self.trace.clear();
201 self.trace_seq = 0;
202 }
203
204 pub fn reset_env(&mut self) {
209 self.env = Rc::new(RefCell::new(Environment::new()));
211
212 self.trace.clear();
214 self.trace_seq = 0;
215
216 self.import_base_stack.clear();
218 self.export_stack.clear();
219 self.module_stack.clear();
220
221 for name in self.registry.names() {
223 self.env
224 .borrow_mut()
225 .set(name.clone(), Value::BuiltIn { name, arity: 0 });
226 }
227 }
228
229 pub fn set_global(&mut self, name: impl Into<String>, value: Value) {
231 self.env.borrow_mut().set(name.into(), value);
232 }
233
234 pub fn enter_child_scope(&mut self) -> Rc<RefCell<Environment>> {
238 let prev = Rc::clone(&self.env);
239 let child = Rc::new(RefCell::new(Environment::with_parent(Rc::clone(&prev))));
240 self.env = child;
241 prev
242 }
243
244 pub fn restore_env(&mut self, prev: Rc<RefCell<Environment>>) {
246 self.env = prev;
247 }
248
249 pub fn eval_program(&mut self, program: &Program) -> EvalResult {
251 let mut result = Value::Null;
252
253 for stmt in program {
254 result = self.eval_statement(stmt)?;
255 }
256
257 Ok(result)
258 }
259
260 pub fn eval_statement(&mut self, stmt: &Stmt) -> EvalResult {
262 match stmt {
263 Stmt::Set { name, value } => {
264 let val = self.eval_expression(value)?;
265 self.env.borrow_mut().set(name.clone(), val.clone());
266 Ok(val)
267 }
268
269 Stmt::SetIndex {
270 object,
271 index,
272 value,
273 } => {
274 let val = self.eval_expression(value)?;
276
277 if let Expr::Identifier(name) = object.as_ref() {
279 let obj = self
281 .env
282 .borrow()
283 .get(name)
284 .ok_or_else(|| RuntimeError::UndefinedVariable(name.clone()))?;
285
286 let idx_val = self.eval_expression(index)?;
288
289 let new_obj = match (obj, idx_val) {
291 (Value::Array(mut arr), Value::Number(n)) => {
292 let idx = n as usize;
293 if idx >= arr.len() {
294 return Err(RuntimeError::InvalidOperation(format!(
295 "Index {} out of bounds (array length: {})",
296 idx,
297 arr.len()
298 )));
299 }
300 arr[idx] = val.clone();
301 Value::Array(arr)
302 }
303 (Value::Dict(mut dict), Value::String(key)) => {
304 dict.insert(key, val.clone());
305 Value::Dict(dict)
306 }
307 (obj, idx) => {
308 return Err(RuntimeError::TypeError(format!(
309 "Cannot index {} with {}",
310 obj.type_name(),
311 idx.type_name()
312 )));
313 }
314 };
315
316 self.env.borrow_mut().set(name.clone(), new_obj);
318 Ok(val)
319 } else {
320 Err(RuntimeError::InvalidOperation(
322 "Can only assign to simple variable indices (e.g., dict[key], not expr[key])"
323 .to_string(),
324 ))
325 }
326 }
327
328 Stmt::FuncDef { name, params, body } => {
329 let func = Value::Function {
330 params: params.clone(),
331 body: body.clone(),
332 env: Rc::clone(&self.env),
333 };
334 self.env.borrow_mut().set(name.clone(), func.clone());
335 Ok(func)
336 }
337
338 Stmt::GeneratorDef { name, params, body } => {
339 let r#gen = Value::Generator {
340 params: params.clone(),
341 body: body.clone(),
342 env: Rc::clone(&self.env),
343 state: GeneratorState::NotStarted,
344 };
345 self.env.borrow_mut().set(name.clone(), r#gen.clone());
346 Ok(r#gen)
347 }
348
349 Stmt::LazyDef { name, expr } => {
350 let lazy = Value::Lazy {
351 expr: expr.clone(),
352 env: Rc::clone(&self.env),
353 cached: None,
354 };
355 self.env.borrow_mut().set(name.clone(), lazy.clone());
356 Ok(lazy)
357 }
358
359 Stmt::Return(expr) => {
360 let val = self.eval_expression(expr)?;
361 Err(RuntimeError::Return(val))
362 }
363
364 Stmt::Yield(expr) => {
365 let val = self.eval_expression(expr)?;
366 Err(RuntimeError::Yield(val))
367 }
368
369 Stmt::Break => Err(RuntimeError::Break),
370
371 Stmt::Continue => Err(RuntimeError::Continue),
372
373 Stmt::While { condition, body } => {
374 let mut result = Value::Null;
375
376 loop {
377 let cond = self.eval_expression(condition)?;
378 if !cond.is_truthy() {
379 break;
380 }
381
382 let mut should_break = false;
383 for stmt in body {
384 match self.eval_statement(stmt) {
385 Ok(val) => result = val,
386 Err(RuntimeError::Break) => {
387 should_break = true;
388 break;
389 }
390 Err(RuntimeError::Continue) => break,
391 Err(e) => return Err(e),
392 }
393 }
394
395 if should_break {
396 break;
397 }
398 }
399
400 Ok(result)
401 }
402
403 Stmt::For {
404 var,
405 iterable,
406 body,
407 } => {
408 let iter_val = self.eval_expression(iterable)?;
409 let mut result = Value::Null;
410
411 match iter_val {
412 Value::Array(arr) => {
413 let mut should_break = false;
414 for item in arr {
415 self.env.borrow_mut().set(var.clone(), item);
416 for stmt in body {
417 match self.eval_statement(stmt) {
418 Ok(val) => result = val,
419 Err(RuntimeError::Break) => {
420 should_break = true;
421 break;
422 }
423 Err(RuntimeError::Continue) => break,
424 Err(e) => return Err(e),
425 }
426 }
427 if should_break {
428 break;
429 }
430 }
431 }
432 _ => {
433 return Err(RuntimeError::TypeError(format!(
434 "Cannot iterate over {}",
435 iter_val.type_name()
436 )));
437 }
438 }
439
440 Ok(result)
441 }
442
443 Stmt::ForIndexed {
444 index_var,
445 value_var,
446 iterable,
447 body,
448 } => {
449 let iter_val = self.eval_expression(iterable)?;
450 let mut result = Value::Null;
451
452 match iter_val {
453 Value::Array(arr) => {
454 let mut should_break = false;
455 for (idx, item) in arr.iter().enumerate() {
456 self.env
457 .borrow_mut()
458 .set(index_var.clone(), Value::Number(idx as f64));
459 self.env.borrow_mut().set(value_var.clone(), item.clone());
460 for stmt in body {
461 match self.eval_statement(stmt) {
462 Ok(val) => result = val,
463 Err(RuntimeError::Break) => {
464 should_break = true;
465 break;
466 }
467 Err(RuntimeError::Continue) => break,
468 Err(e) => return Err(e),
469 }
470 }
471 if should_break {
472 break;
473 }
474 }
475 }
476 _ => {
477 return Err(RuntimeError::TypeError(format!(
478 "Cannot iterate over {}",
479 iter_val.type_name()
480 )));
481 }
482 }
483
484 Ok(result)
485 }
486
487 Stmt::Switch {
488 expr,
489 cases,
490 default,
491 } => {
492 let val = self.eval_expression(expr)?;
493
494 for (case_expr, case_body) in cases {
495 let case_val = self.eval_expression(case_expr)?;
496 if val.equals(&case_val) {
497 let mut result = Value::Null;
498 for stmt in case_body {
499 result = self.eval_statement(stmt)?;
500 }
501 return Ok(result);
502 }
503 }
504
505 if let Some(default_body) = default {
506 let mut result = Value::Null;
507 for stmt in default_body {
508 result = self.eval_statement(stmt)?;
509 }
510 return Ok(result);
511 }
512
513 Ok(Value::Null)
514 }
515
516 Stmt::Import {
517 names,
518 path,
519 aliases,
520 } => self.eval_import(names, path, aliases),
521
522 Stmt::Export(name) => self.eval_export(name),
523
524 Stmt::Throw(expr) => {
525 let val = self.eval_expression(expr)?;
526 Err(RuntimeError::Throw(val))
527 }
528
529 Stmt::Expression(expr) => self.eval_expression(expr),
530 }
531 }
532
533 pub fn eval_expression(&mut self, expr: &Expr) -> EvalResult {
535 match expr {
536 Expr::Number(n) => Ok(Value::Number(*n)),
537
538 Expr::BigInteger(s) => {
539 use num_bigint::BigInt;
541 use num_rational::Ratio;
542
543 match s.parse::<BigInt>() {
544 Ok(big_int) => Ok(Value::Fraction(Ratio::new(big_int, BigInt::from(1)))),
545 Err(_) => Err(RuntimeError::InvalidOperation(format!(
546 "Invalid big integer: {}",
547 s
548 ))),
549 }
550 }
551
552 Expr::String(s) => Ok(Value::String(s.clone())),
553
554 Expr::Boolean(b) => Ok(Value::Boolean(*b)),
555
556 Expr::Null => Ok(Value::Null),
557
558 Expr::Identifier(name) => self
559 .env
560 .borrow()
561 .get(name)
562 .ok_or_else(|| RuntimeError::UndefinedVariable(name.clone())),
563
564 Expr::Binary { left, op, right } => {
565 match op {
567 BinOp::And => {
568 let left_val = self.eval_expression(left)?;
569 if !left_val.is_truthy() {
570 Ok(left_val)
572 } else {
573 self.eval_expression(right)
575 }
576 }
577 BinOp::Or => {
578 let left_val = self.eval_expression(left)?;
579 if left_val.is_truthy() {
580 Ok(left_val)
582 } else {
583 self.eval_expression(right)
585 }
586 }
587 _ => {
589 let left_val = self.eval_expression(left)?;
590 let right_val = self.eval_expression(right)?;
591 self.eval_binary_op(&left_val, op, &right_val)
592 }
593 }
594 }
595
596 Expr::Unary { op, expr } => {
597 let val = self.eval_expression(expr)?;
598 self.eval_unary_op(op, &val)
599 }
600
601 Expr::Call { func, args } => {
602 let func_val = self.eval_expression(func)?;
603 let arg_vals: Result<Vec<_>, _> =
604 args.iter().map(|arg| self.eval_expression(arg)).collect();
605 let arg_vals = arg_vals?;
606
607 self.call_function(&func_val, arg_vals)
608 }
609
610 Expr::Array(elements) => {
611 let vals: Result<Vec<_>, _> =
612 elements.iter().map(|e| self.eval_expression(e)).collect();
613 Ok(Value::Array(vals?))
614 }
615
616 Expr::Dict(pairs) => {
617 let mut map = std::collections::HashMap::new();
618 for (key, value_expr) in pairs {
619 let value = self.eval_expression(value_expr)?;
620 map.insert(key.clone(), value);
621 }
622 Ok(Value::Dict(map))
623 }
624
625 Expr::Index { object, index } => {
626 let obj_val = self.eval_expression(object)?;
627 let idx_val = self.eval_expression(index)?;
628
629 match (obj_val, idx_val) {
630 (Value::Array(arr), Value::Number(n)) => {
631 let idx = n as usize;
632 arr.get(idx).cloned().ok_or_else(|| {
633 RuntimeError::InvalidOperation(format!("Index {} out of bounds", idx))
634 })
635 }
636 (Value::String(s), Value::Number(n)) => {
637 let idx = n as usize;
638 let chars: Vec<char> = s.chars().collect();
639 chars
640 .get(idx)
641 .cloned()
642 .map(|ch| Value::String(ch.to_string()))
643 .ok_or_else(|| {
644 RuntimeError::InvalidOperation(format!(
645 "Index {} out of bounds (string length: {})",
646 idx,
647 chars.len()
648 ))
649 })
650 }
651 (Value::Dict(dict), Value::String(key)) => {
652 dict.get(&key).cloned().ok_or_else(|| {
653 RuntimeError::InvalidOperation(format!("Key '{}' not found", key))
654 })
655 }
656 (obj, idx) => Err(RuntimeError::TypeError(format!(
657 "Cannot index {} with {}",
658 obj.type_name(),
659 idx.type_name()
660 ))),
661 }
662 }
663
664 Expr::If {
665 condition,
666 then_branch,
667 elif_branches,
668 else_branch,
669 } => {
670 let cond = self.eval_expression(condition)?;
671
672 if cond.is_truthy() {
673 let mut result = Value::Null;
674 for stmt in then_branch {
675 result = self.eval_statement(stmt)?;
676 }
677 return Ok(result);
678 }
679
680 for (elif_cond, elif_body) in elif_branches {
681 let cond = self.eval_expression(elif_cond)?;
682 if cond.is_truthy() {
683 let mut result = Value::Null;
684 for stmt in elif_body {
685 result = self.eval_statement(stmt)?;
686 }
687 return Ok(result);
688 }
689 }
690
691 if let Some(else_body) = else_branch {
692 let mut result = Value::Null;
693 for stmt in else_body {
694 result = self.eval_statement(stmt)?;
695 }
696 return Ok(result);
697 }
698
699 Ok(Value::Null)
700 }
701
702 Expr::Lambda { params, body } => {
703 Ok(Value::Function {
705 params: params.clone(),
706 body: body.clone(),
707 env: Rc::clone(&self.env),
708 })
709 }
710 }
711 }
712
713 fn eval_binary_op(&self, left: &Value, op: &BinOp, right: &Value) -> EvalResult {
715 match op {
716 BinOp::Add => match (left, right) {
717 (Value::Number(a), Value::Number(b)) => Ok(Value::Number(a + b)),
718 (Value::String(a), Value::String(b)) => Ok(Value::String(format!("{}{}", a, b))),
719 (Value::Fraction(a), Value::Fraction(b)) => Ok(Value::Fraction(a + b)),
720 (Value::Number(a), Value::Fraction(b)) | (Value::Fraction(b), Value::Number(a)) => {
721 use num_bigint::BigInt;
722 use num_rational::Ratio;
723 if a.fract() == 0.0 {
724 let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
725 Ok(Value::Fraction(a_frac + b))
726 } else {
727 use num_traits::ToPrimitive;
729 let b_float =
730 b.numer().to_f64().unwrap_or(0.0) / b.denom().to_f64().unwrap_or(1.0);
731 Ok(Value::Number(a + b_float))
732 }
733 }
734 _ => Err(RuntimeError::TypeError(format!(
735 "Cannot add {} and {}",
736 left.type_name(),
737 right.type_name()
738 ))),
739 },
740
741 BinOp::Subtract => match (left, right) {
742 (Value::Number(a), Value::Number(b)) => Ok(Value::Number(a - b)),
743 (Value::Fraction(a), Value::Fraction(b)) => Ok(Value::Fraction(a - b)),
744 (Value::Number(a), Value::Fraction(b)) => {
745 use num_bigint::BigInt;
746 use num_rational::Ratio;
747 if a.fract() == 0.0 {
748 let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
749 Ok(Value::Fraction(a_frac - b))
750 } else {
751 use num_traits::ToPrimitive;
752 let b_float =
753 b.numer().to_f64().unwrap_or(0.0) / b.denom().to_f64().unwrap_or(1.0);
754 Ok(Value::Number(a - b_float))
755 }
756 }
757 (Value::Fraction(a), Value::Number(b)) => {
758 use num_bigint::BigInt;
759 use num_rational::Ratio;
760 if b.fract() == 0.0 {
761 let b_frac = Ratio::new(BigInt::from(*b as i64), BigInt::from(1));
762 Ok(Value::Fraction(a - b_frac))
763 } else {
764 use num_traits::ToPrimitive;
765 let a_float =
766 a.numer().to_f64().unwrap_or(0.0) / a.denom().to_f64().unwrap_or(1.0);
767 Ok(Value::Number(a_float - b))
768 }
769 }
770 _ => Err(RuntimeError::TypeError(format!(
771 "Cannot subtract {} from {}",
772 right.type_name(),
773 left.type_name()
774 ))),
775 },
776
777 BinOp::Multiply => match (left, right) {
778 (Value::Number(a), Value::Number(b)) => {
779 if a.fract() == 0.0 && b.fract() == 0.0 {
781 let max_safe = 9007199254740992.0; if a.abs() > max_safe || b.abs() > max_safe {
784 use num_bigint::BigInt;
786 use num_rational::Ratio;
787
788 let a_str = format!("{:.0}", a);
790 let b_str = format!("{:.0}", b);
791
792 if let (Ok(a_big), Ok(b_big)) =
793 (a_str.parse::<BigInt>(), b_str.parse::<BigInt>())
794 {
795 let result_big = a_big * b_big;
796 let frac = Ratio::new(result_big, BigInt::from(1));
797 return Ok(Value::Fraction(frac));
798 }
799 }
800 }
801 Ok(Value::Number(a * b))
802 }
803 (Value::Fraction(a), Value::Fraction(b)) => Ok(Value::Fraction(a * b)),
804 (Value::Number(a), Value::Fraction(b)) | (Value::Fraction(b), Value::Number(a)) => {
805 use num_bigint::BigInt;
806 use num_rational::Ratio;
807 if a.fract() == 0.0 {
808 let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
809 Ok(Value::Fraction(a_frac * b))
810 } else {
811 Err(RuntimeError::TypeError(
812 "Cannot multiply non-integer Number with Fraction".to_string(),
813 ))
814 }
815 }
816 _ => Err(RuntimeError::TypeError(format!(
817 "Cannot multiply {} and {}",
818 left.type_name(),
819 right.type_name()
820 ))),
821 },
822
823 BinOp::Divide => match (left, right) {
824 (Value::Number(a), Value::Number(b)) => {
825 if *b == 0.0 {
826 Err(RuntimeError::DivisionByZero)
827 } else {
828 Ok(Value::Number(a / b))
829 }
830 }
831 (Value::Fraction(a), Value::Fraction(b)) => {
832 use num_traits::Zero;
833 if b.is_zero() {
834 Err(RuntimeError::DivisionByZero)
835 } else {
836 Ok(Value::Fraction(a / b))
837 }
838 }
839 (Value::Number(a), Value::Fraction(b)) => {
840 use num_bigint::BigInt;
841 use num_rational::Ratio;
842 use num_traits::Zero;
843 if b.is_zero() {
844 Err(RuntimeError::DivisionByZero)
845 } else if a.fract() == 0.0 {
846 let a_frac = Ratio::new(BigInt::from(*a as i64), BigInt::from(1));
847 Ok(Value::Fraction(a_frac / b))
848 } else {
849 use num_traits::ToPrimitive;
850 let b_float =
851 b.numer().to_f64().unwrap_or(0.0) / b.denom().to_f64().unwrap_or(1.0);
852 Ok(Value::Number(a / b_float))
853 }
854 }
855 (Value::Fraction(a), Value::Number(b)) => {
856 use num_bigint::BigInt;
857 use num_rational::Ratio;
858 if *b == 0.0 {
859 Err(RuntimeError::DivisionByZero)
860 } else if b.fract() == 0.0 {
861 let b_frac = Ratio::new(BigInt::from(*b as i64), BigInt::from(1));
862 Ok(Value::Fraction(a / b_frac))
863 } else {
864 use num_traits::ToPrimitive;
865 let a_float =
866 a.numer().to_f64().unwrap_or(0.0) / a.denom().to_f64().unwrap_or(1.0);
867 Ok(Value::Number(a_float / b))
868 }
869 }
870 _ => Err(RuntimeError::TypeError(format!(
871 "Cannot divide {} by {}",
872 left.type_name(),
873 right.type_name()
874 ))),
875 },
876
877 BinOp::Modulo => match (left, right) {
878 (Value::Number(a), Value::Number(b)) => {
879 if *b == 0.0 {
880 Err(RuntimeError::DivisionByZero)
881 } else {
882 Ok(Value::Number(a % b))
883 }
884 }
885 _ => Err(RuntimeError::TypeError(format!(
886 "Cannot modulo {} by {}",
887 left.type_name(),
888 right.type_name()
889 ))),
890 },
891
892 BinOp::Equal => Ok(Value::Boolean(left.equals(right))),
893
894 BinOp::NotEqual => Ok(Value::Boolean(!left.equals(right))),
895
896 BinOp::Less => match left.compare(right) {
897 Some(ord) => Ok(Value::Boolean(ord == std::cmp::Ordering::Less)),
898 None => Err(RuntimeError::TypeError(format!(
899 "Cannot compare {} and {}",
900 left.type_name(),
901 right.type_name()
902 ))),
903 },
904
905 BinOp::LessEqual => match left.compare(right) {
906 Some(ord) => Ok(Value::Boolean(ord != std::cmp::Ordering::Greater)),
907 None => Err(RuntimeError::TypeError(format!(
908 "Cannot compare {} and {}",
909 left.type_name(),
910 right.type_name()
911 ))),
912 },
913
914 BinOp::Greater => match left.compare(right) {
915 Some(ord) => Ok(Value::Boolean(ord == std::cmp::Ordering::Greater)),
916 None => Err(RuntimeError::TypeError(format!(
917 "Cannot compare {} and {}",
918 left.type_name(),
919 right.type_name()
920 ))),
921 },
922
923 BinOp::GreaterEqual => match left.compare(right) {
924 Some(ord) => Ok(Value::Boolean(ord != std::cmp::Ordering::Less)),
925 None => Err(RuntimeError::TypeError(format!(
926 "Cannot compare {} and {}",
927 left.type_name(),
928 right.type_name()
929 ))),
930 },
931
932 BinOp::And => {
933 if !left.is_truthy() {
934 Ok(left.clone())
935 } else {
936 Ok(right.clone())
937 }
938 }
939
940 BinOp::Or => {
941 if left.is_truthy() {
942 Ok(left.clone())
943 } else {
944 Ok(right.clone())
945 }
946 }
947 }
948 }
949
950 fn eval_unary_op(&self, op: &UnaryOp, val: &Value) -> EvalResult {
952 match op {
953 UnaryOp::Minus => match val {
954 Value::Number(n) => Ok(Value::Number(-n)),
955 _ => Err(RuntimeError::TypeError(format!(
956 "Cannot negate {}",
957 val.type_name()
958 ))),
959 },
960
961 UnaryOp::Not => Ok(Value::Boolean(!val.is_truthy())),
962 }
963 }
964
965 fn call_function(&mut self, func: &Value, args: Vec<Value>) -> EvalResult {
967 match func {
968 Value::Function { params, body, env } => {
969 if params.len() != args.len() {
970 return Err(RuntimeError::WrongArity {
971 expected: params.len(),
972 got: args.len(),
973 });
974 }
975
976 let func_env = Rc::new(RefCell::new(Environment::with_parent(Rc::clone(env))));
978
979 for (param, arg) in params.iter().zip(args.iter()) {
981 func_env.borrow_mut().set(param.clone(), arg.clone());
982 }
983
984 let prev_env = Rc::clone(&self.env);
986 self.env = func_env;
987
988 let mut result = Value::Null;
989 for stmt in body {
990 match self.eval_statement(stmt) {
991 Ok(val) => result = val,
992 Err(RuntimeError::Return(val)) => {
993 result = val;
994 break;
995 }
996 Err(e) => {
997 self.env = prev_env;
998 return Err(e);
999 }
1000 }
1001 }
1002
1003 self.env = prev_env;
1004 Ok(result)
1005 }
1006
1007 Value::BuiltIn { name, .. } => {
1008 match name.as_str() {
1010 "TRACE" => {
1011 if args.is_empty() {
1012 return Err(RuntimeError::WrongArity {
1013 expected: 1,
1014 got: 0,
1015 });
1016 }
1017
1018 let (label, payload_args) = if args.len() >= 2 {
1021 match &args[0] {
1022 Value::String(s) => (Some(s.as_str()), &args[1..]),
1023 _ => (None, args.as_slice()),
1024 }
1025 } else {
1026 (None, args.as_slice())
1027 };
1028
1029 let payload = payload_args
1030 .iter()
1031 .map(|v| v.to_string())
1032 .collect::<Vec<_>>()
1033 .join(" ");
1034
1035 let msg = match label {
1036 Some(l) => format!("[{}] {}", l, payload),
1037 None => payload,
1038 };
1039
1040 self.trace_push(msg);
1041 Ok(Value::Null)
1042 }
1043 "MAP" => self.builtin_map(&args),
1044 "FILTER" => self.builtin_filter(&args),
1045 "REDUCE" => self.builtin_reduce(&args),
1046 _ => {
1047 if let Some((func, _arity)) = self.registry.get(name) {
1049 func(&args)
1051 } else {
1052 Err(RuntimeError::NotCallable(format!(
1053 "Built-in function '{}' not found",
1054 name
1055 )))
1056 }
1057 }
1058 }
1059 }
1060
1061 _ => Err(RuntimeError::NotCallable(func.type_name().to_string())),
1062 }
1063 }
1064
1065 fn builtin_map(&mut self, args: &[Value]) -> EvalResult {
1067 if args.len() != 2 {
1068 return Err(RuntimeError::WrongArity {
1069 expected: 2,
1070 got: args.len(),
1071 });
1072 }
1073
1074 let arr = match &args[0] {
1075 Value::Array(a) => a,
1076 other => {
1077 return Err(RuntimeError::TypeErrorDetailed {
1078 expected: "Array".to_string(),
1079 got: format!("{:?}", other),
1080 });
1081 }
1082 };
1083
1084 let func = &args[1];
1085
1086 let mut result = Vec::new();
1087 for item in arr {
1088 let mapped = self.call_function(func, vec![item.clone()])?;
1089 result.push(mapped);
1090 }
1091
1092 Ok(Value::Array(result))
1093 }
1094
1095 fn builtin_filter(&mut self, args: &[Value]) -> EvalResult {
1097 if args.len() != 2 {
1098 return Err(RuntimeError::WrongArity {
1099 expected: 2,
1100 got: args.len(),
1101 });
1102 }
1103
1104 let arr = match &args[0] {
1105 Value::Array(a) => a,
1106 other => {
1107 return Err(RuntimeError::TypeErrorDetailed {
1108 expected: "Array".to_string(),
1109 got: format!("{:?}", other),
1110 });
1111 }
1112 };
1113
1114 let predicate = &args[1];
1115
1116 let mut result = Vec::new();
1117 for item in arr {
1118 let test_result = self.call_function(predicate, vec![item.clone()])?;
1119 if test_result.is_truthy() {
1120 result.push(item.clone());
1121 }
1122 }
1123
1124 Ok(Value::Array(result))
1125 }
1126
1127 fn builtin_reduce(&mut self, args: &[Value]) -> EvalResult {
1129 if args.len() != 3 {
1130 return Err(RuntimeError::WrongArity {
1131 expected: 3,
1132 got: args.len(),
1133 });
1134 }
1135
1136 let arr = match &args[0] {
1137 Value::Array(a) => a,
1138 other => {
1139 return Err(RuntimeError::TypeErrorDetailed {
1140 expected: "Array".to_string(),
1141 got: format!("{:?}", other),
1142 });
1143 }
1144 };
1145
1146 let mut accumulator = args[1].clone();
1147 let func = &args[2];
1148
1149 for item in arr {
1150 accumulator = self.call_function(func, vec![accumulator, item.clone()])?;
1151 }
1152
1153 Ok(accumulator)
1154 }
1155}
1156
1157impl Evaluator {
1158 fn current_import_context(&self) -> Option<&ModuleContext> {
1159 self.import_base_stack.last()
1160 }
1161
1162 fn eval_import(
1163 &mut self,
1164 names: &[String],
1165 specifier: &str,
1166 aliases: &[Option<String>],
1167 ) -> EvalResult {
1168 let from_ctx = self.current_import_context();
1169
1170 let resolved = self
1171 .module_resolver
1172 .resolve(specifier, from_ctx)
1173 .map_err(|e| RuntimeError::CustomError(format!("Import error: {e}")))?;
1174
1175 let exports = self.load_module(resolved)?;
1176
1177 for (i, name) in names.iter().enumerate() {
1178 let alias = aliases
1179 .get(i)
1180 .and_then(|a| a.clone())
1181 .unwrap_or_else(|| name.clone());
1182 let v = exports.get(name).cloned().ok_or_else(|| {
1183 RuntimeError::CustomError(format!(
1184 "Import error: '{}' is not exported by module {}",
1185 name, specifier
1186 ))
1187 })?;
1188 self.env.borrow_mut().set(alias, v);
1189 }
1190
1191 Ok(Value::Null)
1192 }
1193
1194 fn eval_export(&mut self, name: &str) -> EvalResult {
1195 let exports = self.export_stack.last_mut().ok_or_else(|| {
1196 RuntimeError::CustomError("Export error: Export used outside of a module".to_string())
1197 })?;
1198
1199 let val = self.env.borrow().get(name).ok_or_else(|| {
1200 RuntimeError::CustomError(format!("Export error: '{}' is not defined", name))
1201 })?;
1202
1203 exports.insert(name.to_string(), val);
1204 Ok(Value::Null)
1205 }
1206
1207 fn load_module(
1208 &mut self,
1209 resolved: ResolvedModule,
1210 ) -> Result<HashMap<String, Value>, RuntimeError> {
1211 if let Some(cached) = self.module_cache.get(&resolved.module_id) {
1212 return Ok(cached.clone());
1213 }
1214
1215 if self.module_stack.contains(&resolved.module_id) {
1216 let mut chain = self.module_stack.clone();
1217 chain.push(resolved.module_id.clone());
1218 return Err(RuntimeError::CustomError(format!(
1219 "Import error: circular import detected: {}",
1220 chain.join(" -> ")
1221 )));
1222 }
1223
1224 self.module_stack.push(resolved.module_id.clone());
1225
1226 let mut parser = crate::parser::Parser::new(&resolved.source);
1228 let program = parser.parse_program().map_err(|e| {
1229 RuntimeError::CustomError(format!(
1230 "Import error: parse failed for module {}: {}",
1231 resolved.module_id, e
1232 ))
1233 })?;
1234
1235 let prev_env = Rc::clone(&self.env);
1237 let module_env = Rc::new(RefCell::new(Environment::new()));
1238 for name in self.registry.names() {
1239 module_env
1240 .borrow_mut()
1241 .set(name.clone(), Value::BuiltIn { name, arity: 0 });
1242 }
1243 self.env = module_env;
1244
1245 self.import_base_stack.push(ModuleContext {
1247 module_id: resolved.module_id.clone(),
1248 base_dir: resolved.base_dir.clone(),
1249 });
1250
1251 self.export_stack.push(HashMap::new());
1253
1254 let _ = self.eval_program(&program)?;
1255
1256 let exports = self.export_stack.pop().unwrap_or_default();
1258 self.import_base_stack.pop();
1259 self.env = prev_env;
1260
1261 let _ = self.module_stack.pop();
1263
1264 self.module_cache
1265 .insert(resolved.module_id.clone(), exports.clone());
1266 Ok(exports)
1267 }
1268}
1269
1270impl Default for Evaluator {
1271 fn default() -> Self {
1272 Self::new()
1273 }
1274}
1275
1276#[cfg(test)]
1277mod tests {
1278 use super::*;
1279 use crate::parser::Parser;
1280
1281 fn eval(code: &str) -> EvalResult {
1282 let mut parser = Parser::new(code);
1283 let program = parser.parse_program().unwrap();
1284 let mut evaluator = Evaluator::new();
1285 evaluator.eval_program(&program)
1286 }
1287
1288 #[test]
1289 fn test_eval_numbers() {
1290 assert_eq!(eval("42").unwrap(), Value::Number(42.0));
1291 #[allow(clippy::approx_constant)]
1292 {
1293 assert_eq!(eval("3.14").unwrap(), Value::Number(3.14));
1294 }
1295 }
1296
1297 #[test]
1298 fn test_eval_strings() {
1299 assert_eq!(
1300 eval(r#""hello""#).unwrap(),
1301 Value::String("hello".to_string())
1302 );
1303 }
1304
1305 #[test]
1306 fn test_eval_booleans() {
1307 assert_eq!(eval("True").unwrap(), Value::Boolean(true));
1308 assert_eq!(eval("False").unwrap(), Value::Boolean(false));
1309 }
1310
1311 #[test]
1312 fn test_eval_arithmetic() {
1313 assert_eq!(eval("(5 + 3)").unwrap(), Value::Number(8.0));
1314 assert_eq!(eval("(10 - 3)").unwrap(), Value::Number(7.0));
1315 assert_eq!(eval("(4 * 3)").unwrap(), Value::Number(12.0));
1316 assert_eq!(eval("(10 / 2)").unwrap(), Value::Number(5.0));
1317 assert_eq!(eval("(10 % 3)").unwrap(), Value::Number(1.0));
1318 }
1319
1320 #[test]
1321 fn test_eval_arithmetic_precedence() {
1322 assert_eq!(eval("(5 + 3 * 2)").unwrap(), Value::Number(11.0));
1323 assert_eq!(eval("((5 + 3) * 2)").unwrap(), Value::Number(16.0));
1324 }
1325
1326 #[test]
1327 fn test_eval_comparison() {
1328 assert_eq!(eval("(5 < 10)").unwrap(), Value::Boolean(true));
1329 assert_eq!(eval("(10 < 5)").unwrap(), Value::Boolean(false));
1330 assert_eq!(eval("(5 == 5)").unwrap(), Value::Boolean(true));
1331 assert_eq!(eval("(5 != 3)").unwrap(), Value::Boolean(true));
1332 }
1333
1334 #[test]
1335 fn test_eval_logical() {
1336 assert_eq!(eval("(True && False)").unwrap(), Value::Boolean(false));
1337 assert_eq!(eval("(True || False)").unwrap(), Value::Boolean(true));
1338 assert_eq!(eval("(!True)").unwrap(), Value::Boolean(false));
1339 }
1340
1341 #[test]
1342 fn test_eval_set() {
1343 let code = r#"
1344 Set X 42
1345 X
1346 "#;
1347 assert_eq!(eval(code).unwrap(), Value::Number(42.0));
1348 }
1349
1350 #[test]
1351 fn test_eval_function() {
1352 let code = r#"
1353 Func ADD (A, B) {
1354 Return (A + B)
1355 }
1356 ADD(5, 3)
1357 "#;
1358 assert_eq!(eval(code).unwrap(), Value::Number(8.0));
1359 }
1360
1361 #[test]
1362 fn test_eval_array() {
1363 let code = "[1, 2, 3]";
1364 let result = eval(code).unwrap();
1365 match result {
1366 Value::Array(arr) => {
1367 assert_eq!(arr.len(), 3);
1368 assert_eq!(arr[0], Value::Number(1.0));
1369 assert_eq!(arr[1], Value::Number(2.0));
1370 assert_eq!(arr[2], Value::Number(3.0));
1371 }
1372 _ => panic!("Expected array"),
1373 }
1374 }
1375
1376 #[test]
1377 fn test_eval_array_index() {
1378 let code = r#"
1379 Set ARR [10, 20, 30]
1380 ARR[1]
1381 "#;
1382 assert_eq!(eval(code).unwrap(), Value::Number(20.0));
1383 }
1384
1385 #[test]
1386 fn test_eval_if() {
1387 let code = r#"
1388 If (True) {
1389 Set X 42
1390 } Else {
1391 Set X 0
1392 }
1393 X
1394 "#;
1395 assert_eq!(eval(code).unwrap(), Value::Number(42.0));
1396 }
1397
1398 #[test]
1399 fn test_eval_for() {
1400 let code = r#"
1401 Set SUM 0
1402 For I In [1, 2, 3] {
1403 Set SUM (SUM + I)
1404 }
1405 SUM
1406 "#;
1407 assert_eq!(eval(code).unwrap(), Value::Number(6.0));
1408 }
1409}