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}