r/interpreter/
environment.rs1use std::cell::RefCell;
2use std::rc::Rc;
3
4use fnv::FnvHashMap;
5use itertools::Itertools;
6use tracing::trace;
7
8use crate::interpreter::value::RValue;
9use crate::parser::ast::Expr;
10
11type PromiseExprs = FnvHashMap<String, Expr>;
16
17#[derive(Debug, Clone)]
18pub struct Environment {
19 inner: Rc<RefCell<EnvInner>>,
20}
21
22impl Environment {
23 pub fn ptr_eq(&self, other: &Environment) -> bool {
25 Rc::ptr_eq(&self.inner, &other.inner)
26 }
27}
28
29#[derive(Debug)]
30pub(crate) struct EnvInner {
31 bindings: FnvHashMap<String, RValue>,
32 parent: Option<Environment>,
33 #[allow(dead_code)]
34 name: Option<String>,
35 on_exit: Vec<Expr>,
37 locked: bool,
39 locked_bindings: std::collections::HashSet<String>,
41 active_bindings: FnvHashMap<String, RValue>,
43 promise_exprs: PromiseExprs,
46}
47
48impl Environment {
49 pub fn new_global() -> Self {
50 Environment {
51 inner: Rc::new(RefCell::new(EnvInner {
52 bindings: FnvHashMap::default(),
53 parent: None,
54 name: Some("R_GlobalEnv".to_string()),
55 on_exit: Vec::new(),
56 locked: false,
57 locked_bindings: std::collections::HashSet::new(),
58 active_bindings: FnvHashMap::default(),
59 promise_exprs: FnvHashMap::default(),
60 })),
61 }
62 }
63
64 pub fn new_child(parent: &Environment) -> Self {
65 trace!(
66 "new child env (parent: {})",
67 parent.name().as_deref().unwrap_or("<anonymous>")
68 );
69 Environment {
70 inner: Rc::new(RefCell::new(EnvInner {
71 bindings: FnvHashMap::default(),
72 parent: Some(parent.clone()),
73 name: None,
74 on_exit: Vec::new(),
75 locked: false,
76 locked_bindings: std::collections::HashSet::new(),
77 active_bindings: FnvHashMap::default(),
78 promise_exprs: FnvHashMap::default(),
79 })),
80 }
81 }
82
83 pub fn get(&self, name: &str) -> Option<RValue> {
84 let inner = self.inner.borrow();
85 if let Some(val) = inner.bindings.get(name) {
86 Some(val.clone())
87 } else if let Some(ref parent) = inner.parent {
88 parent.get(name)
89 } else {
90 None
91 }
92 }
93
94 pub fn set(&self, name: String, value: RValue) {
95 self.inner.borrow_mut().bindings.insert(name, value);
96 }
97
98 pub fn set_super(&self, name: String, value: RValue) {
105 if self.is_global() {
115 self.set(name, value);
116 return;
117 }
118 let inner = self.inner.borrow();
119 if let Some(ref parent) = inner.parent {
120 if parent.has_local(&name) {
121 parent.set(name, value);
122 } else if parent.is_global() {
123 parent.set(name, value);
125 } else {
126 parent.set_super(name, value);
127 }
128 } else {
129 drop(inner);
131 self.set(name, value);
132 }
133 }
134
135 fn is_global(&self) -> bool {
137 self.inner.borrow().name.as_deref() == Some("R_GlobalEnv")
138 }
139
140 pub fn has_local(&self, name: &str) -> bool {
141 let inner = self.inner.borrow();
142 inner.bindings.contains_key(name) || inner.active_bindings.contains_key(name)
143 }
144
145 pub fn remove(&self, name: &str) -> bool {
146 let mut inner = self.inner.borrow_mut();
147 let removed_binding = inner.bindings.remove(name).is_some();
148 let removed_active = inner.active_bindings.remove(name).is_some();
149 removed_binding || removed_active
150 }
151
152 pub fn push_on_exit(&self, expr: Expr, add: bool, after: bool) {
156 let mut inner = self.inner.borrow_mut();
157 if add {
158 if after {
159 inner.on_exit.push(expr);
160 } else {
161 inner.on_exit.insert(0, expr);
162 }
163 } else {
164 inner.on_exit = vec![expr];
165 }
166 }
167
168 pub fn take_on_exit(&self) -> Vec<Expr> {
170 std::mem::take(&mut self.inner.borrow_mut().on_exit)
171 }
172
173 pub fn peek_on_exit(&self) -> Vec<Expr> {
175 self.inner.borrow().on_exit.clone()
176 }
177
178 pub fn new_empty() -> Self {
179 Environment {
180 inner: Rc::new(RefCell::new(EnvInner {
181 bindings: FnvHashMap::default(),
182 parent: None,
183 name: Some("R_EmptyEnv".to_string()),
184 on_exit: Vec::new(),
185 locked: false,
186 locked_bindings: std::collections::HashSet::new(),
187 active_bindings: FnvHashMap::default(),
188 promise_exprs: FnvHashMap::default(),
189 })),
190 }
191 }
192
193 pub fn ls(&self) -> Vec<String> {
194 let inner = self.inner.borrow();
195 inner
196 .bindings
197 .keys()
198 .chain(inner.active_bindings.keys())
199 .cloned()
200 .sorted()
201 .collect()
202 }
203
204 pub fn local_bindings(&self) -> Vec<(String, RValue)> {
206 let inner = self.inner.borrow();
207 inner
208 .bindings
209 .iter()
210 .map(|(k, v)| (k.clone(), v.clone()))
211 .sorted_by(|(a, _), (b, _)| a.cmp(b))
212 .collect()
213 }
214
215 pub fn name(&self) -> Option<String> {
216 self.inner.borrow().name.clone()
217 }
218
219 pub fn set_name(&self, name: String) {
220 self.inner.borrow_mut().name = Some(name);
221 }
222
223 pub fn parent(&self) -> Option<Environment> {
224 self.inner.borrow().parent.clone()
225 }
226
227 pub fn set_parent(&self, parent: Option<Environment>) {
229 self.inner.borrow_mut().parent = parent;
230 }
231
232 pub fn get_function(&self, name: &str) -> Option<RValue> {
236 let inner = self.inner.borrow();
237 if let Some(val) = inner.bindings.get(name) {
238 if matches!(val, RValue::Function(_)) {
239 return Some(val.clone());
240 }
241 }
242 if let Some(ref parent) = inner.parent {
243 parent.get_function(name)
244 } else {
245 None
246 }
247 }
248
249 pub fn lock(&self, bindings: bool) {
252 let mut inner = self.inner.borrow_mut();
253 inner.locked = true;
254 if bindings {
255 let names: Vec<String> = inner.bindings.keys().cloned().collect();
256 for name in names {
257 inner.locked_bindings.insert(name);
258 }
259 }
260 }
261
262 pub fn is_locked(&self) -> bool {
264 self.inner.borrow().locked
265 }
266
267 pub fn lock_binding(&self, name: &str) {
269 self.inner
270 .borrow_mut()
271 .locked_bindings
272 .insert(name.to_string());
273 }
274
275 pub fn binding_is_locked(&self, name: &str) -> bool {
277 self.inner.borrow().locked_bindings.contains(name)
278 }
279
280 pub fn set_active_binding(&self, name: String, fun: RValue) {
284 let mut inner = self.inner.borrow_mut();
285 inner.bindings.remove(&name);
287 inner.active_bindings.insert(name, fun);
288 }
289
290 pub fn get_local_active_binding(&self, name: &str) -> Option<RValue> {
292 self.inner.borrow().active_bindings.get(name).cloned()
293 }
294
295 pub fn get_active_binding(&self, name: &str) -> Option<RValue> {
298 let inner = self.inner.borrow();
299 if let Some(fun) = inner.active_bindings.get(name) {
300 Some(fun.clone())
301 } else if let Some(ref parent) = inner.parent {
302 parent.get_active_binding(name)
303 } else {
304 None
305 }
306 }
307
308 pub fn is_active_binding(&self, name: &str) -> bool {
310 let inner = self.inner.borrow();
311 if inner.active_bindings.contains_key(name) {
312 true
313 } else if let Some(ref parent) = inner.parent {
314 parent.is_active_binding(name)
315 } else {
316 false
317 }
318 }
319
320 pub fn is_local_active_binding(&self, name: &str) -> bool {
322 self.inner.borrow().active_bindings.contains_key(name)
323 }
324
325 pub fn set_promise_expr(&self, name: String, expr: Expr) {
332 self.inner.borrow_mut().promise_exprs.insert(name, expr);
333 }
334
335 pub fn get_promise_expr(&self, name: &str) -> Option<Expr> {
338 self.inner.borrow().promise_exprs.get(name).cloned()
339 }
340
341 }