blots_core/
environment.rs1use crate::values::Value;
2use std::cell::RefCell;
3use std::collections::HashMap;
4use std::rc::Rc;
5
6#[derive(Debug)]
12pub struct Environment {
13 local: RefCell<HashMap<String, Value>>,
15 parent: Option<Rc<Environment>>,
17}
18
19impl Environment {
20 pub fn new() -> Self {
22 Environment {
23 local: RefCell::new(HashMap::new()),
24 parent: None,
25 }
26 }
27
28 pub fn with_bindings(bindings: HashMap<String, Value>) -> Self {
30 Environment {
31 local: RefCell::new(bindings),
32 parent: None,
33 }
34 }
35
36 pub fn extend(parent: Rc<Environment>) -> Self {
38 Environment {
39 local: RefCell::new(HashMap::new()),
40 parent: Some(parent),
41 }
42 }
43
44 pub fn extend_with(parent: Rc<Environment>, local: HashMap<String, Value>) -> Self {
46 Environment {
47 local: RefCell::new(local),
48 parent: Some(parent),
49 }
50 }
51
52 pub fn get(&self, key: &str) -> Option<Value> {
54 if let Some(value) = self.local.borrow().get(key) {
56 return Some(*value);
57 }
58 if let Some(parent) = &self.parent {
60 return parent.get(key);
61 }
62 None
63 }
64
65 pub fn insert(&self, key: String, value: Value) {
67 self.local.borrow_mut().insert(key, value);
68 }
69
70 pub fn contains_key(&self, key: &str) -> bool {
72 if self.local.borrow().contains_key(key) {
73 return true;
74 }
75 if let Some(parent) = &self.parent {
76 return parent.contains_key(key);
77 }
78 false
79 }
80
81 pub fn contains_key_local(&self, key: &str) -> bool {
83 self.local.borrow().contains_key(key)
84 }
85}
86
87impl Default for Environment {
88 fn default() -> Self {
89 Self::new()
90 }
91}
92
93impl Clone for Environment {
94 fn clone(&self) -> Self {
95 Environment {
98 local: RefCell::new(self.flatten()),
99 parent: None,
100 }
101 }
102}
103
104impl Environment {
105 pub fn flatten(&self) -> HashMap<String, Value> {
108 let mut result = HashMap::new();
109 self.flatten_into(&mut result);
110 result
111 }
112
113 fn flatten_into(&self, result: &mut HashMap<String, Value>) {
114 if let Some(parent) = &self.parent {
116 parent.flatten_into(result);
117 }
118 for (key, value) in self.local.borrow().iter() {
120 result.insert(key.clone(), *value);
121 }
122 }
123
124 pub fn iter(&self) -> impl Iterator<Item = (String, Value)> {
127 self.flatten().into_iter()
128 }
129
130 pub fn keys(&self) -> impl Iterator<Item = String> {
133 self.flatten().into_keys()
134 }
135}