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:
Ava Apples Affine 2024-07-10 13:22:28 -07:00
parent aa56570d7d
commit 6d2925984f
44 changed files with 967 additions and 779 deletions

113
core/tests/test_eval.rs Normal file
View 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
View 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
View 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(),);
}
}

View 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(),
);
}
}

View 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!()
}
}
}

View 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
View 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()
)
}
}

View 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
View 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
View 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);
}
}
}