Significant improvement to eval routine and tests

This commit is contained in:
Aidan 2021-06-22 00:50:37 -07:00
parent 9b981921b4
commit df5cb47cb4
No known key found for this signature in database
GPG key ID: 327711E983899316
4 changed files with 397 additions and 11 deletions

View file

@ -30,10 +30,107 @@ pub fn eval(
vars: Rc<RefCell<VTable>>,
funcs: Rc<RefCell<FTable>>,
sym_loose: bool
) -> Result<Ast, String> {
eval_inner(ast, vars, funcs, sym_loose, true)
) -> Result<Ctr, String> {
let mut car = ast.borrow().clone().car;
let mut cdr = ast.borrow().clone().cdr;
let ret = new_ast(Ctr::None, Ctr::None);
let mut iter = ret.clone();
// doing an initial variable check here allows us
// to find functions passed in as variables
if let Ctr::Symbol(ref tok) = car {
if let Some(val) = vars.borrow().get(tok) {
car = (**val).clone();
}
}
// another check to detect if we may have a function call
if let Ctr::Symbol(ref tok) = car {
if let Ctr::Seg(ast) = cdr {
if let Some(func) = funcs.borrow().get(tok) {
return func_call(func.clone(), ast.clone(), vars.clone(), funcs.clone())
} else {
return Err(format!("Couldnt find function: {}.", tok))
}
} else {
return Err(format!("Arguments to function not a list!"))
}
}
let mut none = false;
while !none {
match car {
// if LIST: call eval inner on it with first_item=true
Ctr::Seg(ref inner) => {
match eval(inner.clone(), vars.clone(), funcs.clone(), sym_loose) {
Ok(res) => (*iter).borrow_mut().car = res,
Err(e) => return Err(format!("Evaluation error: {}", e))
}
},
// if SYMBOL: unwrap naively
Ctr::Symbol(ref tok) => {
if let Some(val) = vars.borrow().get(&tok.clone()) {
(*iter).borrow_mut().car = (**val).clone();
} else if sym_loose {
(*iter).borrow_mut().car = Ctr::Symbol(tok.to_string());
} else {
return Err(format!("Undefined variable: {}", tok))
}
},
// if OTHER: clone and set
_ => {
(*iter).borrow_mut().car = car.clone();
}
}
match cdr {
// if SYMBOL: unwrap naively, then end
Ctr::Symbol(ref tok) => {
if let Some(val) = vars.borrow().get(&tok.clone()) {
(*iter).borrow_mut().car = (**val).clone();
} else if sym_loose {
(*iter).borrow_mut().car = Ctr::Symbol(tok.to_string());
} else {
return Err(format!("Undefined variable: {}", tok))
}
none = true;
},
// if LIST:
// - iter.cdr = new_ast(None, None)
// - iter = iter.cdr
// - car = cdr.car
// - cdr = cdr.cdr
// - LOOP
Ctr::Seg(next) => {
let n = new_ast(Ctr::None, Ctr::None);
iter.borrow_mut().cdr = Ctr::Seg(n.clone());
iter = n;
car = next.borrow().clone().car;
cdr = next.borrow().clone().cdr;
}
// if OTHER: clone and set, and then end
_ => {
(*iter).borrow_mut().cdr = cdr.clone();
none = true;
}
}
if let Ctr::None = car {
if let Ctr::None = cdr {
none = true;
}
}
}
return Ok(Ctr::Seg(ret))
}
/*
fn eval_inner(
ast: Ast,
vars: Rc<RefCell<VTable>>,
@ -54,6 +151,8 @@ fn eval_inner(
let res_car;
let res_cdr;
// Handle Function Case
match process_ctr(
ast.borrow().clone().car,
vars.clone(),
@ -113,8 +212,10 @@ fn process_ctr(
match ctr.clone() {
Ctr::Symbol(token) => {
print!("[+] Detected Symbol: {}\n", token);
let mut tok = token;
if let Some(s) = vars.borrow().get(&tok) {
print!("[+] Found symbol value\n");
// is function, or variable alias?
let mut pass = false;
@ -141,12 +242,15 @@ fn process_ctr(
if first_item {
if let Some(f) = funcs.borrow().get(&tok) {
if let Ctr::Seg(args) = rest {
print!("[+] Calling function: {}\n", tok);
match func_call(f.clone(), args, vars.clone(), funcs.clone()) {
Ok(a) => return Ok(a.clone()),
Ok(a) => {
print!("[+] Function Call Result: {:#?}\n", a);
return Ok(a.clone())
},
Err(s) => return Err(s)
}
} else {
println!("AC::: {:?}\n", rest);
return Err("evaluation: args to function not a list".to_string())
}
} else {
@ -160,7 +264,7 @@ fn process_ctr(
},
Ctr::Seg(tree) => {
// if list is_car then we need to set first_item to true
match eval_inner(tree, vars, funcs, sym_loose, is_car && first_item) {
match eval_inner(tree, vars, funcs, sym_loose, is_car) {
Ok(ast) => {
Ok(Ctr::Seg(ast))
},
@ -172,3 +276,4 @@ fn process_ctr(
_ => Ok(ctr.clone())
}
}
*/

View file

@ -81,7 +81,13 @@ pub fn func_call(
let mut n_args: Ast = args.clone();
if !called_func.eval_lazy {
match eval(args, vars.clone(), funcs.clone(), called_func.loose_syms) {
Ok(rc_seg) => n_args = rc_seg.clone(),
Ok(rc_seg) => {
if let Ctr::Seg(ast) = rc_seg {
n_args = ast
} else {
return Err("Panicking: eval returned not a list for function args.".to_string())
}
},
Err(s) => return Err(
format!(
"error evaluating args to {}: {}",
@ -166,15 +172,32 @@ pub fn func_call(
);
}
let result = eval(f.ast.clone(), vars.clone(), funcs, called_func.loose_syms);
let mut result = Ctr::None;
let mut iterate = f.ast.clone();
loop {
if let Ctr::Seg(ast) = iterate.borrow().clone().car {
match eval(ast, vars.clone(), funcs.clone(), called_func.loose_syms) {
Ok(ctr) => {
if let Ctr::Seg(ast) = ctr {
result = ast.borrow().clone().car;
}
},
Err(e) => return Err(e)
}
}
match iterate.clone().borrow().clone().cdr {
Ctr::Seg(next) => iterate = next.clone(),
Ctr::None => break,
_ => panic!("function body not in standard form!")
}
}
for n in 0..f.arg_syms.len() {
vars.borrow_mut().remove(&f.arg_syms[n].clone());
}
match result {
Ok(r) => Ok(r.borrow().clone().car),
Err(e) => Err(e)
}
return Ok(result)
}
}
}