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 ops::{Deref, DerefMut},
22 rc::Rc,
23};
24
25pub type StackFrame = HashMap<Symbol, ConValue>;
26
27pub type StackBinds = HashMap<Symbol, usize>;
28
29#[derive(Clone, Debug, Default)]
30pub(crate) struct EnvFrame {
31 pub name: Option<&'static str>,
32
33 pub span: Option<Span>,
34 pub base: usize,
36 pub binds: StackBinds,
38}
39
40#[derive(Clone, Copy, Debug)]
41pub struct Backtrace<'env> {
42 frames: &'env [EnvFrame],
43}
44
45impl std::fmt::Display for Backtrace<'_> {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 let mut count = 0;
48 for EnvFrame { name, span, .. } in self.frames.iter().rev() {
49 if let (Some(name), Some(span)) = (name, span) {
50 writeln!(f, "{count:>4}: {name}")?;
51 count += 1;
52 }
53 }
54 Ok(())
55 }
56}
57
58#[derive(Clone, Debug)]
60pub struct Environment {
61 values: Vec<ConValue>,
62 frames: Vec<EnvFrame>,
63 types: HashMap<Symbol, Type>,
64 impls: Vec<HashMap<Symbol, ConValue>>,
65}
66
67impl Display for Environment {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 for EnvFrame { name, binds, .. } in self.frames.iter().rev() {
70 writeln!(
71 f,
72 "--- {}[{}] ---",
73 if let Some(name) = name { name } else { "" },
74 binds.len(),
75 )?;
76 let mut binds: Vec<_> = binds.iter().collect();
77 binds.sort_by_key(|(_, a)| *a);
78 for (name, idx) in binds {
79 write!(f, "{idx:4} {name}: ")?;
80 match self.values.get(*idx) {
81 Some(ConValue::TypeInfo(t)) => {
82 writeln!(f, "\t{t:?}")
83 }
84 Some(value) => writeln!(f, "\t{value}"),
85 None => writeln!(f, "ERROR: {name}'s address blows the stack!"),
86 }?
87 }
88 }
89 Ok(())
90 }
91}
92
93impl Default for Environment {
94 fn default() -> Self {
95 let mut this = Self::no_builtins();
96 for ty in TypeInfo::defaults() {
97 let value = this.def_type(ty.ident, ty.model);
98 this.bind(ty.ident, ConValue::TypeInfo(value));
99 }
100 this.add_builtins(Builtins).add_builtins(Math);
101 this
102 }
103}
104
105impl Environment {
106 pub fn new() -> Self {
107 Self::default()
108 }
109 pub fn no_builtins() -> Self {
111 Self {
112 values: Vec::new(),
113 frames: vec![EnvFrame::default()],
114 types: HashMap::new(),
115 impls: Vec::new(),
116 }
117 }
118
119 pub fn eval(&mut self, node: &impl Interpret) -> IResult<ConValue> {
121 node.interpret(self)
122 }
123
124 pub fn call(&mut self, name: Symbol, args: &[ConValue]) -> IResult<ConValue> {
127 let function = self.get(name)?;
128 function.call(self, args)
129 }
130
131 pub fn bind(&mut self, name: impl Into<Symbol>, value: impl Into<ConValue>) {
133 self.insert(name.into(), value.into());
134 }
135
136 pub fn bind_raw(&mut self, name: Symbol, id: usize) -> Option<()> {
137 let EnvFrame { name: _, span: _, base: _, binds } = self.frames.last_mut()?;
138 binds.insert(name, id);
139 Some(())
140 }
141
142 pub(crate) fn globals(&self) -> &EnvFrame {
144 self.frames.first().unwrap()
145 }
146
147 pub fn backtrace(&self) -> Backtrace<'_> {
148 Backtrace { frames: &self.frames }
149 }
150
151 pub fn add_builtins(&mut self, builtins: &'static [Builtin]) -> &mut Self {
157 if self.frames.len() != 1 {
158 panic!("Cannot add builtins to full stack: {self}")
159 }
160
161 for builtin in builtins {
162 self.insert(
163 builtin.name().expect("Builtin functions must have names!"),
164 builtin.into(),
165 );
166 }
167
168 self
169 }
170
171 pub fn push_frame(&mut self, name: &'static str, frame: StackFrame) {
172 self.frames.push(EnvFrame {
173 name: Some(name),
174 span: None,
175 base: self.values.len(),
176 binds: HashMap::new(),
177 });
178 for (k, v) in frame {
179 self.insert(k, v);
180 }
181 }
182
183 pub fn pop_frame(&mut self) -> Option<(StackFrame, &'static str)> {
184 let mut out = HashMap::new();
185 let EnvFrame { name, span: _, base, binds } = self.frames.pop()?;
186 for (k, v) in binds {
187 out.insert(k, self.values.get_mut(v).map(std::mem::take)?);
188 }
189 self.values.truncate(base);
190 Some((out, name.unwrap_or("")))
191 }
192
193 pub fn frame(&mut self, name: &'static str, span: Option<Span>) -> Frame<'_> {
197 Frame::new(self, name, span)
198 }
199
200 pub fn with_frame<'e>(&'e mut self, name: &'static str, frame: StackFrame) -> Frame<'e> {
205 let mut scope = self.frame(name, None);
206 for (k, v) in frame {
207 scope.insert(k, v);
208 }
209 scope
210 }
211
212 pub fn get_mut(&mut self, name: Symbol) -> IResult<&mut ConValue> {
216 let at = self.id_of(name)?;
217 self.get_id_mut(at).ok_or(Error::NotDefined(name))
218 }
219
220 pub fn get(&self, name: Symbol) -> IResult<ConValue> {
224 let id = self.id_of(name)?;
225 let res = self.values.get(id);
226 Ok(res.ok_or(Error::NotDefined(name))?.clone())
227 }
228
229 pub fn id_of(&self, name: Symbol) -> IResult<usize> {
231 for EnvFrame { binds, .. } in self.frames.iter().rev() {
232 if let Some(id) = binds.get(&name).copied() {
233 return Ok(id);
234 }
235 }
236 Err(Error::NotDefined(name))
237 }
238
239 pub fn get_id(&self, id: usize) -> Option<&ConValue> {
240 self.values.get(id)
241 }
242
243 pub fn get_id_mut(&mut self, id: usize) -> Option<&mut ConValue> {
244 self.values.get_mut(id)
245 }
246
247 pub fn get_slice(&self, start: usize, len: usize) -> Option<&[ConValue]> {
248 self.values.get(start..start + len)
249 }
250
251 pub fn get_slice_mut(&mut self, start: usize, len: usize) -> Option<&mut [ConValue]> {
252 self.values.get_mut(start..start + len)
253 }
254
255 pub fn def_type(&mut self, name: Symbol, model: typeinfo::Model) -> Type {
256 let typeinfo = TypeInfo { ident: name, model }.intern();
257 self.types.insert(name, (typeinfo));
258 typeinfo
259 }
260 pub fn get_type(&self, name: Symbol) -> Option<Type> {
261 self.types.get(&name).copied()
262 }
263
264 pub fn insert(&mut self, k: Symbol, v: ConValue) {
266 if self.bind_raw(k, self.values.len()).is_some() {
267 self.values.push(v);
268 }
269 }
270
271 pub fn pos(&self) -> usize {
273 self.values.len()
274 }
275
276 pub fn stack_alloc(&mut self, value: ConValue) -> IResult<usize> {
278 let adr = self.values.len();
279 self.values.push(value);
280 Ok(adr)
281 }
282}
283
284#[derive(Debug)]
286pub struct Frame<'scope> {
287 scope: &'scope mut Environment,
288}
289impl<'scope> Frame<'scope> {
290 fn new(scope: &'scope mut Environment, name: &'static str, span: Option<Span>) -> Self {
291 scope.frames.push(EnvFrame {
292 name: Some(name),
293 span,
294 base: scope.values.len(),
295 binds: HashMap::new(),
296 });
297
298 Self { scope }
299 }
300
301 pub fn pop_values(mut self) -> Option<StackFrame> {
302 let mut out = HashMap::new();
303 let binds = std::mem::take(&mut self.frames.last_mut()?.binds);
304 for (k, v) in binds {
305 out.insert(k, self.values.get_mut(v).map(std::mem::take)?);
306 }
307 Some(out)
308 }
309
310 pub fn into_binds(mut self) -> Option<StackBinds> {
311 let EnvFrame { name: _, span: _, base: _, binds } = self.frames.pop()?;
312 std::mem::forget(self);
313 Some(binds)
314 }
315}
316impl Deref for Frame<'_> {
317 type Target = Environment;
318 fn deref(&self) -> &Self::Target {
319 self.scope
320 }
321}
322impl DerefMut for Frame<'_> {
323 fn deref_mut(&mut self) -> &mut Self::Target {
324 self.scope
325 }
326}
327impl Drop for Frame<'_> {
328 fn drop(&mut self) {
329 if let Some(frame) = self.frames.pop() {
330 self.values.truncate(frame.base);
331 }
332 }
333}