diff --git a/rust/ares/src/interpreter.rs b/rust/ares/src/interpreter.rs index 6604d45..bb086b4 100644 --- a/rust/ares/src/interpreter.rs +++ b/rust/ares/src/interpreter.rs @@ -1,4 +1,5 @@ use self::NockWork::*; +use crate::jets::get_jet; use crate::mem::unifying_equality; use crate::mem::NockStack; use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun}; @@ -312,6 +313,20 @@ pub fn interpret(stack: &mut NockStack, mut subject: Noun, formula: Noun) -> Nou Nock11ComputeHint => unsafe { let hint = *stack.local_noun_pointer(1); if let Ok(hint_cell) = hint.as_cell() { + if hint_cell + .head() + .raw_equals(DirectAtom::new_unchecked(0x706f7270).as_noun()) + { + if let Ok(jet_formula) = hint_cell.tail().as_cell() { + let jet_name = jet_formula.tail(); + let jet = get_jet(jet_name); + if let Ok(jet) = jet { + res = jet(stack, subject); + stack.pop(&mut res); + continue; + } + } + } *(stack.local_noun_pointer(0)) = work_to_noun(Nock11ComputeResult); push_formula(stack, hint_cell.tail()); } else { diff --git a/rust/ares/src/jets.rs b/rust/ares/src/jets.rs new file mode 100644 index 0000000..91882e7 --- /dev/null +++ b/rust/ares/src/jets.rs @@ -0,0 +1,68 @@ +use crate::interpreter::raw_slot; +use crate::mem::NockStack; +use crate::noun::{DirectAtom, IndirectAtom, Noun}; +use either::Either::*; + +pub fn get_jet(jet_name: Noun) -> Result Noun, ()> { + if let Ok(jet_direct) = jet_name.as_direct() { + match jet_direct.data() { + 0x636564 => Ok(jet_dec), + 0x747563 => Ok(jet_cut), + _ => Err(()), + } + } else { + Err(()) + } +} + +fn jet_dec(stack: &mut NockStack, subject: Noun) -> Noun { + let arg = raw_slot(subject, 6); + if let Ok(atom) = arg.as_atom() { + match atom.as_either() { + Left(direct) => { + if direct.data() == 0 { + panic!("Decrementing 0"); + } else { + unsafe { DirectAtom::new_unchecked(direct.data() - 1) }.as_noun() + } + } + Right(indirect) => { + let indirect_slice = indirect.as_bitslice(); + match indirect_slice.first_one() { + None => { + panic!("Decrementing 0"); + } + Some(first_one) => { + let (mut new_indirect, new_slice) = + unsafe { IndirectAtom::new_raw_mut_bitslice(stack, indirect.size()) }; + if first_one > 0 { + new_slice[..first_one].fill(true); + } + new_slice.set(first_one, false); + new_slice[first_one + 1..] + .copy_from_bitslice(&indirect_slice[first_one + 1..]); + let res = unsafe { new_indirect.normalize_as_atom() }; + res.as_noun() + } + } + } + } + } else { + panic!("Argument to dec must be atom"); + } +} + +fn jet_cut(stack: &mut NockStack, subject: Noun) -> Noun { + let arg = raw_slot(subject, 6); + let bloq = raw_slot(arg, 2).as_direct().unwrap().data(); + let start = raw_slot(arg, 12).as_direct().unwrap().data(); + let run = raw_slot(arg, 13).as_direct().unwrap().data(); + let atom = raw_slot(arg, 7).as_atom().unwrap(); + let slice = atom.as_bitslice(); + let unit = 1 << bloq; + let (mut new_indirect, new_slice) = + unsafe { IndirectAtom::new_raw_mut_bitslice(stack, ((run * unit + 63) >> 6) as usize) }; + new_slice[..(unit * run) as usize] + .copy_from_bitslice(&slice[(unit * start) as usize..(unit * (start + run)) as usize]); + unsafe { new_indirect.normalize_as_atom().as_noun() } +} diff --git a/rust/ares/src/lib.rs b/rust/ares/src/lib.rs index 55d0089..c70f0b7 100644 --- a/rust/ares/src/lib.rs +++ b/rust/ares/src/lib.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate num_derive; pub mod interpreter; +pub mod jets; pub mod mem; pub mod mug; pub mod noun;