use std::rc::Rc; use crate::{ error::{MachineError, ValueConversionError}, vm::{ Value, env::Environment, machine::Machine, value::{ BooleanValue, BytecodeFunction, ClosureValue, ConsCell, IdentifierValue, NativeFunction, NativeValue, NumberValue, StringValue, Vector, }, }, }; pub trait TryFromValue<'a>: Sized { fn try_from_value(value: &'a Value) -> Result; } pub enum AnyFunction { Native(NativeFunction), Function(Rc), Closure(ClosureValue), } macro_rules! impl_integer { ($($ty:ty : $bits:literal),+ $(,)?) => { $( impl TryFromValue<'_> for $ty { fn try_from_value(value: &Value) -> Result { match value { #[allow(irrefutable_let_patterns)] Value::Number(value) if let Ok(value) = <$ty>::try_from(*value) => Ok(value), _ => Err(ValueConversionError { expected: format!("{}-bit integer", $bits), got: value.clone() }) } } } impl From<$ty> for Value { fn from(value: $ty) -> Value { Value::Number(value.into()) } } )+ }; } impl TryFromValue<'_> for bool { fn try_from_value(value: &'_ Value) -> Result { match value { Value::Boolean(BooleanValue(value)) => Ok(*value), _ => Err(ValueConversionError { expected: "#T or #F".into(), got: value.clone(), }), } } } impl From for Value { fn from(value: bool) -> Self { Value::Boolean(value.into()) } } impl TryFromValue<'_> for NumberValue { fn try_from_value(value: &'_ Value) -> Result { match value { Value::Number(value) => Ok(*value), _ => Err(ValueConversionError { expected: "integer value".into(), got: value.clone(), }), } } } impl From for Value { fn from(value: NumberValue) -> Self { Self::Number(value) } } impl<'a> TryFromValue<'a> for &'a ConsCell { fn try_from_value(value: &'a Value) -> Result { match value { Value::Cons(cons) => Ok(cons.as_ref()), _ => Err(ValueConversionError { expected: "cons cell".into(), got: value.clone(), }), } } } impl From> for Value { fn from(value: Rc) -> Self { Self::Vector(value) } } impl TryFromValue<'_> for StringValue { fn try_from_value(value: &'_ Value) -> Result { match value { Value::String(value) => Ok(value.clone()), _ => Err(ValueConversionError { expected: "string".into(), got: value.clone(), }), } } } impl From for Value { fn from(value: NativeValue) -> Self { Self::NativeValue(value) } } impl From> for Value { fn from(value: Vec) -> Self { Value::Vector(Rc::new(Vector::from_iter(value))) } } impl From for Value { fn from(value: IdentifierValue) -> Self { Value::Identifier(value) } } impl TryFromValue<'_> for AnyFunction { fn try_from_value(value: &'_ Value) -> Result { match value { Value::NativeFunction(function) => Ok(Self::Native(function.clone())), Value::Closure(closure) => Ok(Self::Closure(closure.clone())), Value::Function(function) => Ok(Self::Function(function.clone())), _ => Err(ValueConversionError { expected: "function".into(), got: value.clone(), }), } } } impl AnyFunction { pub fn invoke( &self, vm: &mut Machine, env: &Rc, args: &[Value], ) -> Result { match self { Self::Native(function) => function.invoke(vm, env, args), Self::Closure(closure) => vm .evaluate_closure_args(env, closure.clone(), args) .map_err(|error| error.error), Self::Function(function) => { let closure = ClosureValue { function: function.clone(), upvalues: vec![], }; vm.evaluate_closure_args(env, closure, args) .map_err(|error| error.error) } } } } impl_integer!( i8: 8, i16: 16, i32: 32, i64: 64, usize: 64, );