1use crate::value::Value;
6use std::cell::RefCell;
7use std::collections::HashMap;
8use std::rc::Rc;
9
10pub struct EnvironmentPool {
12 pool: Vec<Environment>,
14 max_size: usize,
16}
17
18impl EnvironmentPool {
19 pub fn new() -> Self {
21 Self::with_capacity(50)
22 }
23
24 pub fn with_capacity(max_size: usize) -> Self {
26 EnvironmentPool {
27 pool: Vec::with_capacity(max_size.min(50)),
28 max_size,
29 }
30 }
31
32 pub fn acquire(&mut self) -> Environment {
34 self.pool.pop().unwrap_or_else(Environment::new)
35 }
36
37 pub fn release(&mut self, mut env: Environment) {
39 if self.pool.len() < self.max_size {
40 env.clear();
41 env.parent = None;
42 self.pool.push(env);
43 }
44 }
45
46 pub fn clear(&mut self) {
48 self.pool.clear();
49 }
50}
51
52impl Default for EnvironmentPool {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58#[derive(Debug, Clone)]
60pub struct Environment {
61 store: HashMap<String, Value>,
63
64 parent: Option<Rc<RefCell<Environment>>>,
66}
67
68impl Environment {
69 pub fn new() -> Self {
71 Environment {
72 store: HashMap::with_capacity(16), parent: None,
74 }
75 }
76
77 pub fn with_parent(parent: Rc<RefCell<Environment>>) -> Self {
79 Environment {
80 store: HashMap::with_capacity(8), parent: Some(parent),
82 }
83 }
84
85 pub fn set(&mut self, name: String, value: Value) {
87 self.store.insert(name, value);
88 }
89
90 pub fn get(&self, name: &str) -> Option<Value> {
92 if let Some(value) = self.store.get(name) {
94 return Some(value.clone());
95 }
96
97 self.get_from_parent(name)
99 }
100
101 #[inline(never)]
103 fn get_from_parent(&self, name: &str) -> Option<Value> {
104 self.parent.as_ref()?.borrow().get(name)
105 }
106
107 pub fn has(&self, name: &str) -> bool {
109 self.store.contains_key(name)
110 || self.parent.as_ref().map_or(false, |p| p.borrow().has(name))
111 }
112
113 pub fn update(&mut self, name: &str, value: Value) -> bool {
116 if self.store.contains_key(name) {
117 self.store.insert(name.to_string(), value);
118 return true;
119 }
120
121 if let Some(parent) = &self.parent {
122 return parent.borrow_mut().update(name, value);
123 }
124
125 false
126 }
127
128 pub fn keys(&self) -> Vec<String> {
130 self.store.keys().cloned().collect()
131 }
132
133 pub fn clear(&mut self) {
135 self.store.clear();
136 }
137}
138
139impl Default for Environment {
140 fn default() -> Self {
141 Self::new()
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn test_environment_set_get() {
151 let mut env = Environment::new();
152 env.set("x".to_string(), Value::Number(42.0));
153
154 assert_eq!(env.get("x"), Some(Value::Number(42.0)));
155 assert_eq!(env.get("y"), None);
156 }
157
158 #[test]
159 fn test_environment_has() {
160 let mut env = Environment::new();
161 env.set("x".to_string(), Value::Number(42.0));
162
163 assert!(env.has("x"));
164 assert!(!env.has("y"));
165 }
166
167 #[test]
168 fn test_environment_update() {
169 let mut env = Environment::new();
170 env.set("x".to_string(), Value::Number(42.0));
171
172 assert!(env.update("x", Value::Number(100.0)));
173 assert_eq!(env.get("x"), Some(Value::Number(100.0)));
174
175 assert!(!env.update("y", Value::Number(200.0)));
176 }
177
178 #[test]
179 fn test_environment_parent_scope() {
180 let parent = Rc::new(RefCell::new(Environment::new()));
181 parent
182 .borrow_mut()
183 .set("x".to_string(), Value::Number(42.0));
184
185 let mut child = Environment::with_parent(parent.clone());
186 child.set("y".to_string(), Value::Number(100.0));
187
188 assert_eq!(child.get("x"), Some(Value::Number(42.0)));
190 assert_eq!(child.get("y"), Some(Value::Number(100.0)));
191
192 assert_eq!(parent.borrow().get("x"), Some(Value::Number(42.0)));
194 assert_eq!(parent.borrow().get("y"), None);
195 }
196
197 #[test]
198 fn test_environment_shadowing() {
199 let parent = Rc::new(RefCell::new(Environment::new()));
200 parent
201 .borrow_mut()
202 .set("x".to_string(), Value::Number(42.0));
203
204 let mut child = Environment::with_parent(parent.clone());
205 child.set("x".to_string(), Value::Number(100.0));
206
207 assert_eq!(child.get("x"), Some(Value::Number(100.0)));
209 assert_eq!(parent.borrow().get("x"), Some(Value::Number(42.0)));
210 }
211
212 #[test]
213 fn test_environment_update_in_parent() {
214 let parent = Rc::new(RefCell::new(Environment::new()));
215 parent
216 .borrow_mut()
217 .set("x".to_string(), Value::Number(42.0));
218
219 let mut child = Environment::with_parent(parent.clone());
220
221 assert!(child.update("x", Value::Number(100.0)));
223 assert_eq!(parent.borrow().get("x"), Some(Value::Number(100.0)));
224 assert_eq!(child.get("x"), Some(Value::Number(100.0)));
225 }
226
227 #[test]
228 fn test_environment_keys() {
229 let mut env = Environment::new();
230 env.set("x".to_string(), Value::Number(42.0));
231 env.set("y".to_string(), Value::String("hello".to_string()));
232
233 let keys = env.keys();
234 assert_eq!(keys.len(), 2);
235 assert!(keys.contains(&"x".to_string()));
236 assert!(keys.contains(&"y".to_string()));
237 }
238
239 #[test]
240 fn test_environment_clear() {
241 let mut env = Environment::new();
242 env.set("x".to_string(), Value::Number(42.0));
243 env.set("y".to_string(), Value::String("hello".to_string()));
244
245 env.clear();
246
247 assert_eq!(env.get("x"), None);
248 assert_eq!(env.get("y"), None);
249 assert_eq!(env.keys().len(), 0);
250 }
251}