nyavascript/evaluate/environment/
mod.rs1use 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}