aether/
environment.rs

1// src/environment.rs
2//! Environment for variable storage and scoping
3//! 优化版本: 减少Rc/RefCell开销, 使用索引代替指针
4
5use crate::value::Value;
6use std::cell::RefCell;
7use std::collections::HashMap;
8use std::rc::Rc;
9
10/// 环境池,用于复用环境对象
11pub struct EnvironmentPool {
12    /// 可复用的环境对象池
13    pool: Vec<Environment>,
14    /// 最大池大小
15    max_size: usize,
16}
17
18impl EnvironmentPool {
19    /// 创建新的环境池
20    pub fn new() -> Self {
21        Self::with_capacity(50)
22    }
23
24    /// 创建指定容量的环境池
25    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    /// 从池中获取或创建新环境
33    pub fn acquire(&mut self) -> Environment {
34        self.pool.pop().unwrap_or_default()
35    }
36
37    /// 将环境归还到池中
38    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    /// 清空池
47    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/// Environment for storing variables
59#[derive(Debug, Clone)]
60pub struct Environment {
61    /// Variables in this scope (使用预分配容量优化)
62    store: HashMap<String, Value>,
63
64    /// Parent environment (for nested scopes)
65    parent: Option<Rc<RefCell<Environment>>>,
66}
67
68impl Environment {
69    /// Create a new global environment (with pre-allocated capacity)
70    pub fn new() -> Self {
71        Environment {
72            store: HashMap::with_capacity(16), // 预分配容量减少rehash
73            parent: None,
74        }
75    }
76
77    /// Create a new environment with a parent
78    pub fn with_parent(parent: Rc<RefCell<Environment>>) -> Self {
79        Environment {
80            store: HashMap::with_capacity(8), // 子环境通常变量较少
81            parent: Some(parent),
82        }
83    }
84
85    /// Set a variable in the current scope
86    pub fn set(&mut self, name: String, value: Value) {
87        self.store.insert(name, value);
88    }
89
90    /// Get a variable from this scope or parent scopes (优化路径)
91    pub fn get(&self, name: &str) -> Option<Value> {
92        // 快速路径: 直接在当前作用域查找
93        if let Some(value) = self.store.get(name) {
94            return Some(value.clone());
95        }
96
97        // 慢速路径: 递归查找父作用域
98        self.get_from_parent(name)
99    }
100
101    /// 从父作用域获取变量 (分离热路径和冷路径)
102    #[inline(never)]
103    fn get_from_parent(&self, name: &str) -> Option<Value> {
104        self.parent.as_ref()?.borrow().get(name)
105    }
106
107    /// Check if a variable exists in this scope or parent scopes
108    pub fn has(&self, name: &str) -> bool {
109        self.store.contains_key(name) || self.parent.as_ref().is_some_and(|p| p.borrow().has(name))
110    }
111
112    /// Update a variable in the scope where it was defined
113    /// Returns true if the variable was found and updated
114    pub fn update(&mut self, name: &str, value: Value) -> bool {
115        if self.store.contains_key(name) {
116            self.store.insert(name.to_string(), value);
117            return true;
118        }
119
120        if let Some(parent) = &self.parent {
121            return parent.borrow_mut().update(name, value);
122        }
123
124        false
125    }
126
127    /// Get all variable names in this scope
128    pub fn keys(&self) -> Vec<String> {
129        self.store.keys().cloned().collect()
130    }
131
132    /// Clear all variables in this scope (not parent scopes)
133    pub fn clear(&mut self) {
134        self.store.clear();
135    }
136}
137
138impl Default for Environment {
139    fn default() -> Self {
140        Self::new()
141    }
142}
143
144#[cfg(test)]
145mod tests {
146    use super::*;
147
148    #[test]
149    fn test_environment_set_get() {
150        let mut env = Environment::new();
151        env.set("x".to_string(), Value::Number(42.0));
152
153        assert_eq!(env.get("x"), Some(Value::Number(42.0)));
154        assert_eq!(env.get("y"), None);
155    }
156
157    #[test]
158    fn test_environment_has() {
159        let mut env = Environment::new();
160        env.set("x".to_string(), Value::Number(42.0));
161
162        assert!(env.has("x"));
163        assert!(!env.has("y"));
164    }
165
166    #[test]
167    fn test_environment_update() {
168        let mut env = Environment::new();
169        env.set("x".to_string(), Value::Number(42.0));
170
171        assert!(env.update("x", Value::Number(100.0)));
172        assert_eq!(env.get("x"), Some(Value::Number(100.0)));
173
174        assert!(!env.update("y", Value::Number(200.0)));
175    }
176
177    #[test]
178    fn test_environment_parent_scope() {
179        let parent = Rc::new(RefCell::new(Environment::new()));
180        parent
181            .borrow_mut()
182            .set("x".to_string(), Value::Number(42.0));
183
184        let mut child = Environment::with_parent(parent.clone());
185        child.set("y".to_string(), Value::Number(100.0));
186
187        // Child can access parent's variables
188        assert_eq!(child.get("x"), Some(Value::Number(42.0)));
189        assert_eq!(child.get("y"), Some(Value::Number(100.0)));
190
191        // Parent cannot access child's variables
192        assert_eq!(parent.borrow().get("x"), Some(Value::Number(42.0)));
193        assert_eq!(parent.borrow().get("y"), None);
194    }
195
196    #[test]
197    fn test_environment_shadowing() {
198        let parent = Rc::new(RefCell::new(Environment::new()));
199        parent
200            .borrow_mut()
201            .set("x".to_string(), Value::Number(42.0));
202
203        let mut child = Environment::with_parent(parent.clone());
204        child.set("x".to_string(), Value::Number(100.0));
205
206        // Child's value shadows parent's
207        assert_eq!(child.get("x"), Some(Value::Number(100.0)));
208        assert_eq!(parent.borrow().get("x"), Some(Value::Number(42.0)));
209    }
210
211    #[test]
212    fn test_environment_update_in_parent() {
213        let parent = Rc::new(RefCell::new(Environment::new()));
214        parent
215            .borrow_mut()
216            .set("x".to_string(), Value::Number(42.0));
217
218        let mut child = Environment::with_parent(parent.clone());
219
220        // Update parent's variable from child
221        assert!(child.update("x", Value::Number(100.0)));
222        assert_eq!(parent.borrow().get("x"), Some(Value::Number(100.0)));
223        assert_eq!(child.get("x"), Some(Value::Number(100.0)));
224    }
225
226    #[test]
227    fn test_environment_keys() {
228        let mut env = Environment::new();
229        env.set("x".to_string(), Value::Number(42.0));
230        env.set("y".to_string(), Value::String("hello".to_string()));
231
232        let keys = env.keys();
233        assert_eq!(keys.len(), 2);
234        assert!(keys.contains(&"x".to_string()));
235        assert!(keys.contains(&"y".to_string()));
236    }
237
238    #[test]
239    fn test_environment_clear() {
240        let mut env = Environment::new();
241        env.set("x".to_string(), Value::Number(42.0));
242        env.set("y".to_string(), Value::String("hello".to_string()));
243
244        env.clear();
245
246        assert_eq!(env.get("x"), None);
247        assert_eq!(env.get("y"), None);
248        assert_eq!(env.keys().len(), 0);
249    }
250}