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