diff --git a/src/stl.rs b/src/stl.rs index 741d7e0..7f3290e 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -59,7 +59,7 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> { pub fn dynamic_stdlib(env: bool, syms: &mut SymTable) -> Result<(), String> { syms.insert("def".to_string(), Symbol { name: String::from("define"), - args: Args::Lazy(2), + args: Args::Infinite, conditional_branches: true, value: ValueType::Internal(Rc::new( move |ast: &Seg, syms: &mut SymTable| -> Result { _store_callback(ast, syms, env) diff --git a/tests/test_vars.rs b/tests/test_vars.rs index 431ef4c..ce4041f 100644 --- a/tests/test_vars.rs +++ b/tests/test_vars.rs @@ -3,7 +3,7 @@ mod var_lib_tests { use relish::stdlib::{static_stdlib, dynamic_stdlib}; #[test] - fn test_variable_export_and_lookup() { + fn test_variable_def_and_lookup() { let doc1 = "(def test 1)"; let doc2 = "(test)"; let result = "(1)"; @@ -39,4 +39,110 @@ mod var_lib_tests { assert!(false); } } + + #[test] + fn test_variable_def_redef_and_lookup() { + let doc1 = "(def test 1)"; + let doc2 = "(def test '2')"; + let doc3 = "(test)"; + let result = "('2')"; + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &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 1)"; + let doc2 = "(def test)"; + let doc3 = "(test)"; + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &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); + } + } }