Step -> ControlFlow (use ?)
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use gc_arena::Mutation;
|
use gc_arena::Mutation;
|
||||||
|
|
||||||
use crate::{BytecodeReader, Step, Vm, VmContext};
|
use crate::{Break, BytecodeReader, Step, Vm, VmContext};
|
||||||
|
|
||||||
pub(crate) enum TailResult {
|
pub(crate) enum TailResult {
|
||||||
YieldFuel(u32),
|
YieldFuel(u32),
|
||||||
@@ -36,8 +36,8 @@ extern "rust-preserve-none" fn op_illegal<'gc, C: VmContext>(
|
|||||||
macro_rules! tail_dispatch_after {
|
macro_rules! tail_dispatch_after {
|
||||||
($result:expr, $new_pc:expr, $vm:ident, $mc:ident, $ctx:ident, $bc:ident, $table:ident, $fuel:ident) => {{
|
($result:expr, $new_pc:expr, $vm:ident, $mc:ident, $ctx:ident, $bc:ident, $table:ident, $fuel:ident) => {{
|
||||||
match $result {
|
match $result {
|
||||||
Step::Continue => {}
|
Step::Continue(()) | Step::Break(Break::Force) => {}
|
||||||
Step::Done => return TailResult::Done,
|
Step::Break(Break::Done) => return TailResult::Done,
|
||||||
}
|
}
|
||||||
let new_pc: u32 = $new_pc;
|
let new_pc: u32 = $new_pc;
|
||||||
if $fuel == 0 {
|
if $fuel == 0 {
|
||||||
|
|||||||
@@ -13,12 +13,8 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
reader: &mut BytecodeReader<'_>,
|
reader: &mut BytecodeReader<'_>,
|
||||||
mc: &Mutation<'gc>,
|
mc: &Mutation<'gc>,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
if let Some(step) = self.try_force(1, reader, mc) {
|
self.try_force(1, reader, mc)?;
|
||||||
return step;
|
self.try_force(0, reader, mc)?;
|
||||||
}
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
let rhs = self.pop_forced();
|
let rhs = self.pop_forced();
|
||||||
let lhs = self.pop_forced();
|
let lhs = self.pop_forced();
|
||||||
if let (Some(ls), Some(rs)) = (
|
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}")));
|
let ns = Gc::new(mc, crate::NixString::new(format!("{ls}{rs}")));
|
||||||
self.push(Value::new_gc(ns));
|
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);
|
let res = numeric_binop(lhs, rhs, mc, i64::wrapping_add, |a, b| a + b);
|
||||||
match res {
|
match res {
|
||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
self.push(val);
|
self.push(val);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
Err(e) => self.finish_vm_err(e),
|
Err(e) => self.finish_vm_err(e),
|
||||||
}
|
}
|
||||||
@@ -65,19 +61,15 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
int_op: fn(i64, i64) -> i64,
|
int_op: fn(i64, i64) -> i64,
|
||||||
float_op: fn(f64, f64) -> f64,
|
float_op: fn(f64, f64) -> f64,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
if let Some(step) = self.try_force(1, reader, mc) {
|
self.try_force(1, reader, mc)?;
|
||||||
return step;
|
self.try_force(0, reader, mc)?;
|
||||||
}
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
let rhs = self.pop_forced();
|
let rhs = self.pop_forced();
|
||||||
let lhs = self.pop_forced();
|
let lhs = self.pop_forced();
|
||||||
let res = numeric_binop(lhs, rhs, mc, int_op, float_op);
|
let res = numeric_binop(lhs, rhs, mc, int_op, float_op);
|
||||||
match res {
|
match res {
|
||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
self.push(val);
|
self.push(val);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
Err(e) => self.finish_vm_err(e),
|
Err(e) => self.finish_vm_err(e),
|
||||||
}
|
}
|
||||||
@@ -89,12 +81,8 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
reader: &mut BytecodeReader<'_>,
|
reader: &mut BytecodeReader<'_>,
|
||||||
mc: &Mutation<'gc>,
|
mc: &Mutation<'gc>,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
if let Some(step) = self.try_force(1, reader, mc) {
|
self.try_force(1, reader, mc)?;
|
||||||
return step;
|
self.try_force(0, reader, mc)?;
|
||||||
}
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
let rhs = self.pop_forced();
|
let rhs = self.pop_forced();
|
||||||
let lhs = self.pop_forced();
|
let lhs = self.pop_forced();
|
||||||
match (get_num(rhs), get_num(lhs)) {
|
match (get_num(rhs), get_num(lhs)) {
|
||||||
@@ -109,7 +97,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
match res {
|
match res {
|
||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
self.push(val);
|
self.push(val);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
Err(e) => self.finish_vm_err(e),
|
Err(e) => self.finish_vm_err(e),
|
||||||
}
|
}
|
||||||
@@ -122,18 +110,14 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
reader: &mut BytecodeReader<'_>,
|
reader: &mut BytecodeReader<'_>,
|
||||||
mc: &Mutation<'gc>,
|
mc: &Mutation<'gc>,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
if let Some(step) = self.try_force(1, reader, mc) {
|
self.try_force(1, reader, mc)?;
|
||||||
return step;
|
self.try_force(0, reader, mc)?;
|
||||||
}
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
let eq = match self.values_equal(ctx) {
|
let eq = match self.values_equal(ctx) {
|
||||||
Ok(eq) => eq,
|
Ok(eq) => eq,
|
||||||
Err(e) => return self.finish_vm_err(e),
|
Err(e) => return self.finish_vm_err(e),
|
||||||
};
|
};
|
||||||
self.push(Value::new_inline(eq));
|
self.push(Value::new_inline(eq));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -143,18 +127,14 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
reader: &mut BytecodeReader<'_>,
|
reader: &mut BytecodeReader<'_>,
|
||||||
mc: &Mutation<'gc>,
|
mc: &Mutation<'gc>,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
if let Some(step) = self.try_force(1, reader, mc) {
|
self.try_force(1, reader, mc)?;
|
||||||
return step;
|
self.try_force(0, reader, mc)?;
|
||||||
}
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
let eq = match self.values_equal(ctx) {
|
let eq = match self.values_equal(ctx) {
|
||||||
Ok(eq) => eq,
|
Ok(eq) => eq,
|
||||||
Err(e) => return self.finish_vm_err(e),
|
Err(e) => return self.finish_vm_err(e),
|
||||||
};
|
};
|
||||||
self.push(Value::new_inline(!eq));
|
self.push(Value::new_inline(!eq));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -204,14 +184,10 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
mc: &Mutation<'gc>,
|
mc: &Mutation<'gc>,
|
||||||
pred: fn(Ordering) -> bool,
|
pred: fn(Ordering) -> bool,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
if let Some(step) = self.try_force(1, reader, mc) {
|
self.try_force(1, reader, mc)?;
|
||||||
return step;
|
self.try_force(0, reader, mc)?;
|
||||||
}
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
match self.compare_values_inner(ctx, pred) {
|
match self.compare_values_inner(ctx, pred) {
|
||||||
Ok(()) => Step::Continue,
|
Ok(()) => Step::Continue(()),
|
||||||
Err(e) => self.finish_vm_err(e),
|
Err(e) => self.finish_vm_err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,12 +198,8 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
reader: &mut BytecodeReader<'_>,
|
reader: &mut BytecodeReader<'_>,
|
||||||
mc: &Mutation<'gc>,
|
mc: &Mutation<'gc>,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
if let Some(step) = self.try_force(1, reader, mc) {
|
self.try_force(1, reader, mc)?;
|
||||||
return step;
|
self.try_force(0, reader, mc)?;
|
||||||
}
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
let r = match self.pop_forced_expect_gc::<List>() {
|
let r = match self.pop_forced_expect_gc::<List>() {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(got) => return self.finish_type_err(NixType::List, got)
|
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(&l);
|
||||||
items.extend_from_slice(&r);
|
items.extend_from_slice(&r);
|
||||||
self.push(Value::new_gc(Gc::new(mc, crate::List { inner: items })));
|
self.push(Value::new_gc(Gc::new(mc, crate::List { inner: items })));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -249,12 +221,8 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
reader: &mut BytecodeReader<'_>,
|
reader: &mut BytecodeReader<'_>,
|
||||||
mc: &Mutation<'gc>,
|
mc: &Mutation<'gc>,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
if let Some(step) = self.try_force(1, reader, mc) {
|
self.try_force(1, reader, mc)?;
|
||||||
return step;
|
self.try_force(0, reader, mc)?;
|
||||||
}
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
let r = match self.pop_forced_expect_gc::<AttrSet>() {
|
let r = match self.pop_forced_expect_gc::<AttrSet>() {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(got) => return self.finish_type_err(NixType::AttrSet, got)
|
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)
|
Err(got) => return self.finish_type_err(NixType::AttrSet, got)
|
||||||
};
|
};
|
||||||
self.push(Value::new_gc(l.merge(&r, mc)));
|
self.push(Value::new_gc(l.merge(&r, mc)));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn op_load_builtins(&mut self) -> Step {
|
pub(crate) fn op_load_builtins(&mut self) -> Step {
|
||||||
self.push(self.builtins);
|
self.push(self.builtins);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -18,7 +18,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
id,
|
id,
|
||||||
arity: fix_builtins::BUILTINS[id as usize].1,
|
arity: fix_builtins::BUILTINS[id as usize].1,
|
||||||
}));
|
}));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
reader: &mut BytecodeReader<'_>,
|
reader: &mut BytecodeReader<'_>,
|
||||||
mc: &Mutation<'gc>,
|
mc: &Mutation<'gc>,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
self.try_force(0, reader, mc)?;
|
||||||
return step;
|
|
||||||
}
|
|
||||||
if self.call_depth > 10000 {
|
if self.call_depth > 10000 {
|
||||||
return self.finish_err(Error::eval_error("stack overflow; max-call-depth exceeded"));
|
return self.finish_err(Error::eval_error("stack overflow; max-call-depth exceeded"));
|
||||||
}
|
}
|
||||||
@@ -41,7 +39,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
} else {
|
} else {
|
||||||
todo!("call other types: {func:?}")
|
todo!("call other types: {func:?}")
|
||||||
}
|
}
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -109,7 +107,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
reader.set_pc(inner_ip);
|
reader.set_pc(inner_ip);
|
||||||
self.env = inner_env;
|
self.env = inner_env;
|
||||||
self.with_env = inner_with_env;
|
self.with_env = inner_with_env;
|
||||||
return Step::Continue;
|
return Step::Continue(());
|
||||||
}
|
}
|
||||||
ThunkState::Evaluated(val) => {
|
ThunkState::Evaluated(val) => {
|
||||||
*outer_thunk.borrow_mut(mc) = ThunkState::Evaluated(val);
|
*outer_thunk.borrow_mut(mc) = ThunkState::Evaluated(val);
|
||||||
@@ -132,6 +130,6 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
}
|
}
|
||||||
self.env = env;
|
self.env = env;
|
||||||
self.with_env = with_env;
|
self.with_env = with_env;
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
self.push(Value::new_gc(thunk));
|
self.push(Value::new_gc(thunk));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -40,7 +40,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.push(Value::new_gc(closure));
|
self.push(Value::new_gc(closure));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -90,6 +90,6 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.push(Value::new_gc(closure));
|
self.push(Value::new_gc(closure));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
kv.sort_by_key(|(k, _)| *k);
|
kv.sort_by_key(|(k, _)| *k);
|
||||||
let attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(kv));
|
let attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(kv));
|
||||||
self.push(Value::new_gc(attrs));
|
self.push(Value::new_gc(attrs));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn op_make_empty_attrs(&mut self) -> Step {
|
pub(crate) fn op_make_empty_attrs(&mut self) -> Step {
|
||||||
self.push(self.empty_attrs);
|
self.push(self.empty_attrs);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -57,9 +57,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
let _span_id = reader.read_u32();
|
let _span_id = reader.read_u32();
|
||||||
let key = reader.read_string_id();
|
let key = reader.read_string_id();
|
||||||
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
self.try_force(0, reader, mc)?;
|
||||||
return step;
|
|
||||||
}
|
|
||||||
|
|
||||||
let attrs = self.peek(0).restrict().expect("forced");
|
let attrs = self.peek(0).restrict().expect("forced");
|
||||||
let Some(attrset) = attrs.as_gc::<AttrSet>() else {
|
let Some(attrset) = attrs.as_gc::<AttrSet>() else {
|
||||||
@@ -89,7 +87,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -101,12 +99,8 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
) -> Step {
|
) -> Step {
|
||||||
let _span_id = reader.read_u32();
|
let _span_id = reader.read_u32();
|
||||||
|
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
self.try_force(0, reader, mc)?;
|
||||||
return step;
|
self.try_force(1, reader, mc)?;
|
||||||
}
|
|
||||||
if let Some(step) = self.try_force(1, reader, mc) {
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
|
|
||||||
let key_val = self.stack[self.stack.len() - 1]
|
let key_val = self.stack[self.stack.len() - 1]
|
||||||
.restrict()
|
.restrict()
|
||||||
@@ -136,7 +130,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
return self.finish_err(Error::eval_error(format!("attribute '{name}' missing")));
|
return self.finish_err(Error::eval_error(format!("attribute '{name}' missing")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -146,7 +140,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
) -> Step {
|
) -> Step {
|
||||||
let offset = reader.read_i32();
|
let offset = reader.read_i32();
|
||||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -169,13 +163,13 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
}
|
}
|
||||||
let list = Gc::new(mc, List { inner: items });
|
let list = Gc::new(mc, List { inner: items });
|
||||||
self.push(Value::new_gc(list));
|
self.push(Value::new_gc(list));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn op_make_empty_list(&mut self) -> Step {
|
pub(crate) fn op_make_empty_list(&mut self) -> Step {
|
||||||
self.push(self.empty_list);
|
self.push(self.empty_list);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
mc: &gc_arena::Mutation<'gc>,
|
mc: &gc_arena::Mutation<'gc>,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
let offset = reader.read_i32();
|
let offset = reader.read_i32();
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
self.try_force(0, reader, mc)?;
|
||||||
return step;
|
|
||||||
}
|
|
||||||
let cond = self.pop();
|
let cond = self.pop();
|
||||||
if cond.as_inline::<bool>() == Some(false) {
|
if cond.as_inline::<bool>() == Some(false) {
|
||||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||||
}
|
}
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -25,21 +23,19 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
mc: &gc_arena::Mutation<'gc>,
|
mc: &gc_arena::Mutation<'gc>,
|
||||||
) -> Step {
|
) -> Step {
|
||||||
let offset = reader.read_i32();
|
let offset = reader.read_i32();
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
self.try_force(0, reader, mc)?;
|
||||||
return step;
|
|
||||||
}
|
|
||||||
let cond = self.pop();
|
let cond = self.pop();
|
||||||
if cond.as_inline::<bool>() == Some(true) {
|
if cond.as_inline::<bool>() == Some(true) {
|
||||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||||
}
|
}
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn op_jump(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
pub(crate) fn op_jump(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||||
let offset = reader.read_i32();
|
let offset = reader.read_i32();
|
||||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
pub(crate) fn op_push_smi(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
pub(crate) fn op_push_smi(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||||
let val = reader.read_i32();
|
let val = reader.read_i32();
|
||||||
self.push(Value::new_inline(val));
|
self.push(Value::new_inline(val));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -18,38 +18,38 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
) -> Step {
|
) -> Step {
|
||||||
let val = reader.read_i64();
|
let val = reader.read_i64();
|
||||||
self.push(Value::new_gc(Gc::new(mc, val)));
|
self.push(Value::new_gc(Gc::new(mc, val)));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn op_push_float(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
pub(crate) fn op_push_float(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||||
let val = reader.read_f64();
|
let val = reader.read_f64();
|
||||||
self.push(Value::new_float(val));
|
self.push(Value::new_float(val));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn op_push_string(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
pub(crate) fn op_push_string(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||||
let sid = reader.read_string_id();
|
let sid = reader.read_string_id();
|
||||||
self.push(Value::new_inline(sid));
|
self.push(Value::new_inline(sid));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn op_push_null(&mut self) -> Step {
|
pub(crate) fn op_push_null(&mut self) -> Step {
|
||||||
self.push(Value::new_inline(crate::Null));
|
self.push(Value::new_inline(crate::Null));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn op_push_true(&mut self) -> Step {
|
pub(crate) fn op_push_true(&mut self) -> Step {
|
||||||
self.push(Value::new_inline(true));
|
self.push(Value::new_inline(true));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn op_push_false(&mut self) -> Step {
|
pub(crate) fn op_push_false(&mut self) -> Step {
|
||||||
self.push(Value::new_inline(false));
|
self.push(Value::new_inline(false));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
pub(crate) fn op_load_local(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
pub(crate) fn op_load_local(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||||
let idx = reader.read_u32() as usize;
|
let idx = reader.read_u32() as usize;
|
||||||
self.push(self.env.borrow().locals[idx]);
|
self.push(self.env.borrow().locals[idx]);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -19,7 +19,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
}
|
}
|
||||||
let val = cur.borrow().locals[idx];
|
let val = cur.borrow().locals[idx];
|
||||||
self.push(val);
|
self.push(val);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -31,7 +31,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
let idx = reader.read_u32() as usize;
|
let idx = reader.read_u32() as usize;
|
||||||
let val = self.pop();
|
let val = self.pop();
|
||||||
self.env.borrow_mut(mc).locals[idx] = val;
|
self.env.borrow_mut(mc).locals[idx] = val;
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -45,6 +45,6 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
.borrow_mut(mc)
|
.borrow_mut(mc)
|
||||||
.locals
|
.locals
|
||||||
.extend(std::iter::repeat_n(Value::default(), count));
|
.extend(std::iter::repeat_n(Value::default(), count));
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.with_env = Some(scope);
|
self.with_env = Some(scope);
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -31,7 +31,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
unreachable!("no with_scope to pop");
|
unreachable!("no with_scope to pop");
|
||||||
};
|
};
|
||||||
self.with_env = scope.prev;
|
self.with_env = scope.prev;
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -43,7 +43,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
env: self.env,
|
env: self.env,
|
||||||
with_env: self.with_env,
|
with_env: self.with_env,
|
||||||
});
|
});
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -66,9 +66,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
self.push(env);
|
self.push(env);
|
||||||
if let Some(step) = self.try_force(0, reader, mc) {
|
self.try_force(0, reader, mc)?;
|
||||||
return step;
|
|
||||||
}
|
|
||||||
|
|
||||||
let env = match self.pop_forced_expect_gc::<AttrSet>() {
|
let env = match self.pop_forced_expect_gc::<AttrSet>() {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
@@ -77,7 +75,7 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
let Some(val) = env.lookup(name) else {
|
let Some(val) = env.lookup(name) else {
|
||||||
reader.set_pc(reader.inst_start_pc());
|
reader.set_pc(reader.inst_start_pc());
|
||||||
self.with_env = prev;
|
self.with_env = prev;
|
||||||
return Step::Continue;
|
return Step::Continue(());
|
||||||
};
|
};
|
||||||
|
|
||||||
self.push(val);
|
self.push(val);
|
||||||
@@ -85,6 +83,6 @@ impl<'gc> crate::Vm<'gc> {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
self.with_env = with_env;
|
self.with_env = with_env;
|
||||||
Step::Continue
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-13
@@ -132,11 +132,13 @@ impl<T: VmContext> VmContextExt for T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub(crate) enum Step {
|
pub(crate) enum Break {
|
||||||
Continue,
|
Force,
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) type Step = std::ops::ControlFlow<Break>;
|
||||||
|
|
||||||
#[derive(Collect)]
|
#[derive(Collect)]
|
||||||
#[collect(no_drop)]
|
#[collect(no_drop)]
|
||||||
pub struct Vm<'gc> {
|
pub struct Vm<'gc> {
|
||||||
@@ -273,19 +275,19 @@ impl<'gc> Vm<'gc> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn finish_ok(&mut self, val: fix_common::Value) -> Step {
|
pub(crate) fn finish_ok(&mut self, val: fix_common::Value) -> Step {
|
||||||
self.result = Some(Ok(val));
|
self.result = Some(Ok(val));
|
||||||
Step::Done
|
Step::Break(Break::Done)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn finish_err(&mut self, err: Box<Error>) -> Step {
|
pub(crate) fn finish_err(&mut self, err: Box<Error>) -> Step {
|
||||||
self.result = Some(Err(err));
|
self.result = Some(Err(err));
|
||||||
Step::Done
|
Step::Break(Break::Done)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn finish_type_err(&mut self, expected: NixType, got: NixType) -> Step {
|
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}"))));
|
self.result = Some(Err(Error::eval_error(format!("expected {expected}, got {got}"))));
|
||||||
Step::Done
|
Step::Break(Break::Done)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -369,8 +371,10 @@ impl<'gc> Vm<'gc> {
|
|||||||
depth: usize,
|
depth: usize,
|
||||||
reader: &mut BytecodeReader<'_>,
|
reader: &mut BytecodeReader<'_>,
|
||||||
mc: &Mutation<'gc>,
|
mc: &Mutation<'gc>,
|
||||||
) -> Option<Step> {
|
) -> Step {
|
||||||
let thunk = self.peek(depth).as_gc::<Thunk>()?;
|
let Some(thunk) = self.peek(depth).as_gc::<Thunk>() else {
|
||||||
|
return Step::Continue(());
|
||||||
|
};
|
||||||
let mut state = thunk.borrow_mut(mc);
|
let mut state = thunk.borrow_mut(mc);
|
||||||
match *state {
|
match *state {
|
||||||
ThunkState::Pending { ip, env, with_env } => {
|
ThunkState::Pending { ip, env, with_env } => {
|
||||||
@@ -386,17 +390,17 @@ impl<'gc> Vm<'gc> {
|
|||||||
self.env = env;
|
self.env = env;
|
||||||
self.with_env = with_env;
|
self.with_env = with_env;
|
||||||
reader.set_pc(ip);
|
reader.set_pc(ip);
|
||||||
Some(Step::Continue)
|
Step::Break(Break::Force)
|
||||||
}
|
}
|
||||||
ThunkState::Evaluated(v) => {
|
ThunkState::Evaluated(v) => {
|
||||||
drop(state);
|
drop(state);
|
||||||
self.replace(depth, v.relax());
|
self.replace(depth, v.relax());
|
||||||
None
|
Step::Continue(())
|
||||||
}
|
}
|
||||||
ThunkState::Apply { .. } => todo!("force apply"),
|
ThunkState::Apply { .. } => todo!("force apply"),
|
||||||
ThunkState::Blackhole => {
|
ThunkState::Blackhole => {
|
||||||
drop(state);
|
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 {
|
match result {
|
||||||
Step::Continue => {}
|
Step::Continue(()) | Step::Break(Break::Force) => {}
|
||||||
Step::Done => {
|
Step::Break(Break::Done) => {
|
||||||
return Action::Done(
|
return Action::Done(
|
||||||
self.result.take().expect("StepResult::Done without result"),
|
self.result.take().expect("Break::Done without result"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user