From b31c2a4906fb4f94809661000b5683446bd04f16 Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Tue, 21 Apr 2026 09:31:41 +0800 Subject: [PATCH] Step -> ControlFlow (use `?`) --- fix-vm/src/dispatch_tailcall.rs | 6 +- fix-vm/src/instructions/arithmetic.rs | 82 ++++++++---------------- fix-vm/src/instructions/builtins_misc.rs | 4 +- fix-vm/src/instructions/calls.rs | 10 ++- fix-vm/src/instructions/closures.rs | 6 +- fix-vm/src/instructions/collections.rs | 26 +++----- fix-vm/src/instructions/control.rs | 14 ++-- fix-vm/src/instructions/literals.rs | 14 ++-- fix-vm/src/instructions/variables.rs | 8 +-- fix-vm/src/instructions/with_scope.rs | 14 ++-- fix-vm/src/lib.rs | 30 +++++---- 11 files changed, 86 insertions(+), 128 deletions(-) diff --git a/fix-vm/src/dispatch_tailcall.rs b/fix-vm/src/dispatch_tailcall.rs index 94ada3a..8efe6c5 100644 --- a/fix-vm/src/dispatch_tailcall.rs +++ b/fix-vm/src/dispatch_tailcall.rs @@ -2,7 +2,7 @@ use gc_arena::Mutation; -use crate::{BytecodeReader, Step, Vm, VmContext}; +use crate::{Break, BytecodeReader, Step, Vm, VmContext}; pub(crate) enum TailResult { YieldFuel(u32), @@ -36,8 +36,8 @@ extern "rust-preserve-none" fn op_illegal<'gc, C: VmContext>( macro_rules! tail_dispatch_after { ($result:expr, $new_pc:expr, $vm:ident, $mc:ident, $ctx:ident, $bc:ident, $table:ident, $fuel:ident) => {{ match $result { - Step::Continue => {} - Step::Done => return TailResult::Done, + Step::Continue(()) | Step::Break(Break::Force) => {} + Step::Break(Break::Done) => return TailResult::Done, } let new_pc: u32 = $new_pc; if $fuel == 0 { diff --git a/fix-vm/src/instructions/arithmetic.rs b/fix-vm/src/instructions/arithmetic.rs index 6b4afee..a02399e 100644 --- a/fix-vm/src/instructions/arithmetic.rs +++ b/fix-vm/src/instructions/arithmetic.rs @@ -13,12 +13,8 @@ impl<'gc> crate::Vm<'gc> { reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { - if let Some(step) = self.try_force(1, reader, mc) { - return step; - } - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(1, reader, mc)?; + self.try_force(0, reader, mc)?; let rhs = self.pop_forced(); let lhs = self.pop_forced(); if let (Some(ls), Some(rs)) = ( @@ -27,13 +23,13 @@ impl<'gc> crate::Vm<'gc> { ) { let ns = Gc::new(mc, crate::NixString::new(format!("{ls}{rs}"))); self.push(Value::new_gc(ns)); - return Step::Continue; + return Step::Continue(()); } let res = numeric_binop(lhs, rhs, mc, i64::wrapping_add, |a, b| a + b); match res { Ok(val) => { self.push(val); - Step::Continue + Step::Continue(()) } Err(e) => self.finish_vm_err(e), } @@ -65,19 +61,15 @@ impl<'gc> crate::Vm<'gc> { int_op: fn(i64, i64) -> i64, float_op: fn(f64, f64) -> f64, ) -> Step { - if let Some(step) = self.try_force(1, reader, mc) { - return step; - } - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(1, reader, mc)?; + self.try_force(0, reader, mc)?; let rhs = self.pop_forced(); let lhs = self.pop_forced(); let res = numeric_binop(lhs, rhs, mc, int_op, float_op); match res { Ok(val) => { self.push(val); - Step::Continue + Step::Continue(()) } Err(e) => self.finish_vm_err(e), } @@ -89,12 +81,8 @@ impl<'gc> crate::Vm<'gc> { reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { - if let Some(step) = self.try_force(1, reader, mc) { - return step; - } - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(1, reader, mc)?; + self.try_force(0, reader, mc)?; let rhs = self.pop_forced(); let lhs = self.pop_forced(); match (get_num(rhs), get_num(lhs)) { @@ -109,7 +97,7 @@ impl<'gc> crate::Vm<'gc> { match res { Ok(val) => { self.push(val); - Step::Continue + Step::Continue(()) } Err(e) => self.finish_vm_err(e), } @@ -122,18 +110,14 @@ impl<'gc> crate::Vm<'gc> { reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { - if let Some(step) = self.try_force(1, reader, mc) { - return step; - } - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(1, reader, mc)?; + self.try_force(0, reader, mc)?; let eq = match self.values_equal(ctx) { Ok(eq) => eq, Err(e) => return self.finish_vm_err(e), }; self.push(Value::new_inline(eq)); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -143,18 +127,14 @@ impl<'gc> crate::Vm<'gc> { reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { - if let Some(step) = self.try_force(1, reader, mc) { - return step; - } - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(1, reader, mc)?; + self.try_force(0, reader, mc)?; let eq = match self.values_equal(ctx) { Ok(eq) => eq, Err(e) => return self.finish_vm_err(e), }; self.push(Value::new_inline(!eq)); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -204,14 +184,10 @@ impl<'gc> crate::Vm<'gc> { mc: &Mutation<'gc>, pred: fn(Ordering) -> bool, ) -> Step { - if let Some(step) = self.try_force(1, reader, mc) { - return step; - } - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(1, reader, mc)?; + self.try_force(0, reader, mc)?; match self.compare_values_inner(ctx, pred) { - Ok(()) => Step::Continue, + Ok(()) => Step::Continue(()), Err(e) => self.finish_vm_err(e), } } @@ -222,12 +198,8 @@ impl<'gc> crate::Vm<'gc> { reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { - if let Some(step) = self.try_force(1, reader, mc) { - return step; - } - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(1, reader, mc)?; + self.try_force(0, reader, mc)?; let r = match self.pop_forced_expect_gc::() { Ok(val) => val, Err(got) => return self.finish_type_err(NixType::List, got) @@ -240,7 +212,7 @@ impl<'gc> crate::Vm<'gc> { items.extend_from_slice(&l); items.extend_from_slice(&r); self.push(Value::new_gc(Gc::new(mc, crate::List { inner: items }))); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -249,12 +221,8 @@ impl<'gc> crate::Vm<'gc> { reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { - if let Some(step) = self.try_force(1, reader, mc) { - return step; - } - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(1, reader, mc)?; + self.try_force(0, reader, mc)?; let r = match self.pop_forced_expect_gc::() { Ok(val) => val, Err(got) => return self.finish_type_err(NixType::AttrSet, got) @@ -264,7 +232,7 @@ impl<'gc> crate::Vm<'gc> { Err(got) => return self.finish_type_err(NixType::AttrSet, got) }; self.push(Value::new_gc(l.merge(&r, mc))); - Step::Continue + Step::Continue(()) } #[inline(always)] diff --git a/fix-vm/src/instructions/builtins_misc.rs b/fix-vm/src/instructions/builtins_misc.rs index 4295212..13bf18b 100644 --- a/fix-vm/src/instructions/builtins_misc.rs +++ b/fix-vm/src/instructions/builtins_misc.rs @@ -7,7 +7,7 @@ impl<'gc> crate::Vm<'gc> { #[inline(always)] pub(crate) fn op_load_builtins(&mut self) -> Step { self.push(self.builtins); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -18,7 +18,7 @@ impl<'gc> crate::Vm<'gc> { id, arity: fix_builtins::BUILTINS[id as usize].1, })); - Step::Continue + Step::Continue(()) } #[inline(always)] diff --git a/fix-vm/src/instructions/calls.rs b/fix-vm/src/instructions/calls.rs index 0611320..afe4432 100644 --- a/fix-vm/src/instructions/calls.rs +++ b/fix-vm/src/instructions/calls.rs @@ -11,9 +11,7 @@ impl<'gc> crate::Vm<'gc> { reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(0, reader, mc)?; if self.call_depth > 10000 { return self.finish_err(Error::eval_error("stack overflow; max-call-depth exceeded")); } @@ -41,7 +39,7 @@ impl<'gc> crate::Vm<'gc> { } else { todo!("call other types: {func:?}") } - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -109,7 +107,7 @@ impl<'gc> crate::Vm<'gc> { reader.set_pc(inner_ip); self.env = inner_env; self.with_env = inner_with_env; - return Step::Continue; + return Step::Continue(()); } ThunkState::Evaluated(val) => { *outer_thunk.borrow_mut(mc) = ThunkState::Evaluated(val); @@ -132,6 +130,6 @@ impl<'gc> crate::Vm<'gc> { } self.env = env; self.with_env = with_env; - Step::Continue + Step::Continue(()) } } diff --git a/fix-vm/src/instructions/closures.rs b/fix-vm/src/instructions/closures.rs index 2befe3d..8eb1f9d 100644 --- a/fix-vm/src/instructions/closures.rs +++ b/fix-vm/src/instructions/closures.rs @@ -19,7 +19,7 @@ impl<'gc> crate::Vm<'gc> { }), ); self.push(Value::new_gc(thunk)); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -40,7 +40,7 @@ impl<'gc> crate::Vm<'gc> { }, ); self.push(Value::new_gc(closure)); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -90,6 +90,6 @@ impl<'gc> crate::Vm<'gc> { }, ); self.push(Value::new_gc(closure)); - Step::Continue + Step::Continue(()) } } diff --git a/fix-vm/src/instructions/collections.rs b/fix-vm/src/instructions/collections.rs index 07f94a8..8490a1e 100644 --- a/fix-vm/src/instructions/collections.rs +++ b/fix-vm/src/instructions/collections.rs @@ -38,13 +38,13 @@ impl<'gc> crate::Vm<'gc> { kv.sort_by_key(|(k, _)| *k); let attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(kv)); self.push(Value::new_gc(attrs)); - Step::Continue + Step::Continue(()) } #[inline(always)] pub(crate) fn op_make_empty_attrs(&mut self) -> Step { self.push(self.empty_attrs); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -57,9 +57,7 @@ impl<'gc> crate::Vm<'gc> { let _span_id = reader.read_u32(); let key = reader.read_string_id(); - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(0, reader, mc)?; let attrs = self.peek(0).restrict().expect("forced"); let Some(attrset) = attrs.as_gc::() else { @@ -89,7 +87,7 @@ impl<'gc> crate::Vm<'gc> { } }, } - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -101,12 +99,8 @@ impl<'gc> crate::Vm<'gc> { ) -> Step { let _span_id = reader.read_u32(); - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } - if let Some(step) = self.try_force(1, reader, mc) { - return step; - } + self.try_force(0, reader, mc)?; + self.try_force(1, reader, mc)?; let key_val = self.stack[self.stack.len() - 1] .restrict() @@ -136,7 +130,7 @@ impl<'gc> crate::Vm<'gc> { return self.finish_err(Error::eval_error(format!("attribute '{name}' missing"))); } } - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -146,7 +140,7 @@ impl<'gc> crate::Vm<'gc> { ) -> Step { let offset = reader.read_i32(); reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -169,13 +163,13 @@ impl<'gc> crate::Vm<'gc> { } let list = Gc::new(mc, List { inner: items }); self.push(Value::new_gc(list)); - Step::Continue + Step::Continue(()) } #[inline(always)] pub(crate) fn op_make_empty_list(&mut self) -> Step { self.push(self.empty_list); - Step::Continue + Step::Continue(()) } } diff --git a/fix-vm/src/instructions/control.rs b/fix-vm/src/instructions/control.rs index ba6b2ae..e1a371a 100644 --- a/fix-vm/src/instructions/control.rs +++ b/fix-vm/src/instructions/control.rs @@ -8,14 +8,12 @@ impl<'gc> crate::Vm<'gc> { mc: &gc_arena::Mutation<'gc>, ) -> Step { let offset = reader.read_i32(); - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(0, reader, mc)?; let cond = self.pop(); if cond.as_inline::() == Some(false) { reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize); } - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -25,21 +23,19 @@ impl<'gc> crate::Vm<'gc> { mc: &gc_arena::Mutation<'gc>, ) -> Step { let offset = reader.read_i32(); - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(0, reader, mc)?; let cond = self.pop(); if cond.as_inline::() == Some(true) { reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize); } - Step::Continue + Step::Continue(()) } #[inline(always)] pub(crate) fn op_jump(&mut self, reader: &mut BytecodeReader<'_>) -> Step { let offset = reader.read_i32(); reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize); - Step::Continue + Step::Continue(()) } #[inline(always)] diff --git a/fix-vm/src/instructions/literals.rs b/fix-vm/src/instructions/literals.rs index 9f95c41..248b4bd 100644 --- a/fix-vm/src/instructions/literals.rs +++ b/fix-vm/src/instructions/literals.rs @@ -7,7 +7,7 @@ impl<'gc> crate::Vm<'gc> { pub(crate) fn op_push_smi(&mut self, reader: &mut BytecodeReader<'_>) -> Step { let val = reader.read_i32(); self.push(Value::new_inline(val)); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -18,38 +18,38 @@ impl<'gc> crate::Vm<'gc> { ) -> Step { let val = reader.read_i64(); self.push(Value::new_gc(Gc::new(mc, val))); - Step::Continue + Step::Continue(()) } #[inline(always)] pub(crate) fn op_push_float(&mut self, reader: &mut BytecodeReader<'_>) -> Step { let val = reader.read_f64(); self.push(Value::new_float(val)); - Step::Continue + Step::Continue(()) } #[inline(always)] pub(crate) fn op_push_string(&mut self, reader: &mut BytecodeReader<'_>) -> Step { let sid = reader.read_string_id(); self.push(Value::new_inline(sid)); - Step::Continue + Step::Continue(()) } #[inline(always)] pub(crate) fn op_push_null(&mut self) -> Step { self.push(Value::new_inline(crate::Null)); - Step::Continue + Step::Continue(()) } #[inline(always)] pub(crate) fn op_push_true(&mut self) -> Step { self.push(Value::new_inline(true)); - Step::Continue + Step::Continue(()) } #[inline(always)] pub(crate) fn op_push_false(&mut self) -> Step { self.push(Value::new_inline(false)); - Step::Continue + Step::Continue(()) } } diff --git a/fix-vm/src/instructions/variables.rs b/fix-vm/src/instructions/variables.rs index 241023d..8698eab 100644 --- a/fix-vm/src/instructions/variables.rs +++ b/fix-vm/src/instructions/variables.rs @@ -5,7 +5,7 @@ impl<'gc> crate::Vm<'gc> { pub(crate) fn op_load_local(&mut self, reader: &mut BytecodeReader<'_>) -> Step { let idx = reader.read_u32() as usize; self.push(self.env.borrow().locals[idx]); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -19,7 +19,7 @@ impl<'gc> crate::Vm<'gc> { } let val = cur.borrow().locals[idx]; self.push(val); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -31,7 +31,7 @@ impl<'gc> crate::Vm<'gc> { let idx = reader.read_u32() as usize; let val = self.pop(); self.env.borrow_mut(mc).locals[idx] = val; - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -45,6 +45,6 @@ impl<'gc> crate::Vm<'gc> { .borrow_mut(mc) .locals .extend(std::iter::repeat_n(Value::default(), count)); - Step::Continue + Step::Continue(()) } } diff --git a/fix-vm/src/instructions/with_scope.rs b/fix-vm/src/instructions/with_scope.rs index 4a10fde..b8c926e 100644 --- a/fix-vm/src/instructions/with_scope.rs +++ b/fix-vm/src/instructions/with_scope.rs @@ -22,7 +22,7 @@ impl<'gc> crate::Vm<'gc> { }, ); self.with_env = Some(scope); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -31,7 +31,7 @@ impl<'gc> crate::Vm<'gc> { unreachable!("no with_scope to pop"); }; self.with_env = scope.prev; - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -43,7 +43,7 @@ impl<'gc> crate::Vm<'gc> { env: self.env, with_env: self.with_env, }); - Step::Continue + Step::Continue(()) } #[inline(always)] @@ -66,9 +66,7 @@ impl<'gc> crate::Vm<'gc> { ))); }; self.push(env); - if let Some(step) = self.try_force(0, reader, mc) { - return step; - } + self.try_force(0, reader, mc)?; let env = match self.pop_forced_expect_gc::() { Ok(val) => val, @@ -77,7 +75,7 @@ impl<'gc> crate::Vm<'gc> { let Some(val) = env.lookup(name) else { reader.set_pc(reader.inst_start_pc()); self.with_env = prev; - return Step::Continue; + return Step::Continue(()); }; self.push(val); @@ -85,6 +83,6 @@ impl<'gc> crate::Vm<'gc> { unreachable!() }; self.with_env = with_env; - Step::Continue + Step::Continue(()) } } diff --git a/fix-vm/src/lib.rs b/fix-vm/src/lib.rs index e461b1e..0a22dab 100644 --- a/fix-vm/src/lib.rs +++ b/fix-vm/src/lib.rs @@ -132,11 +132,13 @@ impl VmContextExt for T { } #[repr(u8)] -pub(crate) enum Step { - Continue, +pub(crate) enum Break { + Force, Done, } +pub(crate) type Step = std::ops::ControlFlow; + #[derive(Collect)] #[collect(no_drop)] pub struct Vm<'gc> { @@ -273,19 +275,19 @@ impl<'gc> Vm<'gc> { #[inline(always)] pub(crate) fn finish_ok(&mut self, val: fix_common::Value) -> Step { self.result = Some(Ok(val)); - Step::Done + Step::Break(Break::Done) } #[inline(always)] pub(crate) fn finish_err(&mut self, err: Box) -> Step { self.result = Some(Err(err)); - Step::Done + Step::Break(Break::Done) } #[inline(always)] 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 + Step::Break(Break::Done) } #[inline(always)] @@ -369,8 +371,10 @@ impl<'gc> Vm<'gc> { depth: usize, reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, - ) -> Option { - let thunk = self.peek(depth).as_gc::()?; + ) -> Step { + let Some(thunk) = self.peek(depth).as_gc::() else { + return Step::Continue(()); + }; let mut state = thunk.borrow_mut(mc); match *state { ThunkState::Pending { ip, env, with_env } => { @@ -386,17 +390,17 @@ impl<'gc> Vm<'gc> { self.env = env; self.with_env = with_env; reader.set_pc(ip); - Some(Step::Continue) + Step::Break(Break::Force) } ThunkState::Evaluated(v) => { drop(state); self.replace(depth, v.relax()); - None + Step::Continue(()) } ThunkState::Apply { .. } => todo!("force apply"), ThunkState::Blackhole => { drop(state); - Some(self.finish_err(Error::eval_error("infinite recursion encountered"))) + self.finish_err(Error::eval_error("infinite recursion encountered")) } } } @@ -582,10 +586,10 @@ impl<'gc> Vm<'gc> { }; match result { - Step::Continue => {} - Step::Done => { + Step::Continue(()) | Step::Break(Break::Force) => {} + Step::Break(Break::Done) => { return Action::Done( - self.result.take().expect("StepResult::Done without result"), + self.result.take().expect("Break::Done without result"), ); } }