parsley/
env.rs

1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::iter::IntoIterator;
4use std::rc::Rc;
5
6use super::{Error, Result, SExp};
7
8/// A type to represent an execution environment.
9pub type Ns = HashMap<String, SExp>;
10
11type Link = Option<Rc<Env>>;
12
13#[derive(Debug, Default)]
14pub struct Env {
15    env: RefCell<Ns>,
16    parent: Link,
17}
18
19impl Env {
20    pub fn new(parent: Link) -> Self {
21        Self {
22            parent,
23            ..Self::default()
24        }
25    }
26
27    pub fn parent(&self) -> Link {
28        self.parent.clone()
29    }
30
31    pub fn into_rc(self) -> Rc<Self> {
32        Rc::new(self)
33    }
34
35    pub fn iter(&self) -> Iter {
36        Iter(Some(self))
37    }
38
39    pub fn len(&self) -> usize {
40        self.parent().into_iter().count() + 1
41    }
42
43    pub fn extend(&self, other: Ns) {
44        self.env.borrow_mut().extend(other.into_iter());
45    }
46
47    pub fn get(&self, key: &str) -> Option<SExp> {
48        for ns in self.iter() {
49            if let Some(val) = ns.env.borrow().get(key) {
50                return Some(val.clone());
51            }
52        }
53
54        None
55    }
56
57    pub fn define(&self, key: &str, val: SExp) {
58        self.env.borrow_mut().insert(key.to_string(), val);
59    }
60
61    pub fn set(&self, key: &str, val: SExp) -> Result {
62        let possible_err = Error::UndefinedSymbol {
63            sym: key.to_string(),
64        };
65
66        for ns in self.iter() {
67            if ns.env.borrow().get(key).is_some() {
68                return ns
69                    .env
70                    .borrow_mut()
71                    .insert(key.to_string(), val)
72                    .ok_or(possible_err);
73            }
74        }
75
76        Err(possible_err)
77    }
78}
79
80pub struct Iter<'a>(Option<&'a Env>);
81
82impl<'a> Iterator for Iter<'a> {
83    type Item = &'a Env;
84
85    fn next(&mut self) -> Option<Self::Item> {
86        let ret = self.0.take();
87
88        if let Some(rc) = ret {
89            if let Some(p) = &rc.parent {
90                self.0 = Some(p);
91            }
92        }
93
94        ret
95    }
96}
97
98impl IntoIterator for Env {
99    type Item = Rc<Self>;
100    type IntoIter = IntoIter;
101
102    fn into_iter(self) -> Self::IntoIter {
103        IntoIter(Some(self.into_rc()))
104    }
105}
106
107pub struct IntoIter(Link);
108
109impl Iterator for IntoIter {
110    type Item = Rc<Env>;
111
112    fn next(&mut self) -> Option<Self::Item> {
113        let ret = self.0.take();
114
115        if let Some(rc) = &ret {
116            self.0 = rc.parent();
117        }
118
119        ret
120    }
121}