1use std::collections::HashMap;
2
3use std::fmt;
4
5use crate::Locker;
6
7use crate::{
8 exp, CallSnapshot, Exception, ExceptionValue as EV, Expression, Operator, Symbol, Value,
9};
10
11#[derive(Debug, Clone)]
12struct ParentEnvironment {
13 namespace: Option<String>,
14 environment: Locker<Environment>,
15}
16
17#[derive(Debug, Clone)]
18pub struct Environment {
19 values: HashMap<Symbol, Locker<Expression>>,
20 parents: Vec<ParentEnvironment>,
22 shadow: bool,
25}
26
27impl Environment {
28 pub fn root() -> Self {
31 Self {
32 values: HashMap::new(),
33 parents: vec![],
34 shadow: false,
35 }
36 }
37
38 pub fn shadow(mut self) -> Self {
39 self.shadow = true;
40 self
41 }
42
43 pub fn with_parent(mut self, parent: Locker<Self>, namespace: Option<String>) -> Self {
44 self.add_parent(parent, namespace);
45 self
46 }
47
48 fn get_literal(symbol: &Symbol) -> Option<Value> {
49 use Operator::*;
50
51 match symbol.string_value().as_str() {
52 "nil" => Some(Value::List(vec![])),
53 "t" | "true" => Some(Value::True),
54 "quote" => Some(Value::Operator(Quote)),
55 "atom" => Some(Value::Operator(Atom)),
56 "eq" => Some(Value::Operator(Eq)),
57 "car" => Some(Value::Operator(Car)),
58 "cdr" => Some(Value::Operator(Cdr)),
59 "cons" => Some(Value::Operator(Cons)),
60 "cond" => Some(Value::Operator(Cond)),
61 "export" => Some(Value::Operator(Export)),
62 "let" => Some(Value::Operator(Let)),
63 "sum" => Some(Value::Operator(Sum)),
64 "prod" => Some(Value::Operator(Prod)),
65 "exp" => Some(Value::Operator(Exp)),
66 "modulo" => Some(Value::Operator(Modulo)),
67 "gt" => Some(Value::Operator(Gt)),
68 "ge" => Some(Value::Operator(Ge)),
69 "type" => Some(Value::Operator(Type)),
70 "disp" => Some(Value::Operator(Disp)),
71 "import" => Some(Value::Operator(Import)),
72 "eval" => Some(Value::Operator(Eval)),
73 "while" => Some(Value::Operator(While)),
74 "macro" => Some(Value::Operator(Macro)),
75 "lambda" => Some(Value::Operator(Lambda)),
76 "list" => Some(Value::Operator(List)),
77 "catch" => Some(Value::Operator(Catch)),
78 "throw" => Some(Value::Operator(Throw)),
79 "format" => Some(Value::Operator(Format)),
80 "parse" => Some(Value::Operator(Parse)),
81 "length" => Some(Value::Operator(Length)),
82 "append" => Some(Value::Operator(Append)),
83 "do" => Some(Value::Operator(Do)),
84 "floor" => Some(Value::Operator(Floor)),
85 "rand" => Some(Value::Operator(Rand)),
86 "equiv" => Some(Value::Operator(Equiv)),
87 _ => None,
88 }
89 }
90
91 fn resolve_symbol(
92 &self,
93 symbol: &Symbol,
94 namespace: Option<String>,
95 ) -> Option<(Locker<Expression>, usize)> {
96 if namespace == None {
97 if let Some(value) = self.values.get(&symbol) {
98 return Some((value.clone(), 0));
99 }
100 } else {
101 for parent in self.parents.iter() {
102 if namespace == parent.namespace {
103 return parent
104 .environment
105 .read()
106 .unwrap()
107 .resolve_symbol(symbol, None);
108 }
109 }
110 }
111 let mut best_match: (Option<Locker<Expression>>, usize) = (None, 0);
112 for parent in self.parents.iter() {
113 if parent.namespace.is_some() {
114 continue;
115 }
116 if let Some((exp, depth)) = parent
117 .environment
118 .read()
119 .unwrap()
120 .resolve_symbol(symbol, None)
121 {
122 if best_match.0.is_none() || depth < best_match.1 {
123 best_match = (Some(exp), depth);
124 }
125 }
126 }
127 if let Some(exp) = best_match.0 {
128 return Some((exp, best_match.1 + 1));
129 }
130 match Self::get_literal(symbol) {
131 Some(value) => Some((Locker::new(Expression::new(value)), 9999)),
132 None => None,
133 }
134 }
135
136 fn extract_components(symbol: &Symbol) -> (Option<String>, Symbol) {
137 let components: Vec<&str> = symbol.string_value().split("::").collect();
138
139 match components.len() {
140 1 => (None, Symbol::from_str(components.get(0).unwrap())),
141 _ => (
142 Some(components.get(0).unwrap().to_string()),
143 Symbol::from_str(
144 &components
145 .iter()
146 .skip(1)
147 .map(|x| x.to_string())
148 .collect::<Vec<String>>()
149 .join("::"),
150 ),
151 ),
152 }
153 }
154
155 pub fn lookup(&self, symbol: &Symbol) -> Option<Locker<Expression>> {
156 let (namespace, identifier) = Self::extract_components(symbol);
157 match self.resolve_symbol(&identifier, namespace) {
158 Some((exp, _)) => Some(exp),
159 None => None,
160 }
161 }
162
163 pub fn add_parent(&mut self, parent: Locker<Self>, namespace: Option<String>) {
164 self.parents.push(ParentEnvironment {
165 namespace,
166 environment: parent,
167 });
168 }
169
170 pub fn assign(
171 &mut self,
172 symbol: Symbol,
173 exp: Expression,
174 only_local: bool,
175 snapshot: Locker<CallSnapshot>,
176 ) -> Result<Locker<Expression>, Exception> {
177 let (namespace, identifier) = Self::extract_components(&symbol);
178
179 if only_local && namespace.is_some() {
180 exp!(
181 EV::Assignment(symbol, exp),
182 snapshot,
183 "cannot perform local assignment with namespace".to_string()
184 )
185 }
186
187 if !self.shadow
188 && (only_local || self.values.contains_key(&identifier) || self.parents.is_empty())
189 {
190 let lock = Locker::new(exp);
191 self.values.insert(identifier, lock.clone());
192 Ok(lock)
193 } else {
194 for parent in self.parents.iter() {
195 if parent.namespace == namespace {
196 return parent
197 .environment
198 .write()
199 .unwrap()
200 .assign(identifier, exp, only_local, snapshot);
201 }
202 }
203 exp!(EV::Assignment(symbol, exp), snapshot, format!("could not find suitable environment for assignment (namespace `{}` not available for assignment)", match namespace {
204 Some(value) => value,
205 None => "no namespace".to_string(),
206 }))
207 }
208 }
209}
210
211impl fmt::Display for Environment {
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 write!(
214 f,
215 "[values: {}]\n{}\nimported namespaces: {}",
216 self.values.len(),
217 self.values
218 .iter()
219 .map(|(k, v)| format!("{} := {}", k, v.read().unwrap()))
220 .collect::<Vec<String>>()
221 .join("\n"),
222 self.parents
223 .iter()
224 .map(|p| match &p.namespace {
225 Some(val) => val.clone(),
226 None => "(directly injected)".to_string(),
227 })
228 .collect::<Vec<String>>()
229 .join(", ")
230 )
231 }
232}