1use crate::{
4 builtin::Builtin,
5 place::Place,
6 typeinfo::{self, Model, Type},
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, fmt::FmtAdapter, 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 use std::fmt::Write as _;
73 for EnvFrame { name, binds, .. } in self.frames.iter().rev() {
74 writeln!(
75 f,
76 "--- {}[{}] ---",
77 if let Some(name) = name { name } else { "" },
78 binds.len(),
79 )?;
80 let mut binds: Vec<_> = binds.iter().collect();
81 binds.sort_by_key(|(_, a)| *a);
82 for (name, idx) in binds {
83 let mut f = f.indent();
84 write!(f, "{idx:4} {:16} ", format!("{name}:"))?;
85 match self.values.get(*idx) {
86 Some(ConValue::TypeInfo(t)) => writeln!(f, "type {t}"),
87 Some(ConValue::Function(v)) => writeln!(f, "\n{v}"),
88 Some(value) => writeln!(f, "{value}"),
89 None => writeln!(f, "ERROR: {name}'s address blows the stack!"),
90 }?
91 }
92 }
93 Ok(())
94 }
95}
96
97impl Default for Environment {
98 fn default() -> Self {
99 let mut this = Self::no_builtins();
100 for (ident, model) in Model::defaults() {
101 let value = this.def_type(ident.into(), model.intern());
102 this.bind(ident, ConValue::TypeInfo(value));
103 }
104 this.add_builtins(Builtins).add_builtins(Math);
105 this
106 }
107}
108
109impl Environment {
110 pub fn new() -> Self {
111 Self::default()
112 }
113 pub fn no_builtins() -> Self {
115 Self {
116 values: Vec::new(),
117 frames: vec![EnvFrame::default()],
118 types: HashMap::new(),
119 impls: Vec::new(),
120 }
121 }
122
123 pub fn eval(&mut self, node: &impl Interpret) -> IResult<ConValue> {
125 node.interpret(self)
126 }
127
128 pub fn call(&mut self, name: Symbol, args: &[ConValue]) -> IResult<ConValue> {
131 let function = self.get(name)?;
132 function.call(self, args)
133 }
134
135 pub fn defer(&mut self, expr: cl_ast::Expr) -> Option<()> {
137 let EnvFrame { name: _, span: _, base: _, binds: _, defer } = self.frames.last_mut()?;
138 defer.push(expr);
139 Some(())
140 }
141
142 pub fn bind(&mut self, name: impl Into<Symbol>, value: impl Into<ConValue>) {
144 self.insert(name.into(), value.into());
145 }
146
147 pub fn bind_raw(&mut self, name: Symbol, id: usize) -> Option<()> {
148 let EnvFrame { name: _, span: _, base: _, binds, defer: _ } = self.frames.last_mut()?;
149 binds.insert(name, id);
150 Some(())
151 }
152
153 pub(crate) fn globals(&self) -> &EnvFrame {
155 self.frames.first().unwrap()
156 }
157
158 pub fn backtrace(&self) -> Backtrace<'_> {
159 Backtrace { frames: &self.frames }
160 }
161
162 pub fn add_builtins(&mut self, builtins: &'static [Builtin]) -> &mut Self {
168 if self.frames.len() != 1 {
169 panic!("Cannot add builtins to full stack: {self}")
170 }
171
172 for builtin in builtins {
173 self.insert(
174 builtin.name().expect("Builtin functions must have names!"),
175 builtin.into(),
176 );
177 }
178
179 self
180 }
181
182 pub fn frame(&mut self, name: &'static str, span: Option<Span>) -> Frame<'_> {
186 Frame::new(self, name, span)
187 }
188
189 pub fn with_frame<'e>(&'e mut self, name: &'static str, frame: StackFrame) -> Frame<'e> {
194 let mut scope = self.frame(name, None);
195 for (k, v) in frame {
196 scope.insert(k, v);
197 }
198 scope
199 }
200
201 pub fn get(&self, name: Symbol) -> IResult<ConValue> {
205 let id = self.id_of(name)?;
206 let res = self.values.get(id);
207 Ok(res.ok_or(Error::NotDefined(name))?.clone())
208 }
209
210 pub fn id_of(&self, name: Symbol) -> IResult<usize> {
212 for EnvFrame { binds, .. } in self.frames.iter().rev() {
213 if let Some(id) = binds.get(&name).copied() {
214 return Ok(id);
215 }
216 }
217 Err(Error::NotDefined(name))
218 }
219
220 pub fn get_id(&self, id: usize) -> Option<&ConValue> {
222 self.values.get(id)
223 }
224
225 pub fn get_id_mut(&mut self, id: usize) -> Option<&mut ConValue> {
227 self.values.get_mut(id)
228 }
229
230 pub fn def_type(&mut self, name: Symbol, ty: Type) -> Type {
231 self.types.insert(name, ty);
232 ty
233 }
234
235 pub fn get_type(&self, name: Symbol) -> Option<Type> {
236 self.types.get(&name).copied()
237 }
238
239 pub fn insert(&mut self, k: Symbol, v: ConValue) {
241 if self.bind_raw(k, self.values.len()).is_some() {
242 self.values.push(v);
243 }
244 }
245
246 pub fn stack_alloc(&mut self, value: ConValue) -> IResult<usize> {
248 let adr = self.values.len();
249 self.values.push(value);
250 Ok(adr)
251 }
252}
253
254#[derive(Debug)]
256pub struct Frame<'scope> {
257 scope: &'scope mut Environment,
258}
259impl<'scope> Frame<'scope> {
260 fn new(scope: &'scope mut Environment, name: &'static str, span: Option<Span>) -> Self {
261 scope.frames.push(EnvFrame {
262 name: Some(name),
263 span,
264 base: scope.values.len(),
265 binds: HashMap::new(),
266 defer: vec![],
267 });
268
269 Self { scope }
270 }
271
272 pub fn pop_values(mut self) -> Option<StackFrame> {
273 let mut out = HashMap::new();
274 let binds = take(&mut self.frames.last_mut()?.binds);
275 for (k, v) in binds {
276 out.insert(k, self.values.get_mut(v).map(take)?);
277 }
278 Some(out)
279 }
280}
281impl Deref for Frame<'_> {
282 type Target = Environment;
283 fn deref(&self) -> &Self::Target {
284 self.scope
285 }
286}
287impl DerefMut for Frame<'_> {
288 fn deref_mut(&mut self) -> &mut Self::Target {
289 self.scope
290 }
291}
292impl Drop for Frame<'_> {
293 fn drop(&mut self) {
294 if let Some(EnvFrame { base, defer, .. }) = self.frames.last_mut() {
295 let (base, deferred) = (*base, take(defer));
296 for defer in deferred.iter().rev() {
297 if let Err(e) = defer.interpret(self) {
298 println!("Error during scope cleanup: {e}")
299 }
300 }
301
302 self.frames.pop();
303 self.values.truncate(base);
304 }
305 }
306}