implement __functor
This commit is contained in:
@@ -4,11 +4,12 @@ use gc_arena::{Gc, Mutation, RefLock};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::value::*;
|
||||
use crate::{BytecodeReader, Step, Vm, VmRuntimeCtx, VmRuntimeCtxExt};
|
||||
use crate::{BytecodeReader, NixNum, Step, Vm, VmRuntimeCtx, VmRuntimeCtxExt};
|
||||
|
||||
impl<'gc> Vm<'gc> {
|
||||
pub(crate) fn primop_seq(
|
||||
&mut self,
|
||||
ctx: &mut impl VmRuntimeCtx,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
@@ -36,6 +37,7 @@ impl<'gc> Vm<'gc> {
|
||||
|
||||
pub(crate) fn primop_deep_seq_force_top(
|
||||
&mut self,
|
||||
ctx: &mut impl VmRuntimeCtx,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
@@ -84,6 +86,7 @@ impl<'gc> Vm<'gc> {
|
||||
|
||||
pub(crate) fn primop_deep_seq_push(
|
||||
&mut self,
|
||||
ctx: &mut impl VmRuntimeCtx,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
@@ -271,6 +274,43 @@ impl<'gc> Vm<'gc> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn primop_call_functor_1(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
// Stack invariant on every (re-)entry: [..., orig_arg, self, functor]
|
||||
// where `functor` is TOS. Retries during force land back here safely.
|
||||
let functor = self.force_and_retry::<StrictValue>(reader, mc)?;
|
||||
// Stack now: [..., orig_arg, self]
|
||||
let self_val = self.pop();
|
||||
self.push(functor.relax());
|
||||
// Stack: [..., orig_arg, functor]
|
||||
// Call 1: functor(self). Resume into CallFunctor2 once it returns.
|
||||
self.call(
|
||||
reader,
|
||||
mc,
|
||||
self_val,
|
||||
PrimOpPhase::CallFunctor2.ip() as usize,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn primop_call_functor_2(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
// Stack on entry: [..., orig_arg, intermediate]
|
||||
// call_stack top: synthetic frame with caller's resume_pc.
|
||||
let intermediate = self.pop();
|
||||
let orig_arg = self.pop();
|
||||
let saved = self.call_stack.pop().expect("functor outer frame missing");
|
||||
self.env = saved.env;
|
||||
self.push(intermediate);
|
||||
// Call 2: intermediate(orig_arg). Resume to caller.
|
||||
self.call(reader, mc, orig_arg, saved.pc)
|
||||
}
|
||||
|
||||
pub(crate) fn primop_call_pattern(
|
||||
&mut self,
|
||||
ctx: &mut impl VmRuntimeCtx,
|
||||
|
||||
@@ -3,7 +3,7 @@ use gc_arena::Mutation;
|
||||
|
||||
use crate::bytecode_reader::BytecodeReader;
|
||||
use crate::value::*;
|
||||
use crate::{Step, Vm};
|
||||
use crate::{Step, Vm, VmRuntimeCtx};
|
||||
|
||||
impl<'gc> Vm<'gc> {
|
||||
pub(crate) fn primop_filter_force_list(
|
||||
@@ -44,6 +44,7 @@ impl<'gc> Vm<'gc> {
|
||||
|
||||
pub(crate) fn primop_filter_check(
|
||||
&mut self,
|
||||
ctx: &mut impl VmRuntimeCtx,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Step {
|
||||
|
||||
@@ -32,14 +32,14 @@ impl<'gc> Vm<'gc> {
|
||||
match phase {
|
||||
Abort => self.primop_abort(ctx, reader, mc),
|
||||
|
||||
DeepSeq => self.primop_deep_seq_force_top(reader, mc),
|
||||
DeepSeqPush => self.primop_deep_seq_push(reader, mc),
|
||||
DeepSeq => self.primop_deep_seq_force_top(ctx, reader, mc),
|
||||
DeepSeqPush => self.primop_deep_seq_push(ctx, reader, mc),
|
||||
DeepSeqLoop => self.primop_deep_seq_loop(reader, mc),
|
||||
Seq => self.primop_seq(reader, mc),
|
||||
Seq => self.primop_seq(ctx, reader, mc),
|
||||
|
||||
FilterForceList => self.primop_filter_force_list(reader, mc),
|
||||
FilterCallPred => self.primop_filter_call_pred(reader, mc),
|
||||
FilterCheck => self.primop_filter_check(reader, mc),
|
||||
FilterCheck => self.primop_filter_check(ctx, reader, mc),
|
||||
|
||||
ForceResultShallow => self.primop_force_result_shallow(ctx, reader, mc),
|
||||
ForceResultShallowPush => self.primop_force_result_shallow_push(ctx, reader, mc),
|
||||
@@ -47,6 +47,8 @@ impl<'gc> Vm<'gc> {
|
||||
ForceResultDeepFinish => self.primop_force_result_deep_finish(ctx, reader, mc),
|
||||
|
||||
CallPattern => self.primop_call_pattern(ctx, reader, mc),
|
||||
CallFunctor1 => self.primop_call_functor_1(reader, mc),
|
||||
CallFunctor2 => self.primop_call_functor_2(reader, mc),
|
||||
|
||||
phase => todo!("primop phase {phase:?}"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user