1use std::collections::BTreeMap;
4use std::sync::Arc;
5
6use crate::Literal;
7
8#[derive(Debug)]
10struct Binding {
11 name: Arc<str>,
12 value: Literal,
13 outer: Option<Arc<Self>>,
14}
15
16#[derive(Clone, Default)]
28pub struct Env {
29 innermost: Option<Arc<Binding>>,
30}
31
32impl Env {
33 #[must_use]
35 pub const fn new() -> Self {
36 Self { innermost: None }
37 }
38
39 #[must_use]
41 pub fn get(&self, name: &str) -> Option<&Literal> {
42 let mut cursor = self.innermost.as_deref();
43 while let Some(binding) = cursor {
44 if &*binding.name == name {
45 return Some(&binding.value);
46 }
47 cursor = binding.outer.as_deref();
48 }
49 None
50 }
51
52 #[must_use]
57 pub fn extend(&self, name: Arc<str>, value: Literal) -> Self {
58 Self {
59 innermost: Some(Arc::new(Binding {
60 name,
61 value,
62 outer: self.innermost.clone(),
63 })),
64 }
65 }
66
67 #[must_use]
69 pub fn len(&self) -> usize {
70 self.iter().count()
71 }
72
73 #[must_use]
75 pub const fn is_empty(&self) -> bool {
76 self.innermost.is_none()
77 }
78
79 pub fn iter(&self) -> impl Iterator<Item = (&Arc<str>, &Literal)> {
86 self.canonical().into_values()
87 }
88
89 fn canonical(&self) -> BTreeMap<&str, (&Arc<str>, &Literal)> {
91 let mut visible: BTreeMap<&str, (&Arc<str>, &Literal)> = BTreeMap::new();
92 let mut cursor = self.innermost.as_deref();
93 while let Some(binding) = cursor {
94 visible
97 .entry(&binding.name)
98 .or_insert((&binding.name, &binding.value));
99 cursor = binding.outer.as_deref();
100 }
101 visible
102 }
103}
104
105impl std::fmt::Debug for Env {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_map().entries(self.iter()).finish()
108 }
109}
110
111impl PartialEq for Env {
112 fn eq(&self, other: &Self) -> bool {
113 self.iter().eq(other.iter())
114 }
115}
116
117impl Eq for Env {}
118
119impl std::hash::Hash for Env {
120 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
121 for (name, value) in self.iter() {
122 name.hash(state);
123 value.hash(state);
124 }
125 }
126}
127
128impl serde::Serialize for Env {
129 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
130 use serde::ser::SerializeSeq as _;
131 let mut seq = serializer.serialize_seq(Some(self.len()))?;
132 for (name, value) in self.iter() {
133 seq.serialize_element(&(name, value))?;
134 }
135 seq.end()
136 }
137}
138
139impl<'de> serde::Deserialize<'de> for Env {
140 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
141 let pairs: Vec<(Arc<str>, Literal)> = serde::Deserialize::deserialize(deserializer)?;
142 Ok(pairs.into_iter().collect())
143 }
144}
145
146impl FromIterator<(Arc<str>, Literal)> for Env {
147 fn from_iter<T: IntoIterator<Item = (Arc<str>, Literal)>>(iter: T) -> Self {
149 iter.into_iter()
150 .fold(Self::new(), |env, (name, value)| env.extend(name, value))
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
159 fn extend_shadows() {
160 let env = Env::new().extend(Arc::from("x"), Literal::Int(1));
161 let env2 = env.extend(Arc::from("x"), Literal::Int(2));
162 assert_eq!(env.get("x"), Some(&Literal::Int(1)));
163 assert_eq!(env2.get("x"), Some(&Literal::Int(2)));
164 }
165
166 #[test]
167 fn missing_variable() {
168 let env = Env::new();
169 assert_eq!(env.get("x"), None);
170 }
171
172 #[test]
173 fn a_shadowed_name_is_counted_and_yielded_once() {
174 let env = Env::new()
175 .extend(Arc::from("x"), Literal::Int(1))
176 .extend(Arc::from("y"), Literal::Int(2))
177 .extend(Arc::from("x"), Literal::Int(3));
178 assert_eq!(env.len(), 2);
179 let mut seen: Vec<(&str, &Literal)> =
180 env.iter().map(|(name, value)| (&**name, value)).collect();
181 seen.sort_by_key(|(name, _)| *name);
182 assert_eq!(seen, vec![("x", &Literal::Int(3)), ("y", &Literal::Int(2))]);
183 }
184
185 #[test]
186 fn the_order_bindings_arrived_in_does_not_change_the_environment() {
187 let forward: Env = [
188 (Arc::from("a"), Literal::Int(1)),
189 (Arc::from("b"), Literal::Int(2)),
190 ]
191 .into_iter()
192 .collect();
193 let backward: Env = [
194 (Arc::from("b"), Literal::Int(2)),
195 (Arc::from("a"), Literal::Int(1)),
196 ]
197 .into_iter()
198 .collect();
199 assert_eq!(forward, backward);
200 }
201
202 #[test]
203 fn collecting_lets_the_last_binding_win() {
204 let env: Env = [
205 (Arc::from("x"), Literal::Int(1)),
206 (Arc::from("x"), Literal::Int(2)),
207 ]
208 .into_iter()
209 .collect();
210 assert_eq!(env.get("x"), Some(&Literal::Int(2)));
211 assert_eq!(env.len(), 1);
212 }
213
214 #[test]
215 fn an_environment_round_trips_through_serde() {
216 let env: Env = [
217 (Arc::from("a"), Literal::Int(1)),
218 (Arc::from("b"), Literal::Str("two".into())),
219 ]
220 .into_iter()
221 .collect();
222 let json = serde_json::to_string(&env).unwrap_or_else(|e| panic!("serialize: {e}"));
223 let back: Env = serde_json::from_str(&json).unwrap_or_else(|e| panic!("deserialize: {e}"));
224 assert_eq!(env, back);
225 }
226}