1use crate::{
4 builtin::Builtin,
5 place::Place,
6 typeinfo::{self, Type, TypeInfo},
7};
8
9use super::{
10 Callable, Interpret,
11 builtin::{Builtins, Math},
12 convalue::ConValue,
13 error::{Error, IResult},
14 function::Function,
15};
16use cl_ast::{Bind as FnDecl, types::Symbol};
17use cl_structures::{intern::interned::Interned, span::Span};
18use std::{
19 collections::HashMap,
20 fmt::Display,
21 mem::take,
22 ops::{Deref, DerefMut},
23 rc::Rc,
24};
25
26pub type StackFrame = HashMap<Symbol, ConValue>;
27
28pub type StackBinds = HashMap<Symbol, usize>;
29
30#[derive(Clone, Debug, Default)]
31pub(crate) struct EnvFrame {
32 pub name: Option<&'static str>,
33
34 pub span: Option<Span>,
35 pub base: usize,
37 pub binds: StackBinds,
39 pub defer: Vec<cl_ast::Expr>,
41}
42
43#[derive(Clone, Copy, Debug)]
44pub struct Backtrace<'env> {
45 frames: &'env [EnvFrame],
46}
47
48impl std::fmt::Display for Backtrace<'_> {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 let mut count = 0;
51 for EnvFrame { name, span, .. } in self.frames.iter().rev() {
52 if let (Some(name), Some(span)) = (name, span) {
53 writeln!(f, "{count:>4}: {name}")?;
54 count += 1;
55 }
56 }
57 Ok(())
58 }
59}
60
61#[derive(Clone, Debug)]
63pub struct Environment {
64 values: Vec<ConValue>,
65 frames: Vec<EnvFrame>,
66 types: HashMap<Symbol, Type>,
67 impls: Vec<HashMap<Symbol, ConValue>>,
68}
69
70impl Display for Environment {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 for EnvFrame { name, binds, .. } in self.frames.iter().rev() {
73 writeln!(
74 f,
75 "--- {}[{}] ---",
76 if let Some(name) = name { name } else { "" },
77 binds.len(),
78 )?;
79 let mut binds: Vec<_> = binds.iter().collect();
80 binds.sort_by_key(|(_, a)| *a);
81 for (name, idx) in binds {
82 write!(f, "{idx:4} {name}: ")?;
83 match self.values.get(*idx) {
84 Some(ConValue::TypeInfo(t)) => {
85 writeln!(f, "\t{t:?}")
86 }
87 Some(value) => writeln!(f, "\t{value}"),
88 None => writeln!(f, "ERROR: {name}'s address blows the stack!"),
89 }?
90 }
91 }
92 Ok(())
93 }
94}
95
96impl Default for Environment {
97 fn default() -> Self {
98 let mut this = Self::no_builtins();
99 for TypeInfo { ident, model } in TypeInfo::defaults() {
100 let Some(ident) = ident else {
101 continue;
102 };
103 let value = this.def_type(ident, model);
104 this.bind(ident, ConValue::TypeInfo(value));
105 }
106 this.add_builtins(Builtins).add_builtins(Math);
107 this
108 }
109}
110
111impl Environment {
112 pub fn new() -> Self {
113 Self::default()
114 }
115 pub fn no_builtins() -> Self {
117 Self {
118 values: Vec::new(),
119 frames: vec![EnvFrame::default()],
120 types: HashMap::new(),
121 impls: Vec::new(),
122 }
123 }
124
125 pub fn eval(&mut self, node: &impl Interpret) -> IResult<ConValue> {
127 node.interpret(self)
128 }
129
130 pub fn call(&mut self, name: Symbol, args: &[ConValue]) -> IResult<ConValue> {
133 let function = self.get(name)?;
134 function.call(self, args)
135 }
136
137 pub fn defer(&mut self, expr: cl_ast::Expr) -> Option<()> {
139 let EnvFrame { name: _, span: _, base: _, binds: _, defer } = self.frames.last_mut()?;
140 defer.push(expr);
141 Some(())
142 }
143
144 pub fn bind(&mut self, name: impl Into<Symbol>, value: impl Into<ConValue>) {
146 self.insert(name.into(), value.into());
147 }
148
149 pub fn bind_raw(&mut self, name: Symbol, id: usize) -> Option<()> {
150 let EnvFrame { name: _, span: _, base: _, binds, defer: _ } = self.frames.last_mut()?;
151 binds.insert(name, id);
152 Some(())
153 }
154
155 pub(crate) fn globals(&self) -> &EnvFrame {
157 self.frames.first().unwrap()
158 }
159
160 pub fn backtrace(&self) -> Backtrace<'_> {
161 Backtrace { frames: &self.frames }
162 }
163
164 pub fn add_builtins(&mut self, builtins: &'static [Builtin]) -> &mut Self {
170 if self.frames.len() != 1 {
171 panic!("Cannot add builtins to full stack: {self}")
172 }
173
174 for builtin in builtins {
175 self.insert(
176 builtin.name().expect("Builtin functions must have names!"),
177 builtin.into(),
178 );
179 }
180
181 self
182 }
183
184 pub fn push_frame(&mut self, name: &'static str, frame: StackFrame) {
185 self.frames.push(EnvFrame {
186 name: Some(name),
187 span: None,
188 base: self.values.len(),
189 binds: HashMap::new(),
190 defer: vec![],
191 });
192 for (k, v) in frame {
193 self.insert(k, v);
194 }
195 }
196
197 pub fn pop_frame(&mut self) -> Option<(StackFrame, &'static str)> {
198 let mut out = HashMap::new();
199 let EnvFrame { name, span: _, base, binds, defer } = self.frames.pop()?;
200 for (k, v) in binds {
201 out.insert(k, self.values.get_mut(v).map(std::mem::take)?);
202 }
203 self.values.truncate(base);
204 Some((out, name.unwrap_or("")))
205 }
206
207 pub fn frame(&mut self, name: &'static str, span: Option<Span>) -> Frame<'_> {
211 Frame::new(self, name, span)
212 }
213
214 pub fn with_frame<'e>(&'e mut self, name: &'static str, frame: StackFrame) -> Frame<'e> {
219 let mut scope = self.frame(name, None);
220 for (k, v) in frame {
221 scope.insert(k, v);
222 }
223 scope
224 }
225
226 pub fn get_mut(&mut self, name: Symbol) -> IResult<&mut ConValue> {
230 let at = self.id_of(name)?;
231 self.get_id_mut(at).ok_or(Error::NotDefined(name))
232 }
233
234 pub fn get(&self, name: Symbol) -> IResult<ConValue> {
238 let id = self.id_of(name)?;
239 let res = self.values.get(id);
240 Ok(res.ok_or(Error::NotDefined(name))?.clone())
241 }
242
243 pub fn id_of(&self, name: Symbol) -> IResult<usize> {
245 for EnvFrame { binds, .. } in self.frames.iter().rev() {
246 if let Some(id) = binds.get(&name).copied() {
247 return Ok(id);
248 }
249 }
250 Err(Error::NotDefined(name))
251 }
252
253 pub fn get_id(&self, id: usize) -> Option<&ConValue> {
254 self.values.get(id)
255 }
256
257 pub fn get_id_mut(&mut self, id: usize) -> Option<&mut ConValue> {
258 self.values.get_mut(id)
259 }
260
261 pub fn get_slice(&self, start: usize, len: usize) -> Option<&[ConValue]> {
262 self.values.get(start..start + len)
263 }
264
265 pub fn get_slice_mut(&mut self, start: usize, len: usize) -> Option<&mut [ConValue]> {
266 self.values.get_mut(start..start + len)
267 }
268
269 pub fn def_type(&mut self, name: Symbol, model: typeinfo::Model) -> Type {
270 let typeinfo = TypeInfo { ident: Some(name), model }.intern();
271 self.types.insert(name, (typeinfo));
272 typeinfo
273 }
274 pub fn get_type(&self, name: Symbol) -> Option<Type> {
275 self.types.get(&name).copied()
276 }
277
278 pub fn insert(&mut self, k: Symbol, v: ConValue) {
280 if self.bind_raw(k, self.values.len()).is_some() {
281 self.values.push(v);
282 }
283 }
284
285 pub fn pos(&self) -> usize {
287 self.values.len()
288 }
289
290 pub fn stack_alloc(&mut self, value: ConValue) -> IResult<usize> {
292 let adr = self.values.len();
293 self.values.push(value);
294 Ok(adr)
295 }
296}
297
298#[derive(Debug)]
300pub struct Frame<'scope> {
301 scope: &'scope mut Environment,
302}
303impl<'scope> Frame<'scope> {
304 fn new(scope: &'scope mut Environment, name: &'static str, span: Option<Span>) -> Self {
305 scope.frames.push(EnvFrame {
306 name: Some(name),
307 span,
308 base: scope.values.len(),
309 binds: HashMap::new(),
310 defer: vec![],
311 });
312
313 Self { scope }
314 }
315
316 pub fn pop_values(mut self) -> Option<StackFrame> {
317 let mut out = HashMap::new();
318 let binds = std::mem::take(&mut self.frames.last_mut()?.binds);
319 for (k, v) in binds {
320 out.insert(k, self.values.get_mut(v).map(std::mem::take)?);
321 }
322 Some(out)
323 }
324
325 pub fn into_binds(mut self) -> Option<StackBinds> {
326 let EnvFrame { name: _, span: _, base: _, binds, defer: _ } = self.frames.pop()?;
327 std::mem::forget(self);
328 Some(binds)
329 }
330}
331impl Deref for Frame<'_> {
332 type Target = Environment;
333 fn deref(&self) -> &Self::Target {
334 self.scope
335 }
336}
337impl DerefMut for Frame<'_> {
338 fn deref_mut(&mut self) -> &mut Self::Target {
339 self.scope
340 }
341}
342impl Drop for Frame<'_> {
343 fn drop(&mut self) {
344 if let Some(EnvFrame { base, defer, .. }) = self.frames.last_mut() {
345 let (base, deferred) = (*base, take(defer));
346 for defer in deferred.iter().rev() {
347 if let Err(e) = defer.interpret(self) {
348 println!("Error during scope cleanup: {e}")
349 }
350 }
351
352 self.frames.pop();
353 self.values.truncate(base);
354 }
355 }
356}