Skip to main content

cl_interpret/
env.rs

1//! Lexical & non-lexical [scoping](Environment) for variables, and [Backtrace] support
2
3use 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    /// The length of the array when this stack frame was constructed
36    pub base: usize,
37    /// The bindings of name to stack position
38    pub binds: StackBinds,
39    /// A list of deferred instructions to run on scope exit
40    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/// Implements a nested lexical scope
62#[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    /// Creates an [Environment] with no [builtins](super::builtin)
114    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    /// Reflexively evaluates a node
124    pub fn eval(&mut self, node: &impl Interpret) -> IResult<ConValue> {
125        node.interpret(self)
126    }
127
128    /// Calls a function inside the Environment's scope,
129    /// and returns the result
130    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    /// Defers an expression until the end of scope. The expression must not fail..?
136    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    /// Binds a value to the given name in the current scope.
143    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    /// Gets all registered globals, bound or unbound.
154    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    /// Adds builtins
163    ///
164    /// # Panics
165    ///
166    /// Will panic if stack contains more than the globals frame!
167    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    /// Enters a nested scope, returning a [`Frame`] stack-guard.
183    ///
184    /// [`Frame`] implements Deref/DerefMut for [`Environment`].
185    pub fn frame(&mut self, name: &'static str, span: Option<Span>) -> Frame<'_> {
186        Frame::new(self, name, span)
187    }
188
189    /// Enters a nested scope, assigning the contents of `frame`,
190    /// and returning a [`Frame`] stack-guard.
191    ///
192    /// [`Frame`] implements Deref/DerefMut for [`Environment`].
193    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    /// Resolves a variable immutably.
202    ///
203    /// Returns a reference to the variable's contents, if it is defined and initialized.
204    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    /// Resolves the index associated with a [Symbol]
211    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    /// Returns a shared reference to the `id`'s record, if it exists.
221    pub fn get_id(&self, id: usize) -> Option<&ConValue> {
222        self.values.get(id)
223    }
224
225    /// Returns a mutable reference to the `id`'s record, if it exists.
226    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    /// Inserts a new [ConValue] into this [Environment]
240    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    /// Allocates a local variable
247    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/// Represents a stack frame
255#[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}