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_else(Environment::new)
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)
110            || self.parent.as_ref().map_or(false, |p| p.borrow().has(name))
111    }
112
113    /// Update a variable in the scope where it was defined
114    /// Returns true if the variable was found and updated
115    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    /// Get all variable names in this scope
129    pub fn keys(&self) -> Vec<String> {
130        self.store.keys().cloned().collect()
131    }
132
133    /// Clear all variables in this scope (not parent scopes)
134    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        // Child can access parent's variables
189        assert_eq!(child.get("x"), Some(Value::Number(42.0)));
190        assert_eq!(child.get("y"), Some(Value::Number(100.0)));
191
192        // Parent cannot access child's variables
193        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        // Child's value shadows parent's
208        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        // Update parent's variable from child
222        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}