mirror of
https://github.com/urbit/ares.git
synced 2024-11-27 05:06:32 +03:00
Replace non_unifying_equality by rewriting assert_jer_err
This commit is contained in:
parent
b6a3ae3064
commit
15e0b5339f
@ -264,7 +264,7 @@ pub struct Context {
|
||||
pub scry_stack: Noun,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Error {
|
||||
ScryBlocked(Noun), // path
|
||||
ScryCrashed(Noun), // trace
|
||||
|
@ -39,7 +39,7 @@ pub type Jet = fn(&mut Context, Noun) -> Result;
|
||||
* Only return a deterministic error if the Nock would have deterministically
|
||||
* crashed.
|
||||
*/
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum JetErr {
|
||||
Punt, // Retry with the raw nock
|
||||
Fail(Error), // Error; do not retry
|
||||
@ -374,13 +374,40 @@ pub mod util {
|
||||
&jet_res
|
||||
);
|
||||
let jet_err = jet_res.unwrap_err();
|
||||
assert_eq!(
|
||||
jet_err, err,
|
||||
match (jet_err, err) {
|
||||
(JetErr::Punt, JetErr::Punt) => {}
|
||||
(JetErr::Fail(actual_err), JetErr::Fail(expected_err)) => {
|
||||
match (actual_err, expected_err) {
|
||||
(Error::ScryBlocked(mut actual), Error::ScryBlocked(mut expected))
|
||||
| (Error::ScryCrashed(mut actual), Error::ScryCrashed(mut expected))
|
||||
| (Error::Deterministic(mut actual), Error::Deterministic(mut expected))
|
||||
| (
|
||||
Error::NonDeterministic(mut actual),
|
||||
Error::NonDeterministic(mut expected),
|
||||
) => unsafe {
|
||||
assert!(unifying_equality(
|
||||
&mut context.stack,
|
||||
&mut actual,
|
||||
&mut expected
|
||||
));
|
||||
},
|
||||
_ => {
|
||||
panic!(
|
||||
"with sample: {}, expected err: {:?}, got: {:?}",
|
||||
sam, expected_err, actual_err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!(
|
||||
"with sample: {}, expected err: {:?}, got: {:?}",
|
||||
sam, err, jet_err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -979,86 +979,6 @@ pub unsafe fn unifying_equality(stack: &mut NockStack, a: *mut Noun, b: *mut Nou
|
||||
(*a).raw_equals(*b)
|
||||
}
|
||||
|
||||
/// This function only exists as a default equality comparator for Nouns in cases where we don't
|
||||
/// have a NockStack available to perform unifying equality checks.
|
||||
///
|
||||
/// One such case is for the implementation of PartialEq on Noun, which is used by the derived
|
||||
/// implementationa of PartialEq for interpreter::Error and jets::JetErr. These themselves are
|
||||
/// only used during unit testing.
|
||||
///
|
||||
/// This function is incredibly inefficient in the case of densely connected DAGs, and should
|
||||
/// never be used without a very good reason. ALWAYS prefer unifying_equality.
|
||||
pub fn non_unifying_equality(a: Noun, b: Noun) -> bool {
|
||||
// If the nouns are already word-equal we have nothing to do
|
||||
if unsafe { a.raw_equals(b) } {
|
||||
return true;
|
||||
};
|
||||
// If the nouns have cached mugs which are disequal we have nothing to do
|
||||
if let (Ok(a_alloc), Ok(b_alloc)) = (a.as_allocated(), b.as_allocated()) {
|
||||
if let (Some(a_mug), Some(b_mug)) = (a_alloc.get_cached_mug(), b_alloc.get_cached_mug()) {
|
||||
if a_mug != b_mug {
|
||||
return false;
|
||||
};
|
||||
};
|
||||
};
|
||||
let mut stack = Vec::new();
|
||||
stack.push((a, b));
|
||||
while let Some((x, y)) = stack.pop() {
|
||||
if unsafe { x.raw_equals(y) } {
|
||||
continue;
|
||||
};
|
||||
if let (Ok(x_alloc), Ok(y_alloc)) = (
|
||||
// equal direct atoms return true for raw_equals()
|
||||
x.as_allocated(),
|
||||
y.as_allocated(),
|
||||
) {
|
||||
if let (Some(x_mug), Some(y_mug)) = (x_alloc.get_cached_mug(), y_alloc.get_cached_mug())
|
||||
{
|
||||
if x_mug != y_mug {
|
||||
// short-circuit: the mugs differ therefore the nouns must differ
|
||||
return false;
|
||||
}
|
||||
};
|
||||
match (x_alloc.as_either(), y_alloc.as_either()) {
|
||||
(Left(x_indirect), Left(y_indirect)) => {
|
||||
if unsafe {
|
||||
x_indirect.size() == y_indirect.size()
|
||||
&& memcmp(
|
||||
x_indirect.data_pointer() as *const c_void,
|
||||
y_indirect.data_pointer() as *const c_void,
|
||||
x_indirect.size() << 3,
|
||||
) == 0
|
||||
} {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
(Right(x_cell), Right(y_cell)) => {
|
||||
if unsafe {
|
||||
x_cell.head().raw_equals(y_cell.head())
|
||||
&& x_cell.tail().raw_equals(y_cell.tail())
|
||||
} {
|
||||
continue;
|
||||
} else {
|
||||
stack.push((x_cell.tail(), y_cell.tail()));
|
||||
stack.push((x_cell.head(), y_cell.head()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
(_, _) => {
|
||||
// cells don't match atoms
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return unsafe { x.raw_equals(y) };
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
unsafe fn senior_pointer_first(
|
||||
stack: &NockStack,
|
||||
a: *const u64,
|
||||
@ -1198,46 +1118,3 @@ impl Stack for NockStack {
|
||||
self.layout_alloc(layout)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{Atom, Noun, D, T};
|
||||
use ibig::{ubig, UBig};
|
||||
|
||||
pub fn init_stack() -> NockStack {
|
||||
NockStack::new(8 << 10 << 10, 0)
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn A(stack: &mut NockStack, ubig: &UBig) -> Noun {
|
||||
Atom::from_ubig(stack, ubig).as_noun()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_non_unifying_equality() {
|
||||
let s = &mut init_stack();
|
||||
let d1 = D(1);
|
||||
let d2 = D(2);
|
||||
let d3 = D(1);
|
||||
let i1 = A(s, &ubig!(0xC0FFEEBABEB00B1E5));
|
||||
let i2 = A(s, &ubig!(0xBADDECAFC0FFEE000));
|
||||
let i3 = A(s, &ubig!(0xC0FFEEBABEB00B1E5));
|
||||
let c1 = T(s, &[d1, i3]);
|
||||
let c2 = T(s, &[d2, i2]);
|
||||
let c3 = T(s, &[d3, i1]);
|
||||
|
||||
assert!(non_unifying_equality(d1, d1));
|
||||
assert!(!non_unifying_equality(d1, d2));
|
||||
assert!(non_unifying_equality(d1, d3));
|
||||
|
||||
assert!(non_unifying_equality(i1, i1));
|
||||
assert!(!non_unifying_equality(i1, i2));
|
||||
assert!(non_unifying_equality(i1, i3));
|
||||
|
||||
assert!(non_unifying_equality(c1, c1));
|
||||
assert!(!non_unifying_equality(c1, c2));
|
||||
assert!(non_unifying_equality(c1, c3));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::mem::{non_unifying_equality, word_size_of, NockStack};
|
||||
use crate::mem::{word_size_of, NockStack};
|
||||
use bitvec::prelude::{BitSlice, Lsb0};
|
||||
use either::{Either, Left, Right};
|
||||
use ibig::{Stack, UBig};
|
||||
@ -1146,12 +1146,6 @@ impl fmt::Display for Noun {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::PartialEq for Noun {
|
||||
fn eq(&self, other: &Noun) -> bool {
|
||||
non_unifying_equality(*self, *other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Slots for Noun {}
|
||||
impl private::RawSlots for Noun {
|
||||
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
||||
|
Loading…
Reference in New Issue
Block a user