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