88 lines
2.8 KiB
Rust
88 lines
2.8 KiB
Rust
use crate::{eval, prims};
|
|
use std::rc::Rc;
|
|
|
|
#[derive(Clone /*, debug2::Debug*/)]
|
|
crate enum Value {
|
|
Num(f64),
|
|
// TODO: implement debug2::Debug for `fn` type, and do it right
|
|
// https://godbolt.org/z/vr9erGeKq
|
|
Func(prims::NativeFunc),
|
|
Lambda(eval::Lambda),
|
|
Bool(bool),
|
|
/// Result of things that shouldnt have values, like (define x 3)
|
|
/// TODO: Figure this out
|
|
Trap,
|
|
}
|
|
|
|
impl std::fmt::Debug for Value {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Num(arg0) => f.debug_tuple("Num").field(arg0).finish(),
|
|
// We cant just pass the field because of livetime bs, see https://godbolt.org/z/vr9erGeKq
|
|
Self::Func(_) => f.debug_struct("Func").finish_non_exhaustive(),
|
|
Self::Lambda(arg0) => f.debug_tuple("Lambda").field(arg0).finish(),
|
|
Self::Bool(arg0) => f.debug_tuple("Bool").field(arg0).finish(),
|
|
Self::Trap => write!(f, "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.func, &r.func) && Rc::ptr_eq(&l.captures, &r.captures)
|
|
}
|
|
|
|
(Num(_), _) => false,
|
|
(Func(_), _) => false,
|
|
(Bool(_), _) => false,
|
|
(Lambda(_), _) => false,
|
|
|
|
(Trap, _) => panic!("Trap value"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for Value {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Num(n) => std::fmt::Debug::fmt(n, f), // TODO: Change to displays
|
|
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()))
|
|
}
|
|
}
|
|
}
|