1use crate::{
2 ast::{BinaryOp, DoStatement, Expr, PostfixOp, RecordEntry, RecordKey, UnaryOp},
3 functions::{
4 BuiltInFunction, get_built_in_function_def_by_ident, get_function_def, is_built_in_function,
5 },
6 heap::{Heap, HeapPointer, HeapValue, IterablePointer, RecordPointer},
7 parser::Rule,
8 values::{
9 LambdaArg, LambdaDef,
10 Value::{self, Bool, List, Number, Spread},
11 },
12};
13use anyhow::{Result, anyhow};
14use indexmap::IndexMap;
15use pest::{
16 iterators::Pairs,
17 pratt_parser::{Assoc, Op, PrattParser},
18};
19use std::{
20 cell::RefCell,
21 collections::{HashMap, HashSet},
22 rc::Rc,
23 sync::LazyLock,
24};
25
26static PRATT: LazyLock<PrattParser<Rule>> = LazyLock::new(|| {
27 PrattParser::new()
28 .op(Op::infix(Rule::and, Assoc::Left)
29 | Op::infix(Rule::natural_and, Assoc::Left)
30 | Op::infix(Rule::or, Assoc::Left)
31 | Op::infix(Rule::natural_or, Assoc::Left)
32 | Op::infix(Rule::pipe, Assoc::Left))
33 .op(Op::infix(Rule::equal, Assoc::Left)
34 | Op::infix(Rule::not_equal, Assoc::Left)
35 | Op::infix(Rule::less, Assoc::Left)
36 | Op::infix(Rule::less_eq, Assoc::Left)
37 | Op::infix(Rule::greater, Assoc::Left)
38 | Op::infix(Rule::greater_eq, Assoc::Left))
39 .op(Op::infix(Rule::add, Assoc::Left) | Op::infix(Rule::subtract, Assoc::Left))
40 .op(Op::infix(Rule::multiply, Assoc::Left)
41 | Op::infix(Rule::divide, Assoc::Left)
42 | Op::infix(Rule::modulo, Assoc::Left))
43 .op(Op::infix(Rule::power, Assoc::Right) | Op::infix(Rule::coalesce, Assoc::Left))
44 .op(Op::prefix(Rule::negation)
45 | Op::prefix(Rule::spread_operator)
46 | Op::prefix(Rule::invert)
47 | Op::prefix(Rule::natural_not))
48 .op(Op::postfix(Rule::factorial))
49 .op(Op::postfix(Rule::access)
50 | Op::postfix(Rule::dot_access)
51 | Op::postfix(Rule::call_list))
52});
53
54pub fn evaluate_pairs(
56 pairs: Pairs<Rule>,
57 heap: Rc<RefCell<Heap>>,
58 bindings: Rc<RefCell<HashMap<String, Value>>>,
59 call_depth: usize,
60) -> Result<Value> {
61 let ast = pairs_to_expr(pairs)?;
63
64 evaluate_ast(&ast, heap, bindings, call_depth)
66}
67
68fn flatten_spread_value(
71 spread_ptr: &IterablePointer,
72 heap: &Rc<RefCell<Heap>>,
73) -> Result<Vec<Value>> {
74 match spread_ptr {
75 IterablePointer::List(list_ptr) => {
76 let borrowed_heap = heap.borrow();
77 Ok(list_ptr.reify(&borrowed_heap).as_list()?.clone())
78 }
79 IterablePointer::String(string_ptr) => {
80 let string = {
81 let borrowed_heap = heap.borrow();
82 string_ptr.reify(&borrowed_heap).as_string()?.to_string()
83 };
84 Ok(string
86 .chars()
87 .map(|c| heap.borrow_mut().insert_string(c.to_string()))
88 .collect())
89 }
90 IterablePointer::Record(record_ptr) => {
91 let entries = {
92 let borrowed_heap = heap.borrow();
93 record_ptr.reify(&borrowed_heap).as_record()?.clone()
94 };
95 Ok(entries
97 .into_iter()
98 .map(|(k, v)| {
99 let key = heap.borrow_mut().insert_string(k);
100 heap.borrow_mut().insert_list(vec![key, v])
101 })
102 .collect())
103 }
104 }
105}
106
107fn evaluate_do_block_expr(
109 expr: &Expr,
110 heap: Rc<RefCell<Heap>>,
111 bindings: Rc<RefCell<HashMap<String, Value>>>,
112 call_depth: usize,
113) -> Result<Value> {
114 if let Expr::Assignment { ident, value } = expr {
116 if matches!(
118 ident.as_str(),
119 "return" | "if" | "then" | "else" | "do" | "true" | "false" | "null" | "output"
120 ) {
121 return Err(anyhow!("{} is a keyword, and cannot be reassigned", ident));
122 }
123
124 let val = evaluate_ast(value, Rc::clone(&heap), Rc::clone(&bindings), call_depth)?;
126
127 if let Value::Lambda(lambda_ptr) = val {
129 let mut borrowed_heap = heap.borrow_mut();
130 if let Some(HeapValue::Lambda(lambda_def)) = borrowed_heap.get_mut(lambda_ptr.index()) {
131 lambda_def.name = Some(ident.clone());
132 }
133 }
134
135 bindings.borrow_mut().insert(ident.clone(), val);
136 return Ok(val);
137 }
138
139 evaluate_ast(expr, heap, bindings, call_depth)
141}
142
143pub fn evaluate_ast(
144 expr: &Expr,
145 heap: Rc<RefCell<Heap>>,
146 bindings: Rc<RefCell<HashMap<String, Value>>>,
147 call_depth: usize,
148) -> Result<Value> {
149 match expr {
150 Expr::Number(n) => Ok(Number(*n)),
151 Expr::String(s) => Ok(heap.borrow_mut().insert_string(s.clone())),
152 Expr::Bool(b) => Ok(Bool(*b)),
153 Expr::Null => Ok(Value::Null),
154 Expr::Identifier(ident) => match ident.as_str() {
155 "infinity" => Ok(Number(f64::INFINITY)),
156 "inf" => Ok(Number(f64::INFINITY)),
157 "constants" => Ok(Value::Record(RecordPointer::new(0))),
158 _ => bindings
159 .borrow()
160 .get(ident)
161 .copied()
162 .ok_or(anyhow!("unknown identifier: {}", ident)),
163 },
164 Expr::BuiltIn(built_in) => Ok(Value::BuiltIn(*built_in)),
165 Expr::List(exprs) => {
166 let values = exprs
167 .iter()
168 .map(|e| evaluate_ast(e, Rc::clone(&heap), Rc::clone(&bindings), call_depth))
169 .collect::<Result<Vec<Value>>>()?;
170
171 let mut flattened = Vec::new();
173
174 for value in values {
175 match value {
176 Value::Spread(spread_ptr) => {
177 let spread_values = flatten_spread_value(&spread_ptr, &heap)?;
178 flattened.extend(spread_values);
179 }
180 _ => flattened.push(value),
181 }
182 }
183
184 Ok(heap.borrow_mut().insert_list(flattened))
185 }
186 Expr::Record(entries) => {
187 let mut record = IndexMap::new();
188
189 for entry in entries {
190 match &entry.key {
191 RecordKey::Static(key) => {
192 let value = evaluate_ast(
193 &entry.value,
194 Rc::clone(&heap),
195 Rc::clone(&bindings),
196 call_depth,
197 )?;
198 record.insert(key.clone(), value);
199 }
200 RecordKey::Dynamic(key_expr) => {
201 let key_value = evaluate_ast(
202 key_expr,
203 Rc::clone(&heap),
204 Rc::clone(&bindings),
205 call_depth,
206 )?;
207 let key = key_value.as_string(&heap.borrow())?.to_string();
208 let value = evaluate_ast(
209 &entry.value,
210 Rc::clone(&heap),
211 Rc::clone(&bindings),
212 call_depth,
213 )?;
214 record.insert(key, value);
215 }
216 RecordKey::Shorthand(ident) => {
217 let value = bindings
218 .borrow()
219 .get(ident)
220 .copied()
221 .ok_or(anyhow!("unknown identifier: {}", ident))?;
222 record.insert(ident.clone(), value);
223 }
224 RecordKey::Spread(spread_expr) => {
225 let spread_value = evaluate_ast(
226 spread_expr,
227 Rc::clone(&heap),
228 Rc::clone(&bindings),
229 call_depth,
230 )?;
231
232 if let Spread(iterable) = spread_value {
233 match iterable {
234 IterablePointer::List(pointer) => {
235 let borrowed_heap = &heap.borrow();
236 pointer
237 .reify(borrowed_heap)
238 .as_list()?
239 .iter()
240 .enumerate()
241 .for_each(|(i, value)| {
242 record.insert(i.to_string(), *value);
243 });
244 }
245 IterablePointer::String(pointer) => {
246 let s = {
247 let borrowed_heap = &heap.borrow();
248 pointer.reify(borrowed_heap).as_string()?.to_string()
249 };
250
251 s.chars().enumerate().for_each(|(i, c)| {
252 record.insert(
253 i.to_string(),
254 heap.borrow_mut().insert_string(c.to_string()),
255 );
256 });
257 }
258 IterablePointer::Record(pointer) => {
259 let borrowed_heap = &heap.borrow();
260 let spread_record = pointer.reify(borrowed_heap).as_record()?;
261
262 for (k, v) in spread_record {
263 record.insert(k.clone(), *v);
264 }
265 }
266 }
267 }
268 }
269 }
270 }
271
272 Ok(heap.borrow_mut().insert_record(record))
273 }
274 Expr::Lambda { args, body } => {
275 let mut captured_scope = HashMap::new();
277 let mut referenced_vars = Vec::new();
278 collect_free_variables(body, &mut referenced_vars, &mut HashSet::new());
279
280 let current_bindings = bindings.borrow();
281 for var in referenced_vars {
282 if current_bindings.contains_key(&var) && !is_built_in_function(&var) {
283 captured_scope.insert(var.clone(), current_bindings[&var]);
284 }
285 }
286
287 let lambda = heap.borrow_mut().insert_lambda(LambdaDef {
288 name: None,
289 args: args.clone(),
290 body: (**body).clone(),
291 scope: captured_scope,
292 });
293
294 Ok(lambda)
295 }
296 Expr::Assignment { ident, value } => {
297 if is_built_in_function(ident) {
298 return Err(anyhow!(
299 "{} is the name of a built-in function, and cannot be reassigned",
300 ident
301 ));
302 }
303
304 if ident == "constants"
305 || ident == "if"
306 || ident == "then"
307 || ident == "else"
308 || ident == "true"
309 || ident == "false"
310 || ident == "null"
311 || ident == "inputs"
312 || ident == "and"
313 || ident == "or"
314 {
315 return Err(anyhow!("{} is a keyword, and cannot be reassigned", ident));
316 }
317
318 if bindings.borrow().contains_key(ident) {
320 return Err(anyhow!(
321 "{} is already defined, and cannot be reassigned",
322 ident
323 ));
324 }
325
326 let val = evaluate_ast(value, Rc::clone(&heap), Rc::clone(&bindings), call_depth)?;
327
328 if let Value::Lambda(lambda_ptr) = val {
330 let mut borrowed_heap = heap.borrow_mut();
331 if let Some(HeapValue::Lambda(lambda_def)) =
332 borrowed_heap.get_mut(lambda_ptr.index())
333 {
334 lambda_def.name = Some(ident.clone());
335 }
336 }
337
338 bindings.borrow_mut().insert(ident.clone(), val);
339 Ok(val)
340 }
341 Expr::Conditional {
342 condition,
343 then_expr,
344 else_expr,
345 } => {
346 let cond_val = evaluate_ast(
347 condition,
348 Rc::clone(&heap),
349 Rc::clone(&bindings),
350 call_depth,
351 )?;
352
353 if cond_val.as_bool()? {
354 evaluate_ast(then_expr, heap, bindings, call_depth)
355 } else {
356 evaluate_ast(else_expr, heap, bindings, call_depth)
357 }
358 }
359 Expr::DoBlock {
360 statements,
361 return_expr,
362 } => {
363 let new_bindings = bindings.borrow().clone();
365 let block_bindings = Rc::new(RefCell::new(new_bindings));
366
367 for stmt in statements {
369 match stmt {
370 DoStatement::Expression(expr) => {
371 evaluate_do_block_expr(
372 expr,
373 Rc::clone(&heap),
374 Rc::clone(&block_bindings),
375 call_depth,
376 )?;
377 }
378 DoStatement::Comment(_) => {} }
380 }
381
382 evaluate_do_block_expr(return_expr, heap, block_bindings, call_depth)
384 }
385 Expr::Call { func, args } => {
386 let func_val = evaluate_ast(func, Rc::clone(&heap), Rc::clone(&bindings), call_depth)?;
387 let arg_vals_raw = args
388 .iter()
389 .map(|arg| evaluate_ast(arg, Rc::clone(&heap), Rc::clone(&bindings), call_depth))
390 .collect::<Result<Vec<_>>>()?;
391
392 let mut arg_vals = Vec::new();
394
395 for value in arg_vals_raw {
396 match value {
397 Value::Spread(spread_ptr) => {
398 let spread_values = flatten_spread_value(&spread_ptr, &heap)?;
399 arg_vals.extend(spread_values);
400 }
401 _ => arg_vals.push(value),
402 }
403 }
404
405 if !func_val.is_lambda() && !func_val.is_built_in() {
406 return Err(anyhow!(
407 "can't call a non-function: {}",
408 func_val.stringify_internal(&heap.borrow())
409 ));
410 }
411
412 let def = {
413 let borrowed_heap = &heap.borrow();
414 get_function_def(&func_val, borrowed_heap).ok_or_else(|| {
415 anyhow!(
416 "unknown function: {}",
417 func_val.stringify_internal(borrowed_heap)
418 )
419 })?
420 };
421
422 def.call(func_val, arg_vals, heap, bindings, call_depth)
423 }
424 Expr::Access { expr, index } => {
425 let val = evaluate_ast(expr, Rc::clone(&heap), Rc::clone(&bindings), call_depth)?;
426 let idx_val = evaluate_ast(index, Rc::clone(&heap), Rc::clone(&bindings), call_depth)?;
427
428 match val {
429 Value::Record(record) => {
430 let borrowed_heap = &heap.borrow();
431 let record = record.reify(borrowed_heap).as_record()?;
432 let key = idx_val.as_string(borrowed_heap)?;
433 Ok(record.get(key).copied().unwrap_or(Value::Null))
434 }
435 Value::List(list) => {
436 let borrowed_heap = &heap.borrow();
437 let list = list.reify(borrowed_heap).as_list()?;
438 let index = usize::try_from(idx_val.as_number()? as u64)?;
439 Ok(list.get(index).copied().unwrap_or(Value::Null))
440 }
441 Value::String(string) => {
442 let string = string.reify(&heap.borrow()).as_string()?.to_string();
443 let index = usize::try_from(idx_val.as_number()? as u64)?;
444
445 Ok(string
446 .chars()
447 .nth(index)
448 .map(|c| heap.borrow_mut().insert_string(c.to_string()))
449 .unwrap_or(Value::Null))
450 }
451 _ => Err(anyhow!(
452 "expected a record, list, string, but got a {}",
453 val.get_type()
454 )),
455 }
456 }
457 Expr::DotAccess { expr, field } => {
458 let val = evaluate_ast(expr, Rc::clone(&heap), Rc::clone(&bindings), call_depth)?;
459 let borrowed_heap = &heap.borrow();
460
461 match val {
462 Value::Record(record) => {
463 let record = record.reify(borrowed_heap).as_record()?;
464 Ok(record.get(field).copied().unwrap_or(Value::Null))
465 }
466 _ => Err(anyhow!("expected a record, but got a {}", val.get_type())),
467 }
468 }
469 Expr::BinaryOp { op, left, right } => {
470 evaluate_binary_op_ast(*op, left, right, heap, bindings, call_depth)
471 }
472 Expr::UnaryOp { op, expr } => {
473 let val = evaluate_ast(expr, heap, bindings, call_depth)?;
474
475 match op {
476 UnaryOp::Negate => Ok(Number(-val.as_number()?)),
477 UnaryOp::Not | UnaryOp::Invert => Ok(Bool(!val.as_bool()?)),
478 }
479 }
480 Expr::PostfixOp { op, expr } => {
481 let val = evaluate_ast(expr, heap, bindings, call_depth)?;
482
483 match op {
484 PostfixOp::Factorial => {
485 let n = val.as_number()?;
486 if n >= 0.0 && n == (n as u64) as f64 {
487 Ok(Number(
488 (1..(n as u64) + 1).map(|x| x as f64).product::<f64>(),
489 ))
490 } else {
491 Err(anyhow!("factorial only works on non-negative integers"))
492 }
493 }
494 }
495 }
496 Expr::Spread(expr) => {
497 let val = evaluate_ast(expr, heap, bindings, call_depth)?;
498
499 match val {
500 List(pointer) => Ok(Spread(IterablePointer::List(pointer))),
501 Value::String(pointer) => Ok(Spread(IterablePointer::String(pointer))),
502 Value::Record(pointer) => Ok(Spread(IterablePointer::Record(pointer))),
503 _ => Err(anyhow!("expected a list, record, or string")),
504 }
505 }
506 }
507}
508
509fn collect_free_variables(expr: &Expr, vars: &mut Vec<String>, bound: &mut HashSet<String>) {
511 match expr {
512 Expr::Identifier(name) => {
513 if !bound.contains(name) && name != "infinity" && name != "inf" && name != "constants" {
514 vars.push(name.clone());
515 }
516 }
517 Expr::Lambda { args, body } => {
518 let mut new_bound = bound.clone();
519 for arg in args {
520 new_bound.insert(arg.get_name().to_string());
521 }
522 collect_free_variables(body, vars, &mut new_bound);
523 }
524 Expr::BinaryOp { left, right, .. } => {
525 collect_free_variables(left, vars, bound);
526 collect_free_variables(right, vars, bound);
527 }
528 Expr::UnaryOp { expr, .. } | Expr::PostfixOp { expr, .. } | Expr::Spread(expr) => {
529 collect_free_variables(expr, vars, bound);
530 }
531 Expr::Call { func, args } => {
532 collect_free_variables(func, vars, bound);
533 for arg in args {
534 collect_free_variables(arg, vars, bound);
535 }
536 }
537 Expr::Access { expr, index } => {
538 collect_free_variables(expr, vars, bound);
539 collect_free_variables(index, vars, bound);
540 }
541 Expr::DotAccess { expr, .. } => {
542 collect_free_variables(expr, vars, bound);
543 }
544 Expr::Conditional {
545 condition,
546 then_expr,
547 else_expr,
548 } => {
549 collect_free_variables(condition, vars, bound);
550 collect_free_variables(then_expr, vars, bound);
551 collect_free_variables(else_expr, vars, bound);
552 }
553 Expr::Assignment { value, .. } => {
554 collect_free_variables(value, vars, bound);
555 }
556 Expr::List(exprs) => {
557 for expr in exprs {
558 collect_free_variables(expr, vars, bound);
559 }
560 }
561 Expr::Record(entries) => {
562 for entry in entries {
563 match &entry.key {
564 RecordKey::Dynamic(expr) | RecordKey::Spread(expr) => {
565 collect_free_variables(expr, vars, bound);
566 }
567 _ => {}
568 }
569 if !matches!(entry.key, RecordKey::Shorthand(_) | RecordKey::Spread(_)) {
570 collect_free_variables(&entry.value, vars, bound);
571 }
572 }
573 }
574 Expr::DoBlock {
575 statements,
576 return_expr,
577 } => {
578 let mut block_bound = bound.clone();
580
581 for stmt in statements {
582 if let DoStatement::Expression(expr) = stmt {
583 if let Expr::Assignment { ident, value } = expr {
585 collect_free_variables(value, vars, &mut block_bound);
587 block_bound.insert(ident.clone());
589 } else {
590 collect_free_variables(expr, vars, &mut block_bound);
591 }
592 }
593 }
594 collect_free_variables(return_expr, vars, &mut block_bound);
595 }
596 _ => {}
597 }
598}
599
600pub fn validate_portable_value(
602 value: &Value,
603 heap: &Heap,
604 bindings: &HashMap<String, Value>,
605) -> Result<()> {
606 match value {
607 Value::Lambda(lambda_ptr) => {
608 if let Some(HeapValue::Lambda(lambda_def)) = heap.get(lambda_ptr.index()) {
610 let mut free_vars = Vec::new();
612 let mut bound_vars = HashSet::new();
613
614 for arg in &lambda_def.args {
616 bound_vars.insert(arg.get_name().to_string());
617 }
618
619 for key in lambda_def.scope.keys() {
621 bound_vars.insert(key.clone());
622 }
623
624 collect_free_variables(&lambda_def.body, &mut free_vars, &mut bound_vars);
625
626 for var in &free_vars {
632 let is_self_reference = lambda_def.name.as_ref() == Some(var);
633
634 if !lambda_def.scope.contains_key(var)
635 && !is_built_in_function(var)
636 && !is_self_reference
637 && !bindings.contains_key(var)
638 {
639 return Err(anyhow!(
640 "Function contains unbound variable \"{}\". Output functions must be self-contained.",
641 var
642 ));
643 }
644 }
645 }
646 Ok(())
647 }
648 Value::List(list_ptr) => {
649 let list = list_ptr.reify(heap).as_list()?;
651 for item in list {
652 validate_portable_value(item, heap, bindings)?;
653 }
654 Ok(())
655 }
656 Value::Record(record_ptr) => {
657 let record = record_ptr.reify(heap).as_record()?;
659 for value in record.values() {
660 validate_portable_value(value, heap, bindings)?;
661 }
662 Ok(())
663 }
664 _ => Ok(()),
666 }
667}
668
669fn evaluate_binary_op_ast(
671 op: BinaryOp,
672 left: &Expr,
673 right: &Expr,
674 heap: Rc<RefCell<Heap>>,
675 bindings: Rc<RefCell<HashMap<String, Value>>>,
676 call_depth: usize,
677) -> Result<Value> {
678 let lhs = evaluate_ast(left, Rc::clone(&heap), Rc::clone(&bindings), call_depth)?;
679 let rhs = evaluate_ast(right, Rc::clone(&heap), Rc::clone(&bindings), call_depth)?;
680
681 match (lhs, rhs) {
682 (Value::List(list_l), Value::List(list_r)) => {
683 let (l_vec, r_vec) = {
684 let borrowed_heap = &heap.borrow();
685 (
686 list_l.reify(borrowed_heap).as_list()?.clone(),
687 list_r.reify(borrowed_heap).as_list()?.clone(),
688 )
689 };
690
691 if l_vec.len() != r_vec.len() {
692 return Err(anyhow!(
693 "left- and right-hand-side lists must be the same length"
694 ));
695 }
696
697 match op {
698 BinaryOp::Equal => {
699 let borrowed_heap = heap.borrow();
700 let mut all_equal = true;
701 for (l, r) in l_vec.iter().zip(&r_vec) {
702 if !l.equals(r, &borrowed_heap)? {
703 all_equal = false;
704 break;
705 }
706 }
707 Ok(Bool(all_equal))
708 }
709 BinaryOp::NotEqual => {
710 let borrowed_heap = heap.borrow();
711 let mut all_not_equal = true;
712 for (l, r) in l_vec.iter().zip(&r_vec) {
713 if l.equals(r, &borrowed_heap)? {
714 all_not_equal = false;
715 break;
716 }
717 }
718 Ok(Bool(all_not_equal))
719 }
720 BinaryOp::Less => {
721 let borrowed_heap = heap.borrow();
722 let mut all_less = true;
723 for (l, r) in l_vec.iter().zip(&r_vec) {
724 match l.compare(r, &borrowed_heap)? {
725 Some(std::cmp::Ordering::Less) => continue,
726 _ => {
727 all_less = false;
728 break;
729 }
730 }
731 }
732 Ok(Bool(all_less))
733 }
734 BinaryOp::LessEq => {
735 let borrowed_heap = heap.borrow();
736 let mut all_less_eq = true;
737 for (l, r) in l_vec.iter().zip(&r_vec) {
738 match l.compare(r, &borrowed_heap)? {
739 Some(std::cmp::Ordering::Less) | Some(std::cmp::Ordering::Equal) => {
740 continue;
741 }
742 _ => {
743 all_less_eq = false;
744 break;
745 }
746 }
747 }
748 Ok(Bool(all_less_eq))
749 }
750 BinaryOp::Greater => {
751 let borrowed_heap = heap.borrow();
752 let mut all_greater = true;
753 for (l, r) in l_vec.iter().zip(&r_vec) {
754 match l.compare(r, &borrowed_heap)? {
755 Some(std::cmp::Ordering::Greater) => continue,
756 _ => {
757 all_greater = false;
758 break;
759 }
760 }
761 }
762 Ok(Bool(all_greater))
763 }
764 BinaryOp::GreaterEq => {
765 let borrowed_heap = heap.borrow();
766 let mut all_greater_eq = true;
767 for (l, r) in l_vec.iter().zip(&r_vec) {
768 match l.compare(r, &borrowed_heap)? {
769 Some(std::cmp::Ordering::Greater) | Some(std::cmp::Ordering::Equal) => {
770 continue;
771 }
772 _ => {
773 all_greater_eq = false;
774 break;
775 }
776 }
777 }
778 Ok(Bool(all_greater_eq))
779 }
780 BinaryOp::And | BinaryOp::NaturalAnd => {
781 let mapped_list = l_vec
782 .iter()
783 .zip(&r_vec)
784 .map(|(l, r)| Ok(Bool(l.as_bool()? && r.as_bool()?)))
785 .collect::<Result<Vec<Value>>>()?;
786 Ok(heap.borrow_mut().insert_list(mapped_list))
787 }
788 BinaryOp::Or | BinaryOp::NaturalOr => {
789 let mapped_list = l_vec
790 .iter()
791 .zip(&r_vec)
792 .map(|(l, r)| Ok(Bool(l.as_bool()? || r.as_bool()?)))
793 .collect::<Result<Vec<Value>>>()?;
794 Ok(heap.borrow_mut().insert_list(mapped_list))
795 }
796 BinaryOp::Add => {
797 let mapped_list = l_vec
798 .iter()
799 .zip(&r_vec)
800 .map(|(l, r)| match (l, r) {
801 (Value::String(_), Value::String(_)) => {
802 let (l_str, r_str) = {
803 (
804 l.as_string(&heap.borrow())?.to_string(),
805 r.as_string(&heap.borrow())?.to_string(),
806 )
807 };
808 Ok(heap
809 .borrow_mut()
810 .insert_string(format!("{}{}", l_str, r_str)))
811 }
812 (Value::Number(_), Value::Number(_)) => {
813 Ok(Number(l.as_number()? + r.as_number()?))
814 }
815 _ => Err(anyhow!("can't add {} and {}", l.get_type(), r.get_type())),
816 })
817 .collect::<Result<Vec<Value>>>()?;
818 Ok(heap.borrow_mut().insert_list(mapped_list))
819 }
820 BinaryOp::Subtract => {
821 let mapped_list = l_vec
822 .iter()
823 .zip(&r_vec)
824 .map(|(l, r)| Ok(Number(l.as_number()? - r.as_number()?)))
825 .collect::<Result<Vec<Value>>>()?;
826 Ok(heap.borrow_mut().insert_list(mapped_list))
827 }
828 BinaryOp::Multiply => {
829 let mapped_list = l_vec
830 .iter()
831 .zip(&r_vec)
832 .map(|(l, r)| Ok(Number(l.as_number()? * r.as_number()?)))
833 .collect::<Result<Vec<Value>>>()?;
834 Ok(heap.borrow_mut().insert_list(mapped_list))
835 }
836 BinaryOp::Divide => {
837 let mapped_list = l_vec
838 .iter()
839 .zip(&r_vec)
840 .map(|(l, r)| Ok(Number(l.as_number()? / r.as_number()?)))
841 .collect::<Result<Vec<Value>>>()?;
842 Ok(heap.borrow_mut().insert_list(mapped_list))
843 }
844 BinaryOp::Modulo => {
845 let mapped_list = l_vec
846 .iter()
847 .zip(&r_vec)
848 .map(|(l, r)| Ok(Number(l.as_number()? % r.as_number()?)))
849 .collect::<Result<Vec<Value>>>()?;
850 Ok(heap.borrow_mut().insert_list(mapped_list))
851 }
852 BinaryOp::Power => {
853 let mapped_list = l_vec
854 .iter()
855 .zip(&r_vec)
856 .map(|(l, r)| Ok(Number(l.as_number()?.powf(r.as_number()?))))
857 .collect::<Result<Vec<Value>>>()?;
858 Ok(heap.borrow_mut().insert_list(mapped_list))
859 }
860 BinaryOp::Coalesce => {
861 let mapped_list = l_vec
862 .iter()
863 .zip(&r_vec)
864 .map(|(l, r)| if *l == Value::Null { Ok(*r) } else { Ok(*l) })
865 .collect::<Result<Vec<Value>>>()?;
866 Ok(heap.borrow_mut().insert_list(mapped_list))
867 }
868 BinaryOp::Pipe => {
869 let mapped_list = l_vec
870 .iter()
871 .zip(&r_vec)
872 .map(|(l, r)| {
873 if !r.is_lambda() && !r.is_built_in() {
874 return Err(anyhow!(
875 "right-hand iterable contains non-function {}",
876 r.stringify_internal(&heap.borrow())
877 ));
878 }
879
880 let def = {
881 let borrowed_heap = &heap.borrow();
882 get_function_def(r, borrowed_heap).ok_or_else(|| {
883 anyhow!(
884 "unknown function: {}",
885 r.stringify_internal(borrowed_heap)
886 )
887 })?
888 };
889
890 def.call(
891 *r,
892 vec![*l],
893 Rc::clone(&heap),
894 Rc::clone(&bindings),
895 call_depth,
896 )
897 })
898 .collect::<Result<Vec<Value>>>()?;
899 Ok(heap.borrow_mut().insert_list(mapped_list))
900 }
901 }
902 }
903 (Value::List(list), scalar) | (scalar, Value::List(list)) => {
904 let (l_vec, is_list_first) = {
905 let borrowed_heap = &heap.borrow();
906 if matches!(lhs, Value::List(_)) {
907 (list.reify(borrowed_heap).as_list()?.clone(), true)
908 } else {
909 (list.reify(borrowed_heap).as_list()?.clone(), false)
910 }
911 };
912
913 match op {
914 BinaryOp::Equal => {
915 let borrowed_heap = heap.borrow();
916 let mut all_equal = true;
917 for v in l_vec.iter() {
918 if !v.equals(&scalar, &borrowed_heap)? {
919 all_equal = false;
920 break;
921 }
922 }
923 Ok(Bool(all_equal))
924 }
925 BinaryOp::NotEqual => {
926 let borrowed_heap = heap.borrow();
927 let mut all_not_equal = true;
928 for v in l_vec.iter() {
929 if v.equals(&scalar, &borrowed_heap)? {
930 all_not_equal = false;
931 break;
932 }
933 }
934 Ok(Bool(all_not_equal))
935 }
936 BinaryOp::Less => {
937 let borrowed_heap = heap.borrow();
938 let mut all_less = true;
939 for v in l_vec.iter() {
940 let ordering = if is_list_first {
941 v.compare(&scalar, &borrowed_heap)?
942 } else {
943 scalar.compare(v, &borrowed_heap)?
944 };
945 match ordering {
946 Some(std::cmp::Ordering::Less) => continue,
947 _ => {
948 all_less = false;
949 break;
950 }
951 }
952 }
953 Ok(Bool(all_less))
954 }
955 BinaryOp::LessEq => {
956 let borrowed_heap = heap.borrow();
957 let mut all_less_eq = true;
958 for v in l_vec.iter() {
959 let ordering = if is_list_first {
960 v.compare(&scalar, &borrowed_heap)?
961 } else {
962 scalar.compare(v, &borrowed_heap)?
963 };
964 match ordering {
965 Some(std::cmp::Ordering::Less) | Some(std::cmp::Ordering::Equal) => {
966 continue;
967 }
968 _ => {
969 all_less_eq = false;
970 break;
971 }
972 }
973 }
974 Ok(Bool(all_less_eq))
975 }
976 BinaryOp::Greater => {
977 let borrowed_heap = heap.borrow();
978 let mut all_greater = true;
979 for v in l_vec.iter() {
980 let ordering = if is_list_first {
981 v.compare(&scalar, &borrowed_heap)?
982 } else {
983 scalar.compare(v, &borrowed_heap)?
984 };
985 match ordering {
986 Some(std::cmp::Ordering::Greater) => continue,
987 _ => {
988 all_greater = false;
989 break;
990 }
991 }
992 }
993 Ok(Bool(all_greater))
994 }
995 BinaryOp::GreaterEq => {
996 let borrowed_heap = heap.borrow();
997 let mut all_greater_eq = true;
998 for v in l_vec.iter() {
999 let ordering = if is_list_first {
1000 v.compare(&scalar, &borrowed_heap)?
1001 } else {
1002 scalar.compare(v, &borrowed_heap)?
1003 };
1004 match ordering {
1005 Some(std::cmp::Ordering::Greater) | Some(std::cmp::Ordering::Equal) => {
1006 continue;
1007 }
1008 _ => {
1009 all_greater_eq = false;
1010 break;
1011 }
1012 }
1013 }
1014 Ok(Bool(all_greater_eq))
1015 }
1016 BinaryOp::And | BinaryOp::NaturalAnd => {
1017 let mapped_list = if is_list_first {
1018 l_vec
1019 .iter()
1020 .map(|v| Ok(Bool(v.as_bool()? && scalar.as_bool()?)))
1021 .collect::<Result<Vec<Value>>>()?
1022 } else {
1023 l_vec
1024 .iter()
1025 .map(|v| Ok(Bool(scalar.as_bool()? && v.as_bool()?)))
1026 .collect::<Result<Vec<Value>>>()?
1027 };
1028 Ok(heap.borrow_mut().insert_list(mapped_list))
1029 }
1030 BinaryOp::Or | BinaryOp::NaturalOr => {
1031 let mapped_list = if is_list_first {
1032 l_vec
1033 .iter()
1034 .map(|v| Ok(Bool(v.as_bool()? || scalar.as_bool()?)))
1035 .collect::<Result<Vec<Value>>>()?
1036 } else {
1037 l_vec
1038 .iter()
1039 .map(|v| Ok(Bool(scalar.as_bool()? || v.as_bool()?)))
1040 .collect::<Result<Vec<Value>>>()?
1041 };
1042 Ok(heap.borrow_mut().insert_list(mapped_list))
1043 }
1044 BinaryOp::Add => {
1045 let mapped_list = if is_list_first {
1046 l_vec
1047 .iter()
1048 .map(|v| match (v, &scalar) {
1049 (Value::String(_), Value::String(_)) => {
1050 let (v_str, s_str) = {
1051 (
1052 v.as_string(&heap.borrow())?.to_string(),
1053 scalar.as_string(&heap.borrow())?.to_string(),
1054 )
1055 };
1056 Ok(heap
1057 .borrow_mut()
1058 .insert_string(format!("{}{}", v_str, s_str)))
1059 }
1060 (Value::Number(_), Value::Number(_)) => {
1061 Ok(Number(v.as_number()? + scalar.as_number()?))
1062 }
1063 _ => Err(anyhow!(
1064 "can't add {} and {}",
1065 v.get_type(),
1066 scalar.get_type()
1067 )),
1068 })
1069 .collect::<Result<Vec<Value>>>()?
1070 } else {
1071 l_vec
1072 .iter()
1073 .map(|v| match (&scalar, v) {
1074 (Value::String(_), Value::String(_)) => {
1075 let (s_str, v_str) = {
1076 (
1077 scalar.as_string(&heap.borrow())?.to_string(),
1078 v.as_string(&heap.borrow())?.to_string(),
1079 )
1080 };
1081 Ok(heap
1082 .borrow_mut()
1083 .insert_string(format!("{}{}", s_str, v_str)))
1084 }
1085 (Value::Number(_), Value::Number(_)) => {
1086 Ok(Number(scalar.as_number()? + v.as_number()?))
1087 }
1088 _ => Err(anyhow!(
1089 "can't add {} and {}",
1090 scalar.get_type(),
1091 v.get_type()
1092 )),
1093 })
1094 .collect::<Result<Vec<Value>>>()?
1095 };
1096 Ok(heap.borrow_mut().insert_list(mapped_list))
1097 }
1098 BinaryOp::Subtract => {
1099 let mapped_list = if is_list_first {
1100 l_vec
1101 .iter()
1102 .map(|v| Ok(Number(v.as_number()? - scalar.as_number()?)))
1103 .collect::<Result<Vec<Value>>>()?
1104 } else {
1105 l_vec
1106 .iter()
1107 .map(|v| Ok(Number(scalar.as_number()? - v.as_number()?)))
1108 .collect::<Result<Vec<Value>>>()?
1109 };
1110 Ok(heap.borrow_mut().insert_list(mapped_list))
1111 }
1112 BinaryOp::Multiply => {
1113 let mapped_list = l_vec
1114 .iter()
1115 .map(|v| Ok(Number(v.as_number()? * scalar.as_number()?)))
1116 .collect::<Result<Vec<Value>>>()?;
1117 Ok(heap.borrow_mut().insert_list(mapped_list))
1118 }
1119 BinaryOp::Divide => {
1120 let mapped_list = if is_list_first {
1121 l_vec
1122 .iter()
1123 .map(|v| Ok(Number(v.as_number()? / scalar.as_number()?)))
1124 .collect::<Result<Vec<Value>>>()?
1125 } else {
1126 l_vec
1127 .iter()
1128 .map(|v| Ok(Number(scalar.as_number()? / v.as_number()?)))
1129 .collect::<Result<Vec<Value>>>()?
1130 };
1131 Ok(heap.borrow_mut().insert_list(mapped_list))
1132 }
1133 BinaryOp::Modulo => {
1134 let mapped_list = if is_list_first {
1135 l_vec
1136 .iter()
1137 .map(|v| Ok(Number(v.as_number()? % scalar.as_number()?)))
1138 .collect::<Result<Vec<Value>>>()?
1139 } else {
1140 l_vec
1141 .iter()
1142 .map(|v| Ok(Number(scalar.as_number()? % v.as_number()?)))
1143 .collect::<Result<Vec<Value>>>()?
1144 };
1145 Ok(heap.borrow_mut().insert_list(mapped_list))
1146 }
1147 BinaryOp::Power => {
1148 let mapped_list = if is_list_first {
1149 l_vec
1150 .iter()
1151 .map(|v| Ok(Number(v.as_number()?.powf(scalar.as_number()?))))
1152 .collect::<Result<Vec<Value>>>()?
1153 } else {
1154 l_vec
1155 .iter()
1156 .map(|v| Ok(Number(scalar.as_number()?.powf(v.as_number()?))))
1157 .collect::<Result<Vec<Value>>>()?
1158 };
1159 Ok(heap.borrow_mut().insert_list(mapped_list))
1160 }
1161 BinaryOp::Coalesce => {
1162 let mapped_list = if is_list_first {
1163 l_vec
1164 .iter()
1165 .map(|v| {
1166 if *v == Value::Null {
1167 Ok(scalar)
1168 } else {
1169 Ok(*v)
1170 }
1171 })
1172 .collect::<Result<Vec<Value>>>()?
1173 } else {
1174 l_vec
1175 .iter()
1176 .map(|v| {
1177 if scalar == Value::Null {
1178 Ok(*v)
1179 } else {
1180 Ok(scalar)
1181 }
1182 })
1183 .collect::<Result<Vec<Value>>>()?
1184 };
1185 Ok(heap.borrow_mut().insert_list(mapped_list))
1186 }
1187 BinaryOp::Pipe => {
1188 if is_list_first {
1189 if !scalar.is_callable() {
1190 return Err(anyhow!(
1191 "can't call a non-function: {}",
1192 scalar.stringify_internal(&heap.borrow())
1193 ));
1194 }
1195
1196 let list = heap.borrow_mut().insert_list(l_vec.clone());
1197
1198 let call_result = get_built_in_function_def_by_ident("map").unwrap().call(
1199 scalar,
1200 vec![list, scalar],
1201 Rc::clone(&heap),
1202 Rc::clone(&bindings),
1203 call_depth,
1204 )?;
1205
1206 let mapped_list = { call_result.as_list(&heap.borrow())?.clone() };
1207
1208 Ok(heap.borrow_mut().insert_list(mapped_list))
1209 } else {
1210 Err(anyhow!(
1211 "pipe operator '|>' requires function on right side"
1212 ))
1213 }
1214 }
1215 }
1216 }
1217 (lhs, rhs) => match op {
1218 BinaryOp::Equal => Ok(Bool(lhs.equals(&rhs, &heap.borrow())?)),
1219 BinaryOp::NotEqual => Ok(Bool(!lhs.equals(&rhs, &heap.borrow())?)),
1220 BinaryOp::Less => match lhs.compare(&rhs, &heap.borrow())? {
1221 Some(std::cmp::Ordering::Less) => Ok(Bool(true)),
1222 _ => Ok(Bool(false)),
1223 },
1224 BinaryOp::LessEq => match lhs.compare(&rhs, &heap.borrow())? {
1225 Some(std::cmp::Ordering::Less) | Some(std::cmp::Ordering::Equal) => Ok(Bool(true)),
1226 _ => Ok(Bool(false)),
1227 },
1228 BinaryOp::Greater => match lhs.compare(&rhs, &heap.borrow())? {
1229 Some(std::cmp::Ordering::Greater) => Ok(Bool(true)),
1230 _ => Ok(Bool(false)),
1231 },
1232 BinaryOp::GreaterEq => match lhs.compare(&rhs, &heap.borrow())? {
1233 Some(std::cmp::Ordering::Greater) | Some(std::cmp::Ordering::Equal) => {
1234 Ok(Bool(true))
1235 }
1236 _ => Ok(Bool(false)),
1237 },
1238 BinaryOp::And | BinaryOp::NaturalAnd => Ok(Bool(lhs.as_bool()? && rhs.as_bool()?)),
1239 BinaryOp::Or | BinaryOp::NaturalOr => Ok(Bool(lhs.as_bool()? || rhs.as_bool()?)),
1240 BinaryOp::Add => {
1241 if lhs.is_string() {
1242 let (l_str, r_str) = {
1243 (
1244 lhs.as_string(&heap.borrow())?.to_string(),
1245 rhs.as_string(&heap.borrow())?.to_string(),
1246 )
1247 };
1248
1249 return Ok(heap
1250 .borrow_mut()
1251 .insert_string(format!("{}{}", l_str, r_str)));
1252 }
1253
1254 Ok(Number(lhs.as_number()? + rhs.as_number()?))
1255 }
1256 BinaryOp::Subtract => Ok(Number(lhs.as_number()? - rhs.as_number()?)),
1257 BinaryOp::Multiply => Ok(Number(lhs.as_number()? * rhs.as_number()?)),
1258 BinaryOp::Divide => Ok(Number(lhs.as_number()? / rhs.as_number()?)),
1259 BinaryOp::Modulo => Ok(Number(lhs.as_number()? % rhs.as_number()?)),
1260 BinaryOp::Power => Ok(Number(lhs.as_number()?.powf(rhs.as_number()?))),
1261 BinaryOp::Coalesce => {
1262 if lhs == Value::Null {
1263 Ok(rhs)
1264 } else {
1265 Ok(lhs)
1266 }
1267 }
1268 BinaryOp::Pipe => {
1269 if !rhs.is_callable() {
1270 return Err(anyhow!(
1271 "can't call a non-function ({} is of type {})",
1272 rhs.stringify_internal(&heap.borrow()),
1273 rhs.get_type()
1274 ));
1275 }
1276
1277 let def = { get_function_def(&rhs, &heap.borrow()) };
1278
1279 if def.is_none() {
1280 return Err(anyhow!(
1281 "unknown function: {}",
1282 rhs.stringify_internal(&heap.borrow())
1283 ));
1284 }
1285
1286 def.unwrap().call(
1287 rhs,
1288 vec![lhs],
1289 Rc::clone(&heap),
1290 Rc::clone(&bindings),
1291 call_depth,
1292 )
1293 }
1294 },
1295 }
1296}
1297
1298pub fn pairs_to_expr(pairs: Pairs<Rule>) -> Result<Expr> {
1300 PRATT
1301 .map_primary(|primary| match primary.as_rule() {
1302 Rule::number => Ok(Expr::Number(
1303 primary
1304 .as_str()
1305 .replace("_", "")
1306 .parse::<f64>()
1307 .map_err(anyhow::Error::from)?,
1308 )),
1309 Rule::list => {
1310 let list_pairs = primary.into_inner();
1311 let exprs = list_pairs
1312 .into_iter()
1313 .map(|pair| pairs_to_expr(pair.into_inner()))
1314 .collect::<Result<Vec<Expr>>>()?;
1315 Ok(Expr::List(exprs))
1316 }
1317 Rule::record => {
1318 let record_pairs = primary.into_inner();
1319 let mut entries = Vec::new();
1320
1321 for pair in record_pairs {
1322 match pair.as_rule() {
1323 Rule::record_pair => {
1324 let mut inner_pairs = pair.into_inner();
1325 let key_pair = inner_pairs.next().unwrap();
1326 let key = match key_pair.as_rule() {
1327 Rule::record_key_static => {
1328 let inner_key_pair = key_pair.into_inner().next().unwrap();
1329 match inner_key_pair.as_rule() {
1330 Rule::identifier => {
1331 RecordKey::Static(inner_key_pair.as_str().to_string())
1332 }
1333 Rule::string => RecordKey::Static(
1334 inner_key_pair.into_inner().as_str().to_string(),
1335 ),
1336 _ => unreachable!(),
1337 }
1338 }
1339 Rule::record_key_dynamic => RecordKey::Dynamic(Box::new(
1340 pairs_to_expr(key_pair.into_inner())?,
1341 )),
1342 _ => unreachable!(),
1343 };
1344
1345 let value = pairs_to_expr(inner_pairs.next().unwrap().into_inner())?;
1346 entries.push(RecordEntry { key, value });
1347 }
1348 Rule::record_shorthand => {
1349 let ident = pair.into_inner().next().unwrap().as_str().to_string();
1350 entries.push(RecordEntry {
1351 key: RecordKey::Shorthand(ident),
1352 value: Expr::Null, });
1354 }
1355 Rule::spread_expression => {
1356 let spread_expr = pairs_to_expr(pair.into_inner())?;
1357 entries.push(RecordEntry {
1358 key: RecordKey::Spread(Box::new(spread_expr)),
1359 value: Expr::Null, });
1361 }
1362 _ => {}
1363 }
1364 }
1365
1366 Ok(Expr::Record(entries))
1367 }
1368 Rule::bool => {
1369 let bool_str = primary.as_str();
1370 match bool_str {
1371 "true" => Ok(Expr::Bool(true)),
1372 "false" => Ok(Expr::Bool(false)),
1373 _ => unreachable!(),
1374 }
1375 }
1376 Rule::null => Ok(Expr::Null),
1377 Rule::string => {
1378 let contents = primary.into_inner().as_str().to_string();
1379 Ok(Expr::String(contents))
1380 }
1381 Rule::assignment => {
1382 let mut inner_pairs = primary.into_inner();
1383 let ident = inner_pairs.next().unwrap().as_str().to_string();
1384 let value = Box::new(pairs_to_expr(inner_pairs.next().unwrap().into_inner())?);
1385 Ok(Expr::Assignment { ident, value })
1386 }
1387 Rule::lambda => {
1388 let mut inner_pairs = primary.into_inner();
1389 let arg_list = inner_pairs.next().unwrap();
1390 let body_pairs = inner_pairs.next().unwrap();
1391
1392 let mut args = Vec::new();
1393 for arg_pair in arg_list.into_inner() {
1394 match arg_pair.as_rule() {
1395 Rule::required_arg => {
1396 args.push(LambdaArg::Required(
1397 arg_pair.into_inner().as_str().to_string(),
1398 ));
1399 }
1400 Rule::optional_arg => {
1401 args.push(LambdaArg::Optional(
1402 arg_pair.into_inner().as_str().to_string(),
1403 ));
1404 }
1405 Rule::rest_arg => {
1406 args.push(LambdaArg::Rest(arg_pair.into_inner().as_str().to_string()));
1407 }
1408 _ => {}
1409 }
1410 }
1411
1412 let body = Box::new(pairs_to_expr(body_pairs.into_inner())?);
1413 Ok(Expr::Lambda { args, body })
1414 }
1415 Rule::conditional => {
1416 let mut inner_pairs = primary.into_inner();
1417 let condition = Box::new(pairs_to_expr(inner_pairs.next().unwrap().into_inner())?);
1418 let then_expr = Box::new(pairs_to_expr(inner_pairs.next().unwrap().into_inner())?);
1419 let else_expr = Box::new(pairs_to_expr(inner_pairs.next().unwrap().into_inner())?);
1420 Ok(Expr::Conditional {
1421 condition,
1422 then_expr,
1423 else_expr,
1424 })
1425 }
1426 Rule::do_block => {
1427 let inner_pairs = primary.into_inner();
1428 let mut statements = Vec::new();
1429 let mut return_expr = Box::new(Expr::Null);
1430
1431 for pair in inner_pairs {
1432 match pair.as_rule() {
1433 Rule::do_statement => {
1434 if let Some(inner) = pair.into_inner().next() {
1435 if inner.as_rule() == Rule::expression {
1436 statements.push(DoStatement::Expression(pairs_to_expr(
1437 inner.into_inner(),
1438 )?));
1439 } else if inner.as_rule() == Rule::comment {
1440 statements
1441 .push(DoStatement::Comment(inner.as_str().to_string()));
1442 }
1443 }
1444 }
1445 Rule::return_statement => {
1446 let return_expr_pair = pair.into_inner().next().unwrap();
1447 return_expr = Box::new(pairs_to_expr(return_expr_pair.into_inner())?);
1448 }
1449 _ => {}
1450 }
1451 }
1452
1453 Ok(Expr::DoBlock {
1454 statements,
1455 return_expr,
1456 })
1457 }
1458 Rule::identifier => {
1459 let ident = primary.as_str();
1460
1461 if let Some(built_in) = BuiltInFunction::from_ident(ident) {
1463 Ok(Expr::BuiltIn(built_in))
1464 } else {
1465 Ok(Expr::Identifier(ident.to_string()))
1466 }
1467 }
1468 Rule::expression => pairs_to_expr(primary.into_inner()),
1469 _ => unreachable!("{}", primary.as_str()),
1470 })
1471 .map_prefix(|op, rhs| match op.as_rule() {
1472 Rule::negation => Ok(Expr::UnaryOp {
1473 op: UnaryOp::Negate,
1474 expr: Box::new(rhs?),
1475 }),
1476 Rule::spread_operator => Ok(Expr::Spread(Box::new(rhs?))),
1477 Rule::invert | Rule::natural_not => Ok(Expr::UnaryOp {
1478 op: UnaryOp::Not,
1479 expr: Box::new(rhs?),
1480 }),
1481 _ => unreachable!(),
1482 })
1483 .map_postfix(|lhs, op| match op.as_rule() {
1484 Rule::factorial => Ok(Expr::PostfixOp {
1485 op: PostfixOp::Factorial,
1486 expr: Box::new(lhs?),
1487 }),
1488 Rule::access => {
1489 let index_expr = pairs_to_expr(op.into_inner())?;
1490 Ok(Expr::Access {
1491 expr: Box::new(lhs?),
1492 index: Box::new(index_expr),
1493 })
1494 }
1495 Rule::dot_access => {
1496 let field = op.into_inner().as_str().to_string();
1497 Ok(Expr::DotAccess {
1498 expr: Box::new(lhs?),
1499 field,
1500 })
1501 }
1502 Rule::call_list => {
1503 let call_list = op.into_inner();
1504 let args = call_list
1505 .into_iter()
1506 .map(|arg| pairs_to_expr(arg.into_inner()))
1507 .collect::<Result<Vec<Expr>>>()?;
1508 Ok(Expr::Call {
1509 func: Box::new(lhs?),
1510 args,
1511 })
1512 }
1513 _ => unreachable!(),
1514 })
1515 .map_infix(|lhs, op, rhs| {
1516 let op = match op.as_rule() {
1517 Rule::add => BinaryOp::Add,
1518 Rule::subtract => BinaryOp::Subtract,
1519 Rule::multiply => BinaryOp::Multiply,
1520 Rule::divide => BinaryOp::Divide,
1521 Rule::modulo => BinaryOp::Modulo,
1522 Rule::power => BinaryOp::Power,
1523 Rule::equal => BinaryOp::Equal,
1524 Rule::not_equal => BinaryOp::NotEqual,
1525 Rule::less => BinaryOp::Less,
1526 Rule::less_eq => BinaryOp::LessEq,
1527 Rule::greater => BinaryOp::Greater,
1528 Rule::greater_eq => BinaryOp::GreaterEq,
1529 Rule::and => BinaryOp::And,
1530 Rule::natural_and => BinaryOp::NaturalAnd,
1531 Rule::or => BinaryOp::Or,
1532 Rule::natural_or => BinaryOp::NaturalOr,
1533 Rule::pipe => BinaryOp::Pipe,
1534 Rule::coalesce => BinaryOp::Coalesce,
1535 _ => unreachable!(),
1536 };
1537 Ok(Expr::BinaryOp {
1538 op,
1539 left: Box::new(lhs?),
1540 right: Box::new(rhs?),
1541 })
1542 })
1543 .parse(pairs)
1544}
1545
1546#[cfg(test)]
1547mod tests {
1548 use super::*;
1549 use crate::{heap::LambdaPointer, parser::get_pairs};
1550
1551 fn parse_and_evaluate(
1552 input: &str,
1553 heap: Option<Rc<RefCell<Heap>>>,
1554 bindings: Option<Rc<RefCell<HashMap<String, Value>>>>,
1555 ) -> Result<Value> {
1556 let binding = input.to_string();
1557 let mut pairs = get_pairs(&binding).unwrap();
1558 let expr = pairs.next().unwrap().into_inner();
1559 evaluate_pairs(
1560 expr,
1561 heap.unwrap_or(Rc::new(RefCell::new(Heap::new()))),
1562 bindings.unwrap_or(Rc::new(RefCell::new(HashMap::new()))),
1563 0,
1564 )
1565 }
1566
1567 #[test]
1568 fn addition_of_integers() {
1569 let result = parse_and_evaluate("5 + 2", None, None).unwrap();
1570 assert_eq!(result, Value::Number(7.0));
1571 }
1572
1573 #[test]
1574 fn exponentiation_of_two_integers() {
1575 let result = parse_and_evaluate("2 ^ 3", None, None).unwrap();
1576 assert_eq!(result, Value::Number(8.0));
1577 }
1578
1579 #[test]
1580 fn multiplication_of_integers() {
1581 let result = parse_and_evaluate("8 * 4", None, None).unwrap();
1582 assert_eq!(result, Value::Number(32.0));
1583 }
1584
1585 #[test]
1586 fn division_with_integer_resulting_in_decimal() {
1587 let result = parse_and_evaluate("9 / 2", None, None).unwrap();
1588 assert_eq!(result, Value::Number(4.5));
1589 }
1590
1591 #[test]
1592 fn addition_with_nested_expression() {
1593 let result = parse_and_evaluate("5 + (2 * 4)", None, None).unwrap();
1594 assert_eq!(result, Value::Number(13.0));
1595 }
1596
1597 #[test]
1598 fn grouping_and_multiplication_in_expression() {
1599 let result = parse_and_evaluate("(3 + 2) * 2", None, None).unwrap();
1600 assert_eq!(result, Value::Number(10.0));
1601 }
1602
1603 #[test]
1604 fn mixed_operations_with_decimal_and_precedence() {
1605 let result = parse_and_evaluate("6.5 / 2 + 4 * 2", None, None).unwrap();
1606 assert_eq!(result, Value::Number(11.25));
1607 }
1608
1609 #[test]
1610 fn exponentiation_with_nested_expression() {
1611 let result = parse_and_evaluate("2 ^ (1 + 2)", None, None).unwrap();
1612 assert_eq!(result, Value::Number(8.0));
1613 }
1614
1615 #[test]
1616 fn complex_expression_with_decimals() {
1617 let result = parse_and_evaluate("7.5 - 3.25 + 2 * (8 / 4)", None, None).unwrap();
1618 assert_eq!(result, Value::Number(8.25));
1619 }
1620
1621 #[test]
1622 fn subtraction_with_decimal_result() {
1623 let result = parse_and_evaluate("10.75 - 3.5", None, None).unwrap();
1624 assert_eq!(result, Value::Number(7.25));
1625 }
1626
1627 #[test]
1628 fn multiplication_of_two_decimals() {
1629 let result = parse_and_evaluate("3.5 * 2.0", None, None).unwrap();
1630 assert_eq!(result, Value::Number(7.0));
1631 }
1632
1633 #[test]
1634 fn division_of_two_decimals() {
1635 let result = parse_and_evaluate("7.5 / 2.5", None, None).unwrap();
1636 assert_eq!(result, Value::Number(3.0));
1637 }
1638
1639 #[test]
1640 fn boolean_and() {
1641 let result = parse_and_evaluate("true and false", None, None).unwrap();
1642 assert_eq!(result, Value::Bool(false));
1643 }
1644
1645 #[test]
1646 fn boolean_and_alt() {
1647 let result = parse_and_evaluate("true && false", None, None).unwrap();
1648 assert_eq!(result, Value::Bool(false));
1649 }
1650
1651 #[test]
1652 fn boolean_or() {
1653 let result = parse_and_evaluate("true or false", None, None).unwrap();
1654 assert_eq!(result, Value::Bool(true));
1655 }
1656
1657 #[test]
1658 fn boolean_or_alt() {
1659 let result = parse_and_evaluate("true || false", None, None).unwrap();
1660 assert_eq!(result, Value::Bool(true));
1661 }
1662
1663 #[test]
1664 fn boolean_and_with_nested_expression() {
1665 let result = parse_and_evaluate("true and (false or true)", None, None).unwrap();
1666 assert_eq!(result, Value::Bool(true));
1667 }
1668
1669 #[test]
1670 fn boolean_and_with_nested_expression_alt() {
1671 let result = parse_and_evaluate("true && (false || true)", None, None).unwrap();
1672 assert_eq!(result, Value::Bool(true));
1673 }
1674
1675 #[test]
1676 fn boolean_or_with_nested_expression() {
1677 let result = parse_and_evaluate("true or (false and true)", None, None).unwrap();
1678 assert_eq!(result, Value::Bool(true));
1679 }
1680
1681 #[test]
1682 fn boolean_or_with_nested_expression_alt() {
1683 let result = parse_and_evaluate("true || (false && true)", None, None).unwrap();
1684 assert_eq!(result, Value::Bool(true));
1685 }
1686
1687 #[test]
1688 fn logical_not() {
1689 let result = parse_and_evaluate("!true", None, None).unwrap();
1690 assert_eq!(result, Value::Bool(false));
1691 }
1692
1693 #[test]
1694 fn logical_not_with_nested_expression() {
1695 let result = parse_and_evaluate("!(true and false)", None, None).unwrap();
1696 assert_eq!(result, Value::Bool(true));
1697 }
1698
1699 #[test]
1700 fn equality_of_two_integers() {
1701 let result = parse_and_evaluate("5 == 5", None, None).unwrap();
1702 assert_eq!(result, Value::Bool(true));
1703 }
1704
1705 #[test]
1706 fn inequality_of_two_integers() {
1707 let result = parse_and_evaluate("5 != 5", None, None).unwrap();
1708 assert_eq!(result, Value::Bool(false));
1709 }
1710
1711 #[test]
1712 fn less_than_comparison() {
1713 let result = parse_and_evaluate("5 < 10", None, None).unwrap();
1714 assert_eq!(result, Value::Bool(true));
1715 }
1716
1717 #[test]
1718 fn less_than_or_equal_comparison() {
1719 let result = parse_and_evaluate("5 <= 5", None, None).unwrap();
1720 assert_eq!(result, Value::Bool(true));
1721 }
1722
1723 #[test]
1724 fn greater_than_comparison() {
1725 let result = parse_and_evaluate("10 > 5", None, None).unwrap();
1726 assert_eq!(result, Value::Bool(true));
1727 }
1728
1729 #[test]
1730 fn greater_than_or_equal_comparison() {
1731 let result = parse_and_evaluate("5 >= 5", None, None).unwrap();
1732 assert_eq!(result, Value::Bool(true));
1733 }
1734
1735 #[test]
1736 fn equality_of_two_lists() {
1737 let result = parse_and_evaluate("[1, 2, 3] == [1, 2, 3]", None, None);
1739 assert!(result.is_ok());
1740 }
1741
1742 #[test]
1743 fn inequality_of_two_lists() {
1744 let result = parse_and_evaluate("[1, 2, 3] != [2, 3, 4]", None, None);
1746 assert!(result.is_ok());
1747 }
1748
1749 #[test]
1750 fn conditional_expression_with_true_condition() {
1751 let result = parse_and_evaluate("if true then 5 else 10", None, None).unwrap();
1752 assert_eq!(result, Value::Number(5.0));
1753 }
1754
1755 #[test]
1756 fn conditional_expression_with_false_condition() {
1757 let result = parse_and_evaluate("if false then 5 else 10", None, None).unwrap();
1758 assert_eq!(result, Value::Number(10.0));
1759 }
1760
1761 #[test]
1762 fn factorial_of_integer() {
1763 let result = parse_and_evaluate("5!", None, None).unwrap();
1764 assert_eq!(result, Value::Number(120.0));
1765 }
1766
1767 #[test]
1768 fn factorial_of_zero() {
1769 let result = parse_and_evaluate("0!", None, None).unwrap();
1770 assert_eq!(result, Value::Number(1.0));
1771 }
1772
1773 #[test]
1774 fn factorial_of_negative_integer() {
1775 let result = parse_and_evaluate("(-5)!", None, None);
1776 assert!(result.is_err());
1777 }
1778
1779 #[test]
1780 fn factorial_of_decimal() {
1781 let result = parse_and_evaluate("5.5!", None, None);
1782 assert!(result.is_err());
1783 }
1784
1785 #[test]
1786 fn string_concatenation() {
1787 let heap = Rc::new(RefCell::new(Heap::new()));
1788 let result =
1789 parse_and_evaluate("\"hello\" + \"world\"", Some(Rc::clone(&heap)), None).unwrap();
1790
1791 assert!(matches!(result, Value::String(_)));
1792 assert_eq!(result.as_string(&heap.borrow()).unwrap(), "helloworld");
1793 }
1794
1795 #[test]
1796 fn string_concatenation_with_integer() {
1797 let result = parse_and_evaluate("\"hello\" + 5", None, None);
1798 assert!(result.is_err());
1799 }
1800
1801 #[test]
1802 fn variable_assignment() {
1803 let bindings = Rc::new(RefCell::new(HashMap::new()));
1804 let result = parse_and_evaluate("x = 5", None, Some(Rc::clone(&bindings))).unwrap();
1805
1806 assert_eq!(result, Value::Number(5.0));
1807 assert_eq!(bindings.borrow().get("x").unwrap(), &Value::Number(5.0));
1808 }
1809
1810 #[test]
1811 fn variable_assignment_with_expression() {
1812 let bindings = Rc::new(RefCell::new(HashMap::new()));
1813 let result = parse_and_evaluate("x = 5 + 2", None, Some(Rc::clone(&bindings))).unwrap();
1814 assert_eq!(result, Value::Number(7.0));
1815 assert_eq!(bindings.borrow().get("x").unwrap(), &Value::Number(7.0));
1816 }
1817
1818 #[test]
1819 fn variable_assignment_with_lambda() {
1820 let heap = Rc::new(RefCell::new(Heap::new()));
1821 let bindings = Rc::new(RefCell::new(HashMap::new()));
1822 let result = parse_and_evaluate(
1823 "f = x => x + 1",
1824 Some(Rc::clone(&heap)),
1825 Some(Rc::clone(&bindings)),
1826 )
1827 .unwrap();
1828
1829 {
1830 let heap_borrow = heap.borrow();
1831 let lambda_def = result.as_lambda(&heap_borrow).unwrap();
1832 assert_eq!(lambda_def.name, Some("f".to_string()));
1833 assert_eq!(lambda_def.args, vec![LambdaArg::Required("x".to_string())]);
1834 assert_eq!(lambda_def.scope, HashMap::new());
1835 match &lambda_def.body {
1837 Expr::BinaryOp {
1838 op: BinaryOp::Add,
1839 left,
1840 right,
1841 } => match (left.as_ref(), right.as_ref()) {
1842 (Expr::Identifier(x), Expr::Number(n)) => {
1843 assert_eq!(x, "x");
1844 assert_eq!(*n, 1.0);
1845 }
1846 _ => panic!("Expected Identifier('x') + Number(1)"),
1847 },
1848 _ => panic!("Expected BinaryOp(Add)"),
1849 }
1850 }
1851 assert_eq!(
1852 bindings.borrow().get("f").unwrap(),
1853 &Value::Lambda(LambdaPointer::new(1))
1854 );
1855 }
1856
1857 #[test]
1858 fn variable_assignment_with_lambda_and_call() {
1859 let heap = Rc::new(RefCell::new(Heap::new()));
1860 let bindings = Rc::new(RefCell::new(HashMap::new()));
1861 let _ = parse_and_evaluate(
1862 "f = x => x + 1",
1863 Some(Rc::clone(&heap)),
1864 Some(Rc::clone(&bindings)),
1865 )
1866 .unwrap();
1867 let result =
1868 parse_and_evaluate("f(5)", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings))).unwrap();
1869
1870 assert_eq!(result, Value::Number(6.0));
1871 }
1872
1873 #[test]
1874 fn variable_assignment_with_lambda_and_call_with_multiple_args() {
1875 let heap = Rc::new(RefCell::new(Heap::new()));
1876 let bindings = Rc::new(RefCell::new(HashMap::new()));
1877 let _ = parse_and_evaluate(
1878 "f = (x, y) => x + y",
1879 Some(Rc::clone(&heap)),
1880 Some(Rc::clone(&bindings)),
1881 )
1882 .unwrap();
1883 let result = parse_and_evaluate(
1884 "f(5, 2)",
1885 Some(Rc::clone(&heap)),
1886 Some(Rc::clone(&bindings)),
1887 )
1888 .unwrap();
1889
1890 assert_eq!(result, Value::Number(7.0));
1891 }
1892
1893 #[test]
1894 fn variable_assignment_with_lambda_and_call_with_multiple_args_and_expression() {
1895 let heap = Rc::new(RefCell::new(Heap::new()));
1896 let bindings = Rc::new(RefCell::new(HashMap::new()));
1897 let _ = parse_and_evaluate(
1898 "f = (x, y) => x + y",
1899 Some(Rc::clone(&heap)),
1900 Some(Rc::clone(&bindings)),
1901 )
1902 .unwrap();
1903 let result = parse_and_evaluate(
1904 "f(5, 2) + 3",
1905 Some(Rc::clone(&heap)),
1906 Some(Rc::clone(&bindings)),
1907 )
1908 .unwrap();
1909
1910 assert_eq!(result, Value::Number(10.0));
1911 }
1912
1913 #[test]
1914 fn coalesce_operator_with_null() {
1915 let result = parse_and_evaluate("null ?? 5", None, None).unwrap();
1916 assert_eq!(result, Value::Number(5.0));
1917 }
1918
1919 #[test]
1920 fn coalesce_operator_with_non_null() {
1921 let result = parse_and_evaluate("3 ?? 10", None, None).unwrap();
1922 assert_eq!(result, Value::Number(3.0));
1923 }
1924
1925 #[test]
1927 fn list_elementwise_addition() {
1928 let heap = Rc::new(RefCell::new(Heap::new()));
1929 let result =
1930 parse_and_evaluate("[1, 2, 3] + [4, 5, 6]", Some(Rc::clone(&heap)), None).unwrap();
1931 let expected = vec![Value::Number(5.0), Value::Number(7.0), Value::Number(9.0)];
1932 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
1933 }
1934
1935 #[test]
1936 fn list_elementwise_subtraction() {
1937 let heap = Rc::new(RefCell::new(Heap::new()));
1938 let result =
1939 parse_and_evaluate("[5, 7, 9] - [1, 2, 3]", Some(Rc::clone(&heap)), None).unwrap();
1940 let expected = vec![Value::Number(4.0), Value::Number(5.0), Value::Number(6.0)];
1941 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
1942 }
1943
1944 #[test]
1945 fn list_elementwise_multiplication() {
1946 let heap = Rc::new(RefCell::new(Heap::new()));
1947 let result =
1948 parse_and_evaluate("[2, 3, 4] * [5, 6, 7]", Some(Rc::clone(&heap)), None).unwrap();
1949 let expected = vec![
1950 Value::Number(10.0),
1951 Value::Number(18.0),
1952 Value::Number(28.0),
1953 ];
1954 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
1955 }
1956
1957 #[test]
1958 fn list_elementwise_division() {
1959 let heap = Rc::new(RefCell::new(Heap::new()));
1960 let result =
1961 parse_and_evaluate("[10, 20, 30] / [2, 4, 5]", Some(Rc::clone(&heap)), None).unwrap();
1962 let expected = vec![Value::Number(5.0), Value::Number(5.0), Value::Number(6.0)];
1963 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
1964 }
1965
1966 #[test]
1967 fn list_elementwise_power() {
1968 let heap = Rc::new(RefCell::new(Heap::new()));
1969 let result =
1970 parse_and_evaluate("[2, 3, 4] ^ [2, 2, 2]", Some(Rc::clone(&heap)), None).unwrap();
1971 let expected = vec![Value::Number(4.0), Value::Number(9.0), Value::Number(16.0)];
1972 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
1973 }
1974
1975 #[test]
1976 fn list_elementwise_modulo() {
1977 let heap = Rc::new(RefCell::new(Heap::new()));
1978 let result =
1979 parse_and_evaluate("[10, 11, 12] % [3, 3, 3]", Some(Rc::clone(&heap)), None).unwrap();
1980 let expected = vec![Value::Number(1.0), Value::Number(2.0), Value::Number(0.0)];
1981 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
1982 }
1983
1984 #[test]
1985 fn list_elementwise_different_lengths_error() {
1986 let result = parse_and_evaluate("[1, 2, 3] + [4, 5]", None, None);
1987 assert!(result.is_err());
1988 assert!(
1989 result
1990 .unwrap_err()
1991 .to_string()
1992 .contains("left- and right-hand-side lists must be the same length")
1993 );
1994 }
1995
1996 #[test]
1998 fn list_scalar_addition() {
1999 let heap = Rc::new(RefCell::new(Heap::new()));
2000 let result = parse_and_evaluate("[1, 2, 3] + 10", Some(Rc::clone(&heap)), None).unwrap();
2001 let expected = vec![
2002 Value::Number(11.0),
2003 Value::Number(12.0),
2004 Value::Number(13.0),
2005 ];
2006 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2007 }
2008
2009 #[test]
2010 fn list_scalar_subtraction() {
2011 let heap = Rc::new(RefCell::new(Heap::new()));
2012 let result = parse_and_evaluate("[10, 20, 30] - 5", Some(Rc::clone(&heap)), None).unwrap();
2013 let expected = vec![Value::Number(5.0), Value::Number(15.0), Value::Number(25.0)];
2014 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2015 }
2016
2017 #[test]
2018 fn list_scalar_multiplication() {
2019 let heap = Rc::new(RefCell::new(Heap::new()));
2020 let result = parse_and_evaluate("[2, 3, 4] * 2", Some(Rc::clone(&heap)), None).unwrap();
2021 let expected = vec![Value::Number(4.0), Value::Number(6.0), Value::Number(8.0)];
2022 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2023 }
2024
2025 #[test]
2026 fn list_scalar_division() {
2027 let heap = Rc::new(RefCell::new(Heap::new()));
2028 let result = parse_and_evaluate("[10, 20, 30] / 10", Some(Rc::clone(&heap)), None).unwrap();
2029 let expected = vec![Value::Number(1.0), Value::Number(2.0), Value::Number(3.0)];
2030 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2031 }
2032
2033 #[test]
2034 fn list_scalar_power() {
2035 let heap = Rc::new(RefCell::new(Heap::new()));
2036 let result = parse_and_evaluate("[2, 3, 4] ^ 2", Some(Rc::clone(&heap)), None).unwrap();
2037 let expected = vec![Value::Number(4.0), Value::Number(9.0), Value::Number(16.0)];
2038 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2039 }
2040
2041 #[test]
2042 fn list_scalar_modulo() {
2043 let heap = Rc::new(RefCell::new(Heap::new()));
2044 let result = parse_and_evaluate("[10, 11, 12] % 3", Some(Rc::clone(&heap)), None).unwrap();
2045 let expected = vec![Value::Number(1.0), Value::Number(2.0), Value::Number(0.0)];
2046 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2047 }
2048
2049 #[test]
2050 fn list_with_operator() {
2051 let heap = Rc::new(RefCell::new(Heap::new()));
2052 let result =
2053 parse_and_evaluate("[1, 2, 3] |> (x => x * x)", Some(Rc::clone(&heap)), None).unwrap();
2054 let expected = vec![Value::Number(1.0), Value::Number(4.0), Value::Number(9.0)];
2055 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2056 }
2057
2058 #[test]
2059 fn list_with_builtin_function() {
2060 let heap = Rc::new(RefCell::new(Heap::new()));
2061 let result =
2062 parse_and_evaluate("[4, 9, 16] |> sqrt", Some(Rc::clone(&heap)), None).unwrap();
2063 let expected = vec![Value::Number(2.0), Value::Number(3.0), Value::Number(4.0)];
2064 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2065 }
2066
2067 #[test]
2068 fn list_elementwise_boolean_and() {
2069 let heap = Rc::new(RefCell::new(Heap::new()));
2070 let result = parse_and_evaluate(
2071 "[true, true, false] && [true, false, true]",
2072 Some(Rc::clone(&heap)),
2073 None,
2074 )
2075 .unwrap();
2076 let expected = vec![Value::Bool(true), Value::Bool(false), Value::Bool(false)];
2077 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2078 }
2079
2080 #[test]
2081 fn list_elementwise_boolean_or() {
2082 let heap = Rc::new(RefCell::new(Heap::new()));
2083 let result = parse_and_evaluate(
2084 "[true, false, false] || [false, true, false]",
2085 Some(Rc::clone(&heap)),
2086 None,
2087 )
2088 .unwrap();
2089 let expected = vec![Value::Bool(true), Value::Bool(true), Value::Bool(false)];
2090 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2091 }
2092
2093 #[test]
2094 fn list_elementwise_coalesce() {
2095 let heap = Rc::new(RefCell::new(Heap::new()));
2096 let result = parse_and_evaluate(
2097 "[null, 2, null] ?? [1, null, 3]",
2098 Some(Rc::clone(&heap)),
2099 None,
2100 )
2101 .unwrap();
2102 let expected = vec![Value::Number(1.0), Value::Number(2.0), Value::Number(3.0)];
2103 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2104 }
2105
2106 #[test]
2107 fn list_scalar_coalesce() {
2108 let heap = Rc::new(RefCell::new(Heap::new()));
2109 let result =
2110 parse_and_evaluate("[null, 2, null] ?? 5", Some(Rc::clone(&heap)), None).unwrap();
2111 let expected = vec![Value::Number(5.0), Value::Number(2.0), Value::Number(5.0)];
2112 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2113 }
2114
2115 #[test]
2116 fn list_elementwise_string_concat() {
2117 let heap = Rc::new(RefCell::new(Heap::new()));
2118 let result = parse_and_evaluate(
2119 "[\"a\", \"b\", \"c\"] + [\"1\", \"2\", \"3\"]",
2120 Some(Rc::clone(&heap)),
2121 None,
2122 )
2123 .unwrap();
2124 let borrowed_heap = heap.borrow();
2125 let result_list = result.as_list(&borrowed_heap).unwrap();
2126 assert_eq!(result_list.len(), 3);
2127 assert_eq!(result_list[0].as_string(&borrowed_heap).unwrap(), "a1");
2128 assert_eq!(result_list[1].as_string(&borrowed_heap).unwrap(), "b2");
2129 assert_eq!(result_list[2].as_string(&borrowed_heap).unwrap(), "c3");
2130 }
2131
2132 #[test]
2133 fn list_scalar_string_concat() {
2134 let heap = Rc::new(RefCell::new(Heap::new()));
2135 let result = parse_and_evaluate(
2136 "[\"a\", \"b\", \"c\"] + \"!\"",
2137 Some(Rc::clone(&heap)),
2138 None,
2139 )
2140 .unwrap();
2141 let borrowed_heap = heap.borrow();
2142 let result_list = result.as_list(&borrowed_heap).unwrap();
2143 assert_eq!(result_list.len(), 3);
2144 assert_eq!(result_list[0].as_string(&borrowed_heap).unwrap(), "a!");
2145 assert_eq!(result_list[1].as_string(&borrowed_heap).unwrap(), "b!");
2146 assert_eq!(result_list[2].as_string(&borrowed_heap).unwrap(), "c!");
2147 }
2148
2149 #[test]
2150 fn nested_list_operations() {
2151 let heap = Rc::new(RefCell::new(Heap::new()));
2152 let result =
2153 parse_and_evaluate("([1, 2, 3] + [4, 5, 6]) * 2", Some(Rc::clone(&heap)), None)
2154 .unwrap();
2155 let expected = vec![
2156 Value::Number(10.0),
2157 Value::Number(14.0),
2158 Value::Number(18.0),
2159 ];
2160 assert_eq!(result.as_list(&heap.borrow()).unwrap(), &expected);
2161 }
2162
2163 #[test]
2164 fn list_comparison_all_equal() {
2165 let result = parse_and_evaluate("[1, 1, 1] == 1", None, None).unwrap();
2166 assert_eq!(result, Value::Bool(true));
2167 }
2168
2169 #[test]
2170 fn list_comparison_not_all_equal() {
2171 let result = parse_and_evaluate("[1, 2, 1] == 1", None, None).unwrap();
2172 assert_eq!(result, Value::Bool(false));
2173 }
2174
2175 #[test]
2176 fn list_comparison_all_less() {
2177 let result = parse_and_evaluate("[1, 2, 3] < 5", None, None).unwrap();
2178 assert_eq!(result, Value::Bool(true));
2179 }
2180
2181 #[test]
2182 fn list_comparison_not_all_less() {
2183 let result = parse_and_evaluate("[1, 6, 3] < 5", None, None).unwrap();
2184 assert_eq!(result, Value::Bool(false));
2185 }
2186
2187 #[test]
2188 fn not_operator_basic() {
2189 let result = parse_and_evaluate("not true", None, None).unwrap();
2190 assert_eq!(result, Value::Bool(false));
2191 }
2192
2193 #[test]
2194 fn not_operator_with_false() {
2195 let result = parse_and_evaluate("not false", None, None).unwrap();
2196 assert_eq!(result, Value::Bool(true));
2197 }
2198
2199 #[test]
2200 fn not_operator_with_expression() {
2201 let result = parse_and_evaluate("not (5 > 10)", None, None).unwrap();
2202 assert_eq!(result, Value::Bool(true));
2203 }
2204
2205 #[test]
2206 fn not_operator_double_negation() {
2207 let result = parse_and_evaluate("not not true", None, None).unwrap();
2208 assert_eq!(result, Value::Bool(true));
2209 }
2210
2211 #[test]
2212 fn not_operator_with_and() {
2213 let result = parse_and_evaluate("not (true and false)", None, None).unwrap();
2214 assert_eq!(result, Value::Bool(true));
2215 }
2216
2217 #[test]
2218 fn not_operator_with_or() {
2219 let result = parse_and_evaluate("not (false or false)", None, None).unwrap();
2220 assert_eq!(result, Value::Bool(true));
2221 }
2222
2223 #[test]
2224 fn not_operator_precedence() {
2225 let result = parse_and_evaluate("not true and false", None, None).unwrap();
2226 assert_eq!(result, Value::Bool(false));
2227 }
2228
2229 #[test]
2230 fn not_operator_comparison_with_invert() {
2231 let not_result = parse_and_evaluate("not true", None, None).unwrap();
2232 let invert_result = parse_and_evaluate("!true", None, None).unwrap();
2233 assert_eq!(not_result, invert_result);
2234 }
2235
2236 #[test]
2237 fn variable_immutability_prevents_reassignment() {
2238 let heap = Rc::new(RefCell::new(Heap::new()));
2239 let bindings = Rc::new(RefCell::new(HashMap::new()));
2240
2241 let result1 =
2243 parse_and_evaluate("x = 5", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2244 assert!(result1.is_ok());
2245 assert_eq!(result1.unwrap(), Value::Number(5.0));
2246
2247 let result2 =
2249 parse_and_evaluate("x = 10", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2250 assert!(result2.is_err());
2251 assert!(
2252 result2
2253 .unwrap_err()
2254 .to_string()
2255 .contains("x is already defined, and cannot be reassigned")
2256 );
2257
2258 let result3 = parse_and_evaluate("x", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2260 assert!(result3.is_ok());
2261 assert_eq!(result3.unwrap(), Value::Number(5.0));
2262 }
2263
2264 #[test]
2265 fn variable_immutability_allows_shadowing_in_nested_scopes() {
2266 let heap = Rc::new(RefCell::new(Heap::new()));
2267 let bindings = Rc::new(RefCell::new(HashMap::new()));
2268
2269 let result1 =
2271 parse_and_evaluate("x = 5", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2272 assert!(result1.is_ok());
2273
2274 let result2 = parse_and_evaluate(
2276 "f = (x) => x * 2",
2277 Some(Rc::clone(&heap)),
2278 Some(Rc::clone(&bindings)),
2279 );
2280 assert!(result2.is_ok());
2281
2282 let result3 =
2284 parse_and_evaluate("f(10)", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2285 assert!(result3.is_ok());
2286 assert_eq!(result3.unwrap(), Value::Number(20.0));
2287
2288 let result4 = parse_and_evaluate("x", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2290 assert!(result4.is_ok());
2291 assert_eq!(result4.unwrap(), Value::Number(5.0));
2292 }
2293
2294 #[test]
2295 fn variable_immutability_in_do_blocks() {
2296 let heap = Rc::new(RefCell::new(Heap::new()));
2297 let bindings = Rc::new(RefCell::new(HashMap::new()));
2298
2299 let result1 =
2301 parse_and_evaluate("x = 5", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2302 assert!(result1.is_ok());
2303
2304 let do_block = r#"do {
2306 x = 10
2307 y = x * 2
2308 return y
2309 }"#;
2310 let result2 =
2311 parse_and_evaluate(do_block, Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2312 assert!(result2.is_ok());
2313 assert_eq!(result2.unwrap(), Value::Number(20.0)); let do_block2 = r#"do {
2317 z = x * 3
2318 return z
2319 }"#;
2320 let result3 = parse_and_evaluate(
2321 do_block2,
2322 Some(Rc::clone(&heap)),
2323 Some(Rc::clone(&bindings)),
2324 );
2325 assert!(result3.is_ok());
2326 assert_eq!(result3.unwrap(), Value::Number(15.0));
2327
2328 let result4 = parse_and_evaluate("x", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2330 assert!(result4.is_ok());
2331 assert_eq!(result4.unwrap(), Value::Number(5.0));
2332 }
2333
2334 #[test]
2335 fn variable_immutability_different_variables() {
2336 let heap = Rc::new(RefCell::new(Heap::new()));
2337 let bindings = Rc::new(RefCell::new(HashMap::new()));
2338
2339 let result1 =
2341 parse_and_evaluate("x = 5", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2342 assert!(result1.is_ok());
2343
2344 let result2 =
2345 parse_and_evaluate("y = 10", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)));
2346 assert!(result2.is_ok());
2347
2348 let result3 = parse_and_evaluate(
2349 "z = x + y",
2350 Some(Rc::clone(&heap)),
2351 Some(Rc::clone(&bindings)),
2352 );
2353 assert!(result3.is_ok());
2354 assert_eq!(result3.unwrap(), Value::Number(15.0));
2355 }
2356
2357 #[test]
2358 fn variable_immutability_with_complex_types() {
2359 let heap = Rc::new(RefCell::new(Heap::new()));
2360 let bindings = Rc::new(RefCell::new(HashMap::new()));
2361
2362 let result1 = parse_and_evaluate(
2364 "list = [1, 2, 3]",
2365 Some(Rc::clone(&heap)),
2366 Some(Rc::clone(&bindings)),
2367 );
2368 assert!(result1.is_ok());
2369
2370 let result2 = parse_and_evaluate(
2372 "list = [4, 5, 6]",
2373 Some(Rc::clone(&heap)),
2374 Some(Rc::clone(&bindings)),
2375 );
2376 assert!(result2.is_err());
2377 assert!(
2378 result2
2379 .unwrap_err()
2380 .to_string()
2381 .contains("list is already defined, and cannot be reassigned")
2382 );
2383
2384 let result3 = parse_and_evaluate(
2386 "rec = {x: 1, y: 2}",
2387 Some(Rc::clone(&heap)),
2388 Some(Rc::clone(&bindings)),
2389 );
2390 assert!(result3.is_ok());
2391
2392 let result4 = parse_and_evaluate(
2394 "rec = {x: 3, y: 4}",
2395 Some(Rc::clone(&heap)),
2396 Some(Rc::clone(&bindings)),
2397 );
2398 assert!(result4.is_err());
2399 assert!(
2400 result4
2401 .unwrap_err()
2402 .to_string()
2403 .contains("rec is already defined, and cannot be reassigned")
2404 );
2405 }
2406
2407 #[test]
2408 fn equality_comparison_numbers() {
2409 let result = parse_and_evaluate("5e2 == 5e2", None, None).unwrap();
2410 assert_eq!(result, Value::Bool(true));
2411
2412 let result = parse_and_evaluate("42 == 42", None, None).unwrap();
2413 assert_eq!(result, Value::Bool(true));
2414
2415 let result = parse_and_evaluate("42 == 43", None, None).unwrap();
2416 assert_eq!(result, Value::Bool(false));
2417 }
2418
2419 #[test]
2420 fn equality_comparison_strings() {
2421 let result = parse_and_evaluate(r#""hey" == "hey""#, None, None).unwrap();
2422 assert_eq!(result, Value::Bool(true));
2423
2424 let result = parse_and_evaluate(r#""hello" == "world""#, None, None).unwrap();
2425 assert_eq!(result, Value::Bool(false));
2426
2427 let result = parse_and_evaluate(r#""" == """#, None, None).unwrap();
2428 assert_eq!(result, Value::Bool(true));
2429 }
2430
2431 #[test]
2432 fn equality_comparison_lists() {
2433 let result = parse_and_evaluate("[1,2,3] == [1,2,3]", None, None).unwrap();
2434 assert_eq!(result, Value::Bool(true));
2435
2436 let result = parse_and_evaluate("[1,2,3] == [1,2,4]", None, None).unwrap();
2437 assert_eq!(result, Value::Bool(false));
2438
2439 let result = parse_and_evaluate(r#"["a", "b"] == ["a", "b"]"#, None, None).unwrap();
2444 assert_eq!(result, Value::Bool(true));
2445
2446 let result = parse_and_evaluate("[[1,2,3]] == [[1,2,3]]", None, None).unwrap();
2448 assert_eq!(result, Value::Bool(true));
2449
2450 let result =
2451 parse_and_evaluate("[[1,2,3], [4,5]] == [[1,2,3], [4,5]]", None, None).unwrap();
2452 assert_eq!(result, Value::Bool(true));
2453 }
2454
2455 #[test]
2456 fn equality_comparison_records() {
2457 let result = parse_and_evaluate("{ hey: 1 } == { hey: 1 }", None, None).unwrap();
2458 assert_eq!(result, Value::Bool(true));
2459
2460 let result = parse_and_evaluate("{ hey: 1 } == { hey: 2 }", None, None).unwrap();
2461 assert_eq!(result, Value::Bool(false));
2462
2463 let result = parse_and_evaluate("{ hey: 1 } == { hello: 1 }", None, None).unwrap();
2464 assert_eq!(result, Value::Bool(false));
2465
2466 let result = parse_and_evaluate("{ a: 1, b: 2 } == { a: 1, b: 2 }", None, None).unwrap();
2468 assert_eq!(result, Value::Bool(true));
2469
2470 let result = parse_and_evaluate("{ a: 1, b: 2 } == { b: 2, a: 1 }", None, None).unwrap();
2472 assert_eq!(result, Value::Bool(true));
2473
2474 let result = parse_and_evaluate("{ x: { y: 1 } } == { x: { y: 1 } }", None, None).unwrap();
2476 assert_eq!(result, Value::Bool(true));
2477 }
2478
2479 #[test]
2480 fn equality_comparison_lambdas() {
2481 let heap = Rc::new(RefCell::new(Heap::new()));
2482 let bindings = Rc::new(RefCell::new(HashMap::new()));
2483
2484 parse_and_evaluate(
2486 "f1 = (x) => x + 2",
2487 Some(Rc::clone(&heap)),
2488 Some(Rc::clone(&bindings)),
2489 )
2490 .unwrap();
2491 parse_and_evaluate(
2492 "f2 = (x) => x + 2",
2493 Some(Rc::clone(&heap)),
2494 Some(Rc::clone(&bindings)),
2495 )
2496 .unwrap();
2497 let result = parse_and_evaluate(
2498 "f1 == f2",
2499 Some(Rc::clone(&heap)),
2500 Some(Rc::clone(&bindings)),
2501 )
2502 .unwrap();
2503 assert_eq!(result, Value::Bool(true));
2504
2505 let result = parse_and_evaluate(
2507 "f1 == f1",
2508 Some(Rc::clone(&heap)),
2509 Some(Rc::clone(&bindings)),
2510 )
2511 .unwrap();
2512 assert_eq!(result, Value::Bool(true));
2513
2514 parse_and_evaluate(
2516 "f3 = f1",
2517 Some(Rc::clone(&heap)),
2518 Some(Rc::clone(&bindings)),
2519 )
2520 .unwrap();
2521 let result = parse_and_evaluate(
2522 "f1 == f3",
2523 Some(Rc::clone(&heap)),
2524 Some(Rc::clone(&bindings)),
2525 )
2526 .unwrap();
2527 assert_eq!(result, Value::Bool(true));
2528
2529 parse_and_evaluate(
2531 "f4 = (x) => x + 3",
2532 Some(Rc::clone(&heap)),
2533 Some(Rc::clone(&bindings)),
2534 )
2535 .unwrap();
2536 let result = parse_and_evaluate(
2537 "f1 == f4",
2538 Some(Rc::clone(&heap)),
2539 Some(Rc::clone(&bindings)),
2540 )
2541 .unwrap();
2542 assert_eq!(result, Value::Bool(false));
2543
2544 parse_and_evaluate(
2546 "f5 = (y) => y + 2",
2547 Some(Rc::clone(&heap)),
2548 Some(Rc::clone(&bindings)),
2549 )
2550 .unwrap();
2551 let result = parse_and_evaluate(
2552 "f1 == f5",
2553 Some(Rc::clone(&heap)),
2554 Some(Rc::clone(&bindings)),
2555 )
2556 .unwrap();
2557 assert_eq!(result, Value::Bool(false));
2558
2559 parse_and_evaluate(
2561 "f6 = (x, y) => x + y",
2562 Some(Rc::clone(&heap)),
2563 Some(Rc::clone(&bindings)),
2564 )
2565 .unwrap();
2566 let result = parse_and_evaluate(
2567 "f1 == f6",
2568 Some(Rc::clone(&heap)),
2569 Some(Rc::clone(&bindings)),
2570 )
2571 .unwrap();
2572 assert_eq!(result, Value::Bool(false));
2573 }
2574
2575 #[test]
2576 fn equality_comparison_mixed_types() {
2577 let result = parse_and_evaluate("1 == \"1\"", None, None).unwrap();
2579 assert_eq!(result, Value::Bool(false));
2580
2581 let result = parse_and_evaluate("true == 1", None, None).unwrap();
2582 assert_eq!(result, Value::Bool(false));
2583
2584 let result = parse_and_evaluate("[1] == 1", None, None).unwrap();
2586 assert_eq!(result, Value::Bool(true));
2587
2588 let result = parse_and_evaluate("null == 0", None, None).unwrap();
2589 assert_eq!(result, Value::Bool(false));
2590 }
2591
2592 #[test]
2593 fn comparison_operators_strings() {
2594 let result = parse_and_evaluate(r#""apple" < "banana""#, None, None).unwrap();
2596 assert_eq!(result, Value::Bool(true));
2597
2598 let result = parse_and_evaluate(r#""zebra" > "apple""#, None, None).unwrap();
2599 assert_eq!(result, Value::Bool(true));
2600
2601 let result = parse_and_evaluate(r#""hello" <= "hello""#, None, None).unwrap();
2602 assert_eq!(result, Value::Bool(true));
2603 }
2604
2605 #[test]
2606 fn comparison_operators_lists() {
2607 let result = parse_and_evaluate("[1, 2] < [2, 3]", None, None).unwrap();
2610 assert_eq!(result, Value::Bool(true));
2611
2612 let result = parse_and_evaluate("[1, 2] < [1, 3]", None, None).unwrap();
2614 assert_eq!(result, Value::Bool(false));
2615
2616 let result = parse_and_evaluate("[2, 1] > [1, 0]", None, None).unwrap();
2618 assert_eq!(result, Value::Bool(true));
2619 }
2620
2621 #[test]
2622 fn late_binding_unbound_variable_succeeds() {
2623 let heap = Rc::new(RefCell::new(Heap::new()));
2625 let bindings = Rc::new(RefCell::new(HashMap::new()));
2626 let result = parse_and_evaluate("f = x => x + y", Some(heap), Some(bindings));
2627 assert!(result.is_ok());
2629 }
2630
2631 #[test]
2632 fn early_binding_bound_variable_succeeds() {
2633 let heap = Rc::new(RefCell::new(Heap::new()));
2635 let bindings = Rc::new(RefCell::new(HashMap::new()));
2636
2637 let _ = parse_and_evaluate("y = 5", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)))
2639 .unwrap();
2640
2641 let result = parse_and_evaluate(
2643 "g = x => x + y",
2644 Some(Rc::clone(&heap)),
2645 Some(Rc::clone(&bindings)),
2646 );
2647 assert!(result.is_ok());
2648
2649 let call_result = parse_and_evaluate("g(2)", Some(heap), Some(bindings)).unwrap();
2651 assert_eq!(call_result, Value::Number(7.0));
2652 }
2653
2654 #[test]
2655 fn early_binding_builtin_function_succeeds() {
2656 let heap = Rc::new(RefCell::new(Heap::new()));
2658 let bindings = Rc::new(RefCell::new(HashMap::new()));
2659 let result = parse_and_evaluate(
2660 "h = x => sin(x)",
2661 Some(Rc::clone(&heap)),
2662 Some(Rc::clone(&bindings)),
2663 );
2664 assert!(result.is_ok());
2665
2666 let call_result = parse_and_evaluate("h(0)", Some(heap), Some(bindings)).unwrap();
2668 assert_eq!(call_result, Value::Number(0.0));
2669 }
2670
2671 #[test]
2672 fn late_binding_nested_function_succeeds() {
2673 let heap = Rc::new(RefCell::new(Heap::new()));
2675 let bindings = Rc::new(RefCell::new(HashMap::new()));
2676
2677 let result = parse_and_evaluate(
2679 "outer = x => do { inner = y => y + z; return inner(x) }",
2680 Some(Rc::clone(&heap)),
2681 Some(Rc::clone(&bindings)),
2682 );
2683 assert!(result.is_ok());
2684
2685 let _ = parse_and_evaluate(
2687 "z = 100",
2688 Some(Rc::clone(&heap)),
2689 Some(Rc::clone(&bindings)),
2690 )
2691 .unwrap();
2692
2693 let call_result = parse_and_evaluate("outer(5)", Some(heap), Some(bindings)).unwrap();
2695 assert_eq!(call_result, Value::Number(105.0));
2696 }
2697
2698 #[test]
2699 fn early_binding_all_variables_bound() {
2700 let heap = Rc::new(RefCell::new(Heap::new()));
2702 let bindings = Rc::new(RefCell::new(HashMap::new()));
2703
2704 let _ = parse_and_evaluate("a = 10", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)))
2706 .unwrap();
2707 let _ = parse_and_evaluate("b = 20", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)))
2708 .unwrap();
2709
2710 let result = parse_and_evaluate(
2712 "func = x => (x + a) * b",
2713 Some(Rc::clone(&heap)),
2714 Some(Rc::clone(&bindings)),
2715 );
2716 assert!(result.is_ok());
2717
2718 let call_result = parse_and_evaluate("func(5)", Some(heap), Some(bindings)).unwrap();
2720 assert_eq!(call_result, Value::Number(300.0));
2721 }
2722
2723 #[test]
2724 fn early_binding_parameter_shadows_outer() {
2725 let heap = Rc::new(RefCell::new(Heap::new()));
2727 let bindings = Rc::new(RefCell::new(HashMap::new()));
2728
2729 let _ = parse_and_evaluate(
2731 "x = 100",
2732 Some(Rc::clone(&heap)),
2733 Some(Rc::clone(&bindings)),
2734 )
2735 .unwrap();
2736
2737 let result = parse_and_evaluate(
2739 "shadow = x => x * 2",
2740 Some(Rc::clone(&heap)),
2741 Some(Rc::clone(&bindings)),
2742 );
2743 assert!(result.is_ok());
2744
2745 let call_result = parse_and_evaluate("shadow(5)", Some(heap), Some(bindings)).unwrap();
2747 assert_eq!(call_result, Value::Number(10.0));
2748 }
2749
2750 #[test]
2751 fn early_binding_do_block_internal_binding() {
2752 let heap = Rc::new(RefCell::new(Heap::new()));
2754 let bindings = Rc::new(RefCell::new(HashMap::new()));
2755
2756 let result = parse_and_evaluate(
2758 "f = x => do { y = 5; return x + y }",
2759 Some(Rc::clone(&heap)),
2760 Some(Rc::clone(&bindings)),
2761 );
2762 assert!(result.is_ok());
2763
2764 let call_result = parse_and_evaluate("f(10)", Some(heap), Some(bindings)).unwrap();
2766 assert_eq!(call_result, Value::Number(15.0));
2767 }
2768
2769 #[test]
2770 fn early_binding_do_block_nested_scope() {
2771 let heap = Rc::new(RefCell::new(Heap::new()));
2773 let bindings = Rc::new(RefCell::new(HashMap::new()));
2774
2775 let result = parse_and_evaluate(
2776 "later_func = do { c = 30; f = x => x + c; return f(10) }",
2777 Some(Rc::clone(&heap)),
2778 Some(Rc::clone(&bindings)),
2779 );
2780 assert!(result.is_ok());
2781
2782 let later_func_result =
2784 parse_and_evaluate("later_func", Some(heap), Some(bindings)).unwrap();
2785 assert_eq!(later_func_result, Value::Number(40.0));
2786 }
2787
2788 #[test]
2789 fn late_binding_do_block_forward_reference_succeeds() {
2790 let heap = Rc::new(RefCell::new(Heap::new()));
2792 let bindings = Rc::new(RefCell::new(HashMap::new()));
2793
2794 let result = parse_and_evaluate(
2795 "g = x => do { f = y => y + z; z = 10; return f(x) }",
2796 Some(Rc::clone(&heap)),
2797 Some(Rc::clone(&bindings)),
2798 );
2799 assert!(result.is_ok());
2800
2801 let call_result = parse_and_evaluate("g(5)", Some(heap), Some(bindings)).unwrap();
2803 assert_eq!(call_result, Value::Number(15.0));
2804 }
2805
2806 #[test]
2807 fn early_binding_do_block_multiple_assignments() {
2808 let heap = Rc::new(RefCell::new(Heap::new()));
2810 let bindings = Rc::new(RefCell::new(HashMap::new()));
2811
2812 let result = parse_and_evaluate(
2813 "calc = x => do { a = 2; b = 3; c = 4; return x * a + b * c }",
2814 Some(Rc::clone(&heap)),
2815 Some(Rc::clone(&bindings)),
2816 );
2817 assert!(result.is_ok());
2818
2819 let call_result = parse_and_evaluate("calc(5)", Some(heap), Some(bindings)).unwrap();
2821 assert_eq!(call_result, Value::Number(22.0));
2822 }
2823
2824 #[test]
2825 fn late_binding_multiple_unbound_variables_succeeds() {
2826 let heap = Rc::new(RefCell::new(Heap::new()));
2828 let bindings = Rc::new(RefCell::new(HashMap::new()));
2829
2830 let result = parse_and_evaluate(
2831 "f = x => x + y + z",
2832 Some(Rc::clone(&heap)),
2833 Some(Rc::clone(&bindings)),
2834 );
2835 assert!(result.is_ok());
2836
2837 let _ = parse_and_evaluate("y = 10", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)))
2839 .unwrap();
2840 let _ = parse_and_evaluate("z = 20", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)))
2841 .unwrap();
2842
2843 let call_result = parse_and_evaluate("f(5)", Some(heap), Some(bindings)).unwrap();
2845 assert_eq!(call_result, Value::Number(35.0));
2846 }
2847
2848 #[test]
2849 fn late_binding_with_optional_args_succeeds() {
2850 let heap = Rc::new(RefCell::new(Heap::new()));
2852 let bindings = Rc::new(RefCell::new(HashMap::new()));
2853
2854 let result = parse_and_evaluate(
2855 "f = (x, y?) => x + z",
2856 Some(Rc::clone(&heap)),
2857 Some(Rc::clone(&bindings)),
2858 );
2859 assert!(result.is_ok());
2860
2861 let _ = parse_and_evaluate(
2863 "z = 100",
2864 Some(Rc::clone(&heap)),
2865 Some(Rc::clone(&bindings)),
2866 )
2867 .unwrap();
2868
2869 let call_result = parse_and_evaluate("f(5)", Some(heap), Some(bindings)).unwrap();
2871 assert_eq!(call_result, Value::Number(105.0));
2872 }
2873
2874 #[test]
2875 fn late_binding_with_rest_args_succeeds() {
2876 let heap = Rc::new(RefCell::new(Heap::new()));
2878 let bindings = Rc::new(RefCell::new(HashMap::new()));
2879
2880 let result = parse_and_evaluate(
2881 "f = (x, ...rest) => x + y",
2882 Some(Rc::clone(&heap)),
2883 Some(Rc::clone(&bindings)),
2884 );
2885 assert!(result.is_ok());
2886
2887 let _ = parse_and_evaluate("y = 50", Some(Rc::clone(&heap)), Some(Rc::clone(&bindings)))
2889 .unwrap();
2890
2891 let call_result = parse_and_evaluate("f(5)", Some(heap), Some(bindings)).unwrap();
2893 assert_eq!(call_result, Value::Number(55.0));
2894 }
2895
2896 #[test]
2897 fn recursion_self_reference_allowed() {
2898 let heap = Rc::new(RefCell::new(Heap::new()));
2900 let bindings = Rc::new(RefCell::new(HashMap::new()));
2901
2902 let result = parse_and_evaluate(
2904 "factorial = n => if n <= 1 then 1 else n * factorial(n - 1)",
2905 Some(Rc::clone(&heap)),
2906 Some(Rc::clone(&bindings)),
2907 );
2908 assert!(result.is_ok());
2909
2910 let call_result = parse_and_evaluate("factorial(5)", Some(heap), Some(bindings)).unwrap();
2912 assert_eq!(call_result, Value::Number(120.0));
2913 }
2914
2915 #[test]
2916 fn recursion_fibonacci() {
2917 let heap = Rc::new(RefCell::new(Heap::new()));
2919 let bindings = Rc::new(RefCell::new(HashMap::new()));
2920
2921 let result = parse_and_evaluate(
2923 "fib = n => if n <= 1 then n else fib(n - 1) + fib(n - 2)",
2924 Some(Rc::clone(&heap)),
2925 Some(Rc::clone(&bindings)),
2926 );
2927 assert!(result.is_ok());
2928
2929 let call_result = parse_and_evaluate("fib(6)", Some(heap), Some(bindings)).unwrap();
2931 assert_eq!(call_result, Value::Number(8.0));
2932 }
2933
2934 #[test]
2935 fn recursion_in_do_block() {
2936 let heap = Rc::new(RefCell::new(Heap::new()));
2938 let bindings = Rc::new(RefCell::new(HashMap::new()));
2939
2940 let result = parse_and_evaluate(
2941 "result = do { factorial = n => if n <= 1 then 1 else n * factorial(n - 1); return factorial(4) }",
2942 Some(Rc::clone(&heap)),
2943 Some(Rc::clone(&bindings)),
2944 );
2945 assert!(result.is_ok());
2946
2947 let result_val = parse_and_evaluate("result", Some(heap), Some(bindings)).unwrap();
2949 assert_eq!(result_val, Value::Number(24.0));
2950 }
2951
2952 #[test]
2953 fn mutual_recursion_succeeds() {
2954 let heap = Rc::new(RefCell::new(Heap::new()));
2956 let bindings = Rc::new(RefCell::new(HashMap::new()));
2957
2958 let result = parse_and_evaluate(
2960 "isEven = n => if n == 0 then true else isOdd(n - 1)",
2961 Some(Rc::clone(&heap)),
2962 Some(Rc::clone(&bindings)),
2963 );
2964 assert!(result.is_ok());
2965
2966 let _ = parse_and_evaluate(
2968 "isOdd = n => if n == 0 then false else isEven(n - 1)",
2969 Some(Rc::clone(&heap)),
2970 Some(Rc::clone(&bindings)),
2971 )
2972 .unwrap();
2973
2974 let result1 = parse_and_evaluate(
2976 "isEven(4)",
2977 Some(Rc::clone(&heap)),
2978 Some(Rc::clone(&bindings)),
2979 )
2980 .unwrap();
2981 assert_eq!(result1, Value::Bool(true));
2982
2983 let result2 = parse_and_evaluate(
2984 "isEven(5)",
2985 Some(Rc::clone(&heap)),
2986 Some(Rc::clone(&bindings)),
2987 )
2988 .unwrap();
2989 assert_eq!(result2, Value::Bool(false));
2990
2991 let result3 = parse_and_evaluate(
2992 "isOdd(3)",
2993 Some(Rc::clone(&heap)),
2994 Some(Rc::clone(&bindings)),
2995 )
2996 .unwrap();
2997 assert_eq!(result3, Value::Bool(true));
2998
2999 let result4 = parse_and_evaluate("isOdd(6)", Some(heap), Some(bindings)).unwrap();
3000 assert_eq!(result4, Value::Bool(false));
3001 }
3002
3003 #[test]
3004 fn recursion_only_for_lambdas() {
3005 let heap = Rc::new(RefCell::new(Heap::new()));
3007 let bindings = Rc::new(RefCell::new(HashMap::new()));
3008
3009 let result = parse_and_evaluate("y = x + 1", Some(heap), Some(bindings));
3011 assert!(result.is_err());
3012 }
3013}