better type assertion ergonomic

This commit is contained in:
2026-04-20 17:57:54 +08:00
parent 581c333070
commit 11b0b8a78e
13 changed files with 399 additions and 258 deletions
+17 -13
View File
@@ -2,7 +2,8 @@ use fix_common::Symbol;
use fix_error::Error;
use gc_arena::Gc;
use crate::{BytecodeReader, CallFrame, StepResult, WithEnv};
use crate::{BytecodeReader, CallFrame, Step, WithEnv};
use crate::value::*;
impl<'gc> crate::Vm<'gc> {
#[inline(always)]
@@ -11,7 +12,7 @@ impl<'gc> crate::Vm<'gc> {
ctx: &mut impl crate::VmContext,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> StepResult {
) -> Step {
let env = reader.read_operand_data(ctx).resolve(mc, self);
let scope = Gc::new(
mc,
@@ -21,20 +22,20 @@ impl<'gc> crate::Vm<'gc> {
},
);
self.with_env = Some(scope);
StepResult::Continue
Step::Continue
}
#[inline(always)]
pub(crate) fn op_pop_with(&mut self) -> StepResult {
pub(crate) fn op_pop_with(&mut self) -> Step {
let Some(scope) = self.with_env else {
unreachable!("no with_scope to pop");
};
self.with_env = scope.prev;
StepResult::Continue
Step::Continue
}
#[inline(always)]
pub(crate) fn op_prepare_with(&mut self) -> StepResult {
pub(crate) fn op_prepare_with(&mut self) -> Step {
self.call_stack.push(CallFrame {
pc: usize::MAX,
stack_depth: 0,
@@ -42,7 +43,7 @@ impl<'gc> crate::Vm<'gc> {
env: self.env,
with_env: self.with_env,
});
StepResult::Continue
Step::Continue
}
#[inline(always)]
@@ -51,7 +52,7 @@ impl<'gc> crate::Vm<'gc> {
ctx: &mut impl crate::VmContext,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> StepResult {
) -> Step {
let name = reader.read_string_id();
let Some(&WithEnv { env, prev }) = self.with_env.as_deref() else {
@@ -64,23 +65,26 @@ impl<'gc> crate::Vm<'gc> {
Symbol::from(ctx.resolve_string(name))
)));
};
self.push_stack(env);
self.push(env);
if let Some(step) = self.try_force(0, reader, mc) {
return step;
}
let env = self.pop_stack().as_gc::<crate::AttrSet>().unwrap();
let env = match self.pop_forced_expect_gc::<AttrSet>() {
Ok(val) => val,
Err(got) => return self.finish_type_err(NixType::List, got)
};
let Some(val) = env.lookup(name) else {
reader.set_pc(reader.inst_start_pc());
self.with_env = prev;
return StepResult::Continue;
return Step::Continue;
};
self.push_stack(val);
self.push(val);
let Some(CallFrame { with_env, .. }) = self.call_stack.pop() else {
unreachable!()
};
self.with_env = with_env;
StepResult::Continue
Step::Continue
}
}