macros, vm, bytecode: add #[handler] await-style primop macro
This commit is contained in:
@@ -2,6 +2,7 @@ mod boxing;
|
||||
mod forced;
|
||||
mod host;
|
||||
mod machine;
|
||||
mod macro_support;
|
||||
mod path_util;
|
||||
mod resolve;
|
||||
mod slot;
|
||||
@@ -13,6 +14,7 @@ pub use fix_bytecode::{BytecodeReader, OperandData};
|
||||
pub use forced::*;
|
||||
pub use host::*;
|
||||
pub use machine::*;
|
||||
pub use macro_support::*;
|
||||
pub use path_util::*;
|
||||
pub use resolve::*;
|
||||
pub use slot::*;
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use gc_arena::Mutation;
|
||||
|
||||
use crate::{
|
||||
Break, BytecodeReader, Forced, Machine, MachineExt, Slot, SlotContent, Step, StrictValue,
|
||||
Value, ValueVariant,
|
||||
};
|
||||
|
||||
pub trait UnwrapSlot {
|
||||
type Unwrapped;
|
||||
}
|
||||
|
||||
impl<T> UnwrapSlot for Slot<T> {
|
||||
type Unwrapped = T;
|
||||
}
|
||||
|
||||
/// Force-target protocol behind the `#[primop]` `force` form: `Value` only
|
||||
/// needs WHNF, `StrictValue` *is* WHNF, and content types are checked through
|
||||
/// [`Forced`] on their stored representation.
|
||||
pub trait ForceTarget<'gc>: SlotContent<'gc> {
|
||||
/// Type-check the stack slot refined by the previous `force(slot)`; the
|
||||
/// slot is already WHNF when this runs.
|
||||
fn refine_check<M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
depth: usize,
|
||||
) -> Step;
|
||||
|
||||
/// Pop and convert the previous suspension's result into the annotated
|
||||
/// binding's stored representation.
|
||||
fn conv_force<M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> ControlFlow<Break, <Self as SlotContent<'gc>>::Ty>;
|
||||
}
|
||||
|
||||
impl<'gc> ForceTarget<'gc> for Value<'gc> {
|
||||
#[inline(always)]
|
||||
fn refine_check<M: Machine<'gc>>(
|
||||
_m: &mut M,
|
||||
_reader: &mut BytecodeReader<'_>,
|
||||
_mc: &Mutation<'gc>,
|
||||
_depth: usize,
|
||||
) -> Step {
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn conv_force<M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> ControlFlow<Break, Value<'gc>> {
|
||||
match m.force_and_retry::<StrictValue<'gc>>(reader, mc) {
|
||||
ControlFlow::Continue(v) => ControlFlow::Continue(v.relax()),
|
||||
ControlFlow::Break(b) => ControlFlow::Break(b),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> ForceTarget<'gc> for StrictValue<'gc> {
|
||||
#[inline(always)]
|
||||
fn refine_check<M: Machine<'gc>>(
|
||||
_m: &mut M,
|
||||
_reader: &mut BytecodeReader<'_>,
|
||||
_mc: &Mutation<'gc>,
|
||||
_depth: usize,
|
||||
) -> Step {
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn conv_force<M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> ControlFlow<Break, StrictValue<'gc>> {
|
||||
m.force_and_retry::<StrictValue<'gc>>(reader, mc)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc, T> ForceTarget<'gc> for T
|
||||
where
|
||||
T: ValueVariant<'gc>,
|
||||
<T as ValueVariant<'gc>>::Ty: Forced<'gc>,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn refine_check<M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
depth: usize,
|
||||
) -> Step {
|
||||
<<T as ValueVariant<'gc>>::Ty as Forced<'gc>>::force_and_check(
|
||||
m,
|
||||
reader,
|
||||
mc,
|
||||
depth,
|
||||
reader.inst_start_pc(),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn conv_force<M: Machine<'gc>>(
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> ControlFlow<Break, <T as SlotContent<'gc>>::Ty> {
|
||||
m.force_and_retry::<<T as ValueVariant<'gc>>::Ty>(reader, mc)
|
||||
}
|
||||
}
|
||||
|
||||
/// Callee protocol behind `call(&slot, ..)`: an unforced `Slot<Value>` is
|
||||
/// WHNF'd before the call; refined slots already hold strict values.
|
||||
pub trait CalleeReady<'gc> {
|
||||
fn callee_ready<M: Machine<'gc>>(
|
||||
&self,
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> ControlFlow<Break>;
|
||||
}
|
||||
|
||||
impl<'gc> CalleeReady<'gc> for Slot<Value<'gc>> {
|
||||
#[inline(always)]
|
||||
fn callee_ready<M: Machine<'gc>>(
|
||||
&self,
|
||||
m: &mut M,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> ControlFlow<Break> {
|
||||
self.force::<StrictValue<'gc>, M>(m, reader, mc)?;
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> CalleeReady<'gc> for Slot<StrictValue<'gc>> {
|
||||
#[inline(always)]
|
||||
fn callee_ready<M: Machine<'gc>>(
|
||||
&self,
|
||||
_m: &mut M,
|
||||
_reader: &mut BytecodeReader<'_>,
|
||||
_mc: &Mutation<'gc>,
|
||||
) -> ControlFlow<Break> {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc, T> CalleeReady<'gc> for Slot<T>
|
||||
where
|
||||
T: ValueVariant<'gc>,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn callee_ready<M: Machine<'gc>>(
|
||||
&self,
|
||||
_m: &mut M,
|
||||
_reader: &mut BytecodeReader<'_>,
|
||||
_mc: &Mutation<'gc>,
|
||||
) -> ControlFlow<Break> {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,11 @@ 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<Value<'gc>> + TryFrom<Value<'gc>> + 'gc;
|
||||
}
|
||||
@@ -50,12 +55,6 @@ where
|
||||
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));
|
||||
|
||||
Reference in New Issue
Block a user