WIP - 09/09

This commit is contained in:
Alex Shelkovnykov 2023-09-10 09:48:21 -06:00
parent 8816d470c9
commit 96a8915cc3
7 changed files with 396 additions and 181 deletions

View File

@ -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]

View File

@ -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
}
}
_ => {}
}

View File

@ -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};

View File

@ -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(

View File

@ -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);
}
}

301
rust/ares/src/jets/mock.rs Normal file
View File

@ -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);
}
}

View File

@ -227,6 +227,16 @@ pub fn T<A: NounAllocator>(allocator: &mut A, tup: &[Noun]) -> Noun {
Cell::new_tuple(allocator, tup).as_noun()
}
/// Create $tape Noun from ASCII string
pub fn tape<A: NounAllocator>(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