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 struct TypeError { pub expected: NixType, pub got: NixType, } pub trait SlotContent<'gc> { type Ty: Into> + TryFrom> + '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 { depth: u8, _marker: PhantomData, } impl Slot { #[inline(always)] pub const fn new(depth: u8) -> Self { Self { depth, _marker: PhantomData, } } } impl<'gc, T> Slot where T: SlotContent<'gc>, >>::Error: std::fmt::Debug, { #[inline(always)] pub fn read>(&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 write>(&self, m: &mut M, val: T::Ty) { m.replace(self.depth as usize, T::Ty::into(val)); } } impl<'gc> Slot> { #[inline(always)] pub fn force, M: Machine<'gc>>( &self, m: &mut M, reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> ControlFlow> { 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>( &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) } }