Big project dir refactor
* split into multi member workspace in preparation for a no_std core * env and posix stuff neatly crammed into a seperate shell project * some pokes at interactive-devel.f * updated ci * removed 'l' shortcut for 'load' and update docs * remove out of date readme content * updated tests * more sensible cond implementation and extra tests * substr stdlib function with tests Signed-off-by: Ava Affine <ava@sunnypup.io>
This commit is contained in:
parent
aa56570d7d
commit
6d2925984f
44 changed files with 967 additions and 779 deletions
113
core/tests/test_eval.rs
Normal file
113
core/tests/test_eval.rs
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
mod eval_tests {
|
||||
use flesh::ast::{eval, lex, SymTable};
|
||||
use flesh::ast::{Args, Ctr, Seg, Symbol, UserFn, ValueType};
|
||||
use flesh::stdlib::static_stdlib;
|
||||
|
||||
#[test]
|
||||
fn eval_simple() {
|
||||
let test_doc = "(1 2)".to_string();
|
||||
let mut syms = SymTable::new();
|
||||
let doc_tree = lex(&test_doc).unwrap();
|
||||
let reduced = *eval(&doc_tree, &mut syms).unwrap();
|
||||
assert_eq!(reduced.to_string(), test_doc);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eval_embedded_lists_no_funcs() {
|
||||
let test_doc = "(1 (1 2 3 4 5) 5)".to_string();
|
||||
let mut syms = SymTable::new();
|
||||
let doc_tree = lex(&test_doc).unwrap();
|
||||
let reduced = *eval(&doc_tree, &mut syms).unwrap();
|
||||
assert_eq!(reduced.to_string(), test_doc);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eval_function_call() {
|
||||
let test_doc = "(\"one\" (echo \"unwrap_me\"))".to_string();
|
||||
let output = "(\"one\" \"unwrap_me\")";
|
||||
let mut syms = SymTable::new();
|
||||
|
||||
let test_external_func: Symbol = Symbol {
|
||||
name: String::from("echo"),
|
||||
args: Args::Lazy(1),
|
||||
conditional_branches: false,
|
||||
docs: String::new(),
|
||||
value: ValueType::FuncForm(UserFn {
|
||||
arg_syms: vec!["input".to_string()],
|
||||
ast: Box::new(Seg::from(
|
||||
Box::from(Ctr::Symbol("input".to_string())),
|
||||
Box::from(Ctr::None),
|
||||
)),
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
syms.insert(String::from("echo"), test_external_func);
|
||||
let doc_tree = lex(&test_doc).unwrap();
|
||||
let reduced = *eval(&doc_tree, &mut syms).unwrap();
|
||||
assert_eq!(reduced.to_string(), output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eval_embedded_func_calls() {
|
||||
let test_doc = "(\"one\" (echo (echo \"unwrap_me\")))".to_string();
|
||||
let output = "(\"one\" \"unwrap_me\")";
|
||||
let mut syms = SymTable::new();
|
||||
|
||||
let test_external_func: Symbol = Symbol {
|
||||
name: String::from("echo"),
|
||||
args: Args::Lazy(1),
|
||||
conditional_branches: false,
|
||||
docs: String::new(),
|
||||
value: ValueType::FuncForm(UserFn {
|
||||
arg_syms: vec!["input".to_string()],
|
||||
ast: Box::new(Seg::from(
|
||||
Box::from(Ctr::Symbol("input".to_string())),
|
||||
Box::from(Ctr::None),
|
||||
)),
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
syms.insert(String::from("echo"), test_external_func);
|
||||
let doc_tree = lex(&test_doc).unwrap();
|
||||
let reduced = *eval(&doc_tree, &mut syms).unwrap();
|
||||
assert_eq!(reduced.to_string(), output);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "implicit-load"))]
|
||||
#[test]
|
||||
fn eval_bad_syms() {
|
||||
let test_doc = "(undefined)".to_string();
|
||||
let mut syms = SymTable::new();
|
||||
let doc_tree = lex(&test_doc).unwrap();
|
||||
match eval(&doc_tree, &mut syms) {
|
||||
Err(e) => {
|
||||
assert_eq!(e.0.first().unwrap().message,
|
||||
"(is an undefined symbol)")
|
||||
}
|
||||
|
||||
Ok(reduced) => {
|
||||
println!("Eval succeeded when it shouldnt have");
|
||||
println!("see: {}", reduced);
|
||||
assert!(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn func_lambda_equivalency() {
|
||||
let comparator = "(def apply \"applicator\" (fn x) (fn x))";
|
||||
let lh_doc = "(apply car (1 2 3))";
|
||||
let rh_doc = "(apply (lambda (x) (car x)) (1 2 3))";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&lex(&comparator.to_string()).unwrap(), &mut syms).unwrap();
|
||||
assert_eq!(
|
||||
eval(&lex(&lh_doc.to_string()).unwrap(), &mut syms).unwrap(),
|
||||
eval(&lex(&rh_doc.to_string()).unwrap(), &mut syms).unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
283
core/tests/test_func.rs
Normal file
283
core/tests/test_func.rs
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
mod func_tests {
|
||||
use flesh::ast::lex;
|
||||
use flesh::ast::{Args, Ctr, Seg, Symbol, ValueType, Traceback};
|
||||
use flesh::ast::{SymTable, Type, UserFn, start_trace};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[test]
|
||||
fn decl_and_call_internal_func() {
|
||||
let mut syms = SymTable::new();
|
||||
let test_internal_func: Symbol = Symbol {
|
||||
name: String::from("test_func_in"),
|
||||
conditional_branches: false,
|
||||
docs: String::new(),
|
||||
args: Args::Strict(vec![Type::Bool]),
|
||||
value: ValueType::Internal(Rc::new(
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, Traceback> {
|
||||
let inner = a;
|
||||
let mut is_bool = false;
|
||||
if let Ctr::Bool(_) = *inner.car {
|
||||
is_bool = true;
|
||||
}
|
||||
Ok(Ctr::Bool(is_bool))
|
||||
},
|
||||
)),
|
||||
..Default::default()
|
||||
};
|
||||
let args = Seg::from(Box::new(Ctr::Bool(true)), Box::new(Ctr::None));
|
||||
syms.insert(String::from("test_func_in"), test_internal_func);
|
||||
if let Ctr::Bool(b) = *syms
|
||||
.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.unwrap()
|
||||
{
|
||||
assert!(b)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decl_and_call_external_func_singlet() {
|
||||
let mut syms = SymTable::new();
|
||||
let finner = lex(&"input".to_string()).unwrap();
|
||||
let test_external_func: Symbol = Symbol {
|
||||
name: String::from("echo"),
|
||||
conditional_branches: false,
|
||||
args: Args::Lazy(1),
|
||||
docs: String::new(),
|
||||
value: ValueType::FuncForm(UserFn {
|
||||
arg_syms: vec!["input".to_string()],
|
||||
ast: finner,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let args = Seg::from(
|
||||
Box::new(Ctr::String("test".to_string())),
|
||||
Box::new(Ctr::None),
|
||||
);
|
||||
|
||||
syms.insert(String::from("test_func_in"), test_external_func);
|
||||
if let Ctr::Bool(b) = *syms
|
||||
.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.unwrap()
|
||||
{
|
||||
assert!(b)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decl_and_call_external_func_multi_body() {
|
||||
let mut syms = SymTable::new();
|
||||
let finner = lex(&"input".to_string()).unwrap();
|
||||
let test_external_func: Symbol = Symbol {
|
||||
name: String::from("echo_2"),
|
||||
conditional_branches: false,
|
||||
args: Args::Lazy(1),
|
||||
docs: String::new(),
|
||||
value: ValueType::FuncForm(UserFn {
|
||||
arg_syms: vec!["input".to_string()],
|
||||
ast: finner,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let args = Seg::from(
|
||||
Box::new(Ctr::String("test".to_string())),
|
||||
Box::new(Ctr::None),
|
||||
);
|
||||
|
||||
syms.insert(String::from("echo_2"), test_external_func);
|
||||
assert_eq!(
|
||||
*syms
|
||||
.call_symbol(&"echo_2".to_string(), &args, true)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"\"test\"".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decl_and_call_func_with_nested_call() {
|
||||
let mut syms = SymTable::new();
|
||||
let inner_func: Symbol = Symbol {
|
||||
name: String::from("test_inner"),
|
||||
conditional_branches: false,
|
||||
args: Args::Strict(vec![Type::Bool]),
|
||||
docs: String::new(),
|
||||
value: ValueType::Internal(Rc::new(
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, Traceback> {
|
||||
let inner = a;
|
||||
if let Ctr::Bool(b) = *inner.car {
|
||||
if b {
|
||||
Ok(Ctr::String("test".to_string()))
|
||||
} else {
|
||||
Ok(Ctr::None)
|
||||
}
|
||||
} else {
|
||||
Err(start_trace(("", "not a bool".to_string()).into()))
|
||||
}
|
||||
},
|
||||
)),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let finner = lex(&"((test_inner true))".to_string()).unwrap();
|
||||
let outer_func: Symbol = Symbol {
|
||||
name: String::from("test_outer"),
|
||||
conditional_branches: false,
|
||||
args: Args::Lazy(1),
|
||||
docs: String::new(),
|
||||
value: ValueType::FuncForm(UserFn {
|
||||
arg_syms: vec!["input".to_string()],
|
||||
ast: finner,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let args = Seg::from(Box::new(Ctr::Bool(true)), Box::new(Ctr::None));
|
||||
syms.insert(String::from("test_inner"), inner_func);
|
||||
syms.insert(String::from("test_outer"), outer_func);
|
||||
assert_eq!(
|
||||
syms.call_symbol(&"test_outer".to_string(), &args, true)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"\"test\"".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arg_type_mismatch() {
|
||||
let mut syms = SymTable::new();
|
||||
let test_internal_func: Symbol = Symbol {
|
||||
name: String::from("test_func_in"),
|
||||
conditional_branches: false,
|
||||
args: Args::Strict(vec![Type::Bool]),
|
||||
docs: String::new(),
|
||||
value: ValueType::Internal(Rc::new(
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, Traceback> {
|
||||
let inner = a;
|
||||
let mut is_bool = false;
|
||||
if let Ctr::Bool(_) = *inner.car {
|
||||
is_bool = true;
|
||||
}
|
||||
Ok(Ctr::Bool(is_bool))
|
||||
},
|
||||
)),
|
||||
..Default::default()
|
||||
};
|
||||
let args = Seg::from(Box::new(Ctr::Integer(1)), Box::new(Ctr::None));
|
||||
|
||||
syms.insert(String::from("test_func_in"), test_internal_func);
|
||||
assert_eq!(
|
||||
syms.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.err()
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"arg 1 expected to be bool".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn too_many_args() {
|
||||
let mut syms = SymTable::new();
|
||||
let finner = lex(&"(input)".to_string()).unwrap();
|
||||
let test_external_func: Symbol = Symbol {
|
||||
name: String::from("echo"),
|
||||
conditional_branches: false,
|
||||
args: Args::Lazy(1),
|
||||
docs: String::new(),
|
||||
value: ValueType::FuncForm(UserFn {
|
||||
arg_syms: vec!["input".to_string()],
|
||||
ast: finner,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let args = Seg::from(
|
||||
Box::new(Ctr::String("test".to_string())),
|
||||
Box::new(Ctr::Seg(Seg::from_mono(Box::new(Ctr::Integer(1))))),
|
||||
);
|
||||
|
||||
syms.insert(String::from("test_func_in"), test_external_func);
|
||||
assert_eq!(
|
||||
syms.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.err()
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"expected 1 args. Got 2.".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn too_few_args() {
|
||||
let mut syms = SymTable::new();
|
||||
let finner = lex(&"(input)".to_string()).unwrap();
|
||||
let test_external_func: Symbol = Symbol {
|
||||
name: String::from("echo"),
|
||||
conditional_branches: false,
|
||||
args: Args::Lazy(1),
|
||||
docs: String::new(),
|
||||
value: ValueType::FuncForm(UserFn {
|
||||
arg_syms: vec!["input".to_string()],
|
||||
ast: finner,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let args = Seg::new();
|
||||
syms.insert(String::from("test_func_in"), test_external_func);
|
||||
assert_eq!(
|
||||
syms.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.err()
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"expected 1 args. Got 0.".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arg_cant_eval() {
|
||||
let mut syms = SymTable::new();
|
||||
let test_internal_func: Symbol = Symbol {
|
||||
name: String::from("test_func_in"),
|
||||
conditional_branches: false,
|
||||
args: Args::Strict(vec![Type::Bool]),
|
||||
docs: String::new(),
|
||||
value: ValueType::Internal(Rc::new(
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, Traceback> {
|
||||
let inner = a;
|
||||
let mut is_bool = false;
|
||||
if let Ctr::Bool(_) = *inner.car {
|
||||
is_bool = true;
|
||||
}
|
||||
Ok(Ctr::Bool(is_bool))
|
||||
},
|
||||
)),
|
||||
..Default::default()
|
||||
};
|
||||
let args = Seg::from(
|
||||
Box::new(Ctr::Symbol("undefined-symbol".to_string())),
|
||||
Box::new(Ctr::None),
|
||||
);
|
||||
|
||||
syms.insert(String::from("test_func_in"), test_internal_func);
|
||||
assert_eq!(
|
||||
syms.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.err()
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"(is an undefined symbol)".to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
111
core/tests/test_lex.rs
Normal file
111
core/tests/test_lex.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
mod lex_tests {
|
||||
use flesh::ast::lex;
|
||||
|
||||
#[test]
|
||||
fn test_lex_basic_pair() {
|
||||
let document = String::from("(hello \"world\")");
|
||||
assert_eq!(lex(&document).unwrap().to_string(), document);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lex_basic_list() {
|
||||
let document = String::from("(hello \"world\" 1 2 3)");
|
||||
assert_eq!(lex(&document).unwrap().to_string(), document);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bad_symbol() {
|
||||
let document = String::from("(as@dd)");
|
||||
let output: &str = "Problem lexing document: \"Unparsable token \\\"as@dd\\\" at char 7\"";
|
||||
assert_eq!(lex(&document).err().unwrap().0.first().unwrap().message, output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lex_complex_list() {
|
||||
let document = String::from("(hello \"world\" (1 2 (1 2 3)) 1 2 3)");
|
||||
assert_eq!(lex(&document).unwrap().to_string(), document);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_delim_in_str() {
|
||||
let document = String::from("(\"(\")");
|
||||
assert_eq!(lex(&document).unwrap().to_string(), document);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_comment_delim_in_str() {
|
||||
let document = String::from("(\"#\")");
|
||||
assert_eq!(lex(&document).unwrap().to_string(), document);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_string() {
|
||||
let document = String::from("(\"\")");
|
||||
assert_eq!(lex(&document).unwrap().to_string(), document);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unmatched_list_delim_flat() {
|
||||
let document = String::from("(one two");
|
||||
let output: &str = "Problem lexing document: \"Unmatched list delimiter in input\"";
|
||||
assert_eq!(lex(&document).err().unwrap().0.first().unwrap().message, output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unmatched_list_delim_complex() {
|
||||
let document = String::from("(one two (three)");
|
||||
let output: &str = "Problem lexing document: \"Unmatched list delimiter in input\"";
|
||||
assert_eq!(lex(&document).err().unwrap().0.first().unwrap().message, output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_comment_1() {
|
||||
let document = String::from("#!/bin/flesh\n(one two)");
|
||||
let output: &str = "(one two)";
|
||||
assert_eq!(lex(&document).unwrap().to_string(), output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_comment_2() {
|
||||
let document = String::from(";; big doc string\n(one two)");
|
||||
let output: &str = "(one two)";
|
||||
assert_eq!(lex(&document).unwrap().to_string(), output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_postline_comment_1() {
|
||||
let document =
|
||||
String::from("#!/bin/flesh\n((one two)# another doc comment\n(\"three\" four))");
|
||||
let output: &str = "((one two) (\"three\" four))";
|
||||
assert_eq!(lex(&document).unwrap().to_string(), output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_postline_comment_2() {
|
||||
let document =
|
||||
String::from("#!/bin/flesh\n((one two);;another doc comment\n(three four))");
|
||||
let output: &str = "((one two) (three four))";
|
||||
assert_eq!(lex(&document).unwrap().to_string(), output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inline_comment_1() {
|
||||
let document = String::from("#!/flesh/flesh\n((one two)\n# another comment\nthree)");
|
||||
let output: &str = "((one two) three)";
|
||||
assert_eq!(lex(&document).unwrap().to_string(), output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inline_comment_2() {
|
||||
let document = String::from("# head\n((one two)\n;; another comment\nthree)");
|
||||
let output: &str = "((one two) three)";
|
||||
assert_eq!(lex(&document).unwrap().to_string(), output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bad_token_list() {
|
||||
let document = String::from("(one t(wo)");
|
||||
let output: &str = "Problem lexing document: \"list started in middle of another token: t\"";
|
||||
assert_eq!(lex(&document).err().unwrap().0.first().unwrap().message, output.to_string(),);
|
||||
}
|
||||
}
|
||||
360
core/tests/test_lib_append.rs
Normal file
360
core/tests/test_lib_append.rs
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
mod append_lib_tests {
|
||||
use flesh::ast::{eval, lex, SymTable};
|
||||
use flesh::stdlib::static_stdlib;
|
||||
|
||||
#[test]
|
||||
fn test_cons_to_empty_list() {
|
||||
let document = "(cons () 1)";
|
||||
let result = "(1)";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_cons_to_empty_list() {
|
||||
let document = "(cons () 1 \"two\" 3.4)";
|
||||
let result = "(1 \"two\" 3.4)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cons_to_full_list() {
|
||||
let document = "(cons (1 2) 3)";
|
||||
let result = "(1 2 3)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mono_cons() {
|
||||
let document = "(cons)";
|
||||
let result = "(<nil>)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cons_no_list() {
|
||||
let document = "(cons \"test\" 1 2 3)";
|
||||
let result = "(\"test\" 1 2 3)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_len_empty() {
|
||||
let document = "(len ())";
|
||||
let result = "0";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_len_normal() {
|
||||
let document = "(len (1 2 3))";
|
||||
let result = "3";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_car_empty() {
|
||||
let document = "(car ())";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.err()
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"input is empty".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_car_normal() {
|
||||
let document = "(car (1 2 3))";
|
||||
let result = "1";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cdr_empty() {
|
||||
let document = "(cdr ())";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.err()
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"input is empty".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cdr_normal() {
|
||||
let document = "(cdr (1 2 3))";
|
||||
let result = "3";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pop() {
|
||||
let document = "(def test \"\" (pop (1 2 3)))";
|
||||
let check1 = "(car test)";
|
||||
let result1 = "1";
|
||||
let check2 = "(cdr test)";
|
||||
let result2 = "(2 3)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&lex(&document.to_string()).unwrap(), &mut syms).unwrap();
|
||||
let ch1 = lex(&check1.to_string()).unwrap();
|
||||
let ch2 = lex(&check2.to_string()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
*eval(&ch1, &mut syms).unwrap().to_string(),
|
||||
result1.to_string(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&ch2, &mut syms).unwrap().to_string(),
|
||||
result2.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pop_mono() {
|
||||
let document = "(def test \"\" (pop (1)))";
|
||||
let check1 = "(car test)";
|
||||
let result1 = "1";
|
||||
let check2 = "(cdr test)";
|
||||
let result2 = "(<nil>)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&lex(&document.to_string()).unwrap(), &mut syms).unwrap();
|
||||
let ch1 = lex(&check1.to_string()).unwrap();
|
||||
let ch2 = lex(&check2.to_string()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
*eval(&ch1, &mut syms).unwrap().to_string(),
|
||||
result1.to_string(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&ch2, &mut syms).unwrap().to_string(),
|
||||
result2.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dq() {
|
||||
let document = "(def test \"\" (dq (1 2 3)))";
|
||||
let check1 = "(car test)";
|
||||
let result1 = "3";
|
||||
let check2 = "(cdr test)";
|
||||
let result2 = "(1 2)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&lex(&document.to_string()).unwrap(), &mut syms).unwrap();
|
||||
let ch1 = lex(&check1.to_string()).unwrap();
|
||||
let ch2 = lex(&check2.to_string()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
*eval(&ch1, &mut syms).unwrap().to_string(),
|
||||
result1.to_string(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&ch2, &mut syms).unwrap().to_string(),
|
||||
result2.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dq_mono() {
|
||||
let document = "(def test \"\" (dq (1)))";
|
||||
let check1 = "(car test)";
|
||||
let result1 = "1";
|
||||
let check2 = "(cdr test)";
|
||||
let result2 = "(<nil>)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&lex(&document.to_string()).unwrap(), &mut syms).unwrap();
|
||||
let ch1 = lex(&check1.to_string()).unwrap();
|
||||
let ch2 = lex(&check2.to_string()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
*eval(&ch1, &mut syms).unwrap().to_string(),
|
||||
result1.to_string(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&ch2, &mut syms).unwrap().to_string(),
|
||||
result2.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reverse() {
|
||||
let document = "(reverse (\"test\" 1 2 3))";
|
||||
let result = "(3 2 1 \"test\")";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reverse_mono() {
|
||||
let document = "(reverse (\"test\"))";
|
||||
let result = "(\"test\")";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reverse_nil() {
|
||||
let document = "(reverse ())";
|
||||
let result = "(<nil>)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_islist_t() {
|
||||
let document = "(list? ())";
|
||||
let result = "true";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_islist_f() {
|
||||
let document = "(list? 1223)";
|
||||
let result = "false";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
397
core/tests/test_lib_bools.rs
Normal file
397
core/tests/test_lib_bools.rs
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
mod bool_lib_tests {
|
||||
use flesh::ast::{eval, lex, Ctr, SymTable};
|
||||
use flesh::stdlib::static_stdlib;
|
||||
|
||||
#[test]
|
||||
fn test_and_true_chain() {
|
||||
let document = "(and true true true true true)";
|
||||
let result = "true";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_and_true_chain_with_false() {
|
||||
let document = "(and true true false true true)";
|
||||
let result = "false";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_and_false_chain() {
|
||||
let document = "(and false false false false false)";
|
||||
let result = "false";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_or_true_chain() {
|
||||
let document = "(or true true true true true)";
|
||||
let result = "true";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_or_true_chain_with_false() {
|
||||
let document = "(or true true false true true)";
|
||||
let result = "true";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_or_false_chain() {
|
||||
let document = "(or false false false false false)";
|
||||
let result = "false";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not() {
|
||||
let document = "(not true)";
|
||||
let result = "false";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_toggle_a_bool() {
|
||||
let document = "(def tester \"\" true)";
|
||||
let change = "(toggle tester)";
|
||||
let check = "(tester)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let change_tree = lex(&change.to_string()).unwrap();
|
||||
let check_tree = lex(&check.to_string()).unwrap();
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
eval(&change_tree, &mut syms).unwrap();
|
||||
|
||||
if let Ctr::Seg(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
if let Ctr::Bool(ref b) = *s.car {
|
||||
assert_eq!(false, *b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
|
||||
eval(&change_tree, &mut syms).unwrap();
|
||||
if let Ctr::Seg(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
if let Ctr::Bool(ref b) = *s.car {
|
||||
assert_eq!(true, *b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_toggle_errors_dont_lose_vars() {
|
||||
let document = "(def tester \"\" \"oops\")";
|
||||
let change = "(toggle tester)";
|
||||
let check = "(tester)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let change_tree = lex(&change.to_string()).unwrap();
|
||||
let check_tree = lex(&check.to_string()).unwrap();
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s.0.first().unwrap().message,
|
||||
"can only toggle a boolean".to_string()
|
||||
);
|
||||
let intermediate = *eval(&check_tree, &mut syms).unwrap();
|
||||
if let Ctr::Seg(ref s) = intermediate {
|
||||
assert_eq!(s.to_string(), "(\"oops\")".to_string());
|
||||
} else {
|
||||
eprintln!("did not expect: {}", intermediate);
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
eprintln!("shouldn't have succeeded!");
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_toggle_errors_dont_lose_funcs() {
|
||||
let document = "(def tester \"\" (oops) oops)";
|
||||
let change = "(toggle tester)";
|
||||
let check = "(tester \"1\")";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let change_tree = lex(&change.to_string()).unwrap();
|
||||
let check_tree = lex(&check.to_string()).unwrap();
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s.0.first().unwrap().message,
|
||||
"cannot toggle a function".to_string()
|
||||
);
|
||||
if let Ctr::String(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
assert_eq!(*s, "1".to_string());
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
eprintln!("shouldn't have succeeded!");
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iseq_basic_t() {
|
||||
let document = "(eq? true true)";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iseq_basic_f() {
|
||||
let document = "(eq? true false)";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(!b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iseq_basic_f_mixed_data() {
|
||||
let document = "(eq? true 1)";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(!b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iseq_long_f() {
|
||||
let document = "(eq? true true true true true false)";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(!b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iseq_long_t_str() {
|
||||
let document = "(eq? \"1\" \"1\" \"1\" \"1\" \"1\" \"1\" \"1\" \"1\" \"1\" \"1\" \"1\")";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iseq_t_mixed_numerals() {
|
||||
let document = "(eq? 1 1.0)";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iseq_f_wrong_type() {
|
||||
let document = "(eq? 1 \"1\")";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(!b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolcast_str_t() {
|
||||
let document = "(bool \"true\")";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolcast_str_f() {
|
||||
let document = "(bool \"false\")";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(!b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolcast_int_t() {
|
||||
let document = "(bool 0)";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolcast_int_f() {
|
||||
let document = "(bool 12)";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(!b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolcast_float_t() {
|
||||
let document = "(bool 0.0)";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_boolcast_float_f() {
|
||||
let document = "(bool 1.2)";
|
||||
let test = lex(&document.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() {
|
||||
assert!(!b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
245
core/tests/test_lib_control.rs
Normal file
245
core/tests/test_lib_control.rs
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
mod control_lib_tests {
|
||||
use flesh::ast::{eval, lex, SymTable};
|
||||
use flesh::stdlib::static_stdlib;
|
||||
|
||||
#[test]
|
||||
fn test_assert_t() {
|
||||
let document = "(assert true)";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
eval(&lex(&document.to_string()).unwrap(), &mut syms).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assert_f() {
|
||||
let document = "(assert false)";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert!(eval(&lex(&document.to_string()).unwrap(), &mut syms).is_err())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_if_first_case_singlet() {
|
||||
let document = "(if true 1 2)";
|
||||
let result = 1;
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_if_second_case_singlet() {
|
||||
let document = "(if false 1 2)";
|
||||
let result = 2;
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complex_case_call() {
|
||||
let document = "(if true (cons () 1) 2)";
|
||||
let result = "(1)";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_let_multiphase_locals() {
|
||||
let document = "(let (
|
||||
(temp \"1\")
|
||||
(temp (cons () temp \"2\")))
|
||||
temp)";
|
||||
let result = "(\"1\" \"2\")";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_let_def_escapes_locals() {
|
||||
let document1 = "(let (
|
||||
(temp \"hello\")
|
||||
(temp (concat temp \" \" \"world\")))
|
||||
(def global \"\" temp))";
|
||||
let document2 = "global";
|
||||
let result = "(\"hello world\")";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
eval(&lex(&document1.to_string()).unwrap(), &mut syms).unwrap();
|
||||
assert_eq!(
|
||||
*eval(&lex(&document2.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_let_multibody_evals() {
|
||||
let document = "(let ((temp \"1\")) temp (cons () temp \"2\"))";
|
||||
let result = "(\"1\" \"2\")";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_let_multiphase_local_multibody_evals() {
|
||||
let document = "(let (
|
||||
(temp \"1\")
|
||||
(temp (cons () temp \"2\")))
|
||||
(echo \"first body\")
|
||||
(cons temp \"3\"))";
|
||||
|
||||
let result = "(\"1\" \"2\" \"3\")";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_while_basic() {
|
||||
let switch_dec = "(def switch \"\" true)";
|
||||
// if prev is true, switch looped once and only once
|
||||
// else prev will have a problematic type
|
||||
let while_loop = "
|
||||
(while switch
|
||||
(def prev \"\" switch)
|
||||
(toggle switch)
|
||||
(if switch
|
||||
(def \"\" prev)
|
||||
()))";
|
||||
let test_check = "prev";
|
||||
|
||||
let switch_tree = lex(&switch_dec.to_string()).unwrap();
|
||||
let while_tree = lex(&while_loop.to_string()).unwrap();
|
||||
let check_tree = lex(&test_check.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&switch_tree, &mut syms).unwrap();
|
||||
eval(&while_tree, &mut syms).unwrap();
|
||||
eval(&check_tree, &mut syms).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_while_eval_cond() {
|
||||
let switch_dec = "(def switch \"\" true)";
|
||||
// if prev is true, switch looped once and only once
|
||||
// else prev will have a problematic type
|
||||
let while_loop = "
|
||||
(while (or switch switch)
|
||||
(def prev \"\" switch)
|
||||
(toggle switch)
|
||||
(if switch
|
||||
(def \"\" prev)
|
||||
()))";
|
||||
let test_check = "prev";
|
||||
|
||||
let switch_tree = lex(&switch_dec.to_string()).unwrap();
|
||||
let while_tree = lex(&while_loop.to_string()).unwrap();
|
||||
let check_tree = lex(&test_check.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&switch_tree, &mut syms).unwrap();
|
||||
eval(&while_tree, &mut syms).unwrap();
|
||||
eval(&check_tree, &mut syms).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_while_2_iter() {
|
||||
let additional = "(def sw1 \"\" true)";
|
||||
let switch_dec = "(def sw2 \"\" true)";
|
||||
// while should loop twice and define result
|
||||
let while_loop = "
|
||||
(while sw1
|
||||
(toggle sw2)
|
||||
(if (and sw1 sw2)
|
||||
(def sw1 \"\" false)
|
||||
(def result \"\" \"yay\")))";
|
||||
let test_check = "result";
|
||||
|
||||
let another_tree = lex(&additional.to_string()).unwrap();
|
||||
let switch_tree = lex(&switch_dec.to_string()).unwrap();
|
||||
let while_tree = lex(&while_loop.to_string()).unwrap();
|
||||
let check_tree = lex(&test_check.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&another_tree, &mut syms).unwrap();
|
||||
eval(&switch_tree, &mut syms).unwrap();
|
||||
eval(&while_tree, &mut syms).unwrap();
|
||||
eval(&check_tree, &mut syms).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_circuit_basic() {
|
||||
let document = "(if (circuit true (and true true) 0 true) (def result \"\" \"passed\") ())";
|
||||
let test = "result";
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let test_tree = lex(&test.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
let res = eval(&test_tree, &mut syms);
|
||||
res.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "implicit-load"))]
|
||||
#[test]
|
||||
fn test_circuit_fail() {
|
||||
let document = "(if (circuit true (and false true) true) (def result \"\" \"passed\") ())";
|
||||
let test = "result";
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let test_tree = lex(&test.to_string()).unwrap();
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
assert_eq!(
|
||||
eval(&test_tree, &mut syms).err().unwrap().0.first().unwrap().message,
|
||||
"(is an undefined symbol)".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
353
core/tests/test_lib_decl.rs
Normal file
353
core/tests/test_lib_decl.rs
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
mod decl_lib_tests {
|
||||
use flesh::ast::{eval, lex, Ctr, SymTable};
|
||||
use flesh::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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "implicit-load"))]
|
||||
#[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);
|
||||
|
||||
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.0.first().unwrap().message,
|
||||
"(is an undefined symbol)".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 ref \"my test var\" \"2\")";
|
||||
let test = "(test)";
|
||||
let res1 = "(1)";
|
||||
let doc4 = "(def (eval ref) \"my test var\" \"2\")";
|
||||
let res2 = "(\"2\")";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
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 r1 = *eval(&lex(&test.to_string()).unwrap(), &mut syms).unwrap();
|
||||
assert_eq!(r1.to_string(), res1);
|
||||
eval(&lex(&doc2.to_string()).unwrap(), &mut syms).unwrap();
|
||||
eval(&lex(&doc4.to_string()).unwrap(), &mut syms).unwrap();
|
||||
let r2 = *eval(&lex(&test.to_string()).unwrap(), &mut syms).unwrap();
|
||||
assert_eq!(r2.to_string(), res2);
|
||||
}
|
||||
|
||||
#[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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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_arg_call() {
|
||||
let document = "(let (())
|
||||
(def appl \"\" (func item) (func item))
|
||||
(def adder \"my adder\" (lambda (x) (add x 1)))
|
||||
(appl adder 2))";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let it = *eval(
|
||||
&lex(&document.to_string()).unwrap(),
|
||||
&mut syms).unwrap();
|
||||
if let Ctr::Integer(i) = it {
|
||||
assert_eq!(i, 3)
|
||||
} else {
|
||||
println!("bad result: {}", it);
|
||||
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);
|
||||
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!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_eval_quote() {
|
||||
let doc = "(eval (quote (add 1 1)))";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&doc.to_string()).unwrap(), &mut syms).unwrap().to_string(),
|
||||
2.to_string()
|
||||
)
|
||||
}
|
||||
}
|
||||
76
core/tests/test_lib_file.rs
Normal file
76
core/tests/test_lib_file.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
mod file_lib_tests {
|
||||
use flesh::ast::{eval, lex, SymTable};
|
||||
use flesh::stdlib::static_stdlib;
|
||||
|
||||
#[test]
|
||||
fn test_fexists() {
|
||||
let document = "(exists? \"/tmp\")";
|
||||
let result = "true";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fexists_doesnt() {
|
||||
let document = "(exists? \"cargo.timtam\")";
|
||||
let result = "false";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_file() {
|
||||
let document = "
|
||||
(let ((s \"test\")
|
||||
(t \"/tmp/flesh-lib-test-file-1\"))
|
||||
(write-file t s)
|
||||
(echo (read-file t))
|
||||
(eq? (read-file t) s))";
|
||||
let result = "true";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_append_file() {
|
||||
let document = "
|
||||
(let ((s \"test\")
|
||||
(t \"/tmp/flesh-lib-test-file-2\"))
|
||||
(write-file t s)
|
||||
(append-file t s)
|
||||
(eq? (read-file t)
|
||||
(concat s s)))";
|
||||
let result = "true";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
774
core/tests/test_lib_math.rs
Normal file
774
core/tests/test_lib_math.rs
Normal file
|
|
@ -0,0 +1,774 @@
|
|||
mod math_lib_tests {
|
||||
use flesh::ast::{eval, lex, Ctr, SymTable};
|
||||
use flesh::stdlib::static_stdlib;
|
||||
|
||||
#[test]
|
||||
fn test_add_chain() {
|
||||
let document = "(add 1 2 3 4)";
|
||||
let result = "10";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_chain_mixed() {
|
||||
let document = "(add 1 2.2 3 4)";
|
||||
let result = "10.2";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mul_chain() {
|
||||
let document = "(mul 1 2 3 4)";
|
||||
let result = "24";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sub_chain() {
|
||||
let document = "(sub 1 2.2 3 4)";
|
||||
let result = "-8.2";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_div() {
|
||||
let document = "(div 10 5)";
|
||||
let result = "2";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_to_int() {
|
||||
let document = "(int 10.5)";
|
||||
let result = "10";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_to_int() {
|
||||
let document = "(int \"10\")";
|
||||
let result = "10";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_int_to_float() {
|
||||
let document = "(float 10)";
|
||||
let result = "10";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_to_float() {
|
||||
let document = "(float \"10.3\")";
|
||||
let result = "10.3";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ii_exp() {
|
||||
let document = "(exp 7 20)";
|
||||
let result = 7i128.pow(20);
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_if_exp() {
|
||||
let document = "(exp 1 10.2)";
|
||||
let result = f64::powf(1f64, 10.2);
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fi_exp() {
|
||||
let document = "(exp 1.2 5)";
|
||||
let result = f64::powf(1.2, 5f64);
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
format!("{:.5}", result),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ff_exp() {
|
||||
let document = "(exp 1.3 1.5)";
|
||||
let result = f64::powf(1.3, 1.5);
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ii_mod() {
|
||||
let document = "(def test \"\" (mod 7 3))";
|
||||
let check1 = "(car test)";
|
||||
let result1 = "2";
|
||||
let check2 = "(cdr test)";
|
||||
let result2 = "1";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let _ = *eval(&lex(&document.to_string()).unwrap(), &mut syms).unwrap();
|
||||
assert_eq!(
|
||||
*eval(&lex(&check1.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result1.to_string(),
|
||||
);
|
||||
assert_eq!(
|
||||
*eval(&lex(&check2.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result2.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_if_mod() {
|
||||
let document = "(def test \"\" (mod 7 3.3))";
|
||||
let check1 = "(car test)";
|
||||
let result1 = "2";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let _ = *eval(&lex(&document.to_string()).unwrap(), &mut syms).unwrap();
|
||||
assert_eq!(
|
||||
*eval(&lex(&check1.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result1.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fi_mod() {
|
||||
let document = "(def test \"\" (mod 7.2 2))";
|
||||
let check1 = "(car test)";
|
||||
let result1 = "3";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let _ = *eval(&lex(&document.to_string()).unwrap(), &mut syms).unwrap();
|
||||
assert_eq!(
|
||||
*eval(&lex(&check1.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result1.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ff_mod() {
|
||||
let document = "(def test \"\" (mod 7.2 3.3))";
|
||||
let check1 = "(car test)";
|
||||
let result1 = "2";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let _ = *eval(&lex(&document.to_string()).unwrap(), &mut syms).unwrap();
|
||||
assert_eq!(
|
||||
*eval(&lex(&check1.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result1.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ii_gt_t() {
|
||||
let document = "(gt? 4 3)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ii_gt_f() {
|
||||
let document = "(gt? 2 3)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_if_gt_t() {
|
||||
let document = "(gt? 4 3.1)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_if_gt_f() {
|
||||
let document = "(gt? 3 3.1)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fi_gt_t() {
|
||||
let document = "(gt? 4.1 4)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fi_gt_f() {
|
||||
let document = "(gt? 2.1 3)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ff_gt_t() {
|
||||
let document = "(gt? 3.2 3.1)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ff_gt_f() {
|
||||
let document = "(gt? 3.1 3.2)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ii_lt_f() {
|
||||
let document = "(lt? 4 3)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ii_lt_t() {
|
||||
let document = "(lt? 2 3)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_if_lt_f() {
|
||||
let document = "(lt? 4 3.1)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_if_lt_t() {
|
||||
let document = "(lt? 3 3.1)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fi_lt_f() {
|
||||
let document = "(lt? 4.1 4)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fi_lt_t() {
|
||||
let document = "(lt? 2.1 3)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ff_lt_f() {
|
||||
let document = "(lt? 3.2 3.1)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ff_lt_ft() {
|
||||
let document = "(lt? 3.1 3.2)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lte() {
|
||||
let document = "(lte? 3.2 3.1)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lte_e() {
|
||||
let document = "(lte? 3.2 3.2)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gte() {
|
||||
let document = "(gte? 3.1 3.2)";
|
||||
let result = false;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gte_e() {
|
||||
let document = "(gte? 3.1 3.1)";
|
||||
let result = true;
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inc() {
|
||||
let document = "(def tester \"\" 1)";
|
||||
let change = "(inc tester)";
|
||||
let check = "(tester)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let change_tree = lex(&change.to_string()).unwrap();
|
||||
let check_tree = lex(&check.to_string()).unwrap();
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
eval(&change_tree, &mut syms).unwrap();
|
||||
|
||||
if let Ctr::Seg(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
if let Ctr::Integer(ref b) = *s.car {
|
||||
assert_eq!(2, *b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
|
||||
eval(&change_tree, &mut syms).unwrap();
|
||||
if let Ctr::Seg(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
if let Ctr::Integer(ref b) = *s.car {
|
||||
assert_eq!(3, *b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inc_errors_dont_lose_vars() {
|
||||
let document = "(def tester \"\" \"oops\")";
|
||||
let change = "(inc tester)";
|
||||
let check = "(tester)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let change_tree = lex(&change.to_string()).unwrap();
|
||||
let check_tree = lex(&check.to_string()).unwrap();
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s.0.first().unwrap().message,
|
||||
"expected tester to be an integer".to_string()
|
||||
);
|
||||
let intermediate = *eval(&check_tree, &mut syms).unwrap();
|
||||
if let Ctr::Seg(ref s) = intermediate {
|
||||
assert_eq!(s.to_string(), "(\"oops\")".to_string());
|
||||
} else {
|
||||
eprintln!("did not expect: {}", intermediate);
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
eprintln!("shouldn't have succeeded!");
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inc_errors_dont_lose_funcs() {
|
||||
let document = "(def tester \"\" (oops) oops)";
|
||||
let change = "(inc tester)";
|
||||
let check = "(tester \"1\")";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let change_tree = lex(&change.to_string()).unwrap();
|
||||
let check_tree = lex(&check.to_string()).unwrap();
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s.0.first().unwrap().message,
|
||||
"expected tester to be an integer".to_string()
|
||||
);
|
||||
if let Ctr::String(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
assert_eq!(*s, "1".to_string());
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
eprintln!("shouldn't have succeeded!");
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec() {
|
||||
let document = "(def tester \"\" 1)";
|
||||
let change = "(dec tester)";
|
||||
let check = "(tester)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let change_tree = lex(&change.to_string()).unwrap();
|
||||
let check_tree = lex(&check.to_string()).unwrap();
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
eval(&change_tree, &mut syms).unwrap();
|
||||
|
||||
if let Ctr::Seg(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
if let Ctr::Integer(ref b) = *s.car {
|
||||
assert_eq!(0, *b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
|
||||
eval(&change_tree, &mut syms).unwrap();
|
||||
if let Ctr::Seg(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
if let Ctr::Integer(ref b) = *s.car {
|
||||
assert_eq!(-1, *b)
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec_errors_dont_lose_vars() {
|
||||
let document = "(def tester \"\" \"oops\")";
|
||||
let change = "(dec tester)";
|
||||
let check = "(tester)";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let change_tree = lex(&change.to_string()).unwrap();
|
||||
let check_tree = lex(&check.to_string()).unwrap();
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s.0.first().unwrap().message,
|
||||
"expected tester to be an integer".to_string()
|
||||
);
|
||||
let intermediate = *eval(&check_tree, &mut syms).unwrap();
|
||||
if let Ctr::Seg(ref s) = intermediate {
|
||||
assert_eq!(s.to_string(), "(\"oops\")".to_string());
|
||||
} else {
|
||||
eprintln!("did not expect: {}", intermediate);
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
eprintln!("shouldn't have succeeded!");
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec_errors_dont_lose_funcs() {
|
||||
let document = "(def tester \"\" (oops) oops)";
|
||||
let change = "(dec tester)";
|
||||
let check = "(tester \"1\")";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
|
||||
let doc_tree = lex(&document.to_string()).unwrap();
|
||||
let change_tree = lex(&change.to_string()).unwrap();
|
||||
let check_tree = lex(&check.to_string()).unwrap();
|
||||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s.0.first().unwrap().message,
|
||||
"expected tester to be an integer".to_string()
|
||||
);
|
||||
if let Ctr::String(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
assert_eq!(*s, "1".to_string());
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
} else {
|
||||
eprintln!("shouldn't have succeeded!");
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
313
core/tests/test_lib_str.rs
Normal file
313
core/tests/test_lib_str.rs
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
mod str_lib_tests {
|
||||
use flesh::ast::{eval, lex, SymTable};
|
||||
use flesh::stdlib::static_stdlib;
|
||||
|
||||
#[test]
|
||||
fn test_simple_concat() {
|
||||
let document = "(concat \"test\")";
|
||||
let result = "\"test\"";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_poly_concat() {
|
||||
let document = "(concat \"test\" 1 2 3)";
|
||||
let result = "\"test123\"";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_concat() {
|
||||
let document = "(concat)";
|
||||
let result = "\"\"";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strlen_str() {
|
||||
let document = "(strlen \"test\")";
|
||||
let result = 4;
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strlen_int() {
|
||||
let document = "(strlen 1000)";
|
||||
let result = 4;
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strlen_float() {
|
||||
let document = "(strlen 10.2)";
|
||||
let result = 4;
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strlen_seg() {
|
||||
let document = "(strlen (1 2 3))";
|
||||
let result = 7;
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strlen_bool() {
|
||||
let document = "(strlen true)";
|
||||
let result = 4;
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strcast_i() {
|
||||
let document = "(string 4)";
|
||||
let result = "\"4\"";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strcast_seg() {
|
||||
let document = "(string (1 2 3))";
|
||||
let result = "\"(1 2 3)\"";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains() {
|
||||
let document = "(substr? \"bigger\" \"ger\")";
|
||||
let result = "true";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_doesnt_contain() {
|
||||
let document = "(substr? \"smaller\" \"ger\")";
|
||||
let result = "false";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split() {
|
||||
let document = "(split \"one.two.three\" \".\")";
|
||||
let result = "(\"one\" \"two\" \"three\")";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_big_delim() {
|
||||
let document = "(split \"one:d:two:d:three\" \":d:\")";
|
||||
let result = "(\"one\" \"two\" \"three\")";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_splitnt() {
|
||||
let document = "(split \"one.two.three\" \"-\")";
|
||||
let result = "(\"one.two.three\")";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_substr_valid() {
|
||||
let document = "(substr \"test\" 0 4)";
|
||||
let result = "\"test\"";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
assert_eq!(
|
||||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
result.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_substr_start_neg() {
|
||||
let document = "(substr \"test\" -1 3)";
|
||||
let result = "start index cannot be negative";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let doc_res= eval(&lex(&document.to_string()).unwrap(), &mut syms);
|
||||
if let Err(e) = doc_res {
|
||||
assert_eq!(
|
||||
e.0.first().unwrap().message,
|
||||
result.to_string(),
|
||||
);
|
||||
} else {
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_substr_end_neg() {
|
||||
let document = "(substr \"test\" 1 -3)";
|
||||
let result = "end index cannot be negative";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let doc_res= eval(&lex(&document.to_string()).unwrap(), &mut syms);
|
||||
if let Err(e) = doc_res {
|
||||
assert_eq!(
|
||||
e.0.first().unwrap().message,
|
||||
result.to_string(),
|
||||
);
|
||||
} else {
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_substr_start_out_of_bounds() {
|
||||
let document = "(substr \"test\" 5 3)";
|
||||
let result = "start index larger than source string";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let doc_res= eval(&lex(&document.to_string()).unwrap(), &mut syms);
|
||||
if let Err(e) = doc_res {
|
||||
assert_eq!(
|
||||
e.0.first().unwrap().message,
|
||||
result.to_string(),
|
||||
);
|
||||
} else {
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_substr_end_out_of_bounds() {
|
||||
let document = "(substr \"test\" 1 5)";
|
||||
let result = "end index larger than source string";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let doc_res= eval(&lex(&document.to_string()).unwrap(), &mut syms);
|
||||
if let Err(e) = doc_res {
|
||||
assert_eq!(
|
||||
e.0.first().unwrap().message,
|
||||
result.to_string(),
|
||||
);
|
||||
} else {
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_substr_index_order() {
|
||||
let document = "(substr \"test\" 3 2)";
|
||||
let result = "end index must be larger than start index";
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
let doc_res= eval(&lex(&document.to_string()).unwrap(), &mut syms);
|
||||
if let Err(e) = doc_res {
|
||||
assert_eq!(
|
||||
e.0.first().unwrap().message,
|
||||
result.to_string(),
|
||||
);
|
||||
} else {
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue