vm, runtime: add slots! macro and port filter primop to typed slots
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use fix_bytecode::BytecodeReader;
|
||||
use gc_arena::Mutation;
|
||||
|
||||
use crate::{Break, Forced, Machine, NixType, Step, StrictValue, Value, ValueVariant};
|
||||
|
||||
pub trait SlotContent<'gc> {
|
||||
type Ty: Into<Value<'gc>> + TryFrom<Value<'gc>> + 'gc;
|
||||
}
|
||||
|
||||
impl<'gc> SlotContent<'gc> for Value<'gc> {
|
||||
type Ty = Value<'gc>;
|
||||
}
|
||||
|
||||
impl<'gc> SlotContent<'gc> for StrictValue<'gc> {
|
||||
type Ty = StrictValue<'gc>;
|
||||
}
|
||||
|
||||
impl<'gc, T> SlotContent<'gc> for T
|
||||
where
|
||||
T: ValueVariant<'gc>,
|
||||
{
|
||||
type Ty = T::Ty;
|
||||
}
|
||||
|
||||
pub struct Slot<T> {
|
||||
depth: u8,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Slot<T> {
|
||||
#[inline(always)]
|
||||
pub const fn new(depth: u8) -> Self {
|
||||
Self {
|
||||
depth,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc, T> Slot<T>
|
||||
where
|
||||
T: SlotContent<'gc>,
|
||||
<T::Ty as TryFrom<Value<'gc>>>::Error: std::fmt::Debug,
|
||||
{
|
||||
#[inline(always)]
|
||||
pub fn read<M: Machine<'gc>>(&self, m: &M) -> T::Ty {
|
||||
T::Ty::try_from(m.peek(self.depth as usize)).expect("slot held a value of the wrong type")
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn read_checked<M: Machine<'gc>>(&self, m: &M) -> Result<T::Ty, NixType> {
|
||||
let val = m.peek(self.depth as usize);
|
||||
T::Ty::try_from(val).map_err(|_err| val.ty())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn write<M: Machine<'gc>>(&self, m: &mut M, val: T::Ty) {
|
||||
m.replace(self.depth as usize, T::Ty::into(val));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Slot<Value<'gc>> {
|
||||
#[inline(always)]
|
||||
pub fn force<T: Forced<'gc>, M: Machine<'gc>>(
|
||||
&self,
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> ControlFlow<Break, Slot<T>> {
|
||||
T::force_and_check(m, reader, mc, self.depth as usize, reader.inst_start_pc())?;
|
||||
ControlFlow::Continue(Slot::new(self.depth))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn force_to_pc<M: Machine<'gc>>(
|
||||
&self,
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
pc: usize,
|
||||
) -> Step {
|
||||
m.force_slot_to_pc(self.depth as usize, reader, mc, pc)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user