better type assertion ergonomic
This commit is contained in:
@@ -2,7 +2,8 @@ use std::cmp::Ordering;
|
||||
|
||||
use gc_arena::{Gc, Mutation};
|
||||
|
||||
use crate::{BytecodeReader, NixNum, StepResult, StrictValue, Value, VmContextExt, VmError};
|
||||
use crate::{BytecodeReader, NixNum, Step, VmContextExt, VmError};
|
||||
use crate::value::*;
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
@@ -11,28 +12,28 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> 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;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
let lhs = self.pop_stack_forced();
|
||||
let rhs = self.pop_forced();
|
||||
let lhs = self.pop_forced();
|
||||
if let (Some(ls), Some(rs)) = (
|
||||
VmContextExt::get_string(ctx, lhs),
|
||||
VmContextExt::get_string(ctx, rhs),
|
||||
) {
|
||||
let ns = Gc::new(mc, crate::NixString::new(format!("{ls}{rs}")));
|
||||
self.push_stack(Value::new_gc(ns));
|
||||
return StepResult::Continue;
|
||||
self.push(Value::new_gc(ns));
|
||||
return Step::Continue;
|
||||
}
|
||||
let res = numeric_binop(lhs, rhs, mc, i64::wrapping_add, |a, b| a + b);
|
||||
match res {
|
||||
Ok(val) => {
|
||||
self.push_stack(val);
|
||||
StepResult::Continue
|
||||
self.push(val);
|
||||
Step::Continue
|
||||
}
|
||||
Err(e) => self.finish_vm_err(e),
|
||||
}
|
||||
@@ -43,7 +44,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
self.op_arith(reader, mc, i64::wrapping_sub, |a, b| a - b)
|
||||
}
|
||||
|
||||
@@ -52,7 +53,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
self.op_arith(reader, mc, i64::wrapping_mul, |a, b| a * b)
|
||||
}
|
||||
|
||||
@@ -63,20 +64,20 @@ impl<'gc> crate::Vm<'gc> {
|
||||
mc: &Mutation<'gc>,
|
||||
int_op: fn(i64, i64) -> i64,
|
||||
float_op: fn(f64, f64) -> f64,
|
||||
) -> StepResult {
|
||||
) -> 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;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
let lhs = self.pop_stack_forced();
|
||||
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_stack(val);
|
||||
StepResult::Continue
|
||||
self.push(val);
|
||||
Step::Continue
|
||||
}
|
||||
Err(e) => self.finish_vm_err(e),
|
||||
}
|
||||
@@ -87,15 +88,15 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> 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;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
let lhs = self.pop_stack_forced();
|
||||
let rhs = self.pop_forced();
|
||||
let lhs = self.pop_forced();
|
||||
match (get_num(rhs), get_num(lhs)) {
|
||||
(_, Some(NixNum::Int(0))) | (_, Some(NixNum::Float(0.))) => {
|
||||
return self.finish_vm_err(VmError::Uncatchable(fix_error::Error::eval_error(
|
||||
@@ -107,8 +108,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
let res = numeric_binop(lhs, rhs, mc, |a, b| a / b, |a, b| a / b);
|
||||
match res {
|
||||
Ok(val) => {
|
||||
self.push_stack(val);
|
||||
StepResult::Continue
|
||||
self.push(val);
|
||||
Step::Continue
|
||||
}
|
||||
Err(e) => self.finish_vm_err(e),
|
||||
}
|
||||
@@ -120,7 +121,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
@@ -131,8 +132,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
Ok(eq) => eq,
|
||||
Err(e) => return self.finish_vm_err(e),
|
||||
};
|
||||
self.push_stack(Value::new_inline(eq));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_inline(eq));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -141,7 +142,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
@@ -152,8 +153,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
Ok(eq) => eq,
|
||||
Err(e) => return self.finish_vm_err(e),
|
||||
};
|
||||
self.push_stack(Value::new_inline(!eq));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_inline(!eq));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -162,7 +163,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
self.compare_values(ctx, reader, mc, Ordering::is_lt)
|
||||
}
|
||||
|
||||
@@ -172,7 +173,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
self.compare_values(ctx, reader, mc, Ordering::is_gt)
|
||||
}
|
||||
|
||||
@@ -182,7 +183,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
self.compare_values(ctx, reader, mc, Ordering::is_le)
|
||||
}
|
||||
|
||||
@@ -192,7 +193,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
self.compare_values(ctx, reader, mc, Ordering::is_ge)
|
||||
}
|
||||
|
||||
@@ -202,7 +203,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
pred: fn(Ordering) -> bool,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
@@ -210,7 +211,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
return step;
|
||||
}
|
||||
match self.compare_values_inner(ctx, pred) {
|
||||
Ok(()) => StepResult::Continue,
|
||||
Ok(()) => Step::Continue,
|
||||
Err(e) => self.finish_vm_err(e),
|
||||
}
|
||||
}
|
||||
@@ -220,30 +221,26 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> 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;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
let lhs = self.pop_stack_forced();
|
||||
let Some(l) = lhs.as_gc::<crate::List>() else {
|
||||
return self.finish_err(fix_error::Error::eval_error(
|
||||
"cannot concatenate: left operand is not a list",
|
||||
));
|
||||
let r = match self.pop_forced_expect_gc::<List>() {
|
||||
Ok(val) => val,
|
||||
Err(got) => return self.finish_type_err(NixType::List, got)
|
||||
};
|
||||
let Some(r) = rhs.as_gc::<crate::List>() else {
|
||||
return self.finish_err(fix_error::Error::eval_error(
|
||||
"cannot concatenate: right operand is not a list",
|
||||
));
|
||||
let l = match self.pop_forced_expect_gc::<List>() {
|
||||
Ok(val) => val,
|
||||
Err(got) => return self.finish_type_err(NixType::List, got)
|
||||
};
|
||||
let mut items = smallvec::SmallVec::new();
|
||||
items.extend_from_slice(&l);
|
||||
items.extend_from_slice(&r);
|
||||
self.push_stack(Value::new_gc(Gc::new(mc, crate::List { inner: items })));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_gc(Gc::new(mc, crate::List { inner: items })));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -251,42 +248,38 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> 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;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
let lhs = self.pop_stack_forced();
|
||||
let Some(l) = lhs.as_gc::<crate::AttrSet>() else {
|
||||
return self.finish_err(fix_error::Error::eval_error(
|
||||
"cannot update: left operand is not a set",
|
||||
));
|
||||
let r = match self.pop_forced_expect_gc::<AttrSet>() {
|
||||
Ok(val) => val,
|
||||
Err(got) => return self.finish_type_err(NixType::AttrSet, got)
|
||||
};
|
||||
let Some(r) = rhs.as_gc::<crate::AttrSet>() else {
|
||||
return self.finish_err(fix_error::Error::eval_error(
|
||||
"cannot update: right operand is not a set",
|
||||
));
|
||||
let l = match self.pop_forced_expect_gc::<AttrSet>() {
|
||||
Ok(val) => val,
|
||||
Err(got) => return self.finish_type_err(NixType::AttrSet, got)
|
||||
};
|
||||
self.push_stack(Value::new_gc(l.merge(&r, mc)));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_gc(l.merge(&r, mc)));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_neg(&mut self) -> StepResult {
|
||||
pub(crate) fn op_neg(&mut self) -> Step {
|
||||
todo!("implement unary operation");
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_not(&mut self) -> StepResult {
|
||||
pub(crate) fn op_not(&mut self) -> Step {
|
||||
todo!("implement unary operation");
|
||||
}
|
||||
|
||||
pub(crate) fn values_equal(&mut self, ctx: &impl crate::VmContext) -> crate::VmResult<bool> {
|
||||
let rhs = self.pop_stack_forced();
|
||||
let lhs = self.pop_stack_forced();
|
||||
let rhs = self.pop_forced();
|
||||
let lhs = self.pop_forced();
|
||||
|
||||
if let (Some(a), Some(b)) = (get_num(lhs), get_num(rhs)) {
|
||||
return Ok(match (a, b) {
|
||||
@@ -314,8 +307,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
let len = a.inner.len();
|
||||
for (x, y) in a.inner.iter().zip(b.inner.iter()).rev() {
|
||||
self.push_stack(*x);
|
||||
self.push_stack(*y);
|
||||
self.push(*x);
|
||||
self.push(*y);
|
||||
}
|
||||
for i in 0..len {
|
||||
let eq = self.values_equal(ctx)?;
|
||||
@@ -336,8 +329,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
if k1 != k2 {
|
||||
return Ok(false);
|
||||
}
|
||||
self.push_stack(*v1);
|
||||
self.push_stack(*v2);
|
||||
self.push(*v1);
|
||||
self.push(*v2);
|
||||
}
|
||||
for i in 0..len {
|
||||
let eq = self.values_equal(ctx)?;
|
||||
@@ -357,8 +350,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &impl crate::VmContext,
|
||||
pred: fn(Ordering) -> bool,
|
||||
) -> crate::VmResult<()> {
|
||||
let rhs = self.pop_stack_forced();
|
||||
let lhs = self.pop_stack_forced();
|
||||
let rhs = self.pop_forced();
|
||||
let lhs = self.pop_forced();
|
||||
|
||||
if let (Some(a), Some(b)) = (get_num(lhs), get_num(rhs)) {
|
||||
let ord = match (a, b) {
|
||||
@@ -371,16 +364,17 @@ impl<'gc> crate::Vm<'gc> {
|
||||
a.partial_cmp(&(b as f64)).unwrap_or(Ordering::Less)
|
||||
}
|
||||
};
|
||||
self.push_stack(Value::new_inline(pred(ord)));
|
||||
self.push(Value::new_inline(pred(ord)));
|
||||
return Ok(());
|
||||
}
|
||||
if let (Some(a), Some(b)) = (
|
||||
VmContextExt::get_string(ctx, lhs),
|
||||
VmContextExt::get_string(ctx, rhs),
|
||||
) {
|
||||
self.push_stack(Value::new_inline(pred(a.cmp(b))));
|
||||
self.push(Value::new_inline(pred(a.cmp(b))));
|
||||
return Ok(());
|
||||
}
|
||||
// TODO: compare other types
|
||||
Err(crate::vm_err("cannot compare these types"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
use fix_builtins::BuiltinId;
|
||||
use num_enum::TryFromPrimitive;
|
||||
|
||||
use crate::{BytecodeReader, PrimOp, StepResult, Value};
|
||||
use crate::{BytecodeReader, PrimOp, Step, Value};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_load_builtins(&mut self) -> StepResult {
|
||||
self.push_stack(self.builtins);
|
||||
StepResult::Continue
|
||||
pub(crate) fn op_load_builtins(&mut self) -> Step {
|
||||
self.push(self.builtins);
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_load_builtin(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
pub(crate) fn op_load_builtin(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let Ok(id) = BuiltinId::try_from_primitive(reader.read_u8())
|
||||
.map_err(|err| panic!("unknown builtin id: {}", err.number));
|
||||
self.push_stack(Value::new_inline(PrimOp {
|
||||
self.push(Value::new_inline(PrimOp {
|
||||
id,
|
||||
arity: fix_builtins::BUILTINS[id as usize].1,
|
||||
}));
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_mk_pos(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
pub(crate) fn op_mk_pos(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let _span_id = reader.read_u32();
|
||||
todo!("MkPos");
|
||||
}
|
||||
@@ -31,7 +31,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
pub(crate) fn op_load_repl_binding(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let _name = reader.read_string_id();
|
||||
todo!("LoadReplBinding");
|
||||
}
|
||||
@@ -40,7 +40,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
pub(crate) fn op_load_scoped_binding(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let _name = reader.read_string_id();
|
||||
todo!("LoadScopedBinding");
|
||||
}
|
||||
@@ -51,7 +51,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
_mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let _parts_count = reader.read_u16() as usize;
|
||||
let _force_string = reader.read_u8() != 0;
|
||||
let mut _operands: smallvec::SmallVec<[crate::OperandData; 4]> =
|
||||
@@ -63,7 +63,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_resolve_path(&mut self, _ctx: &mut impl crate::VmContext) -> StepResult {
|
||||
pub(crate) fn op_resolve_path(&mut self, _ctx: &mut impl crate::VmContext) -> Step {
|
||||
todo!("implement ResolvePath");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use fix_error::Error;
|
||||
use gc_arena::{Gc, Mutation, RefLock};
|
||||
|
||||
use crate::{BytecodeReader, CallFrame, Closure, Env, StepResult, ThunkState, VmContextExt};
|
||||
use crate::{BytecodeReader, CallFrame, Closure, Env, Step, ThunkState, VmContextExt};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
@@ -10,7 +10,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
@@ -18,7 +18,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
return self.finish_err(Error::eval_error("stack overflow; max-call-depth exceeded"));
|
||||
}
|
||||
self.call_depth += 1;
|
||||
let func = self.pop_stack();
|
||||
let func = self.pop();
|
||||
let arg = reader.read_operand_data(ctx).resolve(mc, self);
|
||||
if let Some(closure) = func.as_gc::<Closure>() {
|
||||
let ip = closure.ip;
|
||||
@@ -41,7 +41,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
} else {
|
||||
todo!("call other types: {func:?}")
|
||||
}
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -50,7 +50,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
self.handle_return(reader, ctx, mc)
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
ctx: &C,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let ret_inst_pc = reader.pc() - 1;
|
||||
let Some(CallFrame {
|
||||
pc: ret_pc,
|
||||
@@ -69,18 +69,18 @@ impl<'gc> crate::Vm<'gc> {
|
||||
with_env,
|
||||
}) = self.call_stack.pop()
|
||||
else {
|
||||
let val = self.pop_stack();
|
||||
let val = self.pop();
|
||||
return self.finish_ok(ctx.convert_value(val));
|
||||
};
|
||||
reader.set_pc(ret_pc);
|
||||
if let Some(outer_thunk) = thunk {
|
||||
let val = self.pop_stack();
|
||||
let val = self.pop();
|
||||
match val.restrict() {
|
||||
Ok(val) => {
|
||||
*outer_thunk.borrow_mut(mc) = ThunkState::Evaluated(val);
|
||||
if reader.bytecode().get(ret_pc).copied() == Some(fix_codegen::Op::Return as u8)
|
||||
{
|
||||
self.push_stack(val.relax());
|
||||
self.push(val.relax());
|
||||
}
|
||||
}
|
||||
Err(inner_thunk) => {
|
||||
@@ -109,14 +109,14 @@ impl<'gc> crate::Vm<'gc> {
|
||||
reader.set_pc(inner_ip);
|
||||
self.env = inner_env;
|
||||
self.with_env = inner_with_env;
|
||||
return StepResult::Continue;
|
||||
return Step::Continue;
|
||||
}
|
||||
ThunkState::Evaluated(val) => {
|
||||
*outer_thunk.borrow_mut(mc) = ThunkState::Evaluated(val);
|
||||
if reader.bytecode().get(ret_pc).copied()
|
||||
== Some(fix_codegen::Op::Return as u8)
|
||||
{
|
||||
self.push_stack(val.relax());
|
||||
self.push(val.relax());
|
||||
}
|
||||
}
|
||||
ThunkState::Apply { func: _, arg: _ } => todo!("force Apply thunk"),
|
||||
@@ -132,6 +132,6 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
self.env = env;
|
||||
self.with_env = with_env;
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use gc_arena::{Gc, Mutation, RefLock};
|
||||
|
||||
use crate::{BytecodeReader, StepResult, ThunkState, Value};
|
||||
use crate::{BytecodeReader, Step, ThunkState, Value};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
@@ -8,7 +8,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let entry_point = reader.read_u32();
|
||||
let thunk = Gc::new(
|
||||
mc,
|
||||
@@ -18,8 +18,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
with_env: self.with_env,
|
||||
}),
|
||||
);
|
||||
self.push_stack(Value::new_gc(thunk));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_gc(thunk));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -27,7 +27,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let entry_point = reader.read_u32();
|
||||
let n_locals = reader.read_u32();
|
||||
let closure = Gc::new(
|
||||
@@ -39,8 +39,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
pattern: None,
|
||||
},
|
||||
);
|
||||
self.push_stack(Value::new_gc(closure));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_gc(closure));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -48,7 +48,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let entry_point = reader.read_u32();
|
||||
let n_locals = reader.read_u32();
|
||||
let req_count = reader.read_u16() as usize;
|
||||
@@ -89,7 +89,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
pattern: Some(pattern),
|
||||
},
|
||||
);
|
||||
self.push_stack(Value::new_gc(closure));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_gc(closure));
|
||||
Step::Continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use gc_arena::Gc;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{
|
||||
AttrKeyData, AttrSet, BytecodeReader, List, NixString, OperandData, StepResult, Value,
|
||||
AttrKeyData, AttrSet, BytecodeReader, List, NixString, OperandData, Step, Value,
|
||||
};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
@@ -13,7 +13,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let count = reader.read_u32() as usize;
|
||||
let mut entries: SmallVec<[AttrEntry; 4]> = SmallVec::with_capacity(count);
|
||||
for _ in 0..count {
|
||||
@@ -37,14 +37,14 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
kv.sort_by_key(|(k, _)| *k);
|
||||
let attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(kv));
|
||||
self.push_stack(Value::new_gc(attrs));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_gc(attrs));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_make_empty_attrs(&mut self) -> StepResult {
|
||||
self.push_stack(self.empty_attrs);
|
||||
StepResult::Continue
|
||||
pub(crate) fn op_make_empty_attrs(&mut self) -> Step {
|
||||
self.push(self.empty_attrs);
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -53,7 +53,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let _span_id = reader.read_u32();
|
||||
let key = reader.read_string_id();
|
||||
|
||||
@@ -61,7 +61,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
return step;
|
||||
}
|
||||
|
||||
let attrs = self.peek_stack(0).restrict().expect("forced");
|
||||
let attrs = self.peek(0).restrict().expect("forced");
|
||||
let Some(attrset) = attrs.as_gc::<AttrSet>() else {
|
||||
return self.finish_err(Error::eval_error(
|
||||
"value is not a set while a set was expected",
|
||||
@@ -70,7 +70,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
|
||||
match attrset.lookup(key) {
|
||||
Some(v) => {
|
||||
self.replace_stack(0, v);
|
||||
self.replace(0, v);
|
||||
}
|
||||
None => loop {
|
||||
let byte = reader.bytecode()[reader.pc()];
|
||||
@@ -80,7 +80,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
reader.set_pc(reader.pc() + 1 + 4);
|
||||
} else if byte == fix_codegen::Op::JumpIfSelectSucceeded as u8 {
|
||||
reader.set_pc(reader.pc() + 1 + 4);
|
||||
let _ = self.pop_stack();
|
||||
let _ = self.pop();
|
||||
break;
|
||||
} else {
|
||||
let name = ctx.resolve_string(key);
|
||||
@@ -89,7 +89,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
},
|
||||
}
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -98,7 +98,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let _span_id = reader.read_u32();
|
||||
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
@@ -129,28 +129,28 @@ impl<'gc> crate::Vm<'gc> {
|
||||
match attrset.lookup(key_sid) {
|
||||
Some(v) => {
|
||||
self.stack.truncate(self.stack.len() - 2);
|
||||
self.push_stack(v);
|
||||
self.push(v);
|
||||
}
|
||||
None => {
|
||||
let name = ctx.resolve_string(key_sid);
|
||||
return self.finish_err(Error::eval_error(format!("attribute '{name}' missing")));
|
||||
}
|
||||
}
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_jump_if_select_succeeded(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let offset = reader.read_i32();
|
||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_has_attr(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
pub(crate) fn op_has_attr(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let _n = reader.read_u16() as usize;
|
||||
todo!("HasAttr");
|
||||
}
|
||||
@@ -161,21 +161,21 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let count = reader.read_u32() as usize;
|
||||
let mut items: SmallVec<[Value; 4]> = SmallVec::with_capacity(count);
|
||||
for _ in 0..count {
|
||||
items.push(reader.read_operand_data(ctx).resolve(mc, self));
|
||||
}
|
||||
let list = Gc::new(mc, List { inner: items });
|
||||
self.push_stack(Value::new_gc(list));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_gc(list));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_make_empty_list(&mut self) -> StepResult {
|
||||
self.push_stack(self.empty_list);
|
||||
StepResult::Continue
|
||||
pub(crate) fn op_make_empty_list(&mut self) -> Step {
|
||||
self.push(self.empty_list);
|
||||
Step::Continue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{BytecodeReader, StepResult};
|
||||
use crate::{BytecodeReader, Step};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
@@ -6,16 +6,16 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let offset = reader.read_i32();
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let cond = self.pop_stack();
|
||||
let cond = self.pop();
|
||||
if cond.as_inline::<bool>() == Some(false) {
|
||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||
}
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -23,27 +23,27 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let offset = reader.read_i32();
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let cond = self.pop_stack();
|
||||
let cond = self.pop();
|
||||
if cond.as_inline::<bool>() == Some(true) {
|
||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||
}
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_jump(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
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);
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_assert(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
pub(crate) fn op_assert(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let _raw_idx = reader.read_u32();
|
||||
let _span_id = reader.read_u32();
|
||||
todo!("implement Assert (force TOS)");
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use gc_arena::{Gc, Mutation};
|
||||
|
||||
use crate::{BytecodeReader, StepResult, Value};
|
||||
use crate::{BytecodeReader, Step, Value};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_smi(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
pub(crate) fn op_push_smi(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let val = reader.read_i32();
|
||||
self.push_stack(Value::new_inline(val));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_inline(val));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -15,41 +15,41 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let val = reader.read_i64();
|
||||
self.push_stack(Value::new_gc(Gc::new(mc, val)));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_gc(Gc::new(mc, val)));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_float(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
pub(crate) fn op_push_float(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let val = reader.read_f64();
|
||||
self.push_stack(Value::new_float(val));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_float(val));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_string(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
pub(crate) fn op_push_string(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let sid = reader.read_string_id();
|
||||
self.push_stack(Value::new_inline(sid));
|
||||
StepResult::Continue
|
||||
self.push(Value::new_inline(sid));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_null(&mut self) -> StepResult {
|
||||
self.push_stack(Value::new_inline(crate::Null));
|
||||
StepResult::Continue
|
||||
pub(crate) fn op_push_null(&mut self) -> Step {
|
||||
self.push(Value::new_inline(crate::Null));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_true(&mut self) -> StepResult {
|
||||
self.push_stack(Value::new_inline(true));
|
||||
StepResult::Continue
|
||||
pub(crate) fn op_push_true(&mut self) -> Step {
|
||||
self.push(Value::new_inline(true));
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_false(&mut self) -> StepResult {
|
||||
self.push_stack(Value::new_inline(false));
|
||||
StepResult::Continue
|
||||
pub(crate) fn op_push_false(&mut self) -> Step {
|
||||
self.push(Value::new_inline(false));
|
||||
Step::Continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::{BytecodeReader, Mutation, StepResult, Value};
|
||||
use crate::{BytecodeReader, Mutation, Step, Value};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_load_local(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
pub(crate) fn op_load_local(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let idx = reader.read_u32() as usize;
|
||||
self.push_stack(self.env.borrow().locals[idx]);
|
||||
StepResult::Continue
|
||||
self.push(self.env.borrow().locals[idx]);
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_load_outer(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
pub(crate) fn op_load_outer(&mut self, reader: &mut BytecodeReader<'_>) -> Step {
|
||||
let layer = reader.read_u8();
|
||||
let idx = reader.read_u32() as usize;
|
||||
let mut cur = self.env;
|
||||
@@ -18,8 +18,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
cur = prev;
|
||||
}
|
||||
let val = cur.borrow().locals[idx];
|
||||
self.push_stack(val);
|
||||
StepResult::Continue
|
||||
self.push(val);
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -27,11 +27,11 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let idx = reader.read_u32() as usize;
|
||||
let val = self.pop_stack();
|
||||
let val = self.pop();
|
||||
self.env.borrow_mut(mc).locals[idx] = val;
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -39,12 +39,12 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let count = reader.read_u32() as usize;
|
||||
self.env
|
||||
.borrow_mut(mc)
|
||||
.locals
|
||||
.extend(std::iter::repeat_n(Value::default(), count));
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ use fix_common::Symbol;
|
||||
use fix_error::Error;
|
||||
use gc_arena::Gc;
|
||||
|
||||
use crate::{BytecodeReader, CallFrame, StepResult, WithEnv};
|
||||
use crate::{BytecodeReader, CallFrame, Step, WithEnv};
|
||||
use crate::value::*;
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
@@ -11,7 +12,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let env = reader.read_operand_data(ctx).resolve(mc, self);
|
||||
let scope = Gc::new(
|
||||
mc,
|
||||
@@ -21,20 +22,20 @@ impl<'gc> crate::Vm<'gc> {
|
||||
},
|
||||
);
|
||||
self.with_env = Some(scope);
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_pop_with(&mut self) -> StepResult {
|
||||
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;
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_prepare_with(&mut self) -> StepResult {
|
||||
pub(crate) fn op_prepare_with(&mut self) -> Step {
|
||||
self.call_stack.push(CallFrame {
|
||||
pc: usize::MAX,
|
||||
stack_depth: 0,
|
||||
@@ -42,7 +43,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
});
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -51,7 +52,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult {
|
||||
) -> Step {
|
||||
let name = reader.read_string_id();
|
||||
|
||||
let Some(&WithEnv { env, prev }) = self.with_env.as_deref() else {
|
||||
@@ -64,23 +65,26 @@ impl<'gc> crate::Vm<'gc> {
|
||||
Symbol::from(ctx.resolve_string(name))
|
||||
)));
|
||||
};
|
||||
self.push_stack(env);
|
||||
self.push(env);
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
|
||||
let env = self.pop_stack().as_gc::<crate::AttrSet>().unwrap();
|
||||
let env = match self.pop_forced_expect_gc::<AttrSet>() {
|
||||
Ok(val) => val,
|
||||
Err(got) => return self.finish_type_err(NixType::List, got)
|
||||
};
|
||||
let Some(val) = env.lookup(name) else {
|
||||
reader.set_pc(reader.inst_start_pc());
|
||||
self.with_env = prev;
|
||||
return StepResult::Continue;
|
||||
return Step::Continue;
|
||||
};
|
||||
|
||||
self.push_stack(val);
|
||||
self.push(val);
|
||||
let Some(CallFrame { with_env, .. }) = self.call_stack.pop() else {
|
||||
unreachable!()
|
||||
};
|
||||
self.with_env = with_env;
|
||||
StepResult::Continue
|
||||
Step::Continue
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user