refactor with
This commit is contained in:
@@ -125,10 +125,6 @@ impl<'a> BytecodeReader<'a> {
|
||||
let id = self.read_string_id();
|
||||
OperandData::ScopedImportBinding(id)
|
||||
}
|
||||
OperandType::WithLookup => {
|
||||
let id = self.read_string_id();
|
||||
OperandData::WithLookup(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -187,10 +187,7 @@ tail_fn!(op_resolve_path, (ctx));
|
||||
|
||||
tail_fn!(op_assert, (ctx, reader, mc));
|
||||
|
||||
tail_fn!(op_push_with, (ctx, reader, mc));
|
||||
tail_fn!(op_pop_with, ());
|
||||
tail_fn!(op_lookup_with, (ctx, reader, mc));
|
||||
tail_fn!(op_prepare_with, ());
|
||||
|
||||
tail_fn!(op_load_builtins, ());
|
||||
tail_fn!(op_load_builtin, (reader));
|
||||
@@ -281,10 +278,7 @@ table! {
|
||||
|
||||
Assert => op_assert,
|
||||
|
||||
PushWith => op_push_with,
|
||||
PopWith => op_pop_with,
|
||||
LookupWith => op_lookup_with,
|
||||
PrepareWith => op_prepare_with,
|
||||
|
||||
LoadBuiltins => op_load_builtins,
|
||||
LoadBuiltin => op_load_builtin,
|
||||
|
||||
@@ -46,10 +46,8 @@ impl<'gc> Vm<'gc> {
|
||||
fn return_from_primop(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let Some(CallFrame {
|
||||
pc: ret_pc,
|
||||
stack_depth: _,
|
||||
thunk: _,
|
||||
env,
|
||||
with_env,
|
||||
}) = self.call_stack.pop()
|
||||
else {
|
||||
unreachable!()
|
||||
@@ -57,7 +55,6 @@ impl<'gc> Vm<'gc> {
|
||||
reader.set_pc(ret_pc);
|
||||
self.call_depth -= 1;
|
||||
self.env = env;
|
||||
self.with_env = with_env;
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
@@ -372,6 +369,25 @@ impl<'gc> Vm<'gc> {
|
||||
self.finish_ok(ctx.convert_value(val.relax()))
|
||||
}
|
||||
|
||||
fn is_value_in_seen(&self, seen: Gc<'gc, List<'gc>>, val: Value<'gc>) -> bool {
|
||||
if !is_container(val) {
|
||||
return false;
|
||||
}
|
||||
let target = val.to_bits();
|
||||
for &v in seen.inner.borrow().iter() {
|
||||
if v.to_bits() == target {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn add_value_to_seen(&self, seen: Gc<'gc, List<'gc>>, mc: &Mutation<'gc>, val: Value<'gc>) {
|
||||
if is_container(val) {
|
||||
seen.unlock(mc).borrow_mut().push(val);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn primop_call_pattern(
|
||||
&mut self,
|
||||
ctx: &mut impl VmRuntimeCtx,
|
||||
@@ -421,25 +437,6 @@ impl<'gc> Vm<'gc> {
|
||||
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
fn is_value_in_seen(&self, seen: Gc<'gc, List<'gc>>, val: Value<'gc>) -> bool {
|
||||
if !is_container(val) {
|
||||
return false;
|
||||
}
|
||||
let target = val.to_bits();
|
||||
for &v in seen.inner.borrow().iter() {
|
||||
if v.to_bits() == target {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn add_value_to_seen(&self, seen: Gc<'gc, List<'gc>>, mc: &Mutation<'gc>, val: Value<'gc>) {
|
||||
if is_container(val) {
|
||||
seen.unlock(mc).borrow_mut().push(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_container(val: Value<'_>) -> bool {
|
||||
|
||||
@@ -29,10 +29,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
self.push(arg);
|
||||
self.call_stack.push(CallFrame {
|
||||
pc: resume_pc,
|
||||
stack_depth: 0,
|
||||
thunk: None,
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
});
|
||||
reader.set_pc(PrimOpPhase::CallPattern.ip() as usize);
|
||||
return Step::Continue(());
|
||||
@@ -44,10 +42,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
let new_env = Gc::new(mc, RefLock::new(Env::with_arg(arg, n_locals, env)));
|
||||
self.call_stack.push(CallFrame {
|
||||
pc: resume_pc,
|
||||
stack_depth: 0,
|
||||
thunk: None,
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
});
|
||||
reader.set_pc(ip as usize);
|
||||
self.env = new_env;
|
||||
@@ -56,10 +52,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
self.push(arg);
|
||||
self.call_stack.push(CallFrame {
|
||||
pc: resume_pc,
|
||||
stack_depth: 0,
|
||||
thunk: None,
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
});
|
||||
reader.set_pc(primop.dispatch_ip as usize)
|
||||
} else {
|
||||
@@ -78,10 +72,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
self.push(arg);
|
||||
self.call_stack.push(CallFrame {
|
||||
pc: resume_pc,
|
||||
stack_depth: 0,
|
||||
thunk: None,
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
});
|
||||
reader.set_pc(app.primop.dispatch_ip as usize)
|
||||
} else {
|
||||
@@ -121,10 +113,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
let val = self.force_and_retry::<StrictValue>(reader, mc)?;
|
||||
let Some(CallFrame {
|
||||
pc: ret_pc,
|
||||
stack_depth,
|
||||
thunk,
|
||||
env,
|
||||
with_env,
|
||||
}) = self.call_stack.pop()
|
||||
else {
|
||||
match self.force_mode {
|
||||
@@ -139,10 +129,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
self.push(val.relax());
|
||||
self.call_stack.push(CallFrame {
|
||||
pc: PrimOpPhase::ForceResultDeepFinish.ip() as usize,
|
||||
stack_depth: 0,
|
||||
thunk: None,
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
});
|
||||
self.call_depth += 1;
|
||||
reader.set_pc(PrimOpPhase::DeepSeq.ip() as usize);
|
||||
@@ -153,13 +141,11 @@ impl<'gc> crate::Vm<'gc> {
|
||||
reader.set_pc(ret_pc);
|
||||
if let Some(outer_thunk) = thunk {
|
||||
*outer_thunk.borrow_mut(mc) = ThunkState::Evaluated(val);
|
||||
self.replace(stack_depth, val.relax());
|
||||
} else {
|
||||
self.call_depth -= 1;
|
||||
self.push(val.relax())
|
||||
}
|
||||
self.env = env;
|
||||
self.with_env = with_env;
|
||||
Step::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ impl<'gc> crate::Vm<'gc> {
|
||||
RefLock::new(ThunkState::Pending {
|
||||
ip: entry_point as usize,
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
}),
|
||||
);
|
||||
self.push(Value::new_gc(thunk));
|
||||
|
||||
@@ -1,51 +1,11 @@
|
||||
use fix_common::Symbol;
|
||||
use fix_error::Error;
|
||||
use gc_arena::Gc;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::value::*;
|
||||
use crate::{BytecodeReader, CallFrame, Step, VmRuntimeCtx, WithEnv};
|
||||
use crate::{Break, BytecodeReader, CallFrame, Step, VmRuntimeCtx};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_with(
|
||||
&mut self,
|
||||
ctx: &mut impl VmRuntimeCtx,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> Step {
|
||||
let env = reader.read_operand_data(ctx).resolve(mc, self);
|
||||
let scope = Gc::new(
|
||||
mc,
|
||||
WithEnv {
|
||||
env,
|
||||
prev: self.with_env,
|
||||
},
|
||||
);
|
||||
self.with_env = Some(scope);
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
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;
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_prepare_with(&mut self) -> Step {
|
||||
self.call_stack.push(CallFrame {
|
||||
pc: usize::MAX,
|
||||
stack_depth: 0,
|
||||
thunk: None,
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
});
|
||||
Step::Continue(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_lookup_with(
|
||||
&mut self,
|
||||
@@ -53,31 +13,62 @@ impl<'gc> crate::Vm<'gc> {
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> Step {
|
||||
let name = reader.read_string_id();
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let counter = self.peek_forced(0).as_inline::<i32>().unwrap();
|
||||
|
||||
let Some(&WithEnv { env, prev }) = self.with_env.as_deref() else {
|
||||
let Some(CallFrame { with_env, .. }) = self.call_stack.pop() else {
|
||||
unreachable!()
|
||||
};
|
||||
self.with_env = with_env;
|
||||
let name = reader.read_string_id();
|
||||
let n = reader.read_u8();
|
||||
let mut namespaces = SmallVec::<[_; 2]>::new();
|
||||
for _ in 0..n {
|
||||
namespaces.push(reader.read_operand_data(ctx).resolve(mc, self));
|
||||
}
|
||||
|
||||
let resume_pc = reader.inst_start_pc();
|
||||
let namespace = match namespaces[counter as usize].restrict() {
|
||||
Ok(val) => val,
|
||||
Err(thunk) => {
|
||||
let mut state = thunk.borrow_mut(mc);
|
||||
match *state {
|
||||
ThunkState::Pending { ip, env } => {
|
||||
*state = ThunkState::Blackhole;
|
||||
self.call_stack.push(CallFrame {
|
||||
thunk: Some(thunk),
|
||||
pc: resume_pc,
|
||||
env: self.env,
|
||||
});
|
||||
self.env = env;
|
||||
reader.set_pc(ip);
|
||||
return Step::Break(Break::Force);
|
||||
}
|
||||
ThunkState::Evaluated(v) => v,
|
||||
ThunkState::Apply { func, arg } => {
|
||||
self.call_stack.push(CallFrame {
|
||||
thunk: Some(thunk),
|
||||
pc: resume_pc,
|
||||
env: self.env,
|
||||
});
|
||||
self.push(func);
|
||||
return self.call(reader, mc, arg, resume_pc);
|
||||
}
|
||||
ThunkState::Blackhole => {
|
||||
return self.finish_err(Error::eval_error("infinite recursion encountered"));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(val) = namespace.as_gc::<AttrSet>().and_then(|attrs| attrs.lookup(name)) {
|
||||
self.replace(0, val);
|
||||
} else if counter + 1 == n as i32 {
|
||||
return self.finish_err(Error::eval_error(format!(
|
||||
"undefined variable '{}'",
|
||||
Symbol::from(ctx.resolve_string(name))
|
||||
)));
|
||||
};
|
||||
self.push(env);
|
||||
let env = self.force_and_retry::<Gc<AttrSet>>(reader, mc)?;
|
||||
let Some(val) = env.lookup(name) else {
|
||||
reader.set_pc(reader.inst_start_pc());
|
||||
self.with_env = prev;
|
||||
return Step::Continue(());
|
||||
};
|
||||
} else {
|
||||
self.replace(0, Value::new_inline(counter + 1));
|
||||
reader.set_pc(resume_pc);
|
||||
}
|
||||
|
||||
self.push(val);
|
||||
let Some(CallFrame { with_env, .. }) = self.call_stack.pop() else {
|
||||
unreachable!()
|
||||
};
|
||||
self.with_env = with_env;
|
||||
Step::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
+40
-54
@@ -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),
|
||||
|
||||
@@ -527,7 +527,6 @@ pub(crate) enum ThunkState<'gc> {
|
||||
Pending {
|
||||
ip: usize,
|
||||
env: GcEnv<'gc>,
|
||||
with_env: Option<GcWithEnv<'gc>>,
|
||||
},
|
||||
Apply {
|
||||
func: Value<'gc>,
|
||||
|
||||
Reference in New Issue
Block a user