simplify func return type, complete eval and process logic

This commit is contained in:
Aidan 2021-06-05 01:14:38 -07:00
parent 0adda0109c
commit 4712d5466c
No known key found for this signature in database
GPG key ID: 327711E983899316
3 changed files with 49 additions and 24 deletions

View file

@ -60,10 +60,11 @@ fn eval_inner(
funcs.clone(), funcs.clone(),
sym_loose, sym_loose,
first_item, first_item,
true,
mret.cdr mret.cdr
) { ) {
Ok(ctr) => { Ok(ctr) => {
mret.car = ctr mret.car = ctr;
}, },
Err(err) => { Err(err) => {
return Err(err) return Err(err)
@ -76,15 +77,18 @@ fn eval_inner(
funcs.clone(), funcs.clone(),
sym_loose, sym_loose,
false, false,
RefCell::new(Rc::clone(Ctr::None)) false,
Ctr::None
) { ) {
Ok(ctr) => { Ok(ctr) => {
mret.cdr = ctr mret.cdr = ctr;
}, },
Err(err) => { Err(err) => {
return Err(err) return Err(err)
} }
} }
return Ok(ret)
} }
fn process_ctr( fn process_ctr(
@ -93,7 +97,8 @@ fn process_ctr(
funcs: Rc<RefCell<FTable>>, funcs: Rc<RefCell<FTable>>,
sym_loose: bool, sym_loose: bool,
first_item: bool, first_item: bool,
rest: Ast is_car: bool,
rest: Ctr
) -> Result<Ctr, String> { ) -> Result<Ctr, String> {
/* LOGIC: /* LOGIC:
* 1. if symbol, unwrap (DEEP COPY) * 1. if symbol, unwrap (DEEP COPY)
@ -106,39 +111,52 @@ fn process_ctr(
match ctr { match ctr {
Ctr::Symbol(token) => { Ctr::Symbol(token) => {
let mut tok = token; let mut tok = token;
if let Some(s) = vars.borrow().get(token) { if let Some(s) = vars.borrow().get(&tok) {
// is function, or variable alias? // is function, or variable alias?
if first_item { if first_item {
if let Ctr::Symbol(t) = s { if let Ctr::Symbol(t) = *s.clone() {
if let Some(f) = funcs.borrow().get(t) { if let Some(f) = funcs.borrow().get(&t) {
// leave this set for the function call case below
tok = t; tok = t;
} }
} }
// is a basic value. // is a basic value.
} else { } else {
return Ok((*s).clone()) return Ok(*s.clone())
} }
// else call function // variable not found case
} else if !first_item && !sym_loose { } else if !first_item && !sym_loose {
return Err("variable not found") return Err(format!("variable '{}' not found", tok).to_string())
} }
// function call case
if first_item { if first_item {
if let Some(f) = funcs.borrow().get(tok) { if let Some(f) = funcs.borrow().get(&tok) {
match func_call(f, rest, vars.clone(), funcs.clone()) { if let Ctr::Seg(args) = rest {
Ok(a) => Ok(Ctr::Seg(a.borrow().clone())), match func_call(*f, args, vars.clone(), funcs.clone()) {
Err(s) => Err(s) Ok(a) => return Ok(a.clone()),
Err(s) => return Err(s)
}
} else {
return Err("evaluation: args to function not a list".to_string())
} }
} else {
return Err(format!("function '{}' not defined", tok).to_string())
} }
// sym_loose and not function call
} else {
return Ok(ctr.clone())
} }
}, },
Ctr::Seg(tree) => { Ctr::Seg(tree) => {
match eval(tree, vars, funcs, sym_loose) { // if list is_car then we need to set first_item to true
match eval_inner(tree, vars, funcs, sym_loose, is_car) {
Ok(ast) => { Ok(ast) => {
Ok(ast.borrow()) Ok(Ctr::Seg(ast))
}, },
Err(e) => { Err(e) => {
Err(e) Err(e)

View file

@ -26,7 +26,7 @@ use crate::eval::eval;
pub type FTable = HashMap<String, Rc<RefCell<Function>>>; pub type FTable = HashMap<String, Rc<RefCell<Function>>>;
// Standardized function signature for stdlib functions // Standardized function signature for stdlib functions
pub type InternalOperation = fn(Ast, Rc<RefCell<VTable>>, Rc<RefCell<FTable>>) -> Ast; pub type InternalOperation = fn(Ast, Rc<RefCell<VTable>>, Rc<RefCell<FTable>>) -> Ctr;
pub struct ExternalOperation { pub struct ExternalOperation {
// Un-evaluated abstract syntax tree // Un-evaluated abstract syntax tree
// TODO: Intermediate evaluation to simplify branches with no argument in them // TODO: Intermediate evaluation to simplify branches with no argument in them
@ -76,7 +76,7 @@ pub fn func_call(
args: Ast, args: Ast,
vars: Rc<RefCell<VTable>>, vars: Rc<RefCell<VTable>>,
funcs: Rc<RefCell<FTable>> funcs: Rc<RefCell<FTable>>
) -> Result<Ast, String> { ) -> Result<Ctr, String> {
let called_func = function.borrow_mut(); let called_func = function.borrow_mut();
let mut n_args: Ast = args.clone(); let mut n_args: Ast = args.clone();
if !called_func.eval_lazy { if !called_func.eval_lazy {
@ -151,15 +151,22 @@ pub fn func_call(
match &called_func.function { match &called_func.function {
Operation::Internal(f) => Ok((f)(n_args, vars, funcs)), Operation::Internal(f) => Ok((f)(n_args, vars, funcs)),
Operation::External(f) => { Operation::External(f) => {
let mut temp = vars.borrow().clone();
for n in 0..f.arg_syms.len() { for n in 0..f.arg_syms.len() {
temp.insert( vars.borrow().insert(
f.arg_syms[n].clone(), f.arg_syms[n].clone(),
Rc::new(list_idx(n_args.clone(), n as u128)) Rc::new(list_idx(n_args.clone(), n as u128))
); );
} }
eval(f.ast.clone(), Rc::new(RefCell::new(temp)), funcs, called_func.loose_syms) let result = eval(f.ast.clone(), vars.clone(), funcs, called_func.loose_syms);
for n in 0..f.arg_syms.len() {
vars.borrow().remove(&f.arg_syms[n].clone());
}
match result {
Ok(r) => Ok(r.borrow().car),
Err(e) => Err(e)
}
} }
} }
} }

View file

@ -20,7 +20,7 @@ mod func_tests {
is_bool = true; is_bool = true;
} }
new_ast(Ctr::Bool(is_bool), Ctr::None) Ctr::Bool(is_bool)
} }
) )
}; };
@ -42,8 +42,8 @@ mod func_tests {
return; return;
} }
if let Ok(ast) = func_call(func, args, vt, ft) { if let Ok(ret) = func_call(func, args, vt, ft) {
match &ast.borrow().car { match ret {
Ctr::Bool(b) => assert!(b), Ctr::Bool(b) => assert!(b),
_ => { _ => {
print!("invalid return from func!"); print!("invalid return from func!");