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())
}
}
*/