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