handball/src/value.rs

73 lines
2.0 KiB
Rust

use crate::{ast, eval, prims};
use std::rc::Rc;
#[derive(Clone)]
crate enum Value {
Num(f64),
Func(prims::Func),
Lambda(ast::Lambda),
Bool(bool),
/// Result of things that shouldnt have values, like (define x 3)
Trap,
}
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
use Value::*;
match (self, other) {
(Num(l), Num(r)) => l == r,
(Func(l), Func(r)) => *l as usize == *r as usize,
(Bool(l), Bool(r)) => l == r,
(Lambda(l), Lambda(r)) => Rc::ptr_eq(&l.0, &r.0) && Rc::ptr_eq(&l.1, &r.1),
(Num(_), _) => false,
(Func(_), _) => false,
(Bool(_), _) => false,
(Lambda(_), _) => false,
(Trap, _) => panic!("Trap value"),
}
}
}
impl std::fmt::Debug for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Num(n) => n.fmt(f),
Self::Func(_) => f.write_str("#<procedure>"),
Self::Lambda(_) => f.write_str("#<procedure>"),
Self::Bool(b) => f.write_str(if *b { "#t" } else { "#f" }),
Self::Trap => Ok(()),
}
}
}
impl Value {
crate fn as_num(&self) -> Result<f64, eval::RTError> {
if let Self::Num(n) = self {
Ok(*n)
} else {
Err(eval::RTError("Expected a number".to_owned()))
}
}
crate fn as_func(&self) -> Result<eval::Callable, eval::RTError> {
match self {
Self::Func(f) => Ok(eval::Callable::Func(*f)),
Self::Lambda(l) => Ok(eval::Callable::Lambda(l)),
_ => Err(eval::RTError(format!(
"Expected a function, got {:?}",
self
))),
}
}
crate fn as_bool(&self) -> Result<bool, eval::RTError> {
if let Self::Bool(b) = self {
Ok(*b)
} else {
Err(eval::RTError("Expected a bool".to_owned()))
}
}
}