diff --git a/Cargo.toml b/Cargo.toml
index db0c100..ab899d9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,5 +8,5 @@ edition = "2018"
[dependencies]
dirs = "3.0"
-lazy_static = "1.4.0"
rustyline = "8.2.0"
+once_cell = "1.17.1"
\ No newline at end of file
diff --git a/src/eval.rs b/src/eval.rs
index d7bc949..52e93c6 100644
--- a/src/eval.rs
+++ b/src/eval.rs
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-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, 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, 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)
}
-
diff --git a/src/lib.rs b/src/lib.rs
index 76213de..1a34393 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -26,14 +26,12 @@ mod stl;
/*mod stl;
mod str;*/
-extern crate lazy_static;
-
pub mod ast {
pub use crate::eval::eval;
pub use crate::lex::lex;
pub use crate::segment::{Ctr, Seg, Type};
pub use crate::sym::{
- SYM_TABLE, SymTable, Symbol,
+ SymTable, Symbol,
UserFn, ValueType, Args
};
}
diff --git a/src/stl.rs b/src/stl.rs
index b1abf79..293a3e2 100644
--- a/src/stl.rs
+++ b/src/stl.rs
@@ -17,7 +17,7 @@
use crate::segment::{Ctr, Seg, Type};
use crate::eval::eval;
-use crate::sym::{SYM_TABLE, Symbol, ValueType, Args, UserFn};
+use crate::sym::{SymTable, Symbol, ValueType, Args, UserFn};
use std::env;
/*
@@ -44,18 +44,17 @@ pub static LIB_STORE_NO_ENV: Symbol = Symbol {
};*/
// TODO : declare function if arg list is long enough
-fn _store_callback (ast: &Seg, env_cfg: bool) -> Ctr {
- let mut table_handle = SYM_TABLE.write().unwrap();
+fn _store_callback (ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Ctr {
let is_var = ast.len() == 2;
if let Ctr::Symbol(ref identifier) = *ast.car {
match &*ast.cdr {
- Ctr::Seg(data_tree) if is_var => match eval(&Box::new(data_tree), true, true) {
+ Ctr::Seg(data_tree) if is_var => match eval(&Box::new(data_tree), syms) {
Ok(seg) => if let Ctr::Seg(ref val) = *seg {
- table_handle.insert(identifier.clone(), Symbol{
+ syms.insert(identifier.clone(), Symbol{
value: ValueType::VarForm(val.car.clone()),
name: identifier.clone(),
args: Args::None,
- has_undefined_symbols: false,
+ conditional_branches: false,
});
if env_cfg {
env::set_var(identifier.clone(), val.car.to_string());
@@ -81,7 +80,7 @@ fn _store_callback (ast: &Seg, env_cfg: bool) -> Ctr {
};
if let Ctr::Seg(ref bodies) = *data_tree.cdr {
- table_handle.insert(identifier.clone(), Symbol{
+ syms.insert(identifier.clone(), Symbol{
value: ValueType::FuncForm(UserFn{
ast: Box::new(bodies.clone()),
arg_syms: arg_list.clone(),
@@ -91,7 +90,7 @@ fn _store_callback (ast: &Seg, env_cfg: bool) -> Ctr {
.into_iter()
.map(Type::from)
.collect()),
- has_undefined_symbols: false,
+ conditional_branches: false,
});
} else {
eprintln!("expected one or more function bodies in function definition");
@@ -103,7 +102,7 @@ fn _store_callback (ast: &Seg, env_cfg: bool) -> Ctr {
}
}
Ctr::None => {
- table_handle.remove(&identifier.to_string());
+ syms.remove(&identifier.to_string());
if env_cfg {
env::remove_var(identifier);
}
diff --git a/src/sym.rs b/src/sym.rs
index b8bca9b..e29ffac 100644
--- a/src/sym.rs
+++ b/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;
-
-lazy_static! {
- pub static ref SYM_TABLE: RwLock = {
- RwLock::new(SymTable::new())
- };
-}
+pub struct SymTable(HashMap);
#[derive(Debug, Clone)]
pub struct UserFn {
@@ -47,7 +39,7 @@ pub struct UserFn {
*/
#[derive(Clone)]
pub enum ValueType {
- Internal(Box Ctr>),
+ Internal(Box Ctr>),
FuncForm(UserFn),
VarForm(Box)
}
@@ -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::::new()}
+ }
+
+ pub fn get(&self, arg: &String) -> Option<&Symbol> {
+ self.0.get(arg)
+ }
+
+ pub fn insert(&mut self, k: String, v: Symbol) -> Option {
+ self.0.insert(k, v)
+ }
+
+ pub fn remove(&mut self, arg: &String) -> Option {
+ self.0.remove(arg)
+ }
+
+ pub fn call_symbol(&mut self, name: &String, args: &Seg, call_func: bool) -> Result, 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, 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;
+ 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 {
}
}
}
-