[jets] add con jet

This commit is contained in:
Philip Monk 2023-02-14 20:39:27 -07:00
parent 8946568a08
commit f5d0bea6ac
2 changed files with 64 additions and 24 deletions

View File

@ -42,6 +42,7 @@ pub fn get_jet(jet_name: Noun) -> Result<Jet, ()> {
tas!(b"bex") => Ok(jet_bex),
tas!(b"lsh") => Ok(jet_lsh),
tas!(b"rsh") => Ok(jet_rsh),
tas!(b"con") => Ok(jet_con),
tas!(b"cut") => Ok(jet_cut),
tas!(b"met") => Ok(jet_met),
tas!(b"mug") => Ok(jet_mug),

View File

@ -1,8 +1,3 @@
use crate::interpreter::raw_slot;
use crate::jets::{JetErr, JetErr::*};
use crate::mem::NockStack;
use crate::mug::mug;
use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
/** Math jets
*
* We use ibig for math operations. This is a pure rust library, and it is very convenient to use.
@ -17,11 +12,17 @@ use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YE
* 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::raw_slot;
use crate::jets::{JetErr, JetErr::*};
use crate::mem::NockStack;
use crate::mug::mug;
use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
use bitvec::prelude::{BitSlice, Lsb0};
use either::Either::*;
use ibig::ops::DivRem;
use ibig::UBig;
use num_traits::identities::One;
use std::cmp;
pub fn jet_dec(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
@ -60,25 +61,6 @@ pub fn jet_dec(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_cut(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 {
return Err(Deterministic);
}
let start = raw_slot(arg, 12).as_direct()?.data() as usize;
let run = raw_slot(arg, 13).as_direct()?.data() as usize;
let atom = raw_slot(arg, 7).as_atom()?;
let new_indirect = unsafe {
let (mut new_indirect, new_slice) =
IndirectAtom::new_raw_mut_bitslice(stack, ((run << bloq) + 63) >> 6);
chop(bloq, start, run, 0, new_slice, atom.as_bitslice())?;
new_indirect.normalize_as_atom()
};
Ok(new_indirect.as_noun())
}
pub fn jet_add(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
@ -380,6 +362,41 @@ pub fn jet_rsh(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_con(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
let new_size = cmp::max(a.size(), b.size());
unsafe {
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(stack, new_size);
let a_bit = a.as_bitslice();
dest[..a_bit.len()].copy_from_bitslice(a_bit);
*dest |= b.as_bitslice();
Ok(atom.normalize_as_atom().as_noun())
}
}
pub fn jet_cut(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 {
return Err(Deterministic);
}
let start = raw_slot(arg, 12).as_direct()?.data() as usize;
let run = raw_slot(arg, 13).as_direct()?.data() as usize;
let atom = raw_slot(arg, 7).as_atom()?;
let new_indirect = unsafe {
let (mut new_indirect, new_slice) =
IndirectAtom::new_raw_mut_bitslice(stack, ((run << bloq) + 63) >> 6);
chop(bloq, start, run, 0, new_slice, atom.as_bitslice())?;
new_indirect.normalize_as_atom()
};
Ok(new_indirect.as_noun())
}
pub fn jet_met(_stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
@ -853,6 +870,28 @@ mod tests {
assert_jet(s, jet_rsh, sam, D(0));
}
#[test]
fn test_con() {
let ref mut s = init();
let (_a0, _a24, a63, _a96, a128) = atoms(s);
assert_math_jet(s, jet_con, &[atom_0, atom_0], ubig!(0));
assert_math_jet(
s,
jet_con,
&[atom_24, atom_96],
ubig!(0xfaceb00c15deadbeef977557),
);
assert_math_jet(
s,
jet_con,
&[atom_96, atom_128],
ubig!(0xdeadbeeffafef67cffdebfbeff563656),
);
assert_math_jet_noun(s, jet_con, &[atom_24, atom_63], a63);
assert_math_jet_noun(s, jet_con, &[atom_0, atom_128], a128);
assert_math_jet_noun(s, jet_con, &[atom_128, atom_0], a128);
}
#[test]
fn test_cut() {
let ref mut s = init();