diff --git a/hoon/scaffolding/playpen.hoon b/hoon/scaffolding/playpen.hoon index 693005e..a56be08 100644 --- a/hoon/scaffolding/playpen.hoon +++ b/hoon/scaffolding/playpen.hoon @@ -10,6 +10,7 @@ :: +$ cord @t +$ knot @ta ++$ char @t +$ ship @p +$ life @ud +$ rift @ud @@ -36,6 +37,9 @@ [%1 block=*] [%2 trace=(list [@ta *])] == +++ pair + |$ [head tail] + [p=head q=tail] ++ trel |$ [first second third] [p=first q=second r=third] @@ -55,7 +59,7 @@ [%2 p=(list tank)] == ++ tree |$ [node] $@(~ [n=node l=(tree node) r=(tree node)]) -++ pair |$ [head tail] [p=head q=tail] +++ gate $-(* *) :: ++ map |$ [key value] @@ -779,778 +783,842 @@ =+ d=(get b) (~(put by a) b (~(put in d) c)) -- -:: -:: SHA hashing -:: -++ shay :: sha-256 with length - ~/ %shay - |= [len=@u ruz=@] ^- @ - => .(ruz (cut 3 [0 len] ruz)) - =+ [few==>(fe .(a 5)) wac=|=([a=@ b=@] (cut 5 [a 1] b))] - =+ [sum=sum.few ror=ror.few net=net.few inv=inv.few] - =+ ral=(lsh [0 3] len) - =+ ^= ful - %+ can 0 - :~ [ral ruz] - [8 128] - [(mod (sub 960 (mod (add 8 ral) 512)) 512) 0] - [64 (~(net fe 6) ral)] - == - =+ lex=(met 9 ful) - =+ ^= kbx 0xc671.78f2.bef9.a3f7.a450.6ceb.90be.fffa. - 8cc7.0208.84c8.7814.78a5.636f.748f.82ee. - 682e.6ff3.5b9c.ca4f.4ed8.aa4a.391c.0cb3. - 34b0.bcb5.2748.774c.1e37.6c08.19a4.c116. - 106a.a070.f40e.3585.d699.0624.d192.e819. - c76c.51a3.c24b.8b70.a81a.664b.a2bf.e8a1. - 9272.2c85.81c2.c92e.766a.0abb.650a.7354. - 5338.0d13.4d2c.6dfc.2e1b.2138.27b7.0a85. - 1429.2967.06ca.6351.d5a7.9147.c6e0.0bf3. - bf59.7fc7.b003.27c8.a831.c66d.983e.5152. - 76f9.88da.5cb0.a9dc.4a74.84aa.2de9.2c6f. - 240c.a1cc.0fc1.9dc6.efbe.4786.e49b.69c1. - c19b.f174.9bdc.06a7.80de.b1fe.72be.5d74. - 550c.7dc3.2431.85be.1283.5b01.d807.aa98. - ab1c.5ed5.923f.82a4.59f1.11f1.3956.c25b. - e9b5.dba5.b5c0.fbcf.7137.4491.428a.2f98 - =+ ^= hax 0x5be0.cd19.1f83.d9ab.9b05.688c.510e.527f. - a54f.f53a.3c6e.f372.bb67.ae85.6a09.e667 - =+ i=0 - |- ^- @ - ?: =(i lex) - (run 5 hax net) - =+ ^= wox - =+ dux=(cut 9 [i 1] ful) - =+ wox=(run 5 dux net) - =+ j=16 - |- ^- @ - ?: =(64 j) - wox - =+ :* l=(wac (sub j 15) wox) - m=(wac (sub j 2) wox) - n=(wac (sub j 16) wox) - o=(wac (sub j 7) wox) - == - =+ x=:(mix (ror 0 7 l) (ror 0 18 l) (rsh [0 3] l)) - =+ y=:(mix (ror 0 17 m) (ror 0 19 m) (rsh [0 10] m)) - =+ z=:(sum n x o y) - $(wox (con (lsh [5 j] z) wox), j +(j)) - =+ j=0 - =+ :* a=(wac 0 hax) - b=(wac 1 hax) - c=(wac 2 hax) - d=(wac 3 hax) - e=(wac 4 hax) - f=(wac 5 hax) - g=(wac 6 hax) - h=(wac 7 hax) - == - |- ^- @ - ?: =(64 j) - %= ^$ - i +(i) - hax %+ rep 5 - :~ (sum a (wac 0 hax)) - (sum b (wac 1 hax)) - (sum c (wac 2 hax)) - (sum d (wac 3 hax)) - (sum e (wac 4 hax)) - (sum f (wac 5 hax)) - (sum g (wac 6 hax)) - (sum h (wac 7 hax)) - == - == - =+ l=:(mix (ror 0 2 a) (ror 0 13 a) (ror 0 22 a)) :: s0 - =+ m=:(mix (dis a b) (dis a c) (dis b c)) :: maj - =+ n=(sum l m) :: t2 - =+ o=:(mix (ror 0 6 e) (ror 0 11 e) (ror 0 25 e)) :: s1 - =+ p=(mix (dis e f) (dis (inv e) g)) :: ch - =+ q=:(sum h o p (wac j kbx) (wac j wox)) :: t1 - $(j +(j), a (sum q n), b a, c b, d c, e (sum d q), f e, g f, h g) -:: -:: Scrambling -:: -++ ob - ~% %ob ..ob - == - %fein fein - %fynd fynd - == - |% - :: - :: +fein: conceal structure, v3. - :: - :: +fein conceals planet-sized atoms. The idea is that it should not be - :: trivial to tell which planet a star has spawned under. - :: - ++ fein - ~/ %fein - |= pyn=@ ^- @ - ?: &((gte pyn 0x1.0000) (lte pyn 0xffff.ffff)) - (add 0x1.0000 (feis (sub pyn 0x1.0000))) - ?: &((gte pyn 0x1.0000.0000) (lte pyn 0xffff.ffff.ffff.ffff)) - =/ lo (dis pyn 0xffff.ffff) - =/ hi (dis pyn 0xffff.ffff.0000.0000) - %+ con hi - $(pyn lo) - pyn - :: - :: +fynd: restore structure, v3. - :: - :: Restores obfuscated values that have been enciphered with +fein. - :: - ++ fynd - ~/ %fynd - |= cry=@ ^- @ - ?: &((gte cry 0x1.0000) (lte cry 0xffff.ffff)) - (add 0x1.0000 (tail (sub cry 0x1.0000))) - ?: &((gte cry 0x1.0000.0000) (lte cry 0xffff.ffff.ffff.ffff)) - =/ lo (dis cry 0xffff.ffff) - =/ hi (dis cry 0xffff.ffff.0000.0000) - %+ con hi - $(cry lo) - cry - :: +feis: a four-round generalised Feistel cipher over the domain - :: [0, 2^32 - 2^16 - 1]. - :: - :: See: Black & Rogaway (2002), Ciphers for arbitrary finite domains. - :: - ++ feis - |= m=@ - ^- @ - (fee 4 0xffff 0x1.0000 (mul 0xffff 0x1.0000) eff m) - :: - :: +tail: reverse +feis. - :: - ++ tail - |= m=@ - ^- @ - (feen 4 0xffff 0x1.0000 (mul 0xffff 0x1.0000) eff m) - :: - :: +fee: "Fe" in B&R (2002). - :: - :: A Feistel cipher given the following parameters: - :: - :: r: number of Feistel rounds - :: a, b: parameters such that ab >= k - :: k: value such that the domain of the cipher is [0, k - 1] - :: prf: a gate denoting a family of pseudorandom functions indexed by - :: its first argument and taking its second argument as input - :: m: an input value in the domain [0, k - 1] - :: - ++ fee - |= [r=@ a=@ b=@ k=@ prf=$-([j=@ r=@] @) m=@] - ^- @ - =/ c (fe r a b prf m) - ?: (lth c k) - c - (fe r a b prf c) - :: - :: +feen: "Fe^-1" in B&R (2002). - :: - :: Reverses a Feistel cipher constructed with parameters as described in - :: +fee. - :: - ++ feen - |= [r=@ a=@ b=@ k=@ prf=$-([j=@ r=@] @) m=@] - ^- @ - =/ c (fen r a b prf m) - ?: (lth c k) - c - (fen r a b prf c) - :: - :: +fe: "fe" in B&R (2002). - :: - :: An internal function to +fee. - :: - :: Note that this implementation differs slightly from the reference paper - :: to support some legacy behaviour. See urbit/arvo#1105. - :: - ++ fe - |= [r=@ a=@ b=@ prf=$-([j=@ r=@] @) m=@] - =/ j 1 - =/ ell (mod m a) - =/ arr (div m a) - |- ^- @ - :: - ?: (gth j r) - ?. =((mod r 2) 0) - (add (mul arr a) ell) - :: - :: Note that +fe differs from B&R (2002)'s "fe" below, as a previous - :: implementation of this cipher contained a bug such that certain inputs - :: could encipher to the same output. - :: - :: To correct these problem cases while also preserving the cipher's - :: legacy behaviour on most inputs, we check for a problem case (which - :: occurs when 'arr' is equal to 'a') and, if detected, use an alternate - :: permutation instead. - :: - ?: =(arr a) - (add (mul arr a) ell) - (add (mul ell a) arr) - :: - =/ f (prf (sub j 1) arr) - :: - =/ tmp - ?. =((mod j 2) 0) - (mod (add f ell) a) - (mod (add f ell) b) - :: - $(j +(j), ell arr, arr tmp) - :: - :: +fen: "fe^-1" in B&R (2002). - :: - :: Note that this implementation differs slightly from the reference paper - :: to support some legacy behaviour. See urbit/arvo#1105. - :: - ++ fen - |= [r=@ a=@ b=@ prf=$-([j=@ r=@] @) m=@] - =/ j r - :: - =/ ahh - ?. =((mod r 2) 0) - (div m a) - (mod m a) - :: - =/ ale - ?. =((mod r 2) 0) - (mod m a) - (div m a) - :: - :: Similar to the comment in +fe, +fen differs from B&R (2002)'s "fe^-1" - :: here in order to preserve the legacy cipher's behaviour on most inputs. - :: - :: Here problem cases can be identified by 'ahh' equating with 'a'; we - :: correct those cases by swapping the values of 'ahh' and 'ale'. - :: - =/ ell - ?: =(ale a) - ahh - ale - :: - =/ arr - ?: =(ale a) - ale - ahh - :: - |- ^- @ - ?: (lth j 1) - (add (mul arr a) ell) - =/ f (prf (sub j 1) ell) - :: - :: Note that there is a slight deviation here to avoid dealing with - :: negative values. We add 'a' or 'b' to arr as appropriate and reduce - :: 'f' modulo the same number before performing subtraction. - :: - =/ tmp - ?. =((mod j 2) 0) - (mod (sub (add arr a) (mod f a)) a) - (mod (sub (add arr b) (mod f b)) b) - :: - $(j (sub j 1), ell tmp, arr ell) - :: - :: +eff: a murmur3-based pseudorandom function. 'F' in B&R (2002). - :: - ++ eff - |= [j=@ r=@] - ^- @ - (muk (snag j raku) 2 r) - :: - :: +raku: seeds for eff. - :: - ++ raku - ^- (list @ux) - :~ 0xb76d.5eed - 0xee28.1300 - 0x85bc.ae01 - 0x4b38.7af7 - == - :: - -- -:: -:: Exotic bases -:: -++ po :: phonetic base - ~/ %po - =+ :- ^= sis :: prefix syllables - 'dozmarbinwansamlitsighidfidlissogdirwacsabwissib\ - /rigsoldopmodfoglidhopdardorlorhodfolrintogsilmir\ - /holpaslacrovlivdalsatlibtabhanticpidtorbolfosdot\ - /losdilforpilramtirwintadbicdifrocwidbisdasmidlop\ - /rilnardapmolsanlocnovsitnidtipsicropwitnatpanmin\ - /ritpodmottamtolsavposnapnopsomfinfonbanmorworsip\ - /ronnorbotwicsocwatdolmagpicdavbidbaltimtasmallig\ - /sivtagpadsaldivdactansidfabtarmonranniswolmispal\ - /lasdismaprabtobrollatlonnodnavfignomnibpagsopral\ - /bilhaddocridmocpacravripfaltodtiltinhapmicfanpat\ - /taclabmogsimsonpinlomrictapfirhasbosbatpochactid\ - /havsaplindibhosdabbitbarracparloddosbortochilmac\ - /tomdigfilfasmithobharmighinradmashalraglagfadtop\ - /mophabnilnosmilfopfamdatnoldinhatnacrisfotribhoc\ - /nimlarfitwalrapsarnalmoslandondanladdovrivbacpol\ - /laptalpitnambonrostonfodponsovnocsorlavmatmipfip' - ^= dex :: suffix syllables - 'zodnecbudwessevpersutletfulpensytdurwepserwylsun\ - /rypsyxdyrnuphebpeglupdepdysputlughecryttyvsydnex\ - /lunmeplutseppesdelsulpedtemledtulmetwenbynhexfeb\ - /pyldulhetmevruttylwydtepbesdexsefwycburderneppur\ - /rysrebdennutsubpetrulsynregtydsupsemwynrecmegnet\ - /secmulnymtevwebsummutnyxrextebfushepbenmuswyxsym\ - /selrucdecwexsyrwetdylmynmesdetbetbeltuxtugmyrpel\ - /syptermebsetdutdegtexsurfeltudnuxruxrenwytnubmed\ - /lytdusnebrumtynseglyxpunresredfunrevrefmectedrus\ - /bexlebduxrynnumpyxrygryxfeptyrtustyclegnemfermer\ - /tenlusnussyltecmexpubrymtucfyllepdebbermughuttun\ - /bylsudpemdevlurdefbusbeprunmelpexdytbyttyplevmyl\ - /wedducfurfexnulluclennerlexrupnedlecrydlydfenwel\ - /nydhusrelrudneshesfetdesretdunlernyrsebhulryllud\ - /remlysfynwerrycsugnysnyllyndyndemluxfedsedbecmun\ - /lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes' - |% - ++ ins ~/ %ins :: parse prefix - |= a=@tas - =+ b=0 - |- ^- (unit @) - ?:(=(256 b) ~ ?:(=(a (tos b)) [~ b] $(b +(b)))) - ++ ind ~/ %ind :: parse suffix - |= a=@tas - =+ b=0 - |- ^- (unit @) - ?:(=(256 b) ~ ?:(=(a (tod b)) [~ b] $(b +(b)))) - ++ tos ~/ %tos :: fetch prefix - |=(a=@ ?>((lth a 256) (cut 3 [(mul 3 a) 3] sis))) - ++ tod ~/ %tod :: fetch suffix - |=(a=@ ?>((lth a 256) (cut 3 [(mul 3 a) 3] dex))) - -- -:: -++ fa :: base58check - =+ key='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' - =/ yek=@ux ~+ - =- yek:(roll (rip 3 key) -) - =+ [a=*char b=*@ yek=`@ux`(fil 3 256 0xff)] - |. - [+(b) (mix yek (lsh [3 `@u`a] (~(inv fe 3) b)))] - |% - ++ cha |=(a=char `(unit @uF)`=+(b=(cut 3 [`@`a 1] yek) ?:(=(b 0xff) ~ `b))) - ++ tok - |= a=@ux ^- @ux - =+ b=(pad a) - =- (~(net fe 5) (end [3 4] (shay 32 -))) - (shay (add b (met 3 a)) (lsh [3 b] (swp 3 a))) - :: - ++ pad |=(a=@ =+(b=(met 3 a) ?:((gte b 21) 0 (sub 21 b)))) - ++ enc |=(a=@ux `@ux`(mix (lsh [3 4] a) (tok a))) - ++ den - |= a=@ux ^- (unit @ux) - =+ b=(rsh [3 4] a) - ?. =((tok b) (end [3 4] a)) - ~ - `b - -- -:: -:: Text processing -:: -++ crip :: tape to cord - |= a=tape - ^- @t - (rap 3 a) -++ trip :: cord to tape - ~/ %trip - |= a=@ ^- tape - ?: =(0 (met 3 a)) - ~ - [^-(@ta (end 3 a)) $(a (rsh 3 a))] -:: -:: Parsing -:: -++ ne - |_ tig=@ - ++ c (cut 3 [tig 1] key:fa) - ++ d (add tig '0') - ++ x ?:((gte tig 10) (add tig 87) d) - ++ v ?:((gte tig 10) (add tig 87) d) - ++ w ?:(=(tig 63) '~' ?:(=(tig 62) '-' ?:((gte tig 36) (add tig 29) x))) - -- -:: -:: Atom printing -:: -++ co - !: - ~% %co ..co ~ - =< |_ lot=coin - ++ rear |=(rom=tape rend(rep rom)) - ++ rent ~+ `@ta`(rap 3 rend) - ++ rend - ^- tape - ~+ - ?: ?=(%blob -.lot) - ['~' '0' ((v-co 1) (jam p.lot))] - ?: ?=(%many -.lot) - :- '.' - |- ^- tape - ?~ p.lot - ['_' '_' rep] - ['_' (weld (trip (wack rent(lot i.p.lot))) $(p.lot t.p.lot))] - =+ [yed=(end 3 p.p.lot) hay=(cut 3 [1 1] p.p.lot)] - |- ^- tape - ?+ yed (z-co q.p.lot) - %p - =+ sxz=(fein:ob q.p.lot) - =+ dyx=(met 3 sxz) - :- '~' - ?: (lte dyx 1) - (weld (trip (tod:po sxz)) rep) - =+ dyy=(met 4 sxz) - =| imp=@ud - |- ^- tape - ?: =(imp dyy) - rep - %= $ - imp +(imp) - rep =/ log (cut 4 [imp 1] sxz) - ;: weld - (trip (tos:po (rsh 3 log))) - (trip (tod:po (end 3 log))) - ?:(=((mod imp 4) 0) ?:(=(imp 0) "" "--") "-") - rep - == == - :: - %u - ?: ?=(%c hay) - %+ welp ['0' 'c' (reap (pad:fa q.p.lot) '1')] - (c-co (enc:fa q.p.lot)) - :: - =; gam=(pair tape tape) - (weld p.gam ?:(=(0 q.p.lot) `tape`['0' ~] q.gam)) - ?+ hay [~ ((ox-co [10 3] |=(a=@ ~(d ne a))) q.p.lot)] - %b [['0' 'b' ~] ((ox-co [2 4] |=(a=@ ~(d ne a))) q.p.lot)] - %i [['0' 'i' ~] ((d-co 1) q.p.lot)] - %x [['0' 'x' ~] ((ox-co [16 4] |=(a=@ ~(x ne a))) q.p.lot)] - %v [['0' 'v' ~] ((ox-co [32 5] |=(a=@ ~(x ne a))) q.p.lot)] - %w [['0' 'w' ~] ((ox-co [64 5] |=(a=@ ~(w ne a))) q.p.lot)] - == - -- - =| rep=tape - =< |% - ++ c-co (em-co [58 1] |=([? b=@ c=tape] [~(c ne b) c])) - ++ d-co |=(min=@ (em-co [10 min] |=([? b=@ c=tape] [~(d ne b) c]))) - -- - |% - :: +em-co: format in numeric base - :: - :: in .bas, format .min digits of .hol with .par - :: - :: - .hol is processed least-significant digit first - :: - all available digits in .hol will be processed, but - :: .min digits can exceed the number available in .hol - :: - .par handles all accumulated output on each call, - :: and can edit it, prepend or append digits, &c - :: - until .hol is exhausted, .par's sample is [| digit output], - :: subsequently, it's [& 0 output] - :: - ++ em-co - |= [[bas=@ min=@] par=$-([? @ tape] tape)] - |= hol=@ - ^- tape - ?: &(=(0 hol) =(0 min)) - rep - =/ [dar=@ rad=@] (dvr hol bas) - %= $ - min ?:(=(0 min) 0 (dec min)) - hol dar - rep (par =(0 dar) rad rep) - == - :: - :: +ox-co: format '.'-separated digit sequences in numeric base - :: - :: in .bas, format each digit of .hol with .dug, - :: with '.' separators every .gop digits. - :: - :: - .hol is processed least-significant digit first - :: - .dug handles individual digits, output is prepended - :: - every segment but the last is zero-padded to .gop - :: - ++ ox-co - |= [[bas=@ gop=@] dug=$-(@ @)] - %+ em-co - [(pow bas gop) 0] - |= [top=? seg=@ res=tape] - %+ weld - ?:(top ~ `tape`['.' ~]) - %. seg - %+ em-co(rep res) - [bas ?:(top 0 gop)] - |=([? b=@ c=tape] [(dug b) c]) -:: -:: Formatting functions -:: -++ scow - ~/ %scow - |=(mol=dime ~(rend co %$ mol)) -:: -++ smyt :: pretty print path - |= bon=path ^- tank - :+ %rose [['/' ~] ['/' ~] ~] - (turn bon |=(a=@ [%leaf (trip a)])) -:: -:: Virtualization -:: -++ mack :: untyped, scry-less, unitary virtualization - |= [sub=* fol=*] - ^- (unit) - =/ ton (mink [sub fol] |~(^ ~)) - ?.(?=(%0 -.ton) ~ `product.ton) -:: -++ mink !. :: raw virtual nock - ~/ %mink - |= $: [subject=* formula=*] - scry=$-(^ (unit (unit))) - == - ~/ %sham.%mink - =| trace=(list [@ta *]) - |^ ^- tone - ?+ formula [%2 trace] - [^ *] - =/ head $(formula -.formula) - ?. ?=(%0 -.head) head - =/ tail $(formula +.formula) - ?. ?=(%0 -.tail) tail - [%0 product.head product.tail] - :: - [%0 axis=@] - =/ part (frag axis.formula subject) - ?~ part [%2 trace] - [%0 u.part] - :: - [%1 constant=*] - [%0 constant.formula] - :: - [%2 subject=* formula=*] - =/ subject $(formula subject.formula) - ?. ?=(%0 -.subject) subject - =/ formula $(formula formula.formula) - ?. ?=(%0 -.formula) formula - %= $ - subject product.subject - formula product.formula - == - :: - [%3 argument=*] - =/ argument $(formula argument.formula) - ?. ?=(%0 -.argument) argument - [%0 .?(product.argument)] - :: - [%4 argument=*] - =/ argument $(formula argument.formula) - ?. ?=(%0 -.argument) argument - ?^ product.argument [%2 trace] - [%0 .+(product.argument)] - :: - [%5 a=* b=*] - =/ a $(formula a.formula) - ?. ?=(%0 -.a) a - =/ b $(formula b.formula) - ?. ?=(%0 -.b) b - [%0 =(product.a product.b)] - :: - [%6 test=* yes=* no=*] - =/ result $(formula test.formula) - ?. ?=(%0 -.result) result - ?+ product.result - [%2 trace] - %& $(formula yes.formula) - %| $(formula no.formula) - == - :: - [%7 subject=* next=*] - =/ subject $(formula subject.formula) - ?. ?=(%0 -.subject) subject - %= $ - subject product.subject - formula next.formula - == - :: - [%8 head=* next=*] - =/ head $(formula head.formula) - ?. ?=(%0 -.head) head - %= $ - subject [product.head subject] - formula next.formula - == - :: - [%9 axis=@ core=*] - =/ core $(formula core.formula) - ?. ?=(%0 -.core) core - =/ arm (frag axis.formula product.core) - ?~ arm [%2 trace] - %= $ - subject product.core - formula u.arm - == - :: - [%10 [axis=@ value=*] target=*] - ?: =(0 axis.formula) [%2 trace] - =/ target $(formula target.formula) - ?. ?=(%0 -.target) target - =/ value $(formula value.formula) - ?. ?=(%0 -.value) value - =/ mutant=(unit *) - (edit axis.formula product.target product.value) - ?~ mutant [%2 trace] - [%0 u.mutant] - :: - [%11 tag=@ next=*] - =/ next $(formula next.formula) - ?. ?=(%0 -.next) next - :- %0 - .* subject - [11 tag.formula 1 product.next] - :: - [%11 [tag=@ clue=*] next=*] - =/ clue $(formula clue.formula) - ?. ?=(%0 -.clue) clue - =/ next - =? trace - ?=(?(%hunk %hand %lose %mean %spot) tag.formula) - [[tag.formula product.clue] trace] - $(formula next.formula) - ?. ?=(%0 -.next) next - :- %0 - .* subject - [11 [tag.formula 1 product.clue] 1 product.next] - :: - [%12 ref=* path=*] - =/ ref $(formula ref.formula) - ?. ?=(%0 -.ref) ref - =/ path $(formula path.formula) - ?. ?=(%0 -.path) path - =/ result (scry product.ref product.path) - ?~ result - [%1 product.path] - ?~ u.result - [%2 [%hunk product.ref product.path] trace] - [%0 u.u.result] - == - :: - ++ frag - |= [axis=@ noun=*] - ^- (unit) - ?: =(0 axis) ~ - |- ^- (unit) - ?: =(1 axis) `noun - ?@ noun ~ - =/ pick (cap axis) - %= $ - axis (mas axis) - noun ?-(pick %2 -.noun, %3 +.noun) - == - :: - ++ edit - |= [axis=@ target=* value=*] - ^- (unit) - ?: =(1 axis) `value - ?@ target ~ - =/ pick (cap axis) - =/ mutant - %= $ - axis (mas axis) - target ?-(pick %2 -.target, %3 +.target) - == - ?~ mutant ~ - ?- pick - %2 `[u.mutant +.target] - %3 `[-.target u.mutant] - == - -- -:: -++ mock :: virtual nock - |= [[sub=* fol=*] gul=$-(^ (unit (unit)))] - (mook (mink [sub fol] gul)) -:: -++ mook :: convert %tone to %toon - |= ton=tone - ^- toon - ?. ?=([%2 *] ton) - ton - |^ [%2 (turn skip rend)] - :: - ++ skip - ^+ trace.ton - =/ yel (lent trace.ton) - ?. (gth yel 1.024) trace.ton - %+ 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)}]>" - == - == - -- -:: -++ mole :: typed unitary virtual - :: XX: needs real jet dashboard to jet - ~/ %mole - |* tap=(trap) - ^- (unit _$:tap) - =/ mur (mure tap) - ?~(mur ~ `$:tap) -:: -++ mure :: untyped unitary virtual - |= tap=(trap) - ^- (unit) - =/ ton (mink [tap %9 2 %0 1] |=(a=^ ``.*(a [%12 [%0 2] %0 3]))) - ?.(?=(%0 -.ton) ~ `product.ton) -:: -++ soft :: virtual clam - |* han=$-(* *) - |=(fud=* (mole |.((han fud)))) +:: :: +:: :: 2p: serialization +:: :: +:: ++ cue :: unpack +:: ~/ %cue +:: |= a=@ +:: ^- * +:: =+ b=0 +:: =+ m=`(map @ *)`~ +:: =< q +:: |- ^- [p=@ q=* r=(map @ *)] +:: ?: =(0 (cut 0 [b 1] a)) +:: =+ c=(rub +(b) a) +:: [+(p.c) q.c (~(put by m) b q.c)] +:: =+ c=(add 2 b) +:: ?: =(0 (cut 0 [+(b) 1] a)) +:: =+ u=$(b c) +:: =+ v=$(b (add p.u c), m r.u) +:: =+ w=[q.u q.v] +:: [(add 2 (add p.u p.v)) w (~(put by r.v) b w)] +:: =+ d=(rub c a) +:: [(add 2 p.d) (need (~(get by m) q.d)) m] +:: :: +:: ++ jam :: pack +:: ~/ %jam +:: |= a=* +:: ^- @ +:: =+ b=0 +:: =+ m=`(map * @)`~ +:: =< q +:: |- ^- [p=@ q=@ r=(map * @)] +:: =+ c=(~(get by m) a) +:: ?~ c +:: => .(m (~(put by m) a b)) +:: ?: ?=(@ a) +:: =+ d=(mat a) +:: [(add 1 p.d) (lsh 0 q.d) m] +:: => .(b (add 2 b)) +:: =+ d=$(a -.a) +:: =+ e=$(a +.a, b (add b p.d), m r.d) +:: [(add 2 (add p.d p.e)) (mix 1 (lsh [0 2] (cat 0 q.d q.e))) r.e] +:: ?: ?&(?=(@ a) (lte (met 0 a) (met 0 u.c))) +:: =+ d=(mat a) +:: [(add 1 p.d) (lsh 0 q.d) m] +:: =+ d=(mat u.c) +:: [(add 2 p.d) (mix 3 (lsh [0 2] q.d)) m] +:: :: +:: :: SHA hashing +:: :: +:: ++ shay :: sha-256 with length +:: ~/ %shay +:: |= [len=@u ruz=@] ^- @ +:: => .(ruz (cut 3 [0 len] ruz)) +:: =+ [few==>(fe .(a 5)) wac=|=([a=@ b=@] (cut 5 [a 1] b))] +:: =+ [sum=sum.few ror=ror.few net=net.few inv=inv.few] +:: =+ ral=(lsh [0 3] len) +:: =+ ^= ful +:: %+ can 0 +:: :~ [ral ruz] +:: [8 128] +:: [(mod (sub 960 (mod (add 8 ral) 512)) 512) 0] +:: [64 (~(net fe 6) ral)] +:: == +:: =+ lex=(met 9 ful) +:: =+ ^= kbx 0xc671.78f2.bef9.a3f7.a450.6ceb.90be.fffa. +:: 8cc7.0208.84c8.7814.78a5.636f.748f.82ee. +:: 682e.6ff3.5b9c.ca4f.4ed8.aa4a.391c.0cb3. +:: 34b0.bcb5.2748.774c.1e37.6c08.19a4.c116. +:: 106a.a070.f40e.3585.d699.0624.d192.e819. +:: c76c.51a3.c24b.8b70.a81a.664b.a2bf.e8a1. +:: 9272.2c85.81c2.c92e.766a.0abb.650a.7354. +:: 5338.0d13.4d2c.6dfc.2e1b.2138.27b7.0a85. +:: 1429.2967.06ca.6351.d5a7.9147.c6e0.0bf3. +:: bf59.7fc7.b003.27c8.a831.c66d.983e.5152. +:: 76f9.88da.5cb0.a9dc.4a74.84aa.2de9.2c6f. +:: 240c.a1cc.0fc1.9dc6.efbe.4786.e49b.69c1. +:: c19b.f174.9bdc.06a7.80de.b1fe.72be.5d74. +:: 550c.7dc3.2431.85be.1283.5b01.d807.aa98. +:: ab1c.5ed5.923f.82a4.59f1.11f1.3956.c25b. +:: e9b5.dba5.b5c0.fbcf.7137.4491.428a.2f98 +:: =+ ^= hax 0x5be0.cd19.1f83.d9ab.9b05.688c.510e.527f. +:: a54f.f53a.3c6e.f372.bb67.ae85.6a09.e667 +:: =+ i=0 +:: |- ^- @ +:: ?: =(i lex) +:: (run 5 hax net) +:: =+ ^= wox +:: =+ dux=(cut 9 [i 1] ful) +:: =+ wox=(run 5 dux net) +:: =+ j=16 +:: |- ^- @ +:: ?: =(64 j) +:: wox +:: =+ :* l=(wac (sub j 15) wox) +:: m=(wac (sub j 2) wox) +:: n=(wac (sub j 16) wox) +:: o=(wac (sub j 7) wox) +:: == +:: =+ x=:(mix (ror 0 7 l) (ror 0 18 l) (rsh [0 3] l)) +:: =+ y=:(mix (ror 0 17 m) (ror 0 19 m) (rsh [0 10] m)) +:: =+ z=:(sum n x o y) +:: $(wox (con (lsh [5 j] z) wox), j +(j)) +:: =+ j=0 +:: =+ :* a=(wac 0 hax) +:: b=(wac 1 hax) +:: c=(wac 2 hax) +:: d=(wac 3 hax) +:: e=(wac 4 hax) +:: f=(wac 5 hax) +:: g=(wac 6 hax) +:: h=(wac 7 hax) +:: == +:: |- ^- @ +:: ?: =(64 j) +:: %= ^$ +:: i +(i) +:: hax %+ rep 5 +:: :~ (sum a (wac 0 hax)) +:: (sum b (wac 1 hax)) +:: (sum c (wac 2 hax)) +:: (sum d (wac 3 hax)) +:: (sum e (wac 4 hax)) +:: (sum f (wac 5 hax)) +:: (sum g (wac 6 hax)) +:: (sum h (wac 7 hax)) +:: == +:: == +:: =+ l=:(mix (ror 0 2 a) (ror 0 13 a) (ror 0 22 a)) :: s0 +:: =+ m=:(mix (dis a b) (dis a c) (dis b c)) :: maj +:: =+ n=(sum l m) :: t2 +:: =+ o=:(mix (ror 0 6 e) (ror 0 11 e) (ror 0 25 e)) :: s1 +:: =+ p=(mix (dis e f) (dis (inv e) g)) :: ch +:: =+ q=:(sum h o p (wac j kbx) (wac j wox)) :: t1 +:: $(j +(j), a (sum q n), b a, c b, d c, e (sum d q), f e, g f, h g) +:: :: +:: :: Scrambling +:: :: +:: ++ ob +:: ~% %ob ..ob +:: == +:: %fein fein +:: %fynd fynd +:: == +:: |% +:: :: +:: :: +fein: conceal structure, v3. +:: :: +:: :: +fein conceals planet-sized atoms. The idea is that it should not be +:: :: trivial to tell which planet a star has spawned under. +:: :: +:: ++ fein +:: ~/ %fein +:: |= pyn=@ ^- @ +:: ?: &((gte pyn 0x1.0000) (lte pyn 0xffff.ffff)) +:: (add 0x1.0000 (feis (sub pyn 0x1.0000))) +:: ?: &((gte pyn 0x1.0000.0000) (lte pyn 0xffff.ffff.ffff.ffff)) +:: =/ lo (dis pyn 0xffff.ffff) +:: =/ hi (dis pyn 0xffff.ffff.0000.0000) +:: %+ con hi +:: $(pyn lo) +:: pyn +:: :: +:: :: +fynd: restore structure, v3. +:: :: +:: :: Restores obfuscated values that have been enciphered with +fein. +:: :: +:: ++ fynd +:: ~/ %fynd +:: |= cry=@ ^- @ +:: ?: &((gte cry 0x1.0000) (lte cry 0xffff.ffff)) +:: (add 0x1.0000 (tail (sub cry 0x1.0000))) +:: ?: &((gte cry 0x1.0000.0000) (lte cry 0xffff.ffff.ffff.ffff)) +:: =/ lo (dis cry 0xffff.ffff) +:: =/ hi (dis cry 0xffff.ffff.0000.0000) +:: %+ con hi +:: $(cry lo) +:: cry +:: :: +feis: a four-round generalised Feistel cipher over the domain +:: :: [0, 2^32 - 2^16 - 1]. +:: :: +:: :: See: Black & Rogaway (2002), Ciphers for arbitrary finite domains. +:: :: +:: ++ feis +:: |= m=@ +:: ^- @ +:: (fee 4 0xffff 0x1.0000 (mul 0xffff 0x1.0000) eff m) +:: :: +:: :: +tail: reverse +feis. +:: :: +:: ++ tail +:: |= m=@ +:: ^- @ +:: (feen 4 0xffff 0x1.0000 (mul 0xffff 0x1.0000) eff m) +:: :: +:: :: +fee: "Fe" in B&R (2002). +:: :: +:: :: A Feistel cipher given the following parameters: +:: :: +:: :: r: number of Feistel rounds +:: :: a, b: parameters such that ab >= k +:: :: k: value such that the domain of the cipher is [0, k - 1] +:: :: prf: a gate denoting a family of pseudorandom functions indexed by +:: :: its first argument and taking its second argument as input +:: :: m: an input value in the domain [0, k - 1] +:: :: +:: ++ fee +:: |= [r=@ a=@ b=@ k=@ prf=$-([j=@ r=@] @) m=@] +:: ^- @ +:: =/ c (fe r a b prf m) +:: ?: (lth c k) +:: c +:: (fe r a b prf c) +:: :: +:: :: +feen: "Fe^-1" in B&R (2002). +:: :: +:: :: Reverses a Feistel cipher constructed with parameters as described in +:: :: +fee. +:: :: +:: ++ feen +:: |= [r=@ a=@ b=@ k=@ prf=$-([j=@ r=@] @) m=@] +:: ^- @ +:: =/ c (fen r a b prf m) +:: ?: (lth c k) +:: c +:: (fen r a b prf c) +:: :: +:: :: +fe: "fe" in B&R (2002). +:: :: +:: :: An internal function to +fee. +:: :: +:: :: Note that this implementation differs slightly from the reference paper +:: :: to support some legacy behaviour. See urbit/arvo#1105. +:: :: +:: ++ fe +:: |= [r=@ a=@ b=@ prf=$-([j=@ r=@] @) m=@] +:: =/ j 1 +:: =/ ell (mod m a) +:: =/ arr (div m a) +:: |- ^- @ +:: :: +:: ?: (gth j r) +:: ?. =((mod r 2) 0) +:: (add (mul arr a) ell) +:: :: +:: :: Note that +fe differs from B&R (2002)'s "fe" below, as a previous +:: :: implementation of this cipher contained a bug such that certain inputs +:: :: could encipher to the same output. +:: :: +:: :: To correct these problem cases while also preserving the cipher's +:: :: legacy behaviour on most inputs, we check for a problem case (which +:: :: occurs when 'arr' is equal to 'a') and, if detected, use an alternate +:: :: permutation instead. +:: :: +:: ?: =(arr a) +:: (add (mul arr a) ell) +:: (add (mul ell a) arr) +:: :: +:: =/ f (prf (sub j 1) arr) +:: :: +:: =/ tmp +:: ?. =((mod j 2) 0) +:: (mod (add f ell) a) +:: (mod (add f ell) b) +:: :: +:: $(j +(j), ell arr, arr tmp) +:: :: +:: :: +fen: "fe^-1" in B&R (2002). +:: :: +:: :: Note that this implementation differs slightly from the reference paper +:: :: to support some legacy behaviour. See urbit/arvo#1105. +:: :: +:: ++ fen +:: |= [r=@ a=@ b=@ prf=$-([j=@ r=@] @) m=@] +:: =/ j r +:: :: +:: =/ ahh +:: ?. =((mod r 2) 0) +:: (div m a) +:: (mod m a) +:: :: +:: =/ ale +:: ?. =((mod r 2) 0) +:: (mod m a) +:: (div m a) +:: :: +:: :: Similar to the comment in +fe, +fen differs from B&R (2002)'s "fe^-1" +:: :: here in order to preserve the legacy cipher's behaviour on most inputs. +:: :: +:: :: Here problem cases can be identified by 'ahh' equating with 'a'; we +:: :: correct those cases by swapping the values of 'ahh' and 'ale'. +:: :: +:: =/ ell +:: ?: =(ale a) +:: ahh +:: ale +:: :: +:: =/ arr +:: ?: =(ale a) +:: ale +:: ahh +:: :: +:: |- ^- @ +:: ?: (lth j 1) +:: (add (mul arr a) ell) +:: =/ f (prf (sub j 1) ell) +:: :: +:: :: Note that there is a slight deviation here to avoid dealing with +:: :: negative values. We add 'a' or 'b' to arr as appropriate and reduce +:: :: 'f' modulo the same number before performing subtraction. +:: :: +:: =/ tmp +:: ?. =((mod j 2) 0) +:: (mod (sub (add arr a) (mod f a)) a) +:: (mod (sub (add arr b) (mod f b)) b) +:: :: +:: $(j (sub j 1), ell tmp, arr ell) +:: :: +:: :: +eff: a murmur3-based pseudorandom function. 'F' in B&R (2002). +:: :: +:: ++ eff +:: |= [j=@ r=@] +:: ^- @ +:: (muk (snag j raku) 2 r) +:: :: +:: :: +raku: seeds for eff. +:: :: +:: ++ raku +:: ^- (list @ux) +:: :~ 0xb76d.5eed +:: 0xee28.1300 +:: 0x85bc.ae01 +:: 0x4b38.7af7 +:: == +:: :: +:: -- +:: :: +:: :: Exotic bases +:: :: +:: ++ po :: phonetic base +:: ~/ %po +:: =+ :- ^= sis :: prefix syllables +:: 'dozmarbinwansamlitsighidfidlissogdirwacsabwissib\ +:: /rigsoldopmodfoglidhopdardorlorhodfolrintogsilmir\ +:: /holpaslacrovlivdalsatlibtabhanticpidtorbolfosdot\ +:: /losdilforpilramtirwintadbicdifrocwidbisdasmidlop\ +:: /rilnardapmolsanlocnovsitnidtipsicropwitnatpanmin\ +:: /ritpodmottamtolsavposnapnopsomfinfonbanmorworsip\ +:: /ronnorbotwicsocwatdolmagpicdavbidbaltimtasmallig\ +:: /sivtagpadsaldivdactansidfabtarmonranniswolmispal\ +:: /lasdismaprabtobrollatlonnodnavfignomnibpagsopral\ +:: /bilhaddocridmocpacravripfaltodtiltinhapmicfanpat\ +:: /taclabmogsimsonpinlomrictapfirhasbosbatpochactid\ +:: /havsaplindibhosdabbitbarracparloddosbortochilmac\ +:: /tomdigfilfasmithobharmighinradmashalraglagfadtop\ +:: /mophabnilnosmilfopfamdatnoldinhatnacrisfotribhoc\ +:: /nimlarfitwalrapsarnalmoslandondanladdovrivbacpol\ +:: /laptalpitnambonrostonfodponsovnocsorlavmatmipfip' +:: ^= dex :: suffix syllables +:: 'zodnecbudwessevpersutletfulpensytdurwepserwylsun\ +:: /rypsyxdyrnuphebpeglupdepdysputlughecryttyvsydnex\ +:: /lunmeplutseppesdelsulpedtemledtulmetwenbynhexfeb\ +:: /pyldulhetmevruttylwydtepbesdexsefwycburderneppur\ +:: /rysrebdennutsubpetrulsynregtydsupsemwynrecmegnet\ +:: /secmulnymtevwebsummutnyxrextebfushepbenmuswyxsym\ +:: /selrucdecwexsyrwetdylmynmesdetbetbeltuxtugmyrpel\ +:: /syptermebsetdutdegtexsurfeltudnuxruxrenwytnubmed\ +:: /lytdusnebrumtynseglyxpunresredfunrevrefmectedrus\ +:: /bexlebduxrynnumpyxrygryxfeptyrtustyclegnemfermer\ +:: /tenlusnussyltecmexpubrymtucfyllepdebbermughuttun\ +:: /bylsudpemdevlurdefbusbeprunmelpexdytbyttyplevmyl\ +:: /wedducfurfexnulluclennerlexrupnedlecrydlydfenwel\ +:: /nydhusrelrudneshesfetdesretdunlernyrsebhulryllud\ +:: /remlysfynwerrycsugnysnyllyndyndemluxfedsedbecmun\ +:: /lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes' +:: |% +:: ++ ins ~/ %ins :: parse prefix +:: |= a=@tas +:: =+ b=0 +:: |- ^- (unit @) +:: ?:(=(256 b) ~ ?:(=(a (tos b)) [~ b] $(b +(b)))) +:: ++ ind ~/ %ind :: parse suffix +:: |= a=@tas +:: =+ b=0 +:: |- ^- (unit @) +:: ?:(=(256 b) ~ ?:(=(a (tod b)) [~ b] $(b +(b)))) +:: ++ tos ~/ %tos :: fetch prefix +:: |=(a=@ ?>((lth a 256) (cut 3 [(mul 3 a) 3] sis))) +:: ++ tod ~/ %tod :: fetch suffix +:: |=(a=@ ?>((lth a 256) (cut 3 [(mul 3 a) 3] dex))) +:: -- +:: :: +:: ++ fa :: base58check +:: =+ key='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' +:: =/ yek=@ux ~+ +:: =- yek:(roll (rip 3 key) -) +:: =+ [a=*char b=*@ yek=`@ux`(fil 3 256 0xff)] +:: |. +:: [+(b) (mix yek (lsh [3 `@u`a] (~(inv fe 3) b)))] +:: |% +:: ++ cha |=(a=char `(unit @uF)`=+(b=(cut 3 [`@`a 1] yek) ?:(=(b 0xff) ~ `b))) +:: ++ tok +:: |= a=@ux ^- @ux +:: =+ b=(pad a) +:: =- (~(net fe 5) (end [3 4] (shay 32 -))) +:: (shay (add b (met 3 a)) (lsh [3 b] (swp 3 a))) +:: :: +:: ++ pad |=(a=@ =+(b=(met 3 a) ?:((gte b 21) 0 (sub 21 b)))) +:: ++ enc |=(a=@ux `@ux`(mix (lsh [3 4] a) (tok a))) +:: ++ den +:: |= a=@ux ^- (unit @ux) +:: =+ b=(rsh [3 4] a) +:: ?. =((tok b) (end [3 4] a)) +:: ~ +:: `b +:: -- +:: :: +:: :: Text processing +:: :: +:: ++ crip :: tape to cord +:: |= a=tape +:: ^- @t +:: (rap 3 a) +:: ++ trip :: cord to tape +:: ~/ %trip +:: |= a=@ ^- tape +:: ?: =(0 (met 3 a)) +:: ~ +:: [^-(@ta (end 3 a)) $(a (rsh 3 a))] +:: :: +:: ++ wack :: knot escape +:: |= a=@ta +:: ^- @ta +:: =+ b=(rip 3 a) +:: %+ rap 3 +:: |- ^- tape +:: ?~ b +:: ~ +:: ?: =('~' i.b) ['~' '~' $(b t.b)] +:: ?: =('_' i.b) ['~' '-' $(b t.b)] +:: [i.b $(b t.b)] +:: :: +:: :: Parsing +:: :: +:: ++ ne +:: |_ tig=@ +:: ++ c (cut 3 [tig 1] key:fa) +:: ++ d (add tig '0') +:: ++ x ?:((gte tig 10) (add tig 87) d) +:: ++ v ?:((gte tig 10) (add tig 87) d) +:: ++ w ?:(=(tig 63) '~' ?:(=(tig 62) '-' ?:((gte tig 36) (add tig 29) x))) +:: -- +:: :: +:: :: Atom printing +:: :: +:: ++ co +:: !: +:: ~% %co ..co ~ +:: =< |_ lot=coin +:: ++ rear |=(rom=tape rend(rep rom)) +:: ++ rent ~+ `@ta`(rap 3 rend) +:: ++ rend +:: ^- tape +:: ~+ +:: ?: ?=(%blob -.lot) +:: ['~' '0' ((v-co 1) (jam p.lot))] +:: ?: ?=(%many -.lot) +:: :- '.' +:: |- ^- tape +:: ?~ p.lot +:: ['_' '_' rep] +:: ['_' (weld (trip (wack rent(lot i.p.lot))) $(p.lot t.p.lot))] +:: =+ [yed=(end 3 p.p.lot) hay=(cut 3 [1 1] p.p.lot)] +:: |- ^- tape +:: ?+ yed (z-co q.p.lot) +:: %p +:: =+ sxz=(fein:ob q.p.lot) +:: =+ dyx=(met 3 sxz) +:: :- '~' +:: ?: (lte dyx 1) +:: (weld (trip (tod:po sxz)) rep) +:: =+ dyy=(met 4 sxz) +:: =| imp=@ud +:: |- ^- tape +:: ?: =(imp dyy) +:: rep +:: %= $ +:: imp +(imp) +:: rep =/ log (cut 4 [imp 1] sxz) +:: ;: weld +:: (trip (tos:po (rsh 3 log))) +:: (trip (tod:po (end 3 log))) +:: ?:(=((mod imp 4) 0) ?:(=(imp 0) "" "--") "-") +:: rep +:: == == +:: :: +:: %u +:: ?: ?=(%c hay) +:: %+ welp ['0' 'c' (reap (pad:fa q.p.lot) '1')] +:: (c-co (enc:fa q.p.lot)) +:: :: +:: =; gam=(pair tape tape) +:: (weld p.gam ?:(=(0 q.p.lot) `tape`['0' ~] q.gam)) +:: ?+ hay [~ ((ox-co [10 3] |=(a=@ ~(d ne a))) q.p.lot)] +:: %b [['0' 'b' ~] ((ox-co [2 4] |=(a=@ ~(d ne a))) q.p.lot)] +:: %i [['0' 'i' ~] ((d-co 1) q.p.lot)] +:: %x [['0' 'x' ~] ((ox-co [16 4] |=(a=@ ~(x ne a))) q.p.lot)] +:: %v [['0' 'v' ~] ((ox-co [32 5] |=(a=@ ~(x ne a))) q.p.lot)] +:: %w [['0' 'w' ~] ((ox-co [64 5] |=(a=@ ~(w ne a))) q.p.lot)] +:: == +:: == +:: -- +:: =| rep=tape +:: =< |% +:: ++ c-co (em-co [58 1] |=([? b=@ c=tape] [~(c ne b) c])) +:: ++ d-co |=(min=@ (em-co [10 min] |=([? b=@ c=tape] [~(d ne b) c]))) +:: ++ v-co |=(min=@ (em-co [32 min] |=([? b=@ c=tape] [~(v ne b) c]))) +:: ++ x-co |=(min=@ (em-co [16 min] |=([? b=@ c=tape] [~(x ne b) c]))) +:: ++ y-co |=(dat=@ ((d-co 2) dat)) +:: ++ z-co |=(dat=@ `tape`['0' 'x' ((x-co 1) dat)]) +:: -- +:: |% + :: :: +em-co: format in numeric base + :: :: + :: :: in .bas, format .min digits of .hol with .par + :: :: + :: :: - .hol is processed least-significant digit first + :: :: - all available digits in .hol will be processed, but + :: :: .min digits can exceed the number available in .hol + :: :: - .par handles all accumulated output on each call, + :: :: and can edit it, prepend or append digits, &c + :: :: - until .hol is exhausted, .par's sample is [| digit output], + :: :: subsequently, it's [& 0 output] + :: :: + :: ++ em-co + :: |= [[bas=@ min=@] par=$-([? @ tape] tape)] + :: |= hol=@ + :: ^- tape + :: ?: &(=(0 hol) =(0 min)) + :: rep + :: =/ [dar=@ rad=@] (dvr hol bas) + :: %= $ + :: min ?:(=(0 min) 0 (dec min)) + :: hol dar + :: rep (par =(0 dar) rad rep) + :: == + :: :: + :: :: +ox-co: format '.'-separated digit sequences in numeric base + :: :: + :: :: in .bas, format each digit of .hol with .dug, + :: :: with '.' separators every .gop digits. + :: :: + :: :: - .hol is processed least-significant digit first + :: :: - .dug handles individual digits, output is prepended + :: :: - every segment but the last is zero-padded to .gop + :: :: + :: ++ ox-co + :: |= [[bas=@ gop=@] dug=$-(@ @)] + :: %+ em-co + :: [(pow bas gop) 0] + :: |= [top=? seg=@ res=tape] + :: %+ weld + :: ?:(top ~ `tape`['.' ~]) + :: %. seg + :: %+ em-co(rep res) + :: [bas ?:(top 0 gop)] + :: |=([? b=@ c=tape] [(dug b) c]) + :: -- +:: :: +:: :: Formatting functions +:: :: +:: ++ scow +:: ~/ %scow +:: |=(mol=dime ~(rend co %$ mol)) +:: :: +:: ++ smyt :: pretty print path +:: |= bon=path ^- tank +:: :+ %rose [['/' ~] ['/' ~] ~] +:: (turn bon |=(a=@ [%leaf (trip a)])) +:: :: +:: :: Virtualization +:: :: +:: ++ mack :: untyped, scry-less, unitary virtualization +:: |= [sub=* fol=*] +:: ^- (unit) +:: =/ ton (mink [sub fol] |~(^ ~)) +:: ?.(?=(%0 -.ton) ~ `product.ton) +:: :: +:: ++ mink !. :: raw virtual nock +:: ~/ %mink +:: |= $: [subject=* formula=*] +:: scry=$-(^ (unit (unit))) +:: == +:: ~> %sham.%mink +:: =| trace=(list [@ta *]) +:: |^ ^- tone +:: ?+ formula [%2 trace] +:: [^ *] +:: =/ head $(formula -.formula) +:: ?. ?=(%0 -.head) head +:: =/ tail $(formula +.formula) +:: ?. ?=(%0 -.tail) tail +:: [%0 product.head product.tail] +:: :: +:: [%0 axis=@] +:: =/ part (frag axis.formula subject) +:: ?~ part [%2 trace] +:: [%0 u.part] +:: :: +:: [%1 constant=*] +:: [%0 constant.formula] +:: :: +:: [%2 subject=* formula=*] +:: =/ subject $(formula subject.formula) +:: ?. ?=(%0 -.subject) subject +:: =/ formula $(formula formula.formula) +:: ?. ?=(%0 -.formula) formula +:: %= $ +:: subject product.subject +:: formula product.formula +:: == +:: :: +:: [%3 argument=*] +:: =/ argument $(formula argument.formula) +:: ?. ?=(%0 -.argument) argument +:: [%0 .?(product.argument)] +:: :: +:: [%4 argument=*] +:: =/ argument $(formula argument.formula) +:: ?. ?=(%0 -.argument) argument +:: ?^ product.argument [%2 trace] +:: [%0 .+(product.argument)] +:: :: +:: [%5 a=* b=*] +:: =/ a $(formula a.formula) +:: ?. ?=(%0 -.a) a +:: =/ b $(formula b.formula) +:: ?. ?=(%0 -.b) b +:: [%0 =(product.a product.b)] +:: :: +:: [%6 test=* yes=* no=*] +:: =/ result $(formula test.formula) +:: ?. ?=(%0 -.result) result +:: ?+ product.result +:: [%2 trace] +:: %& $(formula yes.formula) +:: %| $(formula no.formula) +:: == +:: :: +:: [%7 subject=* next=*] +:: =/ subject $(formula subject.formula) +:: ?. ?=(%0 -.subject) subject +:: %= $ +:: subject product.subject +:: formula next.formula +:: == +:: :: +:: [%8 head=* next=*] +:: =/ head $(formula head.formula) +:: ?. ?=(%0 -.head) head +:: %= $ +:: subject [product.head subject] +:: formula next.formula +:: == +:: :: +:: [%9 axis=@ core=*] +:: =/ core $(formula core.formula) +:: ?. ?=(%0 -.core) core +:: =/ arm (frag axis.formula product.core) +:: ?~ arm [%2 trace] +:: %= $ +:: subject product.core +:: formula u.arm +:: == +:: :: +:: [%10 [axis=@ value=*] target=*] +:: ?: =(0 axis.formula) [%2 trace] +:: =/ target $(formula target.formula) +:: ?. ?=(%0 -.target) target +:: =/ value $(formula value.formula) +:: ?. ?=(%0 -.value) value +:: =/ mutant=(unit *) +:: (edit axis.formula product.target product.value) +:: ?~ mutant [%2 trace] +:: [%0 u.mutant] +:: :: +:: [%11 tag=@ next=*] +:: =/ next $(formula next.formula) +:: ?. ?=(%0 -.next) next +:: :- %0 +:: .* subject +:: [11 tag.formula 1 product.next] +:: :: +:: [%11 [tag=@ clue=*] next=*] +:: =/ clue $(formula clue.formula) +:: ?. ?=(%0 -.clue) clue +:: =/ next +:: =? trace +:: ?=(?(%hunk %hand %lose %mean %spot) tag.formula) +:: [[tag.formula product.clue] trace] +:: $(formula next.formula) +:: ?. ?=(%0 -.next) next +:: :- %0 +:: .* subject +:: [11 [tag.formula 1 product.clue] 1 product.next] +:: :: +:: [%12 ref=* path=*] +:: =/ ref $(formula ref.formula) +:: ?. ?=(%0 -.ref) ref +:: =/ path $(formula path.formula) +:: ?. ?=(%0 -.path) path +:: =/ result (scry product.ref product.path) +:: ?~ result +:: [%1 product.path] +:: ?~ u.result +:: [%2 [%hunk product.ref product.path] trace] +:: [%0 u.u.result] +:: == +:: :: +:: ++ frag +:: |= [axis=@ noun=*] +:: ^- (unit) +:: ?: =(0 axis) ~ +:: |- ^- (unit) +:: ?: =(1 axis) `noun +:: ?@ noun ~ +:: =/ pick (cap axis) +:: %= $ +:: axis (mas axis) +:: noun ?-(pick %2 -.noun, %3 +.noun) +:: == +:: :: +:: ++ edit +:: |= [axis=@ target=* value=*] +:: ^- (unit) +:: ?: =(1 axis) `value +:: ?@ target ~ +:: =/ pick (cap axis) +:: =/ mutant +:: %= $ +:: axis (mas axis) +:: target ?-(pick %2 -.target, %3 +.target) +:: == +:: ?~ mutant ~ +:: ?- pick +:: %2 `[u.mutant +.target] +:: %3 `[-.target u.mutant] +:: == +:: -- +:: :: +:: ++ mock :: virtual nock +:: |= [[sub=* fol=*] gul=$-(^ (unit (unit)))] +:: (mook (mink [sub fol] gul)) +:: :: +:: ++ mook :: convert %tone to %toon +:: |= ton=tone +:: ^- toon +:: ?. ?=([%2 *] ton) +:: ton +:: |^ [%2 (turn skip rend)] +:: :: +:: ++ skip +:: ^+ trace.ton +:: =/ yel (lent trace.ton) +:: ?. (gth yel 1.024) trace.ton +:: %+ 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)}]>" +:: == +:: == +:: -- +:: :: +:: ++ mole :: typed unitary virtual +:: :: XX: needs real jet dashboard to jet +:: ~/ %mole +:: |* tap=(trap) +:: ^- (unit _$:tap) +:: =/ mur (mure tap) +:: ?~(mur ~ `$:tap) +:: :: +:: ++ mure :: untyped unitary virtual +:: |= tap=(trap) +:: ^- (unit) +:: =/ ton (mink [tap %9 2 %0 1] |=(a=^ ``.*(a [%12 [%0 2] %0 3]))) +:: ?.(?=(%0 -.ton) ~ `product.ton) +:: :: +:: ++ soft :: virtual clam +:: |* han=$-(* *) +:: |=(fud=* (mole |.((han fud)))) -- diff --git a/hoon/scaffolding/toddler.hoon b/hoon/scaffolding/toddler.hoon index 24416e3..56e9002 100644 --- a/hoon/scaffolding/toddler.hoon +++ b/hoon/scaffolding/toddler.hoon @@ -1,21 +1,17 @@ :: A working pill that grows towards arvo.hoon. Requires playpen.hoon from this :: scaffolding directory. :: -/+ cradle +/+ playpen !. =/ core - => cradle + => playpen != => |% - +$ card (cask) ++ cask |$ [a] (pair mark a) - +$ knot @ta - ++ list |$ [item] $@(~ [i=item t=(list item)]) +$ mark @tas + +$ card (cask) +$ ovum [=wire =card] - ++ pair |$ [head tail] [p=head q=tail] - +$ path (list knot) +$ wire path :: mutually recursive Ackermann functions :: test turning %spot hints on/off @@ -74,4 +70,4 @@ arvo .*([arvo -.epic] [%9 2 %10 [6 %0 3] %0 2]) == -- -[%pill %baby [aeon .*(cradle core) ~] ~ ~] +[%pill %toddler [aeon .*(playpen core) ~] ~ ~] diff --git a/rust/ares/src/interpreter.rs b/rust/ares/src/interpreter.rs index 64fe34d..6b7e9c7 100644 --- a/rust/ares/src/interpreter.rs +++ b/rust/ares/src/interpreter.rs @@ -948,14 +948,17 @@ fn match_hint_pre_nock( match tag.data() { tas!(b"slog") => { + // eprintln!("serf -> %slog start"); let slog_cell = res?.cell()?; let pri = slog_cell.head().direct()?.data(); let tank = slog_cell.tail(); if let Some(not) = newt { + // eprintln!("serf -> %slog hit newt"); not.slog(stack, pri, tank); } else { - println!("raw slog: {} {}", pri, tank); + eprintln!("raw slog: {} {}", pri, tank); } + // eprintln!("serf -> %slog end"); } tas!(b"hand") | tas!(b"hunk") | tas!(b"lose") | tas!(b"mean") | tas!(b"spot") => { let trace = Cell::new(stack, tag.as_noun(), res?).as_noun(); @@ -986,7 +989,7 @@ fn match_hint_pre_nock( if let Ok(Ok(toon)) = mook(stack, newt, tone, true).map(|t| t.as_cell()) { if unsafe { !toon.head().raw_equals(D(2)) } { - // Print jet errors and punt to Nock + // Print jet error and punt to Nock eprintln!("\r%hela failed: toon not %2"); return None; } diff --git a/rust/ares/src/jets.rs b/rust/ares/src/jets.rs index f6c5584..9b271c8 100644 --- a/rust/ares/src/jets.rs +++ b/rust/ares/src/jets.rs @@ -1,13 +1,16 @@ pub mod bits; +pub mod form; pub mod hash; pub mod math; pub mod nock; +pub mod text; pub mod tree; use crate::jets::bits::*; use crate::jets::hash::*; use crate::jets::math::*; use crate::jets::nock::*; +use crate::jets::text::*; use crate::jets::tree::*; use crate::mem::NockStack; use crate::newt::Newt; @@ -59,6 +62,8 @@ pub fn get_jet(jet_name: Noun) -> Option { tas!(b"cap") => Some(jet_cap), tas!(b"mas") => Some(jet_mas), // + tas!(b"lent") => Some(jet_lent), + // tas!(b"bex") => Some(jet_bex), tas!(b"can") => Some(jet_can), tas!(b"cat") => Some(jet_cat), @@ -78,6 +83,9 @@ pub fn get_jet(jet_name: Noun) -> Option { // tas!(b"mug") => Some(jet_mug), // + // Not currently in any pill + // tas!(b"scow") => Some(jet_scow), + // tas!(b"mink") => Some(jet_mink), _ => { // eprintln!("Unknown jet: {:?}", jet_name); diff --git a/rust/ares/src/jets/form.rs b/rust/ares/src/jets/form.rs new file mode 100644 index 0000000..f32c047 --- /dev/null +++ b/rust/ares/src/jets/form.rs @@ -0,0 +1,136 @@ +/** Formatting jets + */ +use crate::jets::Result; +use crate::jets::util::slot; +use crate::mem::NockStack; +use crate::newt::Newt; +use crate::noun::Noun; + +crate::gdb!(); + +pub fn jet_scow( + stack: &mut NockStack, + _newt: &mut Option<&mut Newt>, + subject: Noun +) -> Result { + let aura = slot(subject, 12)?.as_direct()?; + let atom = slot(subject, 13)?.as_atom()?; + util::scow(stack, aura, atom) +} + +pub mod util { + use crate::jets; + use crate::jets::JetErr; + use crate::jets::util::rip; + use crate::jets::text::util::lent; + use crate::mem::NockStack; + use crate::noun::{Atom, DirectAtom, Cell, CellMemory, D, T}; + use ares_macros::tas; + use std::result; + + fn num_to_ascii(num: u64) -> result::Result { + if num > 9 { + Err(JetErr::Deterministic) + } else { + Ok(num + 48) + } + } + + pub fn scow( + stack: &mut NockStack, + aura: DirectAtom, // XX: technically this should be Atom? + atom: Atom + ) -> jets::Result { + match aura.data() { + tas!(b"ud") => { + eprintln!("1"); + let tape = rip(stack, 3, 1, atom)?; + let mut lent = lent(tape)?; + + eprintln!("2"); + if lent == 0 { + assert!(tape.is_atom()); + return Ok(T(stack, &[D(num_to_ascii(0)?), D(0)])); + } + + eprintln!("3"); + unsafe { + let mut list = tape.as_cell()?; + let (root, mut memory) = Cell::new_raw_mut(stack); + (*memory).head = D(num_to_ascii(list.head().as_direct()?.data())?); + lent -= 1; + + eprintln!("4"); + let mut new_cell: Cell; + let mut new_memory: *mut CellMemory; + while lent > 0 { + list = list.tail().as_cell()?; + + if lent % 3 == 0 { + (new_cell, new_memory) = Cell::new_raw_mut(stack); + (*memory).tail = new_cell.as_noun(); + memory = new_memory; + (*memory).head = D(46); // '.' + } + + (new_cell, new_memory) = Cell::new_raw_mut(stack); + (*memory).tail = new_cell.as_noun(); + memory = new_memory; + (*memory).head = D(num_to_ascii(tape.as_cell()?.head().as_direct()?.data())?); + lent -= 1; + } + eprintln!("5"); + (*memory).tail = D(0); + + // 1 1 1 + // 10 2 2 + // 100 3 0 + // 1.000 4 1 + // 10.000 5 2 + // 100.000 6 0 + // 1.000.000 7 1 + + eprintln!("6"); + Ok(root.as_noun()) + } + } + _ => Err(JetErr::Punt) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::jets::JetErr; + use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack, A}; + use crate::noun::{D, T}; + use ares_macros::tas; + use ibig::ubig; + + #[test] + fn test_scow() { + let s = &mut init_stack(); + let aura = D(tas!(b"ud")); + let sam = T(s, &[aura, D(0)]); + let res = T(s, &[D(48), D(0)]); + assert_jet(s, jet_scow, sam, res); + let sam = T(s, &[aura, D(100)]); + let res = T(s, &[D(49), D(48), D(48), D(0)]); + assert_jet(s, jet_scow, sam, res); + let big = A(s, &ubig!(100)); + let sam = T(s, &[aura, big]); + let res = T(s, &[D(49), D(48), D(48), D(0)]); + assert_jet(s, jet_scow, sam, res); + let sam = T(s, &[aura, D(1000)]); + let res = T(s, &[D(49), D(46), D(48), D(48), D(48), D(0)]); + assert_jet(s, jet_scow, sam, res); + let big = A(s, &ubig!(1000)); + let sam = T(s, &[aura, big]); + let res = T(s, &[D(49), D(46), D(48), D(48), D(48), D(0)]); + assert_jet(s, jet_scow, sam, res); + let bad_aura = D(tas!(b"ux")); + let sam = T(s, &[bad_aura, D(0)]); + assert_jet_err(s, jet_scow, sam, JetErr::Punt); + } +} diff --git a/rust/ares/src/jets/hash.rs b/rust/ares/src/jets/hash.rs index a58262b..2ce6612 100644 --- a/rust/ares/src/jets/hash.rs +++ b/rust/ares/src/jets/hash.rs @@ -1,7 +1,7 @@ -use crate::jets::util::*; /** Hash jets */ use crate::jets::Result; +use crate::jets::util::*; use crate::mem::NockStack; use crate::mug::mug; use crate::newt::Newt; diff --git a/rust/ares/src/jets/nock.rs b/rust/ares/src/jets/nock.rs index 1efbb31..130ddf2 100644 --- a/rust/ares/src/jets/nock.rs +++ b/rust/ares/src/jets/nock.rs @@ -33,10 +33,11 @@ pub fn jet_mink( pub mod util { use crate::jets::util::rip; - use crate::jets::{jet_mink, JetErr, Result}; + use crate::jets::{JetErr, Result, jet_mink}; + use crate::jets::form::util::scow; use crate::mem::NockStack; use crate::newt::Newt; - use crate::noun::{tape, Noun, D, T}; + use crate::noun::{Noun, Cell, D, T, tape}; use ares_macros::tas; const LEAF: Noun = D(tas!(b"leaf")); @@ -96,49 +97,86 @@ pub mod util { } } tas!(b"spot") => { - let subj = T(stack, &[D(0), dat, D(0)]); - let tone = jet_mink(stack, newt, subj)?.as_cell()?; - if unsafe { !tone.head().raw_equals(D(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 { - let spot = tone.tail().as_cell()?; - let pint = spot.tail().as_cell()?; - let pstr = pint.head().as_cell()?; - let pend = pint.tail().as_cell()?; + // let subj = T(stack, &[D(0), dat, D(0)]); + // let tone = jet_mink(stack, newt, subj)?.as_cell()?; + // eprintln!("dat = {}", dat); + // eprintln!("tone = {}", tone); + // if unsafe { !tone.head().raw_equals(D(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 { + // let spot = tone.tail().as_cell()?; + let spot = dat.as_cell()?; + let pint = spot.tail().as_cell()?; + let pstr = pint.head().as_cell()?; + let pend = pint.tail().as_cell()?; - let colo = T(stack, &[D(tas!(b":")), D(0)]); - let trel = T(stack, &[colo, D(0), D(0)]); + let colo = T(stack, &[D(tas!(b":")), D(0)]); + let trel = T(stack, &[colo, D(0), D(0)]); - let smyt = smyt(stack, spot.head())?; + let smyt = smyt(stack, spot.head())?; - // XX: numbers not +scow-ed - let text = format!( - "<[{} {}.{} {}]>", - pstr.head().as_atom()?.as_either().either( - |l| l.data().to_string(), - |r| r.as_ubig(stack).to_string() - ), - pstr.tail().as_atom()?.as_either().either( - |l| l.data().to_string(), - |r| r.as_ubig(stack).to_string() - ), - pend.head().as_atom()?.as_either().either( - |l| l.data().to_string(), - |r| r.as_ubig(stack).to_string() - ), - pend.tail().as_atom()?.as_either().either( - |l| l.data().to_string(), - |r| r.as_ubig(stack).to_string() - ) - ); - let tape = tape(stack, &text); + let aura = D(tas!(b"ud")).as_direct()?; + let str_lin = scow(stack, aura, pstr.head().as_atom()?)?; + let str_col = scow(stack, aura, pstr.tail().as_atom()?)?; + let end_lin = scow(stack, aura, pend.head().as_atom()?)?; + let end_col = scow(stack, aura, pend.tail().as_atom()?)?; + + let mut list: Cell; + unsafe { + list = end_col.as_cell()?; + loop { + if let Some(_) = list.tail().atom() { + break; + } + list = list.tail().as_cell()?; + } + // "{end_col}]>" + let p4 = T(stack, &[D(93), D(62), D(0)]); + (*list.tail_as_mut()) = p4; + + list = end_lin.as_cell()?; + loop { + if let Some(_) = list.tail().atom() { + break; + } + list = list.tail().as_cell()?; + } + // "{end_lin} {end_col}]>" + let p3 = T(stack, &[D(32), end_col]); + (*list.tail_as_mut()) = p3; + + list = str_col.as_cell()?; + loop { + if let Some(_) = list.tail().atom() { + break; + } + list = list.tail().as_cell()?; + } + // "{str_col}.{end_lin} {end_col}]>" + let p2 = T(stack, &[D(46), end_lin]); + (*list.tail_as_mut()) = p2; + + list = str_lin.as_cell()?; + loop { + if let Some(_) = list.tail().atom() { + break; + } + list = list.tail().as_cell()?; + } + // "{str_lin} {str_col}.{end_lin} {end_col}]>" + let p1 = T(stack, &[D(32), str_col]); + (*list.tail_as_mut()) = p1; + + // "<[{str_lin} {str_col}.{end_lin} {end_col}]>" + let tape = T(stack, &[D(91), D(60), str_lin]); let finn = T(stack, &[LEAF, tape]); - + T(stack, &[ROSE, trel, smyt, finn]) } + // } } _ => { let tape = rip(stack, 3, 1, tag.as_atom())?; @@ -163,10 +201,11 @@ pub mod util { list = cell.tail(); } - Ok(res) + let ress = T(stack, &[D(2), res]); + Ok(ress) } 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)) + Ok(T(stack, &[D(2), D(0)])) } } diff --git a/rust/ares/src/jets/text.rs b/rust/ares/src/jets/text.rs new file mode 100644 index 0000000..b01533a --- /dev/null +++ b/rust/ares/src/jets/text.rs @@ -0,0 +1,64 @@ +/** Text processing jets + */ +use crate::jets::Result; +use crate::jets::util::slot; +use crate::mem::NockStack; +use crate::newt::Newt; +use crate::noun::{Noun, D}; + +crate::gdb!(); + +pub fn jet_lent( + _stack: &mut NockStack, + _newt: &mut Option<&mut Newt>, + subject: Noun +) -> Result { + let tape = slot(subject, 6)?; + util::lent(tape).map(|x| D(x as u64)) +} + +pub mod util { + use crate::jets::JetErr; + use crate::noun::Noun; + + pub fn lent(tape: Noun) -> Result { + let mut len = 0usize; + let mut list = tape; + loop { + if let Some(atom) = list.atom() { + if let None = atom.as_bitslice().first_one() { + break; + } else { + return Err(JetErr::Deterministic); + } + } + + let cell = list.as_cell()?; + // don't need checked_add or indirect atom result: 2^63-1 atoms would be 64 ebibytes + len += 1; + list = cell.tail(); + } + Ok(len) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::jets::JetErr; + use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack}; + use crate::noun::{D, T}; + + #[test] + fn test_lent() { + let s = &mut init_stack(); + assert_jet(s, jet_lent, D(0), D(0)); + let sam = T(s, &[D(1), D(2), D(3), D(0)]); + assert_jet(s, jet_lent, sam, D(3)); + let sam = T(s, &[D(3), D(2), D(1), D(0)]); + assert_jet(s, jet_lent, sam, D(3)); + assert_jet_err(s, jet_lent, D(1), JetErr::Deterministic); + let sam = T(s, &[D(3), D(2), D(1)]); + assert_jet_err(s, jet_lent, sam, JetErr::Deterministic); + } +} diff --git a/rust/ares/src/newt.rs b/rust/ares/src/newt.rs index 59de883..5385d4c 100644 --- a/rust/ares/src/newt.rs +++ b/rust/ares/src/newt.rs @@ -58,6 +58,7 @@ use either::Either; use std::io::{Read, Write}; use std::os::unix::prelude::FromRawFd; use std::ptr::copy_nonoverlapping; +use std::slice::from_raw_parts_mut; crate::gdb!(); @@ -80,13 +81,20 @@ impl Newt { * problem. */ fn write_noun(&mut self, stack: &mut NockStack, noun: Noun) { + // eprintln!("serf -> writing noun: {}", noun); let atom = jam(stack, noun); + // eprintln!("serf -> jammed noun: {}", atom); let size = atom.size() << 3; - let mut buf = vec![0u8; size + 5]; + // eprintln!("serf -> buffer size: {}", size); + // let mut buf = vec![0u8; size + 5]; + // XX: checked add? + let buf = unsafe { from_raw_parts_mut(stack.struct_alloc::(size + 5), size + 5) }; + // eprintln!("serf -> heap allocation?"); buf[1] = size as u8; buf[2] = (size >> 8) as u8; buf[3] = (size >> 16) as u8; buf[4] = (size >> 24) as u8; + // eprintln!("serf -> matching atom"); match atom.as_either() { Either::Left(direct) => unsafe { copy_nonoverlapping( @@ -105,10 +113,12 @@ impl Newt { }, }; self.output.write_all(&buf).unwrap(); + // eprintln!("serf -> done writing noun"); } /** Send %ripe, the first event. */ pub fn ripe(&mut self, stack: &mut NockStack, eve: u64, mug: u64) { + // eprintln!("serf -> ripe"); let version = T( stack, &[ @@ -123,42 +133,50 @@ impl Newt { /** Send %live, acknowledging. */ pub fn live(&mut self, stack: &mut NockStack) { + // eprintln!("serf -> live"); let live = T(stack, &[D(tas!(b"live")), D(0)]); self.write_noun(stack, live); } /** Send %slog, pretty-printed debug output. */ pub fn slog(&mut self, stack: &mut NockStack, pri: u64, tank: Noun) { + // eprintln!("serf -> starting slog"); let slog = T(stack, &[D(tas!(b"slog")), D(pri), tank]); self.write_noun(stack, slog); + // eprintln!("serf -> ending slog"); } /** Send %flog, raw debug output. */ pub fn flog(&mut self, stack: &mut NockStack, cord: Noun) { + // eprintln!("serf -> flog"); let flog = T(stack, &[D(tas!(b"flog")), cord]); self.write_noun(stack, flog); } /** Send %peek %done, successfully scried. */ pub fn peek_done(&mut self, stack: &mut NockStack, dat: Noun) { + // eprintln!("serf -> peek done"); let peek = T(stack, &[D(tas!(b"peek")), D(tas!(b"done")), dat]); self.write_noun(stack, peek); } /** Send %peek %bail, unsuccessfully scried. */ pub fn peek_bail(&mut self, stack: &mut NockStack, dud: Noun) { + // eprintln!("serf -> peek bail"); let peek = T(stack, &[D(tas!(b"peek")), D(tas!(b"bail")), dud]); self.write_noun(stack, peek); } /** Send %play %done, successfully replayed events. */ pub fn play_done(&mut self, stack: &mut NockStack, mug: u64) { + // eprintln!("serf -> play done"); let play = T(stack, &[D(tas!(b"play")), D(tas!(b"done")), D(mug)]); self.write_noun(stack, play); } /** Send %play %bail, failed to replay events. */ pub fn play_bail(&mut self, stack: &mut NockStack, eve: u64, mug: u64, dud: Noun) { + // eprintln!("serf -> play bail"); let play = T( stack, &[D(tas!(b"play")), D(tas!(b"bail")), D(eve), D(mug), dud], @@ -168,6 +186,7 @@ impl Newt { /** Send %work %done, successfully ran event. */ pub fn work_done(&mut self, stack: &mut NockStack, eve: u64, mug: u64, fec: Noun) { + // eprintln!("serf -> work done"); let work = T( stack, &[D(tas!(b"work")), D(tas!(b"done")), D(eve), D(mug), fec], @@ -177,6 +196,7 @@ impl Newt { /** Send %work %swap, successfully replaced failed event. */ pub fn work_swap(&mut self, stack: &mut NockStack, eve: u64, mug: u64, job: Noun, fec: Noun) { + // eprintln!("serf -> work swap"); let work = T( stack, &[D(tas!(b"work")), D(tas!(b"swap")), D(eve), D(mug), job, fec], @@ -186,6 +206,7 @@ impl Newt { /** Send %work %bail, failed to run event. */ pub fn work_bail(&mut self, stack: &mut NockStack, lud: Noun) { + // eprintln!("serf -> work bail"); let work = T(stack, &[D(tas!(b"work")), D(tas!(b"bail")), lud]); self.write_noun(stack, work); } diff --git a/rust/ares/src/noun.rs b/rust/ares/src/noun.rs index 5ab5482..785bc11 100644 --- a/rust/ares/src/noun.rs +++ b/rust/ares/src/noun.rs @@ -454,6 +454,9 @@ impl IndirectAtom { } } +// XX: Need a version that either: +// a) allocates on the NockStack directly for creating a tape (or even a string?) +// b) disables no-allocation, creates a string, utilitzes it (eprintf or generate tape), and then deallocates impl fmt::Display for IndirectAtom { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "0x")?; diff --git a/rust/ares/src/serf.rs b/rust/ares/src/serf.rs index 5fa8b99..5e381ff 100644 --- a/rust/ares/src/serf.rs +++ b/rust/ares/src/serf.rs @@ -44,13 +44,16 @@ pub fn serf() -> io::Result<()> { let (_epoch, mut event_number, mut arvo) = snap.load(stack).unwrap_or((0, 0, D(0))); let mug = mug_u32(stack, arvo); + // eprintln!("serf -> something is happening"); newt.ripe(stack, event_number, mug as u64); - + // Can't use for loop because it borrows newt while let Some(writ) = newt.next(stack) { + // eprintln!("serf -> loop has begun"); let tag = slot(writ, 2)?.as_direct().unwrap(); match tag.data() { tas!(b"live") => { + // eprintln!("serf -> incoming %live"); let inner = slot(writ, 6)?.as_direct().unwrap(); match inner.data() { tas!(b"cram") => eprintln!("cram"), @@ -67,12 +70,14 @@ pub fn serf() -> io::Result<()> { newt.live(stack); } tas!(b"peek") => { + // eprintln!("serf -> incoming %peek"); let sam = slot(writ, 7)?; let res = slam(stack, newt, arvo, PEEK_AXIS, sam) .expect("peek error handling unimplemented"); newt.peek_done(stack, res); } tas!(b"play") => { + // eprintln!("serf -> incoming %play"); let run = if event_number == 0 { // apply lifecycle to first batch let lit = slot(writ, 7)?; @@ -107,6 +112,7 @@ pub fn serf() -> io::Result<()> { newt.play_done(stack, 0); } tas!(b"work") => { + // eprintln!("serf -> incoming %work"); let ovo = slot(writ, 7)?; let res = slam(stack, newt, arvo, POKE_AXIS, ovo) .expect("work error handling unimplemented")