Significant improvement to eval routine and tests
This commit is contained in:
parent
9b981921b4
commit
df5cb47cb4
4 changed files with 397 additions and 11 deletions
115
src/eval.rs
115
src/eval.rs
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue