1use crate::{builtin::Builtin, constructor::Constructor, modules::ModuleTree};
4
5use super::{
6 Callable, Interpret,
7 builtin::{Builtins, Math},
8 convalue::ConValue,
9 error::{Error, IResult},
10 function::Function,
11};
12use cl_ast::{Function as FnDecl, Sym};
13use std::{
14 collections::HashMap,
15 fmt::Display,
16 ops::{Deref, DerefMut},
17 rc::Rc,
18};
19
20pub type StackFrame = HashMap<Sym, ConValue>;
21
22pub type StackBinds = HashMap<Sym, usize>;
23
24#[derive(Clone, Debug, Default)]
25pub(crate) struct EnvFrame {
26 pub name: Option<&'static str>,
27 pub base: usize,
29 pub binds: StackBinds,
31}
32
33#[derive(Clone, Debug)]
35pub struct Environment {
36 values: Vec<ConValue>,
37 frames: Vec<EnvFrame>,
38 modules: ModuleTree,
39}
40
41impl Display for Environment {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 for EnvFrame { name, base: _, binds } in self.frames.iter().rev() {
44 writeln!(
45 f,
46 "--- {}[{}] ---",
47 if let Some(name) = name { name } else { "" },
48 binds.len(),
49 )?;
50 let mut binds: Vec<_> = binds.iter().collect();
51 binds.sort_by(|(_, a), (_, b)| a.cmp(b));
52 for (name, idx) in binds {
53 write!(f, "{idx:4} {name}: ")?;
54 match self.values.get(*idx) {
55 Some(value) => writeln!(f, "\t{value}"),
56 None => writeln!(f, "ERROR: {name}'s address blows the stack!"),
57 }?
58 }
59 }
60 Ok(())
61 }
62}
63
64impl Default for Environment {
65 fn default() -> Self {
66 let mut this = Self::no_builtins();
67 this.add_builtins(Builtins).add_builtins(Math);
68 this
69 }
70}
71
72impl Environment {
73 pub fn new() -> Self {
74 Self::default()
75 }
76 pub fn no_builtins() -> Self {
78 Self {
79 values: Vec::new(),
80 frames: vec![EnvFrame::default()],
81 modules: ModuleTree::default(),
82 }
83 }
84
85 pub fn eval(&mut self, node: &impl Interpret) -> IResult<ConValue> {
87 node.interpret(self)
88 }
89
90 pub fn call(&mut self, name: Sym, args: &[ConValue]) -> IResult<ConValue> {
93 let function = self.get(name)?;
94 function.call(self, args)
95 }
96
97 pub fn modules_mut(&mut self) -> &mut ModuleTree {
98 &mut self.modules
99 }
100
101 pub fn modules(&self) -> &ModuleTree {
102 &self.modules
103 }
104
105 pub fn bind(&mut self, name: impl Into<Sym>, value: impl Into<ConValue>) {
107 self.insert(name.into(), value.into());
108 }
109
110 pub fn bind_raw(&mut self, name: Sym, id: usize) -> Option<()> {
111 let EnvFrame { name: _, base: _, binds } = self.frames.last_mut()?;
112 binds.insert(name, id);
113 Some(())
114 }
115
116 pub(crate) fn globals(&self) -> &EnvFrame {
118 self.frames.first().unwrap()
119 }
120
121 pub fn add_builtins(&mut self, builtins: &'static [Builtin]) -> &mut Self {
127 if self.frames.len() != 1 {
128 panic!("Cannot add builtins to full stack: {self}")
129 }
130
131 for builtin in builtins {
132 self.insert(builtin.name(), builtin.into());
133 }
134
135 self
136 }
137
138 pub fn push_frame(&mut self, name: &'static str, frame: StackFrame) {
139 self.frames.push(EnvFrame {
140 name: Some(name),
141 base: self.values.len(),
142 binds: HashMap::new(),
143 });
144 for (k, v) in frame {
145 self.insert(k, v);
146 }
147 }
148
149 pub fn pop_frame(&mut self) -> Option<(StackFrame, &'static str)> {
150 let mut out = HashMap::new();
151 let EnvFrame { name, base, binds } = self.frames.pop()?;
152 for (k, v) in binds {
153 out.insert(k, self.values.get_mut(v).map(std::mem::take)?);
154 }
155 self.values.truncate(base);
156 Some((out, name.unwrap_or("")))
157 }
158
159 pub fn frame(&mut self, name: &'static str) -> Frame<'_> {
163 Frame::new(self, name)
164 }
165
166 pub fn with_frame<'e>(&'e mut self, name: &'static str, frame: StackFrame) -> Frame<'e> {
171 let mut scope = self.frame(name);
172 for (k, v) in frame {
173 scope.insert(k, v);
174 }
175 scope
176 }
177
178 pub fn get_mut(&mut self, name: Sym) -> IResult<&mut ConValue> {
182 let at = self.id_of(name)?;
183 self.get_id_mut(at).ok_or(Error::NotDefined(name))
184 }
185
186 pub fn get(&self, name: Sym) -> IResult<ConValue> {
190 let id = self.id_of(name)?;
191 let res = self.values.get(id);
192 Ok(res.ok_or(Error::NotDefined(name))?.clone())
193 }
194
195 pub fn id_of(&self, name: Sym) -> IResult<usize> {
197 for EnvFrame { binds, .. } in self.frames.iter().rev() {
198 if let Some(id) = binds.get(&name).copied() {
199 return Ok(id);
200 }
201 }
202 Err(Error::NotDefined(name))
203 }
204
205 pub fn get_id(&self, id: usize) -> Option<&ConValue> {
206 self.values.get(id)
207 }
208
209 pub fn get_id_mut(&mut self, id: usize) -> Option<&mut ConValue> {
210 self.values.get_mut(id)
211 }
212
213 pub fn get_slice(&self, start: usize, len: usize) -> Option<&[ConValue]> {
214 self.values.get(start..start + len)
215 }
216
217 pub fn get_slice_mut(&mut self, start: usize, len: usize) -> Option<&mut [ConValue]> {
218 self.values.get_mut(start..start + len)
219 }
220
221 pub fn insert(&mut self, k: Sym, v: ConValue) {
223 if self.bind_raw(k, self.values.len()).is_some() {
224 self.values.push(v);
225 }
226 }
227
228 pub fn insert_fn(&mut self, decl: &FnDecl) {
230 let FnDecl { name, .. } = decl;
231 let (name, function) = (*name, Rc::new(Function::new(decl)));
232 self.insert(name, ConValue::Function(function.clone()));
233 function.lift_upvars(self);
235 }
236
237 pub fn insert_tup_constructor(&mut self, name: Sym, arity: usize) {
238 let cs = Constructor { arity: arity as _, name };
239 self.insert(name, ConValue::TupleConstructor(cs));
240 }
241
242 pub fn pos(&self) -> usize {
244 self.values.len()
245 }
246
247 pub fn stack_alloc(&mut self, value: ConValue) -> IResult<usize> {
249 let adr = self.values.len();
250 self.values.push(value);
251 Ok(adr)
252 }
253
254 pub fn alloca(&mut self, value: ConValue, len: usize) -> ConValue {
256 let idx = self.values.len();
257 self.values.extend(std::iter::repeat_n(value, len));
258 ConValue::Slice(idx, len)
259 }
260}
261
262#[derive(Debug)]
264pub struct Frame<'scope> {
265 scope: &'scope mut Environment,
266}
267impl<'scope> Frame<'scope> {
268 fn new(scope: &'scope mut Environment, name: &'static str) -> Self {
269 scope.frames.push(EnvFrame {
270 name: Some(name),
271 base: scope.values.len(),
272 binds: HashMap::new(),
273 });
274
275 Self { scope }
276 }
277
278 pub fn pop_values(mut self) -> Option<StackFrame> {
279 let mut out = HashMap::new();
280 let binds = std::mem::take(&mut self.frames.last_mut()?.binds);
281 for (k, v) in binds {
282 out.insert(k, self.values.get_mut(v).map(std::mem::take)?);
283 }
284 Some(out)
285 }
286
287 pub fn into_binds(mut self) -> Option<StackBinds> {
288 let EnvFrame { name: _, base: _, binds } = self.frames.pop()?;
289 std::mem::forget(self);
290 Some(binds)
291 }
292}
293impl Deref for Frame<'_> {
294 type Target = Environment;
295 fn deref(&self) -> &Self::Target {
296 self.scope
297 }
298}
299impl DerefMut for Frame<'_> {
300 fn deref_mut(&mut self) -> &mut Self::Target {
301 self.scope
302 }
303}
304impl Drop for Frame<'_> {
305 fn drop(&mut self) {
306 if let Some(frame) = self.frames.pop() {
307 self.values.truncate(frame.base);
308 }
309 }
310}