diff --git a/src/eval.rs b/src/eval.rs index ecb311d..d7bc949 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -36,11 +36,10 @@ 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; - let table_handle = SYM_TABLE.lock().unwrap(); - // iterate over ast and build out ret let mut none = false; while !none { @@ -68,7 +67,6 @@ pub fn eval ( } } - // im tired please simplify this Ctr::Symbol(_) => { if simplify_function_branches && first { if let Some(func) = prefetched_function { diff --git a/src/stl.rs b/src/stl.rs index a4334a1..b1abf79 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -45,7 +45,7 @@ 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.lock().unwrap(); + let mut table_handle = SYM_TABLE.write().unwrap(); let is_var = ast.len() == 2; if let Ctr::Symbol(ref identifier) = *ast.car { match &*ast.cdr { diff --git a/src/sym.rs b/src/sym.rs index e48e1fc..b8bca9b 100644 --- a/src/sym.rs +++ b/src/sym.rs @@ -18,14 +18,14 @@ use crate::eval::eval; use crate::segment::{Seg, Ctr, Type}; use std::collections::HashMap; -use std::sync::Mutex; +use std::sync::RwLock; use lazy_static::lazy_static; pub type SymTable = HashMap; lazy_static! { - pub static ref SYM_TABLE: Mutex = { - Mutex::new(SymTable::new()) + pub static ref SYM_TABLE: RwLock = { + RwLock::new(SymTable::new()) }; } @@ -172,7 +172,7 @@ impl Symbol { // Prep var table for function execution for n in 0..f.arg_syms.len() { - if let Some(old) = SYM_TABLE.lock().unwrap() + if let Some(old) = SYM_TABLE.write().unwrap() .insert(f.arg_syms[n].clone(), Symbol{ name: f.arg_syms[n].clone(), value: ValueType::VarForm(Box::new(args[n].clone())), @@ -206,9 +206,9 @@ impl Symbol { // clear local vars and restore previous values for n in 0..f.arg_syms.len() { - SYM_TABLE.lock().unwrap().remove(&f.arg_syms[n]); + SYM_TABLE.write().unwrap().remove(&f.arg_syms[n]); if let Some(val) = holding_table.remove(&f.arg_syms[n]) { - SYM_TABLE.lock().unwrap().insert(f.arg_syms[n].clone(), val); + SYM_TABLE.write().unwrap().insert(f.arg_syms[n].clone(), val); } } diff --git a/tests/test_eval.rs b/tests/test_eval.rs index 46a71d7..5bbf559 100644 --- a/tests/test_eval.rs +++ b/tests/test_eval.rs @@ -51,25 +51,28 @@ mod eval_tests { #[test] fn eval_function_call() { - let mut table_handle = SYM_TABLE.lock().unwrap(); let test_doc = "('one' (echo 'unwrap_me'))".to_string(); let output = "('one' 'unwrap_me')"; - let test_external_func: Symbol = Symbol { - name: String::from("echo"), - args: Args::Lazy(1), - has_undefined_symbols: false, - value: ValueType::FuncForm( UserFn { - arg_syms: vec!["input".to_string()], - ast: Box::new(Seg::from( - Box::new(Ctr::Seg(Seg::from( - Box::from(Ctr::Symbol("input".to_string())), - Box::from(Ctr::None)))), - Box::new(Ctr::None), - )), - }), - }; - table_handle.insert(String::from("echo"), test_external_func); + { // we want the write lock to expire before eval + let mut table_handle = SYM_TABLE.write().unwrap(); + let test_external_func: Symbol = Symbol { + name: String::from("echo"), + args: Args::Lazy(1), + has_undefined_symbols: false, + value: ValueType::FuncForm( UserFn { + arg_syms: vec!["input".to_string()], + ast: Box::new(Seg::from( + Box::new(Ctr::Seg(Seg::from( + Box::from(Ctr::Symbol("input".to_string())), + Box::from(Ctr::None)))), + Box::new(Ctr::None), + )), + }), + }; + + table_handle.insert(String::from("echo"), test_external_func); + } match lex(&test_doc) { Err(e) => { println!("Lexing error: {}\n", e); @@ -91,25 +94,28 @@ mod eval_tests { #[test] fn eval_embedded_func_calls() { - let mut table_handle = SYM_TABLE.lock().unwrap(); let test_doc = "('one' (echo (echo 'unwrap_me')))".to_string(); let output = "('one' 'unwrap_me')"; - let test_external_func: Symbol = Symbol{ - name: String::from("echo"), - args: Args::Lazy(1), - has_undefined_symbols: false, - value: ValueType::FuncForm( UserFn { - arg_syms: vec!["input".to_string()], - ast: Box::new(Seg::from( - Box::new(Ctr::Seg(Seg::from( - Box::from(Ctr::Symbol("input".to_string())), - Box::from(Ctr::None)))), - Box::new(Ctr::None), - )), - }), - }; - table_handle.insert(String::from("echo"), test_external_func); + { + let mut table_handle = SYM_TABLE.write().unwrap(); + let test_external_func: Symbol = Symbol{ + name: String::from("echo"), + args: Args::Lazy(1), + has_undefined_symbols: false, + value: ValueType::FuncForm( UserFn { + arg_syms: vec!["input".to_string()], + ast: Box::new(Seg::from( + Box::new(Ctr::Seg(Seg::from( + Box::from(Ctr::Symbol("input".to_string())), + Box::from(Ctr::None)))), + Box::new(Ctr::None), + )), + }), + }; + + table_handle.insert(String::from("echo"), test_external_func); + } match lex(&test_doc) { Err(e) => { println!("Lexing error: {}\n", e); diff --git a/tests/test_func.rs b/tests/test_func.rs index 91da402..9063da1 100644 --- a/tests/test_func.rs +++ b/tests/test_func.rs @@ -5,7 +5,6 @@ mod func_tests { #[test] fn decl_and_call_internal_func() { - let mut table_handle = SYM_TABLE.lock().unwrap(); let test_internal_func: Symbol = Symbol { name: String::from("test_func_in"), has_undefined_symbols: false, @@ -17,7 +16,6 @@ mod func_tests { if let Ctr::Bool(_) = *inner.car { is_bool = true; } - Ctr::Bool(is_bool) }, )), @@ -27,7 +25,12 @@ mod func_tests { Box::new(Ctr::None) ); - table_handle.insert(String::from("test_func_in"), test_internal_func); + { + let mut table_handle = SYM_TABLE.write().unwrap(); + table_handle.insert(String::from("test_func_in"), test_internal_func); + } + + let table_handle = SYM_TABLE.read().unwrap(); let func: &Symbol; if let Some(f) = table_handle.get(&"test_func_in".to_string()) { func = f; @@ -53,7 +56,6 @@ mod func_tests { #[test] fn decl_and_call_external_func_singlet() { - let mut table_handle = SYM_TABLE.lock().unwrap(); match lex(&"((input))".to_string()) { Err(e) => panic!("{}", e), Ok(finner) => { @@ -72,7 +74,12 @@ mod func_tests { Box::new(Ctr::None) ); - table_handle.insert(String::from("test_func_in"), test_external_func); + { + let mut table_handle = SYM_TABLE.write().unwrap(); + table_handle.insert(String::from("test_func_in"), test_external_func); + } + + let table_handle = SYM_TABLE.read().unwrap(); let func: &Symbol; if let Some(f) = table_handle.get(&"test_func_in".to_string()) { func = f; @@ -82,7 +89,7 @@ mod func_tests { return; } - match func.call(&args) { + match func.call(&args) { Ok(ret) => match *ret { Ctr::String(b) => assert!(b == "test"), _ => { @@ -101,7 +108,6 @@ mod func_tests { #[test] fn decl_and_call_external_func_multi_body() { - let mut table_handle = SYM_TABLE.lock().unwrap(); match lex(&"((input) (input))".to_string()) { Err(e) => panic!("{}", e), Ok(finner) => { @@ -120,7 +126,12 @@ mod func_tests { Box::new(Ctr::None) ); - table_handle.insert(String::from("echo_2"), test_external_func); + { + let mut table_handle = SYM_TABLE.write().unwrap(); + table_handle.insert(String::from("echo_2"), test_external_func); + } + + let table_handle = SYM_TABLE.read().unwrap(); let func: &Symbol; if let Some(f) = table_handle.get(&"echo_2".to_string()) { func = f; @@ -143,7 +154,6 @@ mod func_tests { #[test] fn decl_and_call_func_with_nested_call() { - let mut table_handle = SYM_TABLE.lock().unwrap(); let inner_func: Symbol = Symbol { name: String::from("test_inner"), has_undefined_symbols: false, @@ -177,15 +187,19 @@ mod func_tests { }), }; - let args = Seg::from( Box::new(Ctr::Bool(true)), Box::new(Ctr::None) ); - table_handle.insert(String::from("test_inner"), inner_func); - table_handle.insert(String::from("test_outer"), outer_func); + { + let mut table_handle = SYM_TABLE.write().unwrap(); + table_handle.insert(String::from("test_inner"), inner_func); + table_handle.insert(String::from("test_outer"), outer_func); + } + + let table_handle = SYM_TABLE.read().unwrap(); let func: &Symbol; if let Some(f) = table_handle.get(&"test_outer".to_string()) { func = f;