Files
lysp/src/vm/value/convert.rs
T

180 lines
4.9 KiB
Rust

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<Self, ValueConversionError>;
}
pub enum AnyFunction {
Native(NativeFunction),
Function(Rc<BytecodeFunction>),
Closure(ClosureValue),
}
macro_rules! impl_integer {
($($ty:ty : $bits:literal),+ $(,)?) => {
$(
impl TryFromValue<'_> for $ty {
fn try_from_value(value: &Value) -> Result<Self, ValueConversionError> {
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<Self, ValueConversionError> {
match value {
Value::Boolean(BooleanValue(value)) => Ok(*value),
_ => Err(ValueConversionError {
expected: "#T or #F".into(),
got: value.clone(),
}),
}
}
}
impl From<bool> for Value {
fn from(value: bool) -> Self {
Value::Boolean(value.into())
}
}
impl TryFromValue<'_> for NumberValue {
fn try_from_value(value: &'_ Value) -> Result<Self, ValueConversionError> {
match value {
Value::Number(value) => Ok(*value),
_ => Err(ValueConversionError {
expected: "integer value".into(),
got: value.clone(),
}),
}
}
}
impl From<NumberValue> 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<Self, ValueConversionError> {
match value {
Value::Cons(cons) => Ok(cons.as_ref()),
_ => Err(ValueConversionError {
expected: "cons cell".into(),
got: value.clone(),
}),
}
}
}
impl From<Rc<Vector>> for Value {
fn from(value: Rc<Vector>) -> Self {
Self::Vector(value)
}
}
impl TryFromValue<'_> for StringValue {
fn try_from_value(value: &'_ Value) -> Result<Self, ValueConversionError> {
match value {
Value::String(value) => Ok(value.clone()),
_ => Err(ValueConversionError {
expected: "string".into(),
got: value.clone(),
}),
}
}
}
impl From<NativeValue> for Value {
fn from(value: NativeValue) -> Self {
Self::NativeValue(value)
}
}
impl From<Vec<u8>> for Value {
fn from(value: Vec<u8>) -> Self {
Value::Vector(Rc::new(Vector::from_iter(value)))
}
}
impl From<IdentifierValue> for Value {
fn from(value: IdentifierValue) -> Self {
Value::Identifier(value)
}
}
impl TryFromValue<'_> for AnyFunction {
fn try_from_value(value: &'_ Value) -> Result<Self, ValueConversionError> {
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<Environment>,
args: &[Value],
) -> Result<Value, MachineError> {
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,
);