1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::iter::IntoIterator;
4use std::rc::Rc;
5
6use super::{Error, Result, SExp};
7
8pub 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}