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
+54 -17
View File
@@ -132,7 +132,7 @@ impl<T: VmContext> VmContextExt for T {
}
#[repr(u8)]
pub(crate) enum StepResult {
pub(crate) enum Step {
Continue,
Done,
}
@@ -271,36 +271,42 @@ impl<'gc> Vm<'gc> {
}
#[inline(always)]
pub(crate) fn finish_ok(&mut self, val: fix_common::Value) -> StepResult {
pub(crate) fn finish_ok(&mut self, val: fix_common::Value) -> Step {
self.result = Some(Ok(val));
StepResult::Done
Step::Done
}
#[inline(always)]
pub(crate) fn finish_err(&mut self, err: Box<Error>) -> StepResult {
pub(crate) fn finish_err(&mut self, err: Box<Error>) -> Step {
self.result = Some(Err(err));
StepResult::Done
Step::Done
}
#[inline(always)]
pub(crate) fn finish_vm_err(&mut self, err: VmError) -> StepResult {
pub(crate) fn finish_type_err(&mut self, expected: NixType, got: NixType) -> Step {
self.result = Some(Err(Error::eval_error(format!("expected {expected}, got {got}"))));
Step::Done
}
#[inline(always)]
pub(crate) fn finish_vm_err(&mut self, err: VmError) -> Step {
self.finish_err(err.into_error())
}
#[inline(always)]
pub(crate) fn push_stack(&mut self, val: Value<'gc>) {
pub(crate) fn push(&mut self, val: Value<'gc>) {
self.stack.push(val);
}
#[inline(always)]
#[must_use]
pub(crate) fn pop_stack(&mut self) -> Value<'gc> {
pub(crate) fn pop(&mut self) -> Value<'gc> {
self.stack.pop().expect("stack underflow")
}
#[inline(always)]
#[must_use]
pub(crate) fn peek_stack(&mut self, depth: usize) -> Value<'gc> {
pub(crate) fn peek(&mut self, depth: usize) -> Value<'gc> {
*self
.stack
.get(self.stack.len() - depth - 1)
@@ -308,7 +314,18 @@ impl<'gc> Vm<'gc> {
}
#[inline(always)]
pub(crate) fn replace_stack(&mut self, depth: usize, val: Value<'gc>) {
#[must_use]
pub(crate) fn peek_forced(&mut self, depth: usize) -> StrictValue<'gc> {
self
.stack
.get(self.stack.len() - depth - 1)
.expect("stack underflow")
.restrict()
.expect("forced")
}
#[inline(always)]
pub(crate) fn replace(&mut self, depth: usize, val: Value<'gc>) {
let len = self.stack.len();
*self
.stack
@@ -318,7 +335,7 @@ impl<'gc> Vm<'gc> {
#[inline(always)]
#[cfg_attr(debug_assertions, track_caller)]
pub(crate) fn pop_stack_forced(&mut self) -> StrictValue<'gc> {
pub(crate) fn pop_forced(&mut self) -> StrictValue<'gc> {
self.stack
.pop()
.expect("stack underflow")
@@ -326,14 +343,34 @@ impl<'gc> Vm<'gc> {
.expect("forced")
}
#[inline(always)]
pub(crate) fn pop_forced_expect_inline<T: InlineStorable>(&mut self) -> std::result::Result<T, NixType> {
self.pop_forced().expect_inline::<T>()
}
#[inline(always)]
pub(crate) fn pop_forced_expect_gc<T: GcStorable>(&mut self) -> std::result::Result<Gc<'gc, T>, NixType> {
self.pop_forced().expect_gc::<T>()
}
#[inline(always)]
pub(crate) fn pop_forced_expect_num(&mut self) -> std::result::Result<NixNum, NixType> {
self.pop_forced().expect_num()
}
#[inline(always)]
pub(crate) fn pop_forced_expect_bool(&mut self) -> std::result::Result<bool, NixType> {
self.pop_forced().expect_bool()
}
#[inline(always)]
pub(crate) fn try_force(
&mut self,
depth: usize,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Option<StepResult> {
let thunk = self.peek_stack(depth).as_gc::<Thunk>()?;
) -> Option<Step> {
let thunk = self.peek(depth).as_gc::<Thunk>()?;
let mut state = thunk.borrow_mut(mc);
match *state {
ThunkState::Pending { ip, env, with_env } => {
@@ -349,11 +386,11 @@ impl<'gc> Vm<'gc> {
self.env = env;
self.with_env = with_env;
reader.set_pc(ip);
Some(StepResult::Continue)
Some(Step::Continue)
}
ThunkState::Evaluated(v) => {
drop(state);
self.replace_stack(depth, v.relax());
self.replace(depth, v.relax());
None
}
ThunkState::Apply { .. } => todo!("force apply"),
@@ -545,8 +582,8 @@ impl<'gc> Vm<'gc> {
};
match result {
StepResult::Continue => {}
StepResult::Done => {
Step::Continue => {}
Step::Done => {
return Action::Done(
self.result.take().expect("StepResult::Done without result"),
);