Skip to main content

lambda_ref_cat/
value.rs

1//! Runtime values.
2//!
3//! Extends the spike-1 `Value` with [`Value::Ref`], a first-class cell
4//! reference.  Cells live in the [`Heap`], so a `Ref` carries only an
5//! [`Address`] and the actual contents are looked up against the heap at
6//! deref time.
7//!
8//! [`Heap`]: crate::heap::Heap
9
10use crate::env::Env;
11use crate::heap::Address;
12use crate::syntax::{Expr, VarName};
13
14/// A runtime value.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum Value {
17    /// A function closed over its lexical environment.
18    Closure {
19        /// The parameter the function binds when applied.
20        param: VarName,
21        /// The function body.
22        body: Expr,
23        /// The captured environment.
24        env: Env,
25    },
26    /// A reference to a cell on the heap.
27    Ref(Address),
28}
29
30impl Value {
31    /// Build a closure value.
32    #[must_use]
33    pub fn closure(param: VarName, body: Expr, env: Env) -> Self {
34        Self::Closure { param, body, env }
35    }
36
37    /// Build a reference value.
38    #[must_use]
39    pub fn reference(address: Address) -> Self {
40        Self::Ref(address)
41    }
42}
43
44impl std::fmt::Display for Value {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        match self {
47            Self::Closure { param, body, .. } => write!(f, "\\{param}. {body}"),
48            Self::Ref(address) => write!(f, "ref({address})"),
49        }
50    }
51}