1use std::sync::Arc;
4
5use rustc_hash::FxHashMap;
6
7use crate::Literal;
8
9#[derive(Debug, Clone, Default)]
15pub struct Env {
16 bindings: FxHashMap<Arc<str>, Literal>,
17}
18
19impl Env {
20 #[must_use]
22 pub fn new() -> Self {
23 Self::default()
24 }
25
26 #[must_use]
28 pub fn get(&self, name: &str) -> Option<&Literal> {
29 self.bindings.get(name)
30 }
31
32 #[must_use]
34 pub fn extend(&self, name: Arc<str>, value: Literal) -> Self {
35 let mut bindings = self.bindings.clone();
36 bindings.insert(name, value);
37 Self { bindings }
38 }
39
40 #[must_use]
42 pub fn len(&self) -> usize {
43 self.bindings.len()
44 }
45
46 #[must_use]
48 pub fn is_empty(&self) -> bool {
49 self.bindings.is_empty()
50 }
51
52 pub fn iter(&self) -> impl Iterator<Item = (&Arc<str>, &Literal)> {
54 self.bindings.iter()
55 }
56}
57
58impl FromIterator<(Arc<str>, Literal)> for Env {
59 fn from_iter<T: IntoIterator<Item = (Arc<str>, Literal)>>(iter: T) -> Self {
60 Self {
61 bindings: iter.into_iter().collect(),
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn extend_shadows() {
72 let env = Env::new().extend(Arc::from("x"), Literal::Int(1));
73 let env2 = env.extend(Arc::from("x"), Literal::Int(2));
74 assert_eq!(env.get("x"), Some(&Literal::Int(1)));
75 assert_eq!(env2.get("x"), Some(&Literal::Int(2)));
76 }
77
78 #[test]
79 fn missing_variable() {
80 let env = Env::new();
81 assert_eq!(env.get("x"), None);
82 }
83}