implement primop (filter)

This commit is contained in:
2026-04-25 21:08:54 +08:00
parent 4f3cd0ef4c
commit 26717a8184
18 changed files with 560 additions and 129 deletions
+42 -16
View File
@@ -142,6 +142,7 @@ impl<T: VmRuntimeCtx> VmRuntimeCtxExt for T {
} else if let Some(list) = val.as_gc::<List>() {
let items: Vec<_> = list
.inner
.borrow()
.iter()
.copied()
.map(|v| self.convert_value(v))
@@ -151,10 +152,12 @@ impl<T: VmRuntimeCtx> VmRuntimeCtxExt for T {
Value::Func
} else if val.is::<Thunk>() {
Value::Thunk
} else if val.as_inline::<PrimOp>().is_some() {
Value::PrimOp("primop".into())
} else if val.is::<PrimOpApp>() {
Value::PrimOpApp("primop-app".into())
} else if let Some(primop) = val.as_inline::<PrimOp>() {
let name = fix_builtins::BUILTINS[primop.id as usize].0;
Value::PrimOp(name.strip_prefix("__").unwrap_or(name))
} else if let Some(app) = val.as_gc::<PrimOpApp>() {
let name = fix_builtins::BUILTINS[app.primop.id as usize].0;
Value::PrimOpApp(name.strip_prefix("__").unwrap_or(name))
} else {
Value::Null
}
@@ -231,7 +234,15 @@ fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmRuntimeCtx) -> Value<
let id = BuiltinId::try_from_primitive(idx as u8).expect("infallible");
let name = name.strip_prefix("__").unwrap_or(name);
let name = ctx.intern_string(name);
entries.push((name, Value::new_inline(PrimOp { id, arity })));
let dispatch_ip = id.entry_phase().ip();
entries.push((
name,
Value::new_inline(PrimOp {
id,
arity,
dispatch_ip,
}),
));
}
let consts = [
@@ -248,15 +259,7 @@ fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmRuntimeCtx) -> Value<
"__storeDir",
Value::new_inline(ctx.intern_string("/nix/store")),
),
(
"__nixPath",
Value::new_gc(Gc::new(
mc,
List {
inner: SmallVec::new(),
},
)),
),
("__nixPath", Value::new_gc(Gc::new(mc, List::default()))),
("null", Value::new_inline(Null)),
("true", Value::new_inline(true)),
("false", Value::new_inline(false)),
@@ -382,16 +385,38 @@ impl<'gc> Vm<'gc> {
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> std::ops::ControlFlow<Break, T> {
T::force_and_check(self, reader, mc, 0)?;
self.try_force_to_pc(reader, mc, reader.inst_start_pc())
}
#[inline(always)]
pub(crate) fn try_force_to_pc<T: Forced<'gc>>(
&mut self,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
resume_pc: usize,
) -> std::ops::ControlFlow<Break, T> {
T::force_and_check(self, reader, mc, 0, resume_pc)?;
std::ops::ControlFlow::Continue(T::pop_converted(self))
}
#[inline(always)]
#[allow(unused)]
pub(crate) fn force_slot(
&mut self,
depth: usize,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
self.force_slot_to_pc(depth, reader, mc, reader.inst_start_pc())
}
#[inline(always)]
pub(crate) fn force_slot_to_pc(
&mut self,
depth: usize,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
resume_pc: usize,
) -> Step {
let Some(thunk) = self.peek(depth).as_gc::<Thunk>() else {
return Step::Continue(());
@@ -404,7 +429,7 @@ impl<'gc> Vm<'gc> {
self.call_stack.push(CallFrame {
thunk: Some(thunk),
stack_depth: depth,
pc: reader.inst_start_pc(),
pc: resume_pc,
env: self.env,
with_env: self.with_env,
});
@@ -554,6 +579,7 @@ impl<'gc> Vm<'gc> {
MakePatternClosure => self.op_make_pattern_closure(&mut reader, mc),
Call => self.op_call(ctx, &mut reader, mc),
DispatchPrimOp => self.op_dispatch_primop(ctx, &mut reader, mc),
Return => self.op_return(ctx, &mut reader, mc),
MakeAttrs => self.op_make_attrs(ctx, &mut reader, mc),