mirror of
https://github.com/urbit/ares.git
synced 2024-11-23 09:06:23 +03:00
Merge branch 'mink-scry' into status
This commit is contained in:
commit
9b05f0747d
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ pub mod sort;
|
||||
pub mod text;
|
||||
pub mod tree;
|
||||
|
||||
use crate::interpreter::Context;
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::bits::*;
|
||||
use crate::jets::cold::Cold;
|
||||
use crate::jets::form::*;
|
||||
@ -25,7 +25,8 @@ use crate::jets::text::*;
|
||||
use crate::jets::tree::*;
|
||||
use crate::jets::warm::Warm;
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{self, Noun, Slots};
|
||||
use crate::newt::Newt;
|
||||
use crate::noun::{self, Noun, Slots, D};
|
||||
use ares_macros::tas;
|
||||
use std::cmp;
|
||||
|
||||
@ -41,14 +42,13 @@ pub type Jet = fn(&mut Context, Noun) -> Result;
|
||||
*/
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum JetErr {
|
||||
Punt, // Retry with the raw nock
|
||||
Deterministic, // The Nock would have crashed
|
||||
NonDeterministic, // Other error
|
||||
Punt, // Retry with the raw nock
|
||||
Fail(Error), // Error; do not retry
|
||||
}
|
||||
|
||||
impl From<noun::Error> for JetErr {
|
||||
fn from(_err: noun::Error) -> Self {
|
||||
Self::Deterministic
|
||||
Self::Fail(Error::Deterministic(D(0)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +56,15 @@ impl From<JetErr> for () {
|
||||
fn from(_: JetErr) -> Self {}
|
||||
}
|
||||
|
||||
impl From<JetErr> for Error {
|
||||
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> {
|
||||
match jet_name.as_direct().ok()?.data() {
|
||||
tas!(b"add") => Some(jet_add),
|
||||
@ -138,12 +147,13 @@ pub mod util {
|
||||
pub fn checked_add(a: usize, b: usize) -> result::Result<usize, JetErr> {
|
||||
a.checked_add(b)
|
||||
.filter(|x| x <= &MAX_BIT_LENGTH)
|
||||
.ok_or(JetErr::NonDeterministic)
|
||||
.ok_or(JetErr::Fail(Error::NonDeterministic(D(0))))
|
||||
}
|
||||
|
||||
/// Performs addition that returns None on Noun size overflow
|
||||
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(Error::NonDeterministic(D(0))))
|
||||
}
|
||||
|
||||
pub fn checked_left_shift(bloq: usize, a: usize) -> result::Result<usize, JetErr> {
|
||||
@ -151,7 +161,7 @@ pub mod util {
|
||||
|
||||
// Catch overflow
|
||||
if (res >> bloq) < a || res > MAX_BIT_LENGTH {
|
||||
Err(JetErr::NonDeterministic)
|
||||
Err(JetErr::Fail(Error::NonDeterministic(D(0))))
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
@ -168,14 +178,15 @@ pub mod util {
|
||||
}
|
||||
|
||||
pub fn slot(noun: Noun, axis: u64) -> Result {
|
||||
noun.slot(axis).map_err(|_e| JetErr::Deterministic)
|
||||
noun.slot(axis)
|
||||
.map_err(|_e| JetErr::Fail(Error::Deterministic(D(0))))
|
||||
}
|
||||
|
||||
/// Extract a bloq and check that it's computable by the current system
|
||||
pub fn bloq(a: Noun) -> result::Result<usize, JetErr> {
|
||||
let bloq = a.as_direct()?.data() as usize;
|
||||
if bloq >= 47 {
|
||||
Err(JetErr::NonDeterministic)
|
||||
Err(JetErr::Fail(Error::NonDeterministic(D(0))))
|
||||
} else {
|
||||
Ok(bloq)
|
||||
}
|
||||
@ -298,7 +309,7 @@ pub mod util {
|
||||
if list.as_bitslice().first_one().is_none() {
|
||||
break;
|
||||
} else {
|
||||
return Err(JetErr::Deterministic);
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
}
|
||||
let cell = list.as_cell()?;
|
||||
@ -330,8 +341,23 @@ pub mod util {
|
||||
use assert_no_alloc::assert_no_alloc;
|
||||
use ibig::UBig;
|
||||
|
||||
pub fn init_stack() -> NockStack {
|
||||
NockStack::new(8 << 10 << 10, 0)
|
||||
pub fn init_context() -> Context {
|
||||
let mut stack = NockStack::new(8 << 10 << 10, 0);
|
||||
let newt = Newt::new_mock();
|
||||
let cold = Cold::new(&mut stack);
|
||||
let warm = Warm::new();
|
||||
let hot = Hot::init(&mut stack);
|
||||
let cache = Hamt::<Noun>::new();
|
||||
|
||||
Context {
|
||||
stack,
|
||||
newt,
|
||||
cold,
|
||||
warm,
|
||||
hot,
|
||||
cache,
|
||||
scry_stack: D(0),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
@ -344,51 +370,25 @@ pub mod util {
|
||||
assert!(eq, "got: {}, need: {}", a, b);
|
||||
}
|
||||
|
||||
pub fn assert_jet(stack: &mut NockStack, jet: Jet, sam: Noun, res: Noun) {
|
||||
// XX: consider making a mock context singleton that tests can use
|
||||
let mut cache = Hamt::<Noun>::new();
|
||||
let mut cold = Cold::new(stack);
|
||||
let mut warm = Warm::new();
|
||||
let hot = Hot::init(stack);
|
||||
let mut context = Context {
|
||||
stack,
|
||||
newt: None,
|
||||
cache: &mut cache,
|
||||
cold: &mut cold,
|
||||
warm: &mut warm,
|
||||
hot: &hot,
|
||||
};
|
||||
let sam = T(context.stack, &[D(0), sam, D(0)]);
|
||||
let jet_res = assert_no_alloc(|| jet(&mut context, sam).unwrap());
|
||||
assert_noun_eq(stack, jet_res, res);
|
||||
pub fn assert_jet(context: &mut Context, jet: Jet, sam: Noun, res: Noun) {
|
||||
let sam = T(&mut context.stack, &[D(0), sam, D(0)]);
|
||||
let jet_res = assert_no_alloc(|| jet(context, sam).unwrap());
|
||||
assert_noun_eq(&mut context.stack, jet_res, res);
|
||||
}
|
||||
|
||||
pub fn assert_jet_ubig(stack: &mut NockStack, jet: Jet, sam: Noun, res: UBig) {
|
||||
let res = A(stack, &res);
|
||||
assert_jet(stack, jet, sam, res);
|
||||
pub fn assert_jet_ubig(context: &mut Context, jet: Jet, sam: Noun, res: UBig) {
|
||||
let res = A(&mut context.stack, &res);
|
||||
assert_jet(context, jet, sam, res);
|
||||
}
|
||||
|
||||
pub fn assert_nary_jet_ubig(stack: &mut NockStack, jet: Jet, sam: &[Noun], res: UBig) {
|
||||
let sam = T(stack, sam);
|
||||
assert_jet_ubig(stack, jet, sam, res);
|
||||
pub fn assert_nary_jet_ubig(context: &mut Context, jet: Jet, sam: &[Noun], res: UBig) {
|
||||
let sam = T(&mut context.stack, sam);
|
||||
assert_jet_ubig(context, jet, sam, res);
|
||||
}
|
||||
|
||||
pub fn assert_jet_err(stack: &mut NockStack, jet: Jet, sam: Noun, err: JetErr) {
|
||||
// XX: consider making a mock context singleton that tests can use
|
||||
let mut cache = Hamt::<Noun>::new();
|
||||
let mut cold = Cold::new(stack);
|
||||
let mut warm = Warm::new();
|
||||
let hot = Hot::init(stack);
|
||||
let mut context = Context {
|
||||
stack,
|
||||
newt: None,
|
||||
cache: &mut cache,
|
||||
cold: &mut cold,
|
||||
warm: &mut warm,
|
||||
hot: &hot,
|
||||
};
|
||||
let sam = T(context.stack, &[D(0), sam, D(0)]);
|
||||
let jet_res = jet(&mut context, sam);
|
||||
pub fn assert_jet_err(context: &mut Context, jet: Jet, sam: Noun, err: JetErr) {
|
||||
let sam = T(&mut context.stack, &[D(0), sam, D(0)]);
|
||||
let jet_res = jet(context, sam);
|
||||
assert!(
|
||||
jet_res.is_err(),
|
||||
"with sample: {}, expected err: {:?}, got: {:?}",
|
||||
@ -407,13 +407,14 @@ pub mod util {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::test::{init_stack, A};
|
||||
use super::test::{init_context, A};
|
||||
use super::*;
|
||||
use ibig::ubig;
|
||||
|
||||
#[test]
|
||||
fn test_met() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
let s = &mut c.stack;
|
||||
|
||||
let a = A(s, &ubig!(0xdeadbeef12345678fedcba9876543210))
|
||||
.as_atom()
|
||||
|
@ -1,11 +1,8 @@
|
||||
/** Bit arithmetic & logic jets
|
||||
*/
|
||||
use crate::interpreter::Context;
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::util::*;
|
||||
|
||||
use crate::jets::JetErr::*;
|
||||
use crate::jets::Result;
|
||||
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{DirectAtom, IndirectAtom, Noun, D};
|
||||
use std::cmp;
|
||||
|
||||
@ -17,7 +14,7 @@ crate::gdb!();
|
||||
|
||||
pub fn jet_bex(context: &mut Context, subject: Noun) -> Result {
|
||||
let arg = slot(subject, 6)?.as_direct()?.data() as usize;
|
||||
Ok(bex(context.stack, arg).as_noun())
|
||||
Ok(bex(&mut context.stack, arg).as_noun())
|
||||
}
|
||||
|
||||
pub fn jet_can(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -45,7 +42,7 @@ pub fn jet_can(context: &mut Context, subject: Noun) -> Result {
|
||||
} else {
|
||||
unsafe {
|
||||
let (mut new_indirect, new_slice) =
|
||||
IndirectAtom::new_raw_mut_bitslice(context.stack, bite_to_word(bloq, len)?);
|
||||
IndirectAtom::new_raw_mut_bitslice(&mut context.stack, bite_to_word(bloq, len)?);
|
||||
let mut pos = 0;
|
||||
let mut list = original_list;
|
||||
loop {
|
||||
@ -81,7 +78,7 @@ pub fn jet_cat(context: &mut Context, subject: Noun) -> Result {
|
||||
} else {
|
||||
unsafe {
|
||||
let (mut new_indirect, new_slice) =
|
||||
IndirectAtom::new_raw_mut_bitslice(context.stack, new_len);
|
||||
IndirectAtom::new_raw_mut_bitslice(&mut context.stack, new_len);
|
||||
chop(bloq, 0, len_a, 0, new_slice, a.as_bitslice())?;
|
||||
chop(bloq, 0, len_b, len_a, new_slice, b.as_bitslice())?;
|
||||
Ok(new_indirect.normalize_as_atom().as_noun())
|
||||
@ -102,7 +99,7 @@ pub fn jet_cut(context: &mut Context, subject: Noun) -> Result {
|
||||
|
||||
let new_indirect = unsafe {
|
||||
let (mut new_indirect, new_slice) =
|
||||
IndirectAtom::new_raw_mut_bitslice(context.stack, bite_to_word(bloq, run)?);
|
||||
IndirectAtom::new_raw_mut_bitslice(&mut context.stack, bite_to_word(bloq, run)?);
|
||||
chop(bloq, start, run, 0, new_slice, atom.as_bitslice())?;
|
||||
new_indirect.normalize_as_atom()
|
||||
};
|
||||
@ -121,7 +118,7 @@ pub fn jet_end(context: &mut Context, subject: Noun) -> Result {
|
||||
} else {
|
||||
unsafe {
|
||||
let (mut new_indirect, new_slice) =
|
||||
IndirectAtom::new_raw_mut_bitslice(context.stack, bite_to_word(bloq, step)?);
|
||||
IndirectAtom::new_raw_mut_bitslice(&mut context.stack, bite_to_word(bloq, step)?);
|
||||
chop(bloq, 0, step, 0, new_slice, a.as_bitslice())?;
|
||||
Ok(new_indirect.normalize_as_atom().as_noun())
|
||||
}
|
||||
@ -140,7 +137,7 @@ pub fn jet_lsh(context: &mut Context, subject: Noun) -> Result {
|
||||
|
||||
let new_size = bits_to_word(checked_add(a.bit_size(), checked_left_shift(bloq, step)?)?)?;
|
||||
unsafe {
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(context.stack, new_size);
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(&mut context.stack, new_size);
|
||||
chop(bloq, 0, len, step, dest, a.as_bitslice())?;
|
||||
Ok(atom.normalize_as_atom().as_noun())
|
||||
}
|
||||
@ -177,7 +174,7 @@ pub fn jet_rap(context: &mut Context, subject: Noun) -> Result {
|
||||
} else {
|
||||
unsafe {
|
||||
let (mut new_indirect, new_slice) =
|
||||
IndirectAtom::new_raw_mut_bitslice(context.stack, bite_to_word(bloq, len)?);
|
||||
IndirectAtom::new_raw_mut_bitslice(&mut context.stack, bite_to_word(bloq, len)?);
|
||||
let mut pos = 0;
|
||||
let mut list = original_list;
|
||||
|
||||
@ -223,7 +220,7 @@ pub fn jet_rep(context: &mut Context, subject: Noun) -> Result {
|
||||
} else {
|
||||
unsafe {
|
||||
let (mut new_indirect, new_slice) =
|
||||
IndirectAtom::new_raw_mut_bitslice(context.stack, bite_to_word(bloq, len)?);
|
||||
IndirectAtom::new_raw_mut_bitslice(&mut context.stack, bite_to_word(bloq, len)?);
|
||||
let mut pos = 0;
|
||||
let mut list = original_list;
|
||||
loop {
|
||||
@ -248,7 +245,7 @@ pub fn jet_rev(context: &mut Context, subject: Noun) -> Result {
|
||||
let boz = slot(arg, 2)?.as_atom()?.as_direct()?.data();
|
||||
|
||||
if boz >= 64 {
|
||||
return Err(NonDeterministic);
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
|
||||
let boz = boz as usize;
|
||||
@ -263,7 +260,9 @@ pub fn jet_rev(context: &mut Context, subject: Noun) -> Result {
|
||||
let mut output = if dat.is_direct() && bits < 64 {
|
||||
unsafe { DirectAtom::new_unchecked(0).as_atom() }
|
||||
} else {
|
||||
unsafe { IndirectAtom::new_raw(context.stack, ((bits + 7) / 8) as usize, &0).as_atom() }
|
||||
unsafe {
|
||||
IndirectAtom::new_raw(&mut context.stack, ((bits + 7) / 8) as usize, &0).as_atom()
|
||||
}
|
||||
};
|
||||
|
||||
let src = dat.as_bitslice();
|
||||
@ -283,7 +282,7 @@ pub fn jet_rip(context: &mut Context, subject: Noun) -> Result {
|
||||
let arg = slot(subject, 6)?;
|
||||
let (bloq, step) = bite(slot(arg, 2)?)?;
|
||||
let atom = slot(arg, 3)?.as_atom()?;
|
||||
rip(context.stack, bloq, step, atom)
|
||||
rip(&mut context.stack, bloq, step, atom)
|
||||
}
|
||||
|
||||
pub fn jet_rsh(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -298,7 +297,7 @@ pub fn jet_rsh(context: &mut Context, subject: Noun) -> Result {
|
||||
|
||||
let new_size = bits_to_word(checked_sub(a.bit_size(), checked_left_shift(bloq, step)?)?)?;
|
||||
unsafe {
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(context.stack, new_size);
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(&mut context.stack, new_size);
|
||||
chop(bloq, step, len - step, 0, dest, a.as_bitslice())?;
|
||||
Ok(atom.normalize_as_atom().as_noun())
|
||||
}
|
||||
@ -313,7 +312,7 @@ pub fn jet_con(context: &mut Context, subject: Noun) -> Result {
|
||||
let a = slot(arg, 2)?.as_atom()?;
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
Ok(con(context.stack, a, b).as_noun())
|
||||
Ok(con(&mut context.stack, a, b).as_noun())
|
||||
}
|
||||
|
||||
pub fn jet_dis(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -324,7 +323,7 @@ pub fn jet_dis(context: &mut Context, subject: Noun) -> Result {
|
||||
let new_size = cmp::max(a.size(), b.size());
|
||||
|
||||
unsafe {
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(context.stack, new_size);
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(&mut context.stack, new_size);
|
||||
let a_bit = a.as_bitslice();
|
||||
dest[..a_bit.len()].copy_from_bitslice(a_bit);
|
||||
*dest &= b.as_bitslice();
|
||||
@ -340,7 +339,7 @@ pub fn jet_mix(context: &mut Context, subject: Noun) -> Result {
|
||||
let new_size = cmp::max(a.size(), b.size());
|
||||
|
||||
unsafe {
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(context.stack, new_size);
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(&mut context.stack, new_size);
|
||||
let a_bit = a.as_bitslice();
|
||||
dest[..a_bit.len()].copy_from_bitslice(a_bit);
|
||||
*dest ^= b.as_bitslice();
|
||||
@ -354,9 +353,7 @@ pub fn jet_xeb(_context: &mut Context, subject: Noun) -> Result {
|
||||
|
||||
let syz = met(0, a) as u64;
|
||||
|
||||
unsafe {
|
||||
Ok(DirectAtom::new_unchecked(syz).as_atom().as_noun())
|
||||
}
|
||||
unsafe { Ok(DirectAtom::new_unchecked(syz).as_atom().as_noun()) }
|
||||
}
|
||||
|
||||
pub fn jet_flop(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -367,7 +364,7 @@ pub fn jet_flop(context: &mut Context, subject: Noun) -> Result {
|
||||
return Ok(D(0));
|
||||
}
|
||||
|
||||
flop(context.stack, src)
|
||||
flop(&mut context.stack, src)
|
||||
}
|
||||
|
||||
// return u3kc_rep(u3k(a), 1, u3kb_flop(u3qc_rip(a, 1, b)));
|
||||
@ -392,7 +389,7 @@ pub fn jet_flop(context: &mut Context, subject: Noun) -> Result {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_ubig, init_stack, A};
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_ubig, init_context, A};
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{Noun, D, T};
|
||||
use ibig::ubig;
|
||||
@ -427,12 +424,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_bex() {
|
||||
let s = &mut init_stack();
|
||||
assert_jet(s, jet_bex, D(0), D(1));
|
||||
assert_jet(s, jet_bex, D(5), D(32));
|
||||
assert_jet(s, jet_bex, D(62), D(0x4000000000000000));
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet(c, jet_bex, D(0), D(1));
|
||||
assert_jet(c, jet_bex, D(5), D(32));
|
||||
assert_jet(c, jet_bex, D(62), D(0x4000000000000000));
|
||||
assert_jet_ubig(
|
||||
s,
|
||||
c,
|
||||
jet_bex,
|
||||
D(256),
|
||||
ubig!(_0x10000000000000000000000000000000000000000000000000000000000000000),
|
||||
@ -441,218 +439,243 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_can() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, _a24, _a63, _a96, a128) = atoms(s);
|
||||
let c = &mut init_context();
|
||||
|
||||
let (a0, _a24, _a63, _a96, a128) = atoms(&mut c.stack);
|
||||
let bloq0 = D(0);
|
||||
let bloq3 = D(3);
|
||||
let bloq4 = D(4);
|
||||
let sam = T(s, &[bloq0, D(0)]);
|
||||
assert_jet(s, jet_can, sam, D(0));
|
||||
let sam = T(s, &[bloq3, D(0)]);
|
||||
assert_jet(s, jet_can, sam, D(0));
|
||||
let run1 = T(s, &[D(0), a0]);
|
||||
let run2 = T(s, &[D(1), a0]);
|
||||
let run3 = T(s, &[D(2), a0]);
|
||||
let sam = T(s, &[bloq0, run1, run2, run3, D(0)]);
|
||||
assert_jet(s, jet_can, sam, D(0));
|
||||
let sam = T(s, &[bloq3, run1, run2, run3, D(0)]);
|
||||
assert_jet(s, jet_can, sam, D(0));
|
||||
let run1 = T(s, &[D(1), a128]);
|
||||
let run2 = T(s, &[D(3), a0]);
|
||||
let sam = T(s, &[bloq3, run1, run2, D(0)]);
|
||||
assert_jet(s, jet_can, sam, D(0x10));
|
||||
let run1 = T(s, &[D(3), a0]);
|
||||
let run2 = T(s, &[D(1), a128]);
|
||||
let sam = T(s, &[bloq3, run1, run2, D(0)]);
|
||||
assert_jet(s, jet_can, sam, D(0x10000000));
|
||||
let run1 = T(s, &[D(8), D(0xfe)]);
|
||||
let run2 = T(s, &[D(4), D(0xa)]);
|
||||
let run3 = T(s, &[D(0), D(0xbbbb)]);
|
||||
let run4 = T(s, &[D(1), D(0)]);
|
||||
let run5 = T(s, &[D(1), D(0)]);
|
||||
let run6 = T(s, &[D(1), D(1)]);
|
||||
let run7 = T(s, &[D(1), D(1)]);
|
||||
let sam = T(s, &[bloq0, run1, run2, run3, run4, run5, run6, run7, D(0)]);
|
||||
assert_jet(s, jet_can, sam, D(0xcafe));
|
||||
let run1 = T(s, &[D(1), D(0xfe)]);
|
||||
let run2 = T(s, &[D(1), D(0xca)]);
|
||||
let sam = T(s, &[bloq4, run1, run2, D(0)]);
|
||||
assert_jet(s, jet_can, sam, D(0xca00fe));
|
||||
let sam = T(&mut c.stack, &[bloq0, D(0)]);
|
||||
assert_jet(c, jet_can, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[bloq3, D(0)]);
|
||||
assert_jet(c, jet_can, sam, D(0));
|
||||
let run1 = T(&mut c.stack, &[D(0), a0]);
|
||||
let run2 = T(&mut c.stack, &[D(1), a0]);
|
||||
let run3 = T(&mut c.stack, &[D(2), a0]);
|
||||
let sam = T(&mut c.stack, &[bloq0, run1, run2, run3, D(0)]);
|
||||
assert_jet(c, jet_can, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[bloq3, run1, run2, run3, D(0)]);
|
||||
assert_jet(c, jet_can, sam, D(0));
|
||||
let run1 = T(&mut c.stack, &[D(1), a128]);
|
||||
let run2 = T(&mut c.stack, &[D(3), a0]);
|
||||
let sam = T(&mut c.stack, &[bloq3, run1, run2, D(0)]);
|
||||
assert_jet(c, jet_can, sam, D(0x10));
|
||||
let run1 = T(&mut c.stack, &[D(3), a0]);
|
||||
let run2 = T(&mut c.stack, &[D(1), a128]);
|
||||
let sam = T(&mut c.stack, &[bloq3, run1, run2, D(0)]);
|
||||
assert_jet(c, jet_can, sam, D(0x10000000));
|
||||
let run1 = T(&mut c.stack, &[D(8), D(0xfe)]);
|
||||
let run2 = T(&mut c.stack, &[D(4), D(0xa)]);
|
||||
let run3 = T(&mut c.stack, &[D(0), D(0xbbbb)]);
|
||||
let run4 = T(&mut c.stack, &[D(1), D(0)]);
|
||||
let run5 = T(&mut c.stack, &[D(1), D(0)]);
|
||||
let run6 = T(&mut c.stack, &[D(1), D(1)]);
|
||||
let run7 = T(&mut c.stack, &[D(1), D(1)]);
|
||||
let sam = T(
|
||||
&mut c.stack,
|
||||
&[bloq0, run1, run2, run3, run4, run5, run6, run7, D(0)],
|
||||
);
|
||||
assert_jet(c, jet_can, sam, D(0xcafe));
|
||||
let run1 = T(&mut c.stack, &[D(1), D(0xfe)]);
|
||||
let run2 = T(&mut c.stack, &[D(1), D(0xca)]);
|
||||
let sam = T(&mut c.stack, &[bloq4, run1, run2, D(0)]);
|
||||
assert_jet(c, jet_can, sam, D(0xca00fe));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cat() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, _a63, _a96, a128) = atoms(s);
|
||||
let c = &mut init_context();
|
||||
|
||||
let (a0, a24, _a63, _a96, a128) = atoms(&mut c.stack);
|
||||
let bloq0 = D(0);
|
||||
let bloq3 = D(3);
|
||||
let bloq4 = D(4);
|
||||
let sam = T(s, &[bloq0, a0, a0]);
|
||||
assert_jet(s, jet_cat, sam, D(0));
|
||||
let sam = T(s, &[bloq3, a0, a0]);
|
||||
assert_jet(s, jet_cat, sam, D(0));
|
||||
let sam = T(s, &[bloq0, a24, a128]);
|
||||
let res = A(s, &ubig!(_0xdeadbeef12345678fedcba9876543210876543));
|
||||
assert_jet(s, jet_cat, sam, res);
|
||||
let sam = T(s, &[bloq3, a24, a128]);
|
||||
let res = A(s, &ubig!(_0xdeadbeef12345678fedcba9876543210876543));
|
||||
assert_jet(s, jet_cat, sam, res);
|
||||
let sam = T(s, &[bloq4, a24, a128]);
|
||||
let res = A(s, &ubig!(_0xdeadbeef12345678fedcba987654321000876543));
|
||||
assert_jet(s, jet_cat, sam, res);
|
||||
let sam = T(&mut c.stack, &[bloq0, a0, a0]);
|
||||
assert_jet(c, jet_cat, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[bloq3, a0, a0]);
|
||||
assert_jet(c, jet_cat, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[bloq0, a24, a128]);
|
||||
let res = A(
|
||||
&mut c.stack,
|
||||
&ubig!(_0xdeadbeef12345678fedcba9876543210876543),
|
||||
);
|
||||
assert_jet(c, jet_cat, sam, res);
|
||||
let sam = T(&mut c.stack, &[bloq3, a24, a128]);
|
||||
let res = A(
|
||||
&mut c.stack,
|
||||
&ubig!(_0xdeadbeef12345678fedcba9876543210876543),
|
||||
);
|
||||
assert_jet(c, jet_cat, sam, res);
|
||||
let sam = T(&mut c.stack, &[bloq4, a24, a128]);
|
||||
let res = A(
|
||||
&mut c.stack,
|
||||
&ubig!(_0xdeadbeef12345678fedcba987654321000876543),
|
||||
);
|
||||
assert_jet(c, jet_cat, sam, res);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cut() {
|
||||
let s = &mut init_stack();
|
||||
let (_a0, a24, _a63, a96, a128) = atoms(s);
|
||||
let run = T(s, &[D(0), D(0)]);
|
||||
let sam = T(s, &[D(0), run, a24]);
|
||||
assert_jet(s, jet_cut, sam, D(0));
|
||||
let run = T(s, &[D(0), D(5)]);
|
||||
let sam = T(s, &[D(0), run, a24]);
|
||||
assert_jet(s, jet_cut, sam, D(0x3));
|
||||
let run = T(s, &[D(4), D(6)]);
|
||||
let sam = T(s, &[D(3), run, a96]);
|
||||
assert_jet(s, jet_cut, sam, D(0xb00c15deadbe));
|
||||
let run = T(s, &[D(4), D(1)]);
|
||||
let sam = T(s, &[D(4), run, a24]);
|
||||
assert_jet(s, jet_cut, sam, D(0));
|
||||
let run = T(s, &[D(2), D(10)]);
|
||||
let sam = T(s, &[D(4), run, a128]);
|
||||
let res = A(s, &ubig!(0xdeadbeef12345678fedcba98));
|
||||
assert_jet(s, jet_cut, sam, res);
|
||||
let c = &mut init_context();
|
||||
|
||||
let (_a0, a24, _a63, a96, a128) = atoms(&mut c.stack);
|
||||
let run = T(&mut c.stack, &[D(0), D(0)]);
|
||||
let sam = T(&mut c.stack, &[D(0), run, a24]);
|
||||
assert_jet(c, jet_cut, sam, D(0));
|
||||
let run = T(&mut c.stack, &[D(0), D(5)]);
|
||||
let sam = T(&mut c.stack, &[D(0), run, a24]);
|
||||
assert_jet(c, jet_cut, sam, D(0x3));
|
||||
let run = T(&mut c.stack, &[D(4), D(6)]);
|
||||
let sam = T(&mut c.stack, &[D(3), run, a96]);
|
||||
assert_jet(c, jet_cut, sam, D(0xb00c15deadbe));
|
||||
let run = T(&mut c.stack, &[D(4), D(1)]);
|
||||
let sam = T(&mut c.stack, &[D(4), run, a24]);
|
||||
assert_jet(c, jet_cut, sam, D(0));
|
||||
let run = T(&mut c.stack, &[D(2), D(10)]);
|
||||
let sam = T(&mut c.stack, &[D(4), run, a128]);
|
||||
let res = A(&mut c.stack, &ubig!(0xdeadbeef12345678fedcba98));
|
||||
assert_jet(c, jet_cut, sam, res);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_end() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, _a63, a96, a128) = atoms(s);
|
||||
let sam = T(s, &[a0, a24]);
|
||||
assert_jet(s, jet_end, sam, D(0x1));
|
||||
let sam = T(s, &[D(3), a24]);
|
||||
assert_jet(s, jet_end, sam, D(0x43));
|
||||
let sam = T(s, &[D(7), a24]);
|
||||
assert_jet(s, jet_end, sam, a24);
|
||||
let sam = T(s, &[D(6), a128]);
|
||||
let res = A(s, &ubig!(0xfedcba9876543210));
|
||||
assert_jet(s, jet_end, sam, res);
|
||||
let c = &mut init_context();
|
||||
|
||||
let bit = T(s, &[D(0), D(5)]);
|
||||
let sam = T(s, &[bit, a24]);
|
||||
assert_jet(s, jet_end, sam, D(0x3));
|
||||
let bit = T(s, &[D(4), D(6)]);
|
||||
let sam = T(s, &[bit, a96]);
|
||||
assert_jet(s, jet_end, sam, a96);
|
||||
let (a0, a24, _a63, a96, a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[a0, a24]);
|
||||
assert_jet(c, jet_end, sam, D(0x1));
|
||||
let sam = T(&mut c.stack, &[D(3), a24]);
|
||||
assert_jet(c, jet_end, sam, D(0x43));
|
||||
let sam = T(&mut c.stack, &[D(7), a24]);
|
||||
assert_jet(c, jet_end, sam, a24);
|
||||
let sam = T(&mut c.stack, &[D(6), a128]);
|
||||
let res = A(&mut c.stack, &ubig!(0xfedcba9876543210));
|
||||
assert_jet(c, jet_end, sam, res);
|
||||
|
||||
let bit = T(&mut c.stack, &[D(0), D(5)]);
|
||||
let sam = T(&mut c.stack, &[bit, a24]);
|
||||
assert_jet(c, jet_end, sam, D(0x3));
|
||||
let bit = T(&mut c.stack, &[D(4), D(6)]);
|
||||
let sam = T(&mut c.stack, &[bit, a96]);
|
||||
assert_jet(c, jet_end, sam, a96);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lsh() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, _a63, a96, a128) = atoms(s);
|
||||
let sam = T(s, &[a0, a24]);
|
||||
assert_jet(s, jet_lsh, sam, D(0x10eca86));
|
||||
let sam = T(s, &[D(3), a24]);
|
||||
assert_jet(s, jet_lsh, sam, D(0x87654300));
|
||||
let sam = T(s, &[D(7), a24]);
|
||||
let res = A(s, &ubig!(_0x87654300000000000000000000000000000000));
|
||||
assert_jet(s, jet_lsh, sam, res);
|
||||
let sam = T(s, &[D(6), a128]);
|
||||
let c = &mut init_context();
|
||||
|
||||
let (a0, a24, _a63, a96, a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[a0, a24]);
|
||||
assert_jet(c, jet_lsh, sam, D(0x10eca86));
|
||||
let sam = T(&mut c.stack, &[D(3), a24]);
|
||||
assert_jet(c, jet_lsh, sam, D(0x87654300));
|
||||
let sam = T(&mut c.stack, &[D(7), a24]);
|
||||
let res = A(
|
||||
s,
|
||||
&mut c.stack,
|
||||
&ubig!(_0x87654300000000000000000000000000000000),
|
||||
);
|
||||
assert_jet(c, jet_lsh, sam, res);
|
||||
let sam = T(&mut c.stack, &[D(6), a128]);
|
||||
let res = A(
|
||||
&mut c.stack,
|
||||
&ubig!(_0xdeadbeef12345678fedcba98765432100000000000000000),
|
||||
);
|
||||
assert_jet(s, jet_lsh, sam, res);
|
||||
assert_jet(c, jet_lsh, sam, res);
|
||||
|
||||
let bit = T(s, &[D(0), D(5)]);
|
||||
let sam = T(s, &[bit, a24]);
|
||||
assert_jet(s, jet_lsh, sam, D(0x10eca860));
|
||||
let bit = T(s, &[D(4), D(6)]);
|
||||
let sam = T(s, &[bit, a96]);
|
||||
let bit = T(&mut c.stack, &[D(0), D(5)]);
|
||||
let sam = T(&mut c.stack, &[bit, a24]);
|
||||
assert_jet(c, jet_lsh, sam, D(0x10eca860));
|
||||
let bit = T(&mut c.stack, &[D(4), D(6)]);
|
||||
let sam = T(&mut c.stack, &[bit, a96]);
|
||||
let res = A(
|
||||
s,
|
||||
&mut c.stack,
|
||||
&ubig!(_0xfaceb00c15deadbeef123456000000000000000000000000),
|
||||
);
|
||||
assert_jet(s, jet_lsh, sam, res);
|
||||
assert_jet(c, jet_lsh, sam, res);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_met() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, _a63, _a96, a128) = atoms(s);
|
||||
let sam = T(s, &[a0, a0]);
|
||||
assert_jet(s, jet_met, sam, D(0));
|
||||
let sam = T(s, &[a0, a24]);
|
||||
assert_jet(s, jet_met, sam, D(24));
|
||||
let sam = T(s, &[D(3), a24]);
|
||||
assert_jet(s, jet_met, sam, D(3));
|
||||
let sam = T(s, &[D(1), a128]);
|
||||
assert_jet(s, jet_met, sam, D(64));
|
||||
let c = &mut init_context();
|
||||
|
||||
let (a0, a24, _a63, _a96, a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[a0, a0]);
|
||||
assert_jet(c, jet_met, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[a0, a24]);
|
||||
assert_jet(c, jet_met, sam, D(24));
|
||||
let sam = T(&mut c.stack, &[D(3), a24]);
|
||||
assert_jet(c, jet_met, sam, D(3));
|
||||
let sam = T(&mut c.stack, &[D(1), a128]);
|
||||
assert_jet(c, jet_met, sam, D(64));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rap() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
|
||||
let bloq0 = D(0);
|
||||
let bloq2 = D(2);
|
||||
let bloq3 = D(3);
|
||||
let empty_list = D(0);
|
||||
let zero_list = T(s, &[D(0), D(0), D(0)]);
|
||||
let test_list = T(s, &[D(0xe), D(0xf), D(0xa), D(0xc), D(0)]);
|
||||
let wide_list = T(s, &[D(0xafe), D(0xc), D(0)]);
|
||||
let sam = T(s, &[bloq0, empty_list]);
|
||||
assert_jet(s, jet_rap, sam, D(0));
|
||||
let sam = T(s, &[bloq0, zero_list]);
|
||||
assert_jet(s, jet_rap, sam, D(0));
|
||||
let sam = T(s, &[bloq3, zero_list]);
|
||||
assert_jet(s, jet_rap, sam, D(0));
|
||||
let sam = T(s, &[bloq0, test_list]);
|
||||
assert_jet(s, jet_rap, sam, D(0xcafe));
|
||||
let sam = T(s, &[bloq2, test_list]);
|
||||
assert_jet(s, jet_rap, sam, D(0xcafe));
|
||||
let sam = T(s, &[bloq2, wide_list]);
|
||||
assert_jet(s, jet_rap, sam, D(0xcafe));
|
||||
let sam = T(s, &[bloq3, test_list]);
|
||||
let res = A(s, &ubig!(0xc0a0f0e));
|
||||
assert_jet(s, jet_rap, sam, res);
|
||||
let sam = T(s, &[bloq3, wide_list]);
|
||||
assert_jet(s, jet_rap, sam, D(0xc0afe));
|
||||
let zero_list = T(&mut c.stack, &[D(0), D(0), D(0)]);
|
||||
let test_list = T(&mut c.stack, &[D(0xe), D(0xf), D(0xa), D(0xc), D(0)]);
|
||||
let wide_list = T(&mut c.stack, &[D(0xafe), D(0xc), D(0)]);
|
||||
let sam = T(&mut c.stack, &[bloq0, empty_list]);
|
||||
assert_jet(c, jet_rap, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[bloq0, zero_list]);
|
||||
assert_jet(c, jet_rap, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[bloq3, zero_list]);
|
||||
assert_jet(c, jet_rap, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[bloq0, test_list]);
|
||||
assert_jet(c, jet_rap, sam, D(0xcafe));
|
||||
let sam = T(&mut c.stack, &[bloq2, test_list]);
|
||||
assert_jet(c, jet_rap, sam, D(0xcafe));
|
||||
let sam = T(&mut c.stack, &[bloq2, wide_list]);
|
||||
assert_jet(c, jet_rap, sam, D(0xcafe));
|
||||
let sam = T(&mut c.stack, &[bloq3, test_list]);
|
||||
let res = A(&mut c.stack, &ubig!(0xc0a0f0e));
|
||||
assert_jet(c, jet_rap, sam, res);
|
||||
let sam = T(&mut c.stack, &[bloq3, wide_list]);
|
||||
assert_jet(c, jet_rap, sam, D(0xc0afe));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rep() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, a63, a96, a128) = atoms(s);
|
||||
let sam = T(s, &[D(0), D(0)]);
|
||||
assert_jet(s, jet_rep, sam, D(0));
|
||||
let bit = T(s, &[D(3), D(2)]);
|
||||
let sam = T(s, &[bit, a0, a24, a63, a96, a128, D(0)]);
|
||||
let res = A(s, &ubig!(0x32103456ffff65430000));
|
||||
assert_jet(s, jet_rep, sam, res);
|
||||
let c = &mut init_context();
|
||||
|
||||
let (a0, a24, a63, a96, a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[D(0), D(0)]);
|
||||
assert_jet(c, jet_rep, sam, D(0));
|
||||
let bit = T(&mut c.stack, &[D(3), D(2)]);
|
||||
let sam = T(&mut c.stack, &[bit, a0, a24, a63, a96, a128, D(0)]);
|
||||
let res = A(&mut c.stack, &ubig!(0x32103456ffff65430000));
|
||||
assert_jet(c, jet_rep, sam, res);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rev() {
|
||||
let s = &mut init_stack();
|
||||
let (_a0, a24, _a63, _a96, _a128) = atoms(s);
|
||||
let sam = T(s, &[D(0), D(60), a24]);
|
||||
assert_jet(s, jet_rev, sam, D(0xc2a6e1000000000));
|
||||
let c = &mut init_context();
|
||||
|
||||
let (_a0, a24, _a63, _a96, _a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[D(0), D(60), a24]);
|
||||
assert_jet(c, jet_rev, sam, D(0xc2a6e1000000000));
|
||||
let test = 0x1234567890123u64;
|
||||
let sam = T(s, &[D(3), D(7), D(test)]);
|
||||
assert_jet(s, jet_rev, sam, D(test.swap_bytes() >> 8));
|
||||
let sam = T(&mut c.stack, &[D(3), D(7), D(test)]);
|
||||
assert_jet(c, jet_rev, sam, D(test.swap_bytes() >> 8));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rip() {
|
||||
let s = &mut init_stack();
|
||||
let (_a0, _a24, _a63, _a96, a128) = atoms(s);
|
||||
let sam = T(s, &[D(0), D(0)]);
|
||||
assert_jet(s, jet_rip, sam, D(0));
|
||||
let bit = T(s, &[D(1), D(2)]);
|
||||
let sam = T(s, &[bit, a128]);
|
||||
let c = &mut init_context();
|
||||
|
||||
let (_a0, _a24, _a63, _a96, a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[D(0), D(0)]);
|
||||
assert_jet(c, jet_rip, sam, D(0));
|
||||
let bit = T(&mut c.stack, &[D(1), D(2)]);
|
||||
let sam = T(&mut c.stack, &[bit, a128]);
|
||||
#[rustfmt::skip]
|
||||
let res = T(
|
||||
s,
|
||||
&mut c.stack,
|
||||
&[
|
||||
D(0x0), D(0x1), D(0x2), D(0x3), D(0x4), D(0x5), D(0x6), D(0x7),
|
||||
D(0x8), D(0x9), D(0xa), D(0xb), D(0xc), D(0xd), D(0xe), D(0xf),
|
||||
@ -661,33 +684,33 @@ mod tests {
|
||||
D(0x0),
|
||||
],
|
||||
);
|
||||
|
||||
assert_jet(s, jet_rip, sam, res);
|
||||
assert_jet(c, jet_rip, sam, res);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rsh() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, _a63, a96, a128) = atoms(s);
|
||||
let sam = T(s, &[a0, a24]);
|
||||
assert_jet(s, jet_rsh, sam, D(0x43b2a1));
|
||||
let sam = T(s, &[D(3), a24]);
|
||||
assert_jet(s, jet_rsh, sam, D(0x8765));
|
||||
let sam = T(s, &[D(7), a24]);
|
||||
assert_jet(s, jet_rsh, sam, D(0));
|
||||
let sam = T(s, &[D(2), a128]);
|
||||
let res = A(s, &ubig!(0xdeadbeef12345678fedcba987654321));
|
||||
assert_jet(s, jet_rsh, sam, res);
|
||||
let sam = T(s, &[D(6), a128]);
|
||||
let res = A(s, &ubig!(0xdeadbeef12345678));
|
||||
assert_jet(s, jet_rsh, sam, res);
|
||||
let c = &mut init_context();
|
||||
|
||||
let bit = T(s, &[D(0), D(5)]);
|
||||
let sam = T(s, &[bit, a24]);
|
||||
assert_jet(s, jet_rsh, sam, D(0x43b2a));
|
||||
let bit = T(s, &[D(4), D(6)]);
|
||||
let sam = T(s, &[bit, a96]);
|
||||
assert_jet(s, jet_rsh, sam, D(0));
|
||||
let (a0, a24, _a63, a96, a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[a0, a24]);
|
||||
assert_jet(c, jet_rsh, sam, D(0x43b2a1));
|
||||
let sam = T(&mut c.stack, &[D(3), a24]);
|
||||
assert_jet(c, jet_rsh, sam, D(0x8765));
|
||||
let sam = T(&mut c.stack, &[D(7), a24]);
|
||||
assert_jet(c, jet_rsh, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[D(2), a128]);
|
||||
let res = A(&mut c.stack, &ubig!(0xdeadbeef12345678fedcba987654321));
|
||||
assert_jet(c, jet_rsh, sam, res);
|
||||
let sam = T(&mut c.stack, &[D(6), a128]);
|
||||
let res = A(&mut c.stack, &ubig!(0xdeadbeef12345678));
|
||||
assert_jet(c, jet_rsh, sam, res);
|
||||
|
||||
let bit = T(&mut c.stack, &[D(0), D(5)]);
|
||||
let sam = T(&mut c.stack, &[bit, a24]);
|
||||
assert_jet(c, jet_rsh, sam, D(0x43b2a));
|
||||
let bit = T(&mut c.stack, &[D(4), D(6)]);
|
||||
let sam = T(&mut c.stack, &[bit, a96]);
|
||||
assert_jet(c, jet_rsh, sam, D(0));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -696,75 +719,79 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_con() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, a63, a96, a128) = atoms(s);
|
||||
let sam = T(s, &[a0, a0]);
|
||||
assert_jet(s, jet_con, sam, D(0));
|
||||
let sam = T(s, &[a24, a96]);
|
||||
let res = A(s, &ubig!(0xfaceb00c15deadbeef977557));
|
||||
assert_jet(s, jet_con, sam, res);
|
||||
let sam = T(s, &[a96, a128]);
|
||||
let res = A(s, &ubig!(0xdeadbeeffafef67cffdebfbeff563656));
|
||||
assert_jet(s, jet_con, sam, res);
|
||||
let sam = T(s, &[a24, a63]);
|
||||
assert_jet(s, jet_con, sam, a63);
|
||||
let sam = T(s, &[a0, a128]);
|
||||
assert_jet(s, jet_con, sam, a128);
|
||||
let sam = T(s, &[a128, a0]);
|
||||
assert_jet(s, jet_con, sam, a128);
|
||||
let c = &mut init_context();
|
||||
|
||||
let (a0, a24, a63, a96, a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[a0, a0]);
|
||||
assert_jet(c, jet_con, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[a24, a96]);
|
||||
let res = A(&mut c.stack, &ubig!(0xfaceb00c15deadbeef977557));
|
||||
assert_jet(c, jet_con, sam, res);
|
||||
let sam = T(&mut c.stack, &[a96, a128]);
|
||||
let res = A(&mut c.stack, &ubig!(0xdeadbeeffafef67cffdebfbeff563656));
|
||||
assert_jet(c, jet_con, sam, res);
|
||||
let sam = T(&mut c.stack, &[a24, a63]);
|
||||
assert_jet(c, jet_con, sam, a63);
|
||||
let sam = T(&mut c.stack, &[a0, a128]);
|
||||
assert_jet(c, jet_con, sam, a128);
|
||||
let sam = T(&mut c.stack, &[a128, a0]);
|
||||
assert_jet(c, jet_con, sam, a128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dis() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, a63, a96, a128) = atoms(s);
|
||||
let sam = T(s, &[a0, a0]);
|
||||
assert_jet(s, jet_dis, sam, D(0));
|
||||
let sam = T(s, &[a24, a96]);
|
||||
assert_jet(s, jet_dis, sam, D(0x22442));
|
||||
let sam = T(s, &[a96, a128]);
|
||||
let res = A(s, &ubig!(0x1204100814dca89866103010));
|
||||
assert_jet(s, jet_dis, sam, res);
|
||||
let sam = T(s, &[a24, a63]);
|
||||
assert_jet(s, jet_dis, sam, a24);
|
||||
let sam = T(s, &[a0, a128]);
|
||||
assert_jet(s, jet_dis, sam, a0);
|
||||
let sam = T(s, &[a128, a0]);
|
||||
assert_jet(s, jet_dis, sam, a0);
|
||||
let c = &mut init_context();
|
||||
|
||||
let (a0, a24, a63, a96, a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[a0, a0]);
|
||||
assert_jet(c, jet_dis, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[a24, a96]);
|
||||
assert_jet(c, jet_dis, sam, D(0x22442));
|
||||
let sam = T(&mut c.stack, &[a96, a128]);
|
||||
let res = A(&mut c.stack, &ubig!(0x1204100814dca89866103010));
|
||||
assert_jet(c, jet_dis, sam, res);
|
||||
let sam = T(&mut c.stack, &[a24, a63]);
|
||||
assert_jet(c, jet_dis, sam, a24);
|
||||
let sam = T(&mut c.stack, &[a0, a128]);
|
||||
assert_jet(c, jet_dis, sam, a0);
|
||||
let sam = T(&mut c.stack, &[a128, a0]);
|
||||
assert_jet(c, jet_dis, sam, a0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mix() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, a63, a96, a128) = atoms(s);
|
||||
let sam = T(s, &[a0, a0]);
|
||||
assert_jet(s, jet_mix, sam, D(0));
|
||||
let sam = T(s, &[a24, a96]);
|
||||
let res = A(s, &ubig!(0xfaceb00c15deadbeef955115));
|
||||
assert_jet(s, jet_mix, sam, res);
|
||||
let sam = T(s, &[a96, a128]);
|
||||
let res = A(s, &ubig!(0xdeadbeefe8fae674eb02172699460646));
|
||||
assert_jet(s, jet_mix, sam, res);
|
||||
let sam = T(s, &[a24, a63]);
|
||||
let res = A(s, &ubig!(0x7fffffffff789abc));
|
||||
assert_jet(s, jet_mix, sam, res);
|
||||
let sam = T(s, &[a0, a128]);
|
||||
assert_jet(s, jet_mix, sam, a128);
|
||||
let sam = T(s, &[a128, a0]);
|
||||
assert_jet(s, jet_mix, sam, a128);
|
||||
let c = &mut init_context();
|
||||
|
||||
let (a0, a24, a63, a96, a128) = atoms(&mut c.stack);
|
||||
let sam = T(&mut c.stack, &[a0, a0]);
|
||||
assert_jet(c, jet_mix, sam, D(0));
|
||||
let sam = T(&mut c.stack, &[a24, a96]);
|
||||
let res = A(&mut c.stack, &ubig!(0xfaceb00c15deadbeef955115));
|
||||
assert_jet(c, jet_mix, sam, res);
|
||||
let sam = T(&mut c.stack, &[a96, a128]);
|
||||
let res = A(&mut c.stack, &ubig!(0xdeadbeefe8fae674eb02172699460646));
|
||||
assert_jet(c, jet_mix, sam, res);
|
||||
let sam = T(&mut c.stack, &[a24, a63]);
|
||||
let res = A(&mut c.stack, &ubig!(0x7fffffffff789abc));
|
||||
assert_jet(c, jet_mix, sam, res);
|
||||
let sam = T(&mut c.stack, &[a0, a128]);
|
||||
assert_jet(c, jet_mix, sam, a128);
|
||||
let sam = T(&mut c.stack, &[a128, a0]);
|
||||
assert_jet(c, jet_mix, sam, a128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_xeb() {
|
||||
let s = &mut init_stack();
|
||||
assert_jet(s, jet_xeb, D(0), D(0));
|
||||
assert_jet(s, jet_xeb, D(1), D(1));
|
||||
assert_jet(s, jet_xeb, D(31), D(5));
|
||||
assert_jet(s, jet_xeb, D(32), D(6));
|
||||
assert_jet(s, jet_xeb, D(0xfff), D(12));
|
||||
assert_jet(s, jet_xeb, D(0xffff), D(16));
|
||||
assert_jet(s, jet_xeb, D(0x3fffffffffffffff), D(62));
|
||||
assert_jet(s, jet_xeb, D(0x4000000000000000), D(63));
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet(c, jet_xeb, D(0), D(0));
|
||||
assert_jet(c, jet_xeb, D(1), D(1));
|
||||
assert_jet(c, jet_xeb, D(31), D(5));
|
||||
assert_jet(c, jet_xeb, D(32), D(6));
|
||||
assert_jet(c, jet_xeb, D(0xfff), D(12));
|
||||
assert_jet(c, jet_xeb, D(0xffff), D(16));
|
||||
assert_jet(c, jet_xeb, D(0x3fffffffffffffff), D(62));
|
||||
assert_jet(c, jet_xeb, D(0x4000000000000000), D(63));
|
||||
}
|
||||
|
||||
/*#[test]
|
||||
@ -782,13 +809,15 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_flop() {
|
||||
let s = &mut init_stack();
|
||||
let sam = T(s, &[D(1), D(2), D(3), D(0)]);
|
||||
let res = T(s, &[D(3), D(2), D(1), D(0)]);
|
||||
assert_jet(s, jet_flop, sam, res);
|
||||
let c = &mut init_context();
|
||||
|
||||
let sam = T(&mut c.stack, &[D(1), D(2), D(3), D(0)]);
|
||||
let res = T(&mut c.stack, &[D(3), D(2), D(1), D(0)]);
|
||||
assert_jet(c, jet_flop, sam, res);
|
||||
|
||||
#[rustfmt::skip]
|
||||
let sam = T(
|
||||
s,
|
||||
&mut c.stack,
|
||||
&[
|
||||
D(0xd), D(0xe), D(0xa), D(0xd), D(0xb), D(0xe), D(0xe), D(0xf),
|
||||
D(0x1), D(0x2), D(0x3), D(0x4), D(0x5), D(0x6), D(0x7), D(0x8),
|
||||
@ -799,7 +828,7 @@ mod tests {
|
||||
);
|
||||
#[rustfmt::skip]
|
||||
let res = T(
|
||||
s,
|
||||
&mut c.stack,
|
||||
&[
|
||||
D(0x0), D(0x1), D(0x2), D(0x3), D(0x4), D(0x5), D(0x6), D(0x7),
|
||||
D(0x8), D(0x9), D(0xa), D(0xb), D(0xc), D(0xd), D(0xe), D(0xf),
|
||||
@ -808,7 +837,6 @@ mod tests {
|
||||
D(0x0),
|
||||
],
|
||||
);
|
||||
assert_jet(s, jet_flop, sam, res);
|
||||
assert_jet(c, jet_flop, sam, res);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ impl From<noun::Error> for Error {
|
||||
|
||||
pub type Result = std::result::Result<bool, Error>;
|
||||
|
||||
// Batteries is a core hierarchy (e.g. a path of parent batteries to a root)
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Batteries(*mut BatteriesMem);
|
||||
|
||||
@ -129,6 +130,8 @@ impl Batteries {
|
||||
}
|
||||
}
|
||||
|
||||
// BatteriesList is a linked list of core hierarchies with an iterator; used to
|
||||
// store all possible parent hierarchies for a core
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct BatteriesList(*mut BatteriesListMem);
|
||||
|
||||
@ -199,6 +202,8 @@ impl BatteriesList {
|
||||
}
|
||||
}
|
||||
|
||||
// NounList is a linked list of paths (path = list of nested core names) with an
|
||||
// iterator; used to store all possible registered paths for a core
|
||||
#[derive(Copy, Clone)]
|
||||
struct NounList(*mut NounListMem);
|
||||
|
||||
@ -265,12 +270,21 @@ impl Iterator for NounList {
|
||||
pub struct Cold(*mut ColdMem);
|
||||
|
||||
struct ColdMem {
|
||||
/// key: outermost battery
|
||||
/// key: outermost battery (e.g. furthest battery from root for a core)
|
||||
/// value: possible registered paths for core
|
||||
///
|
||||
/// Identical nock can exist in multiple places, so the outermost battery
|
||||
/// yield multiple paths. Instead of matching on the entire core in the Hamt
|
||||
/// (which would require iterating through every possible pait), we match
|
||||
/// the outermost battery to a path, then compare the core to the registered
|
||||
/// cores for that path.
|
||||
battery_to_paths: Hamt<NounList>,
|
||||
/// Roots
|
||||
/// key: root noun
|
||||
/// value: root path
|
||||
///
|
||||
/// Just like battery_to_paths, but for roots (which refer to themselves as
|
||||
/// their parent).
|
||||
root_to_paths: Hamt<NounList>,
|
||||
/// key: registered path to core
|
||||
/// value: linked list of a sequence of nested batteries
|
||||
|
@ -10,7 +10,7 @@ crate::gdb!();
|
||||
pub fn jet_scow(context: &mut Context, subject: Noun) -> Result {
|
||||
let aura = slot(subject, 12)?.as_direct()?;
|
||||
let atom = slot(subject, 13)?.as_atom()?;
|
||||
util::scow(context.stack, aura, atom)
|
||||
util::scow(&mut context.stack, aura, atom)
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
@ -79,7 +79,7 @@ pub mod util {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack, A};
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context, A};
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::{Noun, D, T};
|
||||
use ares_macros::tas;
|
||||
@ -93,28 +93,35 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_scow() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
|
||||
let aura = D(tas!(b"ud"));
|
||||
let sam = T(s, &[aura, D(0)]);
|
||||
let res = T(s, &[B(b'0'), D(0)]);
|
||||
assert_jet(s, jet_scow, sam, res);
|
||||
let sam = T(s, &[aura, D(100)]);
|
||||
let res = T(s, &[B(b'1'), B(b'0'), B(b'0'), D(0)]);
|
||||
assert_jet(s, jet_scow, sam, res);
|
||||
let big = A(s, &ubig!(100));
|
||||
let sam = T(s, &[aura, big]);
|
||||
let res = T(s, &[B(b'1'), B(b'0'), B(b'0'), D(0)]);
|
||||
assert_jet(s, jet_scow, sam, res);
|
||||
let sam = T(s, &[aura, D(1000)]);
|
||||
let res = T(s, &[B(b'1'), B(b'.'), B(b'0'), B(b'0'), B(b'0'), D(0)]);
|
||||
assert_jet(s, jet_scow, sam, res);
|
||||
let big = A(s, &ubig!(1000));
|
||||
let sam = T(s, &[aura, big]);
|
||||
let res = T(s, &[B(b'1'), B(b'.'), B(b'0'), B(b'0'), B(b'0'), D(0)]);
|
||||
assert_jet(s, jet_scow, sam, res);
|
||||
let sam = T(s, &[aura, D(9876543210)]);
|
||||
let sam = T(&mut c.stack, &[aura, D(0)]);
|
||||
let res = T(&mut c.stack, &[B(b'0'), D(0)]);
|
||||
assert_jet(c, jet_scow, sam, res);
|
||||
let sam = T(&mut c.stack, &[aura, D(100)]);
|
||||
let res = T(&mut c.stack, &[B(b'1'), B(b'0'), B(b'0'), D(0)]);
|
||||
assert_jet(c, jet_scow, sam, res);
|
||||
let big = A(&mut c.stack, &ubig!(100));
|
||||
let sam = T(&mut c.stack, &[aura, big]);
|
||||
let res = T(&mut c.stack, &[B(b'1'), B(b'0'), B(b'0'), D(0)]);
|
||||
assert_jet(c, jet_scow, sam, res);
|
||||
let sam = T(&mut c.stack, &[aura, D(1000)]);
|
||||
let res = T(
|
||||
s,
|
||||
&mut c.stack,
|
||||
&[B(b'1'), B(b'.'), B(b'0'), B(b'0'), B(b'0'), D(0)],
|
||||
);
|
||||
assert_jet(c, jet_scow, sam, res);
|
||||
let big = A(&mut c.stack, &ubig!(1000));
|
||||
let sam = T(&mut c.stack, &[aura, big]);
|
||||
let res = T(
|
||||
&mut c.stack,
|
||||
&[B(b'1'), B(b'.'), B(b'0'), B(b'0'), B(b'0'), D(0)],
|
||||
);
|
||||
assert_jet(c, jet_scow, sam, res);
|
||||
let sam = T(&mut c.stack, &[aura, D(9876543210)]);
|
||||
let res = T(
|
||||
&mut c.stack,
|
||||
&[
|
||||
B(b'9'),
|
||||
B(b'.'),
|
||||
@ -132,9 +139,9 @@ mod tests {
|
||||
D(0),
|
||||
],
|
||||
);
|
||||
assert_jet(s, jet_scow, sam, res);
|
||||
assert_jet(c, jet_scow, sam, res);
|
||||
let bad_aura = D(tas!(b"ux"));
|
||||
let sam = T(s, &[bad_aura, D(0)]);
|
||||
assert_jet_err(s, jet_scow, sam, JetErr::Punt);
|
||||
let sam = T(&mut c.stack, &[bad_aura, D(0)]);
|
||||
assert_jet_err(c, jet_scow, sam, JetErr::Punt);
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,13 @@ crate::gdb!();
|
||||
|
||||
pub fn jet_mug(context: &mut Context, subject: Noun) -> Result {
|
||||
let arg = slot(subject, 6)?;
|
||||
Ok(mug(context.stack, arg).as_noun())
|
||||
Ok(mug(&mut context.stack, arg).as_noun())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::{assert_jet, init_stack, A};
|
||||
use crate::jets::util::test::{assert_jet, init_context, A};
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{Noun, D, T};
|
||||
use ibig::ubig;
|
||||
@ -47,22 +47,23 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_mug() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, a63, a96, a128) = atoms(s);
|
||||
assert_jet(s, jet_mug, a0, D(0x79ff04e8));
|
||||
assert_jet(s, jet_mug, a24, D(0x69d59d90));
|
||||
assert_jet(s, jet_mug, a63, D(0x7a9f252e));
|
||||
assert_jet(s, jet_mug, a96, D(0x2aa4c8fb));
|
||||
assert_jet(s, jet_mug, a128, D(0x44fb2c0c));
|
||||
let sam = T(s, &[a128, a128]);
|
||||
assert_jet(s, jet_mug, sam, D(0x61c0ea5c));
|
||||
let sam = T(s, &[a96, a128]);
|
||||
assert_jet(s, jet_mug, sam, D(0x20fb143f));
|
||||
let sam = T(s, &[a0, a0]);
|
||||
assert_jet(s, jet_mug, sam, D(0x192f5588));
|
||||
let sam = T(s, &[a0, a24, a63, a96, a128]);
|
||||
let sam = T(s, &[sam, a0, a24, a63, a96, a128]);
|
||||
let sam = T(s, &[sam, a0, a24, a63, a96, a128]);
|
||||
assert_jet(s, jet_mug, sam, D(0x7543cac7));
|
||||
let c = &mut init_context();
|
||||
let (a0, a24, a63, a96, a128) = atoms(&mut c.stack);
|
||||
|
||||
assert_jet(c, jet_mug, a0, D(0x79ff04e8));
|
||||
assert_jet(c, jet_mug, a24, D(0x69d59d90));
|
||||
assert_jet(c, jet_mug, a63, D(0x7a9f252e));
|
||||
assert_jet(c, jet_mug, a96, D(0x2aa4c8fb));
|
||||
assert_jet(c, jet_mug, a128, D(0x44fb2c0c));
|
||||
let sam = T(&mut c.stack, &[a128, a128]);
|
||||
assert_jet(c, jet_mug, sam, D(0x61c0ea5c));
|
||||
let sam = T(&mut c.stack, &[a96, a128]);
|
||||
assert_jet(c, jet_mug, sam, D(0x20fb143f));
|
||||
let sam = T(&mut c.stack, &[a0, a0]);
|
||||
assert_jet(c, jet_mug, sam, D(0x192f5588));
|
||||
let sam = T(&mut c.stack, &[a0, a24, a63, a96, a128]);
|
||||
let sam = T(&mut c.stack, &[sam, a0, a24, a63, a96, a128]);
|
||||
let sam = T(&mut c.stack, &[sam, a0, a24, a63, a96, a128]);
|
||||
assert_jet(c, jet_mug, sam, D(0x7543cac7));
|
||||
}
|
||||
}
|
||||
|
@ -5,17 +5,16 @@
|
||||
*
|
||||
* In any case, it's important to ensure that the library only allocates on the nock stack. Gmp
|
||||
* has mp_set_memory_functions. I don't know if rug does any allocation on top of that. ibig does
|
||||
* not appear to support custom allocation functions, but we could probably patch it. If we're
|
||||
* not appear to support custom allocation functionc, but we could probably patch it. If we're
|
||||
* patching it, we might even be able to avoid copying the input and output at all, which might
|
||||
* give a greater performance advantage than using gmp anyway.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
use crate::interpreter::Context;
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::JetErr::*;
|
||||
use crate::jets::Result;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
|
||||
use either::{Left, Right};
|
||||
use ibig::ops::DivRem;
|
||||
@ -30,12 +29,12 @@ pub fn jet_add(context: &mut Context, subject: Noun) -> Result {
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
Ok(Atom::new(*stack, a.data() + b.data()).as_noun())
|
||||
Ok(Atom::new(stack, a.data() + b.data()).as_noun())
|
||||
} else {
|
||||
let a_big = a.as_ubig(*stack);
|
||||
let b_big = b.as_ubig(*stack);
|
||||
let res = UBig::add_stack(*stack, a_big, b_big);
|
||||
Ok(Atom::from_ubig(*stack, &res).as_noun())
|
||||
let a_big = a.as_ubig(stack);
|
||||
let b_big = b.as_ubig(stack);
|
||||
let res = UBig::add_stack(stack, a_big, b_big);
|
||||
Ok(Atom::from_ubig(stack, &res).as_noun())
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +44,7 @@ pub fn jet_dec(context: &mut Context, subject: Noun) -> Result {
|
||||
match atom.as_either() {
|
||||
Left(direct) => {
|
||||
if direct.data() == 0 {
|
||||
Err(Deterministic)
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else {
|
||||
Ok(unsafe { DirectAtom::new_unchecked(direct.data() - 1) }.as_noun())
|
||||
}
|
||||
@ -58,7 +57,7 @@ pub fn jet_dec(context: &mut Context, subject: Noun) -> Result {
|
||||
}
|
||||
Some(first_one) => {
|
||||
let (mut new_indirect, new_slice) = unsafe {
|
||||
IndirectAtom::new_raw_mut_bitslice(context.stack, indirect.size())
|
||||
IndirectAtom::new_raw_mut_bitslice(&mut context.stack, indirect.size())
|
||||
};
|
||||
if first_one > 0 {
|
||||
new_slice[..first_one].fill(true);
|
||||
@ -73,7 +72,7 @@ pub fn jet_dec(context: &mut Context, subject: Noun) -> Result {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(Deterministic)
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,14 +83,14 @@ pub fn jet_div(context: &mut Context, subject: Noun) -> Result {
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
||||
Err(Deterministic)
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
Ok(unsafe { DirectAtom::new_unchecked(a.data() / b.data()) }.as_noun())
|
||||
} else {
|
||||
let a_big = a.as_ubig(*stack);
|
||||
let b_big = b.as_ubig(*stack);
|
||||
let res = UBig::div_stack(*stack, a_big, b_big);
|
||||
Ok(Atom::from_ubig(*stack, &res).as_noun())
|
||||
let a_big = a.as_ubig(stack);
|
||||
let b_big = b.as_ubig(stack);
|
||||
let res = UBig::div_stack(stack, a_big, b_big);
|
||||
Ok(Atom::from_ubig(stack, &res).as_noun())
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +101,7 @@ pub fn jet_dvr(context: &mut Context, subject: Noun) -> Result {
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
||||
Err(Deterministic)
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else {
|
||||
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());
|
||||
@ -113,18 +112,19 @@ pub fn jet_dvr(context: &mut Context, subject: Noun) -> Result {
|
||||
)
|
||||
}
|
||||
} else {
|
||||
let (div, rem) = a.as_ubig(*stack).div_rem(b.as_ubig(*stack));
|
||||
let (div, rem) = a.as_ubig(stack).div_rem(b.as_ubig(stack));
|
||||
(
|
||||
Atom::from_ubig(*stack, &div).as_noun(),
|
||||
Atom::from_ubig(*stack, &rem).as_noun(),
|
||||
Atom::from_ubig(stack, &div).as_noun(),
|
||||
Atom::from_ubig(stack, &rem).as_noun(),
|
||||
)
|
||||
};
|
||||
|
||||
Ok(T(*stack, &[div, rem]))
|
||||
Ok(T(stack, &[div, rem]))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_gte(context: &mut Context, subject: Noun) -> Result {
|
||||
let stack = &mut context.stack;
|
||||
let arg = slot(subject, 6)?;
|
||||
let a = slot(arg, 2)?.as_atom()?;
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
@ -139,7 +139,7 @@ pub fn jet_gte(context: &mut Context, subject: Noun) -> Result {
|
||||
YES
|
||||
} else if a.bit_size() < b.bit_size() {
|
||||
NO
|
||||
} else if a.as_ubig(context.stack) >= b.as_ubig(context.stack) {
|
||||
} else if a.as_ubig(stack) >= b.as_ubig(stack) {
|
||||
YES
|
||||
} else {
|
||||
NO
|
||||
@ -147,6 +147,7 @@ pub fn jet_gte(context: &mut Context, subject: Noun) -> Result {
|
||||
}
|
||||
|
||||
pub fn jet_gth(context: &mut Context, subject: Noun) -> Result {
|
||||
let stack = &mut context.stack;
|
||||
let arg = slot(subject, 6)?;
|
||||
let a = slot(arg, 2)?.as_atom()?;
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
@ -161,7 +162,7 @@ pub fn jet_gth(context: &mut Context, subject: Noun) -> Result {
|
||||
YES
|
||||
} else if a.bit_size() < b.bit_size() {
|
||||
NO
|
||||
} else if a.as_ubig(context.stack) > b.as_ubig(context.stack) {
|
||||
} else if a.as_ubig(stack) > b.as_ubig(stack) {
|
||||
YES
|
||||
} else {
|
||||
NO
|
||||
@ -169,6 +170,7 @@ pub fn jet_gth(context: &mut Context, subject: Noun) -> Result {
|
||||
}
|
||||
|
||||
pub fn jet_lte(context: &mut Context, subject: Noun) -> Result {
|
||||
let stack = &mut context.stack;
|
||||
let arg = slot(subject, 6)?;
|
||||
let a = slot(arg, 2)?.as_atom()?;
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
@ -183,19 +185,20 @@ pub fn jet_lte(context: &mut Context, subject: Noun) -> Result {
|
||||
YES
|
||||
} else if a.bit_size() > b.bit_size() {
|
||||
NO
|
||||
} else if a.as_ubig(context.stack) <= b.as_ubig(context.stack) {
|
||||
} else if a.as_ubig(stack) <= b.as_ubig(stack) {
|
||||
YES
|
||||
} else {
|
||||
NO
|
||||
})
|
||||
}
|
||||
|
||||
pub fn jet_lth(_context: &mut Context, subject: Noun) -> Result {
|
||||
pub fn jet_lth(context: &mut Context, subject: Noun) -> Result {
|
||||
let stack = &mut context.stack;
|
||||
let arg = slot(subject, 6)?;
|
||||
let a = slot(arg, 2)?.as_atom()?;
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
Ok(util::lth(a, b))
|
||||
Ok(util::lth(stack, a, b))
|
||||
}
|
||||
|
||||
pub fn jet_mod(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -205,12 +208,12 @@ pub fn jet_mod(context: &mut Context, subject: Noun) -> Result {
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
||||
Err(Deterministic)
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
Ok(unsafe { DirectAtom::new_unchecked(a.data() % b.data()) }.as_noun())
|
||||
} else {
|
||||
let res = a.as_ubig(*stack) % b.as_ubig(*stack);
|
||||
Ok(Atom::from_ubig(*stack, &res).as_noun())
|
||||
let res = a.as_ubig(stack) % b.as_ubig(stack);
|
||||
Ok(Atom::from_ubig(stack, &res).as_noun())
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,11 +226,11 @@ pub fn jet_mul(context: &mut Context, subject: Noun) -> Result {
|
||||
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
let res = a.data() as u128 * b.data() as u128;
|
||||
if res < DIRECT_MAX as u128 {
|
||||
Ok(Atom::new(*stack, res as u64).as_noun())
|
||||
Ok(Atom::new(stack, res as u64).as_noun())
|
||||
} else {
|
||||
Ok(unsafe {
|
||||
IndirectAtom::new_raw_bytes(
|
||||
*stack,
|
||||
stack,
|
||||
if res < u64::MAX as u128 { 8 } else { 16 },
|
||||
&res as *const u128 as *const u8,
|
||||
)
|
||||
@ -235,10 +238,10 @@ pub fn jet_mul(context: &mut Context, subject: Noun) -> Result {
|
||||
.as_noun())
|
||||
}
|
||||
} else {
|
||||
let a_big = a.as_ubig(*stack);
|
||||
let b_big = b.as_ubig(*stack);
|
||||
let res = UBig::mul_stack(*stack, a_big, b_big);
|
||||
Ok(Atom::from_ubig(*stack, &res).as_noun())
|
||||
let a_big = a.as_ubig(stack);
|
||||
let b_big = b.as_ubig(stack);
|
||||
let res = UBig::mul_stack(stack, a_big, b_big);
|
||||
Ok(Atom::from_ubig(stack, &res).as_noun())
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,16 +250,14 @@ pub fn jet_sub(context: &mut Context, subject: Noun) -> Result {
|
||||
let a = slot(arg, 2)?.as_atom()?;
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
Ok(sub(context.stack, a, b)?.as_noun())
|
||||
Ok(sub(&mut context.stack, a, b)?.as_noun())
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::jets::util::test::init_stack;
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{Atom, Noun, NO, YES};
|
||||
|
||||
pub fn lth(a: Atom, b: Atom) -> Noun {
|
||||
let s = &mut init_stack();
|
||||
|
||||
pub fn lth(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
|
||||
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
if a.data() < b.data() {
|
||||
YES
|
||||
@ -267,7 +268,7 @@ pub mod util {
|
||||
YES
|
||||
} else if a.bit_size() > b.bit_size() {
|
||||
NO
|
||||
} else if a.as_ubig(s) < b.as_ubig(s) {
|
||||
} else if a.as_ubig(stack) < b.as_ubig(stack) {
|
||||
YES
|
||||
} else {
|
||||
NO
|
||||
@ -278,8 +279,9 @@ pub mod util {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::util::test::{
|
||||
assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_stack, A,
|
||||
assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_context, A,
|
||||
};
|
||||
use crate::jets::{Jet, JetErr};
|
||||
use crate::mem::NockStack;
|
||||
@ -326,74 +328,78 @@ mod tests {
|
||||
}
|
||||
|
||||
fn assert_math_jet(
|
||||
stack: &mut NockStack,
|
||||
context: &mut Context,
|
||||
jet: Jet,
|
||||
sam: &[fn(&mut NockStack) -> Noun],
|
||||
res: UBig,
|
||||
) {
|
||||
let sam: Vec<Noun> = sam.iter().map(|f| f(stack)).collect();
|
||||
assert_nary_jet_ubig(stack, jet, &sam, res);
|
||||
let sam: Vec<Noun> = sam.iter().map(|f| f(&mut context.stack)).collect();
|
||||
assert_nary_jet_ubig(context, jet, &sam, res);
|
||||
}
|
||||
|
||||
fn assert_math_jet_noun(
|
||||
stack: &mut NockStack,
|
||||
context: &mut Context,
|
||||
jet: Jet,
|
||||
sam: &[fn(&mut NockStack) -> Noun],
|
||||
res: Noun,
|
||||
) {
|
||||
let sam: Vec<Noun> = sam.iter().map(|f| f(stack)).collect();
|
||||
let sam = T(stack, &sam);
|
||||
assert_jet(stack, jet, sam, res);
|
||||
let sam: Vec<Noun> = sam.iter().map(|f| f(&mut context.stack)).collect();
|
||||
let sam = T(&mut context.stack, &sam);
|
||||
assert_jet(context, jet, sam, res);
|
||||
}
|
||||
|
||||
fn assert_math_jet_err(
|
||||
stack: &mut NockStack,
|
||||
context: &mut Context,
|
||||
jet: Jet,
|
||||
sam: &[fn(&mut NockStack) -> Noun],
|
||||
err: JetErr,
|
||||
) {
|
||||
let sam: Vec<Noun> = sam.iter().map(|f| f(stack)).collect();
|
||||
let sam = T(stack, &sam);
|
||||
assert_jet_err(stack, jet, sam, err);
|
||||
let sam: Vec<Noun> = sam.iter().map(|f| f(&mut context.stack)).collect();
|
||||
let sam = T(&mut context.stack, &sam);
|
||||
assert_jet_err(context, jet, sam, err);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_math_jet(
|
||||
s,
|
||||
c,
|
||||
jet_add,
|
||||
&[atom_128, atom_96],
|
||||
ubig!(0xdeadbef00d03068514bb685765666666),
|
||||
);
|
||||
assert_math_jet(
|
||||
s,
|
||||
c,
|
||||
jet_add,
|
||||
&[atom_63, atom_96],
|
||||
ubig!(0xfaceb00c95deadbeef123455),
|
||||
);
|
||||
assert_math_jet(s, jet_add, &[atom_63, atom_63], ubig!(0xfffffffffffffffe));
|
||||
assert_math_jet(c, jet_add, &[atom_63, atom_63], ubig!(0xfffffffffffffffe));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dec() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
let s = &mut c.stack;
|
||||
|
||||
let (a0, _a24, a63, _a96, a128) = atoms(s);
|
||||
assert_jet_ubig(s, jet_dec, a128, ubig!(0xdeadbeef12345678fedcba987654320f));
|
||||
assert_jet(s, jet_dec, a63, D(0x7ffffffffffffffe));
|
||||
assert_jet_err(s, jet_dec, a0, Deterministic);
|
||||
assert_jet_ubig(c, jet_dec, a128, ubig!(0xdeadbeef12345678fedcba987654320f));
|
||||
assert_jet(c, jet_dec, a63, D(0x7ffffffffffffffe));
|
||||
assert_jet_err(c, jet_dec, a0, JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_div() {
|
||||
let s = &mut init_stack();
|
||||
assert_math_jet(s, jet_div, &[atom_128, atom_96], ubig!(0xe349f8f0));
|
||||
assert_math_jet(s, jet_div, &[atom_96, atom_63], ubig!(0x1f59d6018));
|
||||
assert_math_jet(s, jet_div, &[atom_63, atom_96], ubig!(0));
|
||||
assert_math_jet(s, jet_div, &[atom_63, atom_63], ubig!(1));
|
||||
assert_math_jet(s, jet_div, &[atom_63, atom_24], ubig!(0xf2044dacfe));
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_math_jet(c, jet_div, &[atom_128, atom_96], ubig!(0xe349f8f0));
|
||||
assert_math_jet(c, jet_div, &[atom_96, atom_63], ubig!(0x1f59d6018));
|
||||
assert_math_jet(c, jet_div, &[atom_63, atom_96], ubig!(0));
|
||||
assert_math_jet(c, jet_div, &[atom_63, atom_63], ubig!(1));
|
||||
assert_math_jet(c, jet_div, &[atom_63, atom_24], ubig!(0xf2044dacfe));
|
||||
assert_math_jet(
|
||||
s,
|
||||
c,
|
||||
jet_div,
|
||||
&[atom_128, atom_24],
|
||||
ubig!(0x1a507f98b6fa8605ea3a79e97bf),
|
||||
@ -401,168 +407,206 @@ mod tests {
|
||||
let res = ubig!(
|
||||
_0x00000000000001000000000000000000000000000000000000000000000000000000000000000001
|
||||
);
|
||||
assert_math_jet(s, jet_div, &[atom_528, atom_264], res);
|
||||
assert_math_jet_err(s, jet_div, &[atom_63, atom_0], Deterministic);
|
||||
assert_math_jet_err(s, jet_div, &[atom_0, atom_0], Deterministic);
|
||||
assert_math_jet(c, jet_div, &[atom_528, atom_264], res);
|
||||
assert_math_jet_err(
|
||||
c,
|
||||
jet_div,
|
||||
&[atom_63, atom_0],
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
assert_math_jet_err(
|
||||
c,
|
||||
jet_div,
|
||||
&[atom_0, atom_0],
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dvr() {
|
||||
let s = &mut init_stack();
|
||||
let (a0, a24, a63, a96, a128) = atoms(s);
|
||||
let a264 = atom_264(s);
|
||||
let a528 = atom_528(s);
|
||||
let c = &mut init_context();
|
||||
|
||||
let sam = T(s, &[a128, a96]);
|
||||
let res_a = A(s, &ubig!(0xe349f8f0));
|
||||
let res_b = A(s, &ubig!(0xcb0ce564ec598f658409d170));
|
||||
let res = T(s, &[res_a, res_b]);
|
||||
assert_jet(s, jet_dvr, sam, res);
|
||||
let (a0, a24, a63, a96, a128) = atoms(&mut c.stack);
|
||||
let a264 = atom_264(&mut c.stack);
|
||||
let a528 = atom_528(&mut c.stack);
|
||||
|
||||
let sam = T(s, &[a128, a24]);
|
||||
let res_a = A(s, &ubig!(0x1a507f98b6fa8605ea3a79e97bf));
|
||||
let res_b = A(s, &ubig!(0x3b2013));
|
||||
let res = T(s, &[res_a, res_b]);
|
||||
assert_jet(s, jet_dvr, sam, res);
|
||||
let sam = T(&mut c.stack, &[a128, a96]);
|
||||
let res_a = A(&mut c.stack, &ubig!(0xe349f8f0));
|
||||
let res_b = A(&mut c.stack, &ubig!(0xcb0ce564ec598f658409d170));
|
||||
let res = T(&mut c.stack, &[res_a, res_b]);
|
||||
assert_jet(c, jet_dvr, sam, res);
|
||||
|
||||
let sam = T(s, &[a63, a63]);
|
||||
let res_a = A(s, &ubig!(1));
|
||||
let res_b = A(s, &ubig!(0));
|
||||
let res = T(s, &[res_a, res_b]);
|
||||
assert_jet(s, jet_dvr, sam, res);
|
||||
let sam = T(&mut c.stack, &[a128, a24]);
|
||||
let res_a = A(&mut c.stack, &ubig!(0x1a507f98b6fa8605ea3a79e97bf));
|
||||
let res_b = A(&mut c.stack, &ubig!(0x3b2013));
|
||||
let res = T(&mut c.stack, &[res_a, res_b]);
|
||||
assert_jet(c, jet_dvr, sam, res);
|
||||
|
||||
let sam = T(s, &[a0, a24]);
|
||||
let res_a = A(s, &ubig!(0));
|
||||
let res_b = A(s, &ubig!(0));
|
||||
let res = T(s, &[res_a, res_b]);
|
||||
assert_jet(s, jet_dvr, sam, res);
|
||||
let sam = T(&mut c.stack, &[a63, a63]);
|
||||
let res_a = A(&mut c.stack, &ubig!(1));
|
||||
let res_b = A(&mut c.stack, &ubig!(0));
|
||||
let res = T(&mut c.stack, &[res_a, res_b]);
|
||||
assert_jet(c, jet_dvr, sam, res);
|
||||
|
||||
let sam = T(s, &[a528, a264]);
|
||||
let sam = T(&mut c.stack, &[a0, a24]);
|
||||
let res_a = A(&mut c.stack, &ubig!(0));
|
||||
let res_b = A(&mut c.stack, &ubig!(0));
|
||||
let res = T(&mut c.stack, &[res_a, res_b]);
|
||||
assert_jet(c, jet_dvr, sam, res);
|
||||
|
||||
let sam = T(&mut c.stack, &[a528, a264]);
|
||||
let res_a = A(
|
||||
s,
|
||||
&mut c.stack,
|
||||
&ubig!(
|
||||
_0x00000000000001000000000000000000000000000000000000000000000000000000000000000001
|
||||
),
|
||||
);
|
||||
let res_b = A(s, &ubig!(0x100));
|
||||
let res = T(s, &[res_a, res_b]);
|
||||
assert_jet(s, jet_dvr, sam, res);
|
||||
let res_b = A(&mut c.stack, &ubig!(0x100));
|
||||
let res = T(&mut c.stack, &[res_a, res_b]);
|
||||
assert_jet(c, jet_dvr, sam, res);
|
||||
|
||||
assert_math_jet_err(s, jet_dvr, &[atom_63, atom_0], Deterministic);
|
||||
assert_math_jet_err(
|
||||
c,
|
||||
jet_dvr,
|
||||
&[atom_63, atom_0],
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gte() {
|
||||
let s = &mut init_stack();
|
||||
assert_math_jet_noun(s, jet_gte, &[atom_128, atom_96], YES);
|
||||
assert_math_jet_noun(s, jet_gte, &[atom_96, atom_63], YES);
|
||||
assert_math_jet_noun(s, jet_gte, &[atom_63, atom_96], NO);
|
||||
assert_math_jet_noun(s, jet_gte, &[atom_63, atom_63], YES);
|
||||
assert_math_jet_noun(s, jet_gte, &[atom_63, atom_24], YES);
|
||||
assert_math_jet_noun(s, jet_gte, &[atom_128, atom_24], YES);
|
||||
assert_math_jet_noun(s, jet_gte, &[atom_128, atom_128_b], YES);
|
||||
assert_math_jet_noun(s, jet_gte, &[atom_128_b, atom_128], NO);
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_math_jet_noun(c, jet_gte, &[atom_128, atom_96], YES);
|
||||
assert_math_jet_noun(c, jet_gte, &[atom_96, atom_63], YES);
|
||||
assert_math_jet_noun(c, jet_gte, &[atom_63, atom_96], NO);
|
||||
assert_math_jet_noun(c, jet_gte, &[atom_63, atom_63], YES);
|
||||
assert_math_jet_noun(c, jet_gte, &[atom_63, atom_24], YES);
|
||||
assert_math_jet_noun(c, jet_gte, &[atom_128, atom_24], YES);
|
||||
assert_math_jet_noun(c, jet_gte, &[atom_128, atom_128_b], YES);
|
||||
assert_math_jet_noun(c, jet_gte, &[atom_128_b, atom_128], NO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gth() {
|
||||
let s = &mut init_stack();
|
||||
assert_math_jet_noun(s, jet_gth, &[atom_128, atom_96], YES);
|
||||
assert_math_jet_noun(s, jet_gth, &[atom_96, atom_63], YES);
|
||||
assert_math_jet_noun(s, jet_gth, &[atom_63, atom_96], NO);
|
||||
assert_math_jet_noun(s, jet_gth, &[atom_63, atom_63], NO);
|
||||
assert_math_jet_noun(s, jet_gth, &[atom_63, atom_24], YES);
|
||||
assert_math_jet_noun(s, jet_gth, &[atom_128, atom_24], YES);
|
||||
assert_math_jet_noun(s, jet_gth, &[atom_128, atom_128_b], YES);
|
||||
assert_math_jet_noun(s, jet_gth, &[atom_128_b, atom_128], NO);
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_math_jet_noun(c, jet_gth, &[atom_128, atom_96], YES);
|
||||
assert_math_jet_noun(c, jet_gth, &[atom_96, atom_63], YES);
|
||||
assert_math_jet_noun(c, jet_gth, &[atom_63, atom_96], NO);
|
||||
assert_math_jet_noun(c, jet_gth, &[atom_63, atom_63], NO);
|
||||
assert_math_jet_noun(c, jet_gth, &[atom_63, atom_24], YES);
|
||||
assert_math_jet_noun(c, jet_gth, &[atom_128, atom_24], YES);
|
||||
assert_math_jet_noun(c, jet_gth, &[atom_128, atom_128_b], YES);
|
||||
assert_math_jet_noun(c, jet_gth, &[atom_128_b, atom_128], NO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lte() {
|
||||
let s = &mut init_stack();
|
||||
assert_math_jet_noun(s, jet_lte, &[atom_128, atom_96], NO);
|
||||
assert_math_jet_noun(s, jet_lte, &[atom_96, atom_63], NO);
|
||||
assert_math_jet_noun(s, jet_lte, &[atom_63, atom_96], YES);
|
||||
assert_math_jet_noun(s, jet_lte, &[atom_63, atom_63], YES);
|
||||
assert_math_jet_noun(s, jet_lte, &[atom_63, atom_24], NO);
|
||||
assert_math_jet_noun(s, jet_lte, &[atom_128, atom_24], NO);
|
||||
assert_math_jet_noun(s, jet_lte, &[atom_128, atom_128_b], NO);
|
||||
assert_math_jet_noun(s, jet_lte, &[atom_128_b, atom_128], YES);
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_math_jet_noun(c, jet_lte, &[atom_128, atom_96], NO);
|
||||
assert_math_jet_noun(c, jet_lte, &[atom_96, atom_63], NO);
|
||||
assert_math_jet_noun(c, jet_lte, &[atom_63, atom_96], YES);
|
||||
assert_math_jet_noun(c, jet_lte, &[atom_63, atom_63], YES);
|
||||
assert_math_jet_noun(c, jet_lte, &[atom_63, atom_24], NO);
|
||||
assert_math_jet_noun(c, jet_lte, &[atom_128, atom_24], NO);
|
||||
assert_math_jet_noun(c, jet_lte, &[atom_128, atom_128_b], NO);
|
||||
assert_math_jet_noun(c, jet_lte, &[atom_128_b, atom_128], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lth() {
|
||||
let s = &mut init_stack();
|
||||
assert_math_jet_noun(s, jet_lth, &[atom_128, atom_96], NO);
|
||||
assert_math_jet_noun(s, jet_lth, &[atom_96, atom_63], NO);
|
||||
assert_math_jet_noun(s, jet_lth, &[atom_63, atom_96], YES);
|
||||
assert_math_jet_noun(s, jet_lth, &[atom_63, atom_63], NO);
|
||||
assert_math_jet_noun(s, jet_lth, &[atom_63, atom_24], NO);
|
||||
assert_math_jet_noun(s, jet_lth, &[atom_128, atom_24], NO);
|
||||
assert_math_jet_noun(s, jet_lth, &[atom_128, atom_128_b], NO);
|
||||
assert_math_jet_noun(s, jet_lth, &[atom_128_b, atom_128], YES);
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_math_jet_noun(c, jet_lth, &[atom_128, atom_96], NO);
|
||||
assert_math_jet_noun(c, jet_lth, &[atom_96, atom_63], NO);
|
||||
assert_math_jet_noun(c, jet_lth, &[atom_63, atom_96], YES);
|
||||
assert_math_jet_noun(c, jet_lth, &[atom_63, atom_63], NO);
|
||||
assert_math_jet_noun(c, jet_lth, &[atom_63, atom_24], NO);
|
||||
assert_math_jet_noun(c, jet_lth, &[atom_128, atom_24], NO);
|
||||
assert_math_jet_noun(c, jet_lth, &[atom_128, atom_128_b], NO);
|
||||
assert_math_jet_noun(c, jet_lth, &[atom_128_b, atom_128], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mod() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_math_jet(
|
||||
s,
|
||||
c,
|
||||
jet_mod,
|
||||
&[atom_128, atom_96],
|
||||
ubig!(0xcb0ce564ec598f658409d170),
|
||||
);
|
||||
assert_math_jet(s, jet_mod, &[atom_96, atom_63], ubig!(0x15deadc0e4af946e));
|
||||
assert_math_jet(s, jet_mod, &[atom_63, atom_96], ubig!(0x7fffffffffffffff));
|
||||
assert_math_jet(s, jet_mod, &[atom_63, atom_63], ubig!(0));
|
||||
assert_math_jet(s, jet_mod, &[atom_63, atom_24], ubig!(0x798385));
|
||||
assert_math_jet(s, jet_mod, &[atom_128, atom_24], ubig!(0x3b2013));
|
||||
assert_math_jet(s, jet_mod, &[atom_528, atom_264], ubig!(0x100));
|
||||
assert_math_jet_err(s, jet_mod, &[atom_63, atom_0], Deterministic);
|
||||
assert_math_jet_err(s, jet_mod, &[atom_0, atom_0], Deterministic);
|
||||
assert_math_jet(c, jet_mod, &[atom_96, atom_63], ubig!(0x15deadc0e4af946e));
|
||||
assert_math_jet(c, jet_mod, &[atom_63, atom_96], ubig!(0x7fffffffffffffff));
|
||||
assert_math_jet(c, jet_mod, &[atom_63, atom_63], ubig!(0));
|
||||
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_528, atom_264], ubig!(0x100));
|
||||
assert_math_jet_err(
|
||||
c,
|
||||
jet_mod,
|
||||
&[atom_63, atom_0],
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
assert_math_jet_err(
|
||||
c,
|
||||
jet_mod,
|
||||
&[atom_0, atom_0],
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mul() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_math_jet(
|
||||
s,
|
||||
c,
|
||||
jet_mul,
|
||||
&[atom_128, atom_96],
|
||||
ubig!(_0xda297567129704bf42e744f13ff0ea4fc4ac01215b708bc94f941160),
|
||||
);
|
||||
assert_math_jet(
|
||||
s,
|
||||
c,
|
||||
jet_mul,
|
||||
&[atom_63, atom_96],
|
||||
ubig!(_0x7d6758060aef56de7cba6a1eea21524110edcbaa),
|
||||
);
|
||||
assert_math_jet(
|
||||
s,
|
||||
c,
|
||||
jet_mul,
|
||||
&[atom_63, atom_63],
|
||||
ubig!(0x3fffffffffffffff0000000000000001),
|
||||
);
|
||||
assert_math_jet(s, jet_mul, &[atom_24, atom_24], ubig!(0x479bf4b7ef89));
|
||||
assert_math_jet(c, jet_mul, &[atom_24, atom_24], ubig!(0x479bf4b7ef89));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sub() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_math_jet(
|
||||
s,
|
||||
c,
|
||||
jet_sub,
|
||||
&[atom_128, atom_96],
|
||||
ubig!(0xdeadbeee1765a66ce8fe0cd98741fdba),
|
||||
);
|
||||
assert_math_jet(
|
||||
s,
|
||||
c,
|
||||
jet_sub,
|
||||
&[atom_96, atom_63],
|
||||
ubig!(0xfaceb00b95deadbeef123457),
|
||||
);
|
||||
assert_math_jet(s, jet_sub, &[atom_63, atom_63], ubig!(0));
|
||||
assert_math_jet(s, jet_sub, &[atom_128, atom_128], ubig!(0));
|
||||
assert_math_jet_err(s, jet_sub, &[atom_63, atom_96], Deterministic);
|
||||
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_err(
|
||||
c,
|
||||
jet_sub,
|
||||
&[atom_63, atom_96],
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,71 @@
|
||||
/** Virtualization jets
|
||||
*/
|
||||
use crate::interpreter::Context;
|
||||
use crate::hamt::Hamt;
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::util::slot;
|
||||
use crate::jets::Result;
|
||||
use crate::noun::Noun;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{Noun, T};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
// XX: interpret should accept optional scry function and potentially produce blocked
|
||||
// Determinist scry crashes should have the following behaviour:
|
||||
//
|
||||
// root <-- Deterministic
|
||||
// mink <-- Deterministic
|
||||
// scry <-- ScryCrashed
|
||||
//
|
||||
// root <-- Deterministic
|
||||
// mink <-- Deterministic
|
||||
// mink <-- ScryCrashed
|
||||
// scry <-- ScryCrashed
|
||||
// scry <-- ScryCrashed
|
||||
//
|
||||
// root
|
||||
// mink <-- Tone
|
||||
// mink <-- Deterministic
|
||||
// mink <-- ScryCrashed
|
||||
// scry <-- ScryCrashed
|
||||
// scry <-- ScryCrashed
|
||||
// scry
|
||||
//
|
||||
pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
|
||||
let arg = slot(subject, 6)?;
|
||||
// mink sample = [nock scry_namespace]
|
||||
// = [[subject formula] scry_namespace]
|
||||
let v_subject = slot(arg, 4)?;
|
||||
let v_formula = slot(arg, 5)?;
|
||||
let _scry = slot(arg, 3)?;
|
||||
util::mink(context, v_subject, v_formula)
|
||||
let scry_handler = slot(arg, 3)?;
|
||||
|
||||
let old_cache = context.cache;
|
||||
let old_scry_stack = context.scry_stack;
|
||||
|
||||
context.cache = Hamt::<Noun>::new();
|
||||
context.scry_stack = T(&mut context.stack, &[scry_handler, old_scry_stack]);
|
||||
|
||||
match util::mink(context, v_subject, v_formula) {
|
||||
Ok(noun) => {
|
||||
context.cache = old_cache;
|
||||
context.scry_stack = old_scry_stack;
|
||||
Ok(noun)
|
||||
}
|
||||
Err(error) => match error {
|
||||
Error::NonDeterministic(_) => Err(JetErr::Fail(error)),
|
||||
Error::ScryCrashed(trace) => {
|
||||
if unsafe { context.scry_stack.raw_equals(old_scry_stack) } {
|
||||
Err(JetErr::Fail(Error::Deterministic(trace)))
|
||||
} else {
|
||||
Err(JetErr::Fail(error))
|
||||
}
|
||||
}
|
||||
Error::Deterministic(_) | Error::ScryBlocked(_) => {
|
||||
panic!("scry: mink: unhandled errors in helper")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::interpreter::{interpret, Context, NockErr, Tone};
|
||||
use crate::interpreter::{interpret, Context, Error};
|
||||
use crate::jets;
|
||||
use crate::jets::form::util::scow;
|
||||
use crate::jets::util::rip;
|
||||
@ -27,21 +73,19 @@ pub mod util {
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{tape, Cell, Noun, D, T};
|
||||
use ares_macros::tas;
|
||||
use either::{Left, Right};
|
||||
use std::result;
|
||||
|
||||
pub const LEAF: Noun = D(tas!(b"leaf"));
|
||||
pub const ROSE: Noun = D(tas!(b"rose"));
|
||||
|
||||
pub fn mink(context: &mut Context, subject: Noun, formula: Noun) -> jets::Result {
|
||||
// XX: no partial traces; all of our traces go down to the "home road"
|
||||
pub fn mink(context: &mut Context, subject: Noun, formula: Noun) -> Result<Noun, Error> {
|
||||
match interpret(context, subject, formula) {
|
||||
Ok(res) => Ok(T(context.stack, &[D(0), res])),
|
||||
Ok(res) => Ok(T(&mut context.stack, &[D(0), res])),
|
||||
Err(err) => match err {
|
||||
Tone::Blocked(block) => Ok(T(context.stack, &[D(1), block])),
|
||||
Tone::Error(err, trace) => match err {
|
||||
NockErr::Deterministic => Ok(T(context.stack, &[D(2), trace])),
|
||||
NockErr::NonDeterministic => Err(JetErr::NonDeterministic),
|
||||
},
|
||||
Error::ScryBlocked(path) => Ok(T(&mut context.stack, &[D(1), path])),
|
||||
Error::Deterministic(trace) => Ok(T(&mut context.stack, &[D(2), trace])),
|
||||
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(err),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -55,14 +99,14 @@ pub mod util {
|
||||
|
||||
match tag.data() {
|
||||
x if x < 2 => return Ok(tone),
|
||||
x if x > 2 => return Err(JetErr::Deterministic),
|
||||
x if x > 2 => return Err(JetErr::Fail(Error::Deterministic(D(0)))),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if unsafe { original_list.raw_equals(D(0)) } {
|
||||
return Ok(tone);
|
||||
} else if original_list.atom().is_some() {
|
||||
return Err(JetErr::Deterministic);
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
|
||||
// XX: trim traces longer than 1024 frames
|
||||
@ -71,7 +115,7 @@ pub mod util {
|
||||
let mut res = D(0);
|
||||
let mut list = original_list;
|
||||
// Unused if flopping
|
||||
let (mut new_cell, mut new_memory) = Cell::new_raw_mut(context.stack);
|
||||
let (mut new_cell, mut new_memory) = Cell::new_raw_mut(&mut context.stack);
|
||||
let mut memory = new_memory;
|
||||
|
||||
// loop guaranteed to run at least once
|
||||
@ -81,7 +125,7 @@ pub mod util {
|
||||
} else if !flop && res.raw_equals(D(0)) {
|
||||
res = new_cell.as_noun();
|
||||
} else if !flop {
|
||||
(new_cell, new_memory) = Cell::new_raw_mut(context.stack);
|
||||
(new_cell, new_memory) = Cell::new_raw_mut(&mut context.stack);
|
||||
(*memory).tail = new_cell.as_noun();
|
||||
memory = new_memory
|
||||
}
|
||||
@ -92,31 +136,54 @@ pub mod util {
|
||||
let dat = trace.tail();
|
||||
|
||||
let tank: Noun = match tag.data() {
|
||||
tas!(b"mean") => {
|
||||
if let Ok(atom) = dat.as_atom() {
|
||||
let tape = rip(context.stack, 3, 1, atom)?;
|
||||
T(context.stack, &[LEAF, tape])
|
||||
} else {
|
||||
let tone = mink(context, dat, dat.as_cell()?.head())?.as_cell()?;
|
||||
if !tone.head().raw_equals(D(0)) {
|
||||
let tape = tape(context.stack, "####");
|
||||
T(context.stack, &[LEAF, tape])
|
||||
} else {
|
||||
// XX: need to check that this is actually a tank
|
||||
// return leaf+"mean.mook" if not
|
||||
tone.tail()
|
||||
tas!(b"hunk") => match dat.as_either_atom_cell() {
|
||||
Left(_) => {
|
||||
let stack = &mut context.stack;
|
||||
let tape = tape(stack, "mook.hunk");
|
||||
T(stack, &[LEAF, tape])
|
||||
}
|
||||
Right(cell) => {
|
||||
// XX: need to check that this is actually a path
|
||||
// return leaf+"mook.hunk" if not
|
||||
let path = cell.tail();
|
||||
smyt(&mut context.stack, path)?
|
||||
}
|
||||
},
|
||||
tas!(b"mean") => match dat.as_either_atom_cell() {
|
||||
Left(atom) => {
|
||||
let stack = &mut context.stack;
|
||||
let tape = rip(stack, 3, 1, atom)?;
|
||||
T(stack, &[LEAF, tape])
|
||||
}
|
||||
Right(cell) => {
|
||||
'tank: {
|
||||
if let Ok(tone) = mink(context, dat, cell.head()) {
|
||||
if let Some(cell) = tone.cell() {
|
||||
if cell.head().raw_equals(D(0)) {
|
||||
// XX: need to check that this is
|
||||
// actually a path;
|
||||
// return leaf+"mook.mean" if not
|
||||
break 'tank cell.tail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let stack = &mut context.stack;
|
||||
let tape = tape(stack, "####");
|
||||
T(stack, &[LEAF, tape])
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
tas!(b"spot") => {
|
||||
let stack = &mut context.stack;
|
||||
|
||||
let spot = dat.as_cell()?;
|
||||
let pint = spot.tail().as_cell()?;
|
||||
let pstr = pint.head().as_cell()?;
|
||||
let pend = pint.tail().as_cell()?;
|
||||
|
||||
let colo = T(*stack, &[D(b':' as u64), D(0)]);
|
||||
let trel = T(*stack, &[colo, D(0), D(0)]);
|
||||
let colo = T(stack, &[D(b':' as u64), D(0)]);
|
||||
let trel = T(stack, &[colo, D(0), D(0)]);
|
||||
|
||||
let smyt = smyt(stack, spot.head())?;
|
||||
|
||||
@ -134,7 +201,7 @@ pub mod util {
|
||||
list = list.tail().as_cell()?;
|
||||
}
|
||||
// "{end_col}]>"
|
||||
let p4 = T(*stack, &[D(b']' as u64), D(b'>' as u64), D(0)]);
|
||||
let p4 = T(stack, &[D(b']' as u64), D(b'>' as u64), D(0)]);
|
||||
(*list.tail_as_mut()) = p4;
|
||||
|
||||
list = end_lin.as_cell()?;
|
||||
@ -145,7 +212,7 @@ pub mod util {
|
||||
list = list.tail().as_cell()?;
|
||||
}
|
||||
// "{end_lin} {end_col}]>"
|
||||
let p3 = T(*stack, &[D(b' ' as u64), end_col]);
|
||||
let p3 = T(stack, &[D(b' ' as u64), end_col]);
|
||||
(*list.tail_as_mut()) = p3;
|
||||
|
||||
list = str_col.as_cell()?;
|
||||
@ -157,7 +224,7 @@ pub mod util {
|
||||
}
|
||||
// "{str_col}].[{end_lin} {end_col}]>"
|
||||
let p2 = T(
|
||||
*stack,
|
||||
stack,
|
||||
&[D(b']' as u64), D(b'.' as u64), D(b'[' as u64), end_lin],
|
||||
);
|
||||
(*list.tail_as_mut()) = p2;
|
||||
@ -170,19 +237,20 @@ pub mod util {
|
||||
list = list.tail().as_cell()?;
|
||||
}
|
||||
// "{str_lin} {str_col}].[{end_lin} {end_col}]>"
|
||||
let p1 = T(*stack, &[D(b' ' as u64), str_col]);
|
||||
let p1 = T(stack, &[D(b' ' as u64), str_col]);
|
||||
(*list.tail_as_mut()) = p1;
|
||||
|
||||
// "<[{str_lin} {str_col}].[{end_lin} {end_col}]>"
|
||||
let tape = T(*stack, &[D(b'<' as u64), D(b'[' as u64), str_lin]);
|
||||
let finn = T(*stack, &[LEAF, tape]);
|
||||
let tape = T(stack, &[D(b'<' as u64), D(b'[' as u64), str_lin]);
|
||||
let finn = T(stack, &[LEAF, tape]);
|
||||
|
||||
T(*stack, &[ROSE, trel, smyt, finn, D(0)])
|
||||
T(stack, &[ROSE, trel, smyt, finn, D(0)])
|
||||
}
|
||||
_ => {
|
||||
let tape = rip(context.stack, 3, 1, tag.as_atom())?;
|
||||
let stack = &mut context.stack;
|
||||
let tape = rip(stack, 3, 1, tag.as_atom())?;
|
||||
T(
|
||||
context.stack,
|
||||
stack,
|
||||
&[
|
||||
D(tas!(b"m")),
|
||||
D(tas!(b"o")),
|
||||
@ -194,12 +262,11 @@ pub mod util {
|
||||
)
|
||||
} // XX: TODO
|
||||
// %hand
|
||||
// %hunk
|
||||
// %lose
|
||||
};
|
||||
|
||||
if flop {
|
||||
res = T(context.stack, &[tank, res]);
|
||||
res = T(&mut context.stack, &[tank, res]);
|
||||
} else {
|
||||
(*memory).head = tank;
|
||||
}
|
||||
@ -210,7 +277,7 @@ pub mod util {
|
||||
(*memory).tail = D(0);
|
||||
}
|
||||
|
||||
let toon = Cell::new(context.stack, D(2), res);
|
||||
let toon = Cell::new(&mut context.stack, D(2), res);
|
||||
Ok(toon)
|
||||
}
|
||||
}
|
||||
@ -244,7 +311,7 @@ pub mod util {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::{assert_jet, init_stack};
|
||||
use crate::jets::util::test::{assert_jet, init_context};
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{D, T};
|
||||
use crate::serf::TERMINATOR;
|
||||
@ -265,31 +332,36 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_mink_success() {
|
||||
let sack = &mut init_stack();
|
||||
let context = &mut init_context();
|
||||
let stack = &mut context.stack;
|
||||
|
||||
let subj = D(0);
|
||||
let form = T(sack, &[D(1), D(53)]);
|
||||
let nock = T(sack, &[subj, form]);
|
||||
let form = T(stack, &[D(1), D(53)]);
|
||||
let nock = T(stack, &[subj, form]);
|
||||
let scry = D(0);
|
||||
let samp = T(sack, &[nock, scry]);
|
||||
let rest = T(sack, &[D(0), D(53)]);
|
||||
assert_jet(sack, jet_mink, samp, rest);
|
||||
let samp = T(stack, &[nock, scry]);
|
||||
let rest = T(stack, &[D(0), D(53)]);
|
||||
assert_jet(context, jet_mink, samp, rest);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mink_zapzap() {
|
||||
let sack = &mut init_stack();
|
||||
let context = &mut init_context();
|
||||
let stack = &mut context.stack;
|
||||
|
||||
let subj = D(0);
|
||||
let form = T(sack, &[D(0), D(0)]);
|
||||
let nock = T(sack, &[subj, form]);
|
||||
let form = T(stack, &[D(0), D(0)]);
|
||||
let nock = T(stack, &[subj, form]);
|
||||
let scry = D(0);
|
||||
let samp = T(sack, &[nock, scry]);
|
||||
let rest = T(sack, &[D(2), D(0)]);
|
||||
assert_jet(sack, jet_mink, samp, rest);
|
||||
let samp = T(stack, &[nock, scry]);
|
||||
let rest = T(stack, &[D(2), D(0), D(0)]);
|
||||
assert_jet(context, jet_mink, samp, rest);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mink_trace() {
|
||||
let sack = &mut init_stack();
|
||||
let context = &mut init_context();
|
||||
let stack = &mut context.stack;
|
||||
let subj = D(0);
|
||||
let scry = D(0);
|
||||
|
||||
@ -313,63 +385,63 @@ mod tests {
|
||||
// https://stackoverflow.com/questions/60686259/mutable-borrow-in-function-argument
|
||||
|
||||
let hint_spot = D(1953460339);
|
||||
let hint_path = T(sack, &[D(1953719668), D(0)]);
|
||||
let hint_path = T(stack, &[D(1953719668), D(0)]);
|
||||
let hint_dyn = D(1);
|
||||
let hint_row = D(1);
|
||||
|
||||
let make_hint = |sack: &mut NockStack, col_start: u64, col_end: u64| {
|
||||
let start = T(sack, &[hint_row, D(col_start)]);
|
||||
let end = T(sack, &[hint_row, D(col_end)]);
|
||||
let make_hint = |stack: &mut NockStack, col_start: u64, col_end: u64| {
|
||||
let start = T(stack, &[hint_row, D(col_start)]);
|
||||
let end = T(stack, &[hint_row, D(col_end)]);
|
||||
|
||||
T(sack, &[hint_spot, hint_dyn, hint_path, start, end])
|
||||
T(stack, &[hint_spot, hint_dyn, hint_path, start, end])
|
||||
};
|
||||
|
||||
let sss3s1 = T(sack, &[D(0), D(3)]);
|
||||
let sss3s2s1 = make_hint(sack, 20, 22);
|
||||
let sss3s2s2 = T(sack, &[D(1), D(53)]);
|
||||
let sss3s2 = T(sack, &[D(11), sss3s2s1, sss3s2s2]);
|
||||
let sss3 = T(sack, &[D(7), sss3s1, sss3s2]);
|
||||
let sss3s1 = T(stack, &[D(0), D(3)]);
|
||||
let sss3s2s1 = make_hint(stack, 20, 22);
|
||||
let sss3s2s2 = T(stack, &[D(1), D(53)]);
|
||||
let sss3s2 = T(stack, &[D(11), sss3s2s1, sss3s2s2]);
|
||||
let sss3 = T(stack, &[D(7), sss3s1, sss3s2]);
|
||||
|
||||
let sss2s1 = sss3s1;
|
||||
let sss2s2s1 = make_hint(sack, 16, 18);
|
||||
let sss2s2s2 = T(sack, &[D(0), D(0)]);
|
||||
let sss2s2 = T(sack, &[D(11), sss2s2s1, sss2s2s2]);
|
||||
let sss2 = T(sack, &[D(7), sss2s1, sss2s2]);
|
||||
let sss2s2s1 = make_hint(stack, 16, 18);
|
||||
let sss2s2s2 = T(stack, &[D(0), D(0)]);
|
||||
let sss2s2 = T(stack, &[D(11), sss2s2s1, sss2s2s2]);
|
||||
let sss2 = T(stack, &[D(7), sss2s1, sss2s2]);
|
||||
|
||||
let sss1s1 = T(sack, &[D(1), D(0)]);
|
||||
let sss1s2 = T(sack, &[D(0), D(2)]);
|
||||
let sss1 = T(sack, &[D(5), sss1s1, sss1s2]);
|
||||
let sss1s1 = T(stack, &[D(1), D(0)]);
|
||||
let sss1s2 = T(stack, &[D(0), D(2)]);
|
||||
let sss1 = T(stack, &[D(5), sss1s1, sss1s2]);
|
||||
|
||||
let ss2 = T(sack, &[D(6), sss1, sss2, sss3]);
|
||||
let ss2 = T(stack, &[D(6), sss1, sss2, sss3]);
|
||||
|
||||
let ss1s1 = make_hint(sack, 13, 14);
|
||||
let ss1s1 = make_hint(stack, 13, 14);
|
||||
let ss1s2 = sss1s1;
|
||||
let ss1 = T(sack, &[D(11), ss1s1, ss1s2]);
|
||||
let ss1 = T(stack, &[D(11), ss1s1, ss1s2]);
|
||||
|
||||
let s2 = T(sack, &[D(8), ss1, ss2]);
|
||||
let s1 = make_hint(sack, 9, 22);
|
||||
let form = T(sack, &[D(11), s1, s2]);
|
||||
let s2 = T(stack, &[D(8), ss1, ss2]);
|
||||
let s1 = make_hint(stack, 9, 22);
|
||||
let form = T(stack, &[D(11), s1, s2]);
|
||||
|
||||
let nock = T(sack, &[subj, form]);
|
||||
let samp = T(sack, &[nock, scry]);
|
||||
let nock = T(stack, &[subj, form]);
|
||||
let samp = T(stack, &[nock, scry]);
|
||||
|
||||
// trace
|
||||
// [%2 trace=~[[~.spot [[1.953.719.668 0] [1 16] 1 18]] [~.spot [[1.953.719.668 0] [1 9] 1 22]]]]
|
||||
let ttt2t1 = T(sack, &[D(1), D(9)]);
|
||||
let ttt2t2 = T(sack, &[D(1), D(22)]);
|
||||
let ttt2 = T(sack, &[hint_path, ttt2t1, ttt2t2]);
|
||||
let ttt2t1 = T(stack, &[D(1), D(9)]);
|
||||
let ttt2t2 = T(stack, &[D(1), D(22)]);
|
||||
let ttt2 = T(stack, &[hint_path, ttt2t1, ttt2t2]);
|
||||
|
||||
let ttt1t1 = T(sack, &[D(1), D(16)]);
|
||||
let ttt1t2 = T(sack, &[D(1), D(18)]);
|
||||
let ttt1 = T(sack, &[hint_path, ttt1t1, ttt1t2]);
|
||||
let ttt1t1 = T(stack, &[D(1), D(16)]);
|
||||
let ttt1t2 = T(stack, &[D(1), D(18)]);
|
||||
let ttt1 = T(stack, &[hint_path, ttt1t1, ttt1t2]);
|
||||
|
||||
let tt2 = T(sack, &[hint_spot, ttt2]);
|
||||
let tt1 = T(sack, &[hint_spot, ttt1]);
|
||||
let tt2 = T(stack, &[hint_spot, ttt2]);
|
||||
let tt1 = T(stack, &[hint_spot, ttt1]);
|
||||
|
||||
let t1 = T(sack, &[tt1, tt2, D(0)]);
|
||||
let t1 = T(stack, &[tt1, tt2, D(0)]);
|
||||
|
||||
let rest = T(sack, &[D(2), t1]);
|
||||
let rest = T(stack, &[D(2), t1, D(0)]);
|
||||
|
||||
assert_jet(sack, jet_mink, samp, rest);
|
||||
assert_jet(context, jet_mink, samp, rest);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ pub fn jet_mor(context: &mut Context, subject: Noun) -> jets::Result {
|
||||
match e.data().cmp(&f.data()) {
|
||||
Ordering::Greater => Ok(NO),
|
||||
Ordering::Less => Ok(YES),
|
||||
Ordering::Equal => Ok(util::dor(a, b)),
|
||||
Ordering::Equal => Ok(util::dor(stack, a, b)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,30 +42,31 @@ pub fn jet_gor(context: &mut Context, subject: Noun) -> jets::Result {
|
||||
match c.data().cmp(&d.data()) {
|
||||
Ordering::Greater => Ok(NO),
|
||||
Ordering::Less => Ok(YES),
|
||||
Ordering::Equal => Ok(util::dor(a, b)),
|
||||
Ordering::Equal => Ok(util::dor(stack, a, b)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_dor(_context: &mut Context, subject: Noun) -> jets::Result {
|
||||
pub fn jet_dor(context: &mut Context, subject: Noun) -> jets::Result {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?;
|
||||
let b = slot(sam, 3)?;
|
||||
|
||||
Ok(util::dor(a, b))
|
||||
Ok(util::dor(&mut context.stack, a, b))
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::jets::math::util::lth;
|
||||
use crate::jets::util::slot;
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{Noun, NO, YES};
|
||||
use either::{Left, Right};
|
||||
|
||||
pub fn dor(a: Noun, b: Noun) -> Noun {
|
||||
pub fn dor(stack: &mut NockStack, a: Noun, b: Noun) -> Noun {
|
||||
if unsafe { a.raw_equals(b) } {
|
||||
YES
|
||||
} else {
|
||||
match (a.as_either_atom_cell(), b.as_either_atom_cell()) {
|
||||
(Left(atom_a), Left(atom_b)) => lth(atom_a, atom_b),
|
||||
(Left(atom_a), Left(atom_b)) => lth(stack, atom_a, atom_b),
|
||||
(Left(_), Right(_)) => YES,
|
||||
(Right(_), Left(_)) => NO,
|
||||
(Right(cell_a), Right(cell_b)) => {
|
||||
@ -77,9 +78,9 @@ pub mod util {
|
||||
let a_tail = slot(cell_a.as_noun(), 3).unwrap();
|
||||
let b_tail = slot(cell_b.as_noun(), 3).unwrap();
|
||||
if unsafe { a_head.raw_equals(b_head) } {
|
||||
dor(a_tail, b_tail)
|
||||
dor(stack, a_tail, b_tail)
|
||||
} else {
|
||||
dor(a_head, b_head)
|
||||
dor(stack, a_head, b_head)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,44 +91,47 @@ pub mod util {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::{assert_jet, init_stack, A};
|
||||
use crate::jets::util::test::{assert_jet, init_context, A};
|
||||
use crate::noun::{D, T};
|
||||
use ibig::ubig;
|
||||
|
||||
#[test]
|
||||
fn test_dor() {
|
||||
let s = &mut init_stack();
|
||||
let sam = T(s, &[D(1), D(1)]);
|
||||
assert_jet(s, jet_dor, sam, YES);
|
||||
let c = &mut init_context();
|
||||
|
||||
let a = A(s, &ubig!(_0x3fffffffffffffff));
|
||||
let sam = T(s, &[a, D(1)]);
|
||||
assert_jet(s, jet_dor, sam, NO);
|
||||
let sam = T(&mut c.stack, &[D(1), D(1)]);
|
||||
assert_jet(c, jet_dor, sam, YES);
|
||||
|
||||
let a = A(s, &ubig!(_0x3fffffffffffffff));
|
||||
let sam = T(s, &[a, a]);
|
||||
assert_jet(s, jet_dor, sam, YES);
|
||||
let a = A(&mut c.stack, &ubig!(_0x3fffffffffffffff));
|
||||
let sam = T(&mut c.stack, &[a, D(1)]);
|
||||
assert_jet(c, jet_dor, sam, NO);
|
||||
|
||||
let a = A(&mut c.stack, &ubig!(_0x3fffffffffffffff));
|
||||
let sam = T(&mut c.stack, &[a, a]);
|
||||
assert_jet(c, jet_dor, sam, YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gor() {
|
||||
let s = &mut init_stack();
|
||||
let sam = T(s, &[D(1), D(1)]);
|
||||
assert_jet(s, jet_gor, sam, YES);
|
||||
let c = &mut init_context();
|
||||
|
||||
let a = A(s, &ubig!(_0x3fffffffffffffff));
|
||||
let sam = T(s, &[a, a]);
|
||||
assert_jet(s, jet_gor, sam, YES);
|
||||
let sam = T(&mut c.stack, &[D(1), D(1)]);
|
||||
assert_jet(c, jet_gor, sam, YES);
|
||||
|
||||
let a = A(&mut c.stack, &ubig!(_0x3fffffffffffffff));
|
||||
let sam = T(&mut c.stack, &[a, a]);
|
||||
assert_jet(c, jet_gor, sam, YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mor() {
|
||||
let s = &mut init_stack();
|
||||
let sam = T(s, &[D(1), D(1)]);
|
||||
assert_jet(s, jet_mor, sam, YES);
|
||||
let c = &mut init_context();
|
||||
|
||||
let a = A(s, &ubig!(_0x3fffffffffffffff));
|
||||
let sam = T(s, &[a, a]);
|
||||
assert_jet(s, jet_mor, sam, YES);
|
||||
let sam = T(&mut c.stack, &[D(1), D(1)]);
|
||||
assert_jet(c, jet_mor, sam, YES);
|
||||
|
||||
let a = A(&mut c.stack, &ubig!(_0x3fffffffffffffff));
|
||||
let sam = T(&mut c.stack, &[a, a]);
|
||||
assert_jet(c, jet_mor, sam, YES);
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,9 @@ pub fn jet_lent(_context: &mut Context, subject: Noun) -> Result {
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::Noun;
|
||||
use crate::noun::{Noun, D};
|
||||
|
||||
pub fn lent(tape: Noun) -> Result<usize, JetErr> {
|
||||
let mut len = 0usize;
|
||||
@ -24,7 +25,7 @@ pub mod util {
|
||||
if atom.as_bitslice().first_one().is_none() {
|
||||
break;
|
||||
} else {
|
||||
return Err(JetErr::Deterministic);
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
}
|
||||
let cell = list.as_cell()?;
|
||||
@ -39,20 +40,22 @@ pub mod util {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack};
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::{D, T};
|
||||
|
||||
#[test]
|
||||
fn test_lent() {
|
||||
let s = &mut init_stack();
|
||||
assert_jet(s, jet_lent, D(0), D(0));
|
||||
let sam = T(s, &[D(1), D(2), D(3), D(0)]);
|
||||
assert_jet(s, jet_lent, sam, D(3));
|
||||
let sam = T(s, &[D(3), D(2), D(1), D(0)]);
|
||||
assert_jet(s, jet_lent, sam, D(3));
|
||||
assert_jet_err(s, jet_lent, D(1), JetErr::Deterministic);
|
||||
let sam = T(s, &[D(3), D(2), D(1)]);
|
||||
assert_jet_err(s, jet_lent, sam, JetErr::Deterministic);
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet(c, jet_lent, D(0), D(0));
|
||||
let sam = T(&mut c.stack, &[D(1), D(2), D(3), D(0)]);
|
||||
assert_jet(c, jet_lent, sam, D(3));
|
||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1), D(0)]);
|
||||
assert_jet(c, jet_lent, sam, D(3));
|
||||
assert_jet_err(c, jet_lent, D(1), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1)]);
|
||||
assert_jet_err(c, jet_lent, sam, JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
/** Tree jets
|
||||
*/
|
||||
use crate::interpreter::Context;
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::JetErr::*;
|
||||
use crate::jets::Result;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{Noun, D};
|
||||
|
||||
crate::gdb!();
|
||||
@ -15,7 +14,7 @@ pub fn jet_cap(_context: &mut Context, subject: Noun) -> Result {
|
||||
|
||||
unsafe {
|
||||
if met < 2 {
|
||||
Err(Deterministic)
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else if *(tom.as_bitslice().get_unchecked(met - 2)) {
|
||||
Ok(D(3))
|
||||
} else {
|
||||
@ -31,7 +30,7 @@ pub fn jet_mas(context: &mut Context, subject: Noun) -> Result {
|
||||
let met = met(0, tom);
|
||||
|
||||
if met < 2 {
|
||||
Err(Deterministic)
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else {
|
||||
let c = bex(stack, met - 1);
|
||||
let d = bex(stack, met - 2);
|
||||
@ -44,39 +43,40 @@ pub fn jet_mas(context: &mut Context, subject: Noun) -> Result {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack};
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::D;
|
||||
|
||||
#[test]
|
||||
fn test_cap() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet_err(s, jet_cap, D(0), JetErr::Deterministic);
|
||||
assert_jet_err(s, jet_cap, D(1), JetErr::Deterministic);
|
||||
assert_jet_err(c, jet_cap, D(0), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
assert_jet_err(c, jet_cap, D(1), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
|
||||
assert_jet(s, jet_cap, D(2), D(2));
|
||||
assert_jet(s, jet_cap, D(3), D(3));
|
||||
assert_jet(s, jet_cap, D(4), D(2));
|
||||
assert_jet(s, jet_cap, D(5), D(2));
|
||||
assert_jet(s, jet_cap, D(6), D(3));
|
||||
assert_jet(s, jet_cap, D(7), D(3));
|
||||
assert_jet(s, jet_cap, D(8), 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(4), D(2));
|
||||
assert_jet(c, jet_cap, D(5), D(2));
|
||||
assert_jet(c, jet_cap, D(6), D(3));
|
||||
assert_jet(c, jet_cap, D(7), D(3));
|
||||
assert_jet(c, jet_cap, D(8), D(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mas() {
|
||||
let s = &mut init_stack();
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet_err(s, jet_mas, D(0), JetErr::Deterministic);
|
||||
assert_jet_err(s, jet_mas, D(1), JetErr::Deterministic);
|
||||
assert_jet_err(c, jet_mas, D(0), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
assert_jet_err(c, jet_mas, D(1), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
|
||||
assert_jet(s, jet_mas, D(2), D(1));
|
||||
assert_jet(s, jet_mas, D(3), D(1));
|
||||
assert_jet(s, jet_mas, D(4), D(2));
|
||||
assert_jet(s, jet_mas, D(5), D(3));
|
||||
assert_jet(s, jet_mas, D(6), D(2));
|
||||
assert_jet(s, jet_mas, D(7), D(3));
|
||||
assert_jet(s, jet_mas, D(8), D(4));
|
||||
assert_jet(c, jet_mas, D(2), D(1));
|
||||
assert_jet(c, jet_mas, D(3), D(1));
|
||||
assert_jet(c, jet_mas, D(4), D(2));
|
||||
assert_jet(c, jet_mas, D(5), D(3));
|
||||
assert_jet(c, jet_mas, D(6), D(2));
|
||||
assert_jet(c, jet_mas, D(7), D(3));
|
||||
assert_jet(c, jet_mas, D(8), D(4));
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use crate::mem::{NockStack, Preserve};
|
||||
use crate::noun::{Noun, Slots};
|
||||
use std::ptr::{copy_nonoverlapping, null_mut};
|
||||
|
||||
/// key = formula
|
||||
pub struct Warm(Hamt<WarmEntry>);
|
||||
|
||||
impl Preserve for Warm {
|
||||
@ -129,6 +130,9 @@ impl Warm {
|
||||
warm
|
||||
}
|
||||
|
||||
/// Walk through the linked list of WarmEntry objects and do a partial check
|
||||
/// against the subject using Batteries (walk to root of parent batteries).
|
||||
/// If there's a match, then we've found a valid jet.
|
||||
pub fn find_jet(&mut self, stack: &mut NockStack, s: &mut Noun, f: &mut Noun) -> Option<Jet> {
|
||||
let warm_it = self.0.lookup(stack, f)?;
|
||||
for (_path, batteries, jet) in warm_it {
|
||||
|
@ -4,7 +4,8 @@ use ares::jets::cold::Cold;
|
||||
use ares::jets::hot::Hot;
|
||||
use ares::jets::warm::Warm;
|
||||
use ares::mem::NockStack;
|
||||
use ares::noun::{IndirectAtom, Noun};
|
||||
use ares::newt::Newt;
|
||||
use ares::noun::{IndirectAtom, Noun, D};
|
||||
use ares::serf::serf;
|
||||
use ares::serialization::{cue, jam};
|
||||
use memmap::Mmap;
|
||||
@ -65,24 +66,26 @@ fn main() -> io::Result<()> {
|
||||
let input_cell = input
|
||||
.as_cell()
|
||||
.expect("Input must be jam of subject/formula pair");
|
||||
let mut cache = Hamt::<Noun>::new();
|
||||
let mut cold = Cold::new(&mut stack);
|
||||
let mut warm = Warm::new();
|
||||
let newt = Newt::new_mock();
|
||||
let cache = Hamt::<Noun>::new();
|
||||
let cold = Cold::new(&mut stack);
|
||||
let warm = Warm::new();
|
||||
let hot = Hot::init(&mut stack);
|
||||
let mut context = Context {
|
||||
stack: &mut stack,
|
||||
newt: None,
|
||||
cache: &mut cache,
|
||||
cold: &mut cold,
|
||||
warm: &mut warm,
|
||||
hot: &hot,
|
||||
stack,
|
||||
newt,
|
||||
cache,
|
||||
cold,
|
||||
warm,
|
||||
hot,
|
||||
scry_stack: D(0),
|
||||
};
|
||||
let result =
|
||||
interpret(&mut context, input_cell.head(), input_cell.tail()).expect("nock failed");
|
||||
if let Ok(atom) = result.as_atom() {
|
||||
println!("Result: {}", atom);
|
||||
}
|
||||
let jammed_result = jam(&mut stack, result);
|
||||
let jammed_result = jam(&mut context.stack, result);
|
||||
let f_out = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
|
@ -979,6 +979,77 @@ pub unsafe fn unifying_equality(stack: &mut NockStack, a: *mut Noun, b: *mut Nou
|
||||
(*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(
|
||||
stack: &NockStack,
|
||||
a: *const u64,
|
||||
@ -1118,3 +1189,46 @@ 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));
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +75,13 @@ impl Newt {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_mock() -> Newt {
|
||||
Newt {
|
||||
input: std::fs::File::open("/dev/null").expect("newt: could not open /dev/null"),
|
||||
output: std::fs::File::open("/dev/null").expect("newt: could not open /dev/null"),
|
||||
}
|
||||
}
|
||||
|
||||
/** Write a noun to the newt.
|
||||
*
|
||||
* NB: we write 64-bit words, while vere writes bytes. The extra zero bytes shouldn't be a
|
||||
|
@ -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 either::{Either, Left, Right};
|
||||
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 private::RawSlots for Noun {
|
||||
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::hamt::Hamt;
|
||||
use crate::interpreter;
|
||||
use crate::interpreter::{inc, interpret, Tone};
|
||||
use crate::interpreter::{inc, interpret, Error};
|
||||
use crate::jets::cold::Cold;
|
||||
use crate::jets::hot::Hot;
|
||||
use crate::jets::nock::util::mook;
|
||||
@ -30,13 +30,7 @@ struct Context {
|
||||
snapshot: DoubleJam,
|
||||
arvo: Noun,
|
||||
mug: u32,
|
||||
stack: NockStack,
|
||||
newt: Newt,
|
||||
cache: Hamt<Noun>,
|
||||
// XX: persistent memo cache
|
||||
cold: Cold,
|
||||
warm: Warm,
|
||||
hot: Hot,
|
||||
nock_context: interpreter::Context,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
@ -55,51 +49,23 @@ impl Context {
|
||||
let (epoch, event_num, arvo) = snapshot.load(&mut stack).unwrap_or((0, 0, D(0)));
|
||||
let mug = mug_u32(&mut stack, arvo);
|
||||
|
||||
let nock_context = interpreter::Context {
|
||||
stack,
|
||||
newt,
|
||||
cold,
|
||||
warm,
|
||||
hot,
|
||||
cache,
|
||||
scry_stack: D(0),
|
||||
};
|
||||
|
||||
Context {
|
||||
epoch,
|
||||
event_num,
|
||||
snapshot,
|
||||
arvo,
|
||||
mug,
|
||||
stack,
|
||||
newt,
|
||||
cache,
|
||||
cold,
|
||||
warm,
|
||||
hot,
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Getters
|
||||
//
|
||||
|
||||
pub fn epoch(&self) -> u64 {
|
||||
self.epoch
|
||||
}
|
||||
|
||||
pub fn event_num(&self) -> u64 {
|
||||
self.event_num
|
||||
}
|
||||
|
||||
pub fn arvo(&self) -> Noun {
|
||||
self.arvo
|
||||
}
|
||||
|
||||
pub fn stack_as_mut(&mut self) -> &mut NockStack {
|
||||
&mut self.stack
|
||||
}
|
||||
|
||||
pub fn for_interpreter(&mut self) -> interpreter::Context {
|
||||
self.cache = Hamt::<Noun>::new();
|
||||
|
||||
interpreter::Context {
|
||||
stack: &mut self.stack,
|
||||
newt: Some(&mut self.newt),
|
||||
cache: &mut self.cache,
|
||||
cold: &mut self.cold,
|
||||
warm: &mut self.warm,
|
||||
hot: &self.hot,
|
||||
nock_context,
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,8 +77,9 @@ impl Context {
|
||||
// XX: assert event numbers are continuous
|
||||
self.arvo = new_arvo;
|
||||
self.event_num = new_event_num;
|
||||
self.snapshot.save(&mut self.stack, &mut self.arvo);
|
||||
self.mug = mug_u32(&mut self.stack, self.arvo);
|
||||
self.snapshot
|
||||
.save(&mut self.nock_context.stack, &mut self.arvo);
|
||||
self.mug = mug_u32(&mut self.nock_context.stack, self.arvo);
|
||||
}
|
||||
|
||||
//
|
||||
@ -121,7 +88,7 @@ impl Context {
|
||||
|
||||
pub fn sync(&mut self) {
|
||||
self.snapshot
|
||||
.sync(&mut self.stack, self.epoch, self.event_num);
|
||||
.sync(&mut self.nock_context.stack, self.epoch, self.event_num);
|
||||
}
|
||||
|
||||
//
|
||||
@ -129,43 +96,65 @@ impl Context {
|
||||
//
|
||||
|
||||
pub fn next(&mut self) -> Option<Noun> {
|
||||
self.newt.next(&mut self.stack)
|
||||
self.nock_context.newt.next(&mut self.nock_context.stack)
|
||||
}
|
||||
|
||||
pub fn ripe(&mut self) {
|
||||
self.newt
|
||||
.ripe(&mut self.stack, self.event_num, self.mug as u64);
|
||||
self.nock_context.newt.ripe(
|
||||
&mut self.nock_context.stack,
|
||||
self.event_num,
|
||||
self.mug as u64,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn live(&mut self) {
|
||||
self.newt.live(&mut self.stack);
|
||||
self.nock_context.newt.live(&mut self.nock_context.stack);
|
||||
}
|
||||
|
||||
pub fn peek_done(&mut self, dat: Noun) {
|
||||
self.newt.peek_done(&mut self.stack, dat);
|
||||
self.nock_context
|
||||
.newt
|
||||
.peek_done(&mut self.nock_context.stack, dat);
|
||||
}
|
||||
|
||||
pub fn play_done(&mut self) {
|
||||
self.newt.play_done(&mut self.stack, self.mug as u64);
|
||||
self.nock_context
|
||||
.newt
|
||||
.play_done(&mut self.nock_context.stack, self.mug as u64);
|
||||
}
|
||||
|
||||
pub fn play_bail(&mut self, dud: Noun) {
|
||||
self.newt
|
||||
.play_bail(&mut self.stack, self.event_num, self.mug as u64, dud);
|
||||
self.nock_context.newt.play_bail(
|
||||
&mut self.nock_context.stack,
|
||||
self.event_num,
|
||||
self.mug as u64,
|
||||
dud,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn work_done(&mut self, fec: Noun) {
|
||||
self.newt
|
||||
.work_done(&mut self.stack, self.event_num, self.mug as u64, fec);
|
||||
self.nock_context.newt.work_done(
|
||||
&mut self.nock_context.stack,
|
||||
self.event_num,
|
||||
self.mug as u64,
|
||||
fec,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn work_swap(&mut self, job: Noun, fec: Noun) {
|
||||
self.newt
|
||||
.work_swap(&mut self.stack, self.event_num, self.mug as u64, job, fec);
|
||||
self.nock_context.newt.work_swap(
|
||||
&mut self.nock_context.stack,
|
||||
self.event_num,
|
||||
self.mug as u64,
|
||||
job,
|
||||
fec,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn work_bail(&mut self, lud: Noun) {
|
||||
self.newt.work_bail(&mut self.stack, lud);
|
||||
self.nock_context
|
||||
.newt
|
||||
.work_bail(&mut self.nock_context.stack, lud);
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,8 +192,11 @@ pub fn serf() -> io::Result<()> {
|
||||
|
||||
// Can't use for loop because it borrows newt
|
||||
while let Some(writ) = context.next() {
|
||||
// XX: probably want to bookend this logic frame_push / frame_pop
|
||||
// preserve jet state and persistent cache, lose everything else
|
||||
// Reset the local cache and scry handler stack
|
||||
context.nock_context.cache = Hamt::<Noun>::new();
|
||||
context.nock_context.scry_stack = D(0);
|
||||
context.nock_context.stack.frame_push(0);
|
||||
|
||||
let tag = slot(writ, 2)?.as_direct().unwrap();
|
||||
match tag.data() {
|
||||
tas!(b"live") => {
|
||||
@ -231,7 +223,7 @@ pub fn serf() -> io::Result<()> {
|
||||
}
|
||||
tas!(b"play") => {
|
||||
let lit = slot(writ, 7)?;
|
||||
if context.epoch() == 0 && context.event_num() == 0 {
|
||||
if context.epoch == 0 && context.event_num == 0 {
|
||||
// apply lifecycle to first batch
|
||||
play_life(&mut context, lit);
|
||||
} else {
|
||||
@ -247,54 +239,64 @@ pub fn serf() -> io::Result<()> {
|
||||
};
|
||||
|
||||
clear_interrupt();
|
||||
|
||||
// Persist data that should survive between events
|
||||
// XX: Such data should go in the PMA once that's available
|
||||
unsafe {
|
||||
let stack = &mut context.nock_context.stack;
|
||||
stack.preserve(&mut context.nock_context.cold);
|
||||
stack.preserve(&mut context.nock_context.warm);
|
||||
stack.frame_pop();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn burn(context: &mut Context, subject: Noun, formula: Noun) -> Result<Noun, Tone> {
|
||||
let burn_context = &mut context.for_interpreter();
|
||||
interpret(burn_context, subject, formula)
|
||||
}
|
||||
|
||||
fn slam(context: &mut Context, axis: u64, ovo: Noun) -> Result<Noun, Tone> {
|
||||
let arvo = context.arvo();
|
||||
let pul = T(context.stack_as_mut(), &[D(9), D(axis), D(0), D(2)]);
|
||||
let sam = T(context.stack_as_mut(), &[D(6), D(0), D(7)]);
|
||||
let fol = T(
|
||||
context.stack_as_mut(),
|
||||
&[D(8), pul, D(9), D(2), D(10), sam, D(0), D(2)],
|
||||
);
|
||||
let sub = T(context.stack_as_mut(), &[arvo, ovo]);
|
||||
burn(context, sub, fol)
|
||||
fn slam(context: &mut Context, axis: u64, ovo: Noun) -> Result<Noun, Error> {
|
||||
let arvo = context.arvo;
|
||||
let stack = &mut context.nock_context.stack;
|
||||
let pul = T(stack, &[D(9), D(axis), D(0), D(2)]);
|
||||
let sam = T(stack, &[D(6), D(0), D(7)]);
|
||||
let fol = T(stack, &[D(8), pul, D(9), D(2), D(10), sam, D(0), D(2)]);
|
||||
let sub = T(stack, &[arvo, ovo]);
|
||||
interpret(&mut context.nock_context, sub, fol)
|
||||
}
|
||||
|
||||
fn goof(context: &mut Context, trace: Noun) -> Noun {
|
||||
let tone = Cell::new(context.stack_as_mut(), D(2), trace);
|
||||
let mook_context = &mut context.for_interpreter();
|
||||
|
||||
let tang = mook(mook_context, tone, false)
|
||||
// XX: trace is a $tang with at least one $tank, which we pick off the top.
|
||||
// Actual input to +mook should be (roll trace weld) ( or (zing trace)).
|
||||
let head = trace.cell().unwrap().head();
|
||||
let tone = Cell::new(&mut context.nock_context.stack, D(2), head);
|
||||
let tang = mook(&mut context.nock_context, tone, false)
|
||||
.expect("serf: goof: +mook crashed on bail")
|
||||
.tail();
|
||||
// XX: noun::Tone or noun::NockErr should use a bail enum system similar to u3m_bail motes;
|
||||
// XX: noun::Error should use a bail enum system similar to u3m_bail motes;
|
||||
// might be able to replace NockErr with mote and map determinism to individual motes;
|
||||
// for, always set to %exit
|
||||
T(mook_context.stack, &[D(tas!(b"exit")), tang])
|
||||
T(&mut context.nock_context.stack, &[D(tas!(b"exit")), tang])
|
||||
}
|
||||
|
||||
/** Run slam, process stack trace to tang if error */
|
||||
fn soft(context: &mut Context, ovo: Noun) -> Result<Noun, Noun> {
|
||||
match slam(context, POKE_AXIS, ovo) {
|
||||
Ok(res) => Ok(res),
|
||||
Err(Tone::Error(_, trace)) => Err(goof(context, trace)),
|
||||
Err(Tone::Blocked(_)) => panic!("soft: blocked err handling unimplemented"),
|
||||
Err(error) => match error {
|
||||
Error::Deterministic(trace) | Error::NonDeterministic(trace) => {
|
||||
Err(goof(context, trace))
|
||||
}
|
||||
Error::ScryBlocked(_) | Error::ScryCrashed(_) => {
|
||||
panic!("serf: soft: .^ invalid outside of virtual Nock")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn play_life(context: &mut Context, eve: Noun) {
|
||||
let sub = T(context.stack_as_mut(), &[D(0), D(3)]);
|
||||
let lyf = T(context.stack_as_mut(), &[D(2), sub, D(0), D(2)]);
|
||||
match burn(context, eve, lyf) {
|
||||
let stack = &mut context.nock_context.stack;
|
||||
let sub = T(stack, &[D(0), D(3)]);
|
||||
let lyf = T(stack, &[D(2), sub, D(0), D(2)]);
|
||||
match interpret(&mut context.nock_context, eve, lyf) {
|
||||
Ok(gat) => {
|
||||
let eved = lent(eve).expect("serf: play: boot event number failure") as u64;
|
||||
let arvo = slot(gat, 7).expect("serf: play: lifecycle didn't return initial Arvo");
|
||||
@ -302,18 +304,20 @@ fn play_life(context: &mut Context, eve: Noun) {
|
||||
context.event_update(eved, arvo);
|
||||
context.play_done();
|
||||
}
|
||||
Err(Tone::Error(_, trace)) => {
|
||||
let goof = goof(context, trace);
|
||||
context.play_bail(goof);
|
||||
}
|
||||
Err(Tone::Blocked(_)) => {
|
||||
panic!("play: blocked err handling unimplemented")
|
||||
}
|
||||
Err(error) => match error {
|
||||
Error::Deterministic(trace) | Error::NonDeterministic(trace) => {
|
||||
let goof = goof(context, trace);
|
||||
context.play_bail(goof);
|
||||
}
|
||||
Error::ScryBlocked(_) | Error::ScryCrashed(_) => {
|
||||
panic!("serf: soft: .^ invalid outside of virtual Nock")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn play_list(context: &mut Context, mut lit: Noun) {
|
||||
let mut eve = context.event_num();
|
||||
let mut eve = context.event_num;
|
||||
while let Ok(cell) = lit.as_cell() {
|
||||
let ovo = cell.head();
|
||||
match soft(context, ovo) {
|
||||
@ -340,7 +344,7 @@ fn work(context: &mut Context, job: Noun) {
|
||||
Ok(res) => {
|
||||
let cell = res.as_cell().expect("serf: work: +slam returned atom");
|
||||
let fec = cell.head();
|
||||
let eve = context.event_num();
|
||||
let eve = context.event_num;
|
||||
|
||||
context.event_update(eve + 1, cell.tail());
|
||||
context.work_done(fec);
|
||||
@ -358,21 +362,19 @@ fn work_swap(context: &mut Context, job: Noun, goof: Noun) {
|
||||
|
||||
clear_interrupt();
|
||||
|
||||
let stack = &mut context.nock_context.stack;
|
||||
// crud = [+(now) [%$ %arvo ~] [%crud goof ovo]]
|
||||
let job_cell = job.as_cell().expect("serf: work: job not a cell");
|
||||
let job_now = job_cell.head().as_atom().expect("serf: work: now not atom");
|
||||
let now = inc(context.stack_as_mut(), job_now).as_noun();
|
||||
let wire = T(context.stack_as_mut(), &[D(0), D(tas!(b"arvo")), D(0)]);
|
||||
let crud = T(
|
||||
context.stack_as_mut(),
|
||||
&[now, wire, D(tas!(b"crud")), goof, job_cell.tail()],
|
||||
);
|
||||
let now = inc(stack, job_now).as_noun();
|
||||
let wire = T(stack, &[D(0), D(tas!(b"arvo")), D(0)]);
|
||||
let crud = T(stack, &[now, wire, D(tas!(b"crud")), goof, job_cell.tail()]);
|
||||
|
||||
match soft(context, crud) {
|
||||
Ok(res) => {
|
||||
let cell = res.as_cell().expect("serf: work: crud +slam returned atom");
|
||||
let fec = cell.head();
|
||||
let eve = context.event_num();
|
||||
let eve = context.event_num;
|
||||
|
||||
context.event_update(eve + 1, cell.tail());
|
||||
context.work_swap(crud, fec);
|
||||
@ -384,8 +386,9 @@ fn work_swap(context: &mut Context, job: Noun, goof: Noun) {
|
||||
}
|
||||
|
||||
fn work_bail(context: &mut Context, goofs: &[Noun]) {
|
||||
let lest = T(context.stack_as_mut(), goofs);
|
||||
let lud = T(context.stack_as_mut(), &[lest, D(0)]);
|
||||
let stack = &mut context.nock_context.stack;
|
||||
let lest = T(stack, goofs);
|
||||
let lud = T(stack, &[lest, D(0)]);
|
||||
context.work_bail(lud);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user