use crate::syntax::VarName;
use crate::value::Value;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub enum Env {
#[default]
Empty,
Cons {
name: VarName,
value: Box<Value>,
rest: Box<Env>,
},
}
impl Env {
#[must_use]
pub fn empty() -> Self {
Self::Empty
}
#[must_use]
pub fn extend(&self, name: VarName, value: Value) -> Self {
Self::Cons {
name,
value: Box::new(value),
rest: Box::new(self.clone()),
}
}
#[must_use]
pub fn lookup(&self, name: &VarName) -> Option<&Value> {
match self {
Self::Empty => None,
Self::Cons {
name: bound,
value,
rest,
} => {
if bound == name {
Some(value)
} else {
rest.lookup(name)
}
}
}
}
}
impl std::fmt::Display for Env {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Empty => f.write_str("{}"),
Self::Cons { name, value, rest } => {
write!(f, "{{{name} = {value}}} :: {rest}")
}
}
}
}