simplify eval, add member function to symtable to call a symbol
This commit is contained in:
parent
e055f26e90
commit
a1e19a19d9
5 changed files with 104 additions and 107 deletions
93
src/sym.rs
93
src/sym.rs
|
|
@ -18,16 +18,8 @@
|
|||
use crate::eval::eval;
|
||||
use crate::segment::{Seg, Ctr, Type};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::RwLock;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
pub type SymTable = HashMap<String, Symbol>;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref SYM_TABLE: RwLock<SymTable> = {
|
||||
RwLock::new(SymTable::new())
|
||||
};
|
||||
}
|
||||
pub struct SymTable(HashMap<String, Symbol>);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UserFn {
|
||||
|
|
@ -47,7 +39,7 @@ pub struct UserFn {
|
|||
*/
|
||||
#[derive(Clone)]
|
||||
pub enum ValueType {
|
||||
Internal(Box<fn(&Seg) -> Ctr>),
|
||||
Internal(Box<fn(&Seg, &mut SymTable) -> Ctr>),
|
||||
FuncForm(UserFn),
|
||||
VarForm(Box<Ctr>)
|
||||
}
|
||||
|
|
@ -69,7 +61,47 @@ pub struct Symbol {
|
|||
pub value: ValueType,
|
||||
pub name: String,
|
||||
pub args: Args,
|
||||
pub has_undefined_symbols: bool,
|
||||
// for internal control flow constructs
|
||||
// eval() will not eval the args
|
||||
pub conditional_branches: bool,
|
||||
}
|
||||
|
||||
impl SymTable {
|
||||
pub fn new() -> SymTable {
|
||||
SymTable{0: HashMap::<String, Symbol>::new()}
|
||||
}
|
||||
|
||||
pub fn get(&self, arg: &String) -> Option<&Symbol> {
|
||||
self.0.get(arg)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, k: String, v: Symbol) -> Option<Symbol> {
|
||||
self.0.insert(k, v)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, arg: &String) -> Option<Symbol> {
|
||||
self.0.remove(arg)
|
||||
}
|
||||
|
||||
pub fn call_symbol(&mut self, name: &String, args: &Seg, call_func: bool) -> Result<Box<Ctr>, String> {
|
||||
let symbol = match self.get(name) {
|
||||
Some(s) => s,
|
||||
None => return Err(format!("undefined symbol: {}", name)),
|
||||
};
|
||||
|
||||
let cond_args: &Seg;
|
||||
let outer_scope_seg_holder: Seg;
|
||||
if let ValueType::VarForm(ref val) = symbol.value {
|
||||
return Ok(val.clone());
|
||||
} else if call_func {
|
||||
cond_args = args
|
||||
} else {
|
||||
outer_scope_seg_holder = Seg::new();
|
||||
cond_args = &outer_scope_seg_holder;
|
||||
}
|
||||
|
||||
symbol.call(cond_args, self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Args {
|
||||
|
|
@ -155,14 +187,35 @@ impl Symbol {
|
|||
pub fn call(
|
||||
&self,
|
||||
args: &Seg,
|
||||
syms: &mut SymTable
|
||||
) -> Result<Box<Ctr>, String> {
|
||||
if let Err(msg) = self.args.validate_inputs(args) {
|
||||
let evaluated_args: &Seg;
|
||||
let outer_scope_seg_storage: Seg;
|
||||
let outer_scope_eval: Box<Ctr>;
|
||||
if self.conditional_branches {
|
||||
let outer_scope_eval_result = eval(args, syms);
|
||||
if let Err(s) = outer_scope_eval_result {
|
||||
return Err(s);
|
||||
}
|
||||
outer_scope_eval = outer_scope_eval_result.unwrap();
|
||||
match *outer_scope_eval {
|
||||
Ctr::Seg(ref segment) => evaluated_args = segment,
|
||||
_ => {
|
||||
outer_scope_seg_storage = Seg::from_mono(outer_scope_eval);
|
||||
evaluated_args = &outer_scope_seg_storage;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
evaluated_args = args;
|
||||
}
|
||||
|
||||
if let Err(msg) = self.args.validate_inputs(evaluated_args) {
|
||||
return Err(format!("failure to call {}: {}", self.name, msg));
|
||||
}
|
||||
|
||||
match &self.value {
|
||||
ValueType::VarForm(ref f) => Ok(Box::new(*f.clone())),
|
||||
ValueType::Internal(ref f) => Ok(Box::new(f(args))),
|
||||
ValueType::Internal(ref f) => Ok(Box::new(f(evaluated_args, syms))),
|
||||
ValueType::FuncForm(ref f) => {
|
||||
// stores any value overwritten by local state
|
||||
// If this ever becomes ASYNC this will need to
|
||||
|
|
@ -172,12 +225,11 @@ impl Symbol {
|
|||
|
||||
// Prep var table for function execution
|
||||
for n in 0..f.arg_syms.len() {
|
||||
if let Some(old) = SYM_TABLE.write().unwrap()
|
||||
.insert(f.arg_syms[n].clone(), Symbol{
|
||||
if let Some(old) = syms.insert(f.arg_syms[n].clone(), Symbol{
|
||||
name: f.arg_syms[n].clone(),
|
||||
value: ValueType::VarForm(Box::new(args[n].clone())),
|
||||
value: ValueType::VarForm(Box::new(evaluated_args[n].clone())),
|
||||
args: Args::None,
|
||||
has_undefined_symbols: false,
|
||||
conditional_branches: false,
|
||||
})
|
||||
{
|
||||
holding_table.insert(f.arg_syms[n].clone(), old);
|
||||
|
|
@ -189,7 +241,7 @@ impl Symbol {
|
|||
let mut iterate = &*(f.ast);
|
||||
loop {
|
||||
if let Ctr::Seg(ref data) = *iterate.car {
|
||||
match eval(data, !self.has_undefined_symbols, true) {
|
||||
match eval(data, syms) {
|
||||
Ok(ctr) => result = ctr,
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
|
|
@ -206,9 +258,9 @@ impl Symbol {
|
|||
|
||||
// clear local vars and restore previous values
|
||||
for n in 0..f.arg_syms.len() {
|
||||
SYM_TABLE.write().unwrap().remove(&f.arg_syms[n]);
|
||||
syms.remove(&f.arg_syms[n]);
|
||||
if let Some(val) = holding_table.remove(&f.arg_syms[n]) {
|
||||
SYM_TABLE.write().unwrap().insert(f.arg_syms[n].clone(), val);
|
||||
syms.insert(f.arg_syms[n].clone(), val);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -217,4 +269,3 @@ impl Symbol {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue