better eval and test for eval,quote

This commit is contained in:
Ava Apples Affine 2023-03-11 22:04:46 -08:00
parent 6daf0867df
commit 640a53cad8
Signed by: affine
GPG key ID: 3A4645B8CF806069
4 changed files with 72 additions and 8 deletions

View file

@ -301,10 +301,6 @@ This contains any executable target of this project. Notably the main shell file
Note: this section will not show the status of each item unless you are viewing it with a proper orgmode viewer. Note: this section will not show the status of each item unless you are viewing it with a proper orgmode viewer.
Note: this section only tracks the state of incomplete TODO items. Having everything on here would be cluttered. Note: this section only tracks the state of incomplete TODO items. Having everything on here would be cluttered.
*** TODO Quote function
(just needs tests and stl entries)
*** TODO Eval function
(just needs tests and stl entries)
*** TODO list contains via circuit *** TODO list contains via circuit
*** TODO Lambda hack *** TODO Lambda hack
BAD IDEAS BAD IDEAS

View file

@ -470,6 +470,28 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> {
}, },
); );
syms.insert(
"quote".to_string(),
Symbol {
name: String::from("quote"),
args: Args::Lazy(1),
conditional_branches: true,
docs: decl::QUOTE_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(decl::quote_callback)),
},
);
syms.insert(
"eval".to_string(),
Symbol {
name: String::from("eval"),
args: Args::Lazy(1),
conditional_branches: true,
docs: decl::EVAL_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(decl::eval_callback)),
},
);
Ok(()) Ok(())
} }

View file

@ -26,17 +26,31 @@ pub fn quote_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
if ast.len() > 1 { if ast.len() > 1 {
Err("do not quote more than one thing at a time".to_string()) Err("do not quote more than one thing at a time".to_string())
} else { } else {
Ok(Ctr::Seg(ast.clone())) Ok(*ast.car.clone())
} }
} }
pub const EVAL_DOCSTRING: &str = "takes an unevaluated argument and evaluates it."; pub const EVAL_DOCSTRING: &str = "takes an unevaluated argument and evaluates it.
Specifically, does one pass of the tree simplification algorithm.
If you have a variable referencing another variable you will get the
referenced variable.";
pub fn eval_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> { pub fn eval_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
if ast.len() > 1 { if ast.len() > 1 {
Err("do not quote more than one thing at a time".to_string()) Err("do not eval more than one thing at a time".to_string())
} else { } else {
Ok(*eval(ast, syms)?.clone()) match *ast.car {
Ctr::Seg(ref s) => Ok(*eval(s, syms)?.clone()),
Ctr::Symbol(ref sym) => {
let intermediate = syms.call_symbol(sym, &Seg::new(), true)?;
if let Ctr::Seg(ref s) = *intermediate {
Ok(*eval(s, syms)?.clone())
} else {
Ok(*intermediate)
}
},
_ => Ok(*ast.car.clone())
}
} }
} }

View file

@ -265,4 +265,36 @@ mod var_lib_tests {
eval(&env_tree, &mut syms).unwrap(); eval(&env_tree, &mut syms).unwrap();
eval(&tst_tree, &mut syms).unwrap(); eval(&tst_tree, &mut syms).unwrap();
} }
#[test]
fn test_quote() {
let document = "(quote (add 1 2))";
let result = "(add 1 2)";
let mut syms = SymTable::new();
static_stdlib(&mut syms).unwrap();
dynamic_stdlib(&mut syms).unwrap();
assert_eq!(
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
.unwrap()
.to_string(),
result.to_string(),
);
}
#[test]
fn test_eval() {
let document = "
(let ((stored-tree (quote (add 1 2))))
(eval stored-tree)))";
let result = "3";
let mut syms = SymTable::new();
static_stdlib(&mut syms).unwrap();
dynamic_stdlib(&mut syms).unwrap();
assert_eq!(
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
.unwrap()
.to_string(),
result.to_string(),
);
}
} }