From 114e74ec07e7ba7768579dded98f0e27fb42107e Mon Sep 17 00:00:00 2001 From: Philip Monk Date: Tue, 14 Feb 2023 21:52:19 -0700 Subject: [PATCH] [jets] add rep jet --- rust/ares/src/jets.rs | 1 + rust/ares/src/jets/math.rs | 93 +++++++++++++++++++++++++++++--------- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/rust/ares/src/jets.rs b/rust/ares/src/jets.rs index 1b90278..ed493fa 100644 --- a/rust/ares/src/jets.rs +++ b/rust/ares/src/jets.rs @@ -49,6 +49,7 @@ pub fn get_jet(jet_name: Noun) -> Result { tas!(b"cat") => Ok(jet_cat), tas!(b"cut") => Ok(jet_cut), tas!(b"can") => Ok(jet_can), + tas!(b"rep") => Ok(jet_rep), tas!(b"met") => Ok(jet_met), tas!(b"mug") => Ok(jet_mug), _ => { diff --git a/rust/ares/src/jets/math.rs b/rust/ares/src/jets/math.rs index 0d8a35a..b2fc650 100644 --- a/rust/ares/src/jets/math.rs +++ b/rust/ares/src/jets/math.rs @@ -303,11 +303,6 @@ pub fn jet_bex(stack: &mut NockStack, subject: Noun) -> Result { pub fn jet_lsh(stack: &mut NockStack, subject: Noun) -> Result { let arg = raw_slot(subject, 6); let (bloq, step) = bite(raw_slot(arg, 2))?; - let bloq = bloq.as_direct()?.data() as usize; - if bloq >= 64 { - return Err(Deterministic); - } - let step = step.as_direct()?.data() as usize; let a = raw_slot(arg, 3).as_atom()?; // TODO: need to assert step << bloq doesn't overflow? @@ -334,11 +329,6 @@ pub fn jet_lsh(stack: &mut NockStack, subject: Noun) -> Result { pub fn jet_rsh(stack: &mut NockStack, subject: Noun) -> Result { let arg = raw_slot(subject, 6); let (bloq, step) = bite(raw_slot(arg, 2))?; - let bloq = bloq.as_direct()?.data() as usize; - if bloq >= 64 { - return Err(Deterministic); - } - let step = step.as_direct()?.data() as usize; let a = raw_slot(arg, 3).as_atom()?; let len = met(bloq, a); @@ -413,11 +403,6 @@ pub fn jet_mix(stack: &mut NockStack, subject: Noun) -> Result { pub fn jet_end(stack: &mut NockStack, subject: Noun) -> Result { let arg = raw_slot(subject, 6); let (bloq, step) = bite(raw_slot(arg, 2))?; - let bloq = bloq.as_direct()?.data() as usize; - if bloq >= 64 { - return Err(Deterministic); - } - let step = step.as_direct()?.data() as usize; let a = raw_slot(arg, 3).as_atom()?; if step == 0 { @@ -444,7 +429,7 @@ pub fn jet_cat(stack: &mut NockStack, subject: Noun) -> Result { let arg = raw_slot(subject, 6); let bloq = raw_slot(arg, 2).as_direct()?.data() as usize; if bloq >= 64 { - return Err(Deterministic); + return Err(NonDeterministic); } let a = raw_slot(arg, 6).as_atom()?; let b = raw_slot(arg, 7).as_atom()?; @@ -468,7 +453,7 @@ pub fn jet_can(stack: &mut NockStack, subject: Noun) -> Result { let arg = raw_slot(subject, 6); let bloq = raw_slot(arg, 2).as_direct()?.data() as usize; if bloq >= 64 { - return Err(Deterministic); + return Err(NonDeterministic); } let original_list = raw_slot(arg, 3); @@ -514,11 +499,54 @@ pub fn jet_can(stack: &mut NockStack, subject: Noun) -> Result { } } +pub fn jet_rep(stack: &mut NockStack, subject: Noun) -> Result { + let arg = raw_slot(subject, 6); + let (bloq, step) = bite(raw_slot(arg, 2))?; + let original_list = raw_slot(arg, 3); + + let mut len = 0 as usize; + let mut list = original_list; + loop { + if unsafe { list.raw_equals(D(0)) } { + break; + } + + let cell = list.as_cell()?; + + len = len.checked_add(step).ok_or(NonDeterministic)?; + list = cell.tail(); + } + + if len == 0 { + Ok(D(0)) + } else { + unsafe { + let (mut new_indirect, new_slice) = + IndirectAtom::new_raw_mut_bitslice(stack, len << bloq); + let mut pos = 0; + let mut list = original_list; + loop { + if list.raw_equals(D(0)) { + break; + } + + let cell = list.as_cell()?; + let atom = cell.head().as_atom()?; + chop(bloq, 0, step, pos, new_slice, atom.as_bitslice())?; + + pos += step; + list = cell.tail(); + } + Ok(new_indirect.normalize_as_atom().as_noun()) + } + } +} + pub fn jet_cut(stack: &mut NockStack, subject: Noun) -> Result { let arg = raw_slot(subject, 6); let bloq = raw_slot(arg, 2).as_direct()?.data() as usize; if bloq >= 64 { - return Err(Deterministic); + return Err(NonDeterministic); } let start = raw_slot(arg, 12).as_direct()?.data() as usize; let run = raw_slot(arg, 13).as_direct()?.data() as usize; @@ -537,7 +565,7 @@ pub fn jet_met(_stack: &mut NockStack, subject: Noun) -> Result { let arg = raw_slot(subject, 6); let bloq = raw_slot(arg, 2).as_direct()?.data() as usize; if bloq >= 64 { - return Err(Deterministic); + return Err(NonDeterministic); } let a = raw_slot(arg, 3).as_atom()?; @@ -550,11 +578,20 @@ pub fn jet_mug(stack: &mut NockStack, subject: Noun) -> Result { } /** Extract the bloq and step from a bite */ -fn bite(a: Noun) -> Result<(Atom, Atom), ()> { +fn bite(a: Noun) -> Result<(usize, usize), ()> { if let Ok(cell) = a.as_cell() { - Ok((cell.head().as_atom()?, cell.tail().as_atom()?)) + let bloq = cell.head().as_direct()?.data() as usize; + if bloq >= 64 { + return Err(()); + } + let step = cell.tail().as_direct()?.data() as usize; + Ok((bloq, step)) } else { - Ok((a.as_atom()?, D(1).as_atom()?)) + let bloq = a.as_direct()?.data() as usize; + if bloq >= 64 { + return Err(()); + } + Ok((bloq, 1)) } } @@ -1148,6 +1185,18 @@ mod tests { assert_jet(s, jet_can, sam, res); } + #[test] + fn test_rep() { + let ref mut s = init(); + 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); + } + #[test] fn test_jet_met() { let ref mut s = init();