Added a q shortcut to quote get-doc and set-doc no longer conditionally evaluate args Fixed bug in let, documented potential performance improvements upped default history to 5k lines
358 lines
11 KiB
Rust
358 lines
11 KiB
Rust
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 (quote 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 (q help) 'help')";
|
|
let document = "(get-doc (q 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!()
|
|
}
|
|
}
|
|
|
|
}
|