deep equal

This commit is contained in:
2026-05-16 23:18:50 +08:00
parent 29fab93cd1
commit 9a17990d5e
5 changed files with 266 additions and 91 deletions
+2 -73
View File
@@ -105,12 +105,7 @@ impl<'gc> crate::Vm<'gc> {
mc: &Mutation<'gc>,
) -> Step {
let (lhs, rhs) = self.force_and_retry::<(StrictValue, StrictValue)>(reader, mc)?;
let eq = match self.values_equal(ctx, lhs, rhs) {
Ok(eq) => eq,
Err(e) => return self.finish_vm_err(e),
};
self.push(Value::new_inline(eq));
Step::Continue(())
fix_primops::start_eq(self, ctx, reader, mc, lhs, rhs, false)
}
#[inline(always)]
@@ -121,12 +116,7 @@ impl<'gc> crate::Vm<'gc> {
mc: &Mutation<'gc>,
) -> Step {
let (lhs, rhs) = self.force_and_retry::<(StrictValue, StrictValue)>(reader, mc)?;
let eq = match self.values_equal(ctx, lhs, rhs) {
Ok(eq) => eq,
Err(e) => return self.finish_vm_err(e),
};
self.push(Value::new_inline(!eq));
Step::Continue(())
fix_primops::start_eq(self, ctx, reader, mc, lhs, rhs, true)
}
#[inline(always)]
@@ -230,67 +220,6 @@ impl<'gc> crate::Vm<'gc> {
Step::Continue(())
}
pub(crate) fn values_equal(
&mut self,
ctx: &impl VmRuntimeCtx,
lhs: StrictValue<'gc>,
rhs: StrictValue<'gc>,
) -> crate::VmResult<bool> {
if let (Some(a), Some(b)) = (get_num(lhs), get_num(rhs)) {
return Ok(match (a, b) {
(NixNum::Int(a), NixNum::Int(b)) => a == b,
(NixNum::Float(a), NixNum::Float(b)) => a == b,
(NixNum::Int(a), NixNum::Float(b)) => a as f64 == b,
(NixNum::Float(a), NixNum::Int(b)) => a == b as f64,
});
}
if let (Some(a), Some(b)) = (lhs.as_inline::<bool>(), rhs.as_inline::<bool>()) {
return Ok(a == b);
}
if lhs.is::<crate::Null>() && rhs.is::<crate::Null>() {
return Ok(true);
}
// Paths only equal paths (not strings, even if their text matches).
if let (Some(a), Some(b)) = (lhs.as_inline::<Path>(), rhs.as_inline::<Path>()) {
return Ok(a.0 == b.0);
}
if let (Some(a), Some(b)) = (ctx.get_string(lhs), ctx.get_string(rhs)) {
return Ok(a == b);
}
if let (Some(a), Some(b)) = (lhs.as_gc::<crate::List>(), rhs.as_gc::<crate::List>()) {
if a.inner.borrow().len() != b.inner.borrow().len() {
return Ok(false);
}
for (x, y) in a.inner.borrow().iter().zip(b.inner.borrow().iter()) {
let lx = x.restrict().expect("forced");
let ly = y.restrict().expect("forced");
if !self.values_equal(ctx, lx, ly)? {
return Ok(false);
}
}
return Ok(true);
}
if let (Some(a), Some(b)) = (lhs.as_gc::<crate::AttrSet>(), rhs.as_gc::<crate::AttrSet>()) {
let a = &a.entries;
let b = &b.entries;
if a.len() != b.len() {
return Ok(false);
}
for ((k1, v1), (k2, v2)) in a.iter().zip(b.iter()) {
if k1 != k2 {
return Ok(false);
}
let lv1 = v1.restrict().expect("forced");
let lv2 = v2.restrict().expect("forced");
if !self.values_equal(ctx, lv1, lv2)? {
return Ok(false);
}
}
return Ok(true);
}
Ok(false)
}
fn compare_values_inner(
&mut self,
ctx: &impl VmRuntimeCtx,