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
|
|
@ -1,283 +0,0 @@
|
|||
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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue