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(); eval(&lex(&doc1.to_string()).unwrap(), &mut syms).unwrap(); let res = *eval(&lex(&doc2.to_string()).unwrap(), &mut syms).unwrap(); assert_eq!(res.to_string(), result); } #[test] fn test_variable_def_and_lookup_list() { 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(); eval(&lex(&doc1.to_string()).unwrap(), &mut syms).unwrap(); let res = *eval(&lex(&doc2.to_string()).unwrap(), &mut syms).unwrap(); assert_eq!(res.to_string(), result); } #[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(); eval(&lex(&doc1.to_string()).unwrap(), &mut syms).unwrap(); let res = *eval(&lex(&doc2.to_string()).unwrap(), &mut syms).unwrap(); assert_eq!(res.to_string(), result); } #[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(); eval(&lex(&doc1.to_string()).unwrap(), &mut syms).unwrap(); eval(&lex(&doc2.to_string()).unwrap(), &mut syms).unwrap(); let res = *eval(&lex(&doc3.to_string()).unwrap(), &mut syms).unwrap(); assert_eq!(res.to_string(), result); } #[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(); eval(&lex(&doc1.to_string()).unwrap(), &mut syms).unwrap(); eval(&lex(&doc2.to_string()).unwrap(), &mut syms).unwrap(); let eval_result = eval(&lex(&doc3.to_string()).unwrap(), &mut syms); if let Err(s) = eval_result { assert_eq!( s.to_string(), "error in call to test: undefined symbol: test".to_string() ); } else { assert!(false); } } #[test] fn test_variable_def_redef_via_reference_and_lookup() { let doc1 = "(def test 'my test var' 1)"; let doc2 = "(def ref 'references test' (quote test))"; let doc3 = "(def (eval ref) 'my test var' '2')"; let doc4 = "(test)"; let result = "('2')"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); eval(&lex(&doc1.to_string()).unwrap(), &mut syms).unwrap(); eval(&lex(&doc2.to_string()).unwrap(), &mut syms).unwrap(); eval(&lex(&doc3.to_string()).unwrap(), &mut syms).unwrap(); let res = *eval(&lex(&doc4.to_string()).unwrap(), &mut syms).unwrap(); assert_eq!(res.to_string(), result); } #[test] fn test_variable_doc_dynamic() { let doc1 = "(def test-doc 'docs for test' 'test tests tests test')"; let doc2 = "(def test test-doc 'one')"; let doc3 = "(eq? (and (eq? (get-doc test) test-doc) (eq? test 'one')))"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); eval(&lex(&doc1.to_string()).unwrap(), &mut syms).unwrap(); eval(&lex(&doc2.to_string()).unwrap(), &mut syms).unwrap(); if let Ctr::Bool(b) = *eval(&lex(&doc3.to_string()).unwrap(), &mut syms).unwrap() { assert!(b); } else { 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(); eval(&lex(&doc1.to_string()).unwrap(), &mut syms).unwrap(); let res = *eval(&lex(&doc2.to_string()).unwrap(), &mut syms).unwrap(); assert_eq!(res.to_string(), result); } #[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_eval_basic() { let document = "(eval (1 2 3))"; let result = "(1 2 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(), ); } /* THIS TEST REMOVED BECAUSE EVAL SHOULDNT ARBITRARILY DO THINGS TWICE * KEPT FOR REFERENCE PURPOSES JUST IN CASE #[test] fn test_eval_var_deref() { let def1 = "(def one '' 1)"; let def2 = "(def two '' (quote one))"; let document = "(eval two)"; let result = "1"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); eval(&lex(&def1.to_string()).unwrap(), &mut syms).unwrap(); eval(&lex(&def2.to_string()).unwrap(), &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(); 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(); 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(); if let Ctr::Integer(i) = it { assert_eq!(i, 3) } else { panic!() } } #[test] fn test_setget_doc_string() { let highly_inadvisable = "(set-doc help 'help')"; let document = "(get-doc help)"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap(); let _ = *eval( &lex(&highly_inadvisable.to_string()).unwrap(), &mut syms).unwrap(); let it = *eval( &lex(&document.to_string()).unwrap(), &mut syms).unwrap(); if let Ctr::String(i) = it { assert_eq!(i, "help".to_string()) } else { panic!() } } }