mirror of
https://github.com/urbit/ares.git
synced 2024-12-25 06:12:24 +03:00
Refactor JetErr to use interpreter::Failure enum
This commit is contained in:
parent
0632de6f1e
commit
7e4bf3ae5d
@ -286,7 +286,7 @@ pub enum ScryError {
|
|||||||
NonDeterministic(Noun), // trace
|
NonDeterministic(Noun), // trace
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum Failure {
|
pub enum Failure {
|
||||||
Blocked(Noun), // path
|
Blocked(Noun), // path
|
||||||
Deterministic,
|
Deterministic,
|
||||||
@ -305,16 +305,6 @@ impl From<cold::Error> for Failure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<JetErr> for Failure {
|
|
||||||
fn from(e: JetErr) -> Self {
|
|
||||||
match e {
|
|
||||||
JetErr::Deterministic => Failure::Deterministic,
|
|
||||||
JetErr::NonDeterministic => Failure::NonDeterministic,
|
|
||||||
JetErr::Punt => panic!("unhandled JetErr::Punt"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn debug_assertions(stack: &mut NockStack, noun: Noun) {
|
fn debug_assertions(stack: &mut NockStack, noun: Noun) {
|
||||||
assert_acyclic!(noun);
|
assert_acyclic!(noun);
|
||||||
@ -1476,8 +1466,10 @@ mod hint {
|
|||||||
} else {
|
} else {
|
||||||
// XX: Need better message in slog; need better slogging tools
|
// XX: Need better message in slog; need better slogging tools
|
||||||
// format!("invalid root parent axis: {} {}", chum, parent_formula_ax)
|
// format!("invalid root parent axis: {} {}", chum, parent_formula_ax)
|
||||||
let tape =
|
let tape = tape(
|
||||||
tape(stack, "serf: cold: register: invalid root parent axis");
|
stack,
|
||||||
|
"serf: cold: register: invalid root parent axis",
|
||||||
|
);
|
||||||
slog_leaf(stack, newt, tape);
|
slog_leaf(stack, newt, tape);
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ pub mod nock;
|
|||||||
pub mod text;
|
pub mod text;
|
||||||
pub mod tree;
|
pub mod tree;
|
||||||
|
|
||||||
use crate::interpreter::Context;
|
use crate::interpreter::{Context, Failure};
|
||||||
use crate::jets::bits::*;
|
use crate::jets::bits::*;
|
||||||
use crate::jets::cold::Cold;
|
use crate::jets::cold::Cold;
|
||||||
use crate::jets::form::*;
|
use crate::jets::form::*;
|
||||||
@ -39,14 +39,13 @@ pub type Jet = fn(&mut Context, Noun) -> Result;
|
|||||||
*/
|
*/
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum JetErr {
|
pub enum JetErr {
|
||||||
Punt, // Retry with the raw nock
|
Punt, // Retry with the raw nock
|
||||||
Deterministic, // The Nock would have crashed
|
Fail(Failure), // Error; do not retry
|
||||||
NonDeterministic, // Other error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<noun::Error> for JetErr {
|
impl From<noun::Error> for JetErr {
|
||||||
fn from(_err: noun::Error) -> Self {
|
fn from(_err: noun::Error) -> Self {
|
||||||
Self::Deterministic
|
Self::Fail(Failure::Deterministic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +53,15 @@ impl From<JetErr> for () {
|
|||||||
fn from(_: JetErr) -> Self {}
|
fn from(_: JetErr) -> Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<JetErr> for Failure {
|
||||||
|
fn from(e: JetErr) -> Self {
|
||||||
|
match e {
|
||||||
|
JetErr::Fail(f) => f,
|
||||||
|
JetErr::Punt => panic!("unhandled JetErr::Punt"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_jet(jet_name: Noun) -> Option<Jet> {
|
pub fn get_jet(jet_name: Noun) -> Option<Jet> {
|
||||||
match jet_name.as_direct().ok()?.data() {
|
match jet_name.as_direct().ok()?.data() {
|
||||||
tas!(b"add") => Some(jet_add),
|
tas!(b"add") => Some(jet_add),
|
||||||
@ -130,12 +138,13 @@ pub mod util {
|
|||||||
pub fn checked_add(a: usize, b: usize) -> result::Result<usize, JetErr> {
|
pub fn checked_add(a: usize, b: usize) -> result::Result<usize, JetErr> {
|
||||||
a.checked_add(b)
|
a.checked_add(b)
|
||||||
.filter(|x| x <= &MAX_BIT_LENGTH)
|
.filter(|x| x <= &MAX_BIT_LENGTH)
|
||||||
.ok_or(JetErr::NonDeterministic)
|
.ok_or(JetErr::Fail(Failure::NonDeterministic))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs addition that returns None on Noun size overflow
|
/// Performs addition that returns None on Noun size overflow
|
||||||
pub fn checked_sub(a: usize, b: usize) -> result::Result<usize, JetErr> {
|
pub fn checked_sub(a: usize, b: usize) -> result::Result<usize, JetErr> {
|
||||||
a.checked_sub(b).ok_or(JetErr::NonDeterministic)
|
a.checked_sub(b)
|
||||||
|
.ok_or(JetErr::Fail(Failure::NonDeterministic))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checked_left_shift(bloq: usize, a: usize) -> result::Result<usize, JetErr> {
|
pub fn checked_left_shift(bloq: usize, a: usize) -> result::Result<usize, JetErr> {
|
||||||
@ -143,7 +152,7 @@ pub mod util {
|
|||||||
|
|
||||||
// Catch overflow
|
// Catch overflow
|
||||||
if (res >> bloq) < a || res > MAX_BIT_LENGTH {
|
if (res >> bloq) < a || res > MAX_BIT_LENGTH {
|
||||||
Err(JetErr::NonDeterministic)
|
Err(JetErr::Fail(Failure::NonDeterministic))
|
||||||
} else {
|
} else {
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
@ -160,14 +169,15 @@ pub mod util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn slot(noun: Noun, axis: u64) -> Result {
|
pub fn slot(noun: Noun, axis: u64) -> Result {
|
||||||
noun.slot(axis).map_err(|_e| JetErr::Deterministic)
|
noun.slot(axis)
|
||||||
|
.map_err(|_e| JetErr::Fail(Failure::Deterministic))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract a bloq and check that it's computable by the current system
|
/// Extract a bloq and check that it's computable by the current system
|
||||||
pub fn bloq(a: Noun) -> result::Result<usize, JetErr> {
|
pub fn bloq(a: Noun) -> result::Result<usize, JetErr> {
|
||||||
let bloq = a.as_direct()?.data() as usize;
|
let bloq = a.as_direct()?.data() as usize;
|
||||||
if bloq >= 47 {
|
if bloq >= 47 {
|
||||||
Err(JetErr::NonDeterministic)
|
Err(JetErr::Fail(Failure::NonDeterministic))
|
||||||
} else {
|
} else {
|
||||||
Ok(bloq)
|
Ok(bloq)
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
/** Bit arithmetic & logic jets
|
/** Bit arithmetic & logic jets
|
||||||
*/
|
*/
|
||||||
use crate::interpreter::Context;
|
use crate::interpreter::{Context, Failure};
|
||||||
use crate::jets::util::*;
|
use crate::jets::util::*;
|
||||||
use crate::jets::JetErr::*;
|
use crate::jets::{JetErr, Result};
|
||||||
use crate::jets::Result;
|
|
||||||
use crate::noun::{DirectAtom, IndirectAtom, Noun, D};
|
use crate::noun::{DirectAtom, IndirectAtom, Noun, D};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
@ -246,7 +245,7 @@ pub fn jet_rev(context: &mut Context, subject: Noun) -> Result {
|
|||||||
let boz = slot(arg, 2)?.as_atom()?.as_direct()?.data();
|
let boz = slot(arg, 2)?.as_atom()?.as_direct()?.data();
|
||||||
|
|
||||||
if boz >= 64 {
|
if boz >= 64 {
|
||||||
return Err(NonDeterministic);
|
return Err(JetErr::Fail(Failure::Deterministic));
|
||||||
}
|
}
|
||||||
|
|
||||||
let boz = boz as usize;
|
let boz = boz as usize;
|
||||||
|
@ -271,8 +271,8 @@ pub struct Cold(*mut ColdMem);
|
|||||||
|
|
||||||
struct ColdMem {
|
struct ColdMem {
|
||||||
/// key: outermost battery (e.g. furthest battery from root for a core)
|
/// key: outermost battery (e.g. furthest battery from root for a core)
|
||||||
/// value: possible registered paths for core
|
/// value: possible registered paths for core
|
||||||
///
|
///
|
||||||
/// Identical nock can exist in multiple places, so the outermost battery
|
/// Identical nock can exist in multiple places, so the outermost battery
|
||||||
/// yield multiple paths. Instead of matching on the entire core in the Hamt
|
/// yield multiple paths. Instead of matching on the entire core in the Hamt
|
||||||
/// (which would require iterating through every possible pait), we match
|
/// (which would require iterating through every possible pait), we match
|
||||||
@ -282,7 +282,7 @@ struct ColdMem {
|
|||||||
/// Roots
|
/// Roots
|
||||||
/// key: root noun
|
/// key: root noun
|
||||||
/// value: root path
|
/// value: root path
|
||||||
///
|
///
|
||||||
/// Just like battery_to_paths, but for roots (which refer to themselves as
|
/// Just like battery_to_paths, but for roots (which refer to themselves as
|
||||||
/// their parent).
|
/// their parent).
|
||||||
root_to_paths: Hamt<NounList>,
|
root_to_paths: Hamt<NounList>,
|
||||||
|
@ -12,10 +12,9 @@
|
|||||||
* Another approach is use a global custom allocator. This is fairly involved, but it would allow
|
* Another approach is use a global custom allocator. This is fairly involved, but it would allow
|
||||||
* us to use any library without worrying whether it allocates.
|
* us to use any library without worrying whether it allocates.
|
||||||
*/
|
*/
|
||||||
use crate::interpreter::Context;
|
use crate::interpreter::{Context, Failure};
|
||||||
use crate::jets::util::*;
|
use crate::jets::util::*;
|
||||||
use crate::jets::JetErr::*;
|
use crate::jets::{JetErr, Result};
|
||||||
use crate::jets::Result;
|
|
||||||
use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
|
use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
|
||||||
use either::{Left, Right};
|
use either::{Left, Right};
|
||||||
use ibig::ops::DivRem;
|
use ibig::ops::DivRem;
|
||||||
@ -45,7 +44,7 @@ pub fn jet_dec(context: &mut Context, subject: Noun) -> Result {
|
|||||||
match atom.as_either() {
|
match atom.as_either() {
|
||||||
Left(direct) => {
|
Left(direct) => {
|
||||||
if direct.data() == 0 {
|
if direct.data() == 0 {
|
||||||
Err(Deterministic)
|
Err(JetErr::Fail(Failure::Deterministic))
|
||||||
} else {
|
} else {
|
||||||
Ok(unsafe { DirectAtom::new_unchecked(direct.data() - 1) }.as_noun())
|
Ok(unsafe { DirectAtom::new_unchecked(direct.data() - 1) }.as_noun())
|
||||||
}
|
}
|
||||||
@ -73,7 +72,7 @@ pub fn jet_dec(context: &mut Context, subject: Noun) -> Result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(Deterministic)
|
Err(JetErr::Fail(Failure::Deterministic))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +83,7 @@ pub fn jet_div(context: &mut Context, subject: Noun) -> Result {
|
|||||||
let b = slot(arg, 3)?.as_atom()?;
|
let b = slot(arg, 3)?.as_atom()?;
|
||||||
|
|
||||||
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
||||||
Err(Deterministic)
|
Err(JetErr::Fail(Failure::Deterministic))
|
||||||
} else if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
} else if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||||
Ok(unsafe { DirectAtom::new_unchecked(a.data() / b.data()) }.as_noun())
|
Ok(unsafe { DirectAtom::new_unchecked(a.data() / b.data()) }.as_noun())
|
||||||
} else {
|
} else {
|
||||||
@ -102,7 +101,7 @@ pub fn jet_dvr(context: &mut Context, subject: Noun) -> Result {
|
|||||||
let b = slot(arg, 3)?.as_atom()?;
|
let b = slot(arg, 3)?.as_atom()?;
|
||||||
|
|
||||||
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
||||||
Err(Deterministic)
|
Err(JetErr::Fail(Failure::Deterministic))
|
||||||
} else {
|
} else {
|
||||||
let (div, rem) = if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
let (div, rem) = if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||||
let (div, rem) = (a.data() / b.data(), a.data() % b.data());
|
let (div, rem) = (a.data() / b.data(), a.data() % b.data());
|
||||||
@ -223,7 +222,7 @@ pub fn jet_mod(context: &mut Context, subject: Noun) -> Result {
|
|||||||
let b = slot(arg, 3)?.as_atom()?;
|
let b = slot(arg, 3)?.as_atom()?;
|
||||||
|
|
||||||
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
||||||
Err(Deterministic)
|
Err(JetErr::Fail(Failure::Deterministic))
|
||||||
} else if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
} else if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||||
Ok(unsafe { DirectAtom::new_unchecked(a.data() % b.data()) }.as_noun())
|
Ok(unsafe { DirectAtom::new_unchecked(a.data() % b.data()) }.as_noun())
|
||||||
} else {
|
} else {
|
||||||
@ -271,6 +270,7 @@ pub fn jet_sub(context: &mut Context, subject: Noun) -> Result {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::interpreter::Failure;
|
||||||
use crate::jets::util::test::{
|
use crate::jets::util::test::{
|
||||||
assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_context, A,
|
assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_context, A,
|
||||||
};
|
};
|
||||||
@ -377,7 +377,7 @@ mod tests {
|
|||||||
let (a0, _a24, a63, _a96, a128) = atoms(s);
|
let (a0, _a24, a63, _a96, a128) = atoms(s);
|
||||||
assert_jet_ubig(c, jet_dec, a128, ubig!(0xdeadbeef12345678fedcba987654320f));
|
assert_jet_ubig(c, jet_dec, a128, ubig!(0xdeadbeef12345678fedcba987654320f));
|
||||||
assert_jet(c, jet_dec, a63, D(0x7ffffffffffffffe));
|
assert_jet(c, jet_dec, a63, D(0x7ffffffffffffffe));
|
||||||
assert_jet_err(c, jet_dec, a0, Deterministic);
|
assert_jet_err(c, jet_dec, a0, JetErr::Fail(Failure::Deterministic));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -399,8 +399,18 @@ mod tests {
|
|||||||
_0x00000000000001000000000000000000000000000000000000000000000000000000000000000001
|
_0x00000000000001000000000000000000000000000000000000000000000000000000000000000001
|
||||||
);
|
);
|
||||||
assert_math_jet(c, jet_div, &[atom_528, atom_264], res);
|
assert_math_jet(c, jet_div, &[atom_528, atom_264], res);
|
||||||
assert_math_jet_err(c, jet_div, &[atom_63, atom_0], Deterministic);
|
assert_math_jet_err(
|
||||||
assert_math_jet_err(c, jet_div, &[atom_0, atom_0], Deterministic);
|
c,
|
||||||
|
jet_div,
|
||||||
|
&[atom_63, atom_0],
|
||||||
|
JetErr::Fail(Failure::Deterministic),
|
||||||
|
);
|
||||||
|
assert_math_jet_err(
|
||||||
|
c,
|
||||||
|
jet_div,
|
||||||
|
&[atom_0, atom_0],
|
||||||
|
JetErr::Fail(Failure::Deterministic),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -446,7 +456,12 @@ mod tests {
|
|||||||
let res = T(&mut c.stack, &[res_a, res_b]);
|
let res = T(&mut c.stack, &[res_a, res_b]);
|
||||||
assert_jet(c, jet_dvr, sam, res);
|
assert_jet(c, jet_dvr, sam, res);
|
||||||
|
|
||||||
assert_math_jet_err(c, jet_dvr, &[atom_63, atom_0], Deterministic);
|
assert_math_jet_err(
|
||||||
|
c,
|
||||||
|
jet_dvr,
|
||||||
|
&[atom_63, atom_0],
|
||||||
|
JetErr::Fail(Failure::Deterministic),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -521,8 +536,18 @@ mod tests {
|
|||||||
assert_math_jet(c, jet_mod, &[atom_63, atom_24], ubig!(0x798385));
|
assert_math_jet(c, jet_mod, &[atom_63, atom_24], ubig!(0x798385));
|
||||||
assert_math_jet(c, jet_mod, &[atom_128, atom_24], ubig!(0x3b2013));
|
assert_math_jet(c, jet_mod, &[atom_128, atom_24], ubig!(0x3b2013));
|
||||||
assert_math_jet(c, jet_mod, &[atom_528, atom_264], ubig!(0x100));
|
assert_math_jet(c, jet_mod, &[atom_528, atom_264], ubig!(0x100));
|
||||||
assert_math_jet_err(c, jet_mod, &[atom_63, atom_0], Deterministic);
|
assert_math_jet_err(
|
||||||
assert_math_jet_err(c, jet_mod, &[atom_0, atom_0], Deterministic);
|
c,
|
||||||
|
jet_mod,
|
||||||
|
&[atom_63, atom_0],
|
||||||
|
JetErr::Fail(Failure::Deterministic),
|
||||||
|
);
|
||||||
|
assert_math_jet_err(
|
||||||
|
c,
|
||||||
|
jet_mod,
|
||||||
|
&[atom_0, atom_0],
|
||||||
|
JetErr::Fail(Failure::Deterministic),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -568,6 +593,11 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_math_jet(c, jet_sub, &[atom_63, atom_63], ubig!(0));
|
assert_math_jet(c, jet_sub, &[atom_63, atom_63], ubig!(0));
|
||||||
assert_math_jet(c, jet_sub, &[atom_128, atom_128], ubig!(0));
|
assert_math_jet(c, jet_sub, &[atom_128, atom_128], ubig!(0));
|
||||||
assert_math_jet_err(c, jet_sub, &[atom_63, atom_96], Deterministic);
|
assert_math_jet_err(
|
||||||
|
c,
|
||||||
|
jet_sub,
|
||||||
|
&[atom_63, atom_96],
|
||||||
|
JetErr::Fail(Failure::Deterministic),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod util {
|
pub mod util {
|
||||||
use crate::interpreter::{interpret, Context, Error, NockError, ScryError};
|
use crate::interpreter::{interpret, Context, Error, Failure, NockError, ScryError};
|
||||||
use crate::jets;
|
use crate::jets;
|
||||||
use crate::jets::form::util::scow;
|
use crate::jets::form::util::scow;
|
||||||
use crate::jets::util::rip;
|
use crate::jets::util::rip;
|
||||||
@ -51,14 +51,18 @@ pub mod util {
|
|||||||
Error::Nock(nock_err) => match nock_err {
|
Error::Nock(nock_err) => match nock_err {
|
||||||
NockError::Deterministic(trace) => Ok(T(&mut context.stack, &[D(2), trace])),
|
NockError::Deterministic(trace) => Ok(T(&mut context.stack, &[D(2), trace])),
|
||||||
// XX: trace is unused; needs to be printed or welded to trace from outer context
|
// XX: trace is unused; needs to be printed or welded to trace from outer context
|
||||||
NockError::NonDeterministic(_trace) => Err(JetErr::NonDeterministic),
|
NockError::NonDeterministic(_trace) => {
|
||||||
|
Err(JetErr::Fail(Failure::NonDeterministic))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Error::Scry(scry_err) => match scry_err {
|
Error::Scry(scry_err) => match scry_err {
|
||||||
ScryError::Blocked(path) => Ok(T(&mut context.stack, &[D(1), path])),
|
ScryError::Blocked(path) => Ok(T(&mut context.stack, &[D(1), path])),
|
||||||
// XX: trace is unused; needs to be printed or welded to trace from outer context
|
// XX: trace is unused; needs to be printed or welded to trace from outer context
|
||||||
ScryError::Deterministic(_trace) => Err(JetErr::Deterministic),
|
ScryError::Deterministic(_trace) => Err(JetErr::Fail(Failure::Deterministic)),
|
||||||
// XX: trace is unused; needs to be printed or welded to trace from outer context
|
// XX: trace is unused; needs to be printed or welded to trace from outer context
|
||||||
ScryError::NonDeterministic(_trace) => Err(JetErr::NonDeterministic),
|
ScryError::NonDeterministic(_trace) => {
|
||||||
|
Err(JetErr::Fail(Failure::NonDeterministic))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -73,14 +77,14 @@ pub mod util {
|
|||||||
|
|
||||||
match tag.data() {
|
match tag.data() {
|
||||||
x if x < 2 => return Ok(tone),
|
x if x < 2 => return Ok(tone),
|
||||||
x if x > 2 => return Err(JetErr::Deterministic),
|
x if x > 2 => return Err(JetErr::Fail(Failure::Deterministic)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if unsafe { original_list.raw_equals(D(0)) } {
|
if unsafe { original_list.raw_equals(D(0)) } {
|
||||||
return Ok(tone);
|
return Ok(tone);
|
||||||
} else if original_list.atom().is_some() {
|
} else if original_list.atom().is_some() {
|
||||||
return Err(JetErr::Deterministic);
|
return Err(JetErr::Fail(Failure::Deterministic));
|
||||||
}
|
}
|
||||||
|
|
||||||
// XX: trim traces longer than 1024 frames
|
// XX: trim traces longer than 1024 frames
|
||||||
|
@ -13,6 +13,7 @@ pub fn jet_lent(_context: &mut Context, subject: Noun) -> Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod util {
|
pub mod util {
|
||||||
|
use crate::interpreter::Failure;
|
||||||
use crate::jets::JetErr;
|
use crate::jets::JetErr;
|
||||||
use crate::noun::Noun;
|
use crate::noun::Noun;
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ pub mod util {
|
|||||||
if atom.as_bitslice().first_one().is_none() {
|
if atom.as_bitslice().first_one().is_none() {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
return Err(JetErr::Deterministic);
|
return Err(JetErr::Fail(Failure::Deterministic));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let cell = list.as_cell()?;
|
let cell = list.as_cell()?;
|
||||||
@ -39,6 +40,7 @@ pub mod util {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::interpreter::Failure;
|
||||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
||||||
use crate::jets::JetErr;
|
use crate::jets::JetErr;
|
||||||
use crate::noun::{D, T};
|
use crate::noun::{D, T};
|
||||||
@ -52,8 +54,8 @@ mod tests {
|
|||||||
assert_jet(c, jet_lent, sam, D(3));
|
assert_jet(c, jet_lent, sam, D(3));
|
||||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1), D(0)]);
|
let sam = T(&mut c.stack, &[D(3), D(2), D(1), D(0)]);
|
||||||
assert_jet(c, jet_lent, sam, D(3));
|
assert_jet(c, jet_lent, sam, D(3));
|
||||||
assert_jet_err(c, jet_lent, D(1), JetErr::Deterministic);
|
assert_jet_err(c, jet_lent, D(1), JetErr::Fail(Failure::Deterministic));
|
||||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1)]);
|
let sam = T(&mut c.stack, &[D(3), D(2), D(1)]);
|
||||||
assert_jet_err(c, jet_lent, sam, JetErr::Deterministic);
|
assert_jet_err(c, jet_lent, sam, JetErr::Fail(Failure::Deterministic));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
/** Tree jets
|
/** Tree jets
|
||||||
*/
|
*/
|
||||||
use crate::interpreter::Context;
|
use crate::interpreter::{Context, Failure};
|
||||||
use crate::jets::util::*;
|
use crate::jets::util::*;
|
||||||
use crate::jets::JetErr::*;
|
use crate::jets::{JetErr, Result};
|
||||||
use crate::jets::Result;
|
|
||||||
use crate::noun::{Noun, D};
|
use crate::noun::{Noun, D};
|
||||||
|
|
||||||
crate::gdb!();
|
crate::gdb!();
|
||||||
@ -15,7 +14,7 @@ pub fn jet_cap(_context: &mut Context, subject: Noun) -> Result {
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if met < 2 {
|
if met < 2 {
|
||||||
Err(Deterministic)
|
Err(JetErr::Fail(Failure::Deterministic))
|
||||||
} else if *(tom.as_bitslice().get_unchecked(met - 2)) {
|
} else if *(tom.as_bitslice().get_unchecked(met - 2)) {
|
||||||
Ok(D(3))
|
Ok(D(3))
|
||||||
} else {
|
} else {
|
||||||
@ -31,7 +30,7 @@ pub fn jet_mas(context: &mut Context, subject: Noun) -> Result {
|
|||||||
let met = met(0, tom);
|
let met = met(0, tom);
|
||||||
|
|
||||||
if met < 2 {
|
if met < 2 {
|
||||||
Err(Deterministic)
|
Err(JetErr::Fail(Failure::Deterministic))
|
||||||
} else {
|
} else {
|
||||||
let c = bex(stack, met - 1);
|
let c = bex(stack, met - 1);
|
||||||
let d = bex(stack, met - 2);
|
let d = bex(stack, met - 2);
|
||||||
@ -44,6 +43,7 @@ pub fn jet_mas(context: &mut Context, subject: Noun) -> Result {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::interpreter::Failure;
|
||||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
||||||
use crate::jets::JetErr;
|
use crate::jets::JetErr;
|
||||||
use crate::noun::D;
|
use crate::noun::D;
|
||||||
@ -52,8 +52,8 @@ mod tests {
|
|||||||
fn test_cap() {
|
fn test_cap() {
|
||||||
let c = &mut init_context();
|
let c = &mut init_context();
|
||||||
|
|
||||||
assert_jet_err(c, jet_cap, D(0), JetErr::Deterministic);
|
assert_jet_err(c, jet_cap, D(0), JetErr::Fail(Failure::Deterministic));
|
||||||
assert_jet_err(c, jet_cap, D(1), JetErr::Deterministic);
|
assert_jet_err(c, jet_cap, D(1), JetErr::Fail(Failure::Deterministic));
|
||||||
|
|
||||||
assert_jet(c, jet_cap, D(2), D(2));
|
assert_jet(c, jet_cap, D(2), D(2));
|
||||||
assert_jet(c, jet_cap, D(3), D(3));
|
assert_jet(c, jet_cap, D(3), D(3));
|
||||||
@ -68,8 +68,8 @@ mod tests {
|
|||||||
fn test_mas() {
|
fn test_mas() {
|
||||||
let c = &mut init_context();
|
let c = &mut init_context();
|
||||||
|
|
||||||
assert_jet_err(c, jet_mas, D(0), JetErr::Deterministic);
|
assert_jet_err(c, jet_mas, D(0), JetErr::Fail(Failure::Deterministic));
|
||||||
assert_jet_err(c, jet_mas, D(1), JetErr::Deterministic);
|
assert_jet_err(c, jet_mas, D(1), JetErr::Fail(Failure::Deterministic));
|
||||||
|
|
||||||
assert_jet(c, jet_mas, D(2), D(1));
|
assert_jet(c, jet_mas, D(2), D(1));
|
||||||
assert_jet(c, jet_mas, D(3), D(1));
|
assert_jet(c, jet_mas, D(3), D(1));
|
||||||
|
@ -979,6 +979,77 @@ pub unsafe fn unifying_equality(stack: &mut NockStack, a: *mut Noun, b: *mut Nou
|
|||||||
(*a).raw_equals(*b)
|
(*a).raw_equals(*b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
unsafe fn senior_pointer_first(
|
||||||
stack: &NockStack,
|
stack: &NockStack,
|
||||||
a: *const u64,
|
a: *const u64,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::mem::{word_size_of, NockStack};
|
use crate::mem::{non_unifying_equality, word_size_of, NockStack};
|
||||||
use bitvec::prelude::{BitSlice, Lsb0};
|
use bitvec::prelude::{BitSlice, Lsb0};
|
||||||
use either::{Either, Left, Right};
|
use either::{Either, Left, Right};
|
||||||
use ibig::{Stack, UBig};
|
use ibig::{Stack, UBig};
|
||||||
@ -1146,6 +1146,12 @@ 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 Slots for Noun {}
|
||||||
impl private::RawSlots for Noun {
|
impl private::RawSlots for Noun {
|
||||||
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
||||||
|
Loading…
Reference in New Issue
Block a user