simplify func return type, complete eval and process logic
This commit is contained in:
parent
0adda0109c
commit
4712d5466c
3 changed files with 49 additions and 24 deletions
50
src/eval.rs
50
src/eval.rs
|
|
@ -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)
|
||||||
|
|
|
||||||
17
src/func.rs
17
src/func.rs
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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!");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue