From 640a53cad82ca07c2281ffabd8f9918afccba873 Mon Sep 17 00:00:00 2001 From: Ava Hahn Date: Sat, 11 Mar 2023 22:04:46 -0800 Subject: [PATCH] better eval and test for eval,quote --- Readme.org | 4 ---- src/stl.rs | 22 ++++++++++++++++++++++ src/stl/decl.rs | 22 ++++++++++++++++++---- tests/test_vars.rs | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 8 deletions(-) diff --git a/Readme.org b/Readme.org index d1f8514..71d24ba 100644 --- a/Readme.org +++ b/Readme.org @@ -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 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 Lambda hack BAD IDEAS diff --git a/src/stl.rs b/src/stl.rs index 39bd96e..d72de59 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -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(()) } diff --git a/src/stl/decl.rs b/src/stl/decl.rs index 37ec731..452860b 100644 --- a/src/stl/decl.rs +++ b/src/stl/decl.rs @@ -26,17 +26,31 @@ pub fn quote_callback(ast: &Seg, _syms: &mut SymTable) -> Result { if ast.len() > 1 { Err("do not quote more than one thing at a time".to_string()) } 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 { 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 { - 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()) + } } } diff --git a/tests/test_vars.rs b/tests/test_vars.rs index 818b108..47a8d76 100644 --- a/tests/test_vars.rs +++ b/tests/test_vars.rs @@ -265,4 +265,36 @@ mod var_lib_tests { eval(&env_tree, &mut syms).unwrap(); eval(&tst_tree, &mut syms).unwrap(); } + + #[test] + fn test_quote() { + let document = "(quote (add 1 2))"; + let result = "(add 1 2)"; + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(&mut syms).unwrap(); + assert_eq!( + *eval(&lex(&document.to_string()).unwrap(), &mut syms) + .unwrap() + .to_string(), + result.to_string(), + ); + } + + #[test] + fn test_eval() { + let document = " + (let ((stored-tree (quote (add 1 2)))) + (eval stored-tree)))"; + let result = "3"; + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(&mut syms).unwrap(); + assert_eq!( + *eval(&lex(&document.to_string()).unwrap(), &mut syms) + .unwrap() + .to_string(), + result.to_string(), + ); + } }