nyavascript/evaluate/environment/
mod.rs

1use crate::s_expression::SExpressionRef as SXRef;
2use std::collections::HashMap;
3
4mod mccarthy_scope;
5pub use mccarthy_scope::McCarthyScope;
6
7mod fun_scope;
8pub use fun_scope::FunScope;
9
10#[cfg(test)]
11mod test;
12
13pub type Scope = HashMap<String, SXRef>;
14
15#[derive(Debug)]
16pub struct Environment {
17    global: Scope,
18    lib: Vec<Scope>,
19    stack: Vec<Scope>,
20}
21
22impl Environment {
23    pub fn new() -> Environment {
24        Environment {
25            stack: vec![Scope::new()],
26            lib: vec![],
27            global: Scope::new(),
28        }
29    }
30
31    pub fn pop_lib(&mut self) -> Scope {
32        self.lib.pop().unwrap()
33    }
34
35    pub fn push_lib(&mut self, c: Scope) {
36        self.lib.push(c);
37    }
38
39    pub fn has(&self, key: &str) -> bool {
40        self.stack.iter().any(|s| s.contains_key(key))
41    }
42
43    pub fn get(&self, key: &str) -> SXRef {
44        let local = self.stack.iter().rev()
45            .find_map(|s| s.get(key).map(|exref| SXRef::clone(exref)));
46
47        if let Some(local) = local {
48            return local
49        }
50
51        let lib = self.lib.iter().rev()
52            .find_map(|s| s.get(key).map(|exref| SXRef::clone(exref)));
53
54        if let Some(lib) = lib {
55            return lib
56        }
57
58        if let Some(global) = self.global.get(key) {
59            return SXRef::clone(global)
60        }
61
62        SXRef::nil()
63    }
64
65    pub fn pop(&mut self) -> Scope {
66        self.stack.pop().unwrap()
67    }
68
69    pub fn push(&mut self, c: Scope) {
70        self.stack.push(c);
71    }
72
73    pub fn set(&mut self, key: String, val: SXRef) {
74        self.stack.last_mut().unwrap().insert(key, val);
75    }
76
77    pub fn delete(&mut self, key: &str) {
78        self.stack.last_mut().unwrap().remove(key);
79    }
80
81    pub fn defun(&mut self, key: String, val: SXRef) {
82        self.global.insert(key, val);
83    }
84}