refactor with

This commit is contained in:
2026-05-04 15:43:35 +08:00
parent fca00b04ba
commit b3e6591809
13 changed files with 162 additions and 344 deletions
+40 -54
View File
@@ -26,9 +26,9 @@ mod value;
pub use value::StaticValue;
use value::*;
mod helpers;
pub(crate) mod instructions;
pub(crate) use bytecode_reader::BytecodeReader;
pub(crate) use forced::Forced;
mod instructions;
use bytecode_reader::BytecodeReader;
use forced::Forced;
use helpers::*;
type VmResult<T> = std::result::Result<T, VmError>;
@@ -83,7 +83,7 @@ pub trait VmCode {
) -> fix_error::Result<InstructionPtr>;
}
pub(crate) trait VmRuntimeCtxExt: VmRuntimeCtx {
trait VmRuntimeCtxExt: VmRuntimeCtx {
fn get_string<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str>;
fn get_string_id<'a, 'gc: 'a>(
&'a mut self,
@@ -193,39 +193,38 @@ impl<T: VmRuntimeCtx> ConvertValueWithSeen for T {
}
#[repr(u8)]
pub(crate) enum Break {
enum Break {
Force,
Done,
}
pub(crate) type Step = std::ops::ControlFlow<Break>;
type Step = std::ops::ControlFlow<Break>;
#[derive(Collect)]
#[collect(no_drop)]
pub struct Vm<'gc> {
pub(crate) stack: Vec<Value<'gc>>,
pub(crate) call_stack: Vec<CallFrame<'gc>>,
pub(crate) call_depth: usize,
stack: Vec<Value<'gc>>,
call_stack: Vec<CallFrame<'gc>>,
call_depth: usize,
#[allow(dead_code)]
#[collect(require_static)]
pub(crate) error_context: Vec<ErrorFrame>,
error_context: Vec<ErrorFrame>,
pub(crate) env: GcEnv<'gc>,
pub(crate) with_env: Option<GcWithEnv<'gc>>,
env: GcEnv<'gc>,
pub(crate) import_cache: HashMap<PathBuf, Value<'gc>>,
import_cache: HashMap<PathBuf, Value<'gc>>,
pub(crate) builtins: Value<'gc>,
pub(crate) empty_list: Value<'gc>,
pub(crate) empty_attrs: Value<'gc>,
builtins: Value<'gc>,
empty_list: Value<'gc>,
empty_attrs: Value<'gc>,
pub(crate) force_mode: ForceMode,
force_mode: ForceMode,
#[collect(require_static)]
pub(crate) result: Option<Result<fix_common::Value>>,
result: Option<Result<fix_common::Value>>,
}
pub(crate) enum OperandData {
enum OperandData {
Const(StaticValue),
BigInt(i64),
Local { layer: u8, idx: u32 },
@@ -233,11 +232,10 @@ pub(crate) enum OperandData {
Builtins,
ReplBinding(StringId),
ScopedImportBinding(StringId),
WithLookup(StringId),
}
impl OperandData {
pub(crate) fn resolve<'gc>(&self, mc: &Mutation<'gc>, root: &Vm<'gc>) -> Value<'gc> {
fn resolve<'gc>(&self, mc: &Mutation<'gc>, root: &Vm<'gc>) -> Value<'gc> {
use OperandData::*;
match *self {
Const(sv) => sv.into(),
@@ -260,7 +258,6 @@ impl OperandData {
Builtins => root.builtins,
ReplBinding(_id) => todo!(),
ScopedImportBinding(_id) => todo!(),
WithLookup(_id) => todo!(),
}
}
}
@@ -332,7 +329,6 @@ impl<'gc> Vm<'gc> {
error_context: Vec::with_capacity(1024),
env: Gc::new(mc, RefLock::new(Env::empty())),
with_env: None,
import_cache: HashMap::new(),
@@ -347,19 +343,19 @@ impl<'gc> Vm<'gc> {
}
#[inline(always)]
pub(crate) fn finish_ok(&mut self, val: fix_common::Value) -> Step {
fn finish_ok(&mut self, val: fix_common::Value) -> Step {
self.result = Some(Ok(val));
Step::Break(Break::Done)
}
#[inline(always)]
pub(crate) fn finish_err(&mut self, err: Box<Error>) -> Step {
fn finish_err(&mut self, err: Box<Error>) -> Step {
self.result = Some(Err(err));
Step::Break(Break::Done)
}
#[inline(always)]
pub(crate) fn finish_type_err(&mut self, expected: NixType, got: NixType) -> Step {
fn finish_type_err(&mut self, expected: NixType, got: NixType) -> Step {
self.result = Some(Err(Error::eval_error(format!(
"expected {expected}, got {got}"
))));
@@ -367,24 +363,24 @@ impl<'gc> Vm<'gc> {
}
#[inline(always)]
pub(crate) fn finish_vm_err(&mut self, err: VmError) -> Step {
fn finish_vm_err(&mut self, err: VmError) -> Step {
self.finish_err(err.into_error())
}
#[inline(always)]
pub(crate) fn push(&mut self, val: Value<'gc>) {
fn push(&mut self, val: Value<'gc>) {
self.stack.push(val);
}
#[inline(always)]
#[must_use]
pub(crate) fn pop(&mut self) -> Value<'gc> {
fn pop(&mut self) -> Value<'gc> {
self.stack.pop().expect("stack underflow")
}
#[inline(always)]
#[must_use]
pub(crate) fn peek(&mut self, depth: usize) -> Value<'gc> {
fn peek(&mut self, depth: usize) -> Value<'gc> {
*self
.stack
.get(self.stack.len() - depth - 1)
@@ -393,7 +389,7 @@ impl<'gc> Vm<'gc> {
#[inline(always)]
#[must_use]
pub(crate) fn peek_forced(&mut self, depth: usize) -> StrictValue<'gc> {
fn peek_forced(&mut self, depth: usize) -> StrictValue<'gc> {
self.stack
.get(self.stack.len() - depth - 1)
.expect("stack underflow")
@@ -402,7 +398,7 @@ impl<'gc> Vm<'gc> {
}
#[inline(always)]
pub(crate) fn replace(&mut self, depth: usize, val: Value<'gc>) {
fn replace(&mut self, depth: usize, val: Value<'gc>) {
let len = self.stack.len();
*self
.stack
@@ -412,7 +408,7 @@ impl<'gc> Vm<'gc> {
#[inline(always)]
#[cfg_attr(debug_assertions, track_caller)]
pub(crate) fn pop_forced(&mut self) -> StrictValue<'gc> {
fn pop_forced(&mut self) -> StrictValue<'gc> {
self.stack
.pop()
.expect("stack underflow")
@@ -447,7 +443,7 @@ impl<'gc> Vm<'gc> {
/// * The return value must be propagated with `?` so that
/// `Break::Force` correctly unwinds to the dispatch loop.
#[inline(always)]
pub(crate) fn force_and_retry<T: Forced<'gc>>(
fn force_and_retry<T: Forced<'gc>>(
&mut self,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
@@ -458,7 +454,7 @@ impl<'gc> Vm<'gc> {
/// Same as [`force_and_retry`](Self::force_and_retry) but allows
/// specifying a custom resume PC.
#[inline(always)]
pub(crate) fn force_and_retry_pc<T: Forced<'gc>>(
fn force_and_retry_pc<T: Forced<'gc>>(
&mut self,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
@@ -470,7 +466,7 @@ impl<'gc> Vm<'gc> {
#[inline(always)]
#[allow(unused)]
pub(crate) fn force_slot(
fn force_slot(
&mut self,
depth: usize,
reader: &mut BytecodeReader<'_>,
@@ -480,7 +476,7 @@ impl<'gc> Vm<'gc> {
}
#[inline(always)]
pub(crate) fn force_slot_to_pc(
fn force_slot_to_pc(
&mut self,
depth: usize,
reader: &mut BytecodeReader<'_>,
@@ -492,17 +488,14 @@ impl<'gc> Vm<'gc> {
};
let mut state = thunk.borrow_mut(mc);
match *state {
ThunkState::Pending { ip, env, with_env } => {
ThunkState::Pending { ip, env } => {
*state = ThunkState::Blackhole;
self.call_stack.push(CallFrame {
thunk: Some(thunk),
stack_depth: depth,
pc: resume_pc,
env: self.env,
with_env: self.with_env,
});
self.env = env;
self.with_env = with_env;
reader.set_pc(ip);
Step::Break(Break::Force)
}
@@ -513,10 +506,8 @@ impl<'gc> Vm<'gc> {
ThunkState::Apply { func, arg } => {
self.call_stack.push(CallFrame {
thunk: Some(thunk),
stack_depth: depth,
pc: resume_pc,
env: self.env,
with_env: self.with_env,
});
self.push(func);
self.call(reader, mc, arg, resume_pc)
@@ -536,20 +527,18 @@ struct ErrorFrame {
#[derive(Collect, Debug)]
#[collect(no_drop)]
pub(crate) struct CallFrame<'gc> {
pub(crate) pc: usize,
pub(crate) stack_depth: usize,
pub(crate) thunk: Option<Gc<'gc, Thunk<'gc>>>,
pub(crate) env: Gc<'gc, RefLock<Env<'gc>>>,
pub(crate) with_env: Option<Gc<'gc, WithEnv<'gc>>>,
struct CallFrame<'gc> {
pc: usize,
thunk: Option<Gc<'gc, Thunk<'gc>>>,
env: Gc<'gc, RefLock<Env<'gc>>>,
}
pub(crate) enum Action {
enum Action {
Continue { pc: usize },
Done(Result<fix_common::Value>),
}
pub(crate) enum NixNum {
enum NixNum {
Int(i64),
Float(f64),
}
@@ -699,10 +688,7 @@ impl<'gc> Vm<'gc> {
Assert => self.op_assert(ctx, &mut reader, mc),
PushWith => self.op_push_with(ctx, &mut reader, mc),
PopWith => self.op_pop_with(),
LookupWith => self.op_lookup_with(ctx, &mut reader, mc),
PrepareWith => self.op_prepare_with(),
LoadBuiltins => self.op_load_builtins(),
LoadBuiltin => self.op_load_builtin(&mut reader),