sha: various fixes

- make variable names consistent w/ their Hoon counterparts
- fix slice copy bugs
- add tests for cases that weren't caught until live testing
- btree.c change to boot w/ slim.pill
This commit is contained in:
Alex Shelkovnykov 2024-02-07 22:56:38 +09:00
parent dc657deb0b
commit 593e386bc4
7 changed files with 597 additions and 129 deletions

View File

@ -94,6 +94,11 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
1, 1,
jet_lent, jet_lent,
), ),
(
&[K_139, Left(b"one"), Left(b"two"), Left(b"turn")],
1,
jet_turn,
),
( (
&[K_139, Left(b"one"), Left(b"two"), Left(b"zing")], &[K_139, Left(b"one"), Left(b"two"), Left(b"zing")],
1, 1,
@ -344,6 +349,19 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
jet_pfix, jet_pfix,
), ),
// //
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"plug"),
],
1,
jet_plug,
),
//
( (
&[ &[
K_139, K_139,
@ -370,6 +388,34 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
jet_sfix, jet_sfix,
), ),
// //
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"cold"),
Left(b"fun"),
],
1,
jet_cold,
),
//
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"cook"),
Left(b"fun"),
],
1,
jet_cook,
),
//
( (
&[ &[
K_139, K_139,
@ -426,6 +472,20 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
jet_mask, jet_mask,
), ),
// //
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"shim"),
Left(b"fun"),
],
1,
jet_shim,
),
//
( (
&[ &[
K_139, K_139,
@ -440,6 +500,34 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
jet_stag, jet_stag,
), ),
// //
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"stew"),
Left(b"fun"),
],
1,
jet_stew,
),
//
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"stir"),
Left(b"fun"),
],
1,
jet_stir,
),
//
( (
&[ &[
K_139, K_139,

View File

@ -1,9 +1,11 @@
/** Text processing jets /** Text processing jets
*/ */
use crate::interpreter::Context; use crate::interpreter::{interpret, Context, Error};
use crate::jets::util::slot; use crate::jets::util::slot;
use crate::jets::Result; use crate::jets::{JetErr, Result};
use crate::noun::{Noun, D}; use crate::noun::{Cell, Noun, D, T};
use bitvec::order::Lsb0;
use bitvec::slice::BitSlice;
crate::gdb!(); crate::gdb!();
@ -24,6 +26,97 @@ pub fn jet_zing(context: &mut Context, subject: Noun) -> Result {
util::zing(stack, list) util::zing(stack, list)
} }
pub fn jet_turn(context: &mut Context, subject: Noun) -> Result {
let sample = slot(subject, 6)?;
let mut list = slot(sample, 2)?;
let mut gate = slot(sample, 3)?;
let mut gate_battery = slot(gate, 2)?;
let gate_context = slot(gate, 7)?;
let mut res = D(0);
let mut dest: *mut Noun = &mut res; // Mutable pointer because we cannot guarantee initialized
// Since the gate doesn't change, we can do a single jet check and use that through the whole
// loop
if let Some((jet, _path)) = context
.warm
.find_jet(&mut context.stack, &mut gate, &mut gate_battery)
.filter(|(_jet, mut path)| {
// check that 7 is a prefix of the parent battery axis,
// to ensure that the sample (axis 6) is not part of the jet match.
//
// XX TODO this check is pessimized since there could be multiple ways to match the
// jet and we only actually match one of them, but we check all of them and run
// unjetted if any have an axis outside 7.
let axis_7_bits: &BitSlice<u64, Lsb0> = BitSlice::from_element(&7u64);
let batteries_list = context.cold.find(&mut context.stack, &mut path);
let mut ret = true;
for mut batteries in batteries_list {
if let Some((_battery, parent_axis)) = batteries.next() {
let parent_axis_prefix_bits = &parent_axis.as_bitslice()[0..3];
if parent_axis_prefix_bits == axis_7_bits {
continue;
} else {
ret = false;
break;
}
} else {
ret = false;
break;
}
}
ret
})
{
loop {
if let Ok(list_cell) = list.as_cell() {
list = list_cell.tail();
let element_subject = T(
&mut context.stack,
&[gate_battery, list_cell.head(), gate_context],
);
unsafe {
let (new_cell, new_mem) = Cell::new_raw_mut(&mut context.stack);
(*new_mem).head = jet(context, element_subject)?;
*dest = new_cell.as_noun();
dest = &mut (*new_mem).tail;
}
} else {
if unsafe { !list.raw_equals(D(0)) } {
return Err(JetErr::Fail(Error::Deterministic(D(0))));
}
unsafe {
*dest = D(0);
};
return Ok(res);
}
}
} else {
loop {
if let Ok(list_cell) = list.as_cell() {
list = list_cell.tail();
let element_subject = T(
&mut context.stack,
&[gate_battery, list_cell.head(), gate_context],
);
unsafe {
let (new_cell, new_mem) = Cell::new_raw_mut(&mut context.stack);
(*new_mem).head = interpret(context, element_subject, gate_battery)?;
*dest = new_cell.as_noun();
dest = &mut (*new_mem).tail;
}
} else {
if unsafe { !list.raw_equals(D(0)) } {
return Err(JetErr::Fail(Error::Deterministic(D(0))));
}
unsafe {
*dest = D(0);
};
return Ok(res);
}
}
}
}
pub mod util { pub mod util {
use crate::interpreter::Error; use crate::interpreter::Error;
use crate::jets::{JetErr, Result}; use crate::jets::{JetErr, Result};

View File

@ -13,43 +13,42 @@ pub fn jet_shas(context: &mut Context, subject: Noun) -> Result {
let sal = slot(sam, 2)?.as_atom()?; let sal = slot(sam, 2)?.as_atom()?;
let ruz = slot(sam, 3)?.as_atom()?; let ruz = slot(sam, 3)?.as_atom()?;
let sal_bytes = &(sal.as_bytes())[0..met(3, sal)]; // drop trailing zeros
let (mut _salt_ida, salt) = unsafe { IndirectAtom::new_raw_mut_bytes(stack, sal_bytes.len()) };
salt.copy_from_slice(sal_bytes);
unsafe { unsafe {
let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 32); let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 32);
let sal_bytes = &(sal.as_bytes())[0..met(3, sal)]; // drop trailing zeros
let (mut _salt_ida, salt) = IndirectAtom::new_raw_mut_bytes(stack, sal_bytes.len());
salt.copy_from_slice(sal_bytes);
let msg_len = met(3, ruz); let msg_len = met(3, ruz);
if msg_len > 0 { if msg_len > 0 {
let (_msg_ida, message) = IndirectAtom::new_raw_mut_bytes(stack, msg_len); let msg_bytes = &(ruz.as_bytes())[0..msg_len];
message.copy_from_slice(&ruz.as_bytes()[0..msg_len]); let (_msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, msg_bytes.len());
ac_shas(message, salt, out); msg.copy_from_slice(&msg_bytes);
} ac_shas(msg, salt, out);
else { } else {
ac_shas(&mut [], salt, out); ac_shas(&mut [], salt, out);
} }
Ok(out_ida.normalize_as_atom().as_noun()) Ok(out_ida.normalize_as_atom().as_noun())
} }
} }
pub fn jet_shax(context: &mut Context, subject: Noun) -> Result { pub fn jet_shax(context: &mut Context, subject: Noun) -> Result {
let stack = &mut context.stack; let stack = &mut context.stack;
let sam = slot(subject, 6)?; let sam = slot(subject, 6)?;
let msg = sam.as_atom()?; let ruz = sam.as_atom()?;
let len = met(3, msg); let msg_len = met(3, ruz);
unsafe { unsafe {
let (mut ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 32); let (mut ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 32);
if len > 0 { if msg_len > 0 {
let (mut _msg_ida, msg_copy) = IndirectAtom::new_raw_mut_bytes(stack, len); let msg_bytes = &(ruz.as_bytes())[0..msg_len];
msg_copy.copy_from_slice(&msg.as_bytes()[0..len]); let (_msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, msg_bytes.len());
ac_shay(&mut (msg_copy)[0..len], out); msg.copy_from_slice(&msg_bytes);
} ac_shay(msg, out);
else { } else {
ac_shay(&mut [], out); ac_shay(&mut [], out);
} }
@ -60,24 +59,30 @@ pub fn jet_shax(context: &mut Context, subject: Noun) -> Result {
pub fn jet_shay(context: &mut Context, subject: Noun) -> Result { pub fn jet_shay(context: &mut Context, subject: Noun) -> Result {
let stack = &mut context.stack; let stack = &mut context.stack;
let sam = slot(subject, 6)?; let sam = slot(subject, 6)?;
let wid = slot(sam, 2)?.as_atom()?; let len = slot(sam, 2)?.as_atom()?;
let dat = slot(sam, 3)?.as_atom()?; let ruz = slot(sam, 3)?.as_atom()?;
let width = match wid.as_direct() { let length = match len.as_direct() {
Ok(direct) => direct.data() as usize, Ok(direct) => direct.data() as usize,
Err(_) => return Err(JetErr::Fail(Error::NonDeterministic(D(0)))), Err(_) => return Err(JetErr::Fail(Error::NonDeterministic(D(0)))),
}; };
let msg_len = met(3, ruz);
unsafe { unsafe {
let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 32); let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 32);
if width > 0 { if length == 0 {
let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, width); ac_shay(&mut [], out);
msg.copy_from_slice(&dat.as_bytes()[0..width]); } else if msg_len >= length {
let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length);
msg.copy_from_slice(&(ruz.as_bytes())[0..length]);
ac_shay(msg, out);
} else {
let msg_bytes = &(ruz.as_bytes())[0..msg_len];
let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length);
msg[0..msg_len].copy_from_slice(&msg_bytes);
ac_shay(msg, out); ac_shay(msg, out);
} }
else {
ac_shay(&mut [], out);
}
Ok(out_ida.normalize_as_atom().as_noun()) Ok(out_ida.normalize_as_atom().as_noun())
} }
} }
@ -85,51 +90,61 @@ pub fn jet_shay(context: &mut Context, subject: Noun) -> Result {
pub fn jet_shal(context: &mut Context, subject: Noun) -> Result { pub fn jet_shal(context: &mut Context, subject: Noun) -> Result {
let stack = &mut context.stack; let stack = &mut context.stack;
let sam = slot(subject, 6)?; let sam = slot(subject, 6)?;
let wid = slot(sam, 2)?.as_atom()?; let len = slot(sam, 2)?.as_atom()?;
let dat = slot(sam, 3)?.as_atom()?; let ruz = slot(sam, 3)?.as_atom()?;
let width = match wid.as_direct() { let length = match len.as_direct() {
Ok(direct) => direct.data() as usize, Ok(direct) => direct.data() as usize,
Err(_) => return Err(JetErr::Fail(Error::NonDeterministic(D(0)))), Err(_) => return Err(JetErr::Fail(Error::NonDeterministic(D(0)))),
}; };
let msg_len = met(3, ruz);
// let msg_len = met(3, dat);
unsafe { unsafe {
let msg_bytes = &(dat.as_bytes())[0..width]; let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 64);
let (mut ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 64); if length == 0 {
ac_shal(&mut [], out);
if width > 0 { } else if msg_len >= length {
let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, msg_bytes.len()); let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length);
msg.copy_from_slice(msg_bytes); msg.copy_from_slice(&(ruz.as_bytes())[0..length]);
ac_shal(msg, out);
} else {
let msg_bytes = &(ruz.as_bytes())[0..msg_len];
let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length);
msg[0..msg_len].copy_from_slice(&msg_bytes);
ac_shal(msg, out); ac_shal(msg, out);
} }
else {
ac_shal(&mut [], out);
}
Ok(ida.normalize_as_atom().as_noun()) Ok(out_ida.normalize_as_atom().as_noun())
} }
} }
pub fn jet_sha1(context: &mut Context, subject: Noun) -> Result { pub fn jet_sha1(context: &mut Context, subject: Noun) -> Result {
let stack = &mut context.stack; let stack = &mut context.stack;
let sam = slot(subject, 6)?; let sam = slot(subject, 6)?;
let wid = slot(sam, 2)?.as_atom()?; let len = slot(sam, 2)?.as_atom()?;
let dat = slot(sam, 3)?.as_atom()?; let ruz = slot(sam, 3)?.as_atom()?;
let width = match wid.as_direct() { let length = match len.as_direct() {
Ok(direct) => direct.data() as usize, Ok(direct) => direct.data() as usize,
Err(_) => return Err(JetErr::Fail(Error::NonDeterministic(D(0)))), Err(_) => return Err(JetErr::Fail(Error::NonDeterministic(D(0)))),
}; };
let msg_len = met(3, ruz);
unsafe { unsafe {
let msg_bytes = &(dat.as_bytes())[0..width];
let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, msg_bytes.len());
msg.copy_from_slice(msg_bytes);
let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 20); let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 20);
if length == 0 {
ac_sha1(&mut [], out);
} else if msg_len >= length {
let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length);
msg.copy_from_slice(&(ruz.as_bytes())[0..length]);
ac_sha1(msg, out); ac_sha1(msg, out);
} else {
let msg_bytes = &(ruz.as_bytes())[0..msg_len];
let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length);
msg[0..msg_len].copy_from_slice(&msg_bytes);
ac_sha1(msg, out);
}
Ok(out_ida.normalize_as_atom().as_noun()) Ok(out_ida.normalize_as_atom().as_noun())
} }
} }
@ -311,20 +326,20 @@ mod tests {
ubig!(_0x3eda27f97a3238a5817a4147bd31b9632fec7e87d21883ffb0f2855d3cd1d047cee96cd321a9f483dc15570b05e420d607806dd6502854f1bdb8ef7e35e183cf) ubig!(_0x3eda27f97a3238a5817a4147bd31b9632fec7e87d21883ffb0f2855d3cd1d047cee96cd321a9f483dc15570b05e420d607806dd6502854f1bdb8ef7e35e183cf)
); );
let sam = T(&mut c.stack, &[D(1), D(1)]); let sam = T(&mut c.stack, &[D(1), D(0)]);
assert_jet_ubig( assert_jet_ubig(
c, c,
jet_shal, jet_shal,
sam, sam,
ubig!(_0x39e3d936c6e31eaac08fcfcfe7bb443460c61c0bd5b74408c8bcc35a6b8d6f5700bdcddeaa4b466ae65f8fb67f67ca62dc34149e1d44d213ddfbc13668b6547b) ubig!(_0xee1069e3f03884c3e5d457253423844a323c29eb4cde70630b58c3712a804a70221d35d9506e242c9414ff192e283dd6caa4eff86a457baf93d68189024d24b8)
); );
let sam = T(&mut c.stack, &[D(1), D(2)]); let sam = T(&mut c.stack, &[D(0), D(1)]);
assert_jet_ubig( assert_jet_ubig(
c, c,
jet_shal, jet_shal,
sam, sam,
ubig!(_0xcadc698fca01cf2935f760278554b4e61f35453975a5bb45389003159bc8485b7018dd8152d9cc23b6e9dd91b107380b9d14ddbf9cc037ee53a857b6c948b8fa) ubig!(_0x3eda27f97a3238a5817a4147bd31b9632fec7e87d21883ffb0f2855d3cd1d047cee96cd321a9f483dc15570b05e420d607806dd6502854f1bdb8ef7e35e183cf)
); );
let wid = A( let wid = A(
@ -360,20 +375,28 @@ mod tests {
fn test_sha1() { fn test_sha1() {
let c = &mut init_context(); let c = &mut init_context();
let sam = T(&mut c.stack, &[D(1), D(1)]); let sam = T(&mut c.stack, &[D(0), D(0)]);
assert_jet_ubig( assert_jet_ubig(
c, c,
jet_sha1, jet_sha1,
sam, sam,
ubig!(_0xbf8b4530d8d246dd74ac53a13471bba17941dff7), ubig!(_0xda39a3ee5e6b4b0d3255bfef95601890afd80709),
); );
let sam = T(&mut c.stack, &[D(1), D(2)]); let sam = T(&mut c.stack, &[D(1), D(0)]);
assert_jet_ubig( assert_jet_ubig(
c, c,
jet_sha1, jet_sha1,
sam, sam,
ubig!(_0xc4ea21bb365bbeeaf5f2c654883e56d11e43c44e), ubig!(_0x5ba93c9db0cff93f52b521d7420e43f6eda2784f),
);
let sam = T(&mut c.stack, &[D(0), D(1)]);
assert_jet_ubig(
c,
jet_sha1,
sam,
ubig!(_0xda39a3ee5e6b4b0d3255bfef95601890afd80709),
); );
let wid = A( let wid = A(

View File

@ -15,7 +15,7 @@
use crate::interpreter::{Context, Error}; use crate::interpreter::{Context, Error};
use crate::jets::util::*; use crate::jets::util::*;
use crate::jets::{JetErr, Result}; use crate::jets::{JetErr, Result};
use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES}; use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, T};
use either::{Left, Right}; use either::{Left, Right};
use ibig::ops::DivRem; use ibig::ops::DivRem;
use ibig::UBig; use ibig::UBig;
@ -120,21 +120,7 @@ pub fn jet_gte(context: &mut Context, subject: Noun) -> Result {
let a = slot(arg, 2)?.as_atom()?; let a = slot(arg, 2)?.as_atom()?;
let b = slot(arg, 3)?.as_atom()?; let b = slot(arg, 3)?.as_atom()?;
Ok(if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) { Ok(util::gte(stack, a, b))
if a.data() >= b.data() {
YES
} else {
NO
}
} else if a.bit_size() > b.bit_size() {
YES
} else if a.bit_size() < b.bit_size() {
NO
} else if a.as_ubig(stack) >= b.as_ubig(stack) {
YES
} else {
NO
})
} }
pub fn jet_gth(context: &mut Context, subject: Noun) -> Result { pub fn jet_gth(context: &mut Context, subject: Noun) -> Result {
@ -143,21 +129,7 @@ pub fn jet_gth(context: &mut Context, subject: Noun) -> Result {
let a = slot(arg, 2)?.as_atom()?; let a = slot(arg, 2)?.as_atom()?;
let b = slot(arg, 3)?.as_atom()?; let b = slot(arg, 3)?.as_atom()?;
Ok(if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) { Ok(util::gth(stack, a, b))
if a.data() > b.data() {
YES
} else {
NO
}
} else if a.bit_size() > b.bit_size() {
YES
} else if a.bit_size() < b.bit_size() {
NO
} else if a.as_ubig(stack) > b.as_ubig(stack) {
YES
} else {
NO
})
} }
pub fn jet_lte(context: &mut Context, subject: Noun) -> Result { pub fn jet_lte(context: &mut Context, subject: Noun) -> Result {
@ -166,21 +138,7 @@ pub fn jet_lte(context: &mut Context, subject: Noun) -> Result {
let a = slot(arg, 2)?.as_atom()?; let a = slot(arg, 2)?.as_atom()?;
let b = slot(arg, 3)?.as_atom()?; let b = slot(arg, 3)?.as_atom()?;
Ok(if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) { Ok(util::lte(stack, a, b))
if a.data() <= b.data() {
YES
} else {
NO
}
} else if a.bit_size() < b.bit_size() {
YES
} else if a.bit_size() > b.bit_size() {
NO
} 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 {
@ -307,19 +265,88 @@ pub mod util {
} }
} }
/// Less than /// Greater than or equal to (boolean)
pub fn lth(stack: &mut NockStack, a: Atom, b: Atom) -> Noun { pub fn gte_b(stack: &mut NockStack, a: Atom, b: Atom) -> bool {
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) { if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
if a.data() < b.data() { a.data() >= b.data()
} else if a.bit_size() > b.bit_size() {
true
} else if a.bit_size() < b.bit_size() {
false
} else {
a.as_ubig(stack) >= b.as_ubig(stack)
}
}
/// Greater than or equal to
pub fn gte(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
if gte_b(stack, a, b) {
YES YES
} else { } else {
NO NO
} }
} else if a.bit_size() < b.bit_size() { }
YES
/// Greater than (boolean)
pub fn gth_b(stack: &mut NockStack, a: Atom, b: Atom) -> bool {
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
a.data() > b.data()
} else if a.bit_size() > b.bit_size() { } else if a.bit_size() > b.bit_size() {
true
} else if a.bit_size() < b.bit_size() {
false
} else {
a.as_ubig(stack) > b.as_ubig(stack)
}
}
/// Greater than
pub fn gth(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
if gth_b(stack, a, b) {
YES
} else {
NO NO
} else if a.as_ubig(stack) < b.as_ubig(stack) { }
}
/// Less than or equal to (boolean)
pub fn lte_b(stack: &mut NockStack, a: Atom, b: Atom) -> bool {
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
a.data() <= b.data()
} else if a.bit_size() < b.bit_size() {
true
} else if a.bit_size() > b.bit_size() {
false
} else {
a.as_ubig(stack) <= b.as_ubig(stack)
}
}
/// Less than or equal to
pub fn lte(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
if lte_b(stack, a, b) {
YES
} else {
NO
}
}
/// Less than (boolean)
pub fn lth_b(stack: &mut NockStack, a: Atom, b: Atom) -> bool {
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
a.data() < b.data()
} else if a.bit_size() > b.bit_size() {
false
} else if a.bit_size() < b.bit_size() {
true
} else {
a.as_ubig(stack) < b.as_ubig(stack)
}
}
/// Less than
pub fn lth(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
if lth_b(stack, a, b) {
YES YES
} else { } else {
NO NO

View File

@ -1,9 +1,11 @@
/** Parsing jets /** Parsing jets
*/ */
use crate::interpreter::Context; use crate::interpreter::{Context, Error};
use crate::jets::math::util::{gte_b, lte_b, lth_b};
use crate::jets::util::{kick, slam, slot}; use crate::jets::util::{kick, slam, slot};
use crate::jets::Result; use crate::jets::{JetErr, Result};
use crate::noun::{Noun, D, T}; use crate::noun::{Noun, D, T};
use either::{Left, Right};
crate::gdb!(); crate::gdb!();
@ -177,6 +179,38 @@ pub fn jet_pfix(context: &mut Context, subject: Noun) -> Result {
Ok(T(&mut context.stack, &[arg, q_yit])) Ok(T(&mut context.stack, &[arg, q_yit]))
} }
pub fn jet_plug(context: &mut Context, subject: Noun) -> Result {
let vex = slot(subject, 12)?.as_cell()?;
let sab = slot(subject, 13)?;
let p_vex = vex.head();
let q_vex = vex.tail();
if unsafe { q_vex.raw_equals(D(0)) } {
Ok(vex.as_noun())
} else {
let uq_vex = q_vex.as_cell()?.tail().as_cell()?;
let puq_vex = uq_vex.head();
let quq_vex = uq_vex.tail();
let yit = slam(context, sab, quq_vex)?.as_cell()?;
let p_yit = yit.head();
let q_yit = yit.tail();
let yur = util::last(p_vex, p_yit)?;
if unsafe { q_yit.raw_equals(D(0)) } {
Ok(T(&mut context.stack, &[yur, D(0)]))
} else {
let uq_yit = q_yit.as_cell()?.tail().as_cell()?;
let puq_yit = uq_yit.head();
let quq_yit = uq_yit.tail();
let inner = T(&mut context.stack, &[puq_vex, puq_yit]);
Ok(T(&mut context.stack, &[yur, D(0), inner, quq_yit]))
}
}
}
pub fn jet_pose(context: &mut Context, subject: Noun) -> Result { pub fn jet_pose(context: &mut Context, subject: Noun) -> Result {
let vex = slot(subject, 12)?.as_cell()?; let vex = slot(subject, 12)?.as_cell()?;
let sab = slot(subject, 13)?; let sab = slot(subject, 13)?;
@ -229,6 +263,47 @@ pub fn jet_sfix(context: &mut Context, subject: Noun) -> Result {
// Rule Builders // Rule Builders
// //
pub fn jet_cold(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?;
let van = slot(subject, 7)?;
let cus = slot(van, 12)?;
let sef = slot(van, 13)?;
let vex = slam(context, sef, tub)?.as_cell()?;
let p_vex = vex.head();
let q_vex = vex.tail();
if unsafe { q_vex.raw_equals(D(0)) } {
Ok(vex.as_noun())
} else {
let quq_vex = q_vex.as_cell()?.tail().as_cell()?.tail();
Ok(T(&mut context.stack, &[p_vex, D(0), cus, quq_vex]))
}
}
pub fn jet_cook(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?;
let van = slot(subject, 7)?;
let poq = slot(van, 12)?;
let sef = slot(van, 13)?;
let vex = slam(context, sef, tub)?.as_cell()?;
let p_vex = vex.head();
let q_vex = vex.tail();
if unsafe { q_vex.raw_equals(D(0)) } {
Ok(vex.as_noun())
} else {
let uq_vex = q_vex.as_cell()?.tail().as_cell()?;
let puq_vex = uq_vex.head();
let quq_vex = uq_vex.tail();
let wag = slam(context, poq, puq_vex)?;
Ok(T(&mut context.stack, &[p_vex, D(0), wag, quq_vex]))
}
}
pub fn jet_easy(context: &mut Context, subject: Noun) -> Result { pub fn jet_easy(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?; let tub = slot(subject, 6)?;
let van = slot(subject, 7)?; let van = slot(subject, 7)?;
@ -307,6 +382,35 @@ pub fn jet_mask(context: &mut Context, subject: Noun) -> Result {
util::fail(context, p_tub) util::fail(context, p_tub)
} }
pub fn jet_shim(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?.as_cell()?;
let van = slot(subject, 7)?;
let zep = slot(van, 6)?.as_cell()?;
let p_tub = tub.head();
let q_tub = tub.tail();
if unsafe { q_tub.raw_equals(D(0)) } {
util::fail(context, p_tub)
} else {
let p_zep = zep.head();
let q_zep = zep.tail();
let iq_tub = q_tub.as_cell()?.head();
if let (Some(p_zep_d), Some(q_zep_d), Some(iq_tub_d)) =
(p_zep.direct(), q_zep.direct(), iq_tub.direct())
{
if (iq_tub_d.data() >= p_zep_d.data()) && (iq_tub_d.data() <= q_zep_d.data()) {
util::next(context, tub.as_noun())
} else {
util::fail(context, p_tub)
}
} else {
Err(JetErr::Fail(Error::NonDeterministic(D(0))))
}
}
}
pub fn jet_stag(context: &mut Context, subject: Noun) -> Result { pub fn jet_stag(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?; let tub = slot(subject, 6)?;
let van = slot(subject, 7)?; let van = slot(subject, 7)?;
@ -329,6 +433,139 @@ pub fn jet_stag(context: &mut Context, subject: Noun) -> Result {
} }
} }
pub fn jet_stew(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?.as_cell()?;
let con = slot(subject, 7)?;
let mut hel = slot(con, 2)?;
let p_tub = tub.head();
let q_tub = tub.tail();
if unsafe { q_tub.raw_equals(D(0)) } {
return util::fail(context, p_tub);
}
let iq_tub = q_tub.as_cell()?.head().as_atom()?;
if !iq_tub.is_direct() {
// Character cannot be encoded using 8 bytes = computibilty error
return Err(JetErr::Fail(Error::NonDeterministic(D(0))));
}
loop {
if unsafe { hel.raw_equals(D(0)) } {
return util::fail(context, p_tub);
} else {
let n_hel = slot(hel, 2)?.as_cell()?;
let l_hel = slot(hel, 6)?;
let r_hel = slot(hel, 7)?;
let pn_hel = n_hel.head();
let qn_hel = n_hel.tail();
let bit = match pn_hel.as_either_atom_cell() {
Left(atom) => match atom.as_either() {
Left(direct) => iq_tub.as_direct()?.data() == direct.data(),
Right(_) => {
// Character cannot be encoded using 8 bytes = computibilty error
return Err(JetErr::Fail(Error::NonDeterministic(D(0))));
}
},
Right(cell) => {
let hpn_hel = cell.head().as_atom()?;
let tpn_hel = cell.tail().as_atom()?;
match (hpn_hel.as_either(), tpn_hel.as_either()) {
(Left(_), Left(_)) => {
gte_b(&mut context.stack, iq_tub, hpn_hel)
&& lte_b(&mut context.stack, iq_tub, tpn_hel)
}
_ => {
// XX: Fixes jet mismatch in Vere
// Character cannot be encoded using 8 bytes = computibilty error
return Err(JetErr::Fail(Error::NonDeterministic(D(0))));
}
}
}
};
if bit {
return slam(context, qn_hel, tub.as_noun());
} else {
let wor = match pn_hel.as_either_atom_cell() {
Left(atom) => atom,
Right(cell) => cell.head().as_atom()?,
};
if lth_b(&mut context.stack, iq_tub, wor) {
hel = l_hel;
} else {
hel = r_hel;
}
}
}
}
}
// +$ edge [p=hair q=(unit [p=* q=nail])]
#[derive(Copy, Clone)]
struct StirPair {
pub har: Noun, // p.edge
pub res: Noun, // p.u.q.edge
}
pub fn jet_stir(context: &mut Context, subject: Noun) -> Result {
unsafe {
context.with_stack_frame(0, |context| {
let mut tub = slot(subject, 6)?;
let van = slot(subject, 7)?;
let rud = slot(van, 12)?;
let raq = slot(van, 26)?;
let fel = slot(van, 27)?;
// initial accumulator (deconstructed)
let mut p_wag: Noun;
let mut puq_wag: Noun;
let quq_wag: Noun;
// push incremental, succesful [fel] parse results onto stack
{
let vex = slam(context, fel, tub)?.as_cell()?;
let mut p_vex = vex.head();
let mut q_vex = vex.tail();
while !q_vex.raw_equals(D(0)) {
let puq_vex = slot(q_vex, 6)?;
let quq_vex = slot(q_vex, 7)?;
*(context.stack.push::<StirPair>()) = StirPair {
har: p_vex,
res: puq_vex,
};
tub = quq_vex;
let vex = slam(context, fel, tub)?.as_cell()?;
p_vex = vex.head();
q_vex = vex.tail();
}
p_wag = p_vex;
puq_wag = rud;
quq_wag = tub;
}
// unwind the stack, folding parse results into [wag] by way of [raq]
while !context.stack.stack_is_empty() {
let par_u = *(context.stack.top::<StirPair>());
p_wag = util::last(par_u.har, p_wag)?;
let sam = T(&mut context.stack, &[par_u.res, puq_wag]);
puq_wag = slam(context, raq, sam)?;
context.stack.pop::<StirPair>();
}
let res = T(&mut context.stack, &[p_wag, D(0), puq_wag, quq_wag]);
Ok(res)
})
}
}
pub mod util { pub mod util {
use crate::interpreter::{inc, Context}; use crate::interpreter::{inc, Context};
use crate::jets::Result; use crate::jets::Result;
@ -339,14 +576,14 @@ pub mod util {
let zyl = zyc.as_cell()?; let zyl = zyc.as_cell()?;
let nal = naz.as_cell()?; let nal = naz.as_cell()?;
let zyll = zyl.head().as_direct()?.data(); let p_zyc = zyl.head().as_direct()?.data();
let zylc = zyl.tail().as_direct()?.data(); let q_zyc = zyl.tail().as_direct()?.data();
let nall = nal.head().as_direct()?.data(); let p_naz = nal.head().as_direct()?.data();
let nalc = nal.tail().as_direct()?.data(); let q_naz = nal.tail().as_direct()?.data();
match zyll.cmp(&nall) { match p_zyc.cmp(&p_naz) {
Ordering::Equal => { Ordering::Equal => {
if zylc > nalc { if q_zyc > q_naz {
Ok(zyc) Ok(zyc)
} else { } else {
Ok(naz) Ok(naz)

View File

@ -143,7 +143,7 @@ impl Context {
snapshot: Option<Snapshot>, snapshot: Option<Snapshot>,
constant_hot_state: &[HotEntry], constant_hot_state: &[HotEntry],
) -> Self { ) -> Self {
let mut stack = NockStack::new(1024 << 10 << 10, 0); let mut stack = NockStack::new(4096 << 10 << 10, 0);
let newt = Newt::new(); let newt = Newt::new();
let cache = Hamt::<Noun>::new(&mut stack); let cache = Hamt::<Noun>::new(&mut stack);
@ -419,7 +419,7 @@ fn peek(context: &mut Context, ovo: Noun) -> Noun {
} }
fn goof(context: &mut Context, traces: Noun) -> Noun { fn goof(context: &mut Context, traces: Noun) -> Noun {
let trace = zing(&mut context.nock_context.stack, traces).unwrap(); let trace = zing(&mut context.nock_context.stack, traces).expect("serf: goof: zing failed");
let tone = Cell::new(&mut context.nock_context.stack, D(2), trace); let tone = Cell::new(&mut context.nock_context.stack, D(2), trace);
let tang = mook(&mut context.nock_context, tone, false) let tang = mook(&mut context.nock_context, tone, false)
.expect("serf: goof: +mook crashed on bail") .expect("serf: goof: +mook crashed on bail")

View File

@ -122,7 +122,7 @@ off2addr(vaof_t off)
#define BT_NUMMETAS 2 /* 2 metapages */ #define BT_NUMMETAS 2 /* 2 metapages */
#define BT_META_SECTION_WIDTH (BT_NUMMETAS * BT_PAGESIZE) #define BT_META_SECTION_WIDTH (BT_NUMMETAS * BT_PAGESIZE)
#define BT_ADDRSIZE (BT_PAGESIZE << BT_PAGEWORD) #define BT_ADDRSIZE (BT_PAGESIZE << BT_PAGEWORD)
#define PMA_GROW_SIZE_p (1024) #define PMA_GROW_SIZE_p (10000000)
#define PMA_GROW_SIZE_b (BT_PAGESIZE * PMA_GROW_SIZE_p) #define PMA_GROW_SIZE_b (BT_PAGESIZE * PMA_GROW_SIZE_p)
#define BT_NOPAGE 0 #define BT_NOPAGE 0