1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
#[cfg(test)] use crate::interpreter::Interpreter; use crate::values::Value; use crate::{error::*, interpreter::error::LogicError}; use cell::{Ref, RefCell, RefMut, RefVal}; use std::collections::HashMap; #[cfg(test)] use std::error::Error; use std::rc::Rc; pub type DefinitionIter<'a, V> = Box<dyn 'a + Iterator<Item = (&'a String, &'a V)>>; #[derive(Clone, Debug, PartialEq)] pub struct LexicalScope<V> { parent: Option<Rc<LexicalScope<V>>>, definitions: RefCell<HashMap<String, V>>, } impl<V> LexicalScope<V> { pub fn new() -> Self { Self { parent: None, definitions: RefCell::new(HashMap::new()), } } pub fn new_child(parent: Rc<LexicalScope<V>>) -> Self { Self { parent: Some(parent), definitions: RefCell::new(HashMap::new()), } } pub fn define(&self, name: String, value: V) { self.definitions.borrow_mut().insert(name, value); } pub fn get(&self, name: &str) -> Option<Ref<V>> { if self.definitions.borrow().contains_key(name) { Some(Ref::map(self.definitions.borrow(), |definitions| { definitions.get(name).unwrap() })) } else { match &self.parent { Some(parent) => parent.get(name), None => None, } } } pub fn get_mut(&self, name: &str) -> Option<RefMut<V>> { if self.definitions.borrow().contains_key(name) { Some(RefMut::map(self.definitions.borrow_mut(), |definitions| { definitions.get_mut(name).unwrap() })) } else { match &self.parent { Some(parent) => parent.get_mut(name), None => None, } } } pub fn set(&self, name: &str, value: V) -> Result<(), SchemeError> { match self.definitions.borrow_mut().get_mut(name) { None => match &self.parent { None => { return Err( ErrorData::Logic(LogicError::UnboundedSymbol(name.to_string())).no_locate(), ); } Some(parent) => parent.set(name, value)?, }, Some(variable) => *variable = value, }; Ok(()) } pub fn iter_local_definitions<'a, 'b: 'a>(&'b self) -> RefVal<'a, DefinitionIter<'b, V>> { Ref::map_val( self.definitions.borrow(), |definitions| -> DefinitionIter<'b, V> { Box::new(definitions.iter()) }, ) } } pub type Environment<R> = LexicalScope<Value<R>>; #[test] fn iter_envs() -> Result<(), Box<dyn std::error::Error>> { let it = Interpreter::<f32>::new_with_stdlib(); { it.env.define("a".to_string(), Value::Void); } let env = it.env; { let mut definitions = env.iter_local_definitions(); assert_ne!(definitions.find(|(name, _)| *name == "a"), None); } { let mut definitions = env.iter_local_definitions(); assert_ne!(definitions.find(|(name, _)| *name == "sqrt"), None); } Ok(()) } #[test] fn get_mut() -> Result<(), Box<dyn Error>> { use crate::values::Number; use std::ops::Deref; let env = Environment::<f32>::new(); env.define("x".to_string(), Value::Number(Number::Integer(1))); { let value_mut = env.get_mut("x").unwrap(); let mut i = RefMut::map(value_mut, |value_mut| { if let Value::Number(Number::Integer(i)) = value_mut { i } else { unreachable!() } }); *i += 1; } assert_eq!( env.get("x").unwrap().deref(), &Value::Number(Number::Integer(2)) ); Ok(()) }