From 96a8915cc30932fe5f94aa391819c1391ad26bdf Mon Sep 17 00:00:00 2001 From: Alex Shelkovnykov Date: Sun, 10 Sep 2023 09:48:21 -0600 Subject: [PATCH] WIP - 09/09 --- hoon/scaffolding/toddler.hoon | 34 +++- rust/ares/src/interpreter.rs | 29 ++++ rust/ares/src/jets.rs | 41 +++-- rust/ares/src/jets/bits.rs | 14 +- rust/ares/src/jets/mink.rs | 148 ----------------- rust/ares/src/jets/mock.rs | 301 ++++++++++++++++++++++++++++++++++ rust/ares/src/noun.rs | 10 ++ 7 files changed, 396 insertions(+), 181 deletions(-) delete mode 100644 rust/ares/src/jets/mink.rs create mode 100644 rust/ares/src/jets/mock.rs diff --git a/hoon/scaffolding/toddler.hoon b/hoon/scaffolding/toddler.hoon index 641cabf..24416e3 100644 --- a/hoon/scaffolding/toddler.hoon +++ b/hoon/scaffolding/toddler.hoon @@ -17,12 +17,34 @@ ++ pair |$ [head tail] [p=head q=tail] +$ path (list knot) +$ wire path - ++ ack + :: mutually recursive Ackermann functions + :: test turning %spot hints on/off + ++ wack + :: re-enable %spot hints + !: |= [m=@ud n=@ud] + :: %mean hint + ~_ [%leaf "I am a %mean hint via ~_ from +wack"] + :: %hela hint + ~> %hela + :: %memo hint + ~+ ?~ m +(n) ?~ n - $(m (dec m), n 1) - $(m (dec m), n $(n (dec n))) + (tack (dec m) 1) + (tack (dec m) $(n (dec n))) + ++ tack + :: disable %spot hints + !. + |= [m=@ud n=@ud] + :: %hela hint + ~> %hela + :: %memo hint + ~+ + ?~ m +(n) + ?~ n + (wack (dec m) 1) + (wack (dec m) $(n (dec n))) -- => :: |% @@ -32,10 +54,8 @@ ++ poke |= [now=@da ovo=ovum] ^- ^ - :: ~> %slog.[0 'got'] - :: ~> %slog.[0 -.card.ovo] - =/ fec [//term/1 %blit [%put (snoc "A(2,1) = " (add 48 (ack 2 1)))] [%nel ~] ~] - [[fec ~] ..poke] + ~> %slog.[0 (wack 2 1)] + [~ ..poke] -- :: |= [now=@da ovo=ovum] diff --git a/rust/ares/src/interpreter.rs b/rust/ares/src/interpreter.rs index bae6c17..ba4a2f3 100644 --- a/rust/ares/src/interpreter.rs +++ b/rust/ares/src/interpreter.rs @@ -741,6 +741,35 @@ fn match_hint_pre_nock( let trace = Cell::new(stack, tag.as_noun(), res).as_noun(); stack.trace_push(trace); } + tas!(b"hela") => { + // Joe: "to render to a tank call mook in Arvo with u3v_wish in Vere" + // need to make tank from stack trace; need mook equivalent + // + // u3_serf_writ -> u3_serf_work -> _serf_work -> _serf_poke -> u3m_soft -> u3dc -> u3v_do -> u3v_wish -> +wish in Arvo + // | + // V + // mook + // + // No +wish in toy Arvo; missing +slap and a ton of parsing functions needed by +ream + // + // u3t_slog = print on thing directly + // u3t_slog_trace = print stack trace = - convert tone to toon + // - presume toon is [%2 tang] + // - print each tank in tang one at at time using u3t_slog + // u3t_slog_hela = print entire stack trace = - weld stacks from all roads together + // - call u3t_slog_trace on combined stack + // u3t_slog_nara = print home road stack trace = call u3t_slog_trace on home road stack + // + if let Some(not) = newt { + // flop the trace_stack XX: u3m_soft doesn't do this!!! + // call mook on [%2 trace_stack] + // slog each item in the trace + // if priority given: use priority + // if priority not given: priority = 0 + // delete data structure + + } + } _ => {} } diff --git a/rust/ares/src/jets.rs b/rust/ares/src/jets.rs index 1d8fda1..5f7f30b 100644 --- a/rust/ares/src/jets.rs +++ b/rust/ares/src/jets.rs @@ -1,7 +1,7 @@ pub mod bits; pub mod hash; pub mod math; -pub mod mink; +pub mod mock; pub mod tree; use crate::jets::bits::*; @@ -237,6 +237,33 @@ pub mod util { } } + /// Measure the number of bloqs in an atom + pub fn met(bloq: usize, a: Atom) -> usize { + if unsafe { a.as_noun().raw_equals(D(0)) } { + 0 + } else if bloq < 6 { + (a.bit_size() + ((1 << bloq) - 1)) >> bloq + } else { + let bloq_word = bloq - 6; + (a.size() + ((1 << bloq_word) - 1)) >> bloq_word + } + } + + pub fn rip(bloq: usize, step: usize, atom: Atom) -> Noun { + let len = (met(bloq, atom) + step - 1) / step; + let mut list = D(0); + for i in (0..len).rev() { + let new_atom = unsafe { + let (mut new_indirect, new_slice) = + IndirectAtom::new_raw_mut_bitslice(stack, step << bloq); + chop(bloq, i * step, step, 0, new_slice, atom.as_bitslice())?; + new_indirect.normalize_as_atom() + }; + list = Cell::new(stack, new_atom.as_noun(), list).as_noun(); + } + list + } + /// Binary OR pub fn con(stack: &mut NockStack, a: Atom, b: Atom) -> Atom { let new_size = cmp::max(a.size(), b.size()); @@ -250,18 +277,6 @@ pub mod util { } } - /// Measure the number of bloqs in an atom - pub fn met(bloq: usize, a: Atom) -> usize { - if unsafe { a.as_noun().raw_equals(D(0)) } { - 0 - } else if bloq < 6 { - (a.bit_size() + ((1 << bloq) - 1)) >> bloq - } else { - let bloq_word = bloq - 6; - (a.size() + ((1 << bloq_word) - 1)) >> bloq_word - } - } - pub mod test { use super::*; use crate::mem::{unifying_equality, NockStack}; diff --git a/rust/ares/src/jets/bits.rs b/rust/ares/src/jets/bits.rs index 9d9ff8e..415af00 100644 --- a/rust/ares/src/jets/bits.rs +++ b/rust/ares/src/jets/bits.rs @@ -321,19 +321,7 @@ pub fn jet_rip( let arg = slot(subject, 6)?; let (bloq, step) = bite(slot(arg, 2)?)?; let atom = slot(arg, 3)?.as_atom()?; - let len = (met(bloq, atom) + step - 1) / step; - - let mut list = D(0); - for i in (0..len).rev() { - let new_atom = unsafe { - let (mut new_indirect, new_slice) = - IndirectAtom::new_raw_mut_bitslice(stack, step << bloq); - chop(bloq, i * step, step, 0, new_slice, atom.as_bitslice())?; - new_indirect.normalize_as_atom() - }; - list = Cell::new(stack, new_atom.as_noun(), list).as_noun(); - } - Ok(list) + Ok(rip(bloq, step, atom)) } pub fn jet_rsh( diff --git a/rust/ares/src/jets/mink.rs b/rust/ares/src/jets/mink.rs deleted file mode 100644 index 6237c85..0000000 --- a/rust/ares/src/jets/mink.rs +++ /dev/null @@ -1,148 +0,0 @@ -/** Virtualization jets - */ -use crate::interpreter::{interpret, NockErr}; -use crate::jets; -use crate::jets::util::slot; -use crate::mem::NockStack; -use crate::newt::Newt; -use crate::noun::{Noun, D, T}; - -crate::gdb!(); - -// XX: interpret should accept optional scry function and potentially produce blocked -pub fn jet_mink( - stack: &mut NockStack, - newt: &mut Option<&mut Newt>, - subject: Noun, -) -> jets::Result { - let arg = slot(subject, 6)?; - // mink sample = [nock scry_namespace] - // = [[subject formula] scry_namespace] - let v_subject = slot(arg, 4)?; - let v_formula = slot(arg, 5)?; - let _scry = slot(arg, 3)?; - - match interpret(stack, newt, v_subject, v_formula) { - Ok(res) => Ok(T(stack, &[D(0), res])), - Err(err) => match err { - NockErr::Blocked(block) => Ok(T(stack, &[D(1), block])), - NockErr::Error(error) => Ok(T(stack, &[D(2), error])), - }, - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::jets::util::test::{assert_jet, init_stack}; - - #[test] - fn test_mink_success() { - let sack = &mut init_stack(); - let subj = D(0); - let form = T(sack, &[D(1), D(53)]); - let nock = T(sack, &[subj, form]); - let scry = D(0); - let samp = T(sack, &[nock, scry]); - let rest = T(sack, &[D(0), D(53)]); - assert_jet(sack, jet_mink, samp, rest); - } - - #[test] - fn test_mink_zapzap() { - let sack = &mut init_stack(); - let subj = D(0); - let form = T(sack, &[D(0), D(0)]); - let nock = T(sack, &[subj, form]); - let scry = D(0); - let samp = T(sack, &[nock, scry]); - let rest = T(sack, &[D(2), D(0)]); - assert_jet(sack, jet_mink, samp, rest); - } - - #[test] - fn test_mink_trace() { - let sack = &mut init_stack(); - let subj = D(0); - let scry = D(0); - - // != !: ?~ 0 !! 53 - // [ 11 - // [1.953.460.339 1 [1.953.719.668 0] [1 9] [1 22]] - // [ 8 - // [11 [1.953.460.339 1 [1.953.719.668 0] [1 13] [1 14]] [1 0]] - // [ 6 - // [5 [1 0] [0 2]] - // [7 [0 3] [11 [1.953.460.339 1 [1.953.719.668 0] [1 16] [1 18]] [0 0]]] - // [7 [0 3] [11 [1.953.460.339 1 [1.953.719.668 0] [1 20] [1 22]] [1 53]]] - // ] - // ] - // ] - // - // 1.953.719.668 = 'test' - // 1.953.460.339 = 'spot' - // - // All of this below is because of "two-phase borrow checks" - // https://stackoverflow.com/questions/60686259/mutable-borrow-in-function-argument - - let hint_spot = D(1953460339); - let hint_path = T(sack, &[D(1953719668), D(0)]); - let hint_dyn = D(1); - let hint_row = D(1); - - let make_hint = |sack: &mut NockStack, col_start: u64, col_end: u64| { - let start = T(sack, &[hint_row, D(col_start)]); - let end = T(sack, &[hint_row, D(col_end)]); - - T(sack, &[hint_spot, hint_dyn, hint_path, start, end]) - }; - - let sss3s1 = T(sack, &[D(0), D(3)]); - let sss3s2s1 = make_hint(sack, 20, 22); - let sss3s2s2 = T(sack, &[D(1), D(53)]); - let sss3s2 = T(sack, &[D(11), sss3s2s1, sss3s2s2]); - let sss3 = T(sack, &[D(7), sss3s1, sss3s2]); - - let sss2s1 = sss3s1; - let sss2s2s1 = make_hint(sack, 16, 18); - let sss2s2s2 = T(sack, &[D(0), D(0)]); - let sss2s2 = T(sack, &[D(11), sss2s2s1, sss2s2s2]); - let sss2 = T(sack, &[D(7), sss2s1, sss2s2]); - - let sss1s1 = T(sack, &[D(1), D(0)]); - let sss1s2 = T(sack, &[D(0), D(2)]); - let sss1 = T(sack, &[D(5), sss1s1, sss1s2]); - - let ss2 = T(sack, &[D(6), sss1, sss2, sss3]); - - let ss1s1 = make_hint(sack, 13, 14); - let ss1s2 = sss1s1; - let ss1 = T(sack, &[D(11), ss1s1, ss1s2]); - - let s2 = T(sack, &[D(8), ss1, ss2]); - let s1 = make_hint(sack, 9, 22); - let form = T(sack, &[D(11), s1, s2]); - - let nock = T(sack, &[subj, form]); - let samp = T(sack, &[nock, scry]); - - // trace - // [%2 trace=~[[~.spot [[1.953.719.668 0] [1 16] 1 18]] [~.spot [[1.953.719.668 0] [1 9] 1 22]]]] - let ttt2t1 = T(sack, &[D(1), D(9)]); - let ttt2t2 = T(sack, &[D(1), D(22)]); - let ttt2 = T(sack, &[hint_path, ttt2t1, ttt2t2]); - - let ttt1t1 = T(sack, &[D(1), D(16)]); - let ttt1t2 = T(sack, &[D(1), D(18)]); - let ttt1 = T(sack, &[hint_path, ttt1t1, ttt1t2]); - - let tt2 = T(sack, &[hint_spot, ttt2]); - let tt1 = T(sack, &[hint_spot, ttt1]); - - let t1 = T(sack, &[tt1, tt2, D(0)]); - - let rest = T(sack, &[D(2), t1]); - - assert_jet(sack, jet_mink, samp, rest); - } -} diff --git a/rust/ares/src/jets/mock.rs b/rust/ares/src/jets/mock.rs new file mode 100644 index 0000000..7286dcc --- /dev/null +++ b/rust/ares/src/jets/mock.rs @@ -0,0 +1,301 @@ +/** Virtualization jets + */ +use crate::interpreter::{interpret, NockErr}; +use crate::jets; +use crate::jets::util::slot; +use crate::mem::NockStack; +use crate::newt::Newt; +use crate::noun::{Noun, D, T}; + +crate::gdb!(); + +// XX: interpret should accept optional scry function and potentially produce blocked +pub fn jet_mink( + stack: &mut NockStack, + newt: &mut Option<&mut Newt>, + subject: Noun, +) -> jets::Result { + let arg = slot(subject, 6)?; + // mink sample = [nock scry_namespace] + // = [[subject formula] scry_namespace] + let v_subject = slot(arg, 4)?; + let v_formula = slot(arg, 5)?; + let _scry = slot(arg, 3)?; + + match interpret(stack, newt, v_subject, v_formula) { + Ok(res) => Ok(T(stack, &[D(0), res])), + Err(err) => match err { + NockErr::Blocked(block) => Ok(T(stack, &[D(1), block])), + NockErr::Error(error) => Ok(T(stack, &[D(2), error])), + }, + } +} + +mod util { + // +$ tone $% [%0 product=*] + // [%1 block=*] + // [%2 trace=(list [@ta *])] + // == + // +$ toon $% [%0 p=*] + // [%1 p=*] + // [%2 p=(list tank)] + // == + // ++ mook + // |= ton=tone + // ^- toon + // ?. ?=([%2 *] ton) + // ton + // |^ [%2 (turn skip rend)] + // :: + // ++ skip + // ^+ trace.ton + // =/ yel (lent trace.ton) :: get length of the trace + // ?. (gth yel 1.024) trace.ton :: return early if the length of the trace is less than 1024 + // %+ weld + // (scag 512 trace.ton) + // ^+ trace.ton + // :_ (slag (sub yel 512) trace.ton) + // :- %lose + // (crip "[skipped {(scow %ud (sub yel 1.024))} frames]") + // :: + // :: +rend: raw stack frame to tank + // :: + // :: $% [%hunk ref=* path] :: failed scry ([~ ~]) + // :: [%lose cord] :: skipped frames + // :: [%hand *] :: mug any + // :: [%mean $@(cord (trap tank))] :: ~_ et al + // :: [%spot spot] :: source location + // :: == + // :: + // ++ rend + // |= [tag=@ta dat=*] + // ^- tank + // ?+ tag + // :: + // leaf+"mook.{(rip 3 tag)}" + // :: + // %hunk + // ?@ dat leaf+"mook.hunk" + // =/ sof=(unit path) ((soft path) +.dat) + // ?~ sof leaf+"mook.hunk" + // (smyt u.sof) + // :: + // %lose + // ?^ dat leaf+"mook.lose" + // leaf+(rip 3 dat) + // :: + // %hand + // leaf+(scow %p (mug dat)) + // :: + // %mean + // ?@ dat leaf+(rip 3 dat) + // =/ mac (mack dat -.dat) + // ?~ mac leaf+"####" + // =/ sof ((soft tank) u.mac) + // ?~ sof leaf+"mook.mean" + // u.sof + // :: + // %spot + // =/ sof=(unit spot) ((soft spot) dat) + // ?~ sof leaf+"mook.spot" + // :+ %rose [":" ~ ~] + // :~ (smyt p.u.sof) + // =* l p.q.u.sof + // =* r q.q.u.sof + // =/ ud |=(a=@u (scow %ud a)) + // leaf+"<[{(ud p.l)} {(ud q.l)}].[{(ud p.r)} {(ud q.r)}]>" + // == + // == + // -- + + /** Consume $tone, produce $toon + */ + pub fn mook( + stack: NockStack, + newt: &mut Option<&mut Newt>, + tone: Noun, + flop: bool + ) -> Result { + let temp = tone.as_cell()?; + let tag = temp.head().as_direct()?; + let original_list = temp.tail(); + + if tag.data() < 2 { + return Ok(tone); + } else if tag.data() > 2 { + return Err(JetErr::Deterministic) + } + + // XX: trim traces longer than 1024 frames + let leaf = D(tas!(b"leaf")); + + if flop { + let mut list = original_list; + let mut res = D(0); + loop { + if unsafe { list.raw_equals(D(0)) } { + break; + } + + let cell = list.as_cell()?; + let trace = cell.head().as_cell()?; + let tag = trace.head().as_direct()?; + let dat = trace.tail(); + + // XX: implement + let tank: Noun = match tag.data() { + // *[a [9 2 [0 1]]] + // *[*[a [0 1]] [2 [0 1] [0 2]]] + // *[\[1 a] [2 [0 1] [0 2]]] + // *[a [2 [0 1] [0 2]]] + // *[*[a [0 1]] *[a [0 2]]] + // *[\[1 a] \[2 a]] + // *[a \[2 a]] + tas!(b"spot") => { + let subj = T(stack, &[D(0), dat, D(0)]); + let spot = jet_mink(stack, newt, subj)?; + if spot.as_cell()?.head().as_direct().data() != 0 { + // XX test this in Vere + // if the formula in dat crashes, we produce leaf+"mook.spot" + let msg = tape(stack, "mook.spot"); + T(stack, &[leaf, msg]) + } else { + + } + } + // XX: TODO + // %hand + // %hunk + // %lose + // %mean + // default + + }; + + res = T(stack, &[tank, res]); + list = cell.tail(); + } + + Ok(Res) + } else { + // XX: need non-tail recursive helper to build +mook without +flop, because no helper in noun.rs to allocate Cell and set tail later (like u3i_defcons in Vere) + Ok(D(0)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::jets::util::test::{assert_jet, init_stack}; + + #[test] + fn test_mink_success() { + let sack = &mut init_stack(); + let subj = D(0); + let form = T(sack, &[D(1), D(53)]); + let nock = T(sack, &[subj, form]); + let scry = D(0); + let samp = T(sack, &[nock, scry]); + let rest = T(sack, &[D(0), D(53)]); + assert_jet(sack, jet_mink, samp, rest); + } + + #[test] + fn test_mink_zapzap() { + let sack = &mut init_stack(); + let subj = D(0); + let form = T(sack, &[D(0), D(0)]); + let nock = T(sack, &[subj, form]); + let scry = D(0); + let samp = T(sack, &[nock, scry]); + let rest = T(sack, &[D(2), D(0)]); + assert_jet(sack, jet_mink, samp, rest); + } + + #[test] + fn test_mink_trace() { + let sack = &mut init_stack(); + let subj = D(0); + let scry = D(0); + + // != !: ?~ 0 !! 53 + // [ 11 + // [1.953.460.339 1 [1.953.719.668 0] [1 9] [1 22]] + // [ 8 + // [11 [1.953.460.339 1 [1.953.719.668 0] [1 13] [1 14]] [1 0]] + // [ 6 + // [5 [1 0] [0 2]] + // [7 [0 3] [11 [1.953.460.339 1 [1.953.719.668 0] [1 16] [1 18]] [0 0]]] + // [7 [0 3] [11 [1.953.460.339 1 [1.953.719.668 0] [1 20] [1 22]] [1 53]]] + // ] + // ] + // ] + // + // 1.953.719.668 = 'test' + // 1.953.460.339 = 'spot' + // + // All of this below is because of "two-phase borrow checks" + // https://stackoverflow.com/questions/60686259/mutable-borrow-in-function-argument + + let hint_spot = D(1953460339); + let hint_path = T(sack, &[D(1953719668), D(0)]); + let hint_dyn = D(1); + let hint_row = D(1); + + let make_hint = |sack: &mut NockStack, col_start: u64, col_end: u64| { + let start = T(sack, &[hint_row, D(col_start)]); + let end = T(sack, &[hint_row, D(col_end)]); + + T(sack, &[hint_spot, hint_dyn, hint_path, start, end]) + }; + + let sss3s1 = T(sack, &[D(0), D(3)]); + let sss3s2s1 = make_hint(sack, 20, 22); + let sss3s2s2 = T(sack, &[D(1), D(53)]); + let sss3s2 = T(sack, &[D(11), sss3s2s1, sss3s2s2]); + let sss3 = T(sack, &[D(7), sss3s1, sss3s2]); + + let sss2s1 = sss3s1; + let sss2s2s1 = make_hint(sack, 16, 18); + let sss2s2s2 = T(sack, &[D(0), D(0)]); + let sss2s2 = T(sack, &[D(11), sss2s2s1, sss2s2s2]); + let sss2 = T(sack, &[D(7), sss2s1, sss2s2]); + + let sss1s1 = T(sack, &[D(1), D(0)]); + let sss1s2 = T(sack, &[D(0), D(2)]); + let sss1 = T(sack, &[D(5), sss1s1, sss1s2]); + + let ss2 = T(sack, &[D(6), sss1, sss2, sss3]); + + let ss1s1 = make_hint(sack, 13, 14); + let ss1s2 = sss1s1; + let ss1 = T(sack, &[D(11), ss1s1, ss1s2]); + + let s2 = T(sack, &[D(8), ss1, ss2]); + let s1 = make_hint(sack, 9, 22); + let form = T(sack, &[D(11), s1, s2]); + + let nock = T(sack, &[subj, form]); + let samp = T(sack, &[nock, scry]); + + // trace + // [%2 trace=~[[~.spot [[1.953.719.668 0] [1 16] 1 18]] [~.spot [[1.953.719.668 0] [1 9] 1 22]]]] + let ttt2t1 = T(sack, &[D(1), D(9)]); + let ttt2t2 = T(sack, &[D(1), D(22)]); + let ttt2 = T(sack, &[hint_path, ttt2t1, ttt2t2]); + + let ttt1t1 = T(sack, &[D(1), D(16)]); + let ttt1t2 = T(sack, &[D(1), D(18)]); + let ttt1 = T(sack, &[hint_path, ttt1t1, ttt1t2]); + + let tt2 = T(sack, &[hint_spot, ttt2]); + let tt1 = T(sack, &[hint_spot, ttt1]); + + let t1 = T(sack, &[tt1, tt2, D(0)]); + + let rest = T(sack, &[D(2), t1]); + + assert_jet(sack, jet_mink, samp, rest); + } +} diff --git a/rust/ares/src/noun.rs b/rust/ares/src/noun.rs index cfec55f..8fd8410 100644 --- a/rust/ares/src/noun.rs +++ b/rust/ares/src/noun.rs @@ -227,6 +227,16 @@ pub fn T(allocator: &mut A, tup: &[Noun]) -> Noun { Cell::new_tuple(allocator, tup).as_noun() } +/// Create $tape Noun from ASCII string +pub fn tape(allocator: &mut A, text: &str) -> Noun { + let mut res = D(0); + // XX: Need deferred Cell allocation, like u3i_defcons in Vere + for c in str.bytes().rev() { + res = T(allocator, &[D(c as u64), res]) + } + res +} + /** An indirect atom. * * Indirect atoms represent atoms above DIRECT_MAX as a tagged pointer to a memory buffer