mirror of
https://github.com/urbit/shrub.git
synced 2024-12-14 01:08:54 +03:00
1225 lines
47 KiB
Plaintext
1225 lines
47 KiB
Plaintext
:: :: ::
|
|
:::: /hoon/ames/arvo :::::: vane prelude
|
|
!: :: ::
|
|
|= pit/vase :: kernel vase
|
|
=> =~ ::
|
|
:: :: ::
|
|
:::: :::::: ames structures
|
|
:: :: ::
|
|
|% ::
|
|
++ bait {p/skin q/@ud r/dove} :: fmt nrecvd spec
|
|
++ bath :: per friend
|
|
$: det/pipe :: secure channel
|
|
waz/(list ship) :: path to
|
|
lun/(unit lane) :: latest route
|
|
zam/scar :: outbound boles
|
|
fon/(map bole lock) :: inbound locks
|
|
sal/(map bole colt) :: outbound flows
|
|
== ::
|
|
++ bole bone :: inbound opaque
|
|
++ cake {p/sock q/skin r/@} :: top level packet
|
|
++ chan path :: channel
|
|
++ clue :: live packet state
|
|
$: vig/? :: true iff virgin
|
|
tel/part :: block identity
|
|
fap/flap :: fragment hash
|
|
dat/rock :: fragment data
|
|
== ::
|
|
++ coal :: live packet state
|
|
$: out/@da :: sent date
|
|
lod/@da :: lost-by deadline
|
|
clu/clue :: packet to send
|
|
== ::
|
|
++ colt :: outbound state
|
|
$: seq/tick :: next tick to fill
|
|
lac/tick :: acked tick until
|
|
cob/(map tick comb) :: live messages
|
|
myn/mini :: packet pump
|
|
== ::
|
|
++ comb :: live message
|
|
$: cup/(unit coop) :: final ack
|
|
cha/path :: channel
|
|
num/frag :: number of fragments
|
|
ack/frag :: number acked
|
|
cly/(list clue) :: left to send
|
|
== ::
|
|
++ dove {p/@ud q/(map @ud @)} :: count 13-blocks
|
|
++ flap @uvH :: network packet id
|
|
++ flea (pair bole tick) :: message id
|
|
++ frag @ud :: fragment number
|
|
++ lock :: inbound sequencer
|
|
$: laq/tick :: acknowledged until
|
|
nys/(map tick bait) :: inbound partials
|
|
laz/(unit (trel tick flap lane)) :: awaiting app
|
|
exc/(map tick ares) :: negative acks
|
|
== ::
|
|
++ meal :: payload
|
|
$% {$back p/bone q/flap r/coop s/@dr} :: acknowledgment
|
|
{$bond p/flea q/chan r/*} :: message
|
|
{$carp p/moan q/(pair @ud @)} :: fragment
|
|
{$fore p/ship q/(unit lane) r/@} :: forwarded packet
|
|
== ::
|
|
++ mini :: pump data
|
|
$: saw/stat :: statistics
|
|
liv/(qeu coal) :: live packets
|
|
lop/(qeu clue) :: lost packets
|
|
== ::
|
|
++ moan :: message invariant
|
|
$: {kos/bole liq/tick} :: flow identity
|
|
syn/@ :: skin number
|
|
cnt/@ :: number of packets
|
|
== ::
|
|
++ part (pair frag tick) :: fragment of packet
|
|
++ silo ::
|
|
$: pol/(map ship bath) :: network state
|
|
== ::
|
|
++ skin ?($none $open $fast $full) :: encoding stem
|
|
++ stat :: pump statistics
|
|
$: $: cur/@ud :: window q length
|
|
max/@ud :: max pax out
|
|
rey/@ud :: retry q length
|
|
== ::
|
|
$: rtt/@dr :: roundtrip estimate
|
|
las/@da :: last sent
|
|
lad/@da :: last deadline
|
|
== ::
|
|
== ::
|
|
++ tick @ud :: message sequence no
|
|
-- ::
|
|
:: ::
|
|
:::: :::: arvo structures
|
|
:: ::
|
|
|% ::
|
|
++ flam |=(a/flap `@p`(mug a)) :: debug flap
|
|
++ msec |=(a/@dr `@ud`(div a (div ~s1 1.000))) :: debug @dr
|
|
++ move {p/duct q/(wind note-xmas gift-xmas)} :: local move
|
|
:: ::
|
|
:::: loft :::: main transceiver
|
|
:: ::
|
|
++ loft ::
|
|
=> |% ::
|
|
++ gift :: output
|
|
$% {$east p/duct q/ship r/chan s/*} :: network response
|
|
{$home p/lane q/@} :: resend to self
|
|
{$line p/ship q/@da r/code} :: add outbound key
|
|
{$link p/ship q/@da r/code} :: add inbound key
|
|
{$meet p/gree} :: add public key(s)
|
|
{$rest p/duct q/coop} :: message result
|
|
{$send p/lane q/@} :: transmit packet
|
|
{$view p/ship} :: cache channel
|
|
{$west p/ship q/bole r/chan s/*} :: outbound message
|
|
== ::
|
|
++ task :: input
|
|
$% {$clue p/ship q/pipe} :: update channel
|
|
{$done p/ship q/bole r/coop} :: completion
|
|
{$hear p/lane q/@} :: incoming packet
|
|
{$mess p/ship q/duct r/chan s/*} :: forward message
|
|
{$rend p/ship q/bole r/chan s/*} :: backward message
|
|
{$wake $~} :: wakeup
|
|
==
|
|
--
|
|
=| $: $: now/@da
|
|
eny/@
|
|
see/$-(ship pipe)
|
|
==
|
|
silo
|
|
fex/(list gift)
|
|
==
|
|
=* syl ->-
|
|
|% ::
|
|
++ abet [(flop fex) syl] :: resolve
|
|
++ apex :: compute
|
|
|= job/task
|
|
^+ +>
|
|
?- -.job
|
|
$clue abet:(clue:(etre p.job) q.job)
|
|
$done abet:(done:(etre p.job) q.job r.job)
|
|
$hear
|
|
=+ kec=(bite q.job)
|
|
?> =(our q.p.kec)
|
|
=^ etc +>.$ (etch p.p.kec)
|
|
abet:(hear:etc p.job (shaf %flap q.job) q.kec r.kec)
|
|
::
|
|
$mess
|
|
=^ etc +>.$ (etch p.job)
|
|
=^ kos etc (blow:etc q.job)
|
|
abet:(mess:etc kos r.job s.job)
|
|
::
|
|
$rend
|
|
abet:(mess:(etre p.job) q.job r.job s.job)
|
|
::
|
|
$wake
|
|
|- ^+ +>.^$
|
|
?~ pol +>.^$
|
|
=+ lef=$(pol l.pol)
|
|
=+ ryt=$(pol r.pol, fex fex.lef)
|
|
=+ top=~(to-wake et(fex fex.ryt) n.pol)
|
|
+>.^$(fex fex.top, pol [+<.top pol.lef pol.ryt])
|
|
== ::
|
|
::
|
|
++ doze :: sleep until
|
|
|- ^- (unit @da)
|
|
?~ pol ~
|
|
;: hunt
|
|
$(pol l.pol)
|
|
$(pol r.pol)
|
|
~(to-wait et p.n.pol q.n.pol)
|
|
==
|
|
:: ::
|
|
++ etch :: new neighbor
|
|
|= who/@p
|
|
=+ buh=(~(get by pol) who)
|
|
?^ buh
|
|
:: old neighbor; channel already registered
|
|
[~(. et who u.buh) +>.$]
|
|
:: new neighbor; register secure channel view
|
|
:_ +>.$(fex [[%view who] fex])
|
|
~(. et who `bath`[(see who) (seek our who) ~ [2 ~ ~] ~ ~])
|
|
:: ::
|
|
++ etre :: old neighbor
|
|
|= who/@p
|
|
~(. et who (~(got by pol) who))
|
|
:: ::
|
|
++ et :: per neighbor
|
|
|_ $: who/ship
|
|
bah/bath
|
|
==
|
|
++ abet +>(pol (~(put by pol) who bah)) :: resolve
|
|
++ acme |=(fic/gift +>(fex [fic fex])) :: effect
|
|
++ blow :: register duct
|
|
|= hen/duct
|
|
^- {bole _+>}
|
|
=+ kus=(~(get by q.zam.bah) hen)
|
|
?^ kus [u.kus +>.$]
|
|
:- p.zam.bah
|
|
%= +>.$
|
|
p.zam.bah (add 2 p.zam.bah)
|
|
q.zam.bah (~(put by q.zam.bah) hen p.zam.bah)
|
|
r.zam.bah (~(put by r.zam.bah) p.zam.bah hen)
|
|
==
|
|
::
|
|
++ clue |=(det/pipe +>(det.bah det)) :: purge security
|
|
++ done
|
|
|= {kos/bole cop/coop}
|
|
^+ +>
|
|
(in-task %done +<)
|
|
:: ::
|
|
++ have :: receive message
|
|
|= {kos/bole cha/chan val/*}
|
|
^+ +>
|
|
?: =(0 (end 0 1 kos))
|
|
=+ hen=(~(got by r.zam.bah) kos)
|
|
::
|
|
:: if the bole is even, this is a backward flow,
|
|
:: like a subscription update; ack automatically.
|
|
::
|
|
(acme:(in-task %done kos ~) %east hen who cha val)
|
|
::
|
|
:: if the bole is odd, it's a forward flow. we
|
|
:: need to wait for the target to actively ack it.
|
|
::
|
|
(acme %west who kos cha val)
|
|
::
|
|
++ hear ::
|
|
|= {lyn/lane dam/flap syn/skin msg/@} :: hear packet
|
|
^+ +>
|
|
(in-task %hear +<)
|
|
:: ::
|
|
++ mess :: send message
|
|
|= {kos/bole cha/chan val/*}
|
|
^+ +>
|
|
(to-task kos %mess cha val)
|
|
:: ::
|
|
++ sack :: send acknowledgment
|
|
|= {kos/bole dam/flap cop/coop}
|
|
=+ yex=((knit who det.bah) now eny [%back (mix kos 1) dam cop ~s0])
|
|
=. +>.$ (to-gifs p.yex)
|
|
|- ^+ +>.^$
|
|
?~ q.yex +>.^$
|
|
$(q.yex t.q.yex, +>.^$ (send ~ i.q.yex))
|
|
:: ::
|
|
++ send :: send packet
|
|
|= {urg/(unit lane) pac/rock}
|
|
^+ +>
|
|
?: =(our who) (acme [%send *lane pac])
|
|
=+ zaw=waz.bah
|
|
|- ^+ +>.^$
|
|
?~ zaw +>.^$
|
|
=+ ^= lun ^- (unit lane)
|
|
?: (lth i.zaw 256)
|
|
::
|
|
:: galaxies are mapped into reserved IP space,
|
|
:: which the interpreter maps into a DNS request.
|
|
::
|
|
[~ %if ~2000.1.1 31.337 (mix i.zaw .0.0.1.0)]
|
|
?: =(who i.zaw) lun.bah
|
|
=+ hab=(~(get by pol) i.zaw)
|
|
?~(hab ~ lun.u.hab)
|
|
?~ lun
|
|
$(zaw t.zaw)
|
|
=. pac ?: &(=(i.zaw who) =(~ urg))
|
|
pac
|
|
::
|
|
:: forwarded packets are not signed/encrypted,
|
|
:: because (a) we don't need to; (b) we don't
|
|
:: want to turn one packet into two. the wrapped
|
|
:: packet may exceed 8192 bits, but it's unlikely
|
|
:: to blow the MTU (IP MTU == 1500).
|
|
::
|
|
(spit [our i.zaw] %none (jam `meal`[%fore who urg pac]))
|
|
=. +>.^$ (acme %send u.lun pac)
|
|
::
|
|
:: stop if we have an %if (direct) address;
|
|
:: continue if we only have %ix (forwarded).
|
|
::
|
|
?:(?=($if -.u.lun) +>.^$ $(zaw t.zaw))
|
|
::
|
|
++ in-gift
|
|
|= hox/gift:hose
|
|
^+ +>
|
|
?- -.hox
|
|
$fore
|
|
?: =(our her.hox)
|
|
(acme %home org.hox pac.hox)
|
|
(send(who her.hox) [~ org.hox] pac.hox)
|
|
::
|
|
$have (have +.hox)
|
|
$link (acme %link who exp.hox key.hox)
|
|
$meet (acme hox)
|
|
$rack (to-task kos.hox %back dam.hox cop.hox ~s0)
|
|
$rout +>(lun.bah `lyn.hox)
|
|
$sack (sack +.hox)
|
|
==
|
|
::
|
|
++ in-gifs
|
|
|= hoz/(list gift:hose)
|
|
?~ hoz +>
|
|
$(hoz t.hoz, +> (in-gift i.hoz))
|
|
::
|
|
++ to-gift
|
|
|= rax/gift:rail
|
|
?- -.rax
|
|
$line (acme %line who ~2018.1.1 q.rax)
|
|
$mack (acme %rest (~(got by r.zam.bah) p.rax) q.rax)
|
|
$send (send ~ q.rax)
|
|
==
|
|
::
|
|
++ to-gifs
|
|
|= raz/(list gift:rail)
|
|
?~ raz +>
|
|
$(raz t.raz, +> (to-gift i.raz))
|
|
::
|
|
++ in-task
|
|
|= kyz/task:hose
|
|
^+ +>
|
|
=^ hoz fon.bah abet:(~(apex hose [who det.bah] ~ fon.bah) kyz)
|
|
(in-gifs hoz)
|
|
::
|
|
++ to-task
|
|
|= {kos/bole kyz/task:rail}
|
|
^+ +>
|
|
=+ cot=((bond |.(zeal:rail)) (~(get by sal.bah) kos))
|
|
=^ raz cot abet:(work:(to-rail kos cot) kyz)
|
|
(to-gifs raz)
|
|
::
|
|
++ to-rail
|
|
|= {kos/bole cot/colt}
|
|
~(. rail [[who det.bah] [now eny] kos (yawn:pump myn.cot) ~] cot)
|
|
::
|
|
++ to-wait
|
|
|- ^- (unit @da)
|
|
?~ sal.bah ~
|
|
;: hunt
|
|
$(sal.bah l.sal.bah)
|
|
$(sal.bah r.sal.bah)
|
|
wait:(to-rail p.n.sal.bah q.n.sal.bah)
|
|
==
|
|
::
|
|
++ to-wake
|
|
|- ^+ +.$
|
|
?~ sal.bah +.$
|
|
=+ lef=$(sal.bah l.sal.bah)
|
|
=+ ryt=$(sal.bah r.sal.bah, fex fex.lef)
|
|
=+ top=(work:(to-rail(fex fex.ryt) p.n.sal.bah q.n.sal.bah) %wake ~)
|
|
+.$(fex fex.ryt, sal.bah [[kos cot]:top sal.bah.lef sal.bah.ryt])
|
|
--
|
|
--
|
|
::
|
|
:::: inbound cores
|
|
::
|
|
:: ::
|
|
:::: bite :::: packet format
|
|
:: ::
|
|
++ bite :: packet to cake
|
|
|= pac/rock ^- cake
|
|
=+ [mag=(end 5 1 pac) bod=(rsh 5 1 pac)]
|
|
=+ :* vez=(end 0 3 mag) :: protocol version
|
|
chk=(cut 0 [3 20] mag) :: checksum
|
|
wix=(bex +((cut 0 [23 2] mag))) :: width of receiver
|
|
vix=(bex +((cut 0 [25 2] mag))) :: width of sender
|
|
tay=(cut 0 [27 5] mag) :: message type
|
|
==
|
|
?> =(7 vez)
|
|
?> =(chk (end 0 20 (mug bod)))
|
|
:+ [(end 3 wix bod) (cut 3 [wix vix] bod)]
|
|
(kins tay)
|
|
(rsh 3 (add wix vix) bod)
|
|
::
|
|
++ kins |=(tay/@ (snag tay `(list skin)`[%none %open %fast %full ~]))
|
|
++ ksin |=(sin/skin `@`?-(sin $none 0, $open 1, $fast 2, $full 3))
|
|
++ seek :: path to
|
|
|= {our/ship her/ship}
|
|
^- (list ship)
|
|
::
|
|
:: in order of routing desirability, from `our`
|
|
:: to `who`, up their hierarchy to the least
|
|
:: common ancestor, then up ours to the root.
|
|
::
|
|
=+ [fro=t.+:(saxo our) too=(saxo her)]
|
|
|- ^- (list ship)
|
|
?~ too fro
|
|
?: =(our i.too)
|
|
:: the target is one of our children.
|
|
~
|
|
?: (lien fro |=(a/ship =(a i.too)))
|
|
:: a parent of the target is in our own hierarchy.
|
|
:: clip the target hierarchy here and add our own
|
|
:: hierarchy, from bottom to top.
|
|
|- ^- (list ship)
|
|
?~ fro !!
|
|
?:(=(i.fro i.too) [i.too ~] [i.fro $(fro t.fro)])
|
|
[i.too $(too t.too)]
|
|
::
|
|
++ spit :: cake to packet
|
|
|= kec/cake ^- @
|
|
=+ wim=(met 3 p.p.kec)
|
|
=+ dum=(met 3 q.p.kec)
|
|
=+ yax=?:((lte wim 2) 0 ?:((lte wim 4) 1 ?:((lte wim 8) 2 3)))
|
|
=+ qax=?:((lte dum 2) 0 ?:((lte dum 4) 1 ?:((lte dum 8) 2 3)))
|
|
=+ wix=(bex +(yax))
|
|
=+ vix=(bex +(qax))
|
|
=+ bod=:(mix p.p.kec (lsh 3 wix q.p.kec) (lsh 3 (add wix vix) r.kec))
|
|
=+ tay=(ksin q.kec)
|
|
%+ mix
|
|
%+ can 0
|
|
:~ [3 7]
|
|
[20 (mug bod)]
|
|
[2 yax]
|
|
[2 qax]
|
|
[5 tay]
|
|
==
|
|
(lsh 5 1 bod)
|
|
:: ::
|
|
:::: nose :::: packet decoder
|
|
:: ::
|
|
++ nose !:
|
|
=> |%
|
|
++ gift :: side effect
|
|
$% {$link exp/@da key/code} :: learn symmetric key
|
|
{$meet doy/gree} :: learn public key(s)
|
|
== ::
|
|
--
|
|
|= {him/@p det/pipe}
|
|
|= {syn/skin msg/@}
|
|
^- (pair (list gift) {aut/? ham/meal})
|
|
|^ ?- syn
|
|
$none [~ | (maul msg)]
|
|
$fast
|
|
=+ [mag=`hand`(end 7 1 msg) bod=(rsh 7 1 msg)]
|
|
=+ key=(~(got by inn.det) mag)
|
|
=+ clr=(need (de:crub key bod))
|
|
[~ & (maul clr)]
|
|
::
|
|
$full
|
|
=+ mex=((hard {p/{p/life q/life} q/gree r/@}) (cue msg))
|
|
=+ rig=(~(got by war.det) p.p.mex)
|
|
=+ pas=(whom q.p.mex q.mex)
|
|
=+ [key out]=(need (tear:as:(nol:nu:crub rig) pas r.mex))
|
|
:- :~ [%link ~2018.1.1 key]
|
|
[%meet q.mex]
|
|
==
|
|
[& (maul out)]
|
|
::
|
|
$open
|
|
=+ mex=((hard {p/{$~ q/life} q/gree r/@}) (cue msg))
|
|
=+ pas=(whom q.p.mex q.mex)
|
|
=+ out=(need (sure:as:(com:nu:crub pas) *code r.mex))
|
|
[[%meet q.mex]~ & (maul r.mex)]
|
|
==
|
|
++ maul |=(@ `meal`((hard meal) (cue +<))) :: unpack message
|
|
++ whom :: select public key
|
|
|= {lyf/life gyr/gree}
|
|
^- pass
|
|
::
|
|
:: if we have the public key for this life, use it.
|
|
:: otherwise, use the key the sender sent, without
|
|
:: without checking its validity. invalid public-key
|
|
:: data will crash the packet when we install it.
|
|
::
|
|
%- (bond |.(pub.dat:(~(got by q:(~(got by gyr) lyf)) him)))
|
|
(~(get by pub.det) lyf)
|
|
--
|
|
:: ::
|
|
:::: hose ::
|
|
:: ::
|
|
++ hose :: input decoder
|
|
=> |% ::
|
|
++ gift :: action
|
|
$% {$fore her/ship org/lane pac/rock} :: send forward
|
|
{$have kos/bole cha/chan val/*} :: report message
|
|
{$link exp/@da key/code} :: learn symmetric key
|
|
{$meet doy/gree} :: learn public key
|
|
{$rack kos/bole dam/flap cop/coop} :: report ack
|
|
{$rout lyn/lane} :: learn route
|
|
{$sack kos/bole dam/flap cop/coop} :: send ack
|
|
== ::
|
|
++ task :: event
|
|
$% {$done kos/bole cop/coop} :: commit message
|
|
{$hear lyn/lane dam/flap syn/skin msg/@} :: raw packet
|
|
== ::
|
|
-- ::
|
|
=| $: $: him/ship ::
|
|
det/pipe ::
|
|
== ::
|
|
fex/(list gift) ::
|
|
fon/(map bole lock) ::
|
|
==
|
|
|% ::
|
|
++ abet [(flop fex) fon] :: resolve
|
|
++ acme |=(fic/gift +>(fex [fic fex])) :: effect
|
|
++ acts :: effects
|
|
|=(fix/(list gift) +>(fex (weld (flop fix) fex))) ::
|
|
:: ::
|
|
++ apex :: input
|
|
|= job/task
|
|
^+ +>
|
|
?- -.job
|
|
$done
|
|
=+ loc=(~(got by fon) kos.job)
|
|
?> ?=(^ laz.loc)
|
|
=< hy-abet
|
|
(~(hy-done hy [kos.job p.u.laz.loc] [& [q r]:u.laz.loc] loc) cop.job)
|
|
::
|
|
$hear
|
|
=+ pet=((nose him det) syn.job msg.job)
|
|
=. +>.$ (acts p.pet)
|
|
:: if packet is authenticated, use its routing info
|
|
=. +>.$ ?.(aut.q.pet +>.$ (acme %rout lyn.job))
|
|
?- -.ham.q.pet
|
|
$back
|
|
~| %unsecured-back
|
|
?>(aut.q.pet (acme %rack [p q r]:ham.q.pet))
|
|
::
|
|
$bond
|
|
=+ loc=((bond |.(*lock)) (~(get by fon) p.p.ham.q.pet))
|
|
=< hy-abet
|
|
%. [q r]:ham.q.pet
|
|
~(hy-bond hy p.ham.q.pet [aut.q.pet [dam lyn]:job] loc)
|
|
::
|
|
$carp
|
|
=+ loc=((bond |.(*lock)) (~(get by fon) kos.p.ham.q.pet))
|
|
=< hy-abet
|
|
%. [(kins syn.p.ham.q.pet) cnt.p.ham.q.pet q.ham.q.pet]
|
|
~(hy-carp hy [kos liq]:p.ham.q.pet [aut.q.pet [dam lyn]:job] loc)
|
|
::
|
|
$fore
|
|
(acme %fore p.ham.q.pet (born lyn.job q.ham.q.pet) r.ham.q.pet)
|
|
==
|
|
==
|
|
:: ::
|
|
++ born :: set forward origin
|
|
|= {lyn/lane urg/(unit lane)}
|
|
^- lane
|
|
:: a forwarded packet contains its origin address,
|
|
:: but only after the first hop. if the address
|
|
:: field is empty, we fill it in with the address
|
|
:: we received the packet from. but we replace
|
|
:: %if with %ix, to show that the ultimate receiver
|
|
:: may not be able to send back to the origin
|
|
:: (due to non-full-cone NAT).
|
|
?~ urg lyn
|
|
?. ?=($if -.u.urg)
|
|
u.urg
|
|
[%ix +.u.urg]
|
|
::
|
|
++ hy :: message assembler
|
|
=| $: $: kos/bole :: sender
|
|
liq/tick :: message number
|
|
==
|
|
$: aut/? :: authenticated
|
|
dam/flap :: critical flap
|
|
lyn/lane :: origin address
|
|
==
|
|
lock
|
|
==
|
|
=* loq ->+
|
|
|% ::
|
|
++ hy-abet ..hy(fon (~(put by fon) kos loq)) :: resolve
|
|
++ hy-acme |=(fic/gift +>(+> (acme fic))) :: effect
|
|
++ hy-acts |=(fix/(list gift) +>(+> (acts fix))) :: effects
|
|
++ hy-bond :: full message
|
|
|= {cha/chan val/*}
|
|
^+ +>
|
|
?: (lth liq laq)
|
|
:: we already acked this msg; ack it again
|
|
:: ~& [%hi-bond-low [kos liq] laq]
|
|
hy-cong
|
|
?: (gth liq laq)
|
|
:: later than the next msg; ignore
|
|
~& [%hy-bond-after [kos liq] laq]
|
|
+>
|
|
?: !=(~ laz)
|
|
:: this msg is already being processed; ignore
|
|
~& [%hy-bond-during [kos liq] laq]
|
|
+>
|
|
:: report completed message
|
|
%. [%have kos cha val]
|
|
%= hy-acme
|
|
:: delete partial message
|
|
nys (~(del by nys) liq)
|
|
:: record message in application processing
|
|
laz `[liq dam lyn]
|
|
==
|
|
:: ::
|
|
++ hy-done :: message completed
|
|
|= cop/coop
|
|
^+ +>
|
|
(hy-cone(laq +(laq), laz ~) cop)
|
|
:: ::
|
|
++ hy-carp :: process fragment
|
|
|= {syn/skin cnt/@ud far/(pair @ud @)}
|
|
^+ +>
|
|
:: ~& [%carp fap/`@p`(mug fap) syn/syn cnt/cnt far/p.far]
|
|
?: (lth liq laq)
|
|
:: fragment of a message we've already acknowledged - ack it again.
|
|
:: ~& [%hy-carp-late liq laq]
|
|
hy-cong
|
|
?: (gth liq laq)
|
|
:: fragment of a message after the next we expect - drop it.
|
|
:: ~& [%hy-carp-early liq laq]
|
|
+>
|
|
:: neb: current incomplete message
|
|
=+ neb=`bait`(fall (~(get by nys) liq) [syn 0 [cnt ~]])
|
|
:: all fragments must agree on the message parameters
|
|
?> &(=(p.neb syn) (gth p.r.neb p.far) =(p.r.neb cnt))
|
|
=+ doy=(~(get by q.r.neb) p.far)
|
|
?^ doy
|
|
:: we've already heard this fragment
|
|
(hy-conk ~)
|
|
:: install fragment
|
|
=: q.r.neb (~(put by q.r.neb) p.far q.far)
|
|
q.neb +(q.neb)
|
|
==
|
|
?. =(q.neb p.r.neb)
|
|
:: message not yet complete, reinstall incomplete
|
|
(hy-conk(nys (~(put by nys) liq neb)) ~)
|
|
:: decode complete message
|
|
=+ pet=((nose him det) syn (hy-golf r.neb))
|
|
:: record decoder effects
|
|
=. +>.$ (hy-acts p.pet)
|
|
=. aut |(aut aut.q.pet)
|
|
?- -.ham.q.pet
|
|
$back ~|(%unsecured-back ?>(aut (hy-acme %rack kos [q r]:ham.q.pet)))
|
|
$carp ~|(%meta-carp !!)
|
|
$fore (hy-acme %fore p.ham.q.pet (born lyn q.ham.q.pet) r.ham.q.pet)
|
|
$bond ~| %bogus-assembly
|
|
?> &(aut =([kos liq] p.ham.q.pet))
|
|
(hy-bond [q r]:ham.q.pet)
|
|
==
|
|
::
|
|
++ hy-cong (hy-conk (~(get by exc) liq)) :: duplicate ack
|
|
++ hy-conk :: ack current
|
|
|=(cop/coop (hy-acme %sack kos dam cop))
|
|
++ hy-cone :: record ack
|
|
|= cop/coop
|
|
=> ?~(cop . .(exc (~(put by exc) liq u.cop)))
|
|
(hy-conk cop)
|
|
:: ::
|
|
++ hy-golf :: assemble fragments
|
|
|= duv/dove
|
|
=+ [nix=0 rax=*(list @)]
|
|
|- ^- @
|
|
?: =(p.duv nix)
|
|
(can 13 (turn (flop rax) |=(a/@ [1 a])))
|
|
$(nix +(nix), rax [(need (~(get by q.duv) nix)) rax])
|
|
--
|
|
--
|
|
:: ::
|
|
:::: outbound cores ::::
|
|
:: ::
|
|
::
|
|
:::: packet pump
|
|
::
|
|
++ pump :: packet pump
|
|
=> |% ::
|
|
++ gift :: effect
|
|
$% {$good p/flap q/part r/@dr s/coop} :: logical ack
|
|
{$send p/flap q/part r/rock} :: release packet
|
|
== ::
|
|
++ task :: event
|
|
$% {$back p/flap q/coop r/@dr} :: raw ack
|
|
{$cull p/tick} :: cancel message
|
|
{$pack p/(list clue)} :: submit packets
|
|
{$wake $~} :: random wakeup
|
|
== ::
|
|
--
|
|
|%
|
|
++ yawn ::
|
|
|= myn/mini ::
|
|
^+ zu
|
|
~(. zu ~ myn) ::
|
|
::
|
|
++ zu :: state machine
|
|
|_ $: fex/(list gift) :: effects
|
|
mini :: state
|
|
==
|
|
:: ::
|
|
++ abba :: a older than b
|
|
|= {a/part b/part}
|
|
|((lth q.a q.b) &(=(q.a q.b) (lth p.a p.b)))
|
|
:: ::
|
|
++ abet :: resolve
|
|
^- {(list gift:pump) mini}
|
|
:: =. . aver
|
|
[(flop fex) +<+]
|
|
:: ::
|
|
++ aver :: verify
|
|
?> (lte cur.saw max.saw)
|
|
?> !=(0 max.saw)
|
|
?. =(cur.saw (lent (~(tap to liv))))
|
|
~& [%aver-cur cur.saw (lent (~(tap to liv)))]
|
|
!!
|
|
?> =(rey.saw (lent (~(tap to lop))))
|
|
?> =+ |= {a/coal b/coal}
|
|
&((lth out.a out.b) (lth lod.a lod.b))
|
|
|- ?| ?=($~ liv)
|
|
?& ?| ?=($~ r.liv)
|
|
?& (+< n.r.liv n.liv)
|
|
$(liv r.liv)
|
|
== ==
|
|
?| ?=($~ l.liv)
|
|
?& (+< n.liv n.l.liv)
|
|
$(liv l.liv)
|
|
== ==
|
|
==
|
|
==
|
|
?> =+ |= {a/part b/part}
|
|
|((lth q.a q.b) &(=(q.a q.b) (lth p.a p.b)))
|
|
|- ?| ?=($~ lop)
|
|
?& ?| ?=($~ r.lop)
|
|
?& (+< tel.n.r.lop tel.n.lop)
|
|
$(lop r.lop)
|
|
== ==
|
|
?| ?=($~ l.lop)
|
|
?& (+< tel.n.lop tel.n.l.lop)
|
|
$(lop l.lop)
|
|
== ==
|
|
==
|
|
==
|
|
.
|
|
:: ::
|
|
++ back :: process raw ack
|
|
|= {now/@da dam/flap cop/coop lag/@dr}
|
|
^+ +>
|
|
=- =/ rtt ?~(ack ~s0 (sub now out.u.ack))
|
|
=. rtt ?:((gth rtt lag) (sub rtt lag) rtt)
|
|
(done:(lose(liv lov) ded) ack dam cop rtt)
|
|
|- ^- $: ack/(unit coal)
|
|
ded/(list coal)
|
|
lov/(qeu coal)
|
|
==
|
|
?~ liv [~ ~ ~]
|
|
=+ ryt=$(liv r.liv)
|
|
?^ ack.ryt
|
|
::
|
|
:: found in front, no need to search back.
|
|
::
|
|
[ack.ryt ded.ryt [n.liv l.liv lov.ryt]]
|
|
::
|
|
:: lose unacked packets sent before an acked virgin.
|
|
::
|
|
=+ ^- $: top/?
|
|
ack/(unit coal)
|
|
ded/(list coal)
|
|
lov/(qeu coal)
|
|
==
|
|
?: =(dam fap.clu.n.liv)
|
|
[| `n.liv ~ l.liv]
|
|
[& $(liv l.liv)]
|
|
?~ ack [~ ~ liv]
|
|
=. ded ?:(top [n.liv ded] ded)
|
|
=. ded ?:(vig.clu.u.ack (~(tap to r.liv) ded) ded)
|
|
=. lov ?:(top [n.liv lov ~] lov)
|
|
[ack ded lov]
|
|
:: ::
|
|
++ clap :: ordered enqueue
|
|
::
|
|
:: the `lop` queue isn't really a queue in case of
|
|
:: resent packets; packets from older messages
|
|
:: need to be sent first. unfortunately hoon.hoon
|
|
:: lacks a general sorted/balanced heap right now.
|
|
:: so we implement a balanced queue insert by hand.
|
|
::
|
|
|= clu/clue
|
|
%_ +>
|
|
lop
|
|
|- ^+ lop
|
|
?~ lop [clu ~ ~]
|
|
?: ?| (abba tel.clu tel.n.lop)
|
|
?& =(tel.clu tel.n.lop)
|
|
(lth fap.clu fap.n.lop)
|
|
== ==
|
|
[n.lop l.lop $(lop r.lop)]
|
|
[n.lop $(lop l.lop) r.lop]
|
|
==
|
|
:: ::
|
|
++ cull :: clear message
|
|
|= tiq/tick
|
|
%_ +>
|
|
liv
|
|
|- ^+ liv
|
|
?~ liv ~
|
|
=+ vil=[n.liv $(liv l.liv) $(liv r.liv)]
|
|
?. =(tiq q.tel.clu.n.liv) vil
|
|
~(nip to `(qeu coal)`vil)
|
|
::
|
|
lop
|
|
|- ^+ lop
|
|
?~ lop ~
|
|
=+ pol=[n.lop $(lop l.lop) $(lop r.lop)]
|
|
?: =(tiq q.tel.n.lop) pol
|
|
~(nip to `(qeu clue)`pol)
|
|
==
|
|
:: ::
|
|
++ done :: process cooked ack
|
|
|= {lyd/(unit coal) dam/flap cop/coop rtt/@dr}
|
|
^+ +>
|
|
?~ lyd +>
|
|
%_ +>
|
|
cur.saw (dec cur.saw)
|
|
fex [[%good dam tel.clu.u.lyd rtt cop] fex]
|
|
==
|
|
:: ::
|
|
++ fire :: send a packet
|
|
|= {now/@da clu/clue}
|
|
^+ +>
|
|
?> (lth cur.saw max.saw)
|
|
=+ out=?:((lte now las.saw) +(las.saw) now)
|
|
=+ lod=(add now (mul 2 rtt.saw))
|
|
=. lod ?:((gth lod lad.saw) lod +(lad.saw))
|
|
:: ~& [%fire (flam fap.clu) `@da`out `@da`lod]
|
|
%= +>.$
|
|
fex [[%send fap.clu tel.clu dat.clu] fex]
|
|
las.saw out
|
|
lad.saw lod
|
|
cur.saw +(cur.saw)
|
|
liv (~(put to liv) [out lod clu])
|
|
==
|
|
:: ::
|
|
++ flay :: time out packets
|
|
|= now/@da
|
|
^+ +>
|
|
=- (lose(liv q.ole) p.ole)
|
|
^= ole
|
|
=| ded/(list coal)
|
|
|- ^+ [p=ded q=liv]
|
|
?~ liv [ded ~]
|
|
?: (gte now lod.n.liv)
|
|
::
|
|
:: everything in front of a dead packet is dead
|
|
::
|
|
$(liv l.liv, ded (~(tap to r.liv) [n.liv ded]))
|
|
=+ ryt=$(liv r.liv)
|
|
[p.ryt [n.liv l.liv q.ryt]]
|
|
:: ::
|
|
++ lose :: abandon packets
|
|
|= cud/(list coal)
|
|
^+ +>
|
|
?~ cud +>
|
|
=. +> (clap clu.i.cud)
|
|
%= $
|
|
cud t.cud
|
|
cur.saw (dec cur.saw)
|
|
rey.saw +(rey.saw)
|
|
==
|
|
:: ::
|
|
++ ship :: send packets
|
|
|= {now/@da cly/(list clue)}
|
|
^+ +>
|
|
?: (gte cur.saw max.saw) +>
|
|
?: =(0 rey.saw)
|
|
?~ cly +>
|
|
$(cly t.cly, +> (fire now i.cly))
|
|
=^ clu lop ~(get to lop)
|
|
$(+> (fire(rey.saw (dec rey.saw)) now clu))
|
|
:: ::
|
|
++ wait :: next wakeup
|
|
^- (unit @da)
|
|
=+ tup=`(unit coal)`~(top to liv)
|
|
?~(tup ~ `lod.u.tup)
|
|
:: ::
|
|
++ want :: window space
|
|
^- @ud
|
|
?: (gte cur.saw max.saw) 0
|
|
=+ gap=(sub max.saw cur.saw)
|
|
?: (gte rey.saw gap) 0
|
|
(sub gap rey.saw)
|
|
::
|
|
++ work ::
|
|
|= {now/@da job/task} :: perform
|
|
^+ +>
|
|
?- -.job
|
|
$back (back now [p q r]:job)
|
|
$cull (cull p.job)
|
|
$pack (ship now p.job)
|
|
$wake (flay now)
|
|
==
|
|
--
|
|
--
|
|
:: ::
|
|
:::: knit :::: message encoder
|
|
:: ::
|
|
++ knit
|
|
=> |%
|
|
++ gift :: side effect
|
|
$% {$line exp/@da key/code} :: set symmetric key
|
|
== ::
|
|
--
|
|
|= {her/@p det/pipe}
|
|
|= {now/@da eny/@ ham/meal}
|
|
=+ hom=(jam ham)
|
|
^- (pair (list gift) (list rock))
|
|
=< weft
|
|
|%
|
|
++ wain :: message identity
|
|
^- flea
|
|
?+ -.ham [0 0]
|
|
$bond p.ham
|
|
$carp [kos liq]:p.ham
|
|
==
|
|
::
|
|
++ wasp ^-({p/skin q/@} [%none hom]) :: null security
|
|
++ weft :: fragment message
|
|
^- (pair (list gift) (list rock))
|
|
=+ gum=wisp
|
|
:- p.gum
|
|
=+ wit=(met 13 q.q.gum)
|
|
?: =(1 wit)
|
|
:: message fits in one packet, don't fragment
|
|
[(spit [our her] p.q.gum q.q.gum) ~]
|
|
=+ ruv=(rip 13 q.q.gum)
|
|
=+ inx=0
|
|
|- ^- (list rock)
|
|
?~ ruv ~
|
|
:_ $(ruv t.ruv, inx +(inx))
|
|
%+ spit
|
|
[our her]
|
|
wasp(ham [%carp [wain (ksin p.q.gum) wit] inx i.ruv])
|
|
::
|
|
++ wisp :: generate message
|
|
^- (pair (list gift) (pair skin @))
|
|
?: =(%carp -.ham)
|
|
[~ wasp]
|
|
?^ out.det
|
|
:- ~
|
|
:- %fast
|
|
%^ cat 7
|
|
p.u.out.det
|
|
(en:crub q.u.out.det hom)
|
|
=+ cry=(nol:nu:crub (~(got by war.det) p.cur.det))
|
|
?~ q.cur.det
|
|
:- ~
|
|
:- %open
|
|
%^ jam
|
|
[~ p.cur.det]
|
|
gyr.det
|
|
(sign:as:cry *code hom)
|
|
=+ key=(shaz :(mix (mug ham) now eny))
|
|
:- [%line ~2018.1.1 key]~
|
|
:- %full
|
|
%^ jam
|
|
[u.q.cur.det p.cur.det]
|
|
gyr.det
|
|
(seal:as:cry (~(got by pub.det) u.q.cur.det) key hom)
|
|
--
|
|
:: ::
|
|
:::: rail :::: message manager
|
|
:: ::
|
|
++ rail ::
|
|
=> |% ::
|
|
++ gift ::
|
|
$% {$line p/@da q/code} :: sent key
|
|
{$mack p/bole q/coop} :: message ack
|
|
{$send p/flap q/rock} :: release packet
|
|
== ::
|
|
++ task ::
|
|
$% {$back p/flap q/coop r/@dr} :: raw ack
|
|
{$mess p/chan q/*} :: send message
|
|
{$wake $~} :: random wakeup
|
|
== ::
|
|
-- ::
|
|
=| $: $: $: her/ship
|
|
det/pipe
|
|
==
|
|
$: now/@da
|
|
eny/@
|
|
==
|
|
kos/bole
|
|
mup/_(yawn:pump)
|
|
fex/(list gift)
|
|
==
|
|
colt
|
|
==
|
|
=* cot ->
|
|
|% ::
|
|
++ abet [(flop fex) `colt`cot] :: resolve
|
|
++ view :: inspect
|
|
|% ::
|
|
++ bulk :: queue count
|
|
^- @ud
|
|
|-(?~(cob 0 :(add 1 $(cob l.cob) $(cob r.cob))))
|
|
:: ::
|
|
++ wait :: next wakeup
|
|
^- (unit @da)
|
|
wait:mup
|
|
--
|
|
::
|
|
++ work ::
|
|
|= job/task :: compute
|
|
^+ +>
|
|
=< +>:wy-abet:wy-work
|
|
|% ::
|
|
++ wy-abet +:wy-able :: resolve
|
|
++ wy-able wy-tire:wy-ably:wy-feed:wy-ably :: converge
|
|
++ wy-ably :: drain
|
|
^+ .
|
|
=^ fix myn abet:mup
|
|
=. mup (yawn:pump myn)
|
|
|- ^+ +>.$
|
|
?~ fix +>.$
|
|
$(fix t.fix, +>.$ (wy-abut i.fix))
|
|
:: ::
|
|
++ wy-abut :: pump effect
|
|
|= fic/gift:pump
|
|
^+ +>
|
|
?- -.fic
|
|
$good
|
|
:: ~& [%ok her `@p`(mug p.fic) r.fic]
|
|
(wy-good q.fic s.fic)
|
|
::
|
|
$send
|
|
:: ~& [%go her `@p`(mug p.fic) q.fic]
|
|
+>(fex [[%send p.fic r.fic] fex])
|
|
==
|
|
:: ::
|
|
++ wy-back :: hear an ack
|
|
|= {dam/flap cop/coop lag/@dr}
|
|
:: ~& [%wy-back (flam dam) cop lag]
|
|
+>(mup (work:mup now %back dam cop lag))
|
|
:: ::
|
|
++ wy-feed :: feed pump
|
|
^+ .
|
|
=^ cly . (wy-find want.mup)
|
|
:: ~& [%wy-feed want.mup (lent cly)]
|
|
+(mup (work:mup now %pack cly))
|
|
:: ::
|
|
++ wy-find :: collect packets
|
|
|= may/@ud
|
|
^- {(list clue) _+>}
|
|
=- [(flop -<) ->]
|
|
=+ [inx=lac hav=*(list clue)]
|
|
|- ^- {(list clue) _+>.^$}
|
|
?: |(=(0 may) =(inx seq)) [hav +>.^$]
|
|
=^ hey +>.^$ (wy-flow inx may hav)
|
|
$(inx +(inx), may p.hey, hav q.hey)
|
|
:: ::
|
|
++ wy-flow :: collect by message
|
|
|= {tiq/tick may/@ud hav/(list clue)}
|
|
=+ mob=(~(got by cob) tiq)
|
|
|- ^- {(pair @ud (list clue)) _+>.^$}
|
|
?: |(=(0 may) ?=($~ cly.mob))
|
|
[[may hav] +>.^$(cob (~(put by cob) tiq mob))]
|
|
%= $
|
|
may (dec may)
|
|
hav [i.cly.mob hav]
|
|
cly.mob t.cly.mob
|
|
==
|
|
:: ::
|
|
++ wy-good :: message ack
|
|
|= {paz/part cop/coop}
|
|
^+ +>
|
|
=+ bum=(~(get by cob) q.paz)
|
|
?: |(?=($~ bum) =(~ cly.u.bum))
|
|
:: ~& [%wy-good-ignore paz ?=($~ cop)]
|
|
+>.$
|
|
?^ cop
|
|
::
|
|
:: a failure; save this nack, clear the message
|
|
::
|
|
~& [%wy-good-fail q.paz]
|
|
%_ +>.$
|
|
mup (work:mup now %cull q.paz)
|
|
cob (~(put by cob) q.paz u.bum(cly ~, cup `cop))
|
|
==
|
|
?> (lth ack.u.bum num.u.bum)
|
|
=. ack.u.bum +(ack.u.bum)
|
|
=. cup.u.bum ?.(=(ack.u.bum num.u.bum) ~ [~ ~])
|
|
+>.$(cob (~(put by cob) q.paz u.bum))
|
|
:: ::
|
|
++ wy-mess :: send
|
|
|= {cha/chan val/*}
|
|
^+ +>
|
|
=+ yex=((knit her det) now eny [%bond [(mix kos 1) seq] cha val])
|
|
=. fex (weld (flop p.yex) fex)
|
|
:: ~& [?:(=(0 (end 0 1 kos)) %tx %bx) her kos seq cha (lent pex)]
|
|
%_ +>.$
|
|
seq +(seq)
|
|
cob
|
|
%+ ~(put by cob)
|
|
seq
|
|
^- comb
|
|
:* ~
|
|
cha
|
|
(lent q.yex)
|
|
0
|
|
=+ inx=0
|
|
|- ?~ q.yex ~
|
|
:_ $(q.yex +.q.yex, inx +(inx))
|
|
[& [inx seq] (shaf %flap i.q.yex) i.q.yex]
|
|
==
|
|
==
|
|
:: ::
|
|
++ wy-tire :: report results
|
|
|- ^+ +
|
|
=+ zup=(~(get by cob) lac)
|
|
?~ zup +.$
|
|
?~ cup.u.zup +.$
|
|
:: ~& [?:(=(0 (end 0 1 kos)) %ta %ba) her kos lac]
|
|
%= $
|
|
lac +(lac)
|
|
cob (~(del by cob) lac)
|
|
fex :_(fex [%mack kos `coop`u.cup.u.zup])
|
|
==
|
|
:: ::
|
|
++ wy-wake :: timeout
|
|
^+ .
|
|
.(mup (work:mup now %wake ~))
|
|
::
|
|
++ wy-work
|
|
^+ .
|
|
?- -.job
|
|
$back (wy-back +.job)
|
|
$mess (wy-mess +.job)
|
|
$wake wy-wake
|
|
==
|
|
--
|
|
:: ::
|
|
++ zeal :: default state
|
|
^- colt
|
|
:* 0 :: seq/tick
|
|
0 :: lac/tick
|
|
~ :: cob/(map tick comb)
|
|
^- mini
|
|
:* ^- stat
|
|
:* :* 0 :: cur/@ud
|
|
2 :: max/@ud
|
|
0 :: rey/@ud
|
|
==
|
|
:* ~s5 :: rtt/@dr
|
|
~2010.1.1 :: las/@da
|
|
~2010.1.1 :: lad/@da
|
|
== ==
|
|
~
|
|
~
|
|
== ==
|
|
--
|
|
--
|
|
. ==
|
|
:: ::
|
|
:::: :::: kernel interface
|
|
:: ::
|
|
=| $: syl/silo :: kernel state
|
|
== ::
|
|
|= {now/@da eny/@ ski/sley} :: current invocation
|
|
=> |%
|
|
++ look :: get secure channel
|
|
|= who/ship
|
|
^- pipe
|
|
!!
|
|
::
|
|
++ love ~(. loft [now eny look] syl ~) :: create loft
|
|
++ lung :: gift to move
|
|
|= gax/gift:loft
|
|
^- move
|
|
?- -.gax
|
|
$east [p.gax %give [%east s.gax]]
|
|
$home [~ %give gax]
|
|
$link [~ %pass /sec %j gax]
|
|
$line [~ %pass /sec %j gax]
|
|
$meet [~ %pass /sec %j gax]
|
|
$rest [p.gax %give %rest q.gax]
|
|
$send [~ %give gax]
|
|
$view [~ %pass /sec %j gax]
|
|
$west
|
|
=+ pax=/msg/(scot %p p.gax)/(scot %ud q.gax)
|
|
=+ cad=[%west p.gax +.r.gax s.gax]
|
|
=+ dat=?+(-.r.gax !! $c [%c cad], $e [%e cad], $g [%g cad])
|
|
[~ %pass pax dat]
|
|
==
|
|
::
|
|
++ work
|
|
|= job/task:loft
|
|
^- {(list move) q/_..^$}
|
|
=^ fex syl abet:(apex:love job)
|
|
[(turn fex lung) ..^$]
|
|
--
|
|
|% :: vane interface
|
|
++ call :: handle request
|
|
|= $: hen/duct
|
|
hic/(hypo kiss-xmas)
|
|
==
|
|
^- {p/(list move) q/_..^$}
|
|
%- work
|
|
^- task:loft
|
|
?- -.q.hic
|
|
$hear q.hic
|
|
$mess [%mess p.q.hic hen q.q.hic r.q.hic]
|
|
$wake q.hic
|
|
==
|
|
::
|
|
++ doze
|
|
|= {now/@da hen/duct}
|
|
^- (unit @da)
|
|
doze:love
|
|
::
|
|
++ load
|
|
|= old/silo
|
|
^+ ..^$
|
|
..^$(syl old)
|
|
::
|
|
++ scry
|
|
|= {fur/(unit (set monk)) ren/@tas who/ship syd/desk lot/coin tyl/path}
|
|
^- (unit (unit cage))
|
|
~
|
|
::
|
|
++ stay syl
|
|
++ take :: accept response
|
|
|= {tea/wire hen/duct hin/(hypo sign-arvo)}
|
|
^- {p/(list move) q/_..^$}
|
|
%- work
|
|
?+ -.tea !!
|
|
$msg
|
|
?> ?=({@ @ $~} +.tea)
|
|
=+ [who kos]=[(slav %p i.t.tea) (slav %ud i.t.t.tea)]
|
|
?> ?=(?($rend $mack) +<.q.hin)
|
|
?- +<.q.hin
|
|
$rend [%rend who kos p.+.q.hin q.+.q.hin]
|
|
$mack [%done who kos ?~(p.+.q.hin ~ `coop`[~ `[%fail u.p.+.q.hin]])]
|
|
==
|
|
::
|
|
$sec
|
|
?> ?=($clue +<.q.hin)
|
|
+.q.hin
|
|
==
|
|
--
|