implement __functor

This commit is contained in:
2026-05-04 18:24:33 +08:00
parent 62d65b2e5f
commit 4aff27142c
7 changed files with 79 additions and 8 deletions
+41 -1
View File
@@ -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,
+2 -1
View File
@@ -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 {
+6 -4
View File
@@ -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:?}"),
}