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("#"), Self::Lambda(_) => f.write_str("#"), Self::Bool(b) => f.write_str(if *b { "#t" } else { "#f" }), Self::Trap => Ok(()), } } } impl Value { crate fn as_num(&self) -> Result { if let Self::Num(n) = self { Ok(*n) } else { Err(eval::RTError("Expected a number".to_owned())) } } crate fn as_func(&self) -> Result { 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 { if let Self::Bool(b) = self { Ok(*b) } else { Err(eval::RTError("Expected a bool".to_owned())) } } }