Merge branch 'status' into profile

This commit is contained in:
Alex Shelkovnykov 2023-11-16 12:22:11 +01:00
commit 33186d5789
7 changed files with 124 additions and 95 deletions

View File

@ -12,9 +12,9 @@ edition = "2018"
# Please keep these alphabetized
[dependencies]
ares_macros = { path = "../ares_macros" }
# assert_no_alloc = "1.1.2"
assert_no_alloc = "1.1.2"
# use this when debugging requires allocation (e.g. eprintln)
assert_no_alloc = {version="1.1.2", features=["warn_debug"]}
# assert_no_alloc = {version="1.1.2", features=["warn_debug"]}
bitvec = "1.0.0"
criterion = "0.4"
either = "1.9.0"

View File

@ -49,15 +49,15 @@ pub enum JetErr {
Fail(Error), // Error; do not retry
}
impl From<noun::Error> for JetErr {
fn from(_err: noun::Error) -> Self {
Self::Fail(Error::Deterministic(D(0)))
impl From<Error> for JetErr {
fn from(err: Error) -> Self {
Self::Fail(err)
}
}
impl From<Error> for JetErr {
fn from(e: Error) -> Self {
Self::Fail(e)
impl From<noun::Error> for JetErr {
fn from(_err: noun::Error) -> Self {
Self::Fail(Error::Deterministic(D(0)))
}
}
@ -343,6 +343,14 @@ pub mod util {
}
}
pub fn assert_jet_size(context: &mut Context, jet: Jet, sam: Noun, siz: usize) {
let sam = T(&mut context.stack, &[D(0), sam, D(0)]);
let res = assert_no_alloc(|| jet(context, sam).unwrap());
assert!(res.is_atom(), "jet result not atom");
let res_siz = res.atom().unwrap().size();
assert!(siz == res_siz, "got: {}, need: {}", res_siz, siz);
}
pub fn assert_common_jet(
context: &mut Context,
jet: Jet,
@ -374,5 +382,16 @@ pub mod util {
let sam = T(&mut context.stack, &sam);
assert_jet_err(context, jet, sam, err);
}
pub fn assert_common_jet_size(
context: &mut Context,
jet: Jet,
sam: &[fn(&mut NockStack) -> Noun],
siz: usize,
) {
let sam: Vec<Noun> = sam.iter().map(|f| f(&mut context.stack)).collect();
let sam = T(&mut context.stack, &sam);
assert_jet_size(context, jet, sam, siz)
}
}
}

View File

@ -130,7 +130,7 @@ pub fn jet_lsh(context: &mut Context, subject: Noun) -> Result {
let (bloq, step) = bite(slot(arg, 2)?)?;
let a = slot(arg, 3)?.as_atom()?;
util::lsh(&mut context.stack, bloq, step, a).map(|a| a.as_noun())
util::lsh(&mut context.stack, bloq, step, a)
}
pub fn jet_met(_context: &mut Context, subject: Noun) -> Result {
@ -306,13 +306,11 @@ pub fn jet_mix(context: &mut Context, subject: Noun) -> Result {
}
pub mod util {
use crate::jets;
use crate::jets::util::*;
use crate::jets::JetErr;
use crate::jets::Result;
use crate::mem::NockStack;
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, D, Noun};
use std::cmp;
use std::result;
/// Binary exponent
pub fn bex(stack: &mut NockStack, arg: usize) -> Atom {
@ -327,22 +325,17 @@ pub mod util {
}
}
pub fn lsh(
stack: &mut NockStack,
bloq: usize,
step: usize,
a: Atom,
) -> result::Result<Atom, JetErr> {
pub fn lsh(stack: &mut NockStack, bloq: usize, step: usize, a: Atom) -> Result {
let len = met(bloq, a);
if len == 0 {
return Ok(D(0).as_atom()?);
return Ok(D(0));
}
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(stack, new_size);
chop(bloq, 0, len, step, dest, a.as_bitslice())?;
Ok(atom.normalize_as_atom())
Ok(atom.normalize_as_atom().as_noun())
}
}
@ -358,7 +351,7 @@ pub mod util {
}
}
pub fn rip(stack: &mut NockStack, bloq: usize, step: usize, atom: Atom) -> jets::Result {
pub fn rip(stack: &mut NockStack, bloq: usize, step: usize, atom: Atom) -> Result {
let len = (met(bloq, atom) + step - 1) / step;
let mut list = D(0);
for i in (0..len).rev() {

View File

@ -9,12 +9,12 @@ crate::gdb!();
pub fn jet_flop(context: &mut Context, subject: Noun) -> Result {
let sam = slot(subject, 6)?;
Ok(util::flop(&mut context.stack, sam)?)
util::flop(&mut context.stack, sam)
}
pub fn jet_lent(_context: &mut Context, subject: Noun) -> Result {
let tape = slot(subject, 6)?;
util::lent(tape).map(|x| D(x as u64))
let list = slot(subject, 6)?;
util::lent(list).map(|x| D(x as u64))
}
pub fn jet_zing(context: &mut Context, subject: Noun) -> Result {
@ -26,14 +26,13 @@ pub fn jet_zing(context: &mut Context, subject: Noun) -> Result {
pub mod util {
use crate::interpreter::Error;
use crate::jets;
use crate::jets::JetErr;
use crate::jets::{JetErr, Result};
use crate::mem::NockStack;
use crate::noun::{Cell, Noun, D, T};
use std::result::Result;
use std::result;
/// Reverse order of list
pub fn flop(stack: &mut NockStack, noun: Noun) -> Result<Noun, Error> {
pub fn flop(stack: &mut NockStack, noun: Noun) -> Result {
let mut list = noun;
let mut tsil = D(0);
loop {
@ -49,7 +48,7 @@ pub mod util {
Ok(tsil)
}
pub fn lent(tape: Noun) -> Result<usize, JetErr> {
pub fn lent(tape: Noun) -> result::Result<usize, JetErr> {
let mut len = 0usize;
let mut list = tape;
loop {
@ -68,50 +67,29 @@ pub mod util {
Ok(len)
}
pub fn zing(stack: &mut NockStack, mut list: Noun) -> jets::Result {
pub fn zing(stack: &mut NockStack, mut list: Noun) -> Result {
unsafe {
let (mut new_cell, mut new_memory) = Cell::new_raw_mut(stack);
#[allow(unused_assignments)]
let (mut cell, mut memory) = (new_cell, new_memory);
let mut res: Noun = D(0);
let mut flag = false;
loop {
if list.raw_equals(D(0)) {
break;
}
let mut dest = &mut res as *mut Noun;
while !list.raw_equals(D(0)) {
let pair = list.as_cell()?;
let mut sub_list = pair.head();
loop {
if sub_list.raw_equals(D(0)) {
break;
}
let elem = sub_list.as_cell()?;
let head = elem.head();
if flag {
(new_cell, new_memory) = Cell::new_raw_mut(stack);
(*memory).tail = new_cell.as_noun();
memory = new_memory;
} else {
(cell, memory) = Cell::new_raw_mut(stack);
res = cell.as_noun();
flag = true;
}
(*memory).head = head;
sub_list = elem.tail();
}
let mut sublist = pair.head();
list = pair.tail();
while !sublist.raw_equals(D(0)) {
let it = sublist.as_cell()?;
let i = it.head();
sublist = it.tail();
let (new_cell, new_memory) = Cell::new_raw_mut(stack);
(*new_memory).head = i;
*dest = new_cell.as_noun();
dest = &mut (*new_memory).tail;
}
}
if flag {
(*memory).tail = D(0);
}
*dest = D(0);
Ok(res)
}
}

View File

@ -307,6 +307,7 @@ pub mod util {
}
}
/// Less than
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() {

View File

@ -1,18 +1,17 @@
/** Tree jets
*/
use crate::interpreter::{Context, Error};
use crate::jets::bits;
use crate::jets::math;
use crate::jets::util::slot;
use crate::jets::bits::util::*;
use crate::jets::util::*;
use crate::jets::{JetErr, Result};
use crate::noun::{Noun, D};
use crate::noun::{IndirectAtom, Noun, D};
crate::gdb!();
pub fn jet_cap(_context: &mut Context, subject: Noun) -> Result {
let arg = slot(subject, 6)?;
let tom = arg.as_atom()?;
let met = bits::util::met(0, tom);
let met = met(0, tom);
unsafe {
if met < 2 {
@ -27,43 +26,53 @@ pub fn jet_cap(_context: &mut Context, subject: Noun) -> Result {
pub fn jet_mas(context: &mut Context, subject: Noun) -> Result {
let stack = &mut context.stack;
let arg = slot(subject, 6)?;
let tom = arg.as_atom()?;
let met = bits::util::met(0, tom);
let tom = slot(subject, 6)?.as_atom()?;
let met = met(0, tom);
if met < 2 {
Err(JetErr::Fail(Error::Deterministic(D(0))))
} else {
let c = bits::util::bex(stack, met - 1);
let d = bits::util::bex(stack, met - 2);
let e = math::util::sub(stack, tom, c)?;
Ok(bits::util::con(stack, e, d).as_noun())
let out_bits = met - 1;
let out_words = (out_bits + 63) >> 6;
let (mut indirect_out, out_bs) =
unsafe { IndirectAtom::new_raw_mut_bitslice(stack, out_words) };
out_bs.set(met - 2, true); // Set MSB
if met > 2 {
out_bs[0..(met - 2)].copy_from_bitslice(&tom.as_bitslice()[0..(met - 2)]);
};
unsafe { Ok(indirect_out.normalize_as_atom().as_noun()) }
}
}
pub fn jet_peg(context: &mut Context, subject: Noun) -> Result {
let stack = &mut context.stack;
let arg = slot(subject, 6)?;
let a = slot(arg, 2)?;
let b = slot(arg, 3)?;
let a = slot(arg, 2)?.as_atom()?;
let b = slot(arg, 3)?.as_atom()?;
unsafe {
if a.raw_equals(D(0)) {
if a.as_noun().raw_equals(D(0)) {
return Err(JetErr::Fail(Error::Deterministic(D(0))));
}
// XX: Import jet mistmatch from Vere
if b.raw_equals(D(0)) {
return Err(JetErr::Fail(Error::Deterministic(D(0))));
}
};
};
let c = bits::util::met(0, b.as_atom()?);
let d = c - 1;
let e = bits::util::lsh(stack, 0, d, D(1).as_atom()?)?;
let f = math::util::sub(stack, b.as_atom()?, e)?;
let g = bits::util::lsh(stack, 0, d, a.as_atom()?)?;
Ok(math::util::add(stack, f, g).as_noun())
if b.as_noun().raw_equals(D(0)) {
return Err(JetErr::Fail(Error::Deterministic(D(0))));
};
}
let a_bits = met(0, a);
let b_bits = met(0, b);
let out_bits = a_bits + b_bits - 1;
let out_words = (out_bits + 63) >> 6; // bits to 8-byte words
let (mut indirect_out, out_bs) =
unsafe { IndirectAtom::new_raw_mut_bitslice(stack, out_words) };
out_bs[0..b_bits - 1].copy_from_bitslice(&b.as_bitslice()[0..b_bits - 1]);
out_bs[b_bits - 1..out_bits].copy_from_bitslice(&a.as_bitslice()[0..a_bits]);
unsafe { Ok(indirect_out.normalize_as_atom().as_noun()) }
}
#[cfg(test)]
@ -92,10 +101,18 @@ mod tests {
D(0x4000000000000000)
}
fn atom_64(stack: &mut NockStack) -> Noun {
A(stack, &ubig!(_0x8000000000000000))
}
fn atom_65(stack: &mut NockStack) -> Noun {
A(stack, &ubig!(_0x10000000000000000))
}
fn atom_66(stack: &mut NockStack) -> Noun {
A(stack, &ubig!(_0x20000000000000000))
}
fn pos_2(_stack: &mut NockStack) -> Noun {
D(2)
}
@ -127,10 +144,16 @@ mod tests {
#[test]
fn test_mas() {
let c = &mut init_context();
let a63 = atom_63(&mut c.stack);
let a64 = atom_64(&mut c.stack);
let a65 = atom_65(&mut c.stack);
let a66 = atom_66(&mut c.stack);
// Test invalid input
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))));
// Test direct
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));
@ -138,6 +161,16 @@ mod tests {
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));
// Test indirect
assert_jet(c, jet_mas, a64, a63);
assert_jet(c, jet_mas, a65, a64);
assert_jet(c, jet_mas, a66, a65);
// Test allocation
assert_jet_size(c, jet_mas, D(2), 1_usize);
assert_jet_size(c, jet_mas, a65, 1_usize);
assert_jet_size(c, jet_mas, a66, 2_usize);
}
#[test]
@ -174,5 +207,10 @@ mod tests {
&[atom_65, atom_65],
ubig!(_0x100000000000000000000000000000000),
);
// Test allocation
assert_common_jet_size(c, jet_peg, &[atom_65, atom_1], 2_usize);
assert_common_jet_size(c, jet_peg, &[atom_1, atom_65], 2_usize);
assert_common_jet_size(c, jet_peg, &[atom_65, atom_65], 3_usize);
}
}

View File

@ -40,7 +40,7 @@ const FORWARDING_MASK: u64 = CELL_MASK;
/** Loobeans */
pub const YES: Noun = D(0);
pub const NO: Noun = D(1);
pub const NONE: Noun = unsafe { DirectAtom::new_unchecked(tas!(b"mormagic")).as_noun() };
pub const NONE: Noun = unsafe { DirectAtom::new_unchecked(tas!(b"MORMAGIC")).as_noun() };
#[cfg(feature = "check_acyclic")]
#[macro_export]