mod decl_lib_tests { use relish::ast::{eval, lex, Ctr, SymTable}; use relish::stdlib::{dynamic_stdlib, static_stdlib}; #[test] fn test_variable_def_and_lookup() { let doc1 = "(def test 'my test var' 1)"; let doc2 = "(test)"; let result = "(1)"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); if let Ok(tree) = lex(&doc1.to_string()) { let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::None = eval_result { // pass } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc1"); assert!(false); } if let Ok(tree) = lex(&doc2.to_string()) { println!("tree: {tree}"); let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::Seg(ref i) = eval_result { assert_eq!(i.to_string(), result); } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc2"); assert!(false); } } #[test] fn test_func_def_and_lookup() { let doc1 = "(def test 'my test func' (hello) hello)"; let doc2 = "(test '1')"; let result = "1"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); if let Ok(tree) = lex(&doc1.to_string()) { let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::None = eval_result { // pass } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc1"); assert!(false); } if let Ok(tree) = lex(&doc2.to_string()) { let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::String(ref i) = eval_result { assert_eq!(i.to_string(), result); } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc2"); assert!(false); } } #[test] fn test_variable_def_redef_and_lookup() { let doc1 = "(def test 'my test var' 1)"; let doc2 = "(def test 'my test var' '2')"; let doc3 = "(test)"; let result = "('2')"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); if let Ok(tree) = lex(&doc1.to_string()) { let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::None = eval_result { // pass } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc1"); assert!(false); } if let Ok(tree) = lex(&doc2.to_string()) { println!("tree: {tree}"); let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::None = eval_result { // pass } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc2"); assert!(false); } if let Ok(tree) = lex(&doc3.to_string()) { println!("tree: {tree}"); let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::Seg(ref i) = eval_result { assert_eq!(i.to_string(), result); } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc3"); assert!(false); } } #[test] fn test_variable_def_undef_and_lookup_fail() { let doc1 = "(def test 'my test var' 1)"; let doc2 = "(def test)"; let doc3 = "(test)"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); if let Ok(tree) = lex(&doc1.to_string()) { let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::None = eval_result { // pass } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc1"); assert!(false); } if let Ok(tree) = lex(&doc2.to_string()) { println!("tree: {tree}"); let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::None = eval_result { // pass } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc2"); assert!(false); } if let Ok(tree) = lex(&doc3.to_string()) { println!("tree: {tree}"); let eval_result = eval(&tree, &mut syms); if let Err(s) = eval_result { assert_eq!( s.to_string(), "error in call to test: undefined symbol: test".to_string() ); } else { let res = eval_result.unwrap(); eprintln!("shouldn't have suceeded: {res}"); assert!(false); } } else { eprintln!("couldn't lex doc3"); assert!(false); } } #[test] fn test_func_def_no_args() { let doc1 = "(def test 'my test func' () '1')"; let doc2 = "(test)"; let result = "1"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); if let Ok(tree) = lex(&doc1.to_string()) { let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::None = eval_result { // pass } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc1"); assert!(false); } if let Ok(tree) = lex(&doc2.to_string()) { let eval_result = *eval(&tree, &mut syms).unwrap(); if let Ctr::String(ref i) = eval_result { assert_eq!(i.to_string(), result); } else { eprintln!("bad: {eval_result}"); assert!(false); } } else { eprintln!("couldn't lex doc2"); assert!(false); } } #[test] fn test_isset_true() { let doc1 = "(def test '' 1)"; let doc2 = "(set? test)"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); let def_tree = lex(&doc1.to_string()).unwrap(); let set_tree = lex(&doc2.to_string()).unwrap(); eval(&def_tree, &mut syms).unwrap(); if let Ctr::Bool(b) = *eval(&set_tree, &mut syms).unwrap() { assert!(b); } } #[test] fn test_isset_false() { let doc = "(set? test)"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); let set_tree = lex(&doc.to_string()).unwrap(); if let Ctr::Bool(b) = *eval(&set_tree, &mut syms).unwrap() { assert!(!b); } } #[test] fn test_env_doesnt_lose_elements() { let doc1 = "(def t '' 1)"; let doc2 = "(env)"; let doc3 = "t"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); let set_tree = lex(&doc1.to_string()).unwrap(); let env_tree = lex(&doc2.to_string()).unwrap(); let tst_tree = lex(&doc3.to_string()).unwrap(); eval(&set_tree, &mut syms).unwrap(); eval(&env_tree, &mut syms).unwrap(); eval(&tst_tree, &mut syms).unwrap(); } #[test] fn test_quote() { let document = "(quote (add 1 2))"; let result = "(add 1 2)"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); assert_eq!( *eval(&lex(&document.to_string()).unwrap(), &mut syms) .unwrap() .to_string(), result.to_string(), ); } #[test] fn test_eval() { let document = " (let ((stored-tree (quote (add 1 2)))) (eval stored-tree)))"; let result = "3"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); assert_eq!( *eval(&lex(&document.to_string()).unwrap(), &mut syms) .unwrap() .to_string(), result.to_string(), ); } #[test] fn test_lambda_str_equivalency_list() { let document = "(lambda (x y) (add x y))"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); assert_eq!( *eval(&lex(&document.to_string()).unwrap(), &mut syms) .unwrap() .to_string(), document.to_string(), ); } #[test] fn test_lambda_str_equivalency_no_args() { let document = "(lambda () (add 1 2))"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); assert_eq!( *eval(&lex(&document.to_string()).unwrap(), &mut syms) .unwrap() .to_string(), document.to_string(), ); } #[test] fn test_lambda_inline_call() { let document = "((lambda (x y) (add x y)) 1 2)"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); let it = *eval( &lex(&document.to_string()).unwrap(), &mut syms).unwrap(); println!("final return: {}", it); if let Ctr::Integer(i) = it { assert_eq!(i, 3) } else { panic!() } } #[test] fn test_lambda_let_call() { let document = "(let ((adder (lambda (x y) (add x y)))) (adder 1 2))"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); let it = *eval( &lex(&document.to_string()).unwrap(), &mut syms).unwrap(); println!("{}", it); if let Ctr::Integer(i) = it { assert_eq!(i, 3) } else { panic!() } } #[test] fn test_lambda_var_bound_call() { let document = "(let (()) (def adder 'my adder' (lambda (x y) (add x y))) (adder 1 2))"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); let it = *eval( &lex(&document.to_string()).unwrap(), &mut syms).unwrap(); println!("{}", it); if let Ctr::Integer(i) = it { assert_eq!(i, 3) } else { panic!() } } }