simplify eval, add member function to symtable to call a symbol

This commit is contained in:
Ava Hahn 2023-02-23 23:01:47 -08:00
parent e055f26e90
commit a1e19a19d9
Signed by untrusted user who does not match committer: affine
GPG key ID: 3A4645B8CF806069
5 changed files with 104 additions and 107 deletions

View file

@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use crate::sym::{SYM_TABLE, Symbol, ValueType};
use crate::sym::SymTable;
use crate::segment::{Seg, Ctr};
/* iterates over a syntax tree
@ -24,8 +24,7 @@ use crate::segment::{Seg, Ctr};
*/
pub fn eval (
ast: &Seg,
expect_all_symbols_defined: bool,
simplify_function_branches: bool,
syms: &mut SymTable,
) -> Result<Box<Ctr>, String> {
// data to return
let mut ret = Box::from(Ctr::None);
@ -36,70 +35,33 @@ pub fn eval (
let mut cdr = Box::from(Ctr::None);
// lets me redirect the input
let table_handle = SYM_TABLE.read().unwrap();
let mut arg_car = &ast.car;
let mut arg_cdr = &ast.cdr;
// iterate over ast and build out ret
let mut none = false;
while !none {
let mut prefetched_function: Option<&Symbol> = None;
while let Ctr::Symbol(ref tok) = **arg_car {
prefetched_function = table_handle.get(tok);
if let Some(sym_ref) = prefetched_function {
if let ValueType::VarForm(ref value) = sym_ref.value {
arg_car = value;
} else {
break;
}
} else if !expect_all_symbols_defined {
return Err(format!("evaluation error: undefined symbol {}", tok))
} else {
break
}
}
match **arg_car {
match &**arg_car {
Ctr::Seg(ref inner) => {
match eval(inner, expect_all_symbols_defined, simplify_function_branches) {
match eval(inner, syms) {
Ok(res) => car = res,
Err(e) => return Err(format!("evaluation error: {}", e)),
}
}
Ctr::Symbol(_) => {
if simplify_function_branches && first {
if let Some(func) = prefetched_function {
if let Ctr::Seg(ref candidates) = **arg_cdr {
let fc: Result<Box<Ctr>, String>;
match eval(candidates, expect_all_symbols_defined, false) {
Ok(res) => {
match *res {
Ctr::Seg(ref args) => {
fc = func.call(args);
},
_ => {
fc = func.call(&Seg::from_mono(res.clone()))
}
}
match fc {
Ok(datum) => car = datum,
Err(e) => return Err(format!("call to {} failed: {}", func.name, e))
}
}
Err(e) => return Err(format!("evaluation error: {}", e))
}
} else {
match func.call(&Seg::new()) {
Ok(res) => car = res,
Err(e) => return Err(format!("call to {} failed: {}", func.name, e))
}
}
} else {
car = arg_car.clone();
}
Ctr::Symbol(ref tok) => {
let outer_scope_seg_holder: Seg;
let args: &Seg;
if let Ctr::Seg(ref candidate_args) = **arg_cdr {
args = candidate_args;
} else {
car = arg_car.clone();
outer_scope_seg_holder = Seg::from_mono(arg_cdr.clone());
args = &outer_scope_seg_holder;
}
match syms.call_symbol(tok, args, first) {
Ok(s) => car = s,
Err(s) => return Err(format!("error in call to {}: {}", tok, s)),
}
}
@ -108,25 +70,13 @@ pub fn eval (
}
}
// weird tree but okay
while let Ctr::Symbol(ref tok) = **arg_cdr {
prefetched_function = table_handle.get(tok);
if let Some(sym_ref) = prefetched_function {
if let ValueType::VarForm(ref value) = sym_ref.value {
arg_cdr = value;
} else {
break;
}
} else if !expect_all_symbols_defined {
return Err(format!("evaluation error: undefined symbol {}", tok))
} else {
break
}
}
match **arg_cdr {
Ctr::Symbol(_) => {
cdr = arg_cdr.clone();
Ctr::Symbol(ref tok) => {
let blank = Seg::new();
match syms.call_symbol(tok, &blank, false) {
Ok(res) => cdr = res,
Err(s) => return Err(format!("error fetching {}: {}", tok, s)),
}
none = true;
}
@ -157,4 +107,3 @@ pub fn eval (
Ok(ret)
}