1use std::rc::Rc;
44use crate::ast::Node;
45use crate::value::{Scope, Value, Undef, BuiltinFn};
46
47
48mod affirm_operation;
51mod negation_operation;
53mod logical_negation_operation;
55mod lifting_operation;
57
58mod pairing_operation;
61pub(crate) mod assignment_operation;
63mod then_operation;
65mod arithmetic_operations;
67mod comparison_operations;
69
70
71
72macro_rules! map_pairs {
89 ($lhv:expr, $rhv:expr, $eval_fn:expr) => {{
90 let (lhv, rhv) = ($lhv, $rhv);
91 if matches!(lhv, Value::Tuple(_)) || matches!(rhv, Value::Tuple(_)) {
92 Value::tuple(
93 lhv.pair(&rhv)
94 .map(|(l,r)| $eval_fn(l,r))
95 .collect(),
96 )
97 } else if lhv == Value::Nothing && rhv == Value::Nothing {
98 Value::Nothing
99 } else {
100 $eval_fn(lhv, rhv)
101 }
102 }};
103}
104
105macro_rules! map_values {
115 ($val:expr, $eval_fn:expr) => {{
116 let val = $val;
117 match val {
118 Value::Nothing => Value::Nothing,
119 Value::Tuple(_) => {
120 Value::tuple(
121 val.items()
122 .map($eval_fn)
123 .collect()
124 )
125 }
126 _ => $eval_fn(val)
127 }
128 }};
129}
130
131
132
133pub fn eval(node: &Node, scope: &Scope) -> Value {
174 match node {
175
176
177 Node::Numb(leaf) => Value::Numb(leaf.val),
181
182 Node::Text(leaf) => Value::Text(leaf.val.as_str().into()),
184
185 Node::Nothing(_) => Value::Nothing,
187
188 Node::Identifier(leaf) => scope.get(&leaf.val),
190
191
192
193 Node::List(unary) => {
197 let val = eval(&unary.opd, scope);
198 let vec: Vec<_> = val.items().collect();
199 Value::list(vec)
200 }
201
202 Node::Namespace(unary) => {
204 let child_scope = scope.new_child();
205 eval(&unary.opd, &child_scope);
206 Value::Namespace(child_scope)
207 }
208
209
210
211 Node::AffirmOp(unary) => {
216 let val = eval(&unary.opd, scope);
217 affirm_operation::eval(val)
218 }
219
220 Node::NegateOp(unary) => {
222 let val = eval(&unary.opd, scope);
223 map_values!(val, |v| negation_operation::eval(v, unary.pos))
224 }
225
226 Node::LogicalNegationOp(unary) => {
228 let val = eval(&unary.opd, scope);
229 map_values!(val, logical_negation_operation::eval)
230 }
231
232 Node::LiftingOp(unary) => {
234 let names = eval_names(&unary.opd);
235 map_values!(names, |n| lifting_operation::eval(n, scope, unary.pos))
236 }
237
238
239
240 Node::FunctionDefinitionOp(bin) => {
244 let names = eval_names(&bin.lho);
245 if matches!(names, Value::Undefined(_)) {
246 invalid_names("function_definition", names, bin.pos)
247 } else {
248 Value::Func{
249 params: Box::new(names),
250 body: bin.rho.clone(),
251 closure: scope.clone(),
252 }
253 }
254 }
255
256 Node::ApplicationOp(bin) => {
258 let func = eval(&bin.lho, scope);
263 let args = eval(&bin.rho, scope);
264 map_values!(func, |f| eval_apply(f, args.clone(), bin.pos))
265 }
266
267 Node::PairingOp(bin) => {
269 let lhv = eval(&bin.lho, scope);
270 let rhv = eval(&bin.rho, scope);
271 pairing_operation::eval(lhv, rhv)
272 }
273
274 Node::MappingOp(bin) => {
276 let args = eval(&bin.lho, scope);
277 let func = eval(&bin.rho, scope);
278 map_values!(args, |a: Value| map_values!(func.clone(), |f| eval_apply(f, a.clone(), bin.pos)))
279 }
280
281 Node::ThenOp(bin) => {
283 let promises = eval(&bin.lho, scope);
284 let func = eval(&bin.rho, scope);
285 map_values!(promises, |p| then_operation::eval(p, func.clone(), bin.pos))
286 }
287
288 Node::AssignmentOp(bin) => {
290 let names = eval_names(&bin.lho);
291 if matches!(names, Value::Undefined(_)) {
292 return invalid_names("assignment", names, bin.pos);
293 }
294
295 let values = eval(&bin.rho, scope);
296 assignment_operation::eval(scope, &names, &values);
297 Value::Nothing
298 }
299
300 Node::LabellingOp(bin) => {
302 let names = eval_names(&bin.lho);
303 if matches!(names, Value::Undefined(_)) {
304 return invalid_names("labelling", names, bin.pos);
305 }
306
307 let values = eval(&bin.rho, scope);
308 assignment_operation::eval(scope, &names, &values);
309 values
310 }
311
312 Node::SubcontextingOp(bin) => {
314 let nst = eval(&bin.lho, scope);
318 map_values!(nst, |ns| match ns {
319 Value::Namespace(ns_scope) => {
320 eval(&bin.rho, &ns_scope)
321 }
322 lhv => Value::undef_binary("subcontexting", lhv, Value::Nothing, bin.pos),
323 })
324 }
325
326
327
328 Node::SumOp(bin) => {
332 let lhv = eval(&bin.lho, scope);
333 let rhv = eval(&bin.rho, scope);
334 map_pairs!(lhv, rhv, |l,r| arithmetic_operations::eval_add(l, r, bin.pos))
335 }
336
337 Node::SubtractionOp(bin) => {
339 let lhv = eval(&bin.lho, scope);
340 let rhv = eval(&bin.rho, scope);
341 map_pairs!(lhv, rhv, |l,r| arithmetic_operations::eval_subtraction(l, r, bin.pos))
342 }
343
344 Node::ProductOp(bin) => {
346 let lhv = eval(&bin.lho, scope);
347 let rhv = eval(&bin.rho, scope);
348 map_pairs!(lhv, rhv, |l,r| arithmetic_operations::eval_product(l, r, bin.pos))
349 }
350
351 Node::DivisionOp(bin) => {
353 let lhv = eval(&bin.lho, scope);
354 let rhv = eval(&bin.rho, scope);
355 map_pairs!(lhv, rhv, |l,r| arithmetic_operations::eval_division(l, r, bin.pos))
356 }
357
358 Node::ModuloOp(bin) => {
360 let lhv = eval(&bin.lho, scope);
361 let rhv = eval(&bin.rho, scope);
362 map_pairs!(lhv, rhv, |l,r| arithmetic_operations::eval_modulo(l, r, bin.pos))
363 }
364
365 Node::PowerOp(bin) => {
367 let lhv = eval(&bin.lho, scope);
368 let rhv = eval(&bin.rho, scope);
369 map_pairs!(lhv, rhv, |l,r| arithmetic_operations::eval_power(l, r, bin.pos))
370 }
371
372
373
374 Node::EqualToOp(bin) => {
378 let lhv = eval(&bin.lho, scope);
379 let rhv = eval(&bin.rho, scope);
380 map_pairs!(lhv, rhv, |l,r| comparison_operations::eval_equal_to(l, r))
381 }
382
383 Node::NotEqualToOp(bin) => {
385 let lhv = eval(&bin.lho, scope);
386 let rhv = eval(&bin.rho, scope);
387 map_pairs!(lhv, rhv, |l,r| comparison_operations::eval_not_equal_to(l, r))
388 }
389
390 Node::GreaterThanOp(bin) => {
392 let lhv = eval(&bin.lho, scope);
393 let rhv = eval(&bin.rho, scope);
394 map_pairs!(lhv, rhv, |l,r| comparison_operations::eval_greater_than(l, r, bin.pos))
395 }
396
397 Node::GreaterThanOrEqualToOp(bin) => {
399 let lhv = eval(&bin.lho, scope);
400 let rhv = eval(&bin.rho, scope);
401 map_pairs!(lhv, rhv, |l,r| comparison_operations::eval_greater_than_or_equal_to(l, r, bin.pos))
402 }
403
404 Node::LessThanOp(bin) => {
406 let lhv = eval(&bin.lho, scope);
407 let rhv = eval(&bin.rho, scope);
408 map_pairs!(lhv, rhv, |l,r| comparison_operations::eval_less_than(l, r, bin.pos))
409 }
410
411 Node::LessThanOrEqualToOp(bin) => {
413 let lhv = eval(&bin.lho, scope);
414 let rhv = eval(&bin.rho, scope);
415 map_pairs!(lhv, rhv, |l,r| comparison_operations::eval_less_than_or_equal_to(l, r, bin.pos))
416 }
417
418
419
420 Node::AndOp(bin) => {
425 let lhv = eval(&bin.lho, scope);
426 if bool::from(lhv.clone()) { eval(&bin.rho, scope) } else { lhv }
427 }
428
429 Node::OrOp(bin) => {
432 let lhv = eval(&bin.lho, scope);
433 if bool::from(lhv.clone()) { lhv } else { eval(&bin.rho, scope) }
434 }
435
436
437
438 Node::ConditionalOp(bin) => {
443 let lhv = eval(&bin.lho, scope);
444 if bool::from(lhv) { eval(&bin.rho, scope) } else { Value::Nothing }
445 }
446
447 Node::AlternativeOp(bin) => {
449 let lhv = eval(&bin.lho, scope);
450 match lhv {
451 Value::Nothing => eval(&bin.rho, scope),
452 _ => lhv
453 }
454 }
455
456
457
458 Node::CompositionOp(bin) => {
462 let lhv = eval(&bin.lho, scope);
463 let rhv = eval(&bin.rho, scope);
464 map_pairs!(lhv, rhv, |l,r| eval_composition(l, r, bin.pos))
465 }
466
467 Node::ReverseCompositionOp(bin) => {
469 let lhv = eval(&bin.lho, scope);
470 let rhv = eval(&bin.rho, scope);
471 map_pairs!(lhv, rhv, |l,r| eval_composition(r, l, bin.pos))
472 }
473
474
475
476 Node::Unclosed(leaf) => {
480 Value::Undefined(Undef::Termination{
481 expected: leaf.val,
482 pos: leaf.pos,
483 })
484 }
485
486 Node::UnexpectedToken(leaf) => {
488 Value::Undefined(Undef::Token{
489 token: leaf.val.clone(),
490 pos: leaf.pos
491 })
492 }
493 }
494}
495
496
497fn invalid_names(op: &'static str, names: Value, pos: usize) -> Value {
508 Value::undef_binary(op, names, Value::Nothing, pos)
509}
510
511fn eval_names(node: &Node) -> Value {
524 match node {
525
526 Node::Nothing(_) => Value::Nothing,
528
529 Node::Identifier(leaf) => Value::Name(leaf.val.as_str().into()),
531
532 Node::PairingOp(bin) => {
534 let name1 = eval_names(&bin.lho);
535 let name2 = eval_names(&bin.rho);
536
537 if matches!(name1, Value::Undefined(_)) {
539 return name1;
540 }
541 if matches!(name2, Value::Undefined(_)) {
542 return name2;
543 }
544
545 pairing_operation::eval(name1, name2)
546 }
547
548
549
550 node => Value::Undefined(Undef::Name{ pos: node.position() }),
552 }
553}
554
555
556
557pub fn eval_apply(func: Value, arg: Value, pos: usize) -> Value {
583 match func {
584 Value::Builtin(ref f) => f.call(arg),
585
586 Value::Func { params, body, closure } => {
587 let local_scope = closure.new_child();
588 assignment_operation::eval(&local_scope, ¶ms, &arg);
589 eval(&body, &local_scope)
590 }
591
592 Value::List(list) => {
594 if matches!(arg, Value::Tuple(_)) {
595 let items: Vec<Value> = arg
596 .items()
597 .map(|idx| eval_apply_list(&list, idx, pos))
598 .collect();
599 Value::tuple(items)
600 } else {
601 eval_apply_list(&list, arg, pos)
602 }
603 }
604
605 Value::Namespace(scope) => {
607 if matches!(arg, Value::Tuple(_)) {
608 let items: Vec<Value> = arg
609 .items()
610 .map(|key| eval_apply_namespace(&scope, key, pos))
611 .collect();
612 Value::tuple(items)
613 } else {
614 eval_apply_namespace(&scope, arg, pos)
615 }
616 }
617
618 Value::Text(text) => {
620 if matches!(arg, Value::Tuple(_)) {
621 let items: Vec<Value> = arg
622 .items()
623 .map(|idx| eval_apply_text(&text, idx, pos))
624 .collect();
625 Value::tuple(items)
626 } else {
627 eval_apply_text(&text, arg, pos)
628 }
629 }
630
631 other => Value::undef_binary("application", other, arg, pos),
632 }
633}
634
635fn eval_apply_list(list: &[Value], arg: Value, pos: usize) -> Value {
640 match arg {
641 Value::Numb(n) => {
642 if n >= 0.0 && n.fract() == 0.0 {
643 let idx = n as usize;
644 if idx < list.len() {
645 return list[idx].clone();
646 }
647 }
648 Value::Nothing
650 }
651 other => Value::undef_binary("application", Value::list(list.to_vec()), other, pos),
653 }
654}
655
656fn eval_apply_text(text: &Rc<str>, arg: Value, pos: usize) -> Value {
663 match arg {
664 Value::Numb(n) => {
665 if n >= 0.0 && n.fract() == 0.0 {
666 if let Some(ch) = text.chars().nth(n as usize) {
667 return Value::Text(ch.to_string().into());
668 }
669 }
670 Value::Nothing
672 }
673 other => Value::undef_binary("application", Value::Text(text.clone()), other, pos),
675 }
676}
677
678fn eval_apply_namespace(scope: &Scope, arg: Value, pos: usize) -> Value {
684 match arg {
685 Value::Text(t) => {
686 let found = scope.0.borrow().bindings.get(t.as_ref()).cloned();
687 found.unwrap_or(Value::Nothing)
688 }
689 other => Value::undef_binary("application", Value::Namespace(scope.clone()), other, pos),
691 }
692}
693
694
695
696fn eval_composition(f: Value, g: Value, pos: usize) -> Value {
708 Value::Builtin(BuiltinFn::new("composed", move |x:Value| {
709 let y = eval_apply(g.clone(), x, pos); eval_apply(f.clone(), y, pos) }))
712}
713
714
715
716#[cfg(test)]
721mod tests {
723 use super::*;
724 use std::assert_matches;
725 use crate::lexer::Lexer;
726 use crate::parser::Parser;
727
728 fn evaluate(src: &str) -> Value {
730 let mut parser = Parser::new(Lexer::new(src));
731 let ast = parser.parse();
732 let scope = Scope::new();
733 scope.set("TRUE", Value::Bool(true));
734 scope.set("FALSE", Value::Bool(false));
735 eval(&ast, &scope)
736 }
737
738 #[test]
739 fn number_literal() {
740 assert_eq!(evaluate("7.2"), Value::Numb(7.2));
741 }
742
743 #[test]
744 fn string_literal() {
745 assert_eq!(evaluate("\"abc\""), Value::Text("abc".into()));
746 }
747
748 #[test]
749 fn nothing_literal() {
750
751 assert_eq!(evaluate(""), Value::Nothing);
752 assert_eq!(evaluate(" "), Value::Nothing);
753 assert_eq!(evaluate("# comment\n"), Value::Nothing);
754 assert_eq!(evaluate(" # comment\n "), Value::Nothing);
755
756 assert_eq!(evaluate("()"), Value::Nothing);
757 assert_eq!(evaluate("( )"), Value::Nothing);
758 assert_eq!(evaluate("(\n# comment\n)"), Value::Nothing);
759 assert_eq!(evaluate("(())"), Value::Nothing);
760 }
761
762 #[test]
763 fn identifier() {
764 assert_eq!(evaluate("TRUE"), Value::Bool(true));
765 assert_eq!(evaluate("x = 4, x"), Value::Numb(4.0));
766 }
767
768 #[test]
769 fn list_literal() {
770 assert_eq!(
771 evaluate("[7 , 2 , 9]"),
772 Value::list(vec![
773 Value::Numb(7.0),
774 Value::Numb(2.0),
775 Value::Numb(9.0)
776 ])
777 );
778
779 assert_eq!(
780 evaluate("[7 , [2,9]]"),
781 Value::list(vec![
782 Value::Numb(7.0),
783 Value::list(vec![
784 Value::Numb(2.0),
785 Value::Numb(9.0)
786 ])
787 ])
788 );
789
790 assert_eq!(evaluate("[]"), Value::list(vec![]));
791 }
792
793 #[test]
794 fn namespace_literal() {
795 match evaluate("{x:10, y:20}") {
796 Value::Namespace(scope) => {
797 assert_eq!(scope.get("x"), Value::Numb(10.0));
798 assert_eq!(scope.get("y"), Value::Numb(20.0));
799
800 assert_eq!(scope.get("TRUE"), Value::Bool(true));
802 }
803 other => panic!("expected Namespace, got {:?}", other),
804 }
805 }
806
807 #[test]
808 fn function_definition() {
809
810 assert_matches!(evaluate("(x, y) -> x+y"), Value::Func{params:_, body:_, closure:_});
811
812 assert_eq!(evaluate("(x, 12) -> 2*x"), invalid_names("function_definition", Value::Undefined(Undef::Name{pos:4}), 8));
814 }
815
816 #[test]
817 fn application() {
818 assert_eq!(evaluate("f = (a) -> 2*a , f 5"), Value::Numb(10.0));
820 assert_eq!(evaluate("f = (a,b) -> a+b , f(3,7)"), Value::Numb(10.0));
821 assert_eq!(
822 evaluate("f = (a,b,c) -> (a,b)*c , f(2,3,4,5)"),
823 Value::tuple(vec![Value::Numb(8.0), Value::Numb(15.0)])
824 );
825 assert_eq!(evaluate("(()->3)()"), Value::Numb(3.0));
826 assert_eq!(evaluate("(()->3) 10"), Value::Numb(3.0));
827
828 assert_eq!(evaluate("() 5"), Value::Nothing);
830
831 assert_eq!(
833 evaluate("(x->2*x , x->3*x) 4"),
834 Value::tuple(vec![Value::Numb(8.0), Value::Numb(12.0)])
835 );
836
837 assert_eq!(evaluate("[10, 20, 30] 1"), Value::Numb(20.0));
839
840 assert_eq!(evaluate("[10, 20] 5"), Value::Nothing);
842
843 assert!(matches!(
845 evaluate(r#"[10, 20] "0""#),
846 Value::Undefined(Undef::BinaryOperation { op: "application", .. })
847 ));
848
849 assert_eq!(
851 evaluate("[10, 20, 30] (0, 5, 2)"),
852 Value::tuple(vec![Value::Numb(10.0), Value::Numb(30.0)])
853 );
854 assert_eq!(
855 evaluate("([1,2,3] , [10,20,30]) 1"),
856 Value::tuple(vec![Value::Numb(2.0), Value::Numb(20.0)])
857 );
858
859 assert_eq!(evaluate(r#"{x: 10, y: 20} "x""#), Value::Numb(10.0));
861
862 assert_eq!(evaluate(r#"{x: 10} "z""#), Value::Nothing);
864
865 assert!(matches!(
867 evaluate("{x: 10} 1"),
868 Value::Undefined(Undef::BinaryOperation { op: "application", .. })
869 ));
870
871 assert_eq!(
873 evaluate(r#"{x: 10, y: 20} ("x", "missing")"#),
874 Value::Numb(10.0),
875 );
876
877 assert_eq!(
878 evaluate("({x:1, y:2} , {x:10, y:20}) \"y\""),
879 Value::tuple(vec![Value::Numb(2.0), Value::Numb(20.0)])
880 );
881
882 assert_eq!(evaluate(r#""hello" 1"#), Value::Text("e".into()));
884 assert_eq!(evaluate(r#""hello" 0"#), Value::Text("h".into()));
885
886 assert_eq!(evaluate(r#""héllo" 1"#), Value::Text("é".into()));
888
889 assert_eq!(evaluate(r#""hello" 5"#), Value::Nothing);
891 assert_eq!(evaluate(r#""hello" (-1)"#), Value::Nothing);
892 assert_eq!(evaluate(r#""hello" 1.5"#), Value::Nothing);
893 assert_eq!(evaluate(r#""" 0"#), Value::Nothing);
894
895 match evaluate(r#""abc" "0""#) {
897 Value::Undefined(Undef::BinaryOperation { op, lhv, rhv, .. }) => {
898 assert_eq!(op, "application");
899 assert_eq!(*lhv, Value::Text("abc".into()));
900 assert_eq!(*rhv, Value::Text("0".into()));
901 }
902 other => panic!("expected Undefined::BinaryOperation, got {:?}", other),
903 }
904
905 assert_eq!(
907 evaluate(r#""hello" (0, 10, 4)"#),
908 Value::tuple(vec![
909 Value::Text("h".into()),
910 Value::Text("o".into()),
911 ])
912 );
913
914 assert_eq!(
916 evaluate(r#"("abc", "xyz") 1"#),
917 Value::tuple(vec![
918 Value::Text("b".into()),
919 Value::Text("y".into()),
920 ])
921 );
922 }
923
924 #[test]
925 fn assignment() {
926 assert_eq!(evaluate("x = 5"), Value::Nothing);
928 assert_eq!(evaluate("x = 5, x"), Value::Numb(5.0));
929
930 assert_eq!(evaluate("(a, b) = (1, 2), a + b"), Value::Numb(3.0));
932
933 assert_eq!(evaluate("(x, 12) = (1, 2)"), invalid_names("assignment", Value::Undefined(Undef::Name{pos:4}), 8));
935 }
936
937 #[test]
938 fn labelling() {
939 assert_eq!(evaluate("x : 5"), Value::Numb(5.0));
942
943 assert_eq!(
944 evaluate("x : 5, x"),
945 Value::tuple(vec![Value::Numb(5.0), Value::Numb(5.0)])
946 );
947
948 assert_eq!(
951 evaluate("(a, b) : (1, 2)"),
952 Value::tuple(vec![Value::Numb(1.0), Value::Numb(2.0)])
953 );
954
955 assert_eq!(evaluate("(x, 12) : (1, 2)"), invalid_names("labelling", Value::Undefined(Undef::Name{pos:4}), 8));
957 }
958
959 #[test]
960 fn subcontexting() {
961 assert_eq!(evaluate("{x:10}.x"), Value::Numb(10.0));
962 assert_eq!(evaluate("{x:10, y:20}.(x+y)"), Value::Numb(30.0));
963 assert_eq!(evaluate("{x:10, y:20}.TRUE"), Value::Bool(true));
964 match evaluate("x=10, x.TRUE") {
965 Value::Undefined(Undef::BinaryOperation { op, lhv, rhv, pos }) => {
966 assert_eq!(op, "subcontexting");
967 assert_eq!(*lhv, Value::Numb(10.0));
968 assert_eq!(*rhv, Value::Nothing);
969 assert_eq!(pos, 7);
970 }
971 other => panic!("expected Undefined::BinaryOperation, got {:?}", other),
972 }
973 }
974
975 #[test]
976 fn mapping() {
977
978 assert_eq!(evaluate("f = a -> 2*a , (2,3,4) => f"), Value::tuple(vec![
980 Value::Numb(4.0),
981 Value::Numb(6.0),
982 Value::Numb(8.0),
983 ]));
984
985 assert_eq!(evaluate("f = a -> 2*a , 2 => f"), Value::Numb(4.0));
987
988 assert_eq!(evaluate("f = a -> 2*a , () => f"), Value::Nothing);
990
991 assert_eq!(evaluate("f = a -> () , (1,2,3) => f"), Value::Nothing);
993
994 assert_eq!(
996 evaluate("f = a -> 2*a , g = b -> 3*b, (2,5) => (f,g)"),
997 Value::tuple(vec![
998 Value::Numb(4.0),
999 Value::Numb(6.0),
1000 Value::Numb(10.0),
1001 Value::Numb(15.0),
1002 ])
1003 );
1004 }
1005
1006 #[test]
1007 fn conditional() {
1008
1009 assert_eq!(evaluate("TRUE ? 10"), Value::Numb(10.0));
1011 assert_eq!(evaluate("1 ? \"yes\""), Value::Text("yes".into()));
1012 assert_eq!(evaluate("[1] ? 42"), Value::Numb(42.0));
1013
1014 assert_eq!(evaluate("FALSE ? 10"), Value::Nothing);
1016 assert_eq!(evaluate("0 ? 10"), Value::Nothing);
1017 assert_eq!(evaluate("\"\" ? 10"), Value::Nothing);
1018 assert_eq!(evaluate("() ? 10"), Value::Nothing);
1019 assert_eq!(evaluate("() ? ()"), Value::Nothing);
1020
1021 assert_eq!(
1023 evaluate("(TRUE, FALSE, TRUE, FALSE) ? (1,2,3,4)"),
1024 Value::tuple(vec![
1025 Value::Numb(1.0),
1026 Value::Numb(2.0),
1027 Value::Numb(3.0),
1028 Value::Numb(4.0),
1029 ])
1030 );
1031 assert_eq!(evaluate("(FALSE, 0, \"\") ? (1,2,3)"), Value::Nothing);
1032
1033 assert_eq!(evaluate("TRUE ? (1, 2)"), Value::tuple(vec![Value::Numb(1.0), Value::Numb(2.0)]));
1035 }
1036
1037 #[test]
1038 fn alternative() {
1039 assert_eq!(evaluate("() ; 2"), Value::Numb(2.0));
1040 assert_eq!(evaluate("1 ; 2"), Value::Numb(1.0));
1041 assert_eq!(evaluate("FALSE ; 2"), Value::Bool(false));
1042 }
1043
1044 #[test]
1045 fn and_op() {
1046
1047 assert_eq!(evaluate("TRUE & 10"), Value::Numb(10.0));
1049 assert_eq!(evaluate("TRUE & FALSE"), Value::Bool(false));
1050 assert_eq!(evaluate("1 & \"hello\""), Value::Text("hello".into()));
1051
1052 assert_eq!(evaluate("FALSE & 10"), Value::Bool(false));
1054 assert_eq!(evaluate("0 & 10"), Value::Numb(0.0));
1055 assert_eq!(evaluate("\"\" & 10"), Value::Text("".into()));
1056
1057 assert_eq!(evaluate("() & ()"), Value::Nothing);
1059 assert_eq!(evaluate("() & 10"), Value::Nothing);
1060
1061 assert_eq!(
1063 evaluate("(FALSE, 1) & (10, \"abc\")"),
1064 Value::tuple(vec![
1065 Value::Numb(10.0),
1066 Value::Text("abc".into()),
1067 ])
1068 );
1069 assert_eq!(
1070 evaluate("(FALSE, 0) & 10"),
1071 Value::tuple(vec![Value::Bool(false), Value::Numb(0.0)])
1072 );
1073 assert_eq!(evaluate("TRUE & (10, 1)"), Value::tuple(vec![Value::Numb(10.0), Value::Numb(1.0)]));
1074 }
1075
1076 #[test]
1077 fn or_op() {
1078 assert_eq!(evaluate("TRUE | 10"), Value::Bool(true));
1080 assert_eq!(evaluate("1 | 10"), Value::Numb(1.0));
1081 assert_eq!(evaluate("\"yes\" | 10"), Value::Text("yes".into()));
1082
1083 assert_eq!(evaluate("FALSE | 10"), Value::Numb(10.0));
1085 assert_eq!(evaluate("0 | \"fallback\""), Value::Text("fallback".into()));
1086 assert_eq!(evaluate("\"\" | TRUE"), Value::Bool(true));
1087
1088 assert_eq!(evaluate("() | 5"), Value::Numb(5.0));
1090
1091 assert_eq!(
1093 evaluate("(FALSE, 1) | (10, \"abc\")"),
1094 Value::tuple(vec![
1095 Value::Bool(false),
1096 Value::Numb(1.0),
1097 ])
1098 );
1099 assert_eq!(evaluate("(FALSE, 0) | 10"), Value::Numb(10.0));
1100 assert_eq!(evaluate("FALSE | (10, 1)"), Value::tuple(vec![Value::Numb(10.0), Value::Numb(1.0)]));
1101 }
1102
1103 #[test]
1104 fn short_circuit() {
1105 let scope = crate::builtins::root_scope().new_child();
1108 let run = |src: &str| eval(&Parser::new(Lexer::new(src)).parse(), &scope);
1109
1110 run("x = 0");
1111 run("FALSE & (x = 1)");
1112 run("TRUE | (x = 2)");
1113 run("FALSE ? (x = 3)");
1114 run("(FALSE, 0) ? (x = 4)");
1115 run("(FALSE, 1) | (x = 5)");
1116 assert_eq!(run("x"), Value::Numb(0.0));
1117
1118 run("TRUE & (x = 1)");
1119 assert_eq!(run("x"), Value::Numb(1.0));
1120 run("FALSE | (x = 2)");
1121 assert_eq!(run("x"), Value::Numb(2.0));
1122 run("TRUE ? (x = 3)");
1123 assert_eq!(run("x"), Value::Numb(3.0));
1124 run("(FALSE, 1) ? (x = 4)");
1125 assert_eq!(run("x"), Value::Numb(4.0));
1126
1127 assert_eq!(run("f = n -> n > 1 ? n * f (n - 1) ; 1, f 5"), Value::Numb(120.0));
1129 assert_eq!(run("g = n -> (n <= 1 & 1) | n * g (n - 1), g 5"), Value::Numb(120.0));
1130 assert_eq!(run("h = n -> n > 0 & h (n - 1), h 5"), Value::Bool(false));
1131 }
1132
1133 #[test]
1134 fn composition() {
1135 assert_eq!(evaluate("f = y -> 2*y , g = x -> x+1 , (f<<g)(3)"), Value::Numb(8.0));
1136 }
1137
1138 #[test]
1139 fn reverse_composition() {
1140 assert_eq!(evaluate("f = y -> 2*y , g = x -> x+1 , (f>>g)(3)"), Value::Numb(7.0));
1141 }
1142
1143 #[test]
1144 fn unclosed_bracket() {
1145 assert!(matches!(evaluate("(1, 2"), Value::Undefined(Undef::Termination{ .. })));
1146 }
1147
1148 #[test]
1149 fn unexpected_token() {
1150 assert!(matches!(evaluate(")"), Value::Undefined(Undef::Token{ .. })));
1151 }
1152
1153 #[test]
1154 fn precedence() {
1155 assert_eq!(evaluate("ns = {f: x -> 2*x}, ns.f 3"), Value::Numb(6.0));
1156 assert_eq!(evaluate("ns = {a=10}, f = x -> 2*x, f ns.a"), Value::Numb(20.0));
1157 assert_eq!(evaluate("f = x -> {y:x}, (f 3).y"), Value::Numb(3.0));
1158 }
1159
1160 #[test]
1161 fn promise_as_condition() {
1162 let scope = crate::builtins::root_scope().new_child();
1164 let run = |src: &str| eval(&Parser::new(Lexer::new(src)).parse(), &scope);
1165
1166 run("p = promise.create()");
1167 assert_eq!(run("p ? 1"), Value::Nothing);
1168 assert_eq!(run("p ? 1 ; 2"), Value::Numb(2.0));
1169 assert_matches!(run("p & 1"), Value::Promise(_));
1170 assert_eq!(run("p | 1"), Value::Numb(1.0));
1171 assert_eq!(run("!p"), Value::Bool(true));
1172 assert_eq!(run("(FALSE, p) ? 1"), Value::Nothing);
1173
1174 run("promise.resolve p FALSE");
1175 assert_eq!(run("p ? 1"), Value::Numb(1.0));
1176 assert_eq!(run("p & 1"), Value::Numb(1.0));
1177 assert_matches!(run("p | 1"), Value::Promise(_));
1178 assert_eq!(run("!p"), Value::Bool(false));
1179 assert_eq!(run("(FALSE, p) ? 1"), Value::Numb(1.0));
1180 }
1181}