180 lines
4.9 KiB
Rust
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,
|
|
);
|