Skip to main content

lambda_ref_cat/
env.rs

1//! Persistent lexical environments.
2//!
3//! Identical in shape to the spike-1 env: a cons-list of `(name, value)`
4//! bindings with shadowing and persistent extension.
5
6use crate::syntax::VarName;
7use crate::value::Value;
8
9/// A persistent lexical environment.
10#[derive(Debug, Clone, Default, PartialEq, Eq)]
11pub enum Env {
12    /// The empty environment.
13    #[default]
14    Empty,
15    /// A binding of `name` to `value`, atop the rest of the environment.
16    Cons {
17        /// The bound name.
18        name: VarName,
19        /// The bound value.
20        value: Box<Value>,
21        /// The environment without this binding.
22        rest: Box<Env>,
23    },
24}
25
26impl Env {
27    /// The environment with no bindings.
28    #[must_use]
29    pub fn empty() -> Self {
30        Self::Empty
31    }
32
33    /// Return a new environment with `name` bound to `value` shadowing any
34    /// prior binding of `name`.
35    #[must_use]
36    pub fn extend(&self, name: VarName, value: Value) -> Self {
37        Self::Cons {
38            name,
39            value: Box::new(value),
40            rest: Box::new(self.clone()),
41        }
42    }
43
44    /// Look up the most recent binding of `name`, or `None` if unbound.
45    #[must_use]
46    pub fn lookup(&self, name: &VarName) -> Option<&Value> {
47        match self {
48            Self::Empty => None,
49            Self::Cons {
50                name: bound,
51                value,
52                rest,
53            } => {
54                if bound == name {
55                    Some(value)
56                } else {
57                    rest.lookup(name)
58                }
59            }
60        }
61    }
62}
63
64impl std::fmt::Display for Env {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        match self {
67            Self::Empty => f.write_str("{}"),
68            Self::Cons { name, value, rest } => {
69                write!(f, "{{{name} = {value}}} :: {rest}")
70            }
71        }
72    }
73}