on master help sign in
finally merge cleanorg
commita0ef37b8f02a78b20ff68277e2f664f6f7579bb8 authorGalen Wolfe-Pauly <root@office-for.com> dateFri 27 May 2016, 14:37 (10 years ago) parent290de936451555
455 files changed+39301−44053
docs.md+17−15 docs/about.md+8 docs/user/intro.md → docs/about/overview.md+15−64 docs/dev/interpreter/u3.md → docs/about/runtime.md+18−2 docs/arvo.md+8 docs/arvo/api.md+526 docs/dev/hoon/leap-in/basic.md → docs/arvo/basic.md+82−178 docs/arvo/generators.md+253 docs/dev/hoon/leap-in/http.md → docs/arvo/http.md+74−50 docs/arvo/internals.md+148 docs/arvo/internals/ames.md+28 docs/arvo/internals/ames/commentary.md+1820 docs/arvo/internals/behn.md+22 docs/arvo/internals/clay.md+26 docs/arvo/internals/clay/architecture.md+420 docs/arvo/internals/clay/commentary.md+2012 docs/arvo/internals/dill.md+26 docs/arvo/internals/eyre.md+59 docs/arvo/internals/eyre/commentary.md+278 docs/arvo/internals/ford.md+112 docs/arvo/internals/ford/commentary.md+2576 docs/arvo/internals/gall.md+133 docs/dev/hoon/leap-in/marks.md → docs/arvo/marks.md+23−23 docs/dev/hoon/leap-in/network.md → docs/arvo/network.md+72−78 docs/arvo/security-driver.md+302 docs/dev/hoon/leap-in/state.md → docs/arvo/state.md+35−30 docs/arvo/subject.md+105 docs/dev/hoon/leap-in/subscriptions.md → docs/arvo/subscriptions.md+51−53 docs/dev/hoon/leap-in/web-apps.md → docs/arvo/web-apps.md+46−49 docs/dev.md−28 docs/dev/arvo.md−13 docs/dev/client.md−11 docs/dev/client/tree.md−59 docs/dev/contributing.md−213 docs/dev/hoon.md−24 docs/dev/hoon/leap-in.md−8 docs/dev/hoon/leap-in/generators.md−177 docs/dev/hoon/library.md−7 docs/dev/hoon/library/0.md−39 docs/dev/hoon/library/1.md−2237 docs/dev/hoon/library/2a.md−678 docs/dev/hoon/library/2b.md−1320 docs/dev/hoon/library/2c.md−3176 docs/dev/hoon/library/2db.md−813 docs/dev/hoon/library/2dd.md−112 docs/dev/hoon/library/2eb.md−93 docs/dev/hoon/library/2ee.md−305 docs/dev/hoon/library/2eg.md−211 docs/dev/hoon/library/2eh.md−686 docs/dev/hoon/library/2ei.md−163 docs/dev/hoon/library/2ek.md−264 docs/dev/hoon/library/2el.md−2863 docs/dev/hoon/library/2em.md−758 docs/dev/hoon/library/2eo.md−578 docs/dev/hoon/library/2ez.md−250 docs/dev/hoon/library/3bc.md−526 docs/dev/hoon/library/3bd.md−2922 docs/dev/hoon/library/3be.md−1316 docs/dev/hoon/library/3bf.md−394 docs/dev/hoon/library/3bh.md−572 docs/dev/hoon/library/3bi.md−3559 docs/dev/hoon/principles.md−18 docs/dev/hoon/principles/0-nouns.md−286 docs/dev/hoon/principles/1-twigs.md−286 docs/dev/hoon/principles/2-syntax.md−476 docs/dev/hoon/principles/3-program.md−350 docs/dev/hoon/principles/4-functions.md−327 docs/dev/hoon/reference.md−7 docs/dev/hoon/reference/cheat-sheet.md−532 docs/dev/hoon/reference/odors.md−686 docs/dev/hoon/reference/pronunciation.md−68 docs/dev/hoon/runes.md−132 docs/dev/hoon/runes/bc/bcbr.md−41 docs/dev/hoon/runes/bc/bccb.md−52 docs/dev/hoon/runes/bc/bccl.md−44 docs/dev/hoon/runes/bc/bccn.md−52 docs/dev/hoon/runes/bc/bcls.md−57 docs/dev/hoon/runes/bc/bcpm.md−30 docs/dev/hoon/runes/bc/bctr.md−41 docs/dev/hoon/runes/bc/bcts.md−59 docs/dev/hoon/runes/bc/bcwt.md−42 docs/dev/hoon/runes/br/brcb.md−99 docs/dev/hoon/runes/br/brcn.md−115 docs/dev/hoon/runes/br/brdt.md−101 docs/dev/hoon/runes/br/brfs.md−89 docs/dev/hoon/runes/br/brhp.md−62 docs/dev/hoon/runes/br/brkt.md−85 docs/dev/hoon/runes/br/brls.md−49 docs/dev/hoon/runes/br/brtr.md−58 docs/dev/hoon/runes/br/brts.md−60 docs/dev/hoon/runes/br/brwt.md−48 docs/dev/hoon/runes/cl/clcb.md−50 docs/dev/hoon/runes/cl/clfs.md−37 docs/dev/hoon/runes/cl/clhp.md−79 docs/dev/hoon/runes/cl/clkt.md−61 docs/dev/hoon/runes/cl/clls.md−54 docs/dev/hoon/runes/cl/clsg.md−67 docs/dev/hoon/runes/cl/cltr.md−56 docs/dev/hoon/runes/cn/cncb.md−74 docs/dev/hoon/runes/cn/cndt.md−53 docs/dev/hoon/runes/cn/cnhp.md−46 docs/dev/hoon/runes/cn/cnkt.md−29 docs/dev/hoon/runes/cn/cnls.md−52 docs/dev/hoon/runes/cn/cnsg.md−77 docs/dev/hoon/runes/cn/cntr.md−48 docs/dev/hoon/runes/cn/cnts.md−68 docs/dev/hoon/runes/dt/dtkt.md−51 docs/dev/hoon/runes/dt/dtls.md−66 docs/dev/hoon/runes/dt/dttr.md−50 docs/dev/hoon/runes/dt/dtts.md−71 docs/dev/hoon/runes/dt/dtwt.md−53 docs/dev/hoon/runes/dt/dtzy.md−47 docs/dev/hoon/runes/dt/dtzz.md−47 docs/dev/hoon/runes/hx/hxgl.md−61 docs/dev/hoon/runes/hx/hxgr.md−83 docs/dev/hoon/runes/kt/ktbr.md−46 docs/dev/hoon/runes/kt/ktdt.md−38 docs/dev/hoon/runes/kt/kthp.md−58 docs/dev/hoon/runes/kt/ktls.md−67 docs/dev/hoon/runes/kt/ktpm.md−46 docs/dev/hoon/runes/kt/ktsg.md−41 docs/dev/hoon/runes/kt/ktts.md−53 docs/dev/hoon/runes/kt/ktwt.md−36 docs/dev/hoon/runes/sg/sgbc.md−37 docs/dev/hoon/runes/sg/sgbr.md−28 docs/dev/hoon/runes/sg/sgcb.md−36 docs/dev/hoon/runes/sg/sgcn.md−55 docs/dev/hoon/runes/sg/sgfs.md−38 docs/dev/hoon/runes/sg/sggl.md−45 docs/dev/hoon/runes/sg/sggr.md−43 docs/dev/hoon/runes/sg/sgls.md−44 docs/dev/hoon/runes/sg/sgpm.md−63 docs/dev/hoon/runes/sg/sgts.md−44 docs/dev/hoon/runes/sg/sgwt.md−59 docs/dev/hoon/runes/sg/sgzp.md−59 docs/dev/hoon/runes/sm.md−42 docs/dev/hoon/runes/sm/smcl.md−65 docs/dev/hoon/runes/sm/smcn.md−82 docs/dev/hoon/runes/sm/smdq.md−46 docs/dev/hoon/runes/sm/smhp.md−45 docs/dev/hoon/runes/sm/smls.md−48 docs/dev/hoon/runes/sm/smsg.md−157 docs/dev/hoon/runes/sm/smsm.md−47 docs/dev/hoon/runes/sm/smtr.md−50 docs/dev/hoon/runes/sm/smzz.md−79 docs/dev/hoon/runes/ts/tsbr.md−47 docs/dev/hoon/runes/ts/tscl.md−43 docs/dev/hoon/runes/ts/tsdt.md−52 docs/dev/hoon/runes/ts/tsgl.md−60 docs/dev/hoon/runes/ts/tsgr.md−57 docs/dev/hoon/runes/ts/tshp.md−55 docs/dev/hoon/runes/ts/tskt.md−67 docs/dev/hoon/runes/ts/tsls.md−56 docs/dev/hoon/runes/ts/tssg.md−45 docs/dev/hoon/runes/ts/tstr.md−48 docs/dev/hoon/runes/wt/wtbr.md−54 docs/dev/hoon/runes/wt/wtcl.md−38 docs/dev/hoon/runes/wt/wtdt.md−45 docs/dev/hoon/runes/wt/wtgl.md−40 docs/dev/hoon/runes/wt/wtgr.md−40 docs/dev/hoon/runes/wt/wthp.md−85 docs/dev/hoon/runes/wt/wthz.md−52 docs/dev/hoon/runes/wt/wtkt.md−62 docs/dev/hoon/runes/wt/wtkz.md−34 docs/dev/hoon/runes/wt/wtls.md−104 docs/dev/hoon/runes/wt/wtlz.md−35 docs/dev/hoon/runes/wt/wtpm.md−48 docs/dev/hoon/runes/wt/wtpt.md−53 docs/dev/hoon/runes/wt/wtpz.md−34 docs/dev/hoon/runes/wt/wtsg.md−46 docs/dev/hoon/runes/wt/wtsz.md−37 docs/dev/hoon/runes/wt/wtts.md−39 docs/dev/hoon/runes/wt/wttz.md−35 docs/dev/hoon/runes/wt/wtzp.md−46 docs/dev/hoon/runes/zp/zpcb.md−57 docs/dev/hoon/runes/zp/zpcm.md−31 docs/dev/hoon/runes/zp/zpfs.md−59 docs/dev/hoon/runes/zp/zpgr.md−57 docs/dev/hoon/runes/zp/zpsm.md−38 docs/dev/hoon/runes/zp/zpts.md−50 docs/dev/hoon/runes/zp/zpwt.md−39 docs/dev/hoon/runes/zp/zpzp.md−42 docs/dev/interpreter.md−12 docs/dev/nock.md−52 docs/dev/nock/reference.md−737 docs/dev/nock/tutorial.md−1044 docs/hoon.md+8 docs/hoon/advanced.md+198 docs/hoon/basic.md+183 docs/hoon/concepts.md+236 docs/hoon/demo.md+63 docs/hoon/examples.md+597 docs/hoon/exercises.md+16 docs/hoon/exercises/data-structures.md+62 docs/hoon/exercises/fizzbuzz.md+38 docs/hoon/exercises/life.md+121 docs/hoon/exercises/lists.md+40 docs/hoon/exercises/math.md+27 docs/hoon/library.md+9 docs/hoon/library/1a.md+509 docs/hoon/library/1b.md+147 docs/hoon/library/1c.md+292 docs/hoon/library/2a.md+457 docs/hoon/library/2b.md+900 docs/hoon/library/2c.md+676 docs/hoon/library/2d.md+227 docs/hoon/library/2e.md+160 docs/hoon/library/2f.md+279 docs/hoon/library/2g.md+6 docs/dev/hoon/library/2da.md → docs/hoon/library/2h.md+112−140 docs/hoon/library/2i.md+589 docs/hoon/library/2j.md+224 docs/dev/hoon/library/2dc.md → docs/hoon/library/2k.md+71−62 docs/hoon/library/2l.md+6 docs/hoon/library/2m.md+6 docs/hoon/library/2n.md+201 docs/hoon/library/2o.md+151 docs/dev/hoon/library/2ea.md → docs/hoon/library/2p.md+46−40 docs/hoon/library/2q.md+256 docs/hoon/library/3a.md+947 docs/hoon/library/3b.md+6 docs/hoon/library/3c.md+600 docs/dev/hoon/library/2ey.md → docs/hoon/library/3d.md+111−160 docs/dev/hoon/library/2ex.md → docs/hoon/library/3e.md+20−71 docs/dev/hoon/library/2en.md → docs/hoon/library/3f.md+315−296 docs/hoon/library/3g.md+339 docs/hoon/library/4a.md+211 docs/dev/hoon/library/2ej.md → docs/hoon/library/4b.md+427−255 docs/hoon/library/4c.md+361 docs/hoon/library/4d.md+98 docs/dev/hoon/library/2ed.md → docs/hoon/library/4e.md+149−102 docs/dev/hoon/library/2ec.md → docs/hoon/library/4f.md+493−232 docs/hoon/library/4g.md+175 docs/dev/hoon/library/2ef.md → docs/hoon/library/4h.md+246−210 docs/hoon/library/4i.md+6 docs/hoon/library/4j.md+1656 docs/hoon/library/4k.md+1268 docs/hoon/library/4l.md+603 docs/hoon/library/4m.md+421 docs/hoon/library/4n.md+459 docs/hoon/library/4o.md+728 docs/hoon/library/5a.md+6 docs/hoon/library/5b.md+6 docs/hoon/library/5c.md+6 docs/hoon/library/5d.md+6 docs/hoon/library/5e.md+6 docs/hoon/library/5f.md+178 docs/hoon/library/5g.md+5 docs/hoon/library/zuse.md+8 docs/dev/hoon/library/3bb.md → docs/hoon/library/zuse/core/crua.md+5−2 docs/dev/hoon/library/3bg.md → docs/hoon/library/zuse/core/epur.md+4−539 docs/dev/hoon/library/3ba.md → docs/hoon/library/zuse/core/fu.md+8−2 docs/hoon/library/zuse/core/jo.md+953 docs/hoon/library/zuse/core/poja.md+720 docs/hoon/library/zuse/core/poxa.md+445 docs/hoon/library/zuse/core/poxo.md+260 docs/hoon/library/zuse/core/yu.md+217 docs/dev/hoon/library/2ep.md → docs/hoon/library/zuse/diff.md+8−2 docs/hoon/library/zuse/gate/clan.md+45 docs/hoon/library/zuse/gate/dawn.md+44 docs/hoon/library/zuse/gate/daws.md+42 docs/hoon/library/zuse/gate/deal.md+49 docs/hoon/library/zuse/gate/deft.md+53 docs/hoon/library/zuse/gate/dust.md+47 docs/hoon/library/zuse/gate/earl.md+45 docs/hoon/library/zuse/gate/earn.md+185 docs/hoon/library/zuse/gate/fain.md+61 docs/hoon/library/zuse/gate/feel.md+52 docs/hoon/library/zuse/gate/file.md+49 docs/hoon/library/zuse/gate/foal.md+48 docs/hoon/library/zuse/gate/fray.md+43 docs/hoon/library/zuse/gate/fuel.md+82 docs/hoon/library/zuse/gate/furl.md+55 docs/hoon/library/zuse/gate/glam.md+89 docs/hoon/library/zuse/gate/glon.md+221 docs/hoon/library/zuse/gate/gnom.md+43 docs/hoon/library/zuse/gate/jape.md+43 docs/hoon/library/zuse/gate/jesc.md+46 docs/hoon/library/zuse/gate/joba.md+45 docs/hoon/library/zuse/gate/jobe.md+39 docs/hoon/library/zuse/gate/jone.md+45 docs/hoon/library/zuse/gate/lead.md+53 docs/hoon/library/zuse/gate/mang.md+60 docs/hoon/library/zuse/gate/meat.md+53 docs/hoon/library/zuse/gate/moon.md+45 docs/hoon/library/zuse/gate/mung.md+60 docs/hoon/library/zuse/gate/perk.md+54 docs/hoon/library/zuse/gate/pojo.md+83 docs/hoon/library/zuse/gate/saxo.md+42 docs/hoon/library/zuse/gate/scanf.md+88 docs/hoon/library/zuse/gate/sein.md+61 docs/hoon/library/zuse/gate/sifo.md+51 docs/hoon/library/zuse/gate/stud.md+63 docs/hoon/library/zuse/gate/taco.md+32 docs/hoon/library/zuse/gate/tact.md+39 docs/hoon/library/zuse/gate/tame.md+59 docs/hoon/library/zuse/gate/tell.md+44 docs/hoon/library/zuse/gate/tome.md+51 docs/hoon/library/zuse/gate/tope.md+35 docs/hoon/library/zuse/gate/txml.md+37 docs/hoon/library/zuse/gate/unt.md+40 docs/hoon/library/zuse/gate/urld.md+53 docs/hoon/library/zuse/gate/urle.md+56 docs/hoon/library/zuse/mold/udal.md+15 docs/hoon/library/zuse/mold/udon.md+20 docs/hoon/library/zuse/mold/umph.md+18 docs/hoon/library/zuse/mold/unce.md+13 docs/hoon/library/zuse/mold/upas.md+17 docs/hoon/library/zuse/mold/urge.md+12 docs/dev/hoon/library/2ew.md → docs/hoon/library/zuse/rsa.md+4−39 docs/hoon/mission.md+46 docs/hoon/reference.md+77 docs/hoon/syntax.md+368 docs/hoon/troubleshooting.md+189 docs/hoon/twig.md+75 docs/hoon/twig/atom.md+16 docs/hoon/twig/atom/knit.md+45 docs/hoon/twig/atom/path.md+30 docs/hoon/twig/atom/rock.md+37 docs/hoon/twig/atom/sand.md+57 docs/hoon/twig/bar-core.md+19 docs/hoon/twig/bar-core/cab-door.md+72 docs/hoon/twig/bar-core/cen-core.md+43 docs/hoon/twig/bar-core/dot-trap.md+54 docs/hoon/twig/bar-core/hep-loop.md+44 docs/hoon/twig/bar-core/tar-gill.md+49 docs/hoon/twig/bar-core/tis-gate.md+44 docs/hoon/twig/buc-mold.md+52 docs/hoon/twig/buc-mold/base.md+33 docs/hoon/twig/buc-mold/cab-shoe.md+41 docs/hoon/twig/buc-mold/cen-book.md+44 docs/hoon/twig/buc-mold/col-bank.md+43 docs/hoon/twig/buc-mold/hep-lamb.md+37 docs/hoon/twig/buc-mold/ket-bush.md+39 docs/hoon/twig/buc-mold/pat-claw.md+41 docs/hoon/twig/buc-mold/tis-coat.md+37 docs/hoon/twig/buc-mold/wut-pick.md+47 docs/hoon/twig/cen-call.md+15 docs/hoon/twig/cen-call/cab-keep.md+39 docs/hoon/twig/cen-call/dot-lace.md+25 docs/hoon/twig/cen-call/hep-call.md+44 docs/hoon/twig/cen-call/ket-calq.md+24 docs/hoon/twig/cen-call/lus-calt.md+24 docs/hoon/twig/cen-call/sig-open.md+35 docs/hoon/twig/cen-call/tis-make.md+44 docs/hoon/twig/col-cell.md+15 docs/hoon/twig/col-cell/cab-scon.md+25 docs/hoon/twig/col-cell/hep-cons.md+43 docs/hoon/twig/col-cell/ket-conq.md+29 docs/hoon/twig/col-cell/lus-cont.md+29 docs/hoon/twig/col-cell/sig-conl.md+34 docs/hoon/twig/col-cell/tar-conp.md+37 docs/hoon/twig/dot-nock.md+13 docs/hoon/twig/dot-nock/ket-wish.md+24 docs/hoon/twig/dot-nock/lus-bump.md+30 docs/hoon/twig/dot-nock/tar-nock.md+39 docs/hoon/twig/dot-nock/tis-same.md+36 docs/hoon/twig/dot-nock/wut-deep.md+25 docs/hoon/twig/ket-cast.md+17 docs/hoon/twig/ket-cast/bar-iron.md+40 docs/hoon/twig/ket-cast/hep-cast.md+42 docs/hoon/twig/ket-cast/lus-like.md+26 docs/hoon/twig/ket-cast/sig-burn.md+25 docs/hoon/twig/ket-cast/tis-name.md+33 docs/hoon/twig/ket-cast/wut-lead.md+39 docs/hoon/twig/limb.md+23 docs/hoon/twig/limb/limb.md+70 docs/hoon/twig/limb/wing.md+49 docs/hoon/twig/sem-make.md+13 docs/hoon/twig/sem-make/col-wad.md+31 docs/hoon/twig/sem-make/fas-nub.md+20 docs/hoon/twig/sem-make/sem-fry.md+49 docs/hoon/twig/sem-make/sig-dip.md+64 docs/hoon/twig/sig-hint.md+14 docs/hoon/twig/sig-hint/bar-show.md+28 docs/hoon/twig/sig-hint/buc-poll.md+27 docs/hoon/twig/sig-hint/cab-lurk.md+28 docs/hoon/twig/sig-hint/cen-fast.md+94 docs/hoon/twig/sig-hint/fas-funk.md+31 docs/hoon/twig/sig-hint/gal-thin.md+32 docs/hoon/twig/sig-hint/gar-hint.md+38 docs/hoon/twig/sig-hint/lus-memo.md+44 docs/hoon/twig/sig-hint/pam-dump.md+28 docs/hoon/twig/sig-hint/tis-ddup.md+35 docs/hoon/twig/sig-hint/wut-warn.md+30 docs/hoon/twig/sig-hint/zap-peep.md+30 docs/hoon/twig/tis-flow.md+34 docs/hoon/twig/tis-flow/bar-new.md+39 docs/hoon/twig/tis-flow/col-fix.md+29 docs/hoon/twig/tis-flow/dot-set.md+36 docs/hoon/twig/tis-flow/fas-var.md+37 docs/hoon/twig/tis-flow/gal-rap.md+29 docs/hoon/twig/tis-flow/gar-per.md+25 docs/hoon/twig/tis-flow/hep-nip.md+34 docs/hoon/twig/tis-flow/ket-sip.md+42 docs/hoon/twig/tis-flow/lus-pin.md+33 docs/hoon/twig/tis-flow/sem-rev.md+30 docs/hoon/twig/tis-flow/tar-aka.md+38 docs/hoon/twig/wut-test.md+31 docs/hoon/twig/wut-test/bar-or.md+31 docs/hoon/twig/wut-test/col-if.md+43 docs/hoon/twig/wut-test/dot-lest.md+40 docs/hoon/twig/wut-test/gal-deny.md+28 docs/hoon/twig/wut-test/gar-sure.md+27 docs/hoon/twig/wut-test/hep-case.md+51 docs/hoon/twig/wut-test/ket-ifcl.md+37 docs/hoon/twig/wut-test/lus-deft.md+43 docs/hoon/twig/wut-test/pam-and.md+31 docs/hoon/twig/wut-test/pat-ifat.md+33 docs/hoon/twig/wut-test/sig-ifno.md+34 docs/hoon/twig/wut-test/tis-fits.md+41 docs/hoon/twig/wut-test/zap-not.md+33 docs/hoon/twig/zap-wild.md+11 docs/hoon/twig/zap-wild/gar-wrap.md+28 docs/hoon/twig/zap-wild/tis-code.md+27 docs/hoon/twig/zap-wild/wut-need.md+28 docs/hoon/twig/zap-wild/zap-fail.md+27 docs/nock.md+9 docs/nock/definition.md+168 docs/nock/example.md+365 docs/nock/explanation.md+562 docs/nock/implementations.md+9 docs/nock/implementations/c.md+212 docs/nock/implementations/clojure.md+125 docs/nock/implementations/haskell.md+63 docs/nock/implementations/hoon.md+54 docs/nock/implementations/python.md+95 docs/nock/implementations/ruby.md+139 docs/nock/implementations/scala.md+86 docs/theory.md−26 docs/theory/network-goals.md−565 docs/theory/old.md−21 docs/theory/part-i.md−512 docs/theory/part-ii.md−462 docs/theory/whitepaper.md−2347 docs/user.md−25 docs/user/appliance.md−274 docs/user/basic.md−149 docs/user/clay.md−418 docs/user/dojo.md−547 docs/user/launch.md−112 docs/user/talk.md−313 docs/user/tour.md−209 docs/using.md+8 docs/using/admin.md+99 docs/using/filesystem.md+240 docs/using/install.md+82 docs/using/layout.md+107 docs/using/messaging.md+194 docs/using/setup.md+88 docs/using/shell.md+277 docs/using/web.md+299 docs/using/web/blog.md+95 docs/using/web/comments.md+43 docs/using/web/static.md+127
docs.md+17−15
@@ -1,24 +1,26 @@
11---
22anchor: none
3−layout: no-anchor
4−logo: black
3+footer: true
4+title: Develop
5+sort: 4
56---
67
7−<div class="short">
8−
9−# Urbit documentation
10−
11−The Urbit doc is divided into three parts: [user doc](docs/user),
12−[developer doc](docs/dev), and [theory](docs/theory) (whitepaper, essays,
13−videos, etc).
8+<div class="lead">
9+ <div class="logo inverse"></div>
10+ <h1 class="blue i-b">Urbit docs</h1>
11+</div>
1412
15−If you want to try Urbit, start with the user doc. If you want
16−to learn about Urbit, try the theory. Or just start with the
17−user doc; it doesn't assume any prior knowledge.
13+Go to the [technical overview](about/overview) for a high-level
14+architecture description. To install and run Urbit, read forward from the
15+[installation guide](using/install).
1816
19−The most fun thing to do with Urbit is code, but the developer
20−doc remains under construction. Sorry. We'll have more soon.
17+Most programmers start by [learning Hoon](hoon). Some maniacs can skim the
18+Hoon doc, then go straight to [Arvo systems programming](arvo/system). All
19+registered aspies are required to start with [Nock](nock).
2120
22−<list dataSort="true"></list>
21+<br/>
22+<br/>
2323
24+<div class="sections">
25+ <kids grid="true"></kids>
2426</div>
docs/about.mdnew file+8
@@ -0,0 +1,8 @@
1+---
2+navhome: /docs
3+sort: 1
4+---
5+
6+# About
7+
8+<list/>
docs/user/intro.md → docs/about/overview.mdrenamed+15−64
@@ -1,10 +1,11 @@
11---
2+navhome: /docs
23next: true
34sort: 1
4−title: Introduction
5+title: Technical overview
56---
67
7−# Introduction
8+# Technical overview
89
910Urbit is a clean-slate system software stack defined as a
1011deterministic computer. An encrypted P2P network, `%ames`, runs
@@ -12,15 +13,6 @@ on a functional operating system, Arvo, written in a strict,
1213typed functional language, Hoon, which compiles itself to a
1314combinator interpreter, Nock, whose spec gzips to 340 bytes.
1415
15−What is Urbit for? Most directly, Urbit is designed as a
16−personal cloud server for self-hosted web apps. It also uses
17−HTTP APIs to manage data stuck in traditional web applications.
18−
19−More broadly, Urbit's network tackles identity and security
20−problems which the Internet can't easily address. Programming
21−for a deterministic single-level store is also a different
22−experience from Unix programming, regardless of language.
23−
2416## Architectural overview
2517
2618A deterministic computer? Urbit's state is a pure function of
@@ -35,7 +27,9 @@ Instead, the top-level event function defines an I/O protocol.
3527It maps an input event and the current state to a list of output
3628actions and the subsequent state. In Hoon:
3729
38− $+([event state] [(list action) state])
30+```
31+$-([event state] [(list action) state])
32+```
3933
4034### Nock
4135
@@ -72,17 +66,17 @@ control system (`%clay`), a web client/server (`%eyre`), a
7266functional build system (`%ford`), and an application engine
7367`(%gall)`.
7468
75−### `%ames`
69+### Ames
7670
77−`%ames`, the Urbit network, is an encrypted P2P protocol over
78−UDP. Its address space is semi-decentralized; 64-bit addresses
79−are hierarchically distributed, 128-bit addresses are
80−self-created. Addresses (or *plots*) are rendered in a phonemic
81−syntax for memorability. The scarcity of short plots helps
82−control spam and other Sybil attacks. The short plot hierarchy
83−is also reused as a supernode routing system for NAT traversal.
71+Ames, the Urbit network, is an encrypted P2P protocol over UDP.
72+Its address space is semi-decentralized; 64-bit addresses are
73+hierarchically distributed, 128-bit addresses are self-created.
74+Addresses (or *plots*) are rendered in a phonemic syntax for
75+memorability. The scarcity of short plots helps control spam and
76+other Sybil attacks. The short plot hierarchy is also reused as
77+a supernode routing system for NAT traversal.
8478
85−### Apps
79+### Dojo and talk
8680
8781Urbit ships with two default applications: a REPL or shell
8882`:dojo`, and a distributed user-level message-bus `:talk`.
@@ -92,46 +86,3 @@ a self-hosted Slack or persistent IRC.
9286The full Urbit stack (compiler, standard library, kernel,
9387modules, and applications) is about 25,000 lines of Hoon.
9488Urbit is patent-free and MIT licensed.
95−
96−## Status
97−
98−Anyone can run the Urbit VM, of course. But the `%ames` network
99−is officially invitation-only. Not that we're antisocial -- just
100−that we're under construction.
101−
102−Right now, Urbit's only practical use is to (a) build Urbit and
103−(b) talk about Urbit. Its performance is lamentable. Its
104−documentation is inadequate. Its keys are test keys. Its
105−planets explode on a regular basis. We reserve the right to
106−reboot ("flag-day") the whole network.
107−
108−However, Urbit is at least out of research mode and focused more
109−or less exclusively on optimization and bug-fixing. So at least,
110−whatever you learn will stay true. And bleeding edges are fun.
111−
112−## Getting involved
113−
114−If you're interested in following Urbit, you can:
115−
116−- Read our documentation at
117− [urbit.org](http://urbit.org/docs)
118−- Subscribe to our newsletter at [urbit.org](http://urbit.org).
119−- Check out the
120− [urbit-dev](https://groups.google.com/forum/#!forum/urbit-dev)
121− mailing list.
122−- Follow [@urbit_](https://twitter.com/urbit\_) on Twitter.
123−- Hit us up by email, <span class="mono">urbit@urbit.org</span>.
124− We're nice!
125−
126−## Code of conduct
127−
128−Everyone involved in the Urbit project needs to understand and
129−respect our code of conduct, which is: "don't be rude."
130−
131−## Pronunciation and etymology
132−
133−Urbit is always pronounced "herb it," never "your bit." Not that
134−it's not your bit! But "herb it" just sounds better. (Yes, we
135−speak American and the 'h' is silent.)
136−
137−The origin of the name is just the Latin *urbi*, meaning city.
docs/dev/interpreter/u3.md → docs/about/runtime.mdrenamed+18−2
@@ -1,4 +1,20 @@
1−# u3: noun processing in C
1+---
2+navhome: /docs
3+sort: 2
4+title: C runtime system
5+---
6+
7+# C runtime system
8+
9+The Urbit interpreter is built on a Nock runtime system written
10+in C, `u3`. This document is a relatively complete description
11+
12+You should keep reading if (a) you're planning to work on the
13+Urbit interpreter; (b) you're a language implementation geek; or
14+(c) you don't really understand anything until you've seen the
15+actual structs.
16+
17+## u3: noun processing in C
218
319`u3` is the C library that makes Urbit work. If it wasn't called
420`u3`, it might be called `libnoun` - it's a library for making
@@ -16,7 +32,7 @@ spec fits on a page and gzips to 340 bytes. But the only
1632arithmetic operation in Nock is increment. So it's nontrivial
1733to compute both efficiently and correctly.
1834
19−Two: `u3` is designed to support "permanent computing," ie, a
35+Two: `u3` is designed to be a "solid-state interpreter," ie, a
2036single-level store which is transparently snapshotted. This
2137implies a specialized memory-management model, etc, etc.
2238
docs/arvo.mdnew file+8
@@ -0,0 +1,8 @@
1+---
2+navhome: /docs
3+sort: 4
4+---
5+
6+# Arvo
7+
8+<list/>
docs/arvo/api.mdnew file+526
@@ -0,0 +1,526 @@
1+---
2+navhome: /docs
3+next: true
4+sort: 12
5+title: API Connectors
6+---
7+
8+# API Connectors
9+
10+Most people have lots of data stored in online services, many of
11+which have APIs. API connectors allow the user to access this
12+data from within their Urbit.
13+
14+A security driver allows the user to make authenticated requests
15+to the service's API, but the user still needs to know the API
16+and send and receive JSON. An API connector puts a layer of
17+porcelain over this to allow the user easier control over their
18+data.
19+
20+Each connector should perform two basic functions. First, it
21+should expose a tree of the data in the service that's accessible
22+through `.^` and FUSE. Second, it should expose event streams as
23+actions occur in the service. Let's take a look at how the `%gh`
24+app accomplishes both for Github.
25+
26+After starting `%gh` (`|start %gh`), let's look at the root of
27+the tree that `%gh` exposes:
28+
29+ ~your-urbit:dojo> .^(arch %gy /=gh=)
30+ [fil=~ dir={[p=~.issues q=~]}]
31+
32+`%gh` is currently a skeleton -- it contains examples of all the
33+functionality necessary for a connector, but many endpoints
34+aren't implemented. As we can see here, only issues are
35+implemented. We can explore this tree:
36+
37+ ~your-urbit:dojo> .^(arch %gy /=gh=/issues)
38+ [fil=~ dir={[p=~.by-repo q=~] [p=~.mine q=~]}]
39+
40+And eventually:
41+
42+ /- gh
43+ .^(issue:gh %gx /=gh=/issues/by-repo/philipcmonktest/testing/7)
44+ <issue...>
45+ login.user:.^(issue:gh %gx /=gh=/issues/by-repo/philipcmonktest/testing/7)
46+ 'philipcmonktest'
47+
48+The other thing an API connector needs to do is expose event
49+streams. One straightforward way to use this capacity is with
50+the `:pipe` app:
51+
52+ :pipe|connect %gh /listen/philipcmonktest/testing/issues/'issue_comment' %public
53+
54+Now creating an issue results in the following message in your
55+`%public` `:talk` channel:
56+
57+ ~your-urbit[philipcmonktest@github]: opened issue #11: i found a bug!
58+
59+You'll also get notifications of issue status changes and
60+comments.
61+
62+As is often the case, the best way to write an API connector is
63+to copy an existing one and modify it. We'll dissect the Github
64+connector here. This code is in `/=home=/app/gh/hoon`, and it's
65+also reproduced at the bottom of this page (in case the code
66+drifts out of sync with this doc).
67+
68+We'll go over the two parts to an API connector (one-time reading vs listening
69+for events) separately.
70+
71+## Reading
72+
73+A connector exposes a tree of data. Every read request has a
74+`care`, which is generally either `%x` or `%y. `%x` is a request
75+for a particular piece of data, while `%y` is a request for a
76+directory listing. Roughly, `%x` means Unix `cat` and `%y` means
77+Unix `ls`.
78+
79+> Sometimes you wish to expose a tree where a part of the path
80+> can't be enumerated. For example, a `%y` of `/issues/by-repo`
81+> "should" produce a list of all Github users, but we don't do
82+> that because it's too long. Instead, we just produce our own
83+> username (from the `web.plan` file). You can still access
84+> repos from other users, you just don't see them in the
85+> directory listing.
86+
87+The usual flow for implementing this tree of data makes heavy use
88+of the `connector` library. This library is well documented in
89+the source, so check out `/=home=/lib/connector/hoon`.
90+
91+The `connector` library needs to be initialized with definitions
92+of `move` and `sub-result` (all the types of data that can be
93+returned by a place). This can just be a line at the top of the
94+main core:
95+
96+ =+ connector=(connector move sub-result) :: Set up connector library
97+
98+Most of the Github-specific logic is in `++places`, which is a
99+list of all the places we can request. A place consists of:
100+
101+ ++ place
102+ $: guard/mold
103+ read-x/$-(path move)
104+ read-y/$-(path move)
105+ sigh-x/$-(jon/json (unit sub-result))
106+ sigh-y/$-(jon/json (unit arch))
107+ ==
108+
109+- `guard`, the type of the paths we should match. For example,
110+ to match `/issues/<user>/<repo>` use `{$issues @t @t $~}`.
111+
112+- `read-x`, called when someone tries to read the place with
113+ `care` `%x`. Should produce a single move, usually either a
114+ `%diff` response if we can immediately answer or a `%hiss`
115+ http request if we need to make a request to the api. See the
116+ `++read-*` functions in `++helpers` for some common handlers.
117+
118+- `read-y`, same as `read-x` except with care `%y`.
119+
120+- `sigh-x`, called when an http response comes back on this
121+ place. You're given the json of the result, and you should
122+ produce either a result or null. Null represents an error.
123+ If you didn't create an http request in `read-x`, then this
124+ should never be called. Use `++sigh-strange` from `++helpers`
125+ to unconditionally signal an error.
126+
127+- `sigh-y`, same as `sigh-x` except with care `%y`. Note that a
128+ `%y` request must produce an arch, unlike a `%x` request,
129+ which may produce data of any mark.
130+
131+Filling out the list of places is a lot of grunt work, but most
132+places are fairly straightforward, and the `++read-*` helper
133+functions are useful. Check out the library source for more
134+information on those.
135+
136+Besides the list of places, we just need to handle the flow of
137+control. `++peek` and `++peer-scry` are the interface we expose
138+to the rest of the system while `++sigh-httr` and `++sigh-tang`
139+are used to handle responses when we make HTTP requests.
140+
141+- `++peek` should usually just produce `~`. If there are cases
142+ where we can respond directly to a `.^` request without
143+ blocking on anything, we could do it here, but it's generally
144+ not worth the hassle since the same logic should be duplicated
145+ in `++peer-scry`.
146+
147+- `++peer-scry` is where the actual handling for a read request
148+ goes. In general, we just need to call `++read` from the
149+ `connector` library with the bone, list of places, care, and
150+ path. This will match the path to the appropriate place and
151+ run either `++read-x` or `++read-y`, depending on the care.
152+
153+- If `++read-x` or `++read-y` made a successful API request, then
154+ the response will come back on `++sigh-httr`. Here, we just
155+ need to parse out the wire and call `++sigh` from the
156+ `connector` library with the list of places, care, path, and
157+ HTTP result. This will match the path to the appropriate place
158+ and run either `++sigh-x` or `++sigh-y`, depending on the care.
159+
160+- If `++read-x` or `++read-y` made an API request that failed,
161+ then we'll get a stack trace in `++sigh-tang`. Here, we just
162+ print it out and move on.
163+
164+That's really all there is to the reading portion of API
165+connectors.
166+
167+One of the most accessbile ways to jump into Arvo programming is
168+to just add more places to an existing API connector. It's
169+useful, small in scope, and comes in bite-sized chunks since most
170+places are less than ten lines of code.
171+
172+## Listening
173+
174+Listening for events is fairly service-specific. In some
175+services, we poll for changes. The Twitter connector has an
176+example of this, but note that it predates the `connector`
177+library and is thus more complicated than it needs to be, and the
178+interface it exposes isn't standard. In Github, we power our
179+event streams with webhooks.
180+
181+For Github, when someone subscribes to
182+`/listen/<user>/<repo>/<events...>`, we want to produce
183+well-typed results when they occur.
184+
185+We only want to create one webhook per event, so in our state we
186+have `hook`, which is a map of event names to the set of bones
187+which are subscribed to that event. We must always keep this
188+up-to-date.
189+
190+Flow of control starts in `++peer-listen`, where we just call
191+`++listen`. In `++listen`, for each event in the list of events,
192+we check to see if we have that hook set up (by checking whether
193+it exists in `hook`). If so, we call `++update-hook` to add the
194+current bone to the set of listeners. Otherwise, we call
195+`++create-hook`, which sends a request to Github to set up the
196+new webhook. We also create an entry in `hook` with the current
197+bone.
198+
199+When we created the webhook, we told Github to send the event to
200+`/~/to/gh/gh-<event>.json?anon&wire=/`. This turns into a poke.
201+Let's parse out this url. The first `gh` is the app name to
202+poke. The next portion, `gh-<event>` is the mark to convert the
203+JSON to. For example, when the "issues" event fires, it'll get
204+converted to mark `gh-issues`. This mark has a conversion
205+routine from `json` to the `issues` type, which is defined in the
206+`gh` structure (`/=home=/sur/gh/hoon`). Once this conversion
207+happens, the `gh` app will get poked with the correctly marked
208+data in `++poke`.
209+
210+In `++poke`, we check `hook` to find the subscribers to the event
211+that was fired, and we update them.
212+
213+That's really all there is to it. Webhook flow isn't well
214+standardized, so even if your chosen service is powered by
215+webhooks, your listening code might look rather different. The
216+point is to expose the correct interface.
217+
218+
219+## Github API Connector Code
220+
221+In case the code in `/=home=/app/gh/hoon` drifts out of sync with
222+this doc:
223+
224+```
225+:: This is a connector for the Github API v3.
226+::
227+:: You can interact with this in a few different ways:
228+::
229+:: - .^({type} %gx /=gh={/endpoint}) to read data or
230+:: .^(arch %gy /=gh={/endpoint}) to explore the possible
231+:: endpoints.
232+::
233+:: - subscribe to /listen/{owner}/{repo}/{events...} for
234+:: webhook-powered event notifications. For event list, see
235+:: https://developer.github.com/webhooks/.
236+::
237+:: This is written with the standard structure for api
238+:: connectors, as described in lib/connector.hoon.
239+::
240+/? 314
241+/- gh, plan-acct
242+/+ gh-parse, connector
243+::
244+!:
245+=> |%
246+ ++ move (pair bone card)
247+ ++ card
248+ $% {$diff sub-result}
249+ {$them wire (unit hiss)}
250+ {$hiss wire {$~ $~} $httr {$hiss hiss}}
251+ ==
252+ ::
253+ :: Types of results we produce to subscribers.
254+ ::
255+ ++ sub-result
256+ $% {$arch arch}
257+ {$gh-issue issue:gh}
258+ {$gh-list-issues (list issue:gh)}
259+ {$gh-issues issues:gh}
260+ {$gh-issue-comment issue-comment:gh}
261+ {$json json}
262+ {$null $~}
263+ ==
264+ ::
265+ :: Types of webhooks we expect.
266+ ::
267+ ++ hook-response
268+ $% {$gh-issues issues:gh}
269+ {$gh-issue-comment issue-comment:gh}
270+ ==
271+ --
272+=+ connector=(connector move sub-result) :: Set up connector library
273+::
274+|_ $: hid/bowl
275+ hook/(map @t {id/@t listeners/(set bone)}) :: map events to listeners
276+ ==
277+:: ++ prep _`. :: Clear state when code changes
278+::
279+:: List of endpoints
280+::
281+++ places
282+ |= wir/wire
283+ ^- (list place:connector)
284+ =+ (helpers:connector ost.hid wir "https://api.github.com")
285+ => |% :: gh-specific helpers
286+ ++ sigh-list-issues-x
287+ |= jon/json
288+ %+ bind ((ar:jo issue:gh-parse) jon)
289+ |= issues/(list issue:gh)
290+ gh-list-issues+issues
291+ ::
292+ ++ sigh-list-issues-y
293+ |= jon/json
294+ %+ bind ((ar:jo issue:gh-parse) jon)
295+ |= issues/(list issue:gh)
296+ :- `(shax (jam issues))
297+ (malt (turn issues |=(issue:gh [(rsh 3 2 (scot %ui number)) ~])))
298+ --
299+ :~ ^- place :: /
300+ :* guard=$~
301+ read-x=read-null
302+ read-y=(read-static %issues ~)
303+ sigh-x=sigh-strange
304+ sigh-y=sigh-strange
305+ ==
306+ ^- place :: /issues
307+ :* guard={$issues $~}
308+ read-x=read-null
309+ read-y=(read-static %mine %by-repo ~)
310+ sigh-x=sigh-strange
311+ sigh-y=sigh-strange
312+ ==
313+ ^- place :: /issues/mine
314+ :* guard={$issues $mine $~}
315+ read-x=(read-get /issues)
316+ read-y=(read-get /issues)
317+ sigh-x=sigh-list-issues-x
318+ sigh-y=sigh-list-issues-y
319+ ==
320+ ^- place :: /issues/by-repo
321+ :* guard={$issues $by-repo $~}
322+ read-x=read-null
323+ ^= read-y
324+ |= pax/path
325+ =+ /(scot %p our.hid)/home/(scot %da now.hid)/web/plan
326+ =+ .^({* acc/(map knot plan-acct)} %cx -)
327+ ::
328+ ((read-static usr:(~(got by acc) %github) ~) pax)
329+ sigh-x=sigh-strange
330+ sigh-y=sigh-strange
331+ ==
332+ ^- place :: /issues/by-repo/<user>
333+ :* guard={$issues $by-repo @t $~}
334+ read-x=read-null
335+ read-y=|=(pax/path (get /users/[-.+>.pax]/repos))
336+ sigh-x=sigh-strange
337+ ^= sigh-y
338+ |= jon/json
339+ %+ bind ((ar:jo repository:gh-parse) jon)
340+ |= repos/(list repository:gh)
341+ [~ (malt (turn repos |=(repository:gh [name ~])))]
342+ ==
343+ ^- place :: /issues/by-repo/<user>/<repo>
344+ :* guard={$issues $by-repo @t @t $~}
345+ read-x=|=(pax/path (get /repos/[-.+>.pax]/[-.+>+.pax]/issues))
346+ read-y=|=(pax/path (get /repos/[-.+>.pax]/[-.+>+.pax]/issues))
347+ sigh-x=sigh-list-issues-x
348+ sigh-y=sigh-list-issues-y
349+ ==
350+ ^- place :: /issues/by-repo/<user>/<repo>
351+ :* guard={$issues $by-repo @t @t @t $~}
352+ ^= read-x
353+ |=(pax/path (get /repos/[-.+>.pax]/[-.+>+.pax]/issues/[-.+>+>.pax]))
354+ ::
355+ read-y=(read-static ~)
356+ ^= sigh-x
357+ |= jon/json
358+ %+ bind (issue:gh-parse jon)
359+ |= issue/issue:gh
360+ gh-issue+issue
361+ ::
362+ sigh-y=sigh-strange
363+ ==
364+ ==
365+::
366+:: When a peek on a path blocks, ford turns it into a peer on
367+:: /scry/{care}/{path}. You can also just peer to this
368+:: directly.
369+::
370+:: We hand control to ++scry.
371+::
372+++ peer-scry
373+ |= pax/path
374+ ^- {(list move) _+>.$}
375+ ?> ?=({care *} pax)
376+ :_ +>.$ :_ ~
377+ (read:connector ost.hid (places %read pax) i.pax t.pax)
378+::
379+:: HTTP response. We make sure the response is good, then
380+:: produce the result (as JSON) to whoever sent the request.
381+::
382+++ sigh-httr
383+ |= {way/wire res/httr}
384+ ^- {(list move) _+>.$}
385+ ?. ?=({$read care @ *} way)
386+ ~& res=res
387+ [~ +>.$]
388+ =* style i.way
389+ =* ren i.t.way
390+ =* pax t.t.way
391+ :_ +>.$ :_ ~
392+ :+ ost.hid %diff
393+ (sigh:connector (places ren style pax) ren pax res)
394+::
395+:: HTTP error. We just print it out, though maybe we should
396+:: also produce a result so that the request doesn't hang?
397+::
398+++ sigh-tang
399+ |= {way/wire tan/tang}
400+ ^- {(list move) _+>.$}
401+ %- (slog >%gh-sigh-tang< tan)
402+ [[ost.hid %diff null+~]~ +>.$]
403+::
404+:: We can't actually give the response to pretty much anything
405+:: without blocking, so we just block unconditionally.
406+::
407+++ peek
408+ |= {ren/@tas tyl/path}
409+ ^- (unit (unit (pair mark *)))
410+ ~ ::``noun/[ren tyl]
411+::
412+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
413+:: Webhook-powered event streams (/listen) ::
414+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
415+::
416+:: To listen to a webhook-powered stream of events, subscribe
417+:: to /listen/<user>/<repo>/<events...>
418+::
419+:: We hand control to ++listen.
420+::
421+++ peer-listen
422+ |= pax/path
423+ ^- {(list move) _+>.$}
424+ ?. ?=({@ @ *} pax)
425+ ~& [%bad-listen-path pax]
426+ [~ +>.$]
427+ (listen pax)
428+::
429+:: This core handles event subscription requests by starting or
430+:: updating the webhook flow for each event.
431+::
432+++ listen
433+ |= pax/path
434+ =| mow/(list move)
435+ =< abet:listen
436+ |%
437+ ++ abet :: Resolve core.
438+ ^- {(list move) _+>.$}
439+ [(flop mow) +>.$]
440+ ::
441+ ++ send-hiss :: Send a hiss
442+ |= hiz/hiss
443+ ^+ +>
444+ =+ wir=`wire`[%x %listen pax]
445+ +>.$(mow [[ost.hid %hiss wir `~ %httr [%hiss hiz]] mow])
446+ ::
447+ :: Create or update a webhook to listen for a set of events.
448+ ::
449+ ++ listen
450+ ^+ .
451+ =+ pax=pax :: TMI-proofing
452+ ?> ?=({@ @ *} pax)
453+ =+ events=t.t.pax
454+ |- ^+ +>+.$
455+ ?~ events
456+ +>+.$
457+ ?: (~(has by hook) i.events)
458+ $(+>+ (update-hook i.events), events t.events)
459+ $(+>+ (create-hook i.events), events t.events)
460+ ::
461+ :: Set up a webhook.
462+ ::
463+ ++ create-hook
464+ |= event/@t
465+ ^+ +>
466+ ?> ?=({@ @ *} pax)
467+ =+ clean-event=`tape`(turn (trip event) |=(a/@tD ?:(=('_' a) '-' a)))
468+ =. hook
469+ %+ ~(put by hook) (crip clean-event)
470+ =+ %+ fall
471+ (~(get by hook) (crip clean-event))
472+ *{id/@t listeners/(set bone)}
473+ [id (~(put in listeners) ost.hid)]
474+ %- send-hiss
475+ :* %+ scan
476+ =+ [(trip i.pax) (trip i.t.pax)]
477+ "https://api.github.com/repos/{-<}/{->}/hooks"
478+ auri:epur
479+ %post ~ ~
480+ %- taco %- crip %- pojo %- jobe :~
481+ name+s+%web
482+ active+b+&
483+ events+a+~[s+event] ::(turn `(list ,@t)`t.t.pax |=(a=@t s/a))
484+ :- %config
485+ %- jobe :~
486+ =+ =+ clean-event
487+ "http://107.170.195.5:8443/~/to/gh/gh-{-}.json?anon&wire=/"
488+ [%url s+(crip -)]
489+ [%'content_type' s+%json]
490+ ==
491+ ==
492+ ==
493+ ::
494+ :: Add current bone to the list of subscribers for this event.
495+ ::
496+ ++ update-hook
497+ |= event/@t
498+ ^+ +>
499+ =+ hok=(~(got by hook) event)
500+ %_ +>.$
501+ hook
502+ %+ ~(put by hook) event
503+ hok(listeners (~(put in listeners.hok) ost.hid))
504+ ==
505+ --
506+::
507+:: Pokes that aren't caught in more specific arms are handled
508+:: here. These should be only from webhooks firing, so if we
509+:: get any mark that we shouldn't get from a webhook, we reject
510+:: it. Otherwise, we spam out the event to everyone who's
511+:: listening for that event.
512+::
513+++ poke
514+ |= response/hook-response
515+ ^- {(list move) _+>.$}
516+ =+ hook-data=(~(get by hook) (rsh 3 3 -.response))
517+ ?~ hook-data
518+ ~& [%strange-hook hook response]
519+ [~ +>.$]
520+ :: ~& response=response
521+ :_ +>.$
522+ %+ turn (~(tap in listeners.u.hook-data))
523+ |= ost/bone
524+ [ost %diff response]
525+--
526+```
docs/dev/hoon/leap-in/basic.md → docs/arvo/basic.mdrenamed+82−178
@@ -1,50 +1,40 @@
11---
2−logo: black
2+navhome: /docs
33sort: 1
44next: true
5−title: Basic Hoon
5+title: Hoon refresher / crash course
66---
77
88# Basic Hoon
99
10+This recapitulates material you've already learned in Core Hoon.
11+It will be a very abrupt tutorial if you don't know Hoon already,
12+but it may be enough in and of itself. If you don't find it obvious at first
13+glance, read it over again.
14+
1015Our goal is to get you programming interesting and useful things
11−as soon as possible. To get there we have to quickly cover some
12−of the fundamentals of hoon. To do this we'll walk through two
16+as soon as possible. To get there, we have to quickly cover some
17+of the fundamentals of hoon. To do this, we'll walk through two
1318simple programs: the first [Project
1419Euler](https://projecteuler.net/) problem and
1520[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz).
1621
17−To run this code, you'll need an urbit, and you'll need the
18−`%examples` desk from `~wactex-ribmex`. If you haven't installed
19−urbit yet, check out the [installation
20−instructions](http://urbit.org/docs/user/install). Once urbit is
21−intalled, take a look at the [basic
22−operation](http://urbit.org/docs/user/basic) of your urbit.
23−
24−If you haven't pulled the examples desk from `~wactex-ribmex`, do
25−so now:
26−
27− ~fintud-macrep:dojo> |merge %examples ~wactex-ribmex %examples
28− >=
29− ; ~wactex-ribmex is your neighbor
30− ; ~wactex-ribmex is your neighbor
31− [time passes...]
32− merged with strategy %init
33−
34−The merge could take several minutes; you'll know it's done when
35−"merged with strategy %init" is printed. Mount the new files to
36−your Unix pier directory:
22+To run this code, you'll need an urbit, and will have to copy the [examples repo](https://github.com/urbit/examples) into it.
3723
38− ~fintud-macrep:dojo> |mount /=examples=
24+If you haven't installed
25+urbit yet, check out the [installation
26+instructions](/docs/user/install). Once urbit is
27+installed, take a look at the [basic
28+operation](/docs/user/basic) of your urbit.
3929
40−Switch desks to run commands from the `%examples` desk:
30+If you haven't copied in the examples repo, running the following commands from your urbit directory should do the trick:
4131
42− ~fintud-macrep:dojo> =dir /=examples=
43− =% /~fintud-macrep/examples/~2015.11.13..02.25.00..41e9/
32+`cp -r {wherever-you've-pulled-to}/examples/gall/*/ arvo/`
33+`cp -r {wherever-you've-pulled-to}/examples/dojo/*/ arvo/`
4434
45−Run an example:
35+Run an example to ensure it worked:
4636
47− ~fintud-macrep:dojo> +euler1
37+ ~fintud-macrep:dojo> +examples-euler1
4838 233.168
4939
5040## Euler 1
@@ -59,33 +49,33 @@ Find the sum of all the multiples of 3 or 5 below 1000.
5949```
6050
6151Here is the hoon solution (which should be in your pier directory
62−under `/examples/gen/euler1.hoon`):
52+under `/gen/examples/euler1`):
6353
6454```
6555:: project euler 1
6656:: https://projecteuler.net/problem=1
67−:: run in dojo with +euler1
57+:: run in dojo with +examples-euler1
6858::
69−:::: /hoon/euler1/gen
59+:::: /hoon/euler1/examples/gen
7060 ::
7161:- %say |= *
7262:- %noun
7363=< (sum 1.000)
7464::
75−:::: ~fintud-macrep
65+:::: ~sivtyv-barnel
7666 ::
7767|%
7868++ three
79− |= a=@
80− =| b=@
69+ |= a/@
70+ =| b/@
8171 |- ^- @u
8272 ?: (lth a b)
8373 0
8474 (add b $(b (add 3 b)))
8575
8676++ five
87− |= a=@
88− =| b=@
77+ |= a/@
78+ =| b/@
8979 |- ^- @
9080 ?: (lte a b)
9181 0
@@ -94,17 +84,21 @@ under `/examples/gen/euler1.hoon`):
9484 (add b $(b (add b 5)))
9585
9686++ sum
97− |= a=@u
87+ |= a/@u
9888 (add (five a) (three a))
9989--
10090```
10191
102−> Hoon is not generally whitespace sensitive, but we do have two
103−> different kinds of whitespace: a single space and a gap, which
104−> is two or more spaces or a linebreak. Tabs are taboo. Do not
105−> use them. Really. For a more detailed explanation of when to
106−> use spaces vs. gaps, see the syntax section before the first
107−> excercises.
92+
93+<blockquote class="blockquote">
94+Hoon is not generally whitespace sensitive, but we do have two
95+different kinds of whitespace: a single space and a gap, which
96+is two or more spaces or a linebreak. Tabs are taboo. Do not
97+use them. Really. For a more detailed explanation of when to
98+use spaces vs. gaps, see the syntax section before the first
99+excercises.
100+</blockquote>
101+
108102
109103### Lines 1-11:
110104
@@ -120,11 +114,11 @@ more detail later.
120114
121115### How to form expressions
122116
123−Hoon does not use reserved words to form expressions. Instead,
124−expressions are formed with runes, which are diagraphs of two
117+Hoon does not typically use reserved words to form expressions. Instead,
118+expressions are formed with runes--diagraphs of two
125119ascii symbols. Each rune takes a specific number of
126120children--either expressions formed by other runes or literals
127−that produce their own value.
121+that produce their own value (some runes take n children, and are usually closed with `==`).
128122
129123For example, the rune `?:` from line 17 is the classic
130124'if-then-else' statement, and thus takes three children:
@@ -160,6 +154,23 @@ See the entire naming schema below/or link to it:
160154
161155Using our naming scheme `?:` is said 'wut col'.
162156
157+For those that would prefer to use reserved words to form expressions, you can substitute a rune's keyword--which you can find in `++twig` in `/arvo/hoon.hoon`--for the rune. For example, here's the code for `?:` in `++twig`:
158+
159+`{$if p/twig q/twig r/twig} :: ?: if/then/else`
160+
161+Instead of:
162+
163+```
164+?:(=(1 2) 'this is true' 'this is false')
165+'this is false'`
166+```
167+You can write:
168+
169+```
170+if(=(1 2) 'this is true' 'this is false')
171+'this is false'
172+```
173+
163174### Lines 12-34
164175
165176Now let's quickly walk through this code line-by-line. Lines
@@ -171,22 +182,24 @@ element in this map begins with a `++` followed by the name and
171182the corresponding code. Since `|%` takes an arbitrary number of
172183children, it needs to be closed with a `--`.
173184
174−> `++` is not technically a rune, since it is only used in core
175−> syntax as shown above
185+<blockquote class="blockquote">
186+`++` is not technically a rune, since it is only used in core
187+syntax as shown above
188+</blockquote>
176189
177190Let's step into each of the three arms within our core.
178191
179192### `++ sum`
180193
181194 ++ sum
182− |= a=@
195+ |= a/@
183196 (add (five a) (three a))
184197 --
185198
186199`|=` produces a function, much like a lambda in lisp. It takes two children:
187200
188201- A set of argument(s). In this case our argument set only
189− contains one: `a` which is required to be an atom or natural
202+ contains one: `a`, which is required to be an atom or natural
190203 number, denoted by `@`.
191204
192205- The body of the function itself, which is executed when the
@@ -198,8 +211,8 @@ Let's step into each of the three arms within our core.
198211### ++ three
199212
200213 ++ three
201− |= a=@
202− =| b=@
214+ |= a/@
215+ =| b/@
203216 |- ^- @u
204217 ?: (lth a b)
205218 0
@@ -236,14 +249,16 @@ Note that we only specify what changes (`b` in this case). If
236249you recurse by an actual function call, then you have to specify
237250every argument.
238251
239−> If you're familiar with Clojure, `|-` is `loop` and `$()` is
240−> recur.
252+<blockquote class="blockquote">
253+If you're familiar with Clojure, `|-` is `loop` and `$()` is
254+recur.
255+</blockquote>
241256
242257**Exercises**:
243258
244259Please tweak your code to complete the following excercises.
245260
246−There are a few runes and some syntax that we have yet to cover that
261+There are a few runes and some syntaxes that we have yet to cover that
247262you will need to complete the excercises below. For these, please
248263refer to our cheatsheat at the bottom.
249264
@@ -251,7 +266,7 @@ refer to our cheatsheat at the bottom.
251266
252267- Change `++sum` to accept two variables, `a` and `b`. Pass `a`
253268 to three and `b` to five. Then run the code with `a` set to
254− `1.000` and b set to `2.000`.
269+ `1.000` and ` q` set to `2.000`.
255270
256271- Check if this new result is under one thousand. If it is,
257272 return the string 'result is less than one thousand'. If not,
@@ -260,7 +275,7 @@ refer to our cheatsheat at the bottom.
260275```
261276Review
262277
263−|% start core (collection of named ++ arms)
278+|% start core (collection of named ++ arms; an "object")
264279|= define function
265280=| define variable from type with default value
266281|- drop a recursion point
@@ -271,14 +286,6 @@ Review
271286
272287New material
273288
274−- :- make a cell of values. The irregular wide form of this is
275− [a b] with two expressions separated by a single space.
276−
277−- Cords are one datatype for text in hoon. They're just a big
278− atom formed from adjacent unicode bytes -- a "c string". To
279− produce a cord enclose text within single quotes. To set the type
280− of an argument to a cord, use @t.
281−
282289- There are two syntaxes for writing Hoon: tall form and wide
283290 form.
284291
@@ -301,118 +308,15 @@ New material
301308 =((mod b 3) 0). In this case = is actually an irregular form
302309 of .=, which tests its two children for equality.
303310
304− Another irregular form is [a b] for :-(a b)
305−
306311 Surrounding a function with () is an irregular wide form
307− syntax for calling a function with n arguments.
308−```
309−
310−
311−## The subject
312−
313−Now we're going to cover the boiler plate that we skimmed over
314−earlier.
315−
316− :- %say |= *
317− :- %noun
318− =< (sum [1.000 2.000])
319−
320−This program is a cell of two elements: the first, `%say`, tells
321−the interpreter what to produce--in this case a value.
322−
323−The second element is `|=`, which we know produces a function.
324−`|=`'s first child is its argument(s), which in this case is any
325−noun (`*`). Its second child is the remainder of the program.
326−
327−Similarly, the rest of the program is a cell of the literal
328−`%noun`, which tells the shell that we're producing a value of
329−type `noun`, and the second child contains the code that we run
330−to actually produce our value of the type `noun`.
331−
332−`=<` is a rune that takes two children. The second child is the
333−context against which we run the first child. So in this case, we
334−are running the expression `(sum 1.000)` against everything
335−contained within the `|%`. In Hoon, we call the code executed the
336−"formula" and its context the "subject".
312+ syntax for calling a function with n arguments. More on this later.
337313
338−```
339−::::::::::::::::::::::::::::::
340−=< (sum 1.000) :: formula
341−::::::::::::::::::::::::::::::
342−|% ::
343−++ three ::
344− |= a=@ ::
345− =| b=@ ::
346− |- ^- @u ::
347− ?: (lth a b) ::
348− 0 ::
349− (add b $(b (add 3 b))) ::
350− ::
351−++ five ::
352− |= a=@ :: subject
353− =| b=@ ::
354− |- ^- @ ::
355− ?: (lte a b) ::
356− 0 ::
357− ?: =((mod b 3) 0) ::
358− $(b (add b 5)) ::
359− (add b $(b (add b 5))) ::
360− ::
361−++ sum ::
362− |= a=@u ::
363− (add (five a) (three a)) ::
364−-- ::
365−::::::::::::::::::::::::::::::
366−```
367−
368−In nearly every language there is a similar concept of a
369−"context" in which expressions are executed. For example, in C
370−this includes things like the call stack, stack variables, and so
371−on.
372−
373−Hoon is unique in that this context is a first-class value.
374−Scheme allows a sort of reification of the context through
375−continutations, and some may see a parallel to Forth's stack, but
376−Hoon takes takes the concept one step further.
377−
378−Our starting subject is the standard library, which is defined in
379−`/arvo/hoon.hoon` and `/arvo/zuse.hoon`. This is where functions
380−like `add` are defined. When we define a core with `|%`, we
381−don't throw away the subject (i.e. the standard library); rather,
382−we stack the new core on top of the old subject so that both are
383−accessible.
314+- :- makes a cell of values. The irregular wide form of this is
315+ [a b], with two expressions separated by a single space. (While the regular form of this rune takes a fixed number of children--2--its irregular wide form can accept n expressions:[a1..an])
384316
385−**Exercises**:
317+- Cords are one datatype for text in hoon. They're just a big
318+ atom formed from adjacent unicode bytes -- a "c string". To
319+ produce a cord enclose text within single quotes. To set the type
320+ of an argument to a cord, use @t.
386321
387−- Pass `++sum` its arguments (`2000` and `3000`) from the
388− commandline.
389−
390−- Comment out all of the arms of the `|%`. Now add another arm
391− and call it `++add`, have it accept two arguments and procduce
392− 42 (regardless of input). Change the `=<` line to `[(add 5 7)
393− (^add 5 7)]`. Can you recognize what's happening?
394−
395−- Write a program that prints the numbers from 1 to 100 (entered
396− from the command line), except that for multiples of three
397− print 'Fizz' instead of the number and for the multiples of
398− five print 'Buzz'. For numbers which are multiples of both
399− three and five print 'FizzBuzz'.
400−
401−Cheatsheet:
402−
403−- To pass arguments from the command line to a program, you
404− replace the `*` in the first line of the boiler plate to
405− `[^ [[arg=TYPE ~] ~]]` where `TYPE` is replaced with the
406− type of argument you're expecting. Then `+euler1 a` from
407− the dojo sets `arg` to `a`.
408−- A list of strings is of type `(list ,@t)`, so the result of
409− the fizzbuzz function is of this type (hint: you'll need to
410− use `^-`)
411−- The empty list is `~`
412−- Lisp-style cons (construct a cell/prepend an element) is
413− `[new-element list]`
414−- For example, the first three positive integers are `[1 2 3
415− ~]`
416−- `gte` tests whether `a` is greater than or equal to `b`.
417−- `mod` runs the modulo operation on two atoms.
418−- See the [basic math section]() for more info.
322+```
docs/arvo/generators.mdnew file+253
@@ -0,0 +1,253 @@
1+---
2+navhome: /docs
3+next: true
4+sort: 8
5+title: Using Generators with Apps
6+---
7+
8+# Generators
9+
10+Up until now we've poked apps directly. This requires the user
11+to specify the mark, and it requires the app to accept the
12+arguments in a way that's convenient for users to input. This is
13+the "plumbing" way to interact with apps. Generators are the
14+"porcelain" layer. This is why when you run a command like `+ls` or
15+`|merge`, there are no marks in sight.
16+
17+We've used generators before, back in [Basic
18+Operation](/docs/user/basic). At that point, we just used the generators
19+to produce values -- we didn't pipe their results into apps. In
20+the dojo cast, the role of a generator is to take a list of
21+arguments and produce a value, which is often, though not always,
22+piped into an app. Generators are pure, stateless functions, and
23+they cannot send moves.
24+
25+`+ls` and `+cat` are commonly-used generators that produce a directory
26+listing and print out a file, respectively. These are useful in
27+themselves, so we generally don't pipe the results into an app.
28+
29+Another generator is `+hood/merge`. Try running `+hood/merge`
30+with the normal arguments for `|merge`:
31+
32+```
33+~fintud-macrep:dojo> +hood/merge %home our %they
34+[syd=%home her=~fintud-macrep sud=%they gem=%auto]
35+~fintud-macrep:dojo> +hood/merge %home our %they, =gem %this
36+[syd=%home her=~fintud-macrep sud=%they gem=%auto]
37+```
38+
39+This didn't run any merge, it just constructed the command that,
40+if sent to `:hood`, would run it. Note first that, even though
41+it's not printed, this value has mark `kiln-merge`. Also, the
42+merge strategy `gem=%auto` was added automatically. Optional
43+arguments are straightforward with generators.
44+
45+In general, generators are prepended by either `+` or `|`. The
46+general form is `+generator`, but often generators are created
47+specifically to work with a single app, they're usually placed in
48+a subdirectory of gen and run with `|`. Thus, if `my-generator`
49+generator is made for use with `:my-app`, then `my-generator` is
50+put in `/gen/my-app/my-generator.hoon`, and can be run directly
51+with `+my-app/my-generator <args>`. If you want to pipe the
52+result into `:my-app`, then run `:my-app +my-app/my-generator
53+<args>`. Because this pattern is so common, this can be
54+abbreviated to `:my-app|my-generator <args>`. Because most
55+built-in commands are generators for the `:hood` app,
56+`:hood|generator <args>` can be shortened to `|generator <args>`.
57+
58+Let's write a generator for a modified version of `:examples-pong` from
59+the chapter on [Network Messages](/docs/programming/system/network). Recall that `:examples-pong`
60+takes an urbit address, which is of mark `urbit`, and sends that
61+urbit the message `'howdy'`. First--without a generator--let's
62+make `:examples-ping` that does the same, except that it lets the user
63+optionally specify the message as well.
64+
65+We'll need a new mark for our arguments. Let's call it
66+`examples-ping-message`.
67+
68+<blockquote class="blockquote">
69+For app-specific marks, it's good style to prefix the name of
70+the mark with the name of the app. Since many apps have
71+several such marks, subdirectories in `/mar` are rendered as
72+`-`, so that `ping-message` is written in
73+(/mar/examples/ping/message.hoon).
74+</blockquote>
75+
76+```
77+:: Up-ness monitor. Accepts atom url, 'on', or 'off'
78+::
79+:::: /hoon/up/examples/app
80+ ::
81+/? 314
82+|%
83+++ move {bone card}
84+++ card
85+ $% {$hiss wire $~ $httr {$purl p/purl}}
86+ {$wait wire @da}
87+ ==
88+++ action
89+ $% {$on $~} :: enable polling('on')
90+ {$off $~} :: disable polling('off)
91+ {$target p/cord} :: set poll target('http://...')
92+ ==
93+--
94+|_ {hid/bowl on/_| in-progress/_| target/@t}
95+++ poke-atom
96+ |= url-or-command/@t ^- (quip move +>)
97+ =+ ^- act/action
98+ ?: ?=($on url-or-command) [%on ~]
99+ ?: ?=($off url-or-command) [%off ~]
100+ [%target url-or-command]
101+ ?- -.act
102+ $target [~ +>.$(target p.act)]
103+ $off [~ +>.$(on |)]
104+ $on
105+ :- ?: |(on in-progress) ~
106+ [ost.hid %hiss /request ~ %httr %purl (need (epur target))]~
107+ +>.$(on &, in-progress &)
108+ ==
109+::
110+
111+:: ~& 'i get here'
112+:: ^- {(list move) _+>.$}
113+:: ?: =('off' url)
114+:: [~ +>.$(on |)]
115+:: ?: =('on' url)
116+:: :_ +>.$(on &, in-progress &)
117+:: ?: |(on in-progress)
118+:: ~
119+:: [ost.hid %them /request ~ (need (epur target)) %get ~ ~]~
120+:: [~ +>.$(target url)]
121+++ sigh-httr
122+ |= {wir/wire code/@ud headers/mess body/(unit octs)}
123+ ~& 'arrive here'
124+ ^- {(list move) _+>.$}
125+ ?: &((gte code 200) (lth code 300))
126+ ~& [%all-is-well code]
127+ :_ +>.$
128+ [ost.hid %wait /timer (add ~s10 now.hid)]~
129+ ~& [%we-have-a-problem code]
130+ ~& [%headers headers]
131+ ~& [%body body]
132+ :_ +>.$
133+ [ost.hid %wait /timer (add ~s10 now.hid)]~
134+++ wake-timer
135+ |= {wir/wire $~} ^- (quip move +>)
136+ ?: on
137+ :_ +>.$
138+ [ost.hid %hiss /request ~ %httr %purl (need (epur target))]~
139+ [~ +>.$(in-progress |)]
140+::
141+++ prep ~& target _`. ::
142+--
143+```
144+
145+The app can easily be modified to use this (`/app/examples/ping.hoon`):
146+
147+```
148+::
149+:::: /hoon/ping/examples/app
150+ ::
151+/? 151
152+|%
153+ ++ move {bone term wire *}
154+--
155+!:
156+|_ {bowl state/$~}
157+::
158+++ poke-examples-ping-message
159+ |= {to/@p message/@t}
160+ ~& 'sent'
161+ ^- {(list move) _+>.$}
162+ :- ^- (list move)
163+ :~ `move`[ost %poke /sending [to dap] %atom message]
164+ ==
165+ +>.$
166+::
167+++ poke-atom
168+ |= arg/@
169+ ~& 'received'
170+ ^- {(list move) _+>.$}
171+ ::
172+ ~& [%receiving (@t arg)]
173+ [~ +>.$]
174+::
175+++ coup |=(* `+>)
176+--
177+
178+
179+```
180+
181+Now we can run this with:
182+
183+```
184+~fintud-macrep:dojo> |start %examples-ping
185+>=
186+~fintud-macrep:dojo> :examples-ping &examples-ping-message [~sampel-sipnym 'heyya']
187+>=
188+```
189+
190+And on `~sampel-sipnym`, assuming it's running `:examples-ping` as well,
191+we see `[%receiving 'heyya']`.
192+
193+This is an annoying way to invoke the app, though. The `[]` are
194+mandatory, and optional arguments are hard. Let's make a
195+generator, `+examples-send` to make everything nicer. Since it's specific
196+to `:examples-ping`, let's put it in `/gen/examples/ping/send.hoon`:
197+
198+```
199+:- %say
200+|= {^ {{to/@p message/?($~ {text/@t $~})} $~}
201+[%examples-ping-message to ?~(message 'howdy' text.message)]
202+```
203+
204+A couple of new things here. Firstly, `message/?($~ {text/@t $~})`
205+should be read as "the message is either null or a pair of text
206+and null". Generator argument lists are always null-terminated,
207+which makes it convenient to accept lists in tail position (which
208+are particularly annoying without generators). `?(a b)` is the
209+irregular form of `$?(a b)`, which is a union type. Thus, `?(a
210+b)` means the type of anything that's in either `a` or `b`.
211+Thus, in our case, `?(~ [text=@t ~])` is either null or a pair of
212+text and null.
213+
214+Secondly, `?~(a b c)` is a rune which means "if the `a` is null,
215+do `b`, else `c`". It is roughly equivalent to `?:(=(~ a) b c)`.
216+
217+<blockquote class="blockquote">
218+`?~(a b c)` is actually equivalent to `?:=(?=(~ a) b c)`,
219+which, although identical at run time, is subtly different at
220+compile time. Specifically, using `?=` rather than `=` means
221+that we're checking whether `a` is in the *type* of `~`, and so
222+the compiler knows that in the `b` case `a` is null, and in the
223+`c` case `a` is not null. Since `=` is purely a runtime value
224+check with no type implications, the compiler doesn't gain any
225+information.
226+
227+At any rate, this is the reason why we can refer to
228+`text.message` in the `c` clause. The compiler knows that
229+`message` is not null, so it must have `text` within it. If
230+you used `?:(=(~ message) 'howdy' text.message)` the compiler
231+would complain that it doesn't know whether `message` has
232+`text` within it.
233+</blockquote>
234+
235+This is run as follows:
236+
237+```
238+~fintud-macrep:dojo> :examples-ping|send ~sampel-sipnym
239+>=
240+~fintud-macrep:dojo> :examples-ping|send ~sampel-sipnym 'how do you do'
241+>=
242+```
243+
244+Which causes `~sampel-sipnym` to print `[%receiving 'howdy']` and
245+`[%receiving 'how do you do']`.
246+
247+**Exercises**:
248+
249+- Create a generator for `:examples-sum` from [State](state) so that
250+ you can run `:examples-sum|add 5` to add numbers to it.
251+
252+- Create a generator for `:examples-click` from [Web Apps](web-apps) so
253+ that you can run `:examplesclick|poke` to poke it.
docs/dev/hoon/leap-in/http.md → docs/arvo/http.mdrenamed+74−50
@@ -1,59 +1,73 @@
11---
2+navhome: /docs
23next: false
3−sort: 8
4+sort: 9
45title: HTTP Requests and Timers
56---
67
8+# Writing an HTTP request
9+
710There's a variety of arvo services we haven't touched on yet.
811Let's figure out how to make HTTP requests and set timers.
912
1013Let's build an uptime-monitoring system. It'll ping a web
1114service periodically and print out an error when the response
12−code isn't 2xx. Here's `ape/up.hoon`:
15+code isn't 2xx. Here's `app/up.hoon`:
1316
1417```
18+:: Up-ness monitor. Accepts atom url, 'on', or 'off'
19+::
20+:::: /hoon/up/examples/app
21+ ::
1522/? 314
1623|%
17−++ move ,[bone card]
24+++ move {bone card}
1825++ card
19− $% [%them wire (unit hiss)]
20− [%wait wire @da]
26+ $% {$hiss wire $~ $httr {$purl p/purl}}
27+ {$wait wire @da}
28+ ==
29+++ action
30+ $% {$on $~} :: enable polling('on')
31+ {$off $~} :: disable polling('off)
32+ {$target p/cord} :: set poll target('http://...')
2133 ==
2234--
23−|_ [hid=bowl on=_| in-progress=_| target=@t]
35+|_ {hid/bowl on/_| in-progress/_| target/@t}
2436++ poke-cord
25− |= url=@t
26− ^- [(list move) _+>.$]
27− ?: =('off' url)
28− [~ +>.$(on |)]
29− ?: =('on' url)
30− :_ +>.$(on &, in-progress &)
31− ?: |(on in-progress)
32− ~
33− [ost.hid %them /request ~ (need (epur target)) %get ~ ~]~
34− [~ +>.$(target url)]
35−++ thou-request
36− |= [wir=wire code=@ud headers=mess body=(unit octs)]
37− ^- [(list move) _+>.$]
37+ |= url-or-command/@t ^- (quip move +>)
38+ =+ ^- act/action
39+ ?: ?=($on url-or-command) [%on ~]
40+ ?: ?=($off url-or-command) [%off ~]
41+ [%target url-or-command]
42+ ?- -.act
43+ $target [~ +>.$(target p.act)]
44+ $off [~ +>.$(on |)]
45+ $on
46+ :- ?: |(on in-progress) ~
47+ [ost.hid %hiss /request ~ %httr %purl (need (epur target))]~
48+ +>.$(on &, in-progress &)
49+ ==
50+++ sigh-httr
51+ |= {wir/wire code/@ud headers/mess body/(unit octs)}
52+ ~& 'arrive here'
53+ ^- {(list move) _+>.$}
3854 ?: &((gte code 200) (lth code 300))
3955 ~& [%all-is-well code]
4056 :_ +>.$
41− ?: on
42− [ost.hid %wait /timer (add ~s10 now.hid)]~
43− ~
57+ [ost.hid %wait /timer (add ~s10 now.hid)]~
4458 ~& [%we-have-a-problem code]
4559 ~& [%headers headers]
4660 ~& [%body body]
4761 :_ +>.$
48− ?: on
49− [ost.hid %wait /timer (add ~s10 now.hid)]~
50− ~
62+ [ost.hid %wait /timer (add ~s10 now.hid)]~
5163++ wake-timer
52− |= [wir=wire ~]
64+ |= {wir/wire $~} ^- (quip move +>)
5365 ?: on
5466 :_ +>.$
55− [ost.hid %them /request ~ (need (epur target)) %get ~ ~]~
67+ [ost.hid %hiss /request ~ %httr %purl (need (epur target))]~
5668 [~ +>.$(in-progress |)]
69+::
70+++ prep ~& target _`. ::
5771--
5872```
5973
@@ -63,10 +77,12 @@ line, though.
6377Firstly, there's two kinds of cards we're sending to arvo. A
6478`%them` card makes an HTTP requrest out of a unit `hiss`.
6579
66−> Recall that `++unit` means "maybe". Formally, "`(unit a)` is
67−> either null or a pair of null and a value in `a`". Also recall
68−> that to pull a value out of a unit `(u.unit)`, you must first
69−> verify that the unit is not null (for example with `?~`).
80+<blockquote class="blockquote">
81+Recall that `++unit` means "maybe". Formally, "`(unit a)` is
82+either null or a pair of null and a value in `a`". Also recall
83+that to pull a value out of a unit `(u.unit)`, you must first
84+verify that the unit is not null (for example with `?~`).
85+</blockquote>
7086
7187A `hiss` (all of the following terms are defined in `zuse`) is a
7288pair of a `purl` and a `moth`. A `purl` is a parsed url
@@ -80,9 +96,11 @@ of HTTP headers. The `(unit octs)` is a possible octet stream
8096representing the body. If it's null, then no body is sent (as in
8197this case).
8298
83−> An octect stream is a pair of the length in bytes of the data
84−> plus the data itself. You can use `++taco` takes text and
85−> turns it into an octet strem.
99+<blockquote class="blockquote">
100+An octect stream is a pair of the length in bytes of the data
101+plus the data itself. You can use `++taco` takes text and
102+turns it into an octet strem.
103+</blockquote>
86104
87105When you send this request, you can expect a `%thou` with the
88106response, which we handle later on in `++thou-request`.
@@ -90,14 +108,16 @@ response, which we handle later on in `++thou-request`.
90108For `%wait`, you just pass a [`@da`]() (absolute date), and arvo will
91109produce a `%wake` when the time comes.
92110
93−> A timer is guaranteed to not be triggered before the given
94−> time, but it's currently impossible to guarantee the timer will be
95−> triggered at exactly the requested time.
111+<blockquote class="blockquote">
112+A timer is guaranteed to not be triggered before the given
113+time, but it's currently impossible to guarantee the timer will be
114+triggered at exactly the requested time.
115+</blockquote>
96116
97117Let's take a look at our state:
98118
99119```
100−|_ [hid=bowl on=_| in-progress=_| target=@t]
120+|_ {hid/bowl on/_| in-progress=_| target/@t}
101121```
102122
103123We have three pieces of app-specific state. `target` is the url
@@ -113,9 +133,11 @@ of `value`, but make the default value be `value`". Thus, our
113133type is still a boolean, just like `?`, but the default value is
114134`|` (false).
115135
116−> This is the same `_` used in `_+>.$`, which means "the same
117−> type as the value "+>.$". In other words, the same type as our
118−> current context and state.
136+<blockquote class="blockquote">
137+This is the same `_` used in `_+>.$`, which means "the same
138+type as the value "+>.$". In other words, the same type as our
139+current context and state.
140+</blockquote>
119141
120142Let's take a look at `++poke-cord`. When we're poked with a
121143cord, we first check whether it's `'off'`. If so, we set `on` to
@@ -129,12 +151,14 @@ This request follows the pattern in `++hiss` well. `(need (epur
129151target))` is the parsed url, `%get` is the HTTP method, `~`
130152means no extra headers, and another `~` means no body.
131153
132−> Note the `~` at the end of the move. This is a convenient
133−> shortcut for creating a list of a single element. It's part of
134−> a small family of such shortcuts. `~[a b c]` is `[a b c ~]`,
135−> `[a b c]~` is `[[a b c] ~]` and `\`[a b c]` is `[~ a b c]`.
136−> These may be mixed and matched to create various convoluted
137−> structures and emojis.
154+<blockquote class="blockquote">
155+Note the `~` at the end of the move. This is a convenient
156+shortcut for creating a list of a single element. It's part of
157+a small family of such shortcuts. `~[a b c]` is `[a b c ~]`,
158+`[a b c]~` is `[[a b c] ~]` and `\`[a b c]` is `[~ a b c]`.
159+These may be mixed and matched to create various convoluted
160+structures and emojis.
161+</blockquote>
138162
139163If the argument is neither 'off' nor 'on', then we assume it's an
140164actual url, so we save it in `target`.
@@ -161,14 +185,14 @@ Let's try it out:
161185```
162186~fintud-macrep:dojo> |start %up
163187>=
164−~fintud-macrep:dojo> :up &cord 'http://www.google.com'
188+~fintud-macrep:dojo> :examples-up &cord 'http://www.google.com'
165189>=
166190[%all-is-well 200]
167191[%all-is-well 200]
168−~fintud-macrep:dojo> :up &cord 'http://example.com'
192+~fintud-macrep:dojo> :examples-up &cord 'http://example.com'
169193>=
170194[%all-is-well 200]
171−~fintud-macrep:dojo> :up &cord 'http://google.com'
195+~fintud-macrep:dojo> :examples-up &cord 'http://google.com'
172196>=
173197[%we-have-a-problem 301]
174198[ %headers
docs/arvo/internals.mdnew file+148
@@ -0,0 +1,148 @@
1+---
2+navhome: /docs
3+sort: 15
4+---
5+
6+# Arvo internals
7+
8+Arvo is composed of modules called vanes:
9+
10+<list dataPreview="true"></list>
11+
12+<hr></hr>
13+
14+At a high level `%arvo` takes a mess of unix io events and turns them
15+into something clean and structured for the programmer.
16+
17+`%arvo` is designed to avoid the usual state of complex event networks:
18+event spaghetti. We keep track of every event's cause so that we have a
19+clear causal chain for every computation. At the bottom of every chain
20+is a unix io event, such as a network request, terminal input, file
21+sync, or timer event. We push every step in the path the request takes
22+onto the chain until we get to the terminal cause of the computation.
23+Then we use this causal stack to route results back to the caller.
24+
25+`++ducts`
26+---------
27+
28+The `%arvo` causal stack is called a `++duct`. This is represented
29+simply as a list of paths, where each path represents a step in the
30+causal chain. The first element in the path is the first letter of
31+whichever vane handled that step in the computation, or the empty span
32+for unix.
33+
34+Here's a duct that was recently observed in the wild:
35+
36+ ~[
37+ /g/a/~zod/4_shell_terminal/u/time
38+ /g/a/~zod/shell_terminal/u/child/4/main
39+ /g/a/~zod/terminal/u/txt
40+ /d/term-mess
41+ //term/1
42+ ]
43+
44+This is the duct the timer vane receives when "timer" sample app asks
45+the timer vane to set a timer. This is also the duct over which the
46+response is produced at the specified time. Unix sent a terminal
47+keystroke event (enter), and arvo routed it to %dill(our terminal),
48+which passed it on to the %gall app terminal, which sent it to shell,
49+its child, which created a new child (with process id 4), which on
50+startup asked the timer vane to set a timer.
51+
52+The timer vane saves this duct, so that when the specified time arrives
53+and unix sends a wakeup event to the timer vane, it can produce the
54+response on the same duct. This response is routed to the place we
55+popped off the top of the duct, i.e. the time app. This app produces the
56+text "ding", which falls down to the shell, which drops it through to
57+the terminal. Terminal drops this down to dill, which converts it into
58+an effect that unix will recognize as a request to print "ding" to the
59+screen. When dill produces this, the last path in the duct has an
60+initial element of the empty span, so this is routed to unix, which
61+applies the effects.
62+
63+This is a call stack, with a crucial feature: the stack is a first-class
64+citizen. You can respond over a duct zero, one, or many times. You can
65+save ducts for later use. There are definitely parallels to Scheme-style
66+continuations, but simpler and with more structure.
67+
68+Making Moves
69+------------
70+
71+If ducts are a call stack, then how do we make calls and produce
72+results? Arvo processes "moves" which are a combination of message data
73+and metadata. There are two types of moves. A `%pass` move is analogous
74+to a call:
75+
76+ [duct %pass return-path=path vane-name=@tD data=card]
77+
78+Arvo pushes the return path (preceded by the first letter of the vane
79+name) onto the duct and sends the given data, a card, to the vane we
80+specified. Any response will come along the same duct with the path
81+`return-path`.
82+
83+A `%give` move is analogous to a return:
84+
85+ [duct %give data=card]
86+
87+Arvo pops the top path off the duct and sends the given card back to the
88+caller.
89+
90+Vanes
91+-----
92+
93+As shown above, we use arvo proper to route and control the flow of
94+moves. However, arvo proper is rarely directly responsible for
95+processing the event data that directly causes the desired outcome of a
96+move. This event data is contained within a card, which is simply a
97+`(pair term noun)`. Instead, arvo proper passes the card off to one of
98+its vanes, which each present an interface to clients for a particular
99+well-defined, stable, and general-purpose piece of functionality.
100+
101+As of this writing, we have seven vanes, which each provide the
102+following services:
103+
104+- `%ames` name of both our network and the vane that communicates over
105+ it
106+- `%clay` version-controlled, referentially- transparent, and global
107+ filesystem
108+- `%dill` terminal driver. Unix sends keyboard events to `%dill` from
109+ either the console or telnet, and `%dill` produces terminal output.
110+- `%eyre` http server. Unix sends http messages to `%eyre`, and
111+ `%eyre` produces http messages in response
112+- `%ford` handles resources and publishing
113+- `%gall` manages our userspace applications.. `%gall` keeps state and
114+ manages subscribers
115+- `%time` a simple timer
116+
117+Cards
118+-----
119+
120+Cards are the vane-specific portion of a move. Each vane defines a
121+protocol for interacting with other vanes (via arvo) by defining four
122+types of cards: kisses, gifts, notes, and signs.
123+
124+When one vane is `%pass`ed a card in its `++kiss`, arvo activates the
125+`++call` gate with the card as its argument. To produce a result, the
126+vane `%give`s one of the cards defined in its `++gift`. If the vane
127+needs to request something of another vane, it `%pass`es it a `++note`
128+card. When that other vane returns a result, arvo activates the `++take`
129+gate of the initial vane with one of the cards defined in its `++sign`.
130+
131+In other words, there are only four ways of seeing a move: (1) as a
132+request seen by the caller, which is a ++note. (2) that same request as
133+seen by the callee, a `++kiss`. (3) the response to that first request
134+as seen by the callee, a `++gift`. (4) the response to the first request
135+as seen by the caller, a `++sign`.
136+
137+When a `++kiss` card is passed to a vane, arvo calls its `++call` gate,
138+passing it both the card and its duct. This gate must be defined in
139+every vane. It produces two things in the following order: a list of
140+moves and a possibly-modified copy of its context. The moves are used to
141+interact with other vanes, while the new context allows the vane to save
142+its state. The next time arvo activates the vane it will have this
143+context as its subject.
144+
145+This overview has detailed how to pass a card to a particular vane. To
146+see the cards each vane can be `%pass`ed as a `++kiss` or return as a
147+`++gift` (as well as the semantics tied to them), each vane's public
148+interface is explained in detail in its respective overview.
docs/arvo/internals/ames.mdnew file+28
@@ -0,0 +1,28 @@
1+---
2+navhome: /docs
3+sort: 1
4+---
5+
6+`%ames`
7+=======
8+
9+Our networking protocol.
10+
11+`%ames` is the name of both our network and the vane that communicates
12+over it. When Unix receives a packet over the correct UDP port, it pipes
13+it straight into `%ames` for handling. Also, all packets sent over the
14+`%ames` network are sent by the `%ames` vane. Apps and vanes may use
15+`%ames` to directly send messages to other ships. In general, apps use
16+gall and clay to communicate with other ships rather than using `%ames`
17+directly, but this isn't a requirement. Of course, gall and clay use
18+`%ames` behind the scenes to communicate across the network. These are
19+the only two vanes that use `%ames`.
20+
21+`%ames` includes several significant components. Although the actual
22+crypto algorithms are defined in zuse, they're used extensively in
23+`%ames` for encrypting and decrypting packets. Congestion control and
24+routing is handled entirely in `%ames`. Finally, the actual `%ames`
25+protocol itself, including how to route incoming packets to the correct
26+vane or app, is defined in `%ames`.
27+
28+<list></list>
docs/arvo/internals/ames/commentary.mdnew file+1820
@@ -0,0 +1,1820 @@
1+---
2+navhome: /docs
3+---
4+
5+
6+`%ames` commentary
7+==================
8+
9+`%ames` is our networking protocol.
10+
11+First we give commentary on the code, the algorithms involved, and the
12+protocol. We trace through the code touched when a packet is sent,
13+received, acknowledged, and that acknowledgment applied. This is fairly
14+comprehensive, and contains many implementation details, but if you
15+understand this, then you understand `%ames`.
16+
17+If you've scrolled down this page, you may be intimidated by the amount
18+of Hoon code, especially if you are new to the language. Don't be afraid
19+of it, you don't have to read any of it if you don't want to -- every
20+interesting action the code takes is explained in plain English. In
21+fact, if you are new to the language, this may be a good learning
22+opportunity. Even if you don't understand every line of Hoon code,
23+you'll hopefully be able to follow most lines. By the time you've worked
24+through this, you'll have seen many common patterns and best practices.
25+Hoon, much more than other languages, is best learned by reading and
26+understanding large quantities of existing code. In this way, it is
27+similar to learning a natural language. All of this code is in
28+`arvo/ames.hoon`.
29+
30+After the commentary, we have reference documentation for all the data
31+structures that are specific to `%ames`. If you see a data structure or
32+a variable used that you don't recognize, search for it in the code, and
33+it's very likely defined in one of these data structures. We recommend
34+that another tab is kept open for easy access to the data structure
35+reference documentation. The code for these is split between
36+`arvo/ames.hoon` and `arvo/zuse.hoon`.
37+
38+The Lifecycle of a Packet (or, How a Packet Becomes Law)
39+--------------------------------------------------------
40+
41+Here, we will trace a packet as it makes its way through ames. There are
42+actually two pathways through ames: the legacy path through `%want`, and
43+the modern way, entered through `%wont`, with full end-to-end
44+acknowledgments. Here we will only trace the modern way, though much of
45+the path is the same for both.
46+
47+When an app (or a vane) wishes to send a packet to another ship, it must
48+send a `%wont` card:
49+
50+ [%wont p=sock q=path r=*] :: e2e send message
51+
52+This card takes three arguments. The `p` is a `sock`, that is, a pair of
53+two ships, the first of which is the sender and the second is the
54+receiver. But wait, you ask, why do I get to decide who is the sender?
55+Can I fake like I'm someone else? The reason is that there are
56+potentially multiple ships on the same pier, and the kernel can send a
57+message from any of them. If you attempt to send a message from a ship
58+not on your pier, then ames will refuse to send it. If you hack around
59+in your own copy of ames to go ahead and send it anyway, then the other
60+ship will reject it because your key is bad. Only send messages from
61+yourself.
62+
63+The `q` is a path, representing the place on the other side that you
64+want to receive your message. It is approximately equivalent to a port
65+number. Messages on the same path are guaranteed to arrive in the same
66+order as they were sent. No such guarantees are made across paths.
67+
68+The `r` is the actual data that you are sending. As the type implies,
69+this can be an arbitrary noun, and it will be transferred to the
70+receiver exactly as-is, in a well-typed way. Of course, this is data
71+that is sent over the wire, so be careful not to send anything too
72+massive unless you're willing to wait.
73+
74+But enough about the interface. Grepping in ames.hoon for `%wont`, we
75+find that it appears in exactly two places: at its definition in
76+`++kiss`, and in `++knob`, where it is handled. We see that we go
77+directly into `++wise:am`.
78+
79+ ++ wise :: wise:am
80+ |= [soq=sock hen=duct cha=path val=* ete=?] :: send a statement
81+ ^- [p=(list boon) q=fort]
82+ zork:zank:(wool:(ho:(um p.soq) q.soq) hen cha val ete)
83+
84+The inputs to this gate are exactly the sort of thing you'd expect. In
85+particular, everything in the `%wont` gate is here plus the calling duct
86+so that we know where to send the acknowledgment and `ete` to determine
87+if we're going to do the modern end-to-end acknowledgments.
88+
89+The actual line of code looks intimidating, but it's really not all that
90+bad. Working from the inside out, the call to `++um` sets up our
91+domestic server, and the call to `++ho` sets up our knowledge about the
92+neighbor we're sending to. From the outside, `++zork` and `++zank` just
93+apply the changes made to our `++um` and `++am` cores, respectively. If
94+you're familiar with the common idiom of `++abet`, that's all this is.
95+The code predates the widespread usage of that name.
96+
97+The interesting part, then, is in `++wool:ho:um:am`. Let's look at the
98+code.
99+
100+ ++ wool :: wool:ho:um:am
101+ |= [hen=duct cha=path val=* ete=?] :: send a statement
102+ ^+ +>
103+ =+ ^= rol ^- rill
104+ =+ rol=(~(get by ryl.bah) cha)
105+ ?~(rol *rill u.rol)
106+ =+ sex=sed.rol
107+ :: ~& [%tx [our her] cha sex]
108+ =. ryl.bah
109+ %+ ~(put by ryl.bah) cha
110+ rol(sed +(sed.rol), san (~(put by san.rol) sex hen))
111+ =+ cov=[p=p:sen:gus q=clon:diz]
112+ %+ wind [cha sex]
113+ ?: ete
114+ [%bund q.cov cha sex val]
115+ [%bond q.cov cha sex val]
116+
117+This is slightly more complicated, but it's still not all that bad. Our
118+inputs, at least, are fairly obvious.
119+
120+If you glance at the code for a second, you'll see that
121+`++wind:ho:um:am` seems to be able to send a message, or `++meal`, given
122+a `++soup`. This gate, then, just sets up the things we need to for
123+`++wind` to do its job.
124+
125+We first get `rol`, which is a `++rill`, that is, a particular outbound
126+stream. This stream is specific to the path on which we're sending. If
127+the path hasn't been used before, then we create it. We let `sex` be the
128+number of messages we've already sent on this path.
129+
130+Then, we update the outbound stream by incrementing the number of
131+messages sent and placing an entry in `san.rol` that associates the
132+message number with the `duct` that sent the message. This allows us to
133+give the acknowledgment to the one who sent the message.
134+
135+We let `cov` be the current life of our crypto and our neighbor's
136+crypto. At the moment, we only need our neighbor's life, which we put
137+into the meal.
138+
139+Finally, we call `++wind:ho:um:am` with the `++soup` of the path and
140+message number and the `++meal` of the payload itself. For end-to-end
141+acknowledged messages, we use `%bund`.
142+
143+ [%bund p=life q=path r=@ud s=*] :: e2e message
144+
145+Looking at how we create the `%bund`, we can easily see what each field
146+is for.
147+
148+Following the trail a little further, we go to `++wind:ho:um:am`.
149+
150+ ++ wind :: wind:ho:um:am
151+ |= [gom=soup ham=meal]
152+ :: ~& [%wind her gom]
153+ ^+ +>
154+ =^ wyv diz (zuul:diz now ham)
155+ =^ feh puz (whap:puz now gom wyv)
156+ (busk xong:diz feh)
157+
158+`++wind` does three things: it (1) encodes the message into a list of
159+possibly-encrypted packets, (2) puts the message into the packet pump,
160+and (3) sends any packets that are ready to be sent. Yes, our nice
161+little linear run of each gate calling exactly one other interesting
162+gate is over. We'll go in order here.
163+
164+`++zuul:lax:as:go` is the what converts a `++meal` into a list of
165+actual, 1KB packets.
166+
167+ ++ zuul :: zuul:lax:as:go
168+ |= [now=@da ham=meal] :: encode message
169+ ^- [p=(list rock) q=_+>]
170+ =< weft
171+ ++ wasp :: null security
172+ ++ weft :: fragment message
173+ ++ wisp :: generate message
174+
175+For organizational purposes, `++zuul` constructs an internal core with
176+three arms. `++wasp` encodes the meal into an atom with no encryption.
177+`++wisp` encodes a meal with possible encryption (else it simply calls
178+`++wasp`). `++weft` takes the result of `++wisp` and splits it into
179+actual packets.
180+
181+ ++ wasp :: null security
182+ ^-([p=skin q=@] [%none (jam ham)])
183+
184+This simply jams the meal, wrapping it with the `skin` of `%none`,
185+meaning no encryption.
186+
187+Since `++wisp` is a little long, we'll go through it line-by-line.
188+
189+ ++ wisp :: generate message
190+ ^- [[p=skin q=@] q=_..wisp]
191+
192+`++wisp` produces a pair of a `skin` and an atom, which is the meal
193+encoded as a single atom and possibly encrypted.
194+
195+ ?: =(%carp -.ham)
196+ [wasp ..wisp]
197+
198+If the meal that we're encoding is a `%carp`, then we don't encrypt it.
199+A `%carp` meal is a partial meal, used when a message is more than 1KB.
200+Since the entire message is already encrypted, we don't need to encrypt
201+each packet individually again.
202+
203+ ?: !=(~ yed.caq.dur)
204+ ?> ?=(^ yed.caq.dur)
205+ :_ ..wisp
206+ :- %fast
207+ %^ cat 7
208+ p.u.yed.caq.dur
209+ (en:r:cluy q.u.yed.caq.dur (jam ham))
210+
211+If we have a symmetric key set up with this neighbor, then we simply use
212+it. The skin `%fast` is used to indicate a symmetric key.
213+
214+ ?: &(=(~ lew.wod.dur) |(=(%back -.ham) =(%buck -.ham)))
215+ [wasp ..wisp]
216+
217+If we do not yet have our neighbor's will, then there is no way that we
218+can seal the message so that only they may read it. If what we're
219+sending is an acknowledgment, then we go ahead and just send it in the
220+clear.
221+
222+ =^ tuy +>.$
223+ ?:(=(~ lew.wod.dur) [*code +>.$] (griz now))
224+
225+If we don't have our neighbor's will, then we "encrypt" with a key of 0.
226+If we do have their will, then we generate a new symmetric key that we
227+will propose.
228+
229+ :_ ..wisp
230+ =+ yig=sen
231+ =+ bil=law.saf :: XX send whole will
232+ =+ hom=(jam ham)
233+
234+`yig` will be the life and engine for our current crypto. `bil` is our
235+will. `hom` is the meal encoded as a single atom.
236+
237+ ?: =(~ lew.wod.dur)
238+ :- %open
239+ %^ jam
240+ [~ `life`p.yig]
241+ bil
242+ (sign:as:q.yig tuy hom)
243+
244+If we do not have our neighbor's will, then we send our current life
245+along with our will and the message. The message itself is "signed" with
246+a key of 0.
247+
248+ :- %full
249+ =+ cay=cluy
250+ %^ jam
251+ [`life`p.cay `life`p.yig]
252+ bil
253+ (seal:as:q.yig pub:ex:r.cay tuy hom)
254+ -- :: --zuul:lax:as:go
255+
256+If we do have our neighbor's will, then we send our perception of their
257+current life, our current life, our will, and the message. The message
258+is sealed with their public key so that only they can read our message.
259+
260+Once we have the message encoded as an atom, `++weft` goes to work.
261+
262+ ++ weft :: fragment message
263+ ^- [p=(list rock) q=_+>.$]
264+ =^ gim ..weft wisp
265+ :_ +>.$
266+ ^- (list rock)
267+
268+We're going to produce a list of the packets to send. First, we use the
269+aforementioned `++wisp` to get the message as an atom.
270+
271+ =+ wit=(met 13 q.gim)
272+ ?< =(0 wit)
273+
274+`wit` is the number of 1KB (2\^13 bit) blocks in the message. We assert
275+that there is at least one block.
276+
277+ ?: =(1 wit)
278+ =+ yup=(spit [our her] p.gim q.gim)
279+ [yup ~]
280+
281+If there is exactly one block, then we just call `++spit` to turn the
282+message into a packet. We'll explain what `++spit` does momentarily.
283+
284+ =+ ruv=(rip 13 q.gim)
285+ =+ gom=(shaf %thug q.gim)
286+ =+ inx=0
287+
288+If there is more than one block, then we rip it into blocks in `ruv`.
289+`gom` is a hash of the message, used as an id. `inx` is the number of
290+packets we've already made.
291+
292+ |- ^- (list rock)
293+ ?~ ruv ~
294+ =+ ^= vie
295+ %+ spit
296+ [our her]
297+ wasp(ham [%carp (ksin p.gim) inx wit gom i.ruv])
298+ :- vie
299+ $(ruv t.ruv, inx +(inx))
300+
301+Here we package each block into a packet with `++spit` and produce the
302+list of packets.
303+
304+ ++ spit :: cake to packet
305+ |= kec=cake ^- @
306+ =+ wim=(met 3 p.p.kec)
307+ =+ dum=(met 3 q.p.kec)
308+ =+ yax=?:((lte wim 2) 0 ?:((lte wim 4) 1 ?:((lte wim 8) 2 3)))
309+ =+ qax=?:((lte dum 2) 0 ?:((lte dum 4) 1 ?:((lte dum 8) 2 3)))
310+ =+ wix=(bex +(yax))
311+ =+ vix=(bex +(qax))
312+ =+ bod=:(mix p.p.kec (lsh 3 wix q.p.kec) (lsh 3 (add wix vix) r.kec))
313+ =+ tay=(ksin q.kec)
314+ %+ mix
315+ %+ can 0
316+ :~ [3 1]
317+ [20 (mug bod)]
318+ [2 yax]
319+ [2 qax]
320+ [5 tay]
321+ ==
322+ (lsh 5 1 bod)
323+
324+This is how we turn a message into a real packet. This has the
325+definition of the packet format.
326+
327+`wim` is the length of the sending ship, and `dum` is the length of the
328+receiving ship. There are only five possibilities for each of those,
329+corresponding to carriers, cruisers, destroyers, yachts, and submarines.
330+These are encoded in `yax` and `qax` as 0, 0, 1, 2, and 3, respectively.
331+Thus, `wix` and `vix` are the number of bytes that must be reserved for
332+the ship names in a packet.
333+
334+Next, we construct `bod` by simply concatenating the sending ship, the
335+receiving ship, and the body of the message. Then, we get the encryption
336+mechanism from `++skin`, which may be a 0, 1, 2, or 3, and put it in
337+`tay`.
338+
339+Next, we concatenate together, bit by bit, some final metadata. We use
340+three bits for our protocol number, which is incremented modulo eight
341+when there is a continuity breach or the protocol changes. We use the
342+final twenty bits of a hash of the body (which, we suppose, makes it a
343+twenty bit hash) for error-checking. We use two bits to tell how much
344+room is used in the body for the sending ship, and another two bits for
345+the receiving ship. Finally, we use five bits to store the encryption
346+type. Note that since there are only two bits worth of encryption types,
347+there are three unused bits here. This adds up to 32 bits of header
348+data. Finally, we concatenate this onto the front of the packet. Thus,
349+we can summarize the packet header format as follows.
350+
351+ 0 1 2 3
352+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
353+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
354+ |Proto| Hash of Body |yax|qax| Crypto |
355+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
356+
357+After this, there are `yax` bits of the sender name, `qax` bits of the
358+receiver name, and up to 8192 bits of data. Thus, the maximum size of a
359+packet is achieved in a message between two submarines with 8192 bits of
360+data. This will require 32+128+128+8192 = 8480 bits, or 1060 bytes.
361+
362+This concludes our discussion of `++zuul:lax:as:go`. If you recall from
363+`++wind:ho:um:am`, the list of packets from `++zuul` is passed into
364+`++whap:pu` to update the packet pump and get any packets that can be
365+sent immediately.
366+
367+ ++ whap :: whap:pu
368+ |= [now=@da gom=soup wyv=(list rock)] :: send a message
369+ ^- [(list rock) _+>]
370+ =. pyz (~(put by pyz) gom (lent wyv))
371+ =. +>
372+ |- ^+ +>.^$
373+ ?~ wyv +>.^$
374+ %= $
375+ wyv t.wyv
376+ nus +(nus)
377+ diq (~(put by diq) (shaf %flap i.wyv) nus)
378+ puq (~(put to puq) [nus `soul`[gom 0 | ~2000.1.1 i.wyv]])
379+ ==
380+ (harv now)
381+
382+First, we put into `pyz` the id for this message and the number of its
383+packets that have not yet been acknowledged, which is of course the
384+total number of packets since we haven't even sent the packets.
385+
386+For every packet, we change three things in the state (`++shed`) of our
387+packet pump: (1) we increment `nus`, the number of packets sent; (2) we
388+put the packet number into `diq` keyed by a hash of the packet; and (3)
389+we put the packet into the packet queue, with the basic metadata of its
390+id `gom`, 0 transmissions, not live yet, last sent in the year 2000, and
391+the packet itself.
392+
393+Finally, we harvest the packet pump.
394+
395+ ++ harv :: harv:pu
396+ |= now=@da :: harvest queue
397+ ^- [(list rock) _+>]
398+ ?: =(~ puq) [~ +>(rtn ~)]
399+ ?. (gth caw nif) [~ +>]
400+ =+ wid=(sub caw nif)
401+ =| rub=(list rock)
402+ =< abet =< apse
403+ |%
404+
405+`++harv` contains a core for most of its work. The meat is in `++apse`.
406+First, though, it sets itself up. If there aren't any packets in the
407+queue, then we simply do nothing except set `rtn`, our next timeout, to
408+nil because we don't have any packets that may need to be retransmitted.
409+If we have more live (that is, sent and unacknowledged) packets than our
410+window size, then we don't do anything.
411+
412+Otherwise, we let `wid` be the width of our remaining packet window, and
413+we initialize `rub` to nil. `rub` will be the list of packets that are
414+ready to be sent. We then call `++apse` and pass the result to `++abet`.
415+`++apse` decides which packets are ready to be sent.
416+
417+ ++ apse
418+ ^+ .
419+ ?~ puq .
420+ ?: =(0 wid) .
421+ => rigt =< left
422+ ?> ?=(^ puq)
423+ ?: =(0 wid) .
424+ ?. =(| liv.q.n.puq) .
425+ :: ~& [%harv nux.q.n.puq p.n.puq]
426+ %_ .
427+ wid (dec wid)
428+ rub [pac.q.n.puq rub]
429+ nif +(nif)
430+ liv.q.n.puq &
431+ nux.q.n.puq +(nux.q.n.puq)
432+ lys.q.n.puq now
433+ ==
434+
435+If there are no remaining packets to send, or if we've filled the packet
436+window, do nothing. We call `++rigt` and `++left` to process the left
437+and right branches of the packet queue.
438+
439+Now we assert that the queue is not empty, and we again check that we
440+haven't filled the packet window. We will operate on the head of the
441+queue. If the packet is live, then do nothing. Otherwise, we go ahead
442+and send it.
443+
444+To send, we (1) decrement `wid`, our packet window width; (2) cons the
445+packet onto the `rub`, which will be returned as the list of packets to
446+send; (3) increment `nif`, the number of live packets; (4) set the
447+packet to be live; (5) increment the number of transmissions of the
448+packet; and (6) set the last sent time of the packet to now.
449+
450+ ++ left
451+ ?> ?=(^ puq)
452+ ^+(. =+(lef=apse(puq l.puq) lef(puq [n.puq puq.lef r.puq])))
453+ ++ rigt
454+ ?> ?=(^ puq)
455+ ^+(. =+(rig=apse(puq r.puq) rig(puq [n.puq l.puq puq.rig])))
456+
457+These do exactly what you would expect: they traverse the packet queue
458+so that `++apse` gets called recursively through it.
459+
460+Finally, `++abet` gets called, which resolves the changes.
461+
462+ ++ abet
463+ ?~ rub [~ +>.$]
464+ [(flop rub) +>.$(rtn [~ (add rto now)])]
465+
466+This returns the packets that we wish to send, and it updates the
467+timeout so that we know when to try resending unacknowledged packets.
468+
469+This concludes our discussion of `++whap:pu`. To finish
470+`++wind:ho:um:am`, we just need to delve into `++busk:ho:um:am`. But
471+wait, in the call to `++busk`, the first argument is `xong:diz`. What is
472+this? This, my dear reader, is one more detour, this time into
473+`++xong:lax:as:go`.
474+
475+ ++ xong :: xong:lax:as:go
476+ ^- (list ship) :: route unto
477+ =+ [fro=xen too=xeno]
478+ =+ ^= oot ^- (list ship)
479+ =| oot=(list ship)
480+ |- ^+ oot
481+ ?~ too ~
482+ ?: (lien fro |=(a=ship =(a i.too))) ~
483+ [i.too $(too t.too)]
484+ :: ~& [%xong-to [our her] (weld oot ?>(?=(^ fro) t.fro))]
485+ (weld oot ?>(?=(^ fro) t.fro))
486+
487+This gets the list of intermediate ships needed to get a packet from us
488+to our neighbor. First, we get `fro` and `too`, the "canons" of ourself
489+and our neighbor, respectively.
490+
491+What is this "canon", you ask? A canon is simply a ship plus its
492+"ancestors", as defined by `++sein`. For example, the canon of
493+`~hoclur-bicrel` is:
494+
495+ ~hoclur-bicrel/try=> (saxo ~hoclur-bicrel)
496+ ~[~hoclur-bicrel ~tasruc ~tug]
497+
498+If we follow the algorithm in `++xong`, we see that we are simply
499+creating a list of ships that form a path from our neighbor to ourself.
500+Essentially, we look through the canon of our neighbor until we find
501+something in our own cannon -- a common ancestor. Or, if we are from
502+different carriers, then there is no common ancestor. We then weld this
503+onto the tail of our own canon. In the end, this is simply a list of
504+possible ships to try to route via to get to our neighbor, ordered by
505+preferability (that is, closeness to our neighbor). We will end up
506+trying, in order, to find a lane to these.
507+
508+Now, we can finally get to `++busk:ho:um:am`.
509+
510+ ++ busk :: busk:ho:um:am
511+ |= [waz=(list ship) pax=(list rock)] :: send packets
512+ %_ +>
513+ bin
514+ |- ^+ bin
515+ ?~ pax bin
516+ $(pax t.pax, bin (weld (flop (wist:diz now waz ~ i.pax)) bin))
517+ ==
518+
519+Thankfully, `++busk` is fairly simple. We go through the list of packets
520+and convert them to `++boon`s with `++wist:lax:as:go`. These boons are
521+placed into `bin`, and they end up getting processed by `++clop` (this
522+happens in `++knob`).
523+
524+ ++ wist :: wist:lax:as:go
525+ |= $: now=@da :: route via
526+ waz=(list ,@p)
527+ ryn=(unit lane)
528+ pac=rock
529+ ==
530+ ^- (list boon)
531+ ?: =(our her) [[%ouzo *lane pac] ~]
532+ ?~ waz ~
533+ =+ dyr=?:(=(her i.waz) dur (gur i.waz))
534+ ?. ?& !=(our i.waz)
535+ ?=(^ lun.wod.dyr)
536+ ==
537+ $(waz t.waz)
538+ :_ ?: ?=(%ix -.u.lun.wod.dyr)
539+ $(waz t.waz)
540+ ~
541+ :+ %ouzo u.lun.wod.dyr
542+ ?: &(=(i.waz her) =(~ ryn)) pac
543+ =+ mal=(jam `meal`[%fore her ryn pac])
544+ %- spit
545+ ^- cake
546+ :* [our i.waz]
547+ ?~ yed.caq.dyr [%none mal]
548+ :- %fast
549+ %^ cat 7
550+ p.u.yed.caq.dyr
551+ (en:crua q.u.yed.caq.dyr mal)
552+ ==
553+
554+This takes a sample of the current time, the list of ships that we just
555+generated, a lane if we already know it, and the packet itself.
556+
557+First, if we are sending a message to ourself, then we simply create a
558+`%ouzo` boon with a bunted lane. Otherwise, if there are no routing
559+candidates, there is nothing we can do, so we return nil.
560+
561+Next, we get the `dore` of the first routing candidate. If we're looking
562+at the neighbor to whom we're trying to send the message, then we simply
563+use the `dore` that we already have. Otherwise, we get a default `dore`.
564+
565+If we're the first routing candidate, or if we have don't have a lane to
566+this candidate, then we skip this candidate and move on to the next one.
567+
568+If we have only a provisional ip address, then we try to send on it, but
569+we also try to send on later routing candidates as well. Otherwise, we
570+only send on this one candidate.
571+
572+Finally, we create the actual `%ouzo` boon. The lane is the one from our
573+`dore`. If we're sending it directly to our intended recipient, and we
574+haven't been told to use a specific lane, then we just send the packet
575+directly. Otherwise, we wrap it in a little `%fore` meal, telling the
576+intermediary to whom we wish it to be sent. If we have already set up a
577+symmetric key with the intermediary, then we encrypt it with that.
578+Otherwise, we send it in the clear.
579+
580+Now, if you recall, we have traced all the way through from the
581+beginning when, in `++knob`, the `%wont` card was handled by a call to
582+`++wise`. There is only one more step before the packet is finally sent.
583+Looking in `++knob`, we see that the resultant list of boons is passed
584+into `++clop`, which will execute the correct actions and return a list
585+of moves. In `++clop`, we see the handling of each specific boon. The
586+one we are interested in is `%ouzo`, since that is the only one we have
587+sent thus far.
588+
589+ %ouzo
590+ :: ~& [%send now p.bon `@p`(mug (shaf %flap q.bon))]
591+ :_ fox
592+ [[gad.fox [%give %send p.bon q.bon]] ~]
593+
594+Very simply, we give a `%send` gift along the special duct that goes
595+straight into the bowels of unix. This is the last stop before we drop
596+into vere, and later libuv. And then... the world.
597+
598+The packet, after its creation, embarks on a journey across physical
599+time and space into the great unknown. Hurtling through fiber-optic
600+cables at hundreds of thousands of kilometers per second, it finally
601+arrives at our neighbor's network adapter. The adapter tells unix, unix
602+tells libuv, libuv tells vere, and vere sends a `%hear` kiss to ames.
603+And now we reenter the kernel.
604+
605+The `%hear` kiss goes straight to `++knob`, just as did the `%wont` kiss
606+earlier.
607+
608+ %hear
609+ (~(gnaw am [now fox]) %good p.kyz q.kyz)
610+
611+Here, though, we call `++gnaw:am` to process the packet. The arguments
612+to `++gnaw` are the same as those to the `%hear` kiss: the lane on which
613+the packet was received and the packet itself. The other argument is
614+just `%good`, which is a `++cape` saying that we expect the packet to
615+succeed. If a formal error occurs, then since we have a transactional
616+event system, the `%hear` event will never be considered to have
617+actually happened, and unix will send a `%hole` kiss so that we may send
618+a negative acknowledgment.
619+
620+ ++ gnaw :: gnaw:am
621+ |= [kay=cape ryn=lane pac=rock] :: process packet
622+ ^- [p=(list boon) q=fort]
623+ ?. =(2 (end 0 3 pac)) [~ fox]
624+ =+ kec=(bite pac)
625+ ?: (goop p.p.kec) [~ fox]
626+ ?. (~(has by urb.ton.fox) q.p.kec)
627+ [~ fox]
628+ =< zork
629+ =< zank
630+ %- ~(chew la:(ho:(um q.p.kec) p.p.kec) kay ryn %none (shaf %flap pac))
631+ [q.kec r.kec]
632+
633+First, we check the protocol number. If it is not correct, then we
634+simply ignore the packet entirely. Otherwise, we parse the packet with
635+`++bite`, which converts a packet atom into a `cake`, that is, a triple
636+of the `sock` (pair of sender and receiver), the `skin` (encryption
637+type), and the data.
638+
639+ ++ bite :: packet to cake
640+ |= pac=rock ^- cake
641+ =+ [mag=(end 5 1 pac) bod=(rsh 5 1 pac)]
642+ =+ :* vez=(end 0 3 mag) :: protocol version
643+ chk=(cut 0 [3 20] mag) :: checksum
644+ wix=(bex +((cut 0 [23 2] mag))) :: width of receiver
645+ vix=(bex +((cut 0 [25 2] mag))) :: width of sender
646+ tay=(cut 0 [27 5] mag) :: message type
647+ ==
648+ ?> =(2 vez)
649+ ?> =(chk (end 0 20 (mug bod)))
650+ :+ [(end 3 wix bod) (cut 3 [wix vix] bod)]
651+ (kins tay)
652+ (rsh 3 (add wix vix) bod)
653+
654+This is exactly the inverse of `++spit`. Note that here we check both
655+the protocol number and the hash, crashing on error. Remember that a
656+crash will result in a negative acknowledgment being sent.
657+
658+Continuing in `++gnaw`, we see that if the intended recipient is not on
659+our pier, then we drop the packet.
660+
661+If we've gotten this far, then we wish to process the packet. Recall
662+that `++ho` and `++um` set up the domestic server and foreign client
663+cores, respectively, and that `++zork` and `++zank` resolve any changes
664+to these cores.
665+
666+The new stuff here, then, is the `++la` core and the `++chew` arm. The
667+`++la` sets up a core for this particular packet, containing the current
668+success/failure `cape`, the lane it was sent on, the encryption type,
669+and a hash of the packet, used as an id.
670+
671+`++chew` is called with the encryption type and the message itself. It
672+contains a little helper core inside of it, which starts immediately
673+with `++apse`.
674+
675+ ++ apse
676+ ^+ +>.$
677+ =+ oub=bust:puz
678+ =+ neg==(~ yed.caq.dur.diz)
679+ =. +>.$ east
680+ =+ eng==(~ yed.caq.dur.diz)
681+ =+ bou=bust:puz
682+ =. bin
683+ ?. &(oub !bou) bin
684+ :_(bin [%wine [our her] " is ok"])
685+ =. bin
686+ ?. &(neg !eng) bin
687+ :_(bin [%wine [our her] " is your neighbor"])
688+ +>.$
689+
690+First, we let `oub` be true if our neighbor hasn't been responding to us
691+for more than sixteen seconds. Let `neg` be true if we haven't yet
692+proposed a symmetric key, meaning that we haven't yet corresponded with
693+this ship, so they are not our neighbor. Next, we run `++east`, which
694+we'll go into in just a minute.
695+
696+We now do the same two checks and store the results in `eng` and `bou`.
697+If our neighbor has, like the prodigal son, returned after an extended
698+absense, then we send a `%wine` boon as the proverbial fatted calf,
699+which is simply printed out to the console. Likewise, if we are meeting
700+one with whom we have never had the pleasure of acquainting ourselves,
701+we send a message to the console to that effect.
702+
703+We skipped over `++east`, which contains the meat of the processing. It
704+first decrypts the message, then calls `++chow:la:ho:um:am` with the
705+resultant meal. We'll go through each of the four cases in turn, but
706+first since each one calls `++bilk:pu`, we'll take a brief detour.
707+
708+ ++ bilk :: bilk:pu
709+ |= now=@da :: inbound packet
710+ ^+ +>
711+ =+ trt=(mul 2 rtt)
712+ %= +>.$
713+ rue [~ now]
714+ rto trt
715+ rtn ?~(puq ~ [~ (add now trt)])
716+ ==
717+
718+This updates the timing information in our packet pump. `rue`, the last
719+time we have heard from this neighbor, is set to now. `rto`, the
720+retransmit timeout is set to twice the current ping time, and if there
721+is anything in the packet queue, then we reset the next timeout, since
722+we've just heard a message.
723+
724+Back to `++east`.
725+
726+ %none
727+ =. puz (bilk:puz now)
728+ (chow ((hard meal) (cue msg)))
729+
730+The simplest case is when the encryption type is `%none`. We first call
731+`++bilk` to update the packet pump, then we cue (unjam) the message into
732+a meal. We hard cast it into a meal -- if the cast fails, then we do
733+want to crash since someone is sending us malformed data. Finally, we
734+send the result to `++chow` for interpretation and handling.
735+
736+ %fast
737+ =+ [mag=`hand`(end 7 1 msg) bod=(rsh 7 1 msg)]
738+ =+ dey=(kuch:diz mag)
739+ ?~ dey
740+ ~& [%bad-key her mag]
741+ +>.$ :: ignore unknown key
742+ =. puz (bilk:puz now)
743+ =^ key diz u.dey
744+ (chow(aut sin) ((hard meal) (cue (dy:q:sen:gus key bod))))
745+
746+For symmetric encryption, we first get the `hand`, which is the hash of
747+the symmetric key. We pass it to `++kuch:lax:as:go`, which returns the
748+key if we either have used it before or we have proposed it. If we have
749+proposed it, then we change its status from proposed to real. If
750+`++kuch` fails, then we drop the packet and print out a `%bad-key`
751+message.
752+
753+Otherwise, we call `++bilk` as before to update the packet pump and pass
754+into `++chow` the decrypted data.
755+
756+ %full
757+ =+ mex=((hard ,[p=[p=life q=life] q=will r=@]) (cue msg))
758+ =. diz (deng:diz q.mex)
759+ =+ wug=cluy:diz
760+ ?> =(q.p.mex p.wug)
761+ =+ gey=(sev:gus p.p.mex)
762+ =+ mes=(need (tear:as:q.gey pub:ex:r.wug r.mex))
763+ =. diz (wasc:diz p.mes)
764+ =. puz (bilk:puz now)
765+ (west(msg q.mes))
766+
767+For sealed asymmetric encryption, we first take off the the layer of
768+data that gives us the life and will of our neighbor, and we apply try
769+to extend their former will with the new data. `++deng` will fail if
770+this is impossible.
771+
772+Next, we get our most current understanding of our neighbor's crypto,
773+and we verify that it's the same life as what they're sending. Then, we
774+get our own crypto from `++sev` and decrypt the message with the public
775+key from our neighbor's crypto. We register the proposed symmetric key,
776+update the packet pump, and call `++west`, which simply casts the
777+message to a meal and calls `++chow`, reporting any error.
778+
779+ %open
780+ =+ mex=((hard ,[p=[~ q=life] q=will r=@]) (cue msg))
781+ =. diz (deng:diz q.mex)
782+ =+ wug=cluy:diz
783+ ?> =(q.p.mex p.wug)
784+ =+ mes=(need (sure:as:r.wug *code r.mex))
785+ =. puz (bilk:puz now)
786+ (west(msg mes))
787+
788+Finally, for signed asymmetric encryption, we, as before, take off the
789+layer of data that gives us the life and will of our neighbor. This
790+time, of course, we do not get our own crypto -- only that of our
791+neighbor.
792+
793+The rest you have seen. We call `++deng` to extend the will, we verify
794+that their crypto life is what we think it ought to be, we "decrypt" the
795+data, we update the packet pump, and we call `++west` to call `++chow`.
796+
797+ ++ chow :: chow:la:ho:um:am
798+ |= fud=meal :: interpret meal
799+ ^+ +>
800+ =. diz ?:(=(%none aut) diz (wast:diz ryn))
801+ (dine fud)
802+
803+Here, if the message was encrypted at all, then we call
804+`++wast:lax:as:go`, which simply updates the lane (route) to our
805+neighbor (unless we're given a provisional route). This ensures that we
806+always have the most direct possible path to them.
807+
808+We've been handling this meal for so long, we've almost forgotten what
809+we want to do with it. The telos is of any meal to be dined on. We will
810+choose out the cases here that are important to our current
811+investigation.
812+
813+ %fore
814+ =+ ^= lyn ^- lane
815+ ?~ q.fud ryn
816+ ?. ?=(%if -.u.q.fud) u.q.fud
817+ [%ix +.u.q.fud]
818+ :: u.q.fud
819+ ?: =(our p.fud)
820+ (emit %mead lyn r.fud)
821+ =+ zid=(myx:gus p.fud)
822+ (emir (wist:zid now xong:zid [~ lyn] r.fud))
823+
824+Forwarding is the simplest case, since we've seen all the arms before,
825+except perhaps `++emit` and `++emir`, which simply take a boon or list
826+of boons respectively and queue them up to be handled when the core
827+resolves. If we're told to forward a packet to ourselves, then we emit a
828+`%mead` boon which simply sends another `%hear` kiss to ourselves with
829+the data. Otherwise, we try to find a route to the recipient, as before.
830+
831+ %carp
832+ =+ zol=(~(get by olz.weg) s.fud)
833+ ?^ zol cock(kay u.zol)
834+ =^ neb nys.weg
835+ =+ neb=(~(get by nys.weg) s.fud)
836+ ?^ neb [u.neb nys.weg]
837+ =+ neb=`bait`[(kins p.fud) 0 r.fud ~]
838+ [neb (~(put by nys.weg) s.fud neb)]
839+ ?> (lth q.fud p.r.neb)
840+ ?> =((kins p.fud) p.neb)
841+ ?> =(r.fud p.r.neb)
842+ =+ doy=`(unit ,@)`(~(get by q.r.neb) q.fud)
843+ ?^ doy cock
844+ => ^+ . %= .
845+ q.r.neb (~(put by q.r.neb) q.fud t.fud)
846+ q.neb +(q.neb)
847+ ==
848+ :: ~& [%carp q.fud s.fud q.neb p.r.neb]
849+ ?: =(q.neb p.r.neb)
850+ =: nys.weg (~(del by nys.weg) s.fud)
851+ olz.weg (~(put by olz.weg) s.fud kay)
852+ ==
853+ (golf p.neb r.neb)
854+ =. +>.$ cock
855+ +>.$(nys.weg (~(put by nys.weg) s.fud neb))
856+
857+Here, we have received a partial message, and we're just assembling the
858+individual packets into a message. Most of this code is fairly
859+algorithmic, so we'll just hit the high points. In the beginning, we
860+check if we've already received this message, and if so, we resend the
861+acknowledgment. Remember, "always ack a dupe, never ack an ack".
862+
863+In `nys.weg` we keep track of an incoming set of partial packets,
864+indexed by the `flap` hash that comes with every packet. We check to see
865+if we have already received this partial message, and if so we
866+acknowledge it. Otherwise, we put it in `nys.weg` unless this is the
867+last message, in which case we ack the last partial message, move the
868+complete message into `olz.weg`, and call `++golf`, which assembles the
869+message and calls `++chew`, to start the dance again with the complete
870+message.
871+
872+ %bund
873+ :: ~& [%bund q.fud r.fud]
874+ ?> =(p:sen:gus p.fud)
875+ (deer q.fud r.fud ?-(kay %dead ~, %good [~ s.fud]))
876+
877+What if we're just receiving a regular old, garden variety message? We
878+call `++deer` with the data from the message. If we already know that
879+the message processing will fail (that is, if we got a `%hole` card from
880+unix rather than a `%hear` card), then we don't even send the data at
881+all. Remember, if a packet fails to process, it's as if it never even
882+arrived, except that we send a negative acknowledgment.
883+
884+ ++ deer :: deer:la:ho:um:am
885+ |= [cha=path num=@ud dut=(unit)] :: interpret message
886+ ^+ +>
887+ =+ rum=(fall (~(get by raz.bah) cha) *race)
888+ %= +>.$
889+ +>
890+ ?. (gte num did.rum) :: always ack a dup
891+ (cook (~(get by bum.rum) num) cha ~ ryn dam)
892+ ?: dod.rum
893+ (coat cha rum(mis (~(put by mis.rum) num [kay ryn dam dut])))
894+ %= +>.+>.$
895+ raz.bah
896+ %+ ~(put by raz.bah) cha
897+ rum(mis (~(put by mis.rum) num [kay ryn dam dut]))
898+ ==
899+ ==
900+
901+First, we get the race for this particular triple of sender, receiver,
902+and path, creating it if it doesn't exist. If we've already acked the
903+message, then we resend the ack. Note that `did.rum` is the number of
904+packets we acknowledged, positively or negatively while `bum.rum` is a
905+map of message numbers to negative acknowledgments. Thus, if a message
906+number is less than `did.rum`, then if it's in `bum.rum` then it was
907+negatively acknowledged, otherwise it's postively acknowledged. Thus, we
908+are constant in space with the number of successful messages and linear
909+in the number of failed messages. We'll document `++cook` later on, but
910+suffice it to say that it sends an acknowledgment. It is to end-to-end
911+acknowledgments what `++cock` is to packet-level acknowledgments.
912+
913+If we are still processing a message (that is, `dod.rum` is false), then
914+we simply put this message in the map of misordered packets to be
915+processed when their time comes. "Processing a message" in this case
916+means that we've received the message and notified the correct
917+application, but we're still waiting for the application-level
918+acknowledgment.
919+
920+Otherwise, we're ready for a packet, so we process it.
921+
922+ ++ coat :: coat:ho:um:am
923+ |= [cha=path rum=race] :: update input race
924+ ^+ +>
925+ =+ cun=(~(get by mis.rum) did.rum)
926+ ?~ cun
927+ +>.$(raz.bah (~(put by raz.bah) cha rum))
928+ ?. =(%good p.u.cun) +>.$
929+ ?> ?=(^ s.u.cun)
930+ %= +>.$
931+ raz.bah (~(put by raz.bah) cha rum(dod |))
932+ bin
933+ :_ bin
934+ :^ %mulk
935+ [our her]
936+ `soap`[[p:sen:gus clon:diz] cha did.rum]
937+ u.s.u.cun
938+ ==
939+
940+First, we grab the message we want to process and store it in `cun`. If
941+it's a good packet, then we change `dod.rum` to false, meaning that
942+we're in the middle of processing a packet and should not start
943+processing another one. We also put a `%mulk` boon into the queue so
944+that, when it all resolves, we send a mesage to the intended recipient
945+application. The boon contains the sender, the receiver, the identity of
946+the message, and the message itself.
947+
948+This bubbles up all the way back to `++knob`, where we were handling the
949+`%hear` card. Following the logic in `++knob`, we can see that the boons
950+get sent into `++clop` to be turned into actual arvo-level moves. We've
951+been here before, if you recall, when we handled the `%cake` boon to
952+send a message. Now, we're handling the `%mulk` boon, which is
953+unfortunately slightly more complicated.
954+
955+ %mulk
956+ :: ~& [%mulk p.bon q.bon]
957+ ?> ?=([@ @ *] q.q.bon)
958+ ?> ?=(%q i.q.q.bon)
959+ ?+ i.t.q.q.bon
960+ ~& %mulk-bad
961+ :_ fox
962+ :~ :- (claw p.p.bon)
963+ [%sick %wart p.bon i.t.q.q.bon t.t.q.q.bon r.bon]
964+ ==
965+ %ge :: %gall request
966+ ?> ?=([@ ~] t.t.q.q.bon)
967+ =+ app=`term`(need ((sand %tas) i.t.t.q.q.bon))
968+ =+ ^= pax
969+ :+ (scot %p p.p.bon)
970+ (scot %p q.p.bon)
971+ q.q.bon
972+ :_ fox [hen %pass pax %g %rote p.bon app r.bon]~
973+ %gh :: %gall response
974+ ?> ?=([@ ~] t.t.q.q.bon)
975+ =+ app=`term`(need ((sand %tas) i.t.t.q.q.bon))
976+ =+ ^= pax
977+ :+ (scot %p p.p.bon)
978+ (scot %p q.p.bon)
979+ q.q.bon
980+ :_ fox [hen %pass pax %g %roth p.bon app r.bon]~
981+ ==
982+
983+We're dispatching messages based on the prefix of their path. Since only
984+`%gall` apps use end-to-end acknowledgments at the moment, every path
985+must have at least two elements, and the first one must be `%q`. Beyond
986+that, we handle the `/q/ge` and `/q/gh` cases for gall requests and
987+responses, respectively.
988+
989+In both cases, we require the next term in the path to be the name of
990+the intended recipient `%gall` app. Thus, a message to `/q/ge/talk` for
991+example, will send a message to the talk app.
992+
993+We then send a message to the app itself. The message is either a
994+`%rote` or a `%roth` for a request and a response, respectively. The
995+content is the `rook` or `roon` that was sent (stored in `r.bon`), but
996+we don't actually handle that at all here. That's completely a
997+`%gall`-level thing. We're just the messenger.
998+
999+Notice the path we send this over. We encode the sender, the receiver,
1000+and the path over which it was sent. This fully specifies the `race` so
1001+that when the app gives us the acknowledgment we know where to send it.
1002+
1003+We now have another interlude. We have entrusted our precious data, so
1004+carefully guarded and guided from the app on that far-away ship, to our
1005+local app. It has the ability to do whatever it pleases with it. It may
1006+take a significant amount of time to process. When the message has been
1007+handled by this app, though, it must produce an acknowledgment. Our
1008+final task is to deliver this acknowledgment to the sending app.
1009+
1010+We should describe here what exactly these oft-mentioned acknowledgments
1011+actually consist of. There are two kinds of acknowledgments: positive
1012+and negative. A positive acknowledgment contains no data other than its
1013+existence. A negative acknowledgment may optionally include a reason for
1014+said negativity. Formally, a negative acknowledgment is an `ares`, which
1015+is a unit pair of a term and a list of tanks. If this is null, this is
1016+simply a failure with no associated information. If the pair exists, the
1017+term is a short error code that is usually both human and computer
1018+readable. For example, if you try to send a message to a valid `%gall`
1019+app that doesn't have any `++poke` to handle it, then `%gall` will give
1020+a negative acknowledgment with error term `%poke-find-fail`. The list of
1021+tanks is a human-readable description of the error. This often contains
1022+a stack trace. At any rate, all this information is returned to the
1023+sending app on the other end of the wire.
1024+
1025+After this brief interlude, our story resumes in `++knap`, where we
1026+receive responses. In particular, a `%mean` indicates a negative
1027+acknowledgment while a `%nice` indicates a positive acknowledgment.
1028+
1029+ ?(%mean %nice)
1030+ ?> ?=([@ @ @ *] tea)
1031+ =+ soq=[(slav %p i.tea) (slav %p i.t.tea)]
1032+ =+ pax=t.t.tea
1033+ =+ ^= fuy
1034+ =< zork =< zank
1035+ %^ ~(rack am [now fox]) soq pax
1036+ ?-(+<.sih %mean `p.+.sih, %nice ~)
1037+ => %_(. fox q.fuy)
1038+ =| out=(list move)
1039+ |- ^- [p=(list move) q=_+>.^$]
1040+ ?~ p.fuy
1041+ [(flop out) +>.^$]
1042+ =^ toe fox (clop now hen i.p.fuy)
1043+ $(p.fuy t.p.fuy, out (weld (flop toe) out))
1044+
1045+Recall the format of the path we sent the message on, and you'll
1046+understand why `soq` and `pax` are the sender/receiver pair and path on
1047+which the message was sent. The rest of this is structured much like
1048+`++knob`, so we call `++rack:am` and send the resulting boons to
1049+`++clop`. Business as usual.
1050+
1051+ ++ rack :: rack:am
1052+ |= [soq=sock cha=path cop=coop] :: e2e ack
1053+ =+ oh=(ho:(um p.soq) q.soq)
1054+ =. oh (cook:oh cop cha ~)
1055+ (cans:oh cha)
1056+
1057+First, we set up `++um` and `++ho`, as we've done twice before, for our
1058+domestic and foreign servers, respectively. The other two things are
1059+new, though. Well, `++cook` is not actually new, but we delayed the
1060+explanation saying only that it sends an acknowledgment. The time has
1061+come.
1062+
1063+ ++ cook :: cook:ho:um:am
1064+ |= [cop=coop cha=path ram=(unit ,[ryn=lane dam=flap])]
1065+ ^+ +> :: acknowledgment
1066+ =+ rum=(need (~(get by raz.bah) cha))
1067+ =+ lat=(~(get by mis.rum) did.rum)
1068+ ?: &(?=(~ lat) ?=(~ ram)) ~&(%ack-late-or-redundant +>.$)
1069+ =+ ^- [ryn=lane dam=flap]
1070+ ?^ ram [ryn.u.ram dam.u.ram]
1071+ ?< ?=(~ lat)
1072+ [q r]:u.lat
1073+ =. raz.bah
1074+ ?^ ram raz.bah
1075+ %+ ~(put by raz.bah) cha
1076+ rum(dod &, bum ?~(cop bum.rum (~(put by bum.rum) did.rum u.cop)))
1077+ =^ roc diz (zuul:diz now [%buck cop dam ~s0])
1078+ (busk(diz (wast:diz ryn)) xong:diz roc)
1079+
1080+If we are acknowledging a message that we have already acked, the `ram`
1081+will contain the new lane and flap to send the duplicate ack to. This
1082+happens if we call `++cook` in `++deer`, but it doesn't happen from
1083+`++rack`. If there is no message waiting to be acknowledged and we're
1084+not given an explicit lane and flap (that is, we're not sending a
1085+duplicate ack), then the app must have sent us multiple acknowledgments.
1086+We do the only sensible thing we can do and drop all acknowledgments
1087+after the first, printing a message. This is, in fact, an error, so it
1088+could be argued that we ought to crash. Whatever you do, don't depend on
1089+this not crashing.
1090+
1091+First, we grab the race specified by the given path, and we get the most
1092+recent in-order message, which must be the one which is being
1093+acknowledged.
1094+
1095+Then, we decide which lane/flap to respond on/to. Basically, in the
1096+usual case we respond on the lane through which the initial message was
1097+sent, which is stored along with the other packet information in
1098+`mis.rum`, since it has to be remembered across calls to ames. However,
1099+if we receive a duplicate message, then we must respond to the new
1100+message. It's quite possible the reason the other acknowledgment didn't
1101+get returned was that the lane between the ships was broken.
1102+
1103+At any rate, we update the race by saying that we've finished processing
1104+this packet (unless we're sending a duplicate ack) and, if we're sending
1105+a negative acknowledgment, putting the negative ack into `bum.rum` so
1106+that we can resend it if necessary.
1107+
1108+We encode our new message, updating the packet pump, with `++zuul`, as
1109+before, and we send it off with `++busk`, routed via `++wast` to one of
1110+the ships in `++xong`. Of course, in practice, we don't even look at the
1111+ships in `++xong` because we already have a lane directly to our
1112+neighbor (the one over which they sent their message to us).
1113+
1114+We glossed over the actual message we're sending back. We're sending a
1115+`%buck` meal, which is an acknowledgment. The `cop` specifies whether
1116+this is a positive or a negative ack, `dam` specifies the message we're
1117+acknowledging, and the `~s0` is a placeholder for the processing time
1118+required. This time is neither calculated (though it is hopefully
1119+obvious how to do so) nor used at present, but this information may be
1120+used in the future for improved congestion control. Since the round-trip
1121+time for an end-to-end acknowledged packet includes the processing time
1122+on the other end, most common congestion control algorithms will stumble
1123+when some messages take much longer to process than others. As noted,
1124+though, this is simply an opportunity for improvement -- our congestion
1125+control algorithms are relatively naive at the moment.
1126+
1127+Recall that `++busk` calls `++wist` to put the actual `%ouzo` boon in
1128+the queue, which gets handled by `++clop` to actually send the message.
1129+This is the same pipeline as sending any other message, so we'll refer
1130+you to the explanation above if you've forgotten it.
1131+
1132+The last thing we need to do on this ship is move on to the next packet
1133+in the queue if there is one. If you recall, in `++rack` after the call
1134+to `++cook` there was a call to `++cans:ho:um:am`.
1135+
1136+ ++ cans :: cans:ho:um:am
1137+ |= cha=path
1138+ =+ rum=(need (~(get by raz.bah) cha))
1139+ =. rum
1140+ %= rum
1141+ did +(did.rum)
1142+ mis (~(del by mis.rum) did.rum)
1143+ ==
1144+ (coat cha rum)
1145+
1146+This is very simple. We increment the number of packets that we've
1147+acknowledged on this race and we delete the packet that we just
1148+acknowledged from the set of misordered packets.
1149+
1150+Then, we call `++coat` again to process the next packet if we've already
1151+received it. And that's it for this.
1152+
1153+The acknowledgment now travels the same path that its forebearer, the
1154+original message, once tread, but this time not into the great unknown.
1155+The weary traveler is seeking out its familial roots, finding the app
1156+from whom sprung forth the original message way back in paragraph three.
1157+When it arrives at the network adapter of its ancestors, the adapter
1158+tells unix, unix tells libuv, libuv tells vere, and vere sends a `%hear`
1159+kiss to ames. Once more into the kernel.
1160+
1161+The `%hear` kiss is handled in `++knob` as before, leading to `++gnaw`,
1162+going over to `++chew`, `++apse`, `++chow`, and eventualy to `++dine`.
1163+We've seen most of the cases in `++dine`, but we haven't yet looked at
1164+the handling of this `%buck` meal.
1165+
1166+ %buck
1167+ =. +> ?.(=(%full aut) +> cock) :: finish key exch
1168+ +>(..la (tock p.fud q.fud r.fud))
1169+
1170+We send a packet level acknowledgment if we're finishing a key exchange,
1171+else we call `++tock` to process the acknowledgment.
1172+
1173+This will get a little involved, so if you don't much care about how
1174+exactly an acknowledgment happens, just know that the result gets gifted
1175+as a `%woot` card back to the app who sent it. For those brave souls who
1176+wish to see this thing through to the end, it's once more into the
1177+breach.
1178+
1179+ ++ tock :: tock:ho:um:am
1180+ |= [cop=coop fap=flap cot=@dr] :: e2e ack by hash
1181+ ^+ +>
1182+ =^ yoh puz (bick:puz now fap)
1183+ =. +>.$
1184+ ?~ p.yoh +>.$
1185+ =^ hud +>.$
1186+ (done p.u.p.yoh q.u.p.yoh)
1187+ ?~ hud +>.$
1188+ %= +>.$
1189+ bin
1190+ :_ bin
1191+ `boon`[%cake [our her] [[p:sen:gus clon:diz] u.p.yoh] cop u.hud]
1192+ ==
1193+ (busk xong:diz q.yoh)
1194+
1195+We're going to work through this one a little backwards since it's
1196+mostly fairly simple except the call to `++bick:pu`. In fact, we'll just
1197+skip `++bick` for the moment and finish the rest.
1198+
1199+If `++bick` succesfully acks the message, then we call `++done`.
1200+
1201+ ++ done :: done:ho:um:am
1202+ |= [cha=path num=@ud] :: complete outgoing
1203+ ^- [(unit duct) _+>]
1204+ =+ rol=(need (~(get by ryl.bah) cha))
1205+ =+ rix=(~(get by san.rol) num)
1206+ ?~ rix [~ +>.$]
1207+ :- rix
1208+ %_ +>.$
1209+ ryl.bah
1210+ (~(put by ryl.bah) cha rol(san (~(del by san.rol) num)))
1211+ ==
1212+
1213+This very simply gets the rill (the outgoing counterpart to a race, if
1214+you recall), pulls out of the map of outstanding messages the duct over
1215+which the original message was sent, and produces this duct while
1216+deleting that entry from the map of outstanding messages.
1217+
1218+Going back to `++tock`, we now have the duct we need to return the
1219+result over. We do the very sensible thing and put a `%cake` boon in the
1220+queue to be processed later by `++clop`.
1221+
1222+In `q.yoh` we have a list of messages that may need to be sent, which we
1223+pass to `++busk` to send, as usual. When an acknowledgment arrives, that
1224+may trigger other messages immediately. This often happens when sending
1225+more messages than the width of the logical window since for congestion
1226+control reasons another message cannot be sent until some of the earlier
1227+ones have been acknowledged.
1228+
1229+We'll look at the processing of the `%cake` boon in `++clop` before we
1230+get back to talking about `++bick`.
1231+
1232+ %cake
1233+ :_ fox
1234+ :~ [s.bon %give %woot q.p.bon r.bon]
1235+ ==
1236+
1237+We very simply give, along the duct we found above, a `%woot` card with
1238+the ship who sent us the ack and the ack itself. This allows the
1239+application to decide what to do about the result. In case of a failure,
1240+we usually either resend the message or display it to the user.
1241+Sometimes, we recognize the error term and handle it internally. In any
1242+case, the decision of how to handle the acknowledgment is entirely up to
1243+the application. Our job is done.
1244+
1245+Well, except that we skipped `++bick:pu`. Let's go back to that.
1246+
1247+ ++ bick :: bick:pu
1248+ |= [now=@da fap=flap] :: ack by hash
1249+ ^- [[p=(unit soup) q=(list rock)] _+>]
1250+ =+ sun=(~(get by diq) fap)
1251+ ?~ sun
1252+ [[~ ~] +>.$]
1253+ =. diq (~(del by diq) fap)
1254+ =^ gub +>.$ (bock now u.sun)
1255+ =^ yop +>.$ (harv now)
1256+ [[gub yop] +>.$]
1257+
1258+If you recall, in `++whap:pu` we created the packet pump's
1259+representation of the message, which included putting the message into
1260+`diq`, which maps from packet hashes to packet sequence numbers. Thus,
1261+`u.sun` is the sequence number of this particular message.
1262+
1263+We delete this message from `diq` since we have now received an ack for
1264+it. We call `++bock` to perform the ack by sequence number. We call
1265+`++harv` to harvest the packet queue, sending any messages that are now
1266+able to be sent.
1267+
1268+In `++bock`, there are three arms we haven't seen before: `++bine`,
1269+`+wept`, and `++beet`. We'll describe each of these before we get to
1270+`++bock`. `++bine` looks scariest.
1271+
1272+ ++ bine :: bine:pu
1273+ |= [now=@da num=@ud] :: apply ack
1274+ ^- [(unit soup) _+>]
1275+ ?~ puq !!
1276+ ?. =(num p.n.puq)
1277+ ?: (gth num p.n.puq)
1278+ =+ lef=$(puq l.puq)
1279+ [-.lef +.lef(puq [n.puq puq.lef r.puq])]
1280+ =+ rig=$(puq r.puq)
1281+ [-.rig +.rig(puq [n.puq l.puq puq.rig])]
1282+ =: rtt ?. &(liv.q.n.puq =(1 nux.q.n.puq)) rtt
1283+ =+ gap=(sub now lys.q.n.puq)
1284+ :: ~& [%bock-trip num (div gap (div ~s1 1.000))]
1285+ (div (add (mul 2 rtt) gap) 3)
1286+ nif (sub nif !liv.q.n.puq)
1287+ ==
1288+ =+ lez=(dec (need (~(get by pyz) gom.q.n.puq)))
1289+ =^ gub pyz
1290+ ?: =(0 lez)
1291+ [[~ gom.q.n.puq] (~(del by pyz) gom.q.n.puq)]
1292+ [~ (~(put by pyz) gom.q.n.puq lez)]
1293+ :- gub
1294+ +>.$(puq ~(nap to puq))
1295+
1296+The first few lines are simply looking through the packet queue until we
1297+find the correct packet to ack. This is basic queue manipulation that
1298+operates directly on the treap structure of the queue. If you understand
1299+treap queues, the logic is easy to follow. Otherwise, just trust us that
1300+by the time we get to the `=:`, the packet with sequence number `num` is
1301+on the top of the packet queue (that is, at `n.puq`).
1302+
1303+We first update the round-trip time. If the packet is either not alive
1304+or had to be transmitted more than once, then we don't have any reliable
1305+way of calculating the round-trip time since we're unsure of exactly
1306+which transmission was acknowledged. Otherwise, the round-trip time is
1307+the difference between now and when the packet was last sent. We set
1308+`rtt` by a little weighted average where the previous smoothed RTT is
1309+weighted twice as much as the RTT of the current packet. Thus,
1310+`(2*rtt+gap)/3`. This gives us a nice smooth RTT that is somewhat
1311+resilient to outlier data while still being responsive to our
1312+ever-changing world.
1313+
1314+If the packet wasn't already dead, then we decrement the number of live
1315+packets, which may allow more packets to be sent.
1316+
1317+We decrement the number of unacknowledged packets in our `pyz` for this
1318+particular message. If you recall, this was set in `++whap` to the
1319+number of packets required to send a message.
1320+
1321+If that was the last packet in the messge that needed to be acked, then
1322+we delete the messgae reference from `pyz` and produce the id of the
1323+message. Otherwise, we simply update `pyz` with the new number of
1324+unacked messages. In either case, we remove the packet from the packet
1325+queue.
1326+
1327+ ++ wept :: wept:pu
1328+ |= [fip=@ud lap=@ud] :: fip thru lap-1
1329+ =< abet =< apse
1330+ |%
1331+ ++ abet +>.$
1332+ ++ apse
1333+ ^+ .
1334+ ?~ puq .
1335+ ?: (lth p.n.puq fip) ?~(l.puq . left)
1336+ ?: (gte p.n.puq lap) ?~(r.puq . rigt)
1337+ => rigt =< left
1338+ ?> ?=(^ puq)
1339+ ?.(liv.q.n.puq . .(nif (dec nif), liv.q.n.puq |))
1340+ ::
1341+ ++ left
1342+ ?> ?=(^ puq)
1343+ ^+(. =+(lef=apse(puq l.puq) lef(puq [n.puq puq.lef r.puq])))
1344+ ++ rigt
1345+ ?> ?=(^ puq)
1346+ ^+(. =+(rig=apse(puq r.puq) rig(puq [n.puq l.puq puq.rig])))
1347+ --
1348+
1349+The algorithm is a simple case of traversing the packet queue.
1350+Essentialy, we mark as dead all packets in the queue between `fip` and
1351+`(dec lap)`. We also update `nif`, the number of live packets. Lest you
1352+mourn too much the passing of these packets, know that they shall soon
1353+rise again. Recall that in `++bick` after the call to `++bock` we call
1354+`++harv`. This will resend the packets that have just been labeled dead.
1355+
1356+ ++ beet :: beet:pu
1357+ ^+ . :: advance unacked
1358+ =- +(nep ?~(foh nus u.foh))
1359+ ^= foh
1360+ |- ^- (unit ,@ud)
1361+ ?~ puq ~
1362+ ?: (lte p.n.puq nep) $(puq l.puq)
1363+ =+ rig=$(puq r.puq)
1364+ ?^(rig rig [~ p.n.puq])
1365+
1366+Here we search for the next expected packet number. Basically, we search
1367+the queue for the leftmost packet whose number is greater than the
1368+current `nep`. If we don't find any such packet, we just use the total
1369+number of packets sent.
1370+
1371+We can now dive into `++bock`, our last arm.
1372+
1373+ ++ bock :: bock:pu
1374+ |= [now=@da num=@ud] :: ack by sequence
1375+ ^- [(unit soup) _+>]
1376+ =^ gym +> (bine now num)
1377+ :- gym
1378+ ?: (gth num nep)
1379+ =+ cam=(max 2 (div caw 2))
1380+ :: ~& [%bock-hole num nep cam]
1381+ beet:(wept(nep num, cag cam, caw cam) nep num)
1382+ =. caw ?: (lth caw cag) +(caw)
1383+ (add caw !=(0 (mod (mug now) caw)))
1384+ ?: =(num nep)
1385+ :: ~& [%bock-fine num nif caw cag]
1386+ beet
1387+ :: ~& [%bock-fill num nif caw cag]
1388+ +>.$
1389+
1390+First, we call `++bine` to apply the ack to the packet pump information.
1391+We produce `gym`, which, if it exists, is the id of the packet that was
1392+acked. If we received an ack for a packet later than the one we
1393+expected, then we halve the logical packet window and kill all the
1394+earlier packets so that they may be resent.
1395+
1396+Otherwise, we possibly increase the congestion window. If the window is
1397+less than the congestion threshold, then we increment the size of the
1398+window. Otherwise, we only increment one out of every `caw` times.
1399+
1400+If we received an ack for the packet we expected, then we simply advance
1401+`nep` with `++beet`. If we received an ack for a packet earlier than we
1402+expected, we do nothing.
1403+
1404+It may be hard to believe, but we are, in fact, done. The message has
1405+been sent, received, acknowledged, and the acknowledgment has been
1406+returned to the original sender. We hope it's clear that, while the
1407+process has been somewhat involved, the algorithms are not all that
1408+complicated. If you've read this far, you know `%ames`. The only other
1409+code involves initialization, timeouts, and the like.
1410+
1411+Below, we give detailed reference documentation for the data models
1412+involved.
1413+
1414+Data Models
1415+-----------
1416+
1417+### `++fort`, formal state
1418+
1419+ ++ fort :: formal state
1420+ $: %0 :: version
1421+ gad=duct :: client interface
1422+ hop=@da :: network boot date
1423+ ton=town :: security
1424+ zac=(map ship corn) :: flows by server
1425+ == ::
1426+
1427+This is the state of our vane. Anything that must be remembered between
1428+calls to ames must be stored in this state.
1429+
1430+`%0` is the version of the ames state model itself. If the data model
1431+`++fort` changes, then this number needs to be incremented, and an
1432+adapter must be written to upgrade the old state into the new state.
1433+Note that this is the version number of the model itself, not the
1434+contents. When the data changes, there is of course no need to change
1435+this.
1436+
1437+`gad` is a `duct` over which we send `%send` cards to unix. This card is
1438+initialized when unix sends a `%barn` card as vere starts up. Vere
1439+treats this duct specially -- don't send anything weird over it.
1440+
1441+`hop` is the network boot date. This is set when the `%kick` card is
1442+sent by vere on start up.
1443+
1444+`ton` is a `++town`, where we store all of our security/encryption
1445+state. Note that this is shared across all ships on a pier.
1446+
1447+`zac` is a map of ships to `++corn`. This stores all the per-ship state.
1448+The keys to this map are the ships on the current pier.
1449+
1450+### `++town`, all security state
1451+
1452+ ++ town :: all security state
1453+ $: lit=@ud :: imperial modulus
1454+ any=@ :: entropy
1455+ urb=(map ship sufi) :: all keys and routes
1456+ fak=? ::
1457+ == ::
1458+
1459+This is the security state of our pier.
1460+
1461+`lit` is unused.
1462+
1463+`any` is 256 bits of entropy. This entropy is used and updated in
1464+exactly two places: when we send a `%junk` card, and when we generate a
1465+new symmetric key in `++griz:lax:as:go`. When it is updated, it is
1466+updated by a SHA-256 hash of the current time and the old value of the
1467+entropy.
1468+
1469+`urb` is a map of ships to `++sufi`. This is where we store all the
1470+per-ship state for the pier. The keys to this map are the ships on the
1471+current pier.
1472+
1473+`fak` is true if we are on a fake network. This disables certain
1474+security checks so that anyone may run a fake `~zod`. This is used only
1475+for development. To use, run vere with the `-F` option (and the
1476+`-I ~zod` option for a fake `~zod`).
1477+
1478+### `++sufi`, domestic host
1479+
1480+ ++ sufi :: domestic host
1481+ $: hoy=(list ship) :: hierarchy
1482+ val=wund :: private keys
1483+ law=will :: server will
1484+ seh=(map hand ,[p=ship q=@da]) :: key cache
1485+ hoc=(map ship dore) :: neighborhood
1486+ == ::
1487+
1488+This is the security state of a domestic server.
1489+
1490+`hoy` is a list of the ships directly above us in the hierarchy of
1491+ships. For example, for `~hoclur-bicrel`, this would be `~tasruc` and
1492+`~tug`. See `++sein`.
1493+
1494+`val` is a list of our private keys.
1495+
1496+`law` is our certificate, which is a list of the XXX
1497+
1498+`seh`
1499+
1500+`hoc` is a map of ships to `++dore`. The stores all the security
1501+informatoin about foreign ships. The keys to this map are the neighbors
1502+(ships we have been in contact with) of this domestic server.
1503+
1504+### `++wund`, private keys
1505+
1506+ ++ wund (list ,[p=life q=ring r=acru]) :: mace in action
1507+
1508+This is a list of our own private keys, indexed by life. The key itself
1509+is the `++ring`, and the `++acru` is the encryption engine. We generate
1510+the `++acru` from the private key by calling `++weur`. Thus, we can at
1511+any time regenerate our `++wund` from a `++mace`. The current crypto is
1512+at the head of the list and can be accessed with `++sen:as:go`.
1513+
1514+### `++ring`, private key
1515+
1516+ ++ ring ,@ :: private key
1517+
1518+This is a private key. The first byte is reserved to identify the type
1519+of cryptography. Lower-case means public key, upper-case means public
1520+key, and the letter identifies which `++acru` to use.
1521+
1522+### `++pass`, public key
1523+
1524+ ++ pass ,@ :: public key
1525+
1526+This is a public key. The first byte is reserved to identify the type of
1527+cryptography. Lower-case means public key, upper-case means public key,
1528+and the letter identifies which `++acru` to use.
1529+
1530+### `++mace`, private secrets
1531+
1532+ ++ mace (list ,[p=life q=ring]) :: private secrets
1533+
1534+This is a list of the our private keys, indexed by life. From this we
1535+can generate a `++wund` for actual use.
1536+
1537+### `++skin`, encoding stem
1538+
1539+ ++ skin ?(%none %open %fast %full) :: encoding stem
1540+
1541+This defines the type of encryption used for each message. `%none`
1542+refers to messages sent in the clear, `%open` refers to signed messages,
1543+`%full` refers to sealed messages, and `%fast` refers to symmetrically
1544+encrypted messages. See `++acru` for details.
1545+
1546+### `++acru`, asymmetric cryptosuite
1547+
1548+ ++ acru :: asym cryptosuite
1549+ $_ ^? |% :: opaque object
1550+ ++ as ^? :: asym ops
1551+ |% ++ seal |=([a=pass b=@ c=@] _@) :: encrypt to a
1552+ ++ sign |=([a=@ b=@] _@) :: certify as us
1553+ ++ sure |=([a=@ b=@] *(unit ,@)) :: authenticate from us
1554+ ++ tear |= [a=pass b=@] :: accept from a
1555+ *(unit ,[p=@ q=@]) ::
1556+ -- ::
1557+ ++ de |+([a=@ b=@] *(unit ,@)) :: symmetric de, soft
1558+ ++ dy |+([a=@ b=@] _@) :: symmetric de, hard
1559+ ++ en |+([a=@ b=@] _@) :: symmetric en
1560+ ++ ex ^? :: export
1561+ |% ++ fig _@uvH :: fingerprint
1562+ ++ pac _@uvG :: default passcode
1563+ ++ pub *pass :: public key
1564+ ++ sec *ring :: private key
1565+ --
1566+ ++ nu ^? :: reconstructors
1567+ |% ++ pit |=([a=@ b=@] ^?(..nu)) :: from [width seed]
1568+ ++ nol |=(a=@ ^?(..nu)) :: from naked ring
1569+ ++ com |=(a=@ ^?(..nu)) :: from naked pass
1570+ --
1571+ --
1572+
1573+This is an opaque interface for a general asymmetric cryptosuite. Any
1574+form of asymmetric cryptography can be dropped in to be used instead of
1575+the default. Right now, there are two cryptosuites, `++crua`, which is
1576+your standard RSA, and `++crub`, which is elliptic curve crypto but is
1577+mostly stubbed out at the moment.
1578+
1579+#### `++as:acru`, asymmetric operations
1580+
1581+ ++ as ^? :: asym ops
1582+ |% ++ seal |=([a=pass b=@ c=@] _@) :: encrypt to a
1583+ ++ sign |=([a=@ b=@] _@) :: certify as us
1584+ ++ sure |=([a=@ b=@] *(unit ,@)) :: authenticate from us
1585+ ++ tear |= [a=pass b=@] :: accept from a
1586+ *(unit ,[p=@ q=@]) ::
1587+ -- ::
1588+
1589+This is the core that defines the standard asymmetric cryptography
1590+operations.
1591+
1592+`++seal:as:acru` allows us to send a message encrypted with someone's
1593+public key so that only they may read it. If Alice seals a message with
1594+Bob's public key, then she can be sure that Bob is the only one who can
1595+read it. This is associated with the `++skin` `%full`.
1596+
1597+`++sign:as:acru` allows us to sign a message with our private key so
1598+that others can verify that we sent the message. If Alice signs a
1599+message with her private key, then Bob can verify with her public key
1600+that it was indeed Alice who sent it. This is associated with the
1601+`++skin` `%open`.
1602+
1603+`++sure:as:acru` is the dual to `++sign:as:acru`. It allows us to verify
1604+that a message we have received is indeed from the claimed sender. If
1605+Alice sends a message with her private key, then Bob can use this arm to
1606+verify that it was indeed Alice who sent it. This is associated with the
1607+`++skin` `%open`.
1608+
1609+`++tear:as:acru` is the dual to `++seal:as:acru`. It allows us to read a
1610+message that we can be sure is only read by us. If Alice seals a message
1611+with Bob's public key, then Bob can use this arm to read it. This is
1612+associated with the `++skin` `%full`.
1613+
1614+#### `++de:acru`, `++dy:acru`, and `++en:acru`, symmetric encryption/decryption
1615+
1616+ ++ de |+([a=@ b=@] *(unit ,@)) :: symmetric de, soft
1617+ ++ dy |+([a=@ b=@] _@) :: symmetric de, hard
1618+ ++ en |+([a=@ b=@] _@) :: symmetric en
1619+
1620+Symmetric encryption is associated with the `++skin` `%fast`.
1621+
1622+`++de:acru` decrypts a message with a symmetric key, returning `~` on
1623+failure and `[~ u=data]` on success.
1624+
1625+`++dy:acru` decrypts a message with a symmetric key, crashing on
1626+failure. This should almost always be defined as, and should always be
1627+semantically equivalent to, `(need (de a b))`.
1628+
1629+`++en:acru` encrypts a message with a symmetric key.
1630+
1631+#### `++ex:acru`, exporting data
1632+
1633+ ++ ex ^? :: export
1634+ |% ++ fig _@uvH :: fingerprint
1635+ ++ pac _@uvG :: default passcode
1636+ ++ pub *pass :: public key
1637+ ++ sec *ring :: private key
1638+ --
1639+
1640+`++fig:ex:acru` is our fingerprint, usually a hash of our public key.
1641+This is used, for example, in `++zeno`, where every carrier owner's
1642+fingerprint is stored so that we can ensure that carriers are indeed
1643+owned by their owners
1644+
1645+`++pac:ex:acru` is our default passcode, which is unused at present.
1646+
1647+`++pub:ex:acru` is the `++pass` form of our public key.
1648+
1649+`++sec:ex:acru` is the `++ring` form of our private key.
1650+
1651+#### `++nu:acru`, reconstructors
1652+
1653+ ++ nu ^? :: reconstructors
1654+ |% ++ pit |=([a=@ b=@] ^?(..nu)) :: from [width seed]
1655+ ++ nol |=(a=@ ^?(..nu)) :: from naked ring
1656+ ++ com |=(a=@ ^?(..nu)) :: from naked pass
1657+ --
1658+
1659+These arms allow us to reconstruct a `++acru` from basic data.
1660+
1661+`++pit:nu:acru` constructs a `++acru` from the width of our intended key
1662+and seed entropy. This is usually used in the initial construction of
1663+the `++acru`.
1664+
1665+`++nol:nu:acru` constructs a `++acru` from a "naked ring", meaning a
1666+`++ring` without the initial byte identifying the type of crypto. There
1667+is often a helper arm that that wraps this; see `++weur` for `++crua`
1668+and `++wear` for `++crub`.
1669+
1670+`++com:nu:acru` constructs a `++acru` from a "naked pass", meaning a
1671+`++ring` without the initial byte identifying the type of crypto. There
1672+is often a helper arm that that wraps this; see `++haul` for `++crua`
1673+and `++hail` for `++crub`.
1674+
1675+### `++will`, certificate
1676+
1677+ ++ will (list deed) :: certificate
1678+
1679+This is a list of deeds associated with the current ship. There should
1680+be an item in this list for every ship from this point up in the
1681+hierarchy times the number of lives that each ship has had. For example,
1682+\~hoclur-bicrel may have a will with three items: one for itself, one
1683+for \~tasruc (who issued \~hoclur-bicrel's deed) and one for \~tug (who
1684+issued \~tasruc's deed).
1685+
1686+### `++deed`, identity
1687+
1688+ ++ deed ,[p=@ q=step r=?] :: sig, stage, fake?
1689+
1690+`p` is the signature of a particular deed, which is a signed copy of
1691+`q`.
1692+
1693+`q` is the stage in the identity.
1694+
1695+`r` is true if we're working on a fake network, where we don't check
1696+that the carrier fingerprints are correct. This allows us to create fake
1697+networks for development without interfering with the real network.
1698+
1699+### `++step`, identity stage
1700+
1701+ ++ step ,[p=bray q=gens r=pass] :: identity stage
1702+
1703+This is a single stage in our identity. Thus, this is specific to a
1704+single life in a single ship. Everything in here may change between
1705+lives.
1706+
1707+`p`
1708+
1709+`q`
1710+
1711+`r` is the public key for this stage in the identity.
1712+
1713+### `++bray`
1714+
1715+ ++ bray ,[p=life q=(unit life) r=ship s=@da] :: our parent us now
1716+
1717+XXX
1718+
1719+### `++gens`, general identity
1720+
1721+ ++ gens ,[p=lang q=gcos] :: general identity
1722+
1723+`p` is the IETF language code for the preferred language of this
1724+identity. This is unused at the moment, but in the future text should be
1725+localized based on this.
1726+
1727+`q` is the description of the ship.
1728+
1729+### `++gcos`, identity description
1730+
1731+ ++ gcos :: id description
1732+ $% [%czar ~] :: 8-bit ship
1733+ [%duke p=what] :: 32-bit ship
1734+ [%earl p=@t] :: 64-bit ship
1735+ [%king p=@t] :: 16-bit ship
1736+ [%pawn p=(unit ,@t)] :: 128-bit ship
1737+ == ::
1738+
1739+This is the description of the identity of a ship. Most types of
1740+identity have a `@t` field, which is their human-readable name. The
1741+identity of a `%duke` is more involved.
1742+
1743+A `%czar`, a carrier, is a ship with an 8-bit address. Thus, there are
1744+only 256 carriers. These are at the top of the namespace hierarchy, and
1745+the fingerprint of each carrier is stored in `++zeno`. These are the
1746+"senators" of Urbit.
1747+
1748+A `%king`, a cruiser, is a ship with a 16-bit address. Thus, there are
1749+65,536 cruisers. Each carrier may issue 256 cruisers. These are the
1750+infrastructure of Urbit.
1751+
1752+A `%duke`, a destroyer, is a ship with a 32-bit address. Thus, there are
1753+4,294,967,296 destroyers. Each cruiser may issue 65,536 cruisers. These
1754+are the individuals of Urbit.
1755+
1756+A `%earl`, a yacht, is a ship with a 64-bit address. Thus, there are
1757+18,446,744,073,709,551,616 yachts. Each destroyer may issue
1758+4,294,967,296 yachts. These are the devices of Urbit.
1759+
1760+A `%pawn`, a submarine, is a ship with a 128-bit address. Thus, there
1761+are a lot of submarines. The chance of random name collision is
1762+negligible, so submarines are not issued by any ship. They must simply
1763+assert their presence, and they are all considered children of \~zod.
1764+This is the underworld of Urbit, where anonymity reigns supreme.
1765+
1766+### `++what`, logical destroyer identity
1767+
1768+ ++ what :: logical identity
1769+ $% [%anon ~] :: anonymous
1770+ [%lady p=whom] :: female person ()
1771+ [%lord p=whom] :: male person []
1772+ [%punk p=sect q=@t] :: opaque handle ""
1773+ == ::
1774+
1775+This is the logical identity of a destroyer.
1776+
1777+A `%anon` is a completely anonymous destroyer. The difference between
1778+this and a submarine is that a submarine is ephemeral while a `%anon`
1779+destroyer is not. Thus, we may not know who \~hoclur-bicrel is, but we
1780+do know that it's always the same person.
1781+
1782+A `%lady` is a female person. The name used here should be a real name.
1783+
1784+A `%lord` is a male person. The name used here should be a real name.
1785+
1786+A `%punk` is a person who is identified only by a handle.
1787+
1788+### `++whom`, real person
1789+
1790+ ++ whom ,[p=@ud q=govt r=sect s=name] :: year/govt/id
1791+
1792+Ths is the information associated with a real person. It is mostly
1793+information that could be observed with the briefest of interactions.
1794+
1795+`p` is the birth year.
1796+
1797+`q` is the location of a user, usually of the form "country/zip".
1798+
1799+`r` is the sect of the user.
1800+
1801+`s` is the real name of the person.
1802+
1803+### `++govt`
1804+
1805+ ++ govt path :: country/postcode
1806+
1807+This is the location of the user, usually of the form "country/zip".
1808+
1809+### `++sect`
1810+
1811+ ++ sect ?(%black %blue %red %orange %white) :: banner
1812+
1813+XXX
1814+
1815+### `++name`
1816+
1817+ ++ name ,[p=@t q=(unit ,@t) r=(unit ,@t) s=@t] :: first mid/nick last
1818+
1819+This is the given name, possible middle name/initial, possible nickname,
1820+and surname of a user.
docs/arvo/internals/behn.mdnew file+22
@@ -0,0 +1,22 @@
1+---
2+navhome: /docs
3+sort: 2
4+---
5+
6+`%behn`
7+=======
8+
9+Our simple timer.
10+
11+It allows vanes and applications to set and timer events, which are
12+managed in a simple priority queue. `%behn` produces effects to start
13+the unix timer, and when the requested `%behn` passes, unix sends wake
14+events to `%behn`, which time routes back to original sender. We don't
15+guarantee that a timer event will happen at exactly the `%behn` it was
16+set for, or even that it'll be particularly close. A timer event is a
17+request to not be woken until after the given time.
18+
19+`%eyre` uses `%behn` for timing out sessions, and `%clay` uses `%behn`
20+for keeping track of time-specified file requests. `%ames` should
21+probably use `%behn` to keep track of things like network timeouts and
22+retry timing, but it currently uses its own alarm system.
docs/arvo/internals/clay.mdnew file+26
@@ -0,0 +1,26 @@
1+---
2+navhome: /docs
3+sort: 3
4+---
5+
6+`%clay`
7+=======
8+
9+Our filesystem.
10+
11+`%clay` is version-controlled, referentially-transparent, and global.
12+While this filesystem is stored in `%clay`, it is mirrored to Unix for
13+convenience. Unix tells `%clay`s whenever a file changes in the Unix
14+copy of the filesystem so that the change may be applied. `%clay` tells
15+unix whenever an app or vane changes the filesystem so that the change
16+can be effected in Unix. Apps and vanes may use `%clay` to write to the
17+filesystem, query it, and subscribe to changes in it. Ford and gall use
18+`%clay` to serve up apps and web pages.
19+
20+`%clay` includes three components. First is the filesystem/version
21+control algorithms, which are mostly defined in `++ze` and `++zu` in
22+zuse. Second is the write, query, and subscription logic. Finally, there
23+is the logic for communicating requests to, and receiving requests from,
24+foreign ships.
25+
26+<list></list>
docs/arvo/internals/clay/architecture.mdnew file+420
@@ -0,0 +1,420 @@
1+---
2+navhome: /docs
3+---
4+
5+
6+# clay
7+
8+## high-level
9+
10+clay is the primary filesystem for the arvo operating system,
11+which is the core of an urbit. The architecture of clay is
12+intrinsically connected with arvo, but we assume no knowledge of
13+either arvo or urbit. We will point out only those features of
14+arvo that are necessary for an understanding of clay, and we will
15+do so only when they arise.
16+
17+The first relevant feature of arvo is that it is a deterministic
18+system where input and output are defined as a series of events
19+and effects. The state of arvo is simply a function of its event
20+log. None of the effects from an event are emitted until the
21+event is entered in the log and persisted, either to disk or
22+another trusted source of persistence, such as a Kafka cluster.
23+Consequently, arvo is a single-level store: everything in its
24+state is persistent.
25+
26+In a more traditional OS, everything in RAM can be erased at any
27+time by power failure, and is always erased on reboot. Thus, a
28+primary purpose of a filesystem is to ensure files persist across
29+power failures and reboots. In arvo, both power failures and
30+reboots are special cases of suspending computation, which is
31+done safely since our event log is already persistent. Therefore,
32+clay is not needed in arvo for persistence. Why, then, do we have a
33+filesystem? There are two answers to this question.
34+
35+First, clay provides a filesystem tree, which is a convenient
36+user interface for some applications. Unix has the useful concept
37+of virtual filesystems, which are used for everything from direct
38+access to devices, to random number generators, to the /proc
39+tree. It is easy and intuitive to read from and write to a
40+filesystem tree.
41+
42+Second, clay has a distributed revision control system baked into
43+it. Traditional filesystems are not revision controlled, so
44+userspace software -- such as git -- is written on top of them to
45+do so. clay natively provides the same functionality as modern
46+DVCSes, and more.
47+
48+clay has two other unique properties that we'll cover later on:
49+it supports typed data and is referentially transparent.
50+
51+### Revision Control
52+
53+Every urbit has one or more "desks", which are independently
54+revision-controlled branches. Each desk contains its own mark
55+definitions, apps, doc, and so forth.
56+
57+Traditionally, an urbit has at least a base and a home desk. The
58+base desk has all the system software from the distribution. the
59+home desk is a fork of base with all the stuff specific to the
60+user of the urbit.
61+
62+A desk is a series of numbered commits, the most recent of which
63+represents the current state of the desk. A commit is composed of
64+(1) an absolute time when it was created, (2) a list of zero or
65+more parents, and (3) a map from paths to data.
66+
67+Most commits have exactly one parent, but the initial commit on a
68+desk may have zero parents, and merge commits have more than one
69+parent.
70+
71+The non-meta data is stored in the map of paths to data. It's
72+worth noting that no constraints are put on this map, so, for
73+example, both /a/b and /a/b/c could have data. This is impossible
74+in a traditional Unix filesystem since it means that /a/b is both
75+a file and a directory. Conventionally, the final element in the
76+path is its mark -- much like a filename extension in Unix. Thus,
77+/doc/readme.md in Unix is stored as /doc/readme/md in urbit.
78+
79+The data is not stored directly in the map; rather, a hash of the
80+data is stored, and we maintain a master blob store. Thus, if the
81+same data is referred to in multiple commits (as, for example,
82+when a file doesn't change between commits), only the hash is
83+duplicated.
84+
85+In the master blob store, we either store the data directly, or
86+else we store a diff against another blob. The hash is dependent
87+only on the data within and not on whether or not it's stored
88+directly, so we may on occasion rearrange the contents of the
89+blob store for performance reasons.
90+
91+Recall that a desk is a series of numbered commits. Not every
92+commit in a desk must be numbered. For example, if the base desk
93+has had 50 commits since home was forked from it, then a merge
94+from base to home will only add a single revision number to home,
95+although the full commit history will be accessible by traversing
96+the parentage of the individual commits.
97+
98+We do guarantee that the first commit is numbered 1, commits are
99+numbered consecutively after that (i.e. there are no "holes"),
100+the topmost commit is always numbered, and every numbered commit
101+is an ancestor of every later numbered commit.
102+
103+There are three ways to refer to particular commits in the
104+revision history. Firstly, one can use the revision number.
105+Secondly, one can use any absolute time between the one numbered
106+commit and the next (inclusive of the first, exclusive of the
107+second). Thirdly, every desk has a map of labels to revision
108+numbers. These labels may be used to refer to specific commits.
109+
110+Additionally, clay is a global filesystem, so data on other urbit
111+is easily accessible the same way as data on our local urbit. In
112+general, the path to a particular revision of a desk is
113+/~urbit-name/desk-name/revision. Thus, to get /try/readme/md
114+from revision 5 of the home desk on ~sampel-sipnym, we refer to
115+/~sampel-sipnym/home/5/try/readme/md. Clay's namespace is thus
116+global and referentially transparent.
117+
118+XXX reactivity here?
119+
120+### A Typed Filesystem
121+
122+Since clay is a general filesystem for storing data of arbitrary
123+types, in order to revision control correctly it needs to be
124+aware of types all the way through. Traditional revision control
125+does an excellent job of handling source code, so for source code
126+we act very similar to traditional revision control. The
127+challenge is to handle other data similarly well.
128+
129+For example, modern VCSs generally support "binary files", which
130+are files for which the standard textual diffing, patching, and
131+merging algorithms are not helpful. A "diff" of two binary files
132+is just a pair of the files, "patching" this diff is just
133+replacing the old file with the new one, and "merging"
134+non-identical diffs is always a conflict, which can't even be
135+helpfully annotated. Without knowing anything about the structure
136+of a blob of data, this is the best we can do.
137+
138+Often, though, "binary" files have some internal structure, and
139+it is possible to create diff, patch, and merge algorithms that
140+take advantage of this structure. An image may be the result of a
141+base image with some set of operations applied. With algorithms
142+aware of this set of operations, not only can revision control
143+software save space by not having to save every revision of the
144+image individually, these transformations can be made on parallel
145+branches and merged at will.
146+
147+Suppose Alice is tasked with touching up a picture, improving the
148+color balance, adjusting the contrast, and so forth, while Bob
149+has the job of cropping the picture to fit where it's needed and
150+adding textual overlay. Without type-aware revision control,
151+these changes must be made serially, requiring Alice and Bob to
152+explicitly coordinate their efforts. With type-aware revision
153+control, these operations may be performed in parallel, and then
154+the two changesets can be merged programmatically.
155+
156+Of course, even some kinds of text files may be better served by
157+diff, patch, and merge algorithms aware of the structure of the
158+files. Consider a file containing a pretty-printed JSON object.
159+Small changes in the JSON object may result in rather significant
160+changes in how the object is pretty-printed (for example, by
161+addding an indentation level, splitting a single line into
162+multiple lines).
163+
164+A text file wrapped at 80 columns also reacts suboptimally with
165+unadorned Hunt-McIlroy diffs. A single word inserted in a
166+paragraph may push the final word or two of the line onto the
167+next line, and the entire rest of the paragraph may be flagged as
168+a change. Two diffs consisting of a single added word to
169+different sentences may be flagged as a conflict. In general,
170+prose should be diffed by sentence, not by line.
171+
172+As far as the author is aware, clay is the first generalized,
173+type-aware revision control system. We'll go into the workings
174+of this system in some detail.
175+
176+### Marks
177+
178+Central to a typed filesystem is the idea of types. In clay, we
179+call these "marks". A mark is a file that defines a type,
180+conversion routines to and from the mark, and diff, patch, and
181+merge routines.
182+
183+For example, a `%txt` mark may be a list of lines of text, and it
184+may include conversions to `%mime` to allow it to be serialized
185+and sent to a browswer or to the unix filesystem. It will also
186+include Hunt-McIlroy diff, patch, and merge algorithms.
187+
188+A `%json` mark would be defined as a json object in the code, and
189+it would have a parser to convert from `%txt` and a printer to
190+convert back to `%txt`. The diff, patch, and merge algorithms are
191+fairly straightforward for json, though they're very different
192+from the text ones.
193+
194+More formally, a mark is a core with three arms, `++grab`,
195+`++grow`, and `++grad`. In `++grab` is a series of functions to
196+convert from other marks to the given mark. In `++grow` is a
197+series of functions to convert from the given mark to other
198+marks. In `++grad` is `++diff`, `++pact`, `++join`, and `++mash`.
199+
200+The types are as follows, in an informal pseudocode:
201+
202+ ++ grab:
203+ ++ mime: <mime> -> <mark-type>
204+ ++ txt: <txt> -> <mark-type>
205+ ...
206+ ++ grow:
207+ ++ mime: <mark-type> -> <mime>
208+ ++ txt: <mark-type> -> <txt>
209+ ...
210+ ++ grad
211+ ++ diff: (<mark-type>, <mark-type>) -> <diff-type>
212+ ++ pact: (<mark-type>, <diff-type>) -> <mark-type>
213+ ++ join: (<diff-type>, <diff-type>) -> <diff-type> or NULL
214+ ++ mash: (<diff-type>, <diff-type>) -> <diff-type>
215+
216+These types are basically what you would expect. Not every mark
217+has each of these functions defined -- all of them are optional
218+in the general case.
219+
220+In general, for a particular mark, the `++grab` and `++grow` entries
221+(if they exist) should be inverses of each other.
222+
223+In `++grad`, `++diff` takes two instances of a mark and produces
224+a diff of them. `++pact` takes an instance of a mark and patches
225+it with the given diff. `++join` takes two diffs and attempts to
226+merge them into a single diff. If there are conflicts, it
227+produces null. `++mash` takes two diffs and forces a merge,
228+annotating any conflicts.
229+
230+In general, if `++diff` called with A and B produces diff D, then
231+`++pact` called with A and D should produce B. Also, if `++join`
232+of two diffs does not produce null, then `++mash` of the same
233+diffs should produce the same result.
234+
235+Alternately, instead of `++diff`, `++pact`, `++join`, and
236+`++mash`, a mark can provide the same functionality by defining
237+`++sted` to be the name of another mark to which we wish to
238+delegate the revision control responsibilities. Then, before
239+running any of those functions, clay will convert to the other
240+mark, and convert back afterward. For example, the `%hoon` mark
241+is revision-controlled in the same way as `%txt`, so its `++grad`
242+is simply `++sted %txt`. Of course, `++txt` must be defined in
243+`++grow` and `++grab` as well.
244+
245+Every file in clay has a mark, and that mark must have a
246+fully-functioning `++grad`. Marks are used for more than just
247+clay, and other marks don't need a `++grad`, but if a piece of
248+data is to be saved to clay, we must know how to revision-control
249+it.
250+
251+Additionally, if a file is to be synced out to unix, then it must
252+have conversion routines to and from the `%mime` mark.
253+
254+##Using clay
255+
256+### Reading and Subscribing
257+
258+When reading from Clay, there are three types of requests. A
259+`%sing` request asks for data at single revsion. A `%next`
260+request asks to be notified the next time there's a change to
261+given file. A `%many` request asks to be notified on every
262+change in a desk for a range of changes.
263+
264+For `%sing` and `%next`, there are generally three things to be
265+queried. A `%u` request simply checks for the existence of a
266+file at a path. A `%x` request gets the data in the file at a
267+path. A `%y` request gets a hash of the data in the file at the
268+path combined with all its children and their data. Thus, `%y`
269+of a node changes if it or any of its children change.
270+
271+A `%sing` request is fulfilled immediately if possible. If the
272+requested revision is in the future, or is on another ship for
273+which we don't have the result cached, we don't respond
274+immediately. If the requested revision is in the future, we wait
275+until the revision happens before we respond to the request. If
276+the request is for data on another ship, we pass on the request
277+to the other ship. In general, Clay subscriptions, like most
278+things in Urbit, aren't guaranteed to return immediately.
279+They'll return when they can, and they'll do so in a
280+referentially transparent manner.
281+
282+A `%next` request checks query at the given revision, and it
283+produces the result of the query the next time it changes, along
284+with the revsion number when it changes. Thus, a `%next` of a
285+`%u` is triggered when a file is added or deleted, a `%next` of a
286+`%x` is triggered when a file is added, deleted, or changed, and
287+a `%next` of a `%y` is triggered when a file or any of its
288+children is added, deleted, or changed.
289+
290+A `%many` request is triggered every time the given desk has a
291+new revision. Unlike a `%next`, a `%many` has both a start and
292+an end revsion, after which it stops returning. For `%next`, a
293+single change is reported, and if the caller wishes to hear of
294+the next change, it must resubscribe. For `%many`, every revsion
295+from the start to the end triggers a response. Since a `%many`
296+request doesn't ask for any particular data, there aren't `%u`,
297+`%x`, and `%y` versions for it.
298+
299+### Unix sync
300+
301+One of the primary functions of clay is as a convenient user
302+interface. While tools exist to use clay from within urbit, it's
303+often useful to be able to treat clay like any other filesystem
304+from the Unix perspective -- to "mount" it, as it were.
305+
306+From urbit, you can run `|mount /path/to/directory %mount-point`,
307+and this will mount the given clay directory to the mount-point
308+directory in Unix. Every file is converted to `%mime` before it's
309+written to Unix, and converted back when read from Unix. The
310+entire directory is watched (a la Dropbox), and every change is
311+auto-committed to clay.
312+
313+### Merging
314+
315+Merging is a fundamental operation for a distributed revision
316+control system. At their root, clay's merges are similar to
317+git's, but with some additions to accomodate typed data. There
318+are seven different merge strategies.
319+
320+Throughout our discussion, we'll say that the merge is from
321+Alice's desk to Bob's. Recall that a commit is a date (for all
322+new commits this will be the current date), a list of parents,
323+and the data itself.
324+
325+A `%init` merge should be used iff it's the first commit to a
326+desk. The head of Alice's desk is used as the number 1 commit to
327+Bob's desk. Obviously, the ancestry remains intact through
328+traversing the parentage of the commit even though previous
329+commits are not numbered for Bob's desk.
330+
331+A `%this` merge means to keep what's in Bob's desk, but join the
332+ancestry. Thus, the new commit has the head of each desk as
333+parents, but the data is exactly what's in Bob's desk. For those
334+following along in git, this is the 'ours' merge strategy, not
335+the '--ours' option to the 'recursive' merge strategy. In other
336+words, even if Alice makes a change that does not conflict with
337+Bob, we throw it away. It's Bob's way or the highway.
338+
339+A `%that` merge means to take what's in Alice's desk, but join
340+the ancestry. This is the reverse of `%this`.
341+
342+A `%fine` merge is a "fast-forward" merge. This succeeds iff one
343+head is in the ancestry of the other. In this case, we use the
344+descendant as our new head.
345+
346+For `%meet`, `%mate`, and `%meld` merges, we first find the most
347+recent common ancestor to use as our merge base. If we have no
348+common ancestors, then we fail. If we have more than one most
349+recent common ancestor, then we have a criss-cross situation,
350+which should be handled delicately. At present, we delicately
351+throw up our hands and give up, but something akin to git's
352+'recursive' strategy should be implemented in the future.
353+
354+There's a functional inclusion ordering on `%fine`, `%meet`,
355+`%mate`, and `%meld` such that if an earlier strategy would have
356+succeeded, then every later strategy will produce the same
357+result. Put another way, every earlier strategy is the same as
358+every later strategy except with a restricted domain.
359+
360+A `%meet` merge only succeeds if the changes from the merge base
361+to Alice's head (hereafter, "Alice's changes") are in different
362+files than Bob's changes. In this case, the parents are both
363+Alice's and Bob's heads, and the data is the merge base plus
364+Alice's changed files plus Bob's changed files.
365+
366+A `%mate` merge attempts to merge changes to the same file when
367+both Alice and bob change it. If the merge is clean, we use it;
368+otherwise, we fail. A merge between different types of changes --
369+for example, deleting a file vs changing it -- is always a
370+conflict. If we succeed, the parents are both Alice's and Bob's
371+heads, and the data is the merge base plus Alice's changed files
372+plus Bob's changed files plus the merged files.
373+
374+A `%meld` merge will succeed even if there are conflicts. If
375+there are conflicts in a file, then we use the merge base's
376+version of that file, and we produce a set of files with
377+conflicts. The parents are both Alice's and Bob's heads, and the
378+data is the merge base plus Alice's changed files plus Bob's
379+changed files plus the successfully merged files plus the merge
380+base's version of the conflicting files.
381+
382+That's the extent of the merge options in clay proper. In
383+userspace there's a final option `%auto`, which is the most
384+common. `%auto` checks to see if Bob's desk exists, and if it
385+doesn't we use a `%init` merge. Otherwise, we progressively try
386+`%fine`, `%meet`, and `%mate` until one succeeds.
387+
388+If none succeed, we merge Bob's desk into a scratch desk. Then,
389+we merge Alice's desk into the scratch desk with the `%meld`
390+option to force the merge. For each file in the produced set of
391+conflicting files, we call the `++mash` function for the
392+appropriate mark, which annotates the conflicts if we know how.
393+
394+Finally, we display a message to the user informing them of the
395+scratch desk's existence, which files have annotated conflicts,
396+and which files have unannotated conflicts. When the user has
397+resolved the conflicts, they can merge the scratch desk back into
398+Bob's desk. This will be a `%fine` merge since Bob's head is in
399+the ancestry of the scratch desk.
400+
401+### Autosync
402+
403+Tracking and staying in sync with another desk is another
404+fundamental operation. We call this "autosync". This doesn't mean
405+simply mirroring a desk, since that wouldn't allow local changes.
406+We simply want to apply changes as they are made upstream, as
407+long as there are no conflicts with local changes.
408+
409+This is implemented by watching the other desk, and, when it has
410+changes, merging these changes into our desk with the usual merge
411+strategies.
412+
413+Note that it's quite reasonable for two desks to be autosynced to
414+each other. This results in any change on one desk being mirrored
415+to the other and vice versa.
416+
417+Additionally, it's fine to set up an autosync even if one desk,
418+the other desk, or both desks do not exist. The sync will be
419+activated when the upstream desk comes into existence and will
420+create the downstream desk if needed.
docs/arvo/internals/clay/commentary.mdnew file+2012
@@ -0,0 +1,2012 @@
1+---
2+navhome: /docs
3+---
4+
5+
6+`%clay` commentary
7+==================
8+
9+`%clay` is our filesystem.
10+
11+The first part of this will be reference documentation for the data
12+types used by our filesystem. In fact, as a general guide, we recommend
13+reading and attempting to understand the data structures used in any
14+Hoon code before you try to read the code itself. Although complete
15+understanding of the data structures is impossible without seeing them
16+used in the code, an 80% understanding greatly clarifies the code. As
17+another general guide, when reading Hoon, it rarely pays off to
18+understand every line of code when it appears. Try to get the gist of
19+it, and then move on. The next time you come back to it, it'll likely
20+make a lot more sense.
21+
22+After a description of the data models, we'll give an overview of the
23+interface that vanes and applications can use to interact with the
24+filesystem.
25+
26+Finally, we'll dive into the code and the algorithms themselves. You
27+know, the fun part.
28+
29+Data Models
30+-----------
31+
32+As you're reading through this section, remember you can always come
33+back to this when you run into these types later on. You're not going to
34+remember everything the first time through, but it is worth reading, or
35+at least skimming, this so that you get a rough idea of how our state is
36+organized.
37+
38+The types that are certainly worth reading are `++raft`, `++room`,
39+`++dome`, `++ankh`, `++rung`, `++rang`, `++blob`, `++yaki`, and `++nori`
40+(possibly in that order). All in all, though, this section isn't too
41+long, so many readers may wish to quickly read through all of it. If you
42+get bored, though, just skip to the next section. You can always come
43+back when you need to.
44+
45+### `++raft`, formal state
46+
47+ ++ raft :: filesystem
48+ $: fat=(map ship room) :: domestic
49+ hoy=(map ship rung) :: foreign
50+ ran=rang :: hashes
51+ == ::
52+
53+This is the state of our vane. Anything that must be remembered between
54+calls to clay is stored in this state.
55+
56+`fat` is the set of domestic servers. This stores all the information
57+that is specfic to a particular ship on this pier. The keys to this map
58+are the ships on the current pier. all the information that is specific
59+to a particular foreign ship. The keys to this map are all the ships
60+whose filesystems we have attempted to access through clay.
61+
62+`ran` is the store of all commits and deltas, keyed by hash. The is
63+where all the "real" data we know is stored; the rest is "just
64+bookkeeping".
65+
66+### `++room`, filesystem per domestic ship
67+
68+ ++ room :: fs per ship
69+ $: hun=duct :: terminal duct
70+ hez=(unit duct) :: sync duch
71+ dos=(map desk dojo) :: native desk
72+ == ::
73+
74+This is the representation of the filesystem of a ship on our pier.
75+
76+`hun` is the duct we use to send messages to dill to display
77+notifications of filesystem changes. Only `%note` gifts should be
78+produced along this duct. This is set by the `%init` kiss.
79+
80+`hez`, if present, is the duct we use to send sync messages to unix so
81+that they end up in the pier unix directory. Only `%ergo` gifts should
82+be producd along this duct. This is set by `%into` and `%invo` kisses.
83+
84+`dos` is a well-known operating system released in 1981. It is also the
85+set of desks on this ship, mapped to their data.
86+
87+### `++desk`, filesystem branch
88+
89+ ++ desk ,@tas :: ship desk case spur
90+
91+This is the name of a branch of the filesystem. The default desks are
92+"arvo", "main", and "try". More may be created by simply referencing
93+them. Desks have independent histories and states, and they may be
94+merged into each other.
95+
96+### `++dojo`, domestic desk state
97+
98+ ++ dojo ,[p=cult q=dome] :: domestic desk state
99+
100+This is the all the data that is specific to a particular desk on a
101+domestic ship. `p` is the set of subscribers to this desk and `q` is the
102+data in the desk.
103+
104+### `++cult`, subscriptions
105+
106+ ++ cult (map duct rave) :: subscriptions
107+
108+This is the set of subscriptions to a particular desk. The keys are the
109+ducts from where the subscriptions requests came. The results will be
110+produced along these ducts. The values are a description of the
111+requested information.
112+
113+### `++rave`, general subscription request
114+
115+ ++ rave :: general request
116+ $% [& p=mood] :: single request
117+ [| p=moat] :: change range
118+ == ::
119+
120+This represents a subscription request for a desk. The request can be
121+for either a single item in the desk or else for a range of changes on
122+the desk.
123+
124+### `++rove`, stored general subscription request
125+
126+ ++ rove (each mood moot) :: stored request
127+
128+When we store a request, we store subscriptions with a little extra
129+information so that we can determine whether new versions actually
130+affect the path we're subscribed to.
131+
132+### `++mood`, single subscription request
133+
134+ ++ mood ,[p=care q=case r=path] :: request in desk
135+
136+This represents a request for the state of the desk at a particular
137+commit, specfied by `q`. `p` specifies what kind of information is
138+desired, and `r` specifies the path we are requesting.
139+
140+### `++moat`, range subscription request
141+
142+ ++ moat ,[p=case q=case r=path] :: change range
143+
144+This represents a request for all changes between `p` and `q` on path
145+`r`. You will be notified when a change is made to the node referenced
146+by the path or to any of its children.
147+
148+### `++moot`, stored range subscription request
149+
150+ ++ moot ,[p=case q=case r=path s=(map path lobe)] ::
151+
152+This is just a `++moat` plus a map of paths to lobes. This map
153+represents the data at the node referenced by the path at case `p`, if
154+we've gotten to that case (else null). We only send a notification along
155+the subscription if the data at a new revision is different than it was.
156+
157+### `++care`, clay submode
158+
159+ ++ care ?(%u %v %w %x %y %z) :: clay submode
160+
161+This specifies what type of information is requested in a subscription
162+or a scry.
163+
164+`%u` requests the `++rang` at the current moment. Because this
165+information is not stored for any moment other than the present, we
166+crash if the `++case` is not a `%da` for now.
167+
168+`%v` requests the `++dome` at the specified commit.
169+
170+`%w` requests the revsion number of the desk.
171+
172+`%x` requests the file at a specified path at the specified commit. If
173+there is no node at that path or if the node has no contents (that is,
174+if `q:ankh` is null), then this produces null.
175+
176+`%y` requests a `++arch` of the specfied commit at the specified path.
177+
178+`%z` requests the `++ankh` of the specified commit at the specfied path.
179+
180+### `++arch`, shallow filesystem node
181+
182+ ++ arch ,[p=@uvI q=(unit ,@uvI) r=(map ,@ta ,~)] :: fundamental node
183+
184+This is analogous to `++ankh` except that the we have neither our
185+contents nor the ankhs of our children. The other fields are exactly the
186+same, so `p` is a hash of the associated ankh, `u.q`, if it exists, is a
187+hash of the contents of this node, and the keys of `r` are the names of
188+our children. `r` is a map to null rather than a set so that the
189+ordering of the map will be equivalent to that of `r:ankh`, allowing
190+efficient conversion.
191+
192+### `++case`, specifying a commit
193+
194+ ++ case :: ship desk case spur
195+ $% [%da p=@da] :: date
196+ [%tas p=@tas] :: label
197+ [%ud p=@ud] :: number
198+ == ::
199+
200+A commit can be referred to in three ways: `%da` refers to the commit
201+that was at the head on date `p`, `%tas` refers to the commit labeled
202+`p`, and `%ud` refers to the commit numbered `p`. Note that since these
203+all can be reduced down to a `%ud`, only numbered commits may be
204+referenced with a `++case`.
205+
206+### `++dome`, desk data
207+
208+ ++ dome :: project state
209+ $: ang=agon :: pedigree
210+ ank=ankh :: state
211+ let=@ud :: top id
212+ hit=(map ,@ud tako) :: changes by id
213+ lab=(map ,@tas ,@ud) :: labels
214+ == ::
215+
216+This is the data that is actually stored in a desk.
217+
218+`ang` is unused and should be removed.
219+
220+`ank` is the current state of the desk. Thus, it is the state of the
221+filesystem at revison `let`. The head of a desk is always a numbered
222+commit.
223+
224+`let` is the number of the most recently numbered commit. This is also
225+the total number of numbered commits.
226+
227+`hit` is a map of numerical ids to hashes of commits. These hashes are
228+mapped into their associated commits in `hut:rang`. In general, the keys
229+of this map are exactly the numbers from 1 to `let`, with no gaps. Of
230+course, when there are no numbered commits, `let` is 0, so `hit` is
231+null. Additionally, each of the commits is an ancestor of every commit
232+numbered greater than this one. Thus, each is a descendant of every
233+commit numbered less than this one. Since it is true that the date in
234+each commit (`t:yaki`) is no earlier than that of each of its parents,
235+the numbered commits are totally ordered in the same way by both
236+pedigree and date. Of course, not every commit is numbered. If that
237+sounds too complicated to you, don't worry about it. It basically
238+behaves exactly as you would expect.
239+
240+`lab` is a map of textual labels to numbered commits. Note that labels
241+can only be applied to numbered commits. Labels must be unique across a
242+desk.
243+
244+### `++ankh`, filesystem node
245+
246+ ++ ankh :: fs node (new)
247+ $: p=cash :: recursive hash
248+ q=(unit ,[p=cash q=*]) :: file
249+ r=(map ,@ta ankh) :: folders
250+ == ::
251+
252+This is a single node in the filesystem. This may be file or a directory
253+or both. In earth filesystems, a node is a file xor a directory. On
254+mars, we're inclusive, so a node is a file ior a directory.
255+
256+`p` is a recursive hash that depends on the contents of the this file or
257+directory and on any children.
258+
259+`q` is the contents of this file, if any. `p.q` is a hash of the
260+contents while `q.q` is the data itself.
261+
262+`r` is the set of children of this node. In the case of a pure file,
263+this is empty. The keys are the names of the children and the values
264+are, recursively, the nodes themselves.
265+
266+### `++cash`, ankh hash
267+
268+ ++ cash ,@uvH :: ankh hash
269+
270+This is a 128-bit hash of an ankh. These are mostly stored within ankhs
271+themselves, and they are used to check for changes in possibly-deep
272+hierarchies.
273+
274+### `++rung`, filesystem per neighbor ship
275+
276+ ++ rung $: rus=(map desk rede) :: neighbor desks
277+ == ::
278+
279+This is the filesystem of a neighbor ship. The keys to this map are all
280+the desks we know about on their ship.
281+
282+### `++rede`, desk state
283+
284+ ++ rede :: universal project
285+ $: lim=@da :: complete to
286+ qyx=cult :: subscribers
287+ ref=(unit rind) :: outgoing requests
288+ dom=dome :: revision state
289+ == ::
290+
291+This is our knowledge of the state of a desk, either foreign or
292+domestic.
293+
294+`lim` is the date of the last full update. We only respond to requests
295+for stuff before this time.
296+
297+`qyx` is the list of subscribers to this desk. For domestic desks, this
298+is simply `p:dojo`, all subscribers to the desk, while in foreign desks
299+this is all the subscribers from our ship to the foreign desk.
300+
301+`ref` is the request manager for the desk. For domestic desks, this is
302+null since we handle requests ourselves.
303+
304+`dom` is the actual data in the desk.
305+
306+### `++rind`, request manager
307+
308+ ++ rind :: request manager
309+ $: nix=@ud :: request index
310+ bom=(map ,@ud ,[p=duct q=rave]) :: outstanding
311+ fod=(map duct ,@ud) :: current requests
312+ haw=(map mood (unit)) :: simple cache
313+ == ::
314+
315+This is the request manager for a foreign desk.
316+
317+`nix` is one more than the index of the most recent request. Thus, it is
318+the next available request number.
319+
320+`bom` is the set of outstanding requests. The keys of this map are some
321+subset of the numbers between 0 and one less than `nix`. The members of
322+the map are exactly those requests that have not yet been fully
323+satisfied.
324+
325+`fod` is the same set as `bom`, but from a different perspective. In
326+particular, the values of `fod` are the same as the values of `bom`, and
327+the `p` out of the values of `bom` are the same as the keys of `fod`.
328+Thus, we can map ducts to their associated request number and `++rave`,
329+and we can map numbers to their associated duct and `++rave`.
330+
331+`haw` is a map from simple requests to their values. This acts as a
332+cache for requests that have already been made. Thus, the second request
333+for a particular `++mood` is nearly instantaneous.
334+
335+### `++rang`, data store
336+
337+ ++ rang $: hut=(map tako yaki) ::
338+ lat=(map lobe blob) ::
339+ == ::
340+
341+This is a set of data keyed by hash. Thus, this is where the "real" data
342+is stored, but it is only meaningful if we know the hash of what we're
343+looking for.
344+
345+`hut` is a map from hashes to commits. We often get the hashes from
346+`hit:dome`, which keys them by logical id. Not every commit has an id.
347+
348+`lat` is a map from hashes to the actual data. We often get the hashes
349+from a `++yaki`, a commit, which references this map to get the data.
350+There is no `++blob` in any `++yaki`. They are only accessible through
351+this map.
352+
353+### `++tako`, commit reference
354+
355+ ++ tako ,@ :: yaki ref
356+
357+This is a hash of a `++yaki`, a commit. These are most notably used as
358+the keys in `hut:rang`, where they are associated with the actual
359+`++yaki`, and as the values in `hit:dome`, where sequential ids are
360+associated with these.
361+
362+### `++yaki`, commit
363+
364+ ++ yaki ,[p=(list tako) q=(map path lobe) r=tako t=@da] :: commit
365+
366+This is a single commit.
367+
368+`p` is a list of the hashes of the parents of this commit. In most
369+cases, this will be a single commit, but in a merge there may be more
370+parents. In theory, there may be an arbitrary number of parents, but in
371+practice merges have exactly two parents. This may change in the future.
372+For commit 1, there is no parent.
373+
374+`q` is a map of the paths on a desk to the data at that location. If you
375+understand what a `++lobe` and a `++blob` is, then the type signature
376+here tells the whole story.
377+
378+`r` is the hash associated with this commit.
379+
380+`t` is the date at which this commit was made.
381+
382+### `++lobe`, data reference
383+
384+ ++ lobe ,@ :: blob ref
385+
386+This is a hash of a `++blob`. These are most notably used in `lat:rang`,
387+where they are associated with the actual `++blob`, and as the values in
388+`q:yaki`, where paths are associated with their data in a commit.
389+
390+### `++blob`, data
391+
392+ ++ blob $% [%delta p=lobe q=lobe r=udon] :: delta on q
393+ [%direct p=lobe q=* r=umph] ::
394+ [%indirect p=lobe q=* r=udon s=lobe] ::
395+ == ::
396+
397+This is a node of data. In every case, `p` is the hash of the blob.
398+
399+`%delta` is the case where we define the data by a delta on other data.
400+In practice, the other data is always the previous commit, but nothing
401+depends on this. `q` is the hash of the parent blob, and `r` is the
402+delta.
403+
404+`%direct` is the case where we simply have the data directly. `q` is the
405+data itself, and `r` is any preprocessing instructions. These almost
406+always come from the creation of a file.
407+
408+`%indirect` is both of the preceding cases at once. `q` is the direct
409+data, `r` is the delta, and `s` is the parent blob. It should always be
410+the case that applying `r` to `s` gives the same data as `q` directly
411+(with the prepreprocessor instructions in `p.r`). This exists purely for
412+performance reasons. This is unused, at the moment, but in general these
413+should be created when there are a long line of changes so that we do
414+not have to traverse the delta chain back to the creation of the file.
415+
416+### `++udon`, abstract delta
417+
418+ ++ udon :: abstract delta
419+ $: p=umph :: preprocessor
420+ $= q :: patch
421+ $% [%a p=* q=*] :: trivial replace
422+ [%b p=udal] :: atomic indel
423+ [%c p=(urge)] :: list indel
424+ [%d p=upas q=upas] :: tree edit
425+ == ::
426+ == ::
427+
428+This is an abstract change to a file. This is a superset of what would
429+normally be called diffs. Diffs usually refer to changes in lines of
430+text while we have the ability to do more interesting deltas on
431+arbitrary data structures.
432+
433+`p` is any preprocessor instructions.
434+
435+`%a` refers to the trival delta of a complete replace of old data with
436+new data.
437+
438+`%b` refers to changes in an opaque atom on the block level. This has
439+very limited usefulness, and is not used at the moment.
440+
441+`%c` refers to changes in a list of data. This is often lines of text,
442+which is your classic diff. We, however, will work on any list of data.
443+
444+`%d` refers to changes in a tree of data. This is general enough to
445+describe changes to any hoon noun, but often more special-purpose delta
446+should be created for different content types. This is not used at the
447+moment, and may in fact be unimplemented.
448+
449+### `++urge`, list change
450+
451+ ++ urge |*(a=_,* (list (unce a))) :: list change
452+
453+This is a parametrized type for list changes. For example, `(urge ,@t)`
454+is a list change for lines of text.
455+
456+### `++unce`, change part of a list.
457+
458+ ++ unce |* a=_,* :: change part
459+ $% [%& p=@ud] :: skip[copy]
460+ [%| p=(list a) q=(list a)] :: p -> q[chunk]
461+ == ::
462+
463+This is a single change in a list of elements of type `a`. For example,
464+`(unce ,@t)` is a single change in a lines of text.
465+
466+`%&` means the next `p` lines are unchanged.
467+
468+`%|` means the lines `p` have changed to `q`.
469+
470+### `++umph`, preprocessing information
471+
472+ ++ umph :: change filter
473+ $| $? %a :: no filter
474+ %b :: jamfile
475+ %c :: LF text
476+ == ::
477+ $% [%d p=@ud] :: blocklist
478+ == ::
479+
480+This space intentionally left undocumented. This stuff will change once
481+we get a well-typed clay.
482+
483+### `++upas`, tree change
484+
485+ ++ upas :: tree change (%d)
486+ $& [p=upas q=upas] :: cell
487+ $% [%0 p=axis] :: copy old
488+ [%1 p=*] :: insert new
489+ [%2 p=axis q=udon] :: mutate!
490+ == ::
491+
492+This space intentionally left undocumented. This stuff is not known to
493+work, and will likely change when we get a well-typed clay. Also, this
494+is not a complicated type; it is not difficult to work out the meaning.
495+
496+### `++nori`, repository action
497+
498+ ++ nori :: repository action
499+ $% [& q=soba] :: delta
500+ [| p=@tas] :: label
501+ == ::
502+
503+This describes a change that we are asking clay to make to the desk.
504+There are two kinds of changes that may be made: we can modify files or
505+we can apply a label to a commit.
506+
507+In the `|` case, we will simply label the current commit with the given
508+label. In the `&` case, we will apply the given changes.
509+
510+### `++soba`, delta
511+
512+ ++ soba ,[p=cart q=(list ,[p=path q=miso])] :: delta
513+
514+This describes a set of changes to make to a desk. The `cart` is simply
515+a pair of the old hash and the new hash of the desk. The list is a list
516+of changes keyed by the file they're changing. Thus, the paths are paths
517+to files to be changed while `miso` is a description of the change
518+itself.
519+
520+### `++miso`, ankh delta
521+
522+ ++ miso :: ankh delta
523+ $% [%del p=*] :: delete
524+ [%ins p=*] :: insert
525+ [%mut p=udon] :: mutate
526+ == ::
527+
528+There are three kinds of changes that may be made to a node in a desk.
529+We can insert a file, in which case `p` is the contents of the new file.
530+We can delete a file, in which case `p` is the contents of the old file.
531+Finally, we can mutate that file, in which case the `udon` describes the
532+changes we are applying to the file.
533+
534+### `++mizu`, merged state
535+
536+ ++ mizu ,[p=@u q=(map ,@ud tako) r=rang] :: new state
537+
538+This is the input to the `%merg` kiss, which allows us to perform a
539+merge. The `p` is the number of the new head commit. The `q` is a map
540+from numbers to commit hashes. This is all the new numbered commits that
541+are to be inserted. The keys to this should always be the numbers from
542+`let.dom` plus one to `p`, inclusive. The `r` is the maps of all the new
543+commits and data. Since these are merged into the current state, no old
544+commits or data need be here.
545+
546+### `++riff`, request/desist
547+
548+ ++ riff ,[p=desk q=(unit rave)] :: request/desist
549+
550+This represents a request for data about a particular desk. If `q`
551+contains a `rave`, then this opens a subscription to the desk for that
552+data. If `q` is null, then this tells clay to cancel the subscription
553+along this duct.
554+
555+### `++riot`, response
556+
557+ ++ riot (unit rant) :: response/complete
558+
559+A riot is a response to a subscription. If null, the subscription has
560+been completed, and no more responses will be sent. Otherwise, the
561+`rant` is the produced data.
562+
563+### `++rant`, response data
564+
565+ ++ rant :: namespace binding
566+ $: p=[p=care q=case r=@tas] :: clade release book
567+ q=path :: spur
568+ r=* :: data
569+ == ::
570+
571+This is the data at a particular node in the filesystem. `p.p` specifies
572+the type of data that was requested (and is produced). `q.p` gives the
573+specific version reported (since a range of versions may be requested in
574+a subscription). `r.p` is the desk. `q` is the path to the filesystem
575+node. `r` is the data itself (in the format specified by `p.p`).
576+
577+### `++nako`, subscription response data
578+
579+ ++ nako $: gar=(map ,@ud tako) :: new ids
580+ let=@ud :: next id
581+ lar=(set yaki) :: new commits
582+ bar=(set blob) :: new content
583+ == ::
584+
585+This is the data that is produced by a request for a range of revisions
586+of a desk. This allows us to easily keep track of a remote repository --
587+all the new information we need is contained in the `nako`.
588+
589+`gar` is a map of the revisions in the range to the hash of the commit
590+at that revision. These hashes can be used with `hut:rang` to find the
591+commit itself.
592+
593+`let` is either the last revision number in the range or the most recent
594+revision number, whichever is smaller.
595+
596+`lar` is the set of new commits, and `bar` is the set of new content.
597+
598+Public Interface
599+----------------
600+
601+As with all vanes, there are exactly two ways to interact with clay.
602+`%clay` exports a namespace accessible through `.^`, which is described
603+above under `++care`. The primary way of interacting with clay, though,
604+is by sending kisses and receiving gifts.
605+
606+ ++ gift :: out result <-$
607+ $% [%ergo p=@p q=@tas r=@ud] :: version update
608+ [%note p=@tD q=tank] :: debug message
609+ [%writ p=riot] :: response
610+ == ::
611+ ++ kiss :: in request ->$
612+ $% [%info p=@p q=@tas r=nori] :: internal edit
613+ [%ingo p=@p q=@tas r=nori] :: internal noun edit
614+ [%init p=@p] :: report install
615+ [%into p=@p q=@tas r=nori] :: external edit
616+ [%invo p=@p q=@tas r=nori] :: external noun edit
617+ [%merg p=@p q=@tas r=mizu] :: internal change
618+ [%wart p=sock q=@tas r=path s=*] :: network request
619+ [%warp p=sock q=riff] :: file request
620+ == ::
621+
622+There are only a small number of possible kisses, so it behooves us to
623+describe each in detail.
624+
625+ $% [%info p=@p q=@tas r=nori] :: internal edit
626+
627+ [%into p=@p q=@tas r=nori] :: external edit
628+
629+These two kisses are nearly identical. At a high level, they apply
630+changes to the filesystem. Whenever we add, remove, or edit a file, one
631+of these cards is sent. The `p` is the ship whose filesystem we're
632+trying to change, the `q` is the desk we're changing, and the `r` is the
633+request change. For the format of the requested change, see the
634+documentation for `++nori` above.
635+
636+When a file is changed in the unix filesystem, vere will send a `%into`
637+kiss. This tells clay that the duct over which the kiss was sent is the
638+duct that unix is listening on for changes. From within Arvo, though, we
639+should never send a `%into` kiss. The `%info` kiss is exactly identical
640+except it does not reset the duct.
641+
642+ [%ingo p=@p q=@tas r=nori] :: internal noun edit
643+
644+ [%invo p=@p q=@tas r=nori] :: external noun edit
645+
646+These kisses are currently identical to `%info` and `%into`, though this
647+will not always be the case. The intent is for these kisses to allow
648+typed changes to clay so that we may store typed data. This is currently
649+unimplemented.
650+
651+ [%init p=@p] :: report install
652+
653+Init is called when a ship is started on our pier. This simply creates a
654+default `room` to go into our `raft`. Essentially, this initializes the
655+filesystem for a ship.
656+
657+ [%merg p=@p q=@tas r=mizu] :: internal change
658+
659+This is called to perform a merge. This is most visibly called by
660+:update to update the filesystem of the current ship to that of its
661+sein. The `p` and `q` are as in `%info`, and the `r` is the description
662+of the merge. See `++mizu` above.
663+
664+XX
665+`XX [%wake ~] :: timer activate XX`
666+XX\
667+XX This card is sent by unix at the time specified by `++doze`. This
668+time is XX usually the closest time specified in a subscription request.
669+When `%wake` is XX called, we update our subscribers if there have been
670+any changes.
671+
672+ [%wart p=sock q=@tas r=path s=*] :: network request
673+
674+This is a request that has come across the network for a particular
675+file. When another ship asks for a file from us, that request comes to
676+us in the form of a `%wart` kiss. This is handled by trivially turning
677+it into a `%warp`.
678+
679+ [%warp p=sock q=riff] :: file request
680+
681+This is a request for information about a particular desk. This is, in
682+its most general form, a subscription, though in many cases it is the
683+trivial case of a subscription -- a read. See `++riff` for the format of
684+the request.
685+
686+Lifecycle of a Local Read
687+-------------------------
688+
689+There are two real types of interaction with a filesystem: you can read,
690+and you can write. We'll describe each process, detailing both the flow
691+of control followed by the kernel and the algorithms involved. The
692+simpler case is that of the read, so we'll begin with that.
693+
694+When a vane or an application wishes to read a file from the filesystem,
695+it sends a `%warp` kiss, as described above. Of course, you may request
696+a file on another ship and, being a global filesystem, clay will happily
697+produce it for you. That code pathway will be described in another
698+section; here, we will restrict ourselves to examining the case of a
699+read from a ship on our own pier.
700+
701+The kiss can request either a single version of a file node or a range
702+of versions of a desk. Here, we'll deal only with a request for a single
703+version.
704+
705+As in all vanes, a kiss enters clay via a call to `++call`. Scanning
706+through the arm, we quickly see where `%warp` is handled.
707+
708+ ?: =(p.p.q.hic q.p.q.hic)
709+ =+ une=(un p.p.q.hic now ruf)
710+ =+ wex=(di:une p.q.q.hic)
711+ =+ ^= wao
712+ ?~ q.q.q.hic
713+ (ease:wex hen)
714+ (eave:wex hen u.q.q.q.hic)
715+ =+ ^= woo
716+ abet:wao
717+ [-.woo abet:(pish:une p.q.q.hic +.woo ran.wao)]
718+
719+We're following the familar patern of producing a list of moves and an
720+updated state. In this case, the state is `++raft`.
721+
722+We first check to see if the sending and receiving ships are the same.
723+If they're not, then this is a request for data on another ship. We
724+describe that process later. Here, we discuss only the case of a local
725+read.
726+
727+At a high level, the call to `++un` sets up the core for the domestic
728+ship that contains the files we're looking for. The call to `++di` sets
729+up the core for the particular desk we're referring to.
730+
731+After this, we perform the actual request. If there is no rave in the
732+riff, then that means we are cancelling a request, so we call
733+`++ease:de`. Otherwise, we start a subscription with `++eave:de`. We
734+call `++abet:de` to resolve our various types of output into actual
735+moves. We produce the moves we found above and the `++un` core resolved
736+with `++pish:un` (putting the modified desk in the room) and `++abet:un`
737+(putting the modified room in the raft).
738+
739+Much of this is fairly straightforward, so we'll only describe `++ease`,
740+`++eave`, and `++abet:de`. Feel free to look up the code to the other
741+steps -- it should be easy to follow.
742+
743+Although it's called last, it's usually worth examining `++abet` first,
744+since it defines in what ways we can cause side effects. Let's do that,
745+and also a few of the lines at the beginning of `++de`.
746+
747+ =| yel=(list ,[p=duct q=gift])
748+ =| byn=(list ,[p=duct q=riot])
749+ =| vag=(list ,[p=duct q=gift])
750+ =| say=(list ,[p=duct q=path r=ship s=[p=@ud q=riff]])
751+ =| tag=(list ,[p=duct q=path c=note])
752+ |%
753+ ++ abet
754+ ^- [(list move) rede]
755+ :_ red
756+ ;: weld
757+ %+ turn (flop yel)
758+ |=([a=duct b=gift] [hun %give b])
759+ ::
760+ %+ turn (flop byn)
761+ |=([a=duct b=riot] [a %give [%writ b]])
762+ ::
763+ %+ turn (flop vag)
764+ |=([a=duct b=gift] [a %give b])
765+ ::
766+ %+ turn (flop say)
767+ |= [a=duct b=path c=ship d=[p=@ud q=riff]]
768+ :- a
769+ [%pass b %a %want [who c] [%q %re p.q.d (scot %ud p.d) ~] q.d]
770+ ::
771+ %+ turn (flop tag)
772+ |=([a=duct b=path c=note] [a %pass b c])
773+ ==
774+
775+This is very simple code. We see there are exactly five different kinds
776+of side effects we can generate.
777+
778+In `yel` we put gifts that we wish to be sent along the `hun:room` duct
779+to dill. See the documentation for `++room` above. This is how we
780+display messages to the terminal.
781+
782+In `byn` we put riots that we wish returned to subscribers. Recall that
783+a riot is a response to a subscription. These are returned to our
784+subscribers in the form of a `%writ` gift.
785+
786+In `vag` we put gifts along with the ducts on which to send them. This
787+allows us to produce arbitrary gifts, but in practice this is only used
788+to produce `%ergo` gifts.
789+
790+In `say` we put messages we wish to pass to ames. These messages are
791+used to request information from clay on other piers. We must provide
792+not only the duct and the request (the riff), but also the return path,
793+the other ship to talk to, and the sequence number of the request.
794+
795+In `tag` we put arbitrary notes we wish to pass to other vanes. For now,
796+the only notes we pass here are `%wait` and `%rest` to the timer vane.
797+
798+Now that we know what kinds of side effects we may have, we can jump
799+into the handling of requests.
800+
801+ ++ ease :: release request
802+ |= hen=duct
803+ ^+ +>
804+ ?~ ref +>
805+ =+ rov=(~(got by qyx) hen)
806+ =. qyx (~(del by qyx) hen)
807+ (mabe rov (cury best hen))
808+ =. qyx (~(del by qyx) hen)
809+ |- ^+ +>+.$
810+ =+ nux=(~(get by fod.u.ref) hen)
811+ ?~ nux +>+.$
812+ %= +>+.$
813+ say [[hen [(scot %ud u.nux) ~] for [u.nux syd ~]] say]
814+ fod.u.ref (~(del by fod.u.ref) hen)
815+ bom.u.ref (~(del by bom.u.ref) u.nux)
816+ ==
817+
818+This is called when we're cancelling a subscription. For domestic desks,
819+`ref` is null, so we're going to cancel any timer we might have created.
820+We first delete the duct from our map of requests, and then we call
821+`++mabe` with `++best` to send a `%rest` kiss to the timer vane if we
822+have started a timer. We'll describe `++best` and `++mabe` momentarily.
823+
824+Although we said we're not going to talk about foreign requests yet,
825+it's easy to see that for foreign desks, we cancel any outstanding
826+requests for this duct and send a message over ames to the other ship
827+telling them to cancel the subscription.
828+
829+ ++ best
830+ |= [hen=duct tym=@da]
831+ %_(+> tag :_(tag [hen /tyme %t %rest tym]))
832+
833+This simply pushes a `%rest` note onto `tag`, from where it will be
834+passed back to arvo to be handled. This cancels the timer at the given
835+duct (with the given time).
836+
837+ ++ mabe :: maybe fire function
838+ |* [rov=rove fun=$+(@da _+>.^$)]
839+ ^+ +>.$
840+ %- fall :_ +>.$
841+ %- bind :_ fun
842+ ^- (unit ,@da)
843+ ?- -.rov
844+ %&
845+ ?. ?=(%da -.q.p.rov) ~
846+ `p.q.p.rov
847+ %|
848+ =* mot p.rov
849+ %+ hunt
850+ ?. ?=(%da -.p.mot) ~
851+ ?.((lth now p.p.mot) ~ [~ p.p.mot])
852+ ?. ?=(%da -.q.mot) ~
853+ ?.((lth now p.q.mot) [~ now] [~ p.q.mot])
854+ ==
855+
856+This decides whether the given request can only be satsified in the
857+future. In that case, we call the given function with the time in the
858+future when we expect to have an update to give to this request. This is
859+called with `++best` to cancel timers and with `++bait` to start them.
860+
861+For single requests, we have a time if the request is for a particular
862+time (which is assumed to be in the future). For ranges of requests, we
863+check both the start and end cases to see if they are time cases. If so,
864+we choose the earlier time.
865+
866+If any of those give us a time, then we call the given funciton with the
867+smallest time.
868+
869+The more interesting case is, of course, when we're not cancelling a
870+subscription but starting one.
871+
872+ ++ eave :: subscribe
873+ |= [hen=duct rav=rave]
874+ ^+ +>
875+ ?- -.rav
876+ &
877+ ?: &(=(p.p.rav %u) !=(p.q.p.rav now))
878+ ~& [%clay-fail p.q.p.rav %now now]
879+ !!
880+ =+ ver=(aver p.rav)
881+ ?~ ver
882+ (duce hen rav)
883+ ?~ u.ver
884+ (blub hen)
885+ (blab hen p.rav u.u.ver)
886+
887+There are two types of subscriptions -- either we're requesting a single
888+file or we're requesting a range of versions of a desk. We'll dicuss the
889+simpler case first.
890+
891+First, we check that we're not requesting the `rang` from any time other
892+than the present. Since we don't store that information for any other
893+time, we can't produce it in a referentially transparent manner for any
894+time other than the present.
895+
896+Then, we try to read the requested `mood` `p.rav`. If we can't access
897+the request data right now, we call `++duce` to put the request in our
898+queue to be satisfied when the information becomes available.
899+
900+This case occurs when we make a request for a case whose (1) date is
901+after the current date, (2) number is after the current number, or (3)
902+label is not yet used.
903+
904+ ++ duce :: produce request
905+ |= [hen=duct rov=rove]
906+ ^+ +>
907+ =. qyx (~(put by qyx) hen rov)
908+ ?~ ref
909+ (mabe rov (cury bait hen))
910+ |- ^+ +>+.$ :: XX why?
911+ =+ rav=(reve rov)
912+ =+ ^= vaw ^- rave
913+ ?. ?=([%& %v *] rav) rav
914+ [%| [%ud let.dom] `case`q.p.rav r.p.rav]
915+ =+ inx=nix.u.ref
916+ %= +>+.$
917+ say [[hen [(scot %ud inx) ~] for [inx syd ~ vaw]] say]
918+ nix.u.ref +(nix.u.ref)
919+ bom.u.ref (~(put by bom.u.ref) inx [hen vaw])
920+ fod.u.ref (~(put by fod.u.ref) hen inx)
921+ ==
922+
923+The code for `++duce` is nearly the exact inverse of `++ease`, which in
924+the case of a domestic desk is very simple -- we simply put the duct and
925+rave into `qyx` and possibly start a timer with `++mabe` and `++bait`.
926+Recall that `ref` is null for domestic desks and that `++mabe` fires the
927+given function with the time we need to be woken up at, if we need to be
928+woken up at a particular time.
929+
930+ ++ bait
931+ |= [hen=duct tym=@da]
932+ %_(+> tag :_(tag [hen /tyme %t %wait tym]))
933+
934+This sets an alarm by sending a `%wait` card with the given time to the
935+timer vane.
936+
937+Back in `++eave`, if `++aver` returned `[~ ~]`, then we cancel the
938+subscription. This occurs when we make (1) a `%x` request for a file
939+that does not exist, (2) a `%w` request with a case that is not a
940+number, or (3) a `%w` request with a nonempty path. The `++blub` is
941+exactly what you would expect it to be.
942+
943+ ++ blub :: ship stop
944+ |= hen=duct
945+ %_(+> byn [[hen ~] byn])
946+
947+We notify the duct that we're cancelling their subscription since it
948+isn't satisfiable.
949+
950+Otherwise, we have received the desired information, so we send it on to
951+the subscriber with `++blab`.
952+
953+ ++ blab :: ship result
954+ |= [hen=duct mun=mood dat=*]
955+ ^+ +>
956+ +>(byn [[hen ~ [p.mun q.mun syd] r.mun dat] byn])
957+
958+The most interesting arm called in `++eave` is, of course, `++aver`,
959+where we actually try to read the data.
960+
961+ ++ aver :: read
962+ |= mun=mood
963+ ^- (unit (unit ,*))
964+ ?: &(=(p.mun %u) !=(p.q.mun now)) :: prevent bad things
965+ ~& [%clay-fail p.q.mun %now now]
966+ !!
967+ =+ ezy=?~(ref ~ (~(get by haw.u.ref) mun))
968+ ?^ ezy ezy
969+ =+ nao=(~(case-to-aeon ze lim dom ran) q.mun)
970+ ?~(nao ~ [~ (~(read-at-aeon ze lim dom ran) u.nao mun)])
971+
972+We check immediately that we're not requesting the `rang` for any time
973+other than the present.
974+
975+If this is a foreign desk, then we check our cache for the specific
976+request. If either this is a domestic desk or we don't have the request
977+in our cache, then we have to actually go read the data from our dome.
978+
979+We need to do two things. First, we try to find the number of the commit
980+specified by the given case, and then we try to get the data there.
981+
982+Here, we jump into `arvo/zuse.hoon`, which is where much of the
983+algorithmic code is stored, as opposed to the clay interface, which is
984+stored in `arvo/clay.hoon`. We examine `++case-to-aeon:ze`.
985+
986+ ++ case-to-aeon :: case-to-aeon:ze
987+ |= lok=case :: act count through
988+ ^- (unit aeon)
989+ ?- -.lok
990+ %da
991+ ?: (gth p.lok lim) ~
992+ |- ^- (unit aeon)
993+ ?: =(0 let) [~ 0] :: avoid underflow
994+ ?: %+ gte p.lok
995+ =< t
996+ %- tako-to-yaki
997+ %- aeon-to-tako
998+ let
999+ [~ let]
1000+ $(let (dec let))
1001+ ::
1002+ %tas (~(get by lab) p.lok)
1003+ %ud ?:((gth p.lok let) ~ [~ p.lok])
1004+ ==
1005+
1006+We handle each type of `case` differently. The latter two types are
1007+easy.
1008+
1009+If we're requesting a revision by label, then we simply look up the
1010+requested label in `lab` from the given dome. If it exists, that is our
1011+aeon; else we produce null, indicating the requested revision does not
1012+yet exist.
1013+
1014+If we're requesting a revision by number, we check if we've yet reached
1015+that number. If so, we produce the number; else we produce null.
1016+
1017+If we're requesting a revision by date, we check first if the date is in
1018+the future, returning null if so. Else we start from the most recent
1019+revision and scan backwards until we find the first revision committed
1020+before that date, and we produce that. If we requested a date before any
1021+revisions were committed, we produce `0`.
1022+
1023+The definitions of `++aeon-to-tako` and `++tako-to-yaki` are trivial.
1024+
1025+ ++ aeon-to-tako ~(got by hit)
1026+
1027+ ++ tako-to-yaki ~(got by hut) :: grab yaki
1028+
1029+We simply look up the aeon or tako in their respective maps (`hit` and
1030+`hut`).
1031+
1032+Assuming we got a valid version number, `++aver` calls
1033+`++read-at-aeon:ze`, which reads the requested data at the given
1034+revision.
1035+
1036+ ++ read-at-aeon :: read-at-aeon:ze
1037+ |= [oan=aeon mun=mood] :: seek and read
1038+ ^- (unit)
1039+ ?: &(?=(%w p.mun) !?=(%ud -.q.mun)) :: NB only for speed
1040+ ?^(r.mun ~ [~ oan])
1041+ (read:(rewind oan) mun)
1042+
1043+If we're requesting the revision number with a case other than by
1044+number, then we go ahead and just produce the number we were given.
1045+Otherwise, we call `++rewind` to rewind our state to the given revision,
1046+and then we call `++read` to get the requested information.
1047+
1048+ ++ rewind :: rewind:ze
1049+ |= oan=aeon :: rewind to aeon
1050+ ^+ +>
1051+ ?: =(let oan) +>
1052+ ?: (gth oan let) !! :: don't have version
1053+ +>(ank (checkout-ankh q:(tako-to-yaki (aeon-to-tako oan))), let oan)
1054+
1055+If we're already at the requested version, we do nothing. If we're
1056+requesting a version later than our head, we are unable to comply.
1057+
1058+Otherwise, we get the hash of the commit at the number, and from that we
1059+get the commit itself (the yaki), which has the map of path to lobe that
1060+represents a version of the filesystem. We call `++checkout-ankh` to
1061+checkout the commit, and we replace `ank` in our context with the
1062+result.
1063+
1064+ ++ checkout-ankh :: checkout-ankh:ze
1065+ |= hat=(map path lobe) :: checkout commit
1066+ ^- ankh
1067+ %- cosh
1068+ %+ roll (~(tap by hat) ~)
1069+ |= [[pat=path bar=lobe] ank=ankh]
1070+ ^- ankh
1071+ %- cosh
1072+ ?~ pat
1073+ =+ zar=(lobe-to-noun bar)
1074+ ank(q [~ (sham zar) zar])
1075+ =+ nak=(~(get by r.ank) i.pat)
1076+ %= ank
1077+ r %+ ~(put by r.ank) i.pat
1078+ $(pat t.pat, ank (fall nak _ankh))
1079+ ==
1080+
1081+Twice we call `++cosh`, which hashes a commit, updating `p` in an
1082+`ankh`. Let's jump into that algorithm before we describe
1083+`++checkout-ankh`.
1084+
1085+ ++ cosh :: locally rehash
1086+ |= ank=ankh :: NB v/unix.c
1087+ ank(p rehash:(zu ank))
1088+
1089+We simply replace `p` in the hash with the `cash` we get from a call to
1090+`++rehash:zu`.
1091+
1092+ ++ zu !: :: filesystem
1093+ |= ank=ankh :: filesystem state
1094+ =| myz=(list ,[p=path q=miso]) :: changes in reverse
1095+ =| ram=path :: reverse path into
1096+ |%
1097+ ++ rehash :: local rehash
1098+ ^- cash
1099+ %+ mix ?~(q.ank 0 p.u.q.ank)
1100+ =+ axe=1
1101+ |- ^- cash
1102+ ?~ r.ank _@
1103+ ;: mix
1104+ (shaf %dash (mix axe (shaf %dush (mix p.n.r.ank p.q.n.r.ank))))
1105+ $(r.ank l.r.ank, axe (peg axe 2))
1106+ $(r.ank r.r.ank, axe (peg axe 3))
1107+ ==
1108+
1109+`++zu` is a core we set up with a particular filesystem node to traverse
1110+a checkout of the filesystem and access the actual data inside it. One
1111+of the things we can do with it is to create a recursive hash of the
1112+node.
1113+
1114+In `++rehash`, if this node is a file, then we xor the remainder of the
1115+hash with the hash of the contents of the file. The remainder of the
1116+hash is `0` if we have no children, else we descend into our children.
1117+Basically, we do a half SHA-256 of the xor of the axis of this child and
1118+the half SHA-256 of the xor of the name of the child and the hash of the
1119+child. This is done for each child and all the results are xored
1120+together.
1121+
1122+Now we return to our discussion of `++checkout-ankh`.
1123+
1124+We fold over every path in this version of the filesystem and create a
1125+great ankh out of them. First, we call `++lobe-to-noun` to get the raw
1126+data referred to be each lobe.
1127+
1128+ ++ lobe-to-noun :: grab blob
1129+ |= p=lobe :: ^- *
1130+ %- blob-to-noun
1131+ (lobe-to-blob p)
1132+
1133+This converts a lobe into the raw data it refers to by first getting the
1134+blob with `++lobe-to-blob` and converting that into data with
1135+`++blob-to-noun`.
1136+
1137+ ++ lobe-to-blob ~(got by lat) :: grab blob
1138+
1139+This just grabs the blob that the lobe refers to.
1140+
1141+ ++ blob-to-noun :: grab blob
1142+ |= p=blob
1143+ ?- -.p
1144+ %delta (lump r.p (lobe-to-noun q.p))
1145+ %direct q.p
1146+ %indirect q.p
1147+ ==
1148+
1149+If we have either a direct or an indirect blob, then the data is stored
1150+right in the blob. Otherwise, we have to reconstruct it from the diffs.
1151+We do this by calling `++lump` on the diff in the blob with the data
1152+obtained by recursively calling the parent of this blob.
1153+
1154+ ++ lump :: apply patch
1155+ |= [don=udon src=*]
1156+ ^- *
1157+ ?+ p.don ~|(%unsupported !!)
1158+ %a
1159+ ?+ -.q.don ~|(%unsupported !!)
1160+ %a q.q.don
1161+ %c (lurk ((hard (list)) src) p.q.don)
1162+ %d (lure src p.q.don)
1163+ ==
1164+ ::
1165+ %c
1166+ =+ dst=(lore ((hard ,@) src))
1167+ %- roly
1168+ ?+ -.q.don ~|(%unsupported !!)
1169+ %a ((hard (list ,@t)) q.q.don)
1170+ %c (lurk dst p.q.don)
1171+ ==
1172+ ==
1173+
1174+This is defined in `arvo/hoon.hoon` for historical reasons which are
1175+likely no longer applicable. Since the `++umph` structure will likely
1176+change we convert clay to be a typed filesystem, we'll only give a
1177+high-level description of this process. If we have a `%a` udon, then
1178+we're performing a trivial replace, so we produce simply `q.q.don`. If
1179+we have a `%c` udon, then we're performing a list merge (as in, for
1180+example, lines of text). The merge is performed by `++lurk`.
1181+
1182+ ++ lurk :: apply list patch
1183+ |* [hel=(list) rug=(urge)]
1184+ ^+ hel
1185+ =+ war=`_hel`~
1186+ |- ^+ hel
1187+ ?~ rug (flop war)
1188+ ?- -.i.rug
1189+ &
1190+ %= $
1191+ rug t.rug
1192+ hel (slag p.i.rug hel)
1193+ war (weld (flop (scag p.i.rug hel)) war)
1194+ ==
1195+ ::
1196+ |
1197+ %= $
1198+ rug t.rug
1199+ hel =+ gur=(flop p.i.rug)
1200+ |- ^+ hel
1201+ ?~ gur hel
1202+ ?>(&(?=(^ hel) =(i.gur i.hel)) $(hel t.hel, gur t.gur))
1203+ war (weld q.i.rug war)
1204+ ==
1205+ ==
1206+
1207+We accumulate our final result in `war`. If there's nothing more in our
1208+list of merge instructions (unces), we just reverse `war` and produce
1209+it. Otherwise, we process another unce. If the unce is of type `&`, then
1210+we have `p.i.rug` lines of no changes, so we just copy them over from
1211+`hel` to `war`. If the unice is of type `|`, then we verify that the
1212+source lines (in `hel`) are what we expect them to be (`p.i.rug`),
1213+crashing on failure. If they're good, then we append the new lines in
1214+`q.i.rug` onto `war`.
1215+
1216+And that's really it. List merges are pretty easy. Anyway, if you
1217+recall, we were discussing `++checkout-ankh`.
1218+
1219+ ++ checkout-ankh :: checkout-ankh:ze
1220+ |= hat=(map path lobe) :: checkout commit
1221+ ^- ankh
1222+ %- cosh
1223+ %+ roll (~(tap by hat) ~)
1224+ |= [[pat=path bar=lobe] ank=ankh]
1225+ ^- ankh
1226+ %- cosh
1227+ ?~ pat
1228+ =+ zar=(lobe-to-noun bar)
1229+ ank(q [~ (sham zar) zar])
1230+ =+ nak=(~(get by r.ank) i.pat)
1231+ %= ank
1232+ r %+ ~(put by r.ank) i.pat
1233+ $(pat t.pat, ank (fall nak _ankh))
1234+ ==
1235+
1236+If the path is null, then we calculate `zar`, the raw data at the path
1237+`pat` in this version. We produce the given ankh with the correct data.
1238+
1239+Otherwise, we try to get the child we're looking at from our parent
1240+ankh. If it's already been created, this succeeds; otherwise, we simply
1241+create a default blank ankh. We place ourselves in our parent after
1242+recursively computing our children.
1243+
1244+This algorithm really isn't that complicated, but it may not be
1245+immediately obvious why it works. An example should clear everything up.
1246+
1247+Suppose `hat` is a map of the following information.
1248+
1249+ /greeting --> "customary upon meeting"
1250+ /greeting/english --> "hello"
1251+ /greeting/spanish --> "hola"
1252+ /greeting/russian/short --> "привет"
1253+ /greeting/russian/long --> "Здравствуйте"
1254+ /farewell/russian --> "до свидания"
1255+
1256+Furthermore, let's say that we process them in this order:
1257+
1258+ /greeting/english
1259+ /greeting/russian/short
1260+ /greeting/russian/long
1261+ /greeting
1262+ /greeting/spanish
1263+ /farewell/russian
1264+
1265+Then, the first path we process is `/greeting/english` . Since our path
1266+is not null, we try to get `nak`, but because our ankh is blank at this
1267+point it doesn't find anything. Thus, update our blank top-level ankh
1268+with a child `%greeting`. and recurse with the blank `nak` to create the
1269+ankh of the new child.
1270+
1271+In the recursion, we our path is `/english` and our ankh is again blank.
1272+We try to get the `english` child of our ankh, but this of course fails.
1273+Thus, we update our blank `/greeting` ankh with a child `english`
1274+produced by recursing.
1275+
1276+Now our path is null, so we call `++lobe-to-noun` to get the actual
1277+data, and we place it in the brand-new ankh.
1278+
1279+Next, we process `/greeting/russian/short`. Since our path is not null,
1280+we try to get the child named `%greeting`, which does exist since we
1281+created it earlier. We put modify this child by recursing on it. Our
1282+path is now `/russian/short`, so we look for a `%russian` child in our
1283+`/greeting` ankh. This doesn't exist, so we add it by recursing. Our
1284+path is now `/short`, so we look for a `%short` child in our
1285+`/greeting/russian` ankh. This doesn't exist, so we add it by recursing.
1286+Now our path is null, so we set the contents of this node to `"привет"`,
1287+and we're done processing this path.
1288+
1289+Next, we process `/greeting/russian/long`. This proceeds similarly to
1290+the previous except that now the ankh for `/greeting/russian` already
1291+exists, so we simply reuse it rather than creating a new one. Of course,
1292+we still must create a new `/greeting/russian/long` ankh.
1293+
1294+Next, we process `/greeting`. This ankh already exists, so after we've
1295+recursed once, our path is null, and our ankh is not blank -- it already
1296+has two children (and two grandchildren). We don't touch those, though,
1297+since a node may be both a file and a directory. We just add the
1298+contents of the file -- "customary upon meeting" -- to the existing
1299+ankh.
1300+
1301+Next, we process `/greeting/spanish`. Of course, the `/greeting` ankh
1302+already exists, but it doesn't have a `%spanish` child, so we create
1303+that, taking care not to disturb the contents of the `/greeting` file.
1304+We put "hola" into the ankh and call it good.
1305+
1306+Finally, we process `/farewell/russian`. Here, the `/farewell` ankh
1307+doesn't exist, so we create it. Clearly the newly-created ankh doesn't
1308+have any children, so we have to add a `%russian` child, and in this
1309+child we put our last content -- "до свидания".
1310+
1311+We hope it's fairly obvious that the order we process the paths doesn't
1312+affect the final ankh tree. The tree will be constructed in a very
1313+different order depending on what order the paths come in, but the
1314+resulting tree is independent of order.
1315+
1316+At any rate, we were talking about something important, weren't we? If
1317+you recall, that concludes our discussion of `++rewind`, which was
1318+called from `++read-at-aeon`. In summary, `++rewind` returns a context
1319+in which our current state is (very nearly) as it was when the specified
1320+version of the desk was the head. This allows `++read-at-aeon` to call
1321+`++read` to read the requested information.
1322+
1323+ ++ read :: read:ze
1324+ |= mun=mood :: read at point
1325+ ^- (unit)
1326+ ?: ?=(%v p.mun)
1327+ [~ `dome`+<+<.read]
1328+ ?: &(?=(%w p.mun) !?=(%ud -.q.mun))
1329+ ?^(r.mun ~ [~ let])
1330+ ?: ?=(%w p.mun)
1331+ =+ ^= yak
1332+ %- tako-to-yaki
1333+ %- aeon-to-tako
1334+ let
1335+ ?^(r.mun ~ [~ [t.yak (forge-nori yak)]])
1336+ ::?> ?=(^ hit) ?^(r.mun ~ [~ i.hit]) :: what do?? need [@da nori]
1337+ (query(ank ank:(descend-path:(zu ank) r.mun)) p.mun)
1338+
1339+If we're requesting the dome, then we just return that immediately.
1340+
1341+If we're requesting the revision number of the desk and we're not
1342+requesting it by number, then we just return the current number of this
1343+desk. Note of course that this was really already handled in
1344+`++read-at-aeon`.
1345+
1346+If we're requesting a `%w` with a specific revision number, then we do
1347+something or other with the commit there. It's kind of weird, and it
1348+doesn't seem to work, so we'll ignore this case.
1349+
1350+Otherwise, we descend into the ankh tree to the given path with
1351+`++descend-path:zu`, and then we handle specific request in `++query`.
1352+
1353+ ++ descend-path :: descend recursively
1354+ |= way=path
1355+ ^+ +>
1356+ ?~(way +> $(way t.way, +> (descend i.way)))
1357+
1358+This is simple recursion down into the ankh tree. `++descend` descends
1359+one level, so this will eventually get us down to the path we want.
1360+
1361+ ++ descend :: descend
1362+ |= lol=@ta
1363+ ^+ +>
1364+ =+ you=(~(get by r.ank) lol)
1365+ +>.$(ram [lol ram], ank ?~(you [*cash ~ ~] u.you))
1366+
1367+`ram` is the path that we're at, so to descend one level we push the
1368+name of this level onto that path. We update the ankh with the correct
1369+one at that path if it exists; else we create a blank one.
1370+
1371+Once we've decscended to the correct level, we need to actually deal
1372+with the request.
1373+
1374+ ++ query :: query:ze
1375+ |= ren=?(%u %v %x %y %z) :: endpoint query
1376+ ^- (unit ,*)
1377+ ?- ren
1378+ %u [~ `rang`+<+>.query]
1379+ %v [~ `dome`+<+<.query]
1380+ %x ?~(q.ank ~ [~ q.u.q.ank])
1381+ %y [~ as-arch]
1382+ %z [~ ank]
1383+ ==
1384+
1385+Now that everything's set up, it's really easy. If they're requesting
1386+the rang, dome, or ankh, we give it to them. If the contents of a file,
1387+we give it to them if it is in fact a file. If the `arch`, then we
1388+calculate it with `++as-arch`.
1389+
1390+ ++ as-arch :: as-arch:ze
1391+ ^- arch :: arch report
1392+ :+ p.ank
1393+ ?~(q.ank ~ [~ p.u.q.ank])
1394+ |- ^- (map ,@ta ,~)
1395+ ?~ r.ank ~
1396+ [[p.n.r.ank ~] $(r.ank l.r.ank) $(r.ank r.r.ank)]
1397+
1398+This very simply strips out all the "real" data and returns just our own
1399+hash, the hash of the file contents (if we're a file), and a map of the
1400+names of our immediate children.
1401+
1402+Lifecycle of a Local Subscription
1403+---------------------------------
1404+
1405+A subscription to a range of revisions of a desk initially follows the
1406+same path that a single read does. In `++aver`, we checked the head of
1407+the given rave. If the head was `&`, then it was a single request, so we
1408+handled it above. If `|`, then we handle it with the following code.
1409+
1410+ =+ nab=(~(case-to-aeon ze lim dom ran) p.p.rav)
1411+ ?~ nab
1412+ ?> =(~ (~(case-to-aeon ze lim dom ran) q.p.rav))
1413+ (duce hen (rive rav))
1414+ =+ huy=(~(case-to-aeon ze lim dom ran) q.p.rav)
1415+ ?: &(?=(^ huy) |((lth u.huy u.nab) &(=(0 u.huy) =(0 u.nab))))
1416+ (blub hen)
1417+ =+ top=?~(huy let.dom u.huy)
1418+ =+ sar=(~(lobes-at-path ze lim dom ran) u.nab r.p.rav)
1419+ =+ ear=(~(lobes-at-path ze lim dom ran) top r.p.rav)
1420+ =. +>.$
1421+ ?: =(sar ear) +>.$
1422+ =+ fud=(~(make-nako ze lim dom ran) u.nab top)
1423+ (bleb hen u.nab fud)
1424+ ?^ huy
1425+ (blub hen)
1426+ =+ ^= ptr ^- case
1427+ [%ud +(let.dom)]
1428+ (duce hen `rove`[%| ptr q.p.rav r.p.rav ear])
1429+ ==
1430+
1431+Recall that `++case-to-aeon:ze` produces the revision number that a case
1432+corresponds to, if it corresponds to any. If it doesn't yet correspond
1433+to a revision, then it produces null.
1434+
1435+Thus, we first check to see if we've even gotten to the beginning of the
1436+range of revisions requested. If not, then we assert that we haven't yet
1437+gotten to the end of the range either, because that would be really
1438+strange. If not, then we immediately call `++duce`, which, if you
1439+recall, for a local request, simply puts this duct and rove into our
1440+cult `qyx`, so that we know who to respond to when the revision does
1441+appear.
1442+
1443+If we've already gotten to the first revision, then we can produce some
1444+content immediately. If we've also gotten to the final revision, and
1445+that revision is earlier than the start revision, then it's a bad
1446+request and we call `++blub`, which tells the subscriber that his
1447+subscription will not be satisfied.
1448+
1449+Otherwise, we find the data at the given path at the beginning of the
1450+subscription and at the last available revision in the subscription. If
1451+they're the same, then we don't send a notification. Otherwise, we call
1452+`++gack`, which creates the `++nako` we need to produce. We call
1453+`++bleb` to actually produce the information.
1454+
1455+If we already have the last requested revision, then we also tell the
1456+subscriber with `++blub` that the subscription will receive no further
1457+updates.
1458+
1459+If there will be more revisions in the subscription, then we call
1460+`++duce`, adding the duct to our subscribers. We modify the rove to
1461+start at the next revision since we've already handled all the revisions
1462+up to the present.
1463+
1464+We glossed over the calls to `++lobes-at-path`, `++make-nako`, and
1465+`++bleb`, so we'll get back to those right now. `++bleb` is simple, so
1466+we'll start with that.
1467+
1468+ ++ bleb :: ship sequence
1469+ |= [hen=duct ins=@ud hip=nako]
1470+ ^+ +>
1471+ (blab hen [%w [%ud ins] ~] hip)
1472+
1473+We're given a duct, the beginning revision number, and the nako that
1474+contains the updates since that revision. We use `++blab` to produce
1475+this result to the subscriber. The case is `%w` with a revision number
1476+of the beginning of the subscription, and the data is the nako itself.
1477+
1478+We call `++lobes-at-path:ze` to get the data at the particular path.
1479+
1480+ ++ lobes-at-path :: lobes-at-path:ze
1481+ |= [oan=aeon pax=path] :: data at path
1482+ ^- (map path lobe)
1483+ ?: =(0 oan) ~
1484+ %- mo
1485+ %+ skim
1486+ %. ~
1487+ %~ tap by
1488+ =< q
1489+ %- tako-to-yaki
1490+ %- aeon-to-tako
1491+ oan
1492+ |= [p=path q=lobe]
1493+ ?| ?=(~ pax)
1494+ ?& !?=(~ p)
1495+ =(-.pax -.p)
1496+ $(p +.p, pax +.pax)
1497+ == ==
1498+
1499+At revision zero, the theoretical common revision between all
1500+repositories, there is no data, so we produce null.
1501+
1502+We get the list of paths (paired with their lobe) in the revision
1503+referred to by the given number and we keep only those paths which begin
1504+with `pax`. Converting to a map, we now have a map from the subpaths at
1505+the given path to the hash of their data. This is simple and efficient
1506+to calculate and compare to later revisions. This allows us to easily
1507+tell if a node or its children have changed.
1508+
1509+Finally, we will describe `++make-nako:ze`.
1510+
1511+ ++ make-nako :: gack a through b
1512+ |= [a=aeon b=aeon]
1513+ ^- [(map aeon tako) aeon (set yaki) (set blob)]
1514+ :_ :- b
1515+ =- [(takos-to-yakis -<) (lobes-to-blobs ->)]
1516+ %+ reachable-between-takos
1517+ (~(get by hit) a) :: if a not found, a=0
1518+ (aeon-to-tako b)
1519+ ^- (map aeon tako)
1520+ %- mo %+ skim (~(tap by hit) ~)
1521+ |= [p=aeon *]
1522+ &((gth p a) (lte p b))
1523+
1524+We need to produce four things -- the numbers of the new commits, the
1525+number of the latest commit, the new commits themselves, and the new
1526+data itself.
1527+
1528+The first is fairly easy to produce. We simply go over our map of
1529+numbered commits and produce all those numbered greater than `a` and not
1530+greater than `b`.
1531+
1532+The second is even easier to produce -- `b` is clearly our most recent
1533+commit.
1534+
1535+The third and fourth are slightly more interesting, though not too
1536+terribly difficult. First, we call `++reachable-between-takos`.
1537+
1538+ ++ reachable-between-takos
1539+ |= [a=(unit tako) b=tako] :: pack a through b
1540+ ^- [(set tako) (set lobe)]
1541+ =+ ^= sar
1542+ ?~ a ~
1543+ (reachable-takos r:(tako-to-yaki u.a))
1544+ =+ yak=`yaki`(tako-to-yaki b)
1545+ %+ new-lobes-takos (new-lobes ~ sar) :: get lobes
1546+ |- ^- (set tako) :: walk onto sar
1547+ ?: (~(has in sar) r.yak)
1548+ ~
1549+ =+ ber=`(set tako)`(~(put in `(set tako)`~) `tako`r.yak)
1550+ %- ~(uni in ber)
1551+ ^- (set tako)
1552+ %+ roll p.yak
1553+ |= [yek=tako bar=(set tako)]
1554+ ^- (set tako)
1555+ ?: (~(has in bar) yek) :: save some time
1556+ bar
1557+ %- ~(uni in bar)
1558+ ^$(yak (tako-to-yaki yek))
1559+
1560+We take a possible starting commit and a definite ending commit, and we
1561+produce the set of commits and the set of data between them.
1562+
1563+We let `sar` be the set of commits reachable from `a`. If `a` is null,
1564+then obviously no commits are reachable. Otherwise, we call
1565+`++reachable-takos` to calculate this.
1566+
1567+ ++ reachable-takos :: reachable
1568+ |= p=tako :: XX slow
1569+ ^- (set tako)
1570+ =+ y=(tako-to-yaki p)
1571+ =+ t=(~(put in _(set tako)) p)
1572+ %+ roll p.y
1573+ |= [q=tako s=_t]
1574+ ?: (~(has in s) q) :: already done
1575+ s :: hence skip
1576+ (~(uni in s) ^$(p q)) :: otherwise traverse
1577+
1578+We very simply produce the set of the given tako plus its parents,
1579+recursively.
1580+
1581+Back in `++reachable-between-takos`, we let `yak` be the yaki of `b`,
1582+the ending commit. With this, we create a set that is the union of `sar`
1583+and all takos reachable from `b`.
1584+
1585+We pass `sar` into `++new-lobes` to get all the lobes referenced by any
1586+tako referenced by `a`. The result is passed into `++new-lobes-takos` to
1587+do the same, but not recomputing those in already calculated last
1588+sentence. This produces the sets of takos and lobes we need.
1589+
1590+ ++ new-lobes :: object hash set
1591+ |= [b=(set lobe) a=(set tako)] :: that aren't in b
1592+ ^- (set lobe)
1593+ %+ roll (~(tap in a) ~)
1594+ |= [tak=tako bar=(set lobe)]
1595+ ^- (set lobe)
1596+ =+ yak=(tako-to-yaki tak)
1597+ %+ roll (~(tap by q.yak) ~)
1598+ |= [[path lob=lobe] far=_bar]
1599+ ^- (set lobe)
1600+ ?~ (~(has in b) lob) :: don't need
1601+ far
1602+ =+ gar=(lobe-to-blob lob)
1603+ ?- -.gar
1604+ %direct (~(put in far) lob)
1605+ %delta (~(put in $(lob q.gar)) lob)
1606+ %indirect (~(put in $(lob s.gar)) lob)
1607+ ==
1608+
1609+Here, we're creating a set of lobes referenced in a commit in `a`. We
1610+start out with `b` as the initial set of lobes, so we don't need to
1611+recompute any of the lobes referenced in there.
1612+
1613+The algorithm is pretty simple, so we won't bore you with the details.
1614+We simply traverse every commit in `a`, looking at every blob referenced
1615+there, and, if it's not already in `b`, we add it to `b`. In the case of
1616+a direct blob, we're done. For a delta or an indirect blob, we
1617+recursively add every blob referenced within the blob.
1618+
1619+ ++ new-lobes-takos :: garg & repack
1620+ |= [b=(set lobe) a=(set tako)]
1621+ ^- [(set tako) (set lobe)]
1622+ [a (new-lobes b a)]
1623+
1624+Here, we just update the set of lobes we're given with the commits we're
1625+given and produce both sets.
1626+
1627+This concludes our discussion of a local subscription.
1628+
1629+Lifecycle of a Foreign Read or Subscription
1630+-------------------------------------------
1631+
1632+Foreign reads and subscriptions are handled in much the same way as
1633+local ones. The interface is the same -- a vane or app sends a `%warp`
1634+kiss with the request. The difference is simply that the `sock` refers
1635+to the foreign ship.
1636+
1637+Thus, we start in the same place -- in `++call`, handling `%warp`.
1638+However, since the two side of the `sock` are different, we follow a
1639+different path.
1640+
1641+ =+ wex=(do now p.q.hic p.q.q.hic ruf)
1642+ =+ ^= woo
1643+ ?~ q.q.q.hic
1644+ abet:(ease:wex hen)
1645+ abet:(eave:wex hen u.q.q.q.hic)
1646+ [-.woo (posh q.p.q.hic p.q.q.hic +.woo ruf)]
1647+
1648+If we compare this to how the local case was handled, we see that it's
1649+not all that different. We use `++do` rather than `++un` and `++de` to
1650+set up the core for the foreign ship. This gives us a `++de` core, so we
1651+either cancel or begin the request by calling `++ease` or `++eave`,
1652+exactly as in the local case. In either case, we call `++abet:de` to
1653+resolve our various types of output into actual moves, as described in
1654+the local case. Finally, we call `++posh` to update our raft, putting
1655+the modified rung into the raft.
1656+
1657+We'll first trace through `++do`.
1658+
1659+ ++ do
1660+ |= [now=@da [who=ship him=ship] syd=@tas ruf=raft]
1661+ =+ ^= rug ^- rung
1662+ =+ rug=(~(get by hoy.ruf) him)
1663+ ?^(rug u.rug *rung)
1664+ =+ ^= red ^- rede
1665+ =+ yit=(~(get by rus.rug) syd)
1666+ ?^(yit u.yit `rede`[~2000.1.1 ~ [~ *rind] *dome])
1667+ ((de now ~ ~) [who him] syd red ran.ruf)
1668+
1669+If we already have a rung for this foreign ship, then we use that.
1670+Otherwise, we create a new blank one. If we already have a rede in this
1671+rung, then we use that, otherwise we create a blank one. An important
1672+point to note here is that we let `ref` in the rede be `[~ *rind]`.
1673+Recall, for domestic desks `ref` is null. We use this to distinguish
1674+between foreign and domestic desks in `++de`.
1675+
1676+With this information, we create a `++de` core as usual.
1677+
1678+Although we've already covered `++ease` and `++eave`, we'll go through
1679+them quickly again, highlighting the case of foreign request.
1680+
1681+ ++ ease :: release request
1682+ |= hen=duct
1683+ ^+ +>
1684+ ?~ ref +>
1685+ =+ rov=(~(got by qyx) hen)
1686+ =. qyx (~(del by qyx) hen)
1687+ (mabe rov (cury best hen))
1688+ =. qyx (~(del by qyx) hen)
1689+ |- ^+ +>+.$
1690+ =+ nux=(~(get by fod.u.ref) hen)
1691+ ?~ nux +>+.$
1692+ %= +>+.$
1693+ say [[hen [(scot %ud u.nux) ~] for [u.nux syd ~]] say]
1694+ fod.u.ref (~(del by fod.u.ref) hen)
1695+ bom.u.ref (~(del by bom.u.ref) u.nux)
1696+ ==
1697+
1698+Here, we still remove the duct from our cult (we maintain a cult even
1699+for foreign desks), but we also need to tell the foreign desk to cancel
1700+our subscription. We do this by sending a request (by appending to
1701+`say`, which gets resolved in `++abet:de` to a `%want` kiss to ames) to
1702+the foreign ship to cancel the subscription. Since we don't anymore
1703+expect a response on this duct, we remove it from `fod` and `bom`, which
1704+are the maps between ducts, raves, and request sequence numbers.
1705+Basically, we remove every trace of the subscription from our request
1706+manager.
1707+
1708+In the case of `++eave`, where we're creating a new request, everything
1709+is exactly identical to the case of the local request except `++duce`.
1710+We said that `++duce` simply puts the request into our cult. This is
1711+true for a domestic request, but distinctly untrue for foreign requests.
1712+
1713+ ++ duce :: produce request
1714+ |= [hen=duct rov=rove]
1715+ ^+ +>
1716+ =. qyx (~(put by qyx) hen rov)
1717+ ?~ ref +>.$
1718+ |- ^+ +>+.$ :: XX why?
1719+ =+ rav=(reve rov)
1720+ =+ ^= vaw ^- rave
1721+ ?. ?=([%& %v *] rav) rav
1722+ [%| [%ud let.dom] `case`q.p.rav r.p.rav]
1723+ =+ inx=nix.u.ref
1724+ %= +>+.$
1725+ say [[hen [(scot %ud inx) ~] for [inx syd ~ vaw]] say]
1726+ nix.u.ref +(nix.u.ref)
1727+ bom.u.ref (~(put by bom.u.ref) inx [hen vaw])
1728+ fod.u.ref (~(put by fod.u.ref) hen inx)
1729+ ==
1730+
1731+If we have a request manager (i.e. this is a foreign desk), then we do
1732+the approximate inverse of `++ease`. We create a rave out of the given
1733+request and send it off to the foreign desk by putting it in `say`. Note
1734+that the rave is created to request the information starting at the next
1735+revision number. Since this is a new request, we put it into `fod` and
1736+`bom` to associate the request with its duct and its sequence number.
1737+Since we're using another sequence number, we must increment `nix`,
1738+which represents the next available sequence number.
1739+
1740+And that's really it for this side of the request. Requesting foreign
1741+information isn't that hard. Let's see what it looks like on the other
1742+side. When we get a request from another ship for information on our
1743+ship, that comes to us in the form of a `%wart` from ames.
1744+
1745+We handle a `%wart` in `++call`, right next to where we handle the
1746+`%warp` case.
1747+
1748+ %wart
1749+ ?> ?=(%re q.q.hic)
1750+ =+ ryf=((hard riff) s.q.hic)
1751+ :_ ..^$
1752+ :~ :- hen
1753+ :^ %pass [(scot %p p.p.q.hic) (scot %p q.p.q.hic) r.q.hic]
1754+ %c
1755+ [%warp [p.p.q.hic p.p.q.hic] ryf]
1756+ ==
1757+
1758+Every request we receive should be of type `riff`, so we coerce it into
1759+that type. We just convert this into a new `%warp` kiss that we pass to
1760+ourself. This gets handled like normal, as a local request. When the
1761+request produces a value, it does so like normal as a `%writ`, which is
1762+returned to `++take` along the path we just sent it on.
1763+
1764+ %writ
1765+ ?> ?=([@ @ *] tea)
1766+ =+ our=(need (slaw %p i.tea))
1767+ =+ him=(need (slaw %p i.t.tea))
1768+ :_ ..^$
1769+ :~ :- hen
1770+ [%pass ~ %a [%want [our him] [%r %re %c t.t.tea] p.+.q.hin]]
1771+ ==
1772+
1773+Since we encoded the ship we need to respond to in the path, we can just
1774+pass our `%want` back to ames, so that we tell the requesting ship about
1775+the new data.
1776+
1777+This comes back to the original ship as a `%waft` from ames, which comes
1778+into `++take`, right next to where we handled `%writ`.
1779+
1780+ %waft
1781+ ?> ?=([@ @ ~] tea)
1782+ =+ syd=(need (slaw %tas i.tea))
1783+ =+ inx=(need (slaw %ud i.t.tea))
1784+ =+ ^= zat
1785+ =< wake
1786+ (knit:(do now p.+.q.hin syd ruf) [inx ((hard riot) q.+.q.hin)])
1787+ =^ mos ruf
1788+ =+ zot=abet.zat
1789+ [-.zot (posh q.p.+.q.hin syd +.zot ruf)]
1790+ [mos ..^$(ran.ruf ran.zat)] :: merge in new obj
1791+
1792+This gets the desk and sequence number from the path the request was
1793+sent over. This determines exactly which request is being responded to.
1794+We call `++knit:de` to apply the changes to our local desk, and we call
1795+`++wake` to update our subscribers. Then we call `++abet:de` and
1796+`++posh` as normal (like in `++eave`).
1797+
1798+We'll examine `++knit` and `++wake`, in that order.
1799+
1800+ ++ knit :: external change
1801+ |= [inx=@ud rot=riot]
1802+ ^+ +>
1803+ ?> ?=(^ ref)
1804+ |- ^+ +>+.$
1805+ =+ ruv=(~(get by bom.u.ref) inx)
1806+ ?~ ruv +>+.$
1807+ => ?. |(?=(~ rot) ?=(& -.q.u.ruv)) .
1808+ %_ .
1809+ bom.u.ref (~(del by bom.u.ref) inx)
1810+ fod.u.ref (~(del by fod.u.ref) p.u.ruv)
1811+ ==
1812+ ?~ rot
1813+ =+ rav=`rave`q.u.ruv
1814+ %= +>+.$
1815+ lim
1816+ ?.(&(?=(| -.rav) ?=(%da -.q.p.rav)) lim `@da`p.q.p.rav)
1817+ ::
1818+ haw.u.ref
1819+ ?. ?=(& -.rav) haw.u.ref
1820+ (~(put by haw.u.ref) p.rav ~)
1821+ ==
1822+ ?< ?=(%v p.p.u.rot)
1823+ =. haw.u.ref
1824+ (~(put by haw.u.ref) [p.p.u.rot q.p.u.rot q.u.rot] ~ r.u.rot)
1825+ ?. ?=(%w p.p.u.rot) +>+.$
1826+ |- ^+ +>+.^$
1827+ =+ nez=[%w [%ud let.dom] ~]
1828+ =+ nex=(~(get by haw.u.ref) nez)
1829+ ?~ nex +>+.^$
1830+ ?~ u.nex +>+.^$ :: should never happen
1831+ =. +>+.^$ =+ roo=(edis ((hard nako) u.u.nex))
1832+ ?>(?=(^ ref.roo) roo)
1833+ %= $
1834+ haw.u.ref (~(del by haw.u.ref) nez)
1835+ ==
1836+
1837+This is kind of a long gate, but don't worry, it's not bad at all.
1838+
1839+First, we assert that we're not a domestic desk. That wouldn't make any
1840+sense at all.
1841+
1842+Since we have the sequence number of the request, we can get the duct
1843+and rave from `bom` in our request manager. If we didn't actually
1844+request this data (or the request was canceled before we got it), then
1845+we do nothing.
1846+
1847+Else, we remove the request from `bom` and `fod` unless this was a
1848+subscription request and we didn't receive a null riot (which would
1849+indicate the last message on the subscription).
1850+
1851+Now, if we received a null riot, then if this was a subscription request
1852+by date, then we update `lim` in our request manager (representing the
1853+latest time at which we have complete information for this desk) to the
1854+date that was requested. If this was a single read request, then we put
1855+the result in our simple cache `haw` to make future requests faster.
1856+Then we're done.
1857+
1858+If we received actual data, then we put it into our cache `haw`. Unless
1859+it's a `%w` request, we're done.
1860+
1861+If it is a `%w` request, then we try to get the `%w` at our current head
1862+from the cache. In general, that should be the thing we just put in a
1863+moment ago, but that is not guaranteed. The most common case where this
1864+is different is when we receive desk updates out of order. At any rate,
1865+since we now have new information, we need to apply it to our local copy
1866+of the desk. We do so in `++edis`, and then we remove the stuff we just
1867+applied from the cache, since it's not really a true "single read", like
1868+what should really be in the cache.
1869+
1870+ ++ edis :: apply subscription
1871+ |= nak=nako
1872+ ^+ +>
1873+ %= +>
1874+ hit.dom (~(uni by hit.dom) gar.nak)
1875+ let.dom let.nak
1876+ lat.ran %+ roll (~(tap in bar.nak) ~)
1877+ =< .(yeb lat.ran)
1878+ |= [sar=blob yeb=(map lobe blob)]
1879+ =+ zax=(blob-to-lobe sar)
1880+ %+ ~(put by yeb) zax sar
1881+ hut.ran %+ roll (~(tap in lar.nak) ~)
1882+ =< .(yeb hut.ran)
1883+ |= [sar=yaki yeb=(map tako yaki)]
1884+ %+ ~(put by yeb) r.sar sar
1885+ ==
1886+
1887+This shows, of course, exactly why nako is defined the way it is. To
1888+become completely up to date with the foreign desk, we need to merge
1889+`hit` with the foreign one so that we have all the revision numbers. We
1890+update `let` so that we know which revision is the head.
1891+
1892+We merge the new blobs in `lat`, keying them by their hash, which we get
1893+from a call to `++blob-to-lobe`. Recall that the hash is stored in the
1894+actual blob itself. We do the same thing to the new yakis, putting them
1895+in `hut`, keyed by their hash.
1896+
1897+Now, our local dome should be exactly the same as the foreign one.
1898+
1899+This concludes our discussion of `++knit`. Now the changes have been
1900+applied to our local copy of the desk, and we just need to update our
1901+subscribers. We do so in `++wake:de`.
1902+
1903+ ++ wake :: update subscribers
1904+ ^+ .
1905+ =+ xiq=(~(tap by qyx) ~)
1906+ =| xaq=(list ,[p=duct q=rove])
1907+ |- ^+ ..wake
1908+ ?~ xiq
1909+ ..wake(qyx (~(gas by *cult) xaq))
1910+ ?- -.q.i.xiq
1911+ &
1912+ =+ cas=?~(ref ~ (~(get by haw.u.ref) `mood`p.q.i.xiq))
1913+ ?^ cas
1914+ %= $
1915+ xiq t.xiq
1916+ ..wake ?~ u.cas (blub p.i.xiq)
1917+ (blab p.i.xiq p.q.i.xiq u.u.cas)
1918+ ==
1919+ =+ nao=(~(case-to-aeon ze lim dom ran) q.p.q.i.xiq)
1920+ ?~ nao $(xiq t.xiq, xaq [i.xiq xaq])
1921+ $(xiq t.xiq, ..wake (balk p.i.xiq u.nao p.q.i.xiq))
1922+ ::
1923+ |
1924+ =+ mot=`moot`p.q.i.xiq
1925+ =+ nab=(~(case-to-aeon ze lim dom ran) p.mot)
1926+ ?~ nab
1927+ $(xiq t.xiq, xaq [i.xiq xaq])
1928+ =+ huy=(~(case-to-aeon ze lim dom ran) q.mot)
1929+ ?~ huy
1930+ =+ ptr=[%ud +(let.dom)]
1931+ %= $
1932+ xiq t.xiq
1933+ xaq [[p.i.xiq [%| ptr q.mot r.mot s.mot]] xaq]
1934+ ..wake =+ ^= ear
1935+ (~(lobes-at-path ze lim dom ran) let.dom r.p.q.i.xiq)
1936+ ?: =(s.p.q.i.xiq ear) ..wake
1937+ =+ fud=(~(make-nako ze lim dom ran) u.nab let.dom)
1938+ (bleb p.i.xiq let.dom fud)
1939+ ==
1940+ %= $
1941+ xiq t.xiq
1942+ ..wake =- (blub:- p.i.xiq)
1943+ =+ ^= ear
1944+ (~(lobes-at-path ze lim dom ran) u.huy r.p.q.i.xiq)
1945+ ?: =(s.p.q.i.xiq ear) (blub p.i.xiq)
1946+ =+ fud=(~(make-nako ze lim dom ran) u.nab u.huy)
1947+ (bleb p.i.xiq +(u.nab) fud)
1948+ ==
1949+ ==
1950+ --
1951+
1952+This is even longer than `++knit`, but it's pretty similar to `++eave`.
1953+We loop through each of our subscribers `xiq`, processing each in turn.
1954+When we're done, we just put the remaining subscribers back in our
1955+subscriber list.
1956+
1957+If the subscriber is a single read, then, if this is a foreign desk
1958+(note that `++wake` is called from other arms, and not only on foreign
1959+desks). Obviously, if we find an identical request there, then we can
1960+produce the result immediately. Referential transparency for the win. We
1961+produce the result with a call to `++blab`. If this is a foreign desk
1962+but the result is not in the cache, then we produce `++blub` (canceled
1963+subscription with no data) for reasons entirely opaque to me. Seriously,
1964+it seems like we should wait until we get an actual response to the
1965+request. If someone figures out why this is, let me know. At any rate,
1966+it seems to work.
1967+
1968+If this is a domestic desk, then we check to see if the case exists yet.
1969+If it doesn't, then we simply move on to the next subscriber, consing
1970+this one onto `xaq` so that we can check again the next time around. If
1971+it does exist, then we call `++balk` to fulfill the request and produce
1972+it.
1973+
1974+`++balk` is very simple, so we'll describe it here before we get to the
1975+subscription case.
1976+
1977+ ++ balk :: read and send
1978+ |= [hen=duct oan=@ud mun=mood]
1979+ ^+ +>
1980+ =+ vid=(~(read-at-aeon ze lim dom ran) oan mun)
1981+ ?~ vid (blub hen) (blab hen mun u.vid)
1982+
1983+We call `++read-at-aeon` on the given request and aeon. If you recall,
1984+this processes a `mood` at a particular aeon and produces the result, if
1985+there is one. If there is data at the requested location, then we
1986+produce it with `++blab`. Else, we call `++blub` to notify the
1987+subscriber that no data can ever come over this subscriptioin since it
1988+is now impossible for there to ever be data for the given request.
1989+Because referential transparency.
1990+
1991+At any rate, back to `++wake`. If the given rave is a subscription
1992+request, then we proceed similarly to how we do in `++eave`. We first
1993+try to get the aeon referred to by the starting case. If it doesn't
1994+exist yet, then we can't do anything interesting with this subscription,
1995+so we move on to the next one.
1996+
1997+Otherwise, we try to get the aeon referred to by the ending case. If it
1998+doesn't exist yet, then we produce all the information we can. We call
1999+`++lobes-at-path` at the given aeon and path to see if the requested
2000+path has actually changed. If it hasn't, then we don't produce anything;
2001+else, we produce the correct nako by calling `++bleb` on the result of
2002+`++make-nako`, as in `++eave`. At any rate, we move on to the next
2003+subscription, putting back into our cult the current subscription with a
2004+new start case of the next aeon after the present.
2005+
2006+If the aeon referred to by the ending case does exist, then we drop this
2007+subscriber from our cult and satisfy its request immediately. This is
2008+the same as before -- we check to see if the data at the path has
2009+actually changed, producing it if it has; else, we call `++blub` since
2010+no more data can be produced over this subscription.
2011+
2012+This concludes our discussion of foreign requests.
docs/arvo/internals/dill.mdnew file+26
@@ -0,0 +1,26 @@
1+---
2+navhome: /docs
3+sort: 4
4+---
5+
6+`%dill`
7+=======
8+
9+Our terminal driver.
10+
11+Unix sends keyboard events to `%dill` from either the console or telnet,
12+and `%dill` produces terminal output. The only app that should directly
13+talk to `%dill` is the terminal app. Command-line apps are run by,
14+receive input from, and produce output to, the `%shell` app, which is
15+controlled by `%terminal`, which talks to `%dill`, which talks to unix.
16+Clay also uses `%dill` directly to print out the filesystem change
17+events, but this is questionable behavior.
18+
19+`%dill` has two main components. First, it controls the terminal on a
20+very basic, event-by-event level. This includes keeping track of things
21+like the dimensions of the terminal, the prompt type (plain text or
22+password), which duct to produce effects on, and so forth. Second, it
23+handles terminal events, keystroke by keystroke. Most characters are
24+simply pushed onto the buffer and blitted to the screen, but some
25+characters, including control-modified keys, arrow keys, etc. require
26+special handling. Most of the readline functionality is in `%dill`.
docs/arvo/internals/eyre.mdnew file+59
@@ -0,0 +1,59 @@
1+---
2+navhome: /docs
3+sort: 5
4+---
5+
6+`%eyre`
7+=======
8+
9+Our http server.
10+
11+Unix sends http messages to `%eyre`, and `%eyre` produces http messages
12+in response. In general, apps and vanes do not call `%eyre`; rather,
13+`%eyre` calls apps and vanes. `%eyre` uses `%ford` and `%gall` to
14+functionally publish pages and facilitate communication with apps.
15+
16+`%eyre` primarily parses web requests and handles them in a variety of
17+ways, depending on the control string. Nearly all of these are
18+essentially stateless, like functional publishing with `%ford`.
19+Additionally, there's a fairly significant component that handles
20+`%gall` messaging and subscriptions, which must be stateful.
21+
22+HTTP Methods
23+============
24+
25+`GET` `gog` `https://[ship-name].urbit.org/gog/[service]` Owner
26+requesting a page on her own Urbit. `gig`
27+`https://[ship-name].urbit.org/gig/[user-name]/[service]` Another user
28+requesting a page on a foreign Urbit.
29+
30+`goe`
31+`https://[ship-name].urbit.org/goe/[service]/[port]/[stream]/[sequence]`
32+`https://[ship-name].urbit.org/goe/[service]/[port]/[stream]/[sequence].json`
33+Pulls a specific response to her subscription on her own Urbit. `gie`
34+`https://[ship-name].urbit.org/gie/[user-name]/[service]/[port]/[stream]/[sequence]`
35+`https://[ship-name].urbit.org/gie/[user-name]/[service]/[port]/[stream]/[sequence].json`
36+Pulls a specific response to her subscription on a foreign Urbit.
37+
38+`PUT` `tos`
39+`https://[ship-name].urbit.org/tos/[service]/[port]/[stream]/[path]`
40+`{oryx: [string]}` Initiate a subscription on her own Urbit. `tis`
41+`https://[ship-name].urbit.org/tis/[user-name]/[service]/[port]/[stream]/[path]`
42+`{oryx: [string]}` Initiate a subscription on a foreign Urbit.
43+
44+`tom` `https://[ship-name].urbit.org/tom/[service]/[port]/[sequence]`
45+`{oryx: [string], xyro: [json]}` Send a message to her Urbit with
46+sequence number `[sequence]`. `tim`
47+`https://[ship-name].urbit.org/tim/[user-name]/[service]/[port]/[sequence]`
48+`{oryx: [string], xyro: [json]}` Send a message to a foreign Urbit with
49+sequence number `[sequence]`.
50+
51+`tou` `https://[ship-name].urbit.org/tou/[service]/[port]/[stream]`
52+Unsubscribe from stream `[stream]` on her Urbit. `tiu`
53+`https://[ship-name].urbit.org/tiu/[user-name]/[service]/[port]/[stream]`
54+Unsubscribe from stream `[stream]` on a foreign Urbit.
55+
56+urb.js
57+======
58+
59+<list></list>
docs/arvo/internals/eyre/commentary.mdnew file+278
@@ -0,0 +1,278 @@
1+---
2+navhome: /docs
3+---
4+
5+
6+Eyre: Reference
7+===============
8+
9+## State
10+
11+Stored
12+
13+- `++bolo`
14+- `++cyst`
15+- `++stem`
16+
17+Runtime
18+
19+- `perk`
20+ + `perk-auth`
21+- `pest`
22+- `even`
23+
24+## Cores
25+
26+- `++handle`
27+ + `++parse`
28+ - `++as...`
29+- `++ya`
30+- `++ix`
31+
32+Eyre: Commentary
33+================
34+
35+Let us follow the loading of a simple cli app, as it bounces from
36+browser to server to browser and back.
37+
38+## Initial request[#init]
39+
40+An http request for `http://sampel-sipnym.urbit.org/cli` will be [redirected](dns)
41+to the `%eyre` on ~sampel-sipnym, and come in as a `%this` kiss.
42+
43+From arvo, requests enter `++call`, which after some type reification are passed
44+along to `++apex:ye`. In the case of a `%this` kiss, its components are
45+parsed(see `++zest:epur`, `++eat-headers`) and handed off to `++handle`, wrapped
46+in `++emule` to produce a `++fail` page in case of error. `++apex:handle` will
47+`++process` the request to a `pest` or a `++done` core, and in the former case
48+`++resolve` the pest into an outgoing card.
49+
50+XX it also seems to affect the current ship, test that serving ship name is consistently correct
51+
52+The pest is produced by `++process`, which will first further `++parse` the
53+request, and if this does not make the response immediately obvious,
54+`++process-parsed` the resulting `perk`.
55+
56+`++parse` produces the `perk`, by attempting to interpret the `pork`(url path)
57+[`++as-magic-filename`](#mage), `++as-beam`, and `++as-aux-request`. In this
58+case, `/cli` is parsed by the second case as a `%beam` query to `/=cli=`: a path
59+which starts with a valid ship name is expected to be a full clay(well, ford)
60+path, and one starting with a term implies the current serving ship and a case
61+of `0`, the current revision.
62+
63+XX spur: when the desks are merged, `/cli` shall point to `/=main=/pub/cli`
64+
65+The parsed `perk` generates a `%f %boil` note, `mark`ed as its extension(here
66+defaulting to `%urb`) and `wire`d with `~` to return unaltered to the client. It
67+goes on to `++resolve` by being passed to `++ford-get-beam`, which translates
68+the perk it into a `%boil` `++ford-req`, adding an `++fcgi` path-segment
69+containing query string and `++fcgi-cred:for-client` auth information.
70+
71+`%ford`s translation of `/=cli=/hymn/hook` to a self-refreshing `%urb` html page
72+[deserves its own commentary](../ford/commentary), but we resume in `%eyre`
73+when the `%made` sign arrives in `++take`, and soon after `++axon:ye`. There the
74+`wire`, or rather the `whir` it has been verified to be, determines that the
75+response should be served immediately. However, as the mark is not `%mime`,
76+another trip to `%ford` is required to encode it, on the same wire; afterwards,
77+the value of the `%mime` cage is verified to be of the correct type, and finally
78+delivered back up the requesting duct as a succesful `%thou` HTTP response.
79+
80+XX `%cast %mime` used to be in ford-get-beam, is there a reason it was removed?
81+
82+## Back into the breach, or: auxilary requests
83+
84+Now, it was mentioned that this result is self-refreshing: the `%urb`
85+translation door injects a `;script@"/~/on/{deps}.js"` into every page, `deps`
86+is a ford-readable hash of the set of resources that page construction depended
87+on.
88+
89+This triggers another `%this` request. Its handling is identical to that of
90+`/cli` up until `++parse`, where it is seen not `++as-beam` but
91+`++as-aux-request`(auxillary requests starting with `/~/` or `/~~/`).
92+`/on/[hash]` is a long-`%poll`, which `++process-parsed`, for a `.js` mark,
93+answers with a direct `%js`. Its contents are the static `++poll:js`, which
94+initiates the long-polling loop, run against an injected `urb.js` of
95+`{poll:[hash]}`.
96+
97+A `%js` `pest` is `resolve`d as a `text/javascript` success `%this`.
98+
99+When `poll.js` is recieved by the client, it opens an `XMLHttpRequest` for
100+`/~/on/{window.urb.poll}.json`, bringing us back to `%poll:process`.
101+
102+In the case of a non-`%js` `/~/on/`, `%poll:process-parsed` turns into a
103+`++new-dependency`, which stores the listening duct, and `pass-note`s a `%wasp`
104+with the deps-hash back to `%ford` whence it came. While this occured, the page
105+has loaded.
106+
107+Some indeterminate amount of time afterwards, with dropped `/~/on/{...}.json`s
108+being retried upon expiring and also being stored, a `%news` sign arrives in
109+`++axon`, and the hash in question is retrieved from the wire, and the listening
110+long-polls retrieved by the hash. Each receives a 205 "Reload parent view" HTTP
111+response, which `poll.js` dutifully executes, and a fixed typo of markdown is
112+rendered.
113+
114+## Authentication.
115+
116+Now, while this accurately reflects the presentation of e.g. a markdown file,
117+`/cli` is an application front-end, and one that permits only owner access. Its
118+second script is `@"/~~/~/at/main/lib/urb.js"`, semantically equivalent to
119+`/~/as/own/~/at/main/lib/urb.js`, and handled as follows.
120+
121+In `++as-aux-request`, `%as %own` becomes `%auth %get our` perk, which
122+`++process` passes to `++process-parsed` passes to `++process-auth`. There, a
123+`yac` "ya" core is built `++for-client`: a `++cookie-prefix`, which is just the
124+serving ship name, is used to get a `++session-from-cookies`, here nil as the
125+client has no cookie set. In lieu of a cookie, a `++new-ya` is constructed, with
126+a random token `hole` and a `++new-cyst` which fills out `cyst` session state
127+from request data.
128+
129+Returning to `++process-auth`, `%get` checks if the yac is authenticated with
130+the requested credentials(`anon` requests are always granted), which for the
131+fresh new `cyst` is not the case (more on success [later](#auth-ok)). Unless
132+authentiacting as a [foreign ship](#xeno), the only thing left is to
133+`++show-login-page`, which detects that the requested resource is not `%html`,
134+and produces a `%red` pest. For `%js`, `%red`irections `++resolve` to
135+`++auth-redir:js`, a line of javascript which prepends `/~~` to the url path.
136+
137+The owner-authenticated main page request similarly ends in `++show-login-page`,
138+which for the empty session is an `[%htme ++login-page:xml]`, `resolve`d to
139+`++give-html` with a 401 "unathorized".
140+
141+The login page shows a simple prompt, and requests `/~/at/auth.js` to handle the
142+submission. And so we are, once again, attempting to divine if what we're doing
143+makes sense `++as-aux-request`.
144+
145+To understand `/~/at`, there will first be a brief diversion to `~/auth.json`.
146+`auth.json`, perk `[%auth %json]`, in `++process-auth` serves `++stat-json:ya`,
147+containing such information as the serving ship, which identities are associated
148+with this session, and `oryx`, a CSRF token. An oryx must be present on all
149+stateful requests, in this case executing a log in. It also saves the new/old
150+session using `abet`.
151+
152+XX explain `ixor` here and not [later](#ixor)?
153+
154+`/~/at` is an alternate interface, which injects `auth.json` data into the
155+requested file. `/~/at/auth.js`, then, is a request for the built-in `auth:js`
156+(parsed to and processed from an `[%auth %js ~]` perk), with session data added
157+as `window.urb`. And indeed, ``[`%js /~/at/auth]`` is parsed to
158+``[%auth at [`%js /auth]``, which in `++process-auth` is re-`process`ed to
159+`[%js ++auth:js]`, which is `++resolve`d after an `++add-json` of
160+the relevant data. The yac cookies are also passed to `resolve`, which
161+`++add-cookies` injects into the `httr`.
162+
163+It is at this point that there is first occasion for user input, namely the password.
164+
165+The `auth:js` script sends a `PUT` request, also to `/~/auth.json`. In `parse`,
166+the first nontrivial `++check-oryx` occurs, `++grab-body` the request oryx and
167+ensuring it is recorded for the session. The request parsed with `++need-body`
168+to a `[%auth %try {password}]` perk. `%get:process-auth` checks it against
169+`++load-secret`, upon success updates the session with `++logon:ya`, and
170+serves a fresh `auth.json` which reflects the changed `user`. Upon recieving
171+this, the page is refreshed to retry the original request.
172+
173+## Post-authentication: app communication. [#auth-ok]
174+
175+Upon refresh, `/~~/cli` brings us for the third time to `%get:process-auth`, but
176+this time the cookie is set, and the `yac` fetched contains the serving ship as
177+authenticated. The `++handle` sample is updated to reflect the requesting ship,
178+and the `process` continues for the rest of the pork, once again serving the
179+ford page.
180+
181+The `/~/on/[deps].json` poll starts anew, and `/~~/~/at/main/lib/urb.js` we now
182+know to serve the window.urb necessary to make requests, and the `urb.js`
183+standard library which extends it with a number of wrappers to them and other
184+useful functions.
185+
186+---
187+
188+One of those functions is `urb.bind`, which is used to subscribe to application
189+data. Userspace javascript sets `urb.appl` to `/tic`, and binds `lines` to a
190+`;pre;` text display, using a callback.
191+
192+This triggers a `PUT` to `/~/is/{ixor}/cli/lines.json`, where `ixor` is a hash
193+of `oryx` that identifies the connection. `++as-aux-request`, an `%is` is a
194+`%subs` subscription update update, which for `%put` forwards to
195+`++add-subs:ix`, the ix core fetched `++for-view` by hashing the request
196+`++oryx-to-ixor`.
197+
198+[#ixor] A view has all the state associated with a client that must be
199+remembered between events. In this case, this is what app/path the request duct
200+is associated with; but mainly, `++add-subs:ix` will `pass-note` to `%gall` so
201+it `%show`s the data on the path, current and future.
202+
203+This will immediately(assuming the ship is local) result in a `%nice` by the
204+`/cli` app, returning `{ok:true}` `++nice-json` to `urb.bind`'s second callback
205+as `{ok:true}`. The initial `%rush` results also arrive, and in `++axon` are
206+converted to json using `++back`(ford `%cast` wrapper), and when `%made` get
207+passed to `++get-rush:ix`. There the source application/path are decoded by
208+duct, and then the full event goes to `++get-even`; `++add-even` inserts it to
209+the queue, and as there is no long poll it simply stays there.
210+
211+Upon receipt, the client realizes the long-poll isn't actually running, so that
212+is started using `urb.poll`. At `/~/of/{ixor}`, perk
213+`[%view ixor ~ {sequence-number}]`, it is `process`ed by `++poll:ix` (the cyst
214+is retrieved by `++ire-ix` form global state, using the perk `ixor`): the
215+sequence number is in the past, so the previously recieved `%rush` is
216+`++give-even`. After deleting the previous message in the queue and invoking
217+`++pass-took` to signal `%gall` of this occurrence, the data is annotated with
218+the source app+path `++subs-to-json`, and returned to the polling duct.
219+
220+On the client, the user callback receives the `/cli` history, and displays it on
221+the page. The `/~/of` long poll is continued, this time reaching `++poll:ix`
222+with the "pending" sequence number, and being stored in the `cyst` for its troubles.
223+
224+---
225+
226+Its next update proceeds idenitcally, but first it must be triggered, which
227+happens when the user enters "(add 2 2)\n", firing an `urb.send` from the event
228+handler. This sends a `POST` request to `/~/to/cli/json.json`, perk `%mess`,
229+`++process`ed to a `%g %mess`. Were the mark not `%json`, a `%ford` conversion
230+would occur first, and `%made:axon` would send the gall message proper. In
231+either case, eventually a `%mean` or `%nice` arrives, is encoded as json, and
232+sent to the client callback.
233+
234+## A path not taken: magic filenames [#mage]
235+
236+The `/robots.txt` and `/favicon.(ico|png)` files are static, and served
237+immediately when caught by a `++parse`.
238+
239+XX index.html?
240+
241+## A path not taken: foreign auth [#xeno]
242+
243+While this example details a login `/~/as/own`, it is possible to be
244+authenticated as any ship on the network. A request for such seen in
245+`%get:process-auth` is passed to `++foreign-auth:ya`, which sends an
246+`%ames /lon` message to the ship in question. The foreign ship stores the
247+inquiry, calculates(the local) `++our-host` and responds with a `/hat`,
248+containing the redirection host, which is stored by `++foreign-hat`; it is later
249+used to send the client to a `/~/am` url on the foreign client, which acts as a
250+normal login page but later sends the client back. XX expand, basically the
251+status quo is you're logged in and `/~/as/foo` is ignored, just setting your
252+`urb.user` XX
253+
254+
255+## A path not taken: deauthentication
256+
257+`/~/away`, perk `[%away ~]`, produces a static `++logout-page:xml`, which also
258+uses `/~/at/auth.js`, to send a `DELETE /~/auth.json`, perk `[%auth %del]`. This
259+executes `++logoff:ya` for the cookie session, resolving to `++abut` to wipe it
260+from memory.
261+
262+## A path not taken: unsubscription
263+
264+`DELETE /~/is/app/path/within` works much like `PUT /~/is/app/path/within`,
265+`++del-subs:ix` acting as reverse of `++add-subs` by deleting the duct binding
266+and sending `%g %nuke`.
267+
268+
269+XX unmentioned arms: abet, add-poll, adit, ames-gram, anon, ares-to-json, bolo, cyst, doze, even, ford-kill, get-mean, gift, give-json, give-thou, gram, hapt, hasp, host-to-ship, ix, ixor, js, kiss, load, mean-json, move, note, pass-note, perk, perk-auth, pest, poke-test, print-subs, render-tang, resp, root-beak, scry, ses-authed, ses-ya, sign, silk, sine, stay, stem, teba, titl, to-oryx, urb, wait-era, wake, whir, wush, xml, ya, ye
270+
271+## Appendix A: DNS [#dns]
272+
273+The `*.urbit.org` domain can be used to access destroyers and cruisers. In the
274+common case oh hosted ships, this is done by dynamic DNS directly to the hosting
275+instance. We do not speak of the uncommon case. When ports are blocked and
276+infrastructure crumbles around you, only imported martian networking can be
277+trusted: the `%get` and `%got` [gram]()s are used to proxy [`%this` requests]() and
278+[`%thou` responses]() respectively.
docs/arvo/internals/ford.mdnew file+112
@@ -0,0 +1,112 @@
1+---
2+navhome: /docs
3+sort: 6
4+---
5+
6+
7+`%ford`
8+=======
9+
10+Our typed and marked computation engine.
11+
12+A variety of different services are provided by `%ford`, but they mostly
13+involve compiling hook files, slapping/slammming code with marked data,
14+and converting data between marks, including validating data to a mark.
15+Throughout every computation, `%ford` keeps track of which resources are
16+dependencies so that the client may be aware when one or more
17+dependencies are updated.
18+
19+`%ford` neither accepts unix events nor produces effects. It exists
20+entirely for the benefit of applications and other vanes, in particular
21+`%gall`. `%eyre` exposes the functional publishing aspects of `%ford`
22+while `%gall` uses `%ford` to control the execution of applications.
23+`%clay` is intended to use `%ford` to managed marked data, but this is
24+not yet reality.
25+
26+<list></list>
27+
28+Cards
29+-----
30+
31+`%ford` accepts just one card, `%exec`. This is misleading, however,
32+since there are fourteen different `silk`s that may be used with it. In
33+every case, the expected response to a `%exec` card is a `%made` gift
34+with either an error or the produced result along with its set of
35+dependencies.
36+
37+Silks may autocons, so that the product of a cell of silks is a cell of
38+the product of the two silks.
39+
40+### `%bake`
41+
42+Tries to functionally produce the file at a given beam with the given
43+mark and heel. It fails if there is no way to translate at this level.
44+
45+### `%boil`
46+
47+Functionally produces the file at a given beam with the given mark and
48+heel. If there is no way to translate at this beam, we pop levels off
49+the stack and attempt to bake there until we find a level we can bake.
50+This should almost always be called instead of `%bake`.
51+
52+### `%call`
53+
54+Slams the result of one silk against the result of another.
55+
56+### `%cast`
57+
58+Translates the given silk to the given mark, if possible. This is one of
59+the critical and fundamental operations of ford.
60+
61+### `%diff`
62+
63+Diffs the two given silks (which must be of the same mark), producing a
64+cage of the mark specified in `++mark` in `++grad` for the mark of the
65+two silks.
66+
67+### `%done`
68+
69+Produces exactly its input. This is rarely used on its own, but many
70+silks are recursively defined in terms of other silks, so we often need
71+a silk that simply produces its input. A monadic return, if you will.
72+
73+### `%dude`
74+
75+Computes the given silk with the given tank as part of the stack trace
76+if there is an error.
77+
78+### `%dune`
79+
80+Produces an error if the cage is empty. Otherwise, it produces the value
81+in the unit.
82+
83+### `%mute`
84+
85+Takes a silk and a list of changes to make to the silk. At each wing in
86+the list we put the value of the associated silk.
87+
88+### `%pact`
89+
90+Applies the second silk as a patch to the first silk. The second silk
91+must be of the mark specified in `++mark` in `++grad` for the mark of
92+the first silk.
93+
94+### `%plan`
95+
96+Performs a structured assembly directly. This is not generally directly
97+useful because several other silks perform supersets of this
98+functionality. We don't usually have naked hoods outside ford.
99+
100+### `%reef`
101+
102+Produces a core containing the entirety of zuse and hoon, suitable for
103+running arbitrary code against. The mark is `%noun`.
104+
105+### `%ride`
106+
107+Slaps a twig against a subject silk. The mark of the result is `%noun`.
108+
109+### `%vale`
110+
111+Validates untyped data from a ship against a given mark. This is an
112+extremely useful function.
docs/arvo/internals/ford/commentary.mdnew file+2576
@@ -0,0 +1,2576 @@
1+---
2+navhome: /docs
3+---
4+
5+
6+Reference
7+=========
8+
9+Data Models
10+-----------
11+
12+### `++axle`, formal state
13+
14+ ++ axle :: all %ford state
15+ $: %1 :: version for update
16+ pol=(map ship baby) ::
17+ == ::
18+
19+This is the formal state of our vane. Anything that must be remembered
20+between calls to ford must be stored here. The number `%1` is a version
21+number for our state that allows us to upgrade the structure of our
22+state in the future if we wish.
23+
24+`pol` is the a map from every ship on our pier to their individual ford
25+state. There is no shared ford state -- every ship is entirely separate.
26+
27+### `++baby`, state by ship
28+
29+ ++ baby :: state by ship
30+ $: tad=[p=@ud q=(map ,@ud task)] :: tasks by number
31+ dym=(map duct ,@ud) :: duct to task number
32+ jav=(map ,* calx) :: cache
33+ == ::
34+
35+This is the state specific to each ship.
36+
37+`tad` and `dym` keep track of the tasks we're currently working on.
38+`dym` is a map from ducts to task numbers, and `q.tad` is a map from
39+task number to the task itself. `p.tad` is the next available task
40+number. Thus, the keys of `q.tad` are a subset of the numbers less than
41+`p.tad`, and ford has attempted exactly `p.tad` tasks so far.
42+
43+`jav` is the cache of previously-solved problems. The keys are a pair of
44+a term (either `%hood`, `%slap`, or `%slam`) and a noun that represents
45+the exact problem solved. In the case of a `%hood`, then, the key is of
46+the form `[%hood beam cage]`. For `%slap`, there is `[%slap vase twig]`.
47+For `%slam`, there is `[%slam vase vase]`. The values are the result of
48+solving the problem. Note that this cache is wiped in `++stay` when ford
49+is reloaded.
50+
51+### `++task`, problem in progress
52+
53+ ++ task :: problem in progress
54+ $: nah=duct :: cause
55+ kas=silk :: problem
56+ kig=[p=@ud q=(map ,@ud beam)] :: blocks
57+ == ::
58+
59+This is all the state we keep regarding a particular task. `nah` is the
60+duct which asked us to solve the problem, and `kas` is the most recent
61+statement of the problem.
62+
63+`kig` keeps track of which resources we are blocked on. Our blocks are
64+stored by index in `q.kig`, and the next available index is `p.kig`.
65+
66+### `++silk`, problem
67+
68+ ++ silk :: construction layer
69+ $& [p=silk q=silk] :: cons
70+ $% [%bake p=mark q=beam r=path] :: local synthesis
71+ [%boil p=mark q=beam r=path] :: general synthesis
72+ [%call p=silk q=silk] :: slam
73+ [%cast p=mark q=silk] :: translate
74+ [%diff p=silk q=silk] :: diff
75+ [%done p=(set beam) q=cage] :: literal
76+ [%dude p=tank q=silk] :: error wrap
77+ [%dune p=(set beam) q=(unit cage)] :: unit literal
78+ [%mute p=silk q=(list (pair wing silk))] :: mutant
79+ [%pact p=silk q=silk] :: patch
80+ [%plan p=beam q=spur r=hood] :: structured assembly
81+ [%reef ~] :: kernel reef
82+ [%ride p=twig q=silk] :: silk thru twig
83+ [%vale p=mark q=ship r=*] :: validate [our his]
84+ == ::
85+
86+This is the every type of problem we can solve. Every `%exec` kiss that
87+requests us to solve a problem must choose one of these problems to
88+solve.
89+
90+Because this is both an internal structure used in ford and the public
91+interface to ford, we choose to document this structure in our
92+discussion of the public interface to ford below.
93+
94+### `++calx`, cache line
95+
96+ ++ calx :: concrete cache line
97+ $% [%hood p=calm q=(pair beam cage) r=hood] :: compile
98+ [%slap p=calm q=[p=vase q=twig] r=vase] :: compute
99+ [%slam p=calm q=[p=vase q=vase] r=vase] :: compute
100+ == ::
101+
102+There are three kinds of cache entries. Every entry includes some
103+metadata in `p` and is the combination of an input and its output.
104+
105+The input to a `%hood` is the location of the resource and a cage
106+representing the data at that location. The output is the hood found by
107+compiling the given cage at the given location.
108+
109+The input to a `%slap` is the vase of the subject and the twig of the
110+formula against which we are slapping the subject. The output is the
111+vase produced by slapping them.
112+
113+The input to a `%slam` is the vase of the subject and the vase of the
114+gate which we are slapping. The output is the vase produced by slamming
115+them.
116+
117+### `++calm`, cache line metadata
118+
119+ ++ calm :: cache metadata
120+ $: laz=@da :: last accessed
121+ dep=(set beam) :: dependencies
122+ == ::
123+
124+Every line in the cache needs to have two pieces of metadata. We must
125+know the last time this line in the cache was accessed, and we must know
126+what are the dependencies of this line.
127+
128+### `++hood`, assembly components
129+
130+ ++ hood :: assembly plan
131+ $: zus=@ud :: zuse kelvin
132+ sur=(list hoot) :: structures
133+ lib=(list hoof) :: libraries
134+ fan=(list horn) :: resources
135+ src=(list hoop) :: program
136+ == ::
137+
138+When assembling a hook file, we split it into several sections.
139+
140+`zus` is the kelvin version of the required zuse. In general, we assume
141+that any newer (lower-numbered) zuse will retain backward compatibility,
142+so any newer zuse is also permissible. This number is set with a `/?` at
143+the beginning of the file.
144+
145+`sur` is the set of structures included. These are included with the
146+`/-` rune. When a structure is included, we look in `/=main=/sur` for
147+the given structure and we load the gate there. When compiling, all the
148+included structures are collected into a single core placed in the
149+subject of the body with a `=>`.
150+
151+`lib` is the set of librarires included. These are included with the
152+`/+` rune. When a library is included, we look in `/=main=/lib` for the
153+given library and we load the library there. As with structures, all the
154+included libraries are collected into a single core placed in the
155+subject of the body with a `=>`.
156+
157+`fan` is the set of resources included. These are loaded in many
158+different ways and may load resources from any location. These are
159+placed in the subject of the body with a `=~`.
160+
161+`src` is the set of twigs or references to twigs in the body of the
162+program. Generally, each of these will represent a core, but this is not
163+required. When compiling, these are strung together in a `=~`.
164+
165+### `++hoot`
166+
167+ ++ hoot (pair bean hoof) :: structure gate/core
168+
169+A structures may be either a direct gate or a core. These are
170+syntactically distinguished by adding a `*` to the beginning of the
171+structure name for a core. The structure itself is a `hoof`.
172+
173+### `++hoof`
174+
175+ ++ hoof (pair term (unit (pair case ship))) :: resource reference
176+
177+A hoof, which is either a structure or a library, has a name, and it may
178+also specify which version of the resource to use and which ship to
179+retrieve it from.
180+
181+### `++horn`
182+
183+ ++ horn :: resource tree
184+ $% [%ape p=twig] :: /~ twig by hand
185+ [%arg p=twig] :: /$ argument
186+ [%day p=horn] :: /| list by @dr
187+ [%dub p=term q=horn] :: /= apply face
188+ [%fan p=(list horn)] :: /. list
189+ [%for p=path q=horn] :: /, descend
190+ [%hub p=horn] :: /@ list by @ud
191+ [%man p=(map span horn)] :: /* hetero map
192+ [%nap p=horn] :: /% homo map
193+ [%now p=horn] :: /& list by @da
194+ [%saw p=twig q=horn] :: /; operate on
195+ [%see p=beam q=horn] :: /: relative to
196+ [%sic p=tile q=horn] :: /^ cast
197+ [%toy p=mark] :: /mark/ static
198+ == ::
199+
200+This is how we represent the static resources hook files can load. The
201+discussion of their use from a user's perspective is documented
202+elsewhere (link), so we will here only give a description of the data
203+structure itself.
204+
205+A `%ape` horn is simply a twig that gets evaluated and placed in the
206+subject.
207+
208+A `%arg` is a gate that gets evaluated with a sample of our location and
209+our heel.
210+
211+A `%day` is a horn that applies to each of a list of `@dr`-named files
212+in the directory.
213+
214+A `%dub` is a term and horn, where the result of a horn is given the
215+face of the term.
216+
217+A `%fan` is a list of horns, all at the current directory level.
218+
219+A `%for` is a path and a horn, where the horn is evaluated relative to
220+the given path, where the given path is relative to the current
221+location.
222+
223+A `%hub` is a horn that applies to each of a list of `@ud`-named files
224+in the directory.
225+
226+A `%man` is a map of spans to horns where the result is a set of each
227+horn applied to the current directory given the associated face.
228+
229+A `%nap` is a homogenous map where each entry in a directory is handled
230+with the same horn and is given a face according to its name.
231+
232+A `%now` is a horn that applies to each of a list of `@da`-named files
233+in the directory.
234+
235+A `%saw` is a twig and a horn, where the twig operates on the result of
236+the horn.
237+
238+A `%see` is a beam and a horn, where the horn is evaluated at a location
239+of the given beam.
240+
241+A `%sic` is a tile and a horn, where the horn is evaluated and cast to
242+the type associated with the tile.
243+
244+A `%toy` is simply a mark to be baked.
245+
246+### `++hoop`, body
247+
248+ ++ hoop :: source in hood
249+ $% [%& p=twig] :: direct twig
250+ [%| p=beam] :: resource location
251+ == ::
252+
253+This is an entry in the body of the hook file. The hoop can either be
254+defined directly in the given file or it can be a reference to another
255+file. The second is specified with a `//` rune.
256+
257+### `++bolt`, monadic edge
258+
259+ ++ bolt :: gonadic edge
260+ |* a=$+(* *) :: product clam
261+ $: p=cafe :: cache
262+ $= q ::
263+ $% [%0 p=(set beam) q=a] :: depends/product
264+ [%1 p=(set ,[p=beam q=(list tank)])] :: blocks
265+ [%2 p=(list tank)] :: error
266+ == ::
267+ == ::
268+
269+Throughout our computation, we let our result flow through with the set
270+of dependencies of the value. At various times, we may wish to either
271+throw an error or declare that the actual result cannot be found until a
272+particular resource is retrieved. This is a perfect case for a monad, so
273+here we define a data structure for it.
274+
275+At every step, we have a cache, so we store that in `p`. In `q` we store
276+the data.
277+
278+In the case of `%0`, we have the result in `q` and the set of
279+dependencies in `p`.
280+
281+In the case of `%1`, we have a set of dependencies on which we are
282+blocking. When this happens, we make a call to clay to get the
283+dependencies, and we proceed with the computation when we receive them.
284+Technically, we restart the computation, but since every expensive step
285+is cached, there is no significant performance penalty to doing this.
286+Referential transparency has its uses.
287+
288+In the case of `%2`, we have a hit an error. This gets passed all the
289+way through to the calling duct. The list of tanks is some description
290+of what went wrong, often including a stack trace.
291+
292+### `++burg`, monadic rule
293+
294+ ++ burg :: gonadic rule
295+ |* [a=$+(* *) b=$+(* *)] :: from and to
296+ $+([c=cafe d=a] (bolt b)) ::
297+ :: ::
298+
299+To operate on bolts, we use `++cope` as our bind operator, and the
300+functions it works on are of type `burg`. Our functions that operate on
301+bolts should have a sample of the cache and a value. Their output should
302+be a bolt of the output value. Then, `++cope` will only call the
303+function when necessary (in the `%0` case), and it will do so without
304+the wrapping of a bolt.
305+
306+If you understand monads, this is probably fairly obvious. Otherwise,
307+see the discussion on `++cope` (link).
308+
309+Public Interface
310+----------------
311+
312+Ford does not export a scry interface, so the only way to interact with
313+ford is by sending kisses and receiving gifts. In fact, ford only sends
314+accepts one kiss and gives one gift. This is, of course, misleading
315+because ford actually does many different things. It does, however, only
316+produce one type of thing -- a result of a computation, which is either
317+an error or the value produced along with the set of dependencies
318+referenced by it.
319+
320+ ++ kiss :: in request ->$
321+ $% [%exec p=@p q=(unit silk)] :: make / kill
322+ == ::
323+
324+The `%exec` gift requests ford to perform a computation on behalf of a
325+particular ship. `p` is the ship, and `q` is the computation. If `q` is
326+null, then we are requesting that ford cancel the computation that it is
327+currently being run along this duct. Thus, if you wish to cancel a
328+computation, you must send the kiss along the same duct as the original
329+request.
330+
331+Otherwise, we ask ford to perform a certain computation, as defined in
332+`++silk`. Since all computations produce the same type of result, we
333+will discuss that result before we jump into `++silk`.
334+
335+ ++ gift :: out result <-$
336+ $% [%made p=(each bead (list tank))] :: computed result
337+ == ::
338+
339+We give either a `bead`, which is a result, or a list of tanks, which is
340+an error messge, often including a stack trace.
341+
342+ ++ bead ,[p=(set beam) q=cage] :: computed result
343+
344+This is a set of dependencies required to compute this value and a cage
345+of the result with its associated mark.
346+
347+There are twelve possible computations defined in `++silk`.
348+
349+ ++ silk :: construction layer
350+ $& [p=silk q=silk] :: cons
351+ $% [%bake p=mark q=beam r=path] :: local synthesis
352+ [%boil p=mark q=beam r=path] :: general synthesis
353+ [%call p=silk q=silk] :: slam
354+ [%cast p=mark q=silk] :: translate
355+ [%done p=(set beam) q=cage] :: literal
356+ [%dude p=tank q=silk] :: error wrap
357+ [%dune p=(set beam) q=(unit cage)] :: unit literal
358+ [%mute p=silk q=(list (pair wing silk))] :: mutant
359+ [%plan p=beam q=spur r=hood] :: structured assembly
360+ [%reef ~] :: kernel reef
361+ [%ride p=twig q=silk] :: silk thru twig
362+ [%vale p=mark q=ship r=*] :: validate [our his]
363+ == ::
364+
365+First, we allow silks to autocons. A cell of silks is also a silk, and
366+the product vase is a cell of the two silks. This obviously extends to
367+an arbitrary number of silks.
368+
369+`%bake` tries to functionally produce the file at a given beam with the
370+given mark and heel. It fails if there is no way to translate at this
371+level.
372+
373+`%boil` functionally produces the file at a given beam with the given
374+mark and heel. If there is no way to translate at this beam, we pop
375+levels off the stack and attempt to bake there until we find a level we
376+can bake. This should almost always be called instead of `%bake`.
377+
378+`%call` slams the result of one silk against the result of another.
379+
380+`%cast` translates the given silk to the given mark, if possible. This
381+is one of the critical and fundamental operations of ford.
382+
383+`%done` produces exactly its input. This is rarely used on its own, but
384+many silks are recursively defined in terms of other silks, so we often
385+need a silk that simply produces its input. A monadic return, if you
386+will.
387+
388+`%diff` diffs the two given silks (which must be of the same mark),
389+producing a cage of the mark specified in `++mark` in `++grad` for the
390+mark of the two silks.
391+
392+`%dude` computes the given silk with the given tank as part of the stack
393+trace if there is an error.
394+
395+`%dune` produces an error if the cage is empty. Otherwise, it produces
396+the value in the unit.
397+
398+`%mute` takes a silk and a list of changes to make to the silk. At each
399+wing in the list we put the value of the associated silk.
400+
401+`%pact` applies the second silk as a patch to the first silk. The second
402+silk must be of the mark specified in `++mark` in `++grad` for the mark
403+of the first silk.
404+
405+`%plan` performs a structured assembly directly. This is not generally
406+directly useful because several other silks perform supersets of this
407+functionality. We don't usually have naked hoods outside ford.
408+
409+`%reef` produces a core containing the entirety of zuse and hoon,
410+suitable for running arbitrary code against. The mark is `%noun`.
411+
412+`%ride` slaps a twig against a subject silk. The mark of the result is
413+`%noun`.
414+
415+`%vale` validates untyped data from a ship against a given mark. This is
416+an extremely useful function.
417+
418+Commentary
419+==========
420+
421+Parsing Hook Files
422+------------------
423+
424+In the commentary on other vanes, we have traced through the lifecycle
425+of various external requests. This is generally a very reasonable order
426+to examine vanes since it will eventually cover the entire vane, and we
427+are never left wondering why we are doing something.
428+
429+For ford, however, it makes more sense to begin by discussing the
430+parsing and assembliing of hook files. Many of the possible requests
431+require us to assemble hook files, so we may as well examine this
432+immediately.
433+
434+First, we will examine the parsing. We parse a file at a beam to a hood
435+in `++fade:zo:za`. The top-level parsing rule is `++fair`, which takes a
436+beam and produces a rule to parse an entire hood file.
437+
438+A note on the naming scheme: the parsing the combinators that parse into
439+a particular structure are conventionally given the same name as the
440+structure. Although this locally clobbers the type names, this pattern
441+makes obvious the intent of the parsing combinators.
442+
443+We kick off with `++hood:fair`.
444+
445+ ++ hood
446+ %+ ifix [gay gay]
447+ ;~ plug
448+ ;~ pose
449+ (ifix [;~(plug fas wut gap) gap] dem)
450+ (easy zuse)
451+ ==
452+ ::
453+ ;~ pose
454+ (ifix [;~(plug fas hep gap) gap] (most ;~(plug com gaw) hoot))
455+ (easy ~)
456+ ==
457+ ::
458+ ;~ pose
459+ (ifix [;~(plug fas lus gap) gap] (most ;~(plug com gaw) hoof))
460+ (easy ~)
461+ ==
462+ ::
463+ (star ;~(sfix horn gap))
464+ (most gap hoop)
465+ ==
466+
467+There are five sections to a hood: system version, structures,
468+libraries, resources, and body.
469+
470+First, we parse the requested version number of the system. This is
471+specified with a unary `/?` rune. If not present, then we default to the
472+current version.
473+
474+Second, we may have zero or more `/-` runes followed by a parsing of a
475+`++hoot`, which represents a shared structure.
476+
477+Third, we may have zero or more `/+` runes followed by a parsing of a
478+`++hoof`, which represents a shared library.
479+
480+Fourth, we may have zero or more other `/` runes (as described in
481+`++horn`), which represent program-specific resources to be loaded.
482+
483+Fifth and finally, we must have one or more body statements (hoops),
484+which are either direct twigs or `//` runes.
485+
486+ ++ hoot
487+ ;~ pose
488+ (stag %| ;~(pfix tar hoof))
489+ (stag %& hoof)
490+ ==
491+
492+A structure can either be a direct gate, or it can be a simple core.
493+Either one is parsed with `++hoof`, so we distinguish the two cases by
494+requireing core references to be prefixed by a `*`.
495+
496+ ++ hoof
497+ %+ cook |=(a=^hoof a)
498+ ;~ plug
499+ sym
500+ ;~ pose
501+ %+ stag ~
502+ ;~(plug ;~(pfix fas case) ;~(pfix ;~(plug fas sig) fed:ag))
503+ (easy ~)
504+ ==
505+ ==
506+
507+A hoof must have a name, which is a term. Optionally, we also include a
508+case and a ship. This is marked by appending a `/` followed by a case to
509+denote the requested version of the resource and a `/` followed by a
510+ship name to denote the requested source of the resource. For example,
511+`resource/1/~zod` requests the first version of `resource` on `~zod`.
512+
513+ ++ case
514+ %- sear
515+ :_ nuck:so
516+ |= a=coin
517+ ?. ?=([%$ ?(%da %ud %tas) *] a) ~
518+ [~ u=(^case a)]
519+
520+Here, we parse a literal with `++nuck:so`, and we accept the input if it
521+is either an absolute date, an unsigned decimal, or a label.
522+
523+This leaves only horns and hoops to parse. Hoops are much simple to
524+parse, so we'll discuss those first.
525+
526+ ++ hoop
527+ ;~ pose
528+ (stag %| ;~(pfix ;~(plug fas fas gap) have))
529+ (stag %& tall:vez)
530+ ==
531+
532+There are two types of hoops. Direct twigs are parsed with
533+`++tall:vast`, which is the just the hoon parser for a tall-form twig.
534+
535+References to external twigs are marked with a `//` rune followed by a
536+beam, which is parsed with `++have`.
537+
538+ ++ hath (sear plex:voz (stag %clsg poor:voz)) :: hood path
539+ ++ have (sear tome ;~(pfix fas hath)) :: hood beam
540+
541+`++have` parses a path with `++hath`, and then it converts the path into
542+a beam with `++tome`.
543+
544+`++hath` parses a `/`-separated list with `++poor:vast`, then converts
545+it to an actual path with `++plex:vast`.
546+
547+This leaves only horns to parse.
548+
549+ ++ horn
550+ =< apex
551+ =| tol=?
552+ |%
553+ ++ apex
554+ %+ knee *^horn |. ~+
555+ ;~ pfix fas
556+ ;~ pose
557+ (stag %toy ;~(sfix sym fas))
558+ (stag %ape ;~(pfix sig ape:read))
559+ (stag %arg ;~(pfix buc ape:read))
560+ (stag %day ;~(pfix bar day:read))
561+ (stag %dub ;~(pfix tis dub:read))
562+ (stag %fan ;~(pfix dot fan:read))
563+ (stag %for ;~(pfix com for:read))
564+ (stag %hub ;~(pfix pat day:read))
565+ (stag %man ;~(pfix tar man:read))
566+ (stag %nap ;~(pfix cen day:read))
567+ (stag %now ;~(pfix pam day:read))
568+ (stag %saw ;~(pfix sem saw:read))
569+ (stag %see ;~(pfix col see:read))
570+ (stag %sic ;~(pfix ket sic:read))
571+ ==
572+ ==
573+
574+Horn parsing is slightly complex, so we create an internal core to
575+organize our code. Our core has a global variable of `tol`, which is
576+true if tall form is permissible and false if we're already in wide
577+form. We kick off the parsing with `++apex`.
578+
579+`++apex` specifies how each rune is parsed. This allows us to offload
580+the different ways of parsing the arguments to these runes into separate
581+arms. The exception here is that the `%toy` horn is simply of the form
582+`/mark/`.
583+
584+We'll examine each of the horn parsing arms right after we discuss
585+`++rail`, which is used in each one.
586+
587+ ++ rail
588+ |* [wid=_rule tal=_rule]
589+ ?. tol wid
590+ ;~(pose wid tal)
591+
592+This takes a wide-form and a tall-form parsing rule. If tall form is
593+permissible, then it allows either rule to match; else, it allows only
594+the wide form rule.
595+
596+ ++ read
597+ |% ++ ape
598+ %+ rail
599+ (ifix [sel ser] (stag %cltr (most ace wide:vez)))
600+ ;~(pfix gap tall:vez)
601+
602+`++ape:read` parses for both the `/~` and the `/$` runes. It produces a
603+twig. The wide form is a tuple of one or more ace-separated wide-form
604+twigs parsed with `++wide:vast` and surrounded by `[` and `]`. The tall
605+form is a single tall form twig parsed by `++tall:vast`
606+
607+ ++ day
608+ %+ rail
609+ apex(tol |)
610+ ;~(pfix gap apex)
611+
612+This parses for the `/|`, `/@`, `/%`, and `/&` runes. It produces a
613+horn. The wide form is, recursively, the entire horn parser with tall
614+form disabled. The tall form is a gap followed by, recursively, the
615+entire horn parser.
616+
617+ ++ dub
618+ %+ rail
619+ ;~(plug sym ;~(pfix tis apex(tol |)))
620+ ;~(pfix gap ;~(plug sym ;~(pfix gap apex)))
621+
622+This parses for the `/=` rune. It produces a term followed by a horn.
623+The wide form is a symbol name followed by a `=` and, recursively, the
624+entire horn parser with tall form disabled. The tall form is a gap
625+followed by a symbol name, another gap, and, recursively, the entire
626+horn parser.
627+
628+ ++ fan
629+ %+ rail fail
630+ ;~(sfix (star ;~(pfix gap apex)) ;~(plug gap duz))
631+
632+This parses for the `/.` rune. It produces a list of horns. There is no
633+wide form. The tall form is a stet-terminated series of gap-separated
634+recursive calls to the entire horn parser.
635+
636+ ++ for
637+ %+ rail
638+ ;~(plug (ifix [sel ser] hath) apex(tol |))
639+ ;~(pfix gap ;~(plug hath ;~(pfix gap apex)))
640+
641+This parses for the `/,` rune. It produces a path and a horn. The wide
642+form is a `[`-`]`-surrounded path followed by, recursively, the entire
643+horn parser with tall form disabled. The tall form is a gap followed by
644+a path, another gap, and, recursively, the entire horn parser.
645+
646+ ++ man
647+ %+ rail fail
648+ %- sear
649+ :_ ;~(sfix (star ;~(pfix gap apex)) ;~(plug gap duz))
650+ |= fan=(list ^horn)
651+ =| naf=(list (pair term ^horn))
652+ |- ^- (unit (map term ^horn))
653+ ?~ fan (some (~(gas by *(map term ^horn)) naf))
654+ ?. ?=(%dub -.i.fan) ~
655+ $(fan t.fan, naf [[p.i.fan q.i.fan] naf])
656+
657+This parses for the `/*` rune. It produces a map of spans to horns.
658+There is no wide form. The tall form is a stet-terminated series of
659+gap-separated recursive calls to the entire horn parser. All produced
660+horns are expected to be from `/=` runes. The term and horn in each `/=`
661+horn is inserted into the produced map as a key-value pair.
662+
663+ ++ saw
664+ %+ rail
665+ ;~(plug ;~(sfix wide:vez sem) apex(tol |))
666+ ;~(pfix gap ;~(plug tall:vez ;~(pfix gap apex)))
667+
668+This parses for the `/;` rune. It produces a twig and a horn. The wide
669+form is a wide-form twig followed by a `;` and, recursively, the entire
670+horn parser with tall form disabled. The tall form is a gap followed by
671+a tall-form twig, another gap, and, recursively, the entire horn parser.
672+
673+ ++ see
674+ %+ rail
675+ ;~(plug ;~(sfix have col) apex(tol |))
676+ ;~(pfix gap ;~(plug have ;~(pfix gap apex)))
677+
678+This parses for the `/:` rune. It produces a beam and a horn. The wide
679+form is a beam followed by a `;` and, recursively, the entire horn
680+parser with tall form disabled. The tall form is a gap followed by a
681+beam, another gap, and, recursively, the entire horn parser.
682+
683+ ++ sic
684+ %+ rail
685+ ;~(plug ;~(sfix toil:vez ket) apex(tol |))
686+ ;~(pfix gap ;~(plug howl:vez ;~(pfix gap apex)))
687+ --
688+
689+This parses for the `/^` rune. It produces a tile and a horn. The wide
690+form is a wide-form tile, parsed with `++toil:vast`, followed by a `^`
691+and, recursively, the entire horn parser with tall form disabled. The
692+tall form is a gap followed by a tall-form tile, parsed with
693+`++howl:vast`, another gap, and, recursively, the entire horn parser.
694+
695+Assembling Hook Files
696+---------------------
697+
698+At this point, we've parsed a hook file into a hood. We will now
699+describe exactly how this hood is assembled into a vase. The problem of
700+assembling is handled entirely within the `++meow:zo:za` core.
701+
702+ ++ meow :: assemble
703+ |= [how=beam arg=heel]
704+ =| $: rop=(map term (pair hoof twig)) :: structure/complex
705+ zog=(set term) :: structure guard
706+ bil=(map term (pair hoof twig)) :: libraries known
707+ lot=(list term) :: library stack
708+ zeg=(set term) :: library guard
709+ boy=(list twig) :: body stack
710+ hol=? :: horns allowed?
711+ ==
712+ |%
713+
714+We take two arguments and keep seven pieces of state. `how` is the
715+location of the hook file we're assembling, and `arg` is the heel, or
716+virtual path extension, of the file.
717+
718+In `rop`, we maintain a map of terms to pairs of hooves and twigs to
719+represent the structures we've encountered that we will put together in
720+a core at the top of the file.
721+
722+In `zog`, we maintain the set of structures we're in the middle of
723+loading. If we try to load a structure already in our dependency
724+ancestry, then we fail because we do not allow circular dependencies.
725+This enforces that our structure dependency graph is a DAG.
726+
727+In `bil`, we maintain a map of terms to pairs of hooves and twigs to
728+represent the libraries we've encountered that we will put together in a
729+series of cores after the structure core.
730+
731+In `lot`, we maintain a stack of library names as they are encountered
732+during a depth-first search. More precisely, we push a library onto the
733+stack after we've processed all its children. Thus, every library
734+depends only on things deeper in the list. The libraries must be loaded
735+in the reverse of this order. Concisely, this is a topological sort of
736+the library dependency partial ordering.
737+
738+In `zeg`, we maintain the set of libraries we're in the middle of
739+loading. If we try to load a library already in our dependency ancestry,
740+then we fail because we do not allow circular dependencies. This
741+enforces that our library dependency graph is a DAG.
742+
743+In `boy`, we maintain a stack of body twigs, which we'll put together in
744+a series of cores at the end of the file.
745+
746+In `hol`, we decide if we're allowed to contain horns. Libraries and
747+structures are not allowed to contain horns.
748+
749+We in every case enter `++meow` through `++abut`. You'll notice that
750+there are four (count 'em, four!) calls to `++cope` in `++abut`. If
751+you've glanced at the ford code in general, you've probably seen cope
752+over and over. It is called in 79 different places. We need to discuss
753+the use of this critical function in detail, so we may as well do it
754+here.
755+
756+ ++ cope :: bolt along
757+ |* [hoc=(bolt) fun=(burg)]
758+ ?- -.q.hoc
759+ %2 hoc
760+ %1 hoc
761+ %0 =+ nuf=(fun p.hoc q.q.hoc)
762+ :- p=p.nuf
763+ ^= q
764+ ?- -.q.nuf
765+ %2 q.nuf
766+ %1 q.nuf
767+ %0 [%0 p=(grom `_p.q.nuf`p.q.hoc p.q.nuf) q=q.q.nuf]
768+ == ==
769+
770+In monad-speak, this is the bind operator for the bolt monad. If monads
771+aren't your thing, don't worry, we're going to explain the use of cope
772+without further reference to them.
773+
774+Recall that there are three different types of bolt. A `%2` error bolt
775+contains a list of tanks describing the error, a `%1` block bolt
776+contains a set of resources we're blocked on, and a `%0` value bolt
777+contains an actual value and the set of its dependencies.
778+
779+We most commonly want to perform an operation on the value in a bolt if
780+it is a `%0` bolt. If it's not a `%0` bolt, we want to leave it alone.
781+This requires us to write a certain amount of boilerplate between each
782+of our operations to see if any of them produced a `%1` or a `%2` bolt.
783+This gets tiresome, so we pull it out into a separate arm and call it
784+`++cope`.
785+
786+Intuitively, we're calling the function `fun` with the value in `hoc`,
787+where `fun` takes an argument of type whatever is the value in a `%0`
788+case of `hoc`, and it produces a bolt of some (possibly different) type.
789+For brevity, we will refer to the type of the of the value in the `%0`
790+case of a bolt as the "type of the bolt".
791+
792+If the `hoc` bolt we're given as input to `fun` is already a `%1` or a
793+`%2` bolt, then we simply produce that. We don't even try to run `fun`
794+on it.
795+
796+Otherwise, we run `fun` with the arguments from the bolt and, if it
797+produces a `%1` or a `%2` bolt, we simply produce that. If it produces a
798+`%0` bolt, then we produce that with the old set of dependencies merged
799+in with the new set.
800+
801+We'll see more about how the bolt monad works as we run into more
802+interesting uses of it. For now, this is sufficient to move on with
803+`++abut`.
804+
805+ ++ abut :: generate
806+ |= [cof=cafe hyd=hood]
807+ ^- (bolt vase)
808+ %+ cope (apex cof hyd)
809+ |= [cof=cafe sel=_..abut]
810+ =. ..abut sel
811+ %+ cope (maim cof pit able)
812+ |= [cof=cafe bax=vase]
813+ %+ cope (chap cof bax [%fan fan.hyd])
814+ |= [cof=cafe gox=vase]
815+ %+ cope (maim cof (slop gox bax) [%tssg (flop boy)])
816+ |= [cof=cafe fin=vase]
817+ (fine cof fin)
818+
819+Our job is simple: we must assemble a hood file into a vase. Hopefully,
820+the usage of `++cope` is fairly understandable. The correct way to read
821+this is that it does essentially five things.
822+
823+First, we call `++apex` to process the structures, libraries, and body.
824+This changes our state, so we set our context to the produced context.
825+Second, we call `++able` to assemble the strucutres and libraries into a
826+twig, which we slap against zuse with `++maim`. Third, we call `++chap`
827+to process the resources in the context of the already-loaded structures
828+and libraries. Fourth, we slap the body against the structures,
829+libraries, and resources. Fifth and finally, we produce the resultant
830+vase.
831+
832+ ++ apex :: build to body
833+ |= [cof=cafe hyd=hood]
834+ ^- (bolt ,_..apex)
835+ ?. |(hol ?=(~ fan.hyd))
836+ %+ flaw cof :_ ~ :- %leaf
837+ "horns not allowed in structures and libraries: {<[how arg]>}"
838+ %+ cope (body cof src.hyd)
839+ |= [cof=cafe sel=_..apex]
840+ =. ..apex sel
841+ %+ cope (neck cof lib.hyd)
842+ |= [cof=cafe sel=_..apex]
843+ =. ..apex sel(boy boy)
844+ %+ cope (head cof sur.hyd)
845+ |= [cof=cafe sel=_..apex]
846+ (fine cof sel)
847+
848+First, we make sure that if we're not allowed to have horns, we don't.
849+Otherwise, we produce and error with `++flaw`.
850+
851+ ++ flaw |=([a=cafe b=(list tank)] [p=a q=[%2 p=b]]) :: bolt from error
852+
853+This produces a `%2` error bolt from a list of tanks. Fairly trivial.
854+
855+We should be starting to get used to the cope syntax, so we can see that
856+we really only do three things here. We process the body with `++body`,
857+the libraries with `++neck`, and the structures with `++head`.
858+
859+ ++ body :: produce functions
860+ |= [cof=cafe src=(list hoop)]
861+ ^- (bolt _..body)
862+ ?~ src (fine cof ..body)
863+ %+ cope (wilt cof i.src)
864+ |= [cof=cafe sel=_..body]
865+ ^$(cof cof, src t.src, ..body sel)
866+
867+We must process a list of hoops that represent our body. If there are no
868+more hoops, we just produce our context in a `%0` bolt with `++fine`.
869+
870+ ++ fine |* [a=cafe b=*] :: bolt from data
871+ [p=`cafe`a q=[%0 p=*(set beam) q=b]] ::
872+
873+In monad-speak, this is the return operator. For us, this just means
874+that we're producing a `%0` bolt, which contains a path and a set of
875+dependencies. We assume there are no dependencies for the given data, or
876+that they will be added later.
877+
878+If there are more hoops in `++body`, we call `++wilt` to process an
879+individual hoop and recurse.
880+
881+ ++ wilt :: process body entry
882+ |= [cof=cafe hop=hoop]
883+ ^- (bolt _..wilt)
884+ ?- -.hop
885+ %& (fine cof ..wilt(boy [p.hop boy]))
886+ %|
887+ %+ cool |.(leaf/"ford: wilt {<[(tope p.hop)]>}")
888+ %+ cope (lend cof p.hop)
889+ |= [cof=cafe arc=arch]
890+ ?: (~(has by r.arc) %hoon)
891+ %+ cope (fade cof %hoon p.hop)
892+ |= [cof=cafe hyd=hood]
893+ %+ cope (apex(boy ~) cof hyd)
894+ |= [cof=cafe sel=_..wilt]
895+ (fine cof sel(boy [[%tssg boy.sel] boy]))
896+ =+ [all=(lark (slat %tas) arc) sel=..wilt]
897+ %+ cope
898+ |- ^- (bolt (pair (map term foot) _..wilt))
899+ ?~ all (fine cof ~ ..wilt)
900+ %+ cope $(all l.all)
901+ |= [cof=cafe lef=(map term foot) sel=_..wilt]
902+ %+ cope ^$(all r.all, cof cof, sel sel)
903+ |= [cof=cafe rig=(map term foot) sel=_..wilt]
904+ %+ cope
905+ %= ^^^^$
906+ cof cof
907+ ..wilt sel(boy ~)
908+ s.p.hop [p.n.all s.p.hop]
909+ ==
910+ |= [cof=cafe sel=_..wilt]
911+ %+ fine cof
912+ [`(map term foot)`[[p.n.all [%ash [%tssg boy.sel]]] lef rig] sel]
913+ |= [cof=cafe mav=(map term foot) sel=_..wilt]
914+ ?~ mav
915+ (flaw cof [%leaf "source missing: {<(tope p.hop)>}"]~)
916+ (fine cof sel(boy [[%brcn mav] boy]))
917+ ==
918+
919+In the case of a direct twig hoop, we just push it onto `boy` and we're
920+done. In the case of an indirect hoop, we must compile the referenced
921+file.
922+
923+First, we push onto the stack trace a message indicating which file
924+exactly we're compiling at the moment with `++cool`.
925+
926+ ++ cool :: error caption
927+ |* [cyt=trap hoc=(bolt)]
928+ ?. ?=(%2 -.q.hoc) hoc
929+ [p.hoc [%2 *cyt p.q.hoc]]
930+
931+If an error occurred in computing `hoc`, we put the bunt of `cyt` onto
932+the stack trace. Thus, `cyt` is not evaluated at all unless an error
933+occurred.
934+
935+Next in `++wilt`, we load the information about the filesystem node
936+referenced by the hoop with `++lend`.
937+
938+ ++ lend :: load arch
939+ |= [cof=cafe bem=beam]
940+ ^- (bolt arch)
941+ =+ von=(ska %cy (tope bem))
942+ ?~ von [p=cof q=[%1 [bem ~] ~ ~]]
943+ (fine cof ((hard arch) (need u.von)))
944+
945+This is a simple call to the namespace. If the resource does not yet
946+exist, we block on it by producing a `%1` bolt. Otherwise, we cast it to
947+an arch and produce this.
948+
949+Continuing in `++wilt`, we examine the produced arch. If the referenced
950+filesystem node has a `hoon` child node, then we've found the required
951+source, so we parse it with `++fade`. Recall that we referred earlier to
952+`++fade`. The salient point there is that it takes a beam, reads in the
953+hook file there, and parses it into a hood file with `++fair`.
954+
955+Now, we simply recurse on `++apex` to compile the new hood. Note that,
956+while we do clear the `boy` list, we do not clear the other lists. Thus,
957+we are accumulating all the structures and libraries referenced in all
958+the referenced hook files in one group, which we will put at the top of
959+the product.
960+
961+After this, we put the new list of body twigs into a `=~`, push this
962+onto our old list of body twigs, and produce the result.
963+
964+If there is no hoon file here, then we descend into each of our children
965+until we find a hoon file. First, we produce a list of all our children
966+whose names are terms with `++lark`.
967+
968+ ++ lark :: filter arch names
969+ |= [wox=$+(span (unit ,@)) arc=arch]
970+ ^- (map ,@ span)
971+ %- ~(gas by *(map ,@ span))
972+ =| rac=(list (pair ,@ span))
973+ |- ^+ rac
974+ ?~ r.arc rac
975+ =. rac $(r.arc l.r.arc, rac $(r.arc r.r.arc))
976+ =+ gib=(wox p.n.r.arc)
977+ ?~(gib rac [[u.gib p.n.r.arc] rac])
978+
979+We traverse the children map of `arc` to filter out those children whose
980+names aren't accepted by `wox` and produce a map from the product of
981+`wox` to the original name. `++lark` is used in many cases to parse
982+names into other types, like numbers or dates, ignoring those which do
983+not fit the format. In `++wilt`, though, we simply want to filter out
984+those children whose names are not terms.
985+
986+Next, we will produce a map from terms to feet. Each of these feet will
987+be placed in a core named by the child name, and it will contain arms
988+according to its children. Thus, if the indirect hoop references
989+`/path`, then to access the twig defined in `/path/to/twig/hoon`, our
990+body must refer to `twig:to`.
991+
992+If there are no more children, then we are done, so we produce our
993+current context.
994+
995+Else, we recurse into the left and right sides of our map. Finally, we
996+process our current entry in the map. We first recurse by calling
997+`++wilt` one level down. Thus, in the previous example, the first time
998+we get to this point we are processing `/path`, so we recurse on
999+`++wilt` with path `/path/to`. We also remove our current body from the
1000+recursion, so that we may add it back in later the way we want to.
1001+
1002+After recursing, we push the new body onto our map, keyed by its name.
1003+We also produce the new context so that all external structures,
1004+libraries, and resources are collected into the same place.
1005+
1006+Finally, we have a map of names to feet. If this map is empty, then
1007+there were no twigs at the requested path, so we give an error with
1008+`++flaw`.
1009+
1010+If the map is nonempty, then we finally produce our context with with
1011+one thing pushed onto the front: a core made out of the map we just
1012+produced.
1013+
1014+This concludes our discussion of `++wilt` and `++body`. Thus, it remains
1015+in `++apex` to discuss `++neck` and `++head`.
1016+
1017+ ++ neck :: consume libraries
1018+ |= [cof=cafe bir=(list hoof)]
1019+ ^- (bolt ,_..neck)
1020+ ?~ bir (fine cof ..neck)
1021+ ?: (~(has in zeg) p.i.bir)
1022+ (flaw cof [%leaf "circular library dependency: {<i.bir>}"]~)
1023+ =+ gez=(~(put in zeg) p.i.bir)
1024+ =+ byf=(~(get by bil) p.i.bir)
1025+ ?^ byf
1026+ ?. =(`hoof`i.bir `hoof`p.u.byf)
1027+ (flaw cof [%leaf "library mismatch: {<~[p.u.byf i.bir]>}"]~)
1028+ $(bir t.bir)
1029+ =+ bem=(hone %core %lib i.bir)
1030+ %+ cope (fade cof %hook bem)
1031+ |= [cof=cafe hyd=hood]
1032+ %+ cope (apex(zeg gez, hol |, boy ~) cof hyd)
1033+ |= [cof=cafe sel=_..neck]
1034+ =. ..neck
1035+ %= sel
1036+ zeg zeg
1037+ hol hol
1038+ lot [p.i.bir lot]
1039+ bil (~(put by bil) p.i.bir [i.bir [%tssg (flop boy.sel)]])
1040+ ==
1041+ ^^$(cof cof, bir t.bir)
1042+
1043+Here, we're going to consume the list of libraries and place them in
1044+`bil`. If there are no more libraries, we're done, so we just produce
1045+our current context.
1046+
1047+Otherwise, we check to see if the next library in the list is in `zeg`.
1048+If so, then this library is one of the libraries that we're already in
1049+the middle of compiling. There is a circular dependency, so we fail.
1050+
1051+Otherwise, we let `gez` be `zeg` plus the current library so that while
1052+compiling the dependencies of this library we don't later create a
1053+circular dependency. We check next to see if this library is alredy in
1054+`bil`. If so, then we have already included this library earlier, so we
1055+check to see if this is the same version of the library as we included
1056+earlier. If so, we skip it. Else, we fail since we can't include two
1057+different versions of a library. We really should allow for newer
1058+versions of a library since in kelvin versioning we assume backwards
1059+compatibility, but for now we require an exact match.
1060+
1061+If we haven't already included this library, then we're going to do
1062+that. First, we get the location of the library with `++hone`.
1063+
1064+ ++ hone :: plant hoof
1065+ |= [for=@tas way=@tas huf=hoof]
1066+ ^- beam
1067+ ?~ q.huf
1068+ how(s ~[for p.huf way])
1069+ [[q.u.q.huf %main p.u.q.huf] ~[for p.huf way]]
1070+
1071+If we haven't specified the version of the library, we use the current
1072+ship, desk, and case. Otherwise, we use the given ship and case on desk
1073+`%main`. In either case, the path is `/way/p.huf/for`. In the case of
1074+`++neck`, this means `/lib/core/[library name]`.
1075+
1076+In `++neck`, we next compile the hook file at that location with
1077+`++fade`. Again, we will delay the discussion of `++fade`, noting only
1078+that it takes a beam and parses the hook file there into a hood.
1079+
1080+We recurse on this to compile the library. During the compilation, we
1081+let `zeg` be `gez` to avoid circular dependencies, we let `hol` be false
1082+since we don't allow horns in libraries, and we let `boy` be null so
1083+that we can isolate the new body twigs.
1084+
1085+Next, we reintegrate the new data into our context. We use the context
1086+created by the recursion with four changes. First, we reset `zeg` to our
1087+old `zeg`. Second, we reset `hol` to our old `hol`. Third, we put the
1088+name of our library onto the stack of libraries. This means all of a
1089+libraries dependencies will be earlier in `lot` than the library itself,
1090+making `lot` a topological ordering on the dependency graph. Fourth, we
1091+put in `bil` the library hoof and body (with all body twigs collected in
1092+a `=~`), keyed by the library name.
1093+
1094+Finally, we recurse, processing the next library in our list.
1095+
1096+To complete our disucssion of `++apex`, we must process our structures.
1097+
1098+ ++ head :: consume structures
1099+ |= [cof=cafe bir=(list hoot)]
1100+ |- ^- (bolt ,_..head)
1101+ ?~ bir
1102+ (fine cof ..head)
1103+ ?: (~(has in zog) p.q.i.bir)
1104+ (flaw cof [%leaf "circular structure dependency: {<i.bir>}"]~)
1105+ =+ goz=(~(put in zog) p.q.i.bir)
1106+ =+ byf=(~(get by rop) p.q.i.bir)
1107+ ?^ byf
1108+ ?. =(`hoof`q.i.bir `hoof`p.u.byf)
1109+ (flaw cof [%leaf "structure mismatch: {<~[p.u.byf q.i.bir]>}"]~)
1110+ $(bir t.bir)
1111+ =+ bem=(hone ?:(p.i.bir %gate %core) %sur q.i.bir)
1112+ %+ cope (fade cof %hook bem)
1113+ |= [cof=cafe hyd=hood]
1114+ %+ cope (apex(zog goz, hol |, boy ~) cof hyd)
1115+ |= [cof=cafe sel=_..head]
1116+ ?. =(bil bil.sel)
1117+ (flaw cof [%leaf "structures cannot include libraries: {<i.bir>}"]~)
1118+ =. ..head
1119+ %= sel
1120+ boy ?: p.i.bir
1121+ boy
1122+ (welp boy [[[%cnzy p.q.i.bir] [%$ 1]] ~])
1123+ zog zog
1124+ hol hol
1125+ rop %+ ~(put by (~(uni by rop) rop.sel))
1126+ p.q.i.bir
1127+ [q.i.bir [%tssg (flop boy.sel)]]
1128+ ==
1129+ ^^$(cof cof, bir t.bir)
1130+
1131+The processing of our structures is very similar to that of our
1132+libraries. For clarity, we'll use many of the same phrases in describing
1133+the parallel natures. First, we check to see if there are more
1134+structures to process. If not, we're done, so we produce our context.
1135+
1136+Otherwise, we let `goz` be `zog` plus the current structure so that
1137+while compiling the dependencies of this structure we don't later create
1138+a circular dependency. We check next to see if this structure is alredy
1139+in `rop`. If so, then we have already included this structure earlier,
1140+so we check to see if this is the same version of the structure as we
1141+included earlier. If so, we skip it. Else, we fail since we can't
1142+include two different versions of a structure.
1143+
1144+If we haven't loaded this structure, then we call `++hone` to get the
1145+beam where the file structure should be. If the loobean in the hoot is
1146+true, then we're looking for a gate; otherwise, we're looking for a
1147+core. We parse this file with `++fade`.
1148+
1149+Now, we recurse on this to compile the structure. During the recursion,
1150+there we have threee changes. Frist, we let `zog` be `goz` so that we
1151+don't create a circular dependency. Second, we let `hol` be false since
1152+we do not allow horns in structures. Third, we let `boy` be null so that
1153+we can isolate the new body twigs.
1154+
1155+Next, we reintegrate the new data into our context. We use the context
1156+cretaed by the recursion with four changes. First, if we're including a
1157+gate structure, then we reset the body to its original body. Else we put
1158+on the top of our list of body twigs what is essentially a
1159+`=+ structure-name` to take off the face of the structure. Second, we
1160+reset `zog` to our old `zog`. Third, we reset `hol` to our old `hol`.
1161+Finally, we put in `rop` the structure hoof and body (with all body
1162+twiggs collected in a `=~`), keyed by the structure name.
1163+
1164+Finally, we recurse, processing the next structure in our list.
1165+
1166+This concludes our discussion of `++apex`.
1167+
1168+ ++ abut :: generate
1169+ |= [cof=cafe hyd=hood]
1170+ ^- (bolt vase)
1171+ %+ cope (apex cof hyd)
1172+ |= [cof=cafe sel=_..abut]
1173+ =. ..abut sel
1174+ %+ cope (maim cof pit able)
1175+ |= [cof=cafe bax=vase]
1176+ %+ cope (chap cof bax [%fan fan.hyd])
1177+ |= [cof=cafe gox=vase]
1178+ %+ cope (maim cof (slop gox bax) [%tssg (flop boy)])
1179+ |= [cof=cafe fin=vase]
1180+ (fine cof fin)
1181+
1182+Returning to `++abut`, we have now processed the structures, libraries
1183+and body twigs. Next, we slap our preamble (structures and libraries)
1184+against zuse. First, we construct our preamble in `++able`.
1185+
1186+ ++ able :: assemble preamble
1187+ ^- twig
1188+ :+ %tsgr
1189+ ?:(=(~ rop) [%$ 1] [%brcn (~(run by rop) |=([* a=twig] [%ash a]))])
1190+ [%tssg (turn (flop lot) |=(a=term q:(need (~(get by bil) a))))]
1191+
1192+We first put the structures in `rop` into a single `|%` at the top and
1193+`=>` it onto a `=~` of our libraries, in the reverse order that they
1194+appear in `lot`. Thus, the structures are in a single core while the
1195+libraries are in consecutive cores.
1196+
1197+We slap the preamble against zuse with `++maim`.
1198+
1199+ ++ maim :: slap
1200+ |= [cof=cafe vax=vase gen=twig]
1201+ ^- (bolt vase)
1202+ %+ (clef %slap) (fine cof vax gen)
1203+ |= [cof=cafe vax=vase gen=twig]
1204+ =+ puz=(mule |.((~(mint ut p.vax) [%noun gen])))
1205+ ?- -.puz
1206+ | (flaw cof p.puz)
1207+ & %+ (coup cof) (mock [q.vax q.p.puz] (mole ska))
1208+ |= val=*
1209+ `vase`[p.p.puz val]
1210+ ==
1211+
1212+Here we start to get into ford's caching system. We wrap our computation
1213+in a call to `++clef` so that we only actually compute it if the result
1214+is not already in our cache. First we'll discuss the computation, then
1215+we'll discuss the caching system.
1216+
1217+We call `++mule` with a call to `++mint:ut` on the type of our subject
1218+vase against the given twig. In other words, we're compiling the twig
1219+with against the subject type in the given subject vase.
1220+
1221+If compilation fails, then we produce an error bolt with the produced
1222+stack trace. Otherwise, we run the produced nock with `++mock` and our
1223+sky function. We convert the produced toon to a bolt with `++coup` and
1224+use the type from `puz` combined with the value from `mock` to produce
1225+our vase.
1226+
1227+If this process seems harder than just calling `++slap`, it's because it
1228+is. We have two requirements that `++slap` doesn't satisfy. First, we
1229+want the to use an explicit sky function for use with `.^`. With
1230+`++slap`, you get whatever sky function is available in the calling
1231+context, which in ford is none. Second, we want to explicitly handle the
1232+stack trace on failure. `++slap` would cause crash on failure.
1233+
1234+We haven't yet discussed either `++clef` or `++coup`. We'll start with
1235+`++coup` to finish the discussion of the computation.
1236+
1237+\``++ coup :: toon to bolt |= cof=cafe |* [ton=toon fun=$+(* *)] :- p=cof ^= q ?- -.ton %2 [%2 p=p.ton] %0 [%0 p=*(set beam) q=(fun p.ton)] %1 ~& [%coup-need ((list path) p.ton)] =- ?- -.faw & [%1 p=(sa (turn p.faw |=(a=beam [a *(list tank)])))] | [%2 p=p.faw] == ^= faw |- ^- (each (list beam) (list tank)) ?~ p.ton [%& ~] =+ nex=$(p.ton t.p.ton) =+ pax=(path i.p.ton) ?~ pax [%| (smyt pax) ?:(?=(& -.nex) ~ p.nex)] =+ zis=(tome t.pax) ?~ zis [%| (smyt pax) ?:(?=(& -.nex) ~ p.nex)] ?- -.nex & [%& u.zis p.nex] | nex == ==`
1238+
1239+Recall that a toon is either a `%0` value, a `%1` block, or a `%2`
1240+failure. Converting a `%2` toon failure into a `%2` bolt failure is
1241+trivial. Converting a `%0` toon value into a `%0` bolt value is easy
1242+since we assume there were no dependencies. Converting the blocks is
1243+rather more difficult.
1244+
1245+To compute `faw`, we recurse through the list of paths in the `%1` toon.
1246+At each one, we make sure with `++tome` that it is, in fact, a beam. If
1247+so, then we check to see if the later paths succeed as well. If so, we
1248+append the current path to the list of other paths. If not, we produce
1249+the error message we got from processing the rest of the paths. If this
1250+path is not a beam, then we fail, producing a list of tanks including
1251+this path and, if later paths fail too, those paths as well.
1252+
1253+If some paths were not beams, then we produce a `%2` error bolt. If all
1254+paths were correct, then we produce a `%1` blocking bolt.
1255+
1256+We will now discuss `++clef`. This is where the cache magic happens.
1257+
1258+ ++ clef :: cache a result
1259+ |* sem=*
1260+ |* [hoc=(bolt) fun=(burg)]
1261+ ?- -.q.hoc
1262+ %2 hoc
1263+ %1 hoc
1264+ %0
1265+ =^ cux p.hoc ((calk p.hoc) sem q.q.hoc)
1266+ ?~ cux
1267+ =+ nuf=(cope hoc fun)
1268+ ?- -.q.nuf
1269+ %2 nuf
1270+ %1 nuf
1271+ %0
1272+ :- p=(came p.nuf `calx`[sem `calm`[now p.q.nuf] q.q.hoc q.q.nuf])
1273+ q=q.nuf
1274+ ==
1275+ [p=p.hoc q=[%0 p=p.q.hoc q=((calf sem) u.cux)]]
1276+ ==
1277+
1278+If the value is already an error or a block, we just pass that through.
1279+Otherwise, we look up the request in the cache with `++calk`.
1280+
1281+ ++ calk :: cache lookup
1282+ |= a=cafe ::
1283+ |= [b=@tas c=*] ::
1284+ ^- [(unit calx) cafe] ::
1285+ =+ d=(~(get by q.a) [b c]) ::
1286+ ?~ d [~ a] ::
1287+ [d a(p (~(put in p.a) u.d))] ::
1288+
1289+When looking up something in the cache, we mark it if we find it. This
1290+way, we have in our cache the set of all cache entries that have been
1291+referenced. While we do not at present do anything with this data, it
1292+should be used to clear out old and unused entries in the cache.
1293+
1294+Moving on in `++clef`, we check to see if we actually found anything. If
1295+we didn't find a cache entry, then we run the computation in `fun`, and
1296+examine its result. If it produced a `%2` error or `%1` block bolt, we
1297+just pass that through. Otherwise, we produce both the value and an
1298+updated cache with this new entry. We add the entry with `++came`.
1299+
1300+ ++ came ::
1301+ |= [a=cafe b=calx] :: cache install
1302+ ^- cafe ::
1303+ a(q (~(put by q.a) [-.b q.b] b)) ::
1304+
1305+We key cache entries by the type of computation (`-:calx`) and the
1306+inputs to the computation (`q:calc`). This just puts the cache line in
1307+the cache at the correct key.
1308+
1309+Back in `++clef`, if we did find a cache entry, then we just produce the
1310+value at that cache line. We convert the cache line into a value with
1311+`++calf`.
1312+
1313+ ++ calf :: reduce calx
1314+ |* sem=* :: a typesystem hack
1315+ |= cax=calx
1316+ ?+ sem !!
1317+ %hood ?>(?=(%hood -.cax) r.cax)
1318+ %slap ?>(?=(%slap -.cax) r.cax)
1319+ %slam ?>(?=(%slam -.cax) r.cax)
1320+ ==
1321+
1322+This is simply a typesystem hack. Because the `sem` is passed in through
1323+a wet gate, we know at type time which of the three cases will be
1324+chosen. Thus, the correct type of the value in the cache line gets
1325+passed through to the caller. This also depends on the fact that
1326+`++clef` is wet. The type stuff here is mathematically interesting, but
1327+the action is simple: we get the value from the cache line.
1328+
1329+This concludes our discussion of `++clef` and `++maim`.
1330+
1331+Back in `++abut`, recall that we processed the structures, libraries,
1332+and body with `++apex`. Then, we slapped our preamble (structures and
1333+libraries) against zuse with `++maim`. Next, we process our resources
1334+with `++chap`. Note that we pass in the preamble so that we may refer to
1335+anything in there in our resources.
1336+
1337+`++chap` is broken up into a different case for each horn. We'll go
1338+through them one by one.
1339+
1340+ ++ chap :: produce resources
1341+ |= [cof=cafe bax=vase hon=horn]
1342+ ^- (bolt vase)
1343+ ?- -.hon
1344+ %ape (maim cof bax p.hon)
1345+
1346+This is `/~`. We slap the twig against our context.
1347+
1348+ %arg
1349+ %+ cope (maim cof bax p.hon)
1350+ |= [cof=cafe gat=vase]
1351+ (maul cof gat !>([how arg]))
1352+
1353+This is `/$`. We slap the twig against our context, which we expect to
1354+produce a gate. We slam this gate with a sample of `how` and `arg`,
1355+which is our location and the heel (virtual path extension).
1356+
1357+`++maul` is similar to `++maim`, but it slams instead of slaps.
1358+
1359+ ++ maul :: slam
1360+ |= [cof=cafe gat=vase sam=vase]
1361+ ^- (bolt vase)
1362+ %+ (clef %slam) (fine cof gat sam)
1363+ |= [cof=cafe gat=vase sam=vase]
1364+ =+ top=(mule |.((slit p.gat p.sam)))
1365+ ?- -.top
1366+ | (flaw cof p.top)
1367+ & %+ (coup cof) (mong [q.gat q.sam] (mole ska))
1368+ |= val=*
1369+ `vase`[p.top val]
1370+ ==
1371+
1372+We cache slams exactly as we cache slaps. We use `++slit` to find the
1373+type of the product of the slam given the types of the gate and the
1374+sample.
1375+
1376+If this type fails, we produce the given stack trace as a `%2` error
1377+bolt. Otherwise, we produce the top produced above combined with the
1378+value we get from slamming the values in the vases with `++mong`.
1379+
1380+Back to `++chap`.
1381+
1382+ %day (chad cof bax %dr p.hon)
1383+
1384+This is `/|`. We call `++chad` to convert textual names to relative
1385+dates and process the next horn against each of the discovered paths.
1386+
1387+ ++ chad :: atomic list
1388+ |= [cof=cafe bax=vase doe=term hon=horn]
1389+ ^- (bolt vase)
1390+ %+ cope ((lash (slat doe)) cof how)
1391+ |= [cof=cafe yep=(map ,@ span)]
1392+ =+ ^= poy ^- (list (pair ,@ span))
1393+ %+ sort (~(tap by yep) ~)
1394+ |=([a=[@ *] b=[@ *]] (lth -.a -.b))
1395+ %+ cope
1396+ |- ^- (bolt (list (pair ,@ vase)))
1397+ ?~ poy (fine cof ~)
1398+ %+ cope $(poy t.poy)
1399+ |= [cof=cafe nex=(list (pair ,@ vase))]
1400+ %+ cope (chap(s.how [q.i.poy s.how]) cof bax hon)
1401+ |= [cof=cafe elt=vase]
1402+ (fine cof [[p.i.poy elt] nex])
1403+ |= [cof=cafe yal=(list (pair ,@ vase))]
1404+ %+ fine cof
1405+ |- ^- vase
1406+ ?~ yal [[%cube 0 [%atom %n]] 0]
1407+ (slop (slop [[%atom doe] p.i.yal] q.i.yal) $(yal t.yal))
1408+
1409+First, we call `++lash` to parse the children of the current beam and
1410+pick out those ones that are of the requested format.
1411+
1412+ ++ lash :: atomic sequence
1413+ |= wox=$+(span (unit ,@))
1414+ |= [cof=cafe bem=beam]
1415+ ^- (bolt (map ,@ span))
1416+ %+ cope (lend cof bem)
1417+ |= [cof=cafe arc=arch]
1418+ (fine cof (lark wox arc))
1419+
1420+First, we get the arch with `++lend`, as described above. We filter and
1421+parse the child names with `++lark` according to the given parser
1422+function.
1423+
1424+In `++chad`, this parser function is `(slat doe)`, which will parse a
1425+cord into an atom of the requested odor. For `%day` the odor is for
1426+relative dates.
1427+
1428+Thus, we now have a map from atoms of the given odor to the actual child
1429+names. We next turn this map into a list and sort it in increasing order
1430+by the atom.
1431+
1432+We next convert this list of pairs of atoms and spans to a list of pairs
1433+of atoms and vases. We process the given horn once at every child beam,
1434+producing the resource at that location.
1435+
1436+Finally, we convert this list of pairs of atoms and vases to a vase of a
1437+list of pairs of atoms to (well-typed) values. Each entry in the list is
1438+of type atom with the given odor combined with the type of the produced
1439+vase.
1440+
1441+Back in `++chap`, we continue parsing resources.
1442+
1443+ %dub
1444+ %+ cope $(hon q.hon)
1445+ |= [cof=cafe vax=vase]
1446+ (fine cof [[%face p.hon p.vax] q.vax])
1447+
1448+This is `/=`. We process the given horn, giving us a vase. We put as a
1449+face on the vase so that it may be referred to later by name.
1450+
1451+ %fan
1452+ %+ cope
1453+ |- ^- (bolt (list vase))
1454+ ?~ p.hon (fine cof ~)
1455+ %+ cope ^$(hon i.p.hon)
1456+ |= [cof=cafe vax=vase]
1457+ %+ cope ^$(cof cof, p.hon t.p.hon)
1458+ |= [cof=cafe tev=(list vase)]
1459+ (fine cof [vax tev])
1460+ |= [cof=cafe tev=(list vase)]
1461+ %+ fine cof
1462+ |- ^- vase
1463+ ?~ tev [[%cube 0 [%atom %n]] 0]
1464+ (slop i.tev $(tev t.tev))
1465+
1466+This is `/.`. We first process each of the child horns, producing a list
1467+of vases. This is done by just recursing on `++chap`. Then, we simply
1468+fold over this list to create a vase of the list of values.
1469+
1470+ %for $(hon q.hon, s.how (weld (flop p.hon) s.how))
1471+
1472+This is `/,`. We simply recurse on the horn with the given path welded
1473+onto our current beam.
1474+
1475+ %hub (chad cof bax %ud p.hon)
1476+
1477+This is `/@`. This is exactly like the processing of `%day` except we
1478+expect the children to be named as unsigned integers rather than
1479+relative dates. We process the horn at each of the children's locations
1480+and produce a list of pairs of absolute dates and values.
1481+
1482+ %man
1483+ |- ^- (bolt vase)
1484+ ?~ p.hon (fine cof [[%cube 0 [%atom %n]] 0])
1485+ %+ cope $(p.hon l.p.hon)
1486+ |= [cof=cafe lef=vase]
1487+ %+ cope ^$(cof cof, p.hon r.p.hon)
1488+ |= [cof=cafe rig=vase]
1489+ %+ cope ^^^$(cof cof, hon q.n.p.hon)
1490+ |= [cof=cafe vax=vase]
1491+ %+ fine cof
1492+ %+ slop
1493+ (slop [[%atom %tas] p.n.p.hon] vax)
1494+ (slop lef rig)
1495+
1496+This is `/*`. We process each of the horns in the given map by recursion
1497+through `++chap`. Once we have these vases, we create a vase of a map
1498+from the given textual names to the produced values.
1499+
1500+ %now (chad cof bax %da p.hon)
1501+
1502+This is `/&`. This is exactly like the processing of `%now` except we
1503+expect the children to be names as absolute dates rather than relative
1504+dates. We process the horn at each of the children's locations and
1505+produce a list of pairs of absolute dates and values.
1506+
1507+ %nap (chai cof bax p.hon)
1508+
1509+This is `/%`. Here, we process the horn at each of our children with
1510+`++chai`.
1511+
1512+ ++ chai :: atomic map
1513+ |= [cof=cafe bax=vase hon=horn]
1514+ ^- (bolt vase)
1515+ %+ cope (lend cof how)
1516+ |= [cof=cafe arc=arch]
1517+ %+ cope
1518+ |- ^- (bolt (map ,@ vase))
1519+ ?~ r.arc (fine cof ~)
1520+ %+ cope $(r.arc l.r.arc)
1521+ |= [cof=cafe lef=(map ,@ vase)]
1522+ %+ cope `(bolt (map ,@ vase))`^$(cof cof, r.arc r.r.arc)
1523+ |= [cof=cafe rig=(map ,@ vase)]
1524+ %+ cope (chap(s.how [p.n.r.arc s.how]) cof bax hon)
1525+ |= [cof=cafe nod=vase]
1526+ (fine cof [[p.n.r.arc nod] lef rig])
1527+ |= [cof=cafe doy=(map ,@ vase)]
1528+ %+ fine cof
1529+ |- ^- vase
1530+ ?~ doy [[%cube 0 [%atom %n]] 0]
1531+ %+ slop
1532+ (slop [[%atom %a] p.n.doy] q.n.doy)
1533+ (slop $(doy l.doy) $(doy r.doy))
1534+
1535+We get the arch at our current beam with `++lend`. Then, we process the
1536+horn at each of our children to give us a map of atoms to vases.
1537+Finally, we convert that into a vase of a map of these atoms to the
1538+values. This is very similar to `++chad` and the handling of `%man`.
1539+
1540+ %see $(hon q.hon, how p.hon)
1541+
1542+This is `/:`. We process the given horn at the given beam.
1543+
1544+ %saw
1545+ %+ cope $(hon q.hon)
1546+ |= [cof=cafe sam=vase]
1547+ %+ cope (maim cof bax p.hon)
1548+ |= [cof=cafe gat=vase]
1549+ (maul cof gat sam)
1550+
1551+This is `/;`. First, we process the given horn. Then, we slap the given
1552+twig against our context to produce (hopefully) a gate. Finally, we slam
1553+the vase we got from processing the horn against the gate.
1554+
1555+ %sic
1556+ %+ cope $(hon q.hon)
1557+ |= [cof=cafe vax=vase]
1558+ %+ cope (maim cof bax [%bctr p.hon])
1559+ |= [cof=cafe tug=vase]
1560+ ?. (~(nest ut p.tug) | p.vax)
1561+ (flaw cof [%leaf "type error: {<p.hon>} {<q.hon>}"]~)
1562+ (fine cof [p.tug q.vax])
1563+
1564+This is `/^`. First, we process the given horn. Then, we slap the the
1565+bunt of the given tile against our context. This will produce a vase
1566+with the correct type. We test to see if this type nests within the type
1567+of the vase we got from processing the horn. If so, we produce the value
1568+from the horn along with the type from the tile. Otherwise, we produce a
1569+`%2` error bolt.
1570+
1571+ %toy (cope (make cof %bake p.hon how ~) feel)
1572+ ==
1573+
1574+This is `/mark/`. Here, we simply run the `%bake` silk on the given
1575+mark, producing a cage. We convert this cage into a vase with `++feel`,
1576+which is exactly as simple as it sounds like it should be.
1577+
1578+ ++ feel |=([a=cafe b=cage] (fine a q.b)) :: cage to vase
1579+
1580+This is trivial.
1581+
1582+We will discuss later `++make` and how `%bake` is processed. Suffice it
1583+to say that baking a resource with a given mark gets the resource and
1584+converts it, if necessary, to the requested mark.
1585+
1586+This concludes our discussion of `++chap`.
1587+
1588+We return once more to `++abut`.
1589+
1590+ ++ abut :: generate
1591+ |= [cof=cafe hyd=hood]
1592+ ^- (bolt vase)
1593+ %+ cope (apex cof hyd)
1594+ |= [cof=cafe sel=_..abut]
1595+ =. ..abut sel
1596+ %+ cope (maim cof pit able)
1597+ |= [cof=cafe bax=vase]
1598+ %+ cope (chap cof bax [%fan fan.hyd])
1599+ |= [cof=cafe gox=vase]
1600+ %+ cope (maim cof (slop gox bax) [%tssg (flop boy)])
1601+ |= [cof=cafe fin=vase]
1602+ (fine cof fin)
1603+
1604+Recall that we processed our structures, libraries and body with
1605+`++apex`. We slapped our structures and libraries against zuse with
1606+`++maim`. We processed our resources with `++chap`. Now, all our body
1607+twigs are collected in a `=~` and slapped against our structures,
1608+libraries, and resources. This produces our final result.
1609+
1610+The hook file has been assembled. And there was great rejoicing.
1611+
1612+Lifecycle of a Kiss
1613+-------------------
1614+
1615+We're now going to go through a series of lifecycle descriptions. When a
1616+user of ford sends a kiss, it is one of a dozen different types of silk.
1617+We'll go through each one, tracing through the flow of control of each
1618+of these.
1619+
1620+First, though, we'll describe the common handling to all kisses.
1621+
1622+The silk in a `%exec` kiss to ford ends up in `++apex`, so we'll enter
1623+the narrative here.
1624+
1625+ ++ apex :: call
1626+ |= kus=(unit silk)
1627+ ^+ +>
1628+ ?~ kus
1629+ =+ nym=(~(get by dym.bay) hen)
1630+ ?~ nym :: XX should never
1631+ ~& [%ford-mystery hen]
1632+ +>.$
1633+ =+ tas=(need (~(get by q.tad.bay) u.nym))
1634+ amok:~(camo zo [u.nym tas])
1635+ =+ num=p.tad.bay
1636+ ?< (~(has by dym.bay) hen)
1637+ =: p.tad.bay +(p.tad.bay)
1638+ dym.bay (~(put by dym.bay) hen num)
1639+ ==
1640+ ~(exec zo [num `task`[hen u.kus 0 ~]])
1641+
1642+Recall that a `%exec` kiss actually sends a unit silk. If it's null,
1643+we're trying to cancel the request. We first look up the task number
1644+keyed by duct. If we don't find it, then we're trying to cancel a
1645+request that either was never started or has already completed. We print
1646+out `%ford-mystery` and do nothing. If we do find the task number, then
1647+we look up the task from it, call `++camo:zo` to cancel pending
1648+requests, and call `++amok:zo` to remove the task from our task lists.
1649+
1650+ ++ camo :: stop requests
1651+ ^+ .
1652+ =+ kiz=(~(tap by q.kig) *(list ,[p=@ud q=beam]))
1653+ |- ^+ +>
1654+ ?~ kiz +>
1655+ %= $
1656+ kiz t.kiz
1657+ mow :_ mow
1658+ :- hen
1659+ :^ %pass [(scot %p our) (scot %ud num) (scot %ud p.i.kiz) ~]
1660+ %c
1661+ [%warp [our p.q.i.kiz] q.q.i.kiz ~]
1662+ ==
1663+
1664+Our list of blocks is in `q.kig`, so we iterate over it, cancelling our
1665+pending requests for each block. Our requests are all to clay, so we
1666+need only to send `%warp` kisses with a null instead of a rave.
1667+
1668+ ++ amok
1669+ %_ ..zo
1670+ q.tad.bay (~(del by q.tad.bay) num)
1671+ dym.bay (~(del by dym.bay) nah)
1672+ ==
1673+
1674+We remove the task number from the map of numbers to tasks and the duct
1675+from the map of ducts to task numbers.
1676+
1677+Back in `++apex`, if we were given a silk, we need to process it. We add
1678+the task to our maps, increment the next task number, and call
1679+`++exec:zo` on the new task.
1680+
1681+ ++ exec :: execute app
1682+ ^+ ..zo
1683+ ?: !=(~ q.kig) ..zo
1684+ |- ^+ ..zo
1685+ =+ bot=(make [~ jav.bay] kas)
1686+ =. ..exec (dash p.bot)
1687+ ?- -.q.bot
1688+ %0 amok:(expo [%made %& p.q.bot q.q.bot])
1689+ %2 amok:(expo [%made %| p.q.bot])
1690+ %1 =+ zuk=(~(tap by p.q.bot) ~)
1691+ =< abet
1692+ |- ^+ ..exec
1693+ ?~ zuk ..exec
1694+ =+ foo=`_..exec`(camp %x `beam`p.i.zuk)
1695+ $(zuk t.zuk, ..exec foo)
1696+ ==
1697+
1698+If we're still blocked on something in `q.kig`, we don't do anything.
1699+
1700+Otherwise, we try to process the silk with `++make`. `++make` handles
1701+each individual request and will be the entire focus of the remainder of
1702+this doc after this section. It produces a bolt of a cage.
1703+
1704+We put the new cache in our state with `++dash`.
1705+
1706+ ++ dash :: process cache
1707+ |= cof=cafe
1708+ ^+ +>
1709+ %_(+> jav.bay q.cof)
1710+
1711+The cache is put in the baby so that it gets stored across calls to
1712+ford.
1713+
1714+In `++exec`, we process the bolt in three different ways according to
1715+the type of bolt produced. If we produced a `%0` value bolt, we use
1716+`++expo` to give the produced value and set of dependencies as a `%made`
1717+gift, and we remove ourselves from the task list with `++amok`.
1718+
1719+ ++ expo :: return gift
1720+ |= gef=gift
1721+ %_(+> mow :_(mow [hen %give gef]))
1722+
1723+We simply push the gift onto our list of moves.
1724+
1725+In `++exec`, if we produced a `%2` error bolt, we produce a `%made` gift
1726+with the stack trace.
1727+
1728+If we produced a `%1` block bolt, we iterate through each of the blocks
1729+and call `++camp` to produce a clay request for the resource.
1730+
1731+ ++ camp :: request a file
1732+ |= [ren=care bem=beam]
1733+ ^+ +>
1734+ %= +>
1735+ kig [+(p.kig) (~(put by q.kig) p.kig bem)]
1736+ mow :_ mow
1737+ :- hen
1738+ :^ %pass [(scot %p our) (scot %ud num) (scot %ud p.kig) ~]
1739+ %c
1740+ [%warp [our p.bem] q.bem [~ %& %x r.bem s.bem]]
1741+ ==
1742+
1743+We put the resource in our block list in `q.kig` so that we save the
1744+fact that we're blocked. We then produce the `%warp` request to clay for
1745+the resource. Our request path has the format
1746+\`/[our-ship]/[task-number]/[block-number]'.
1747+
1748+We'll now describe how each of the individual silks are processed in
1749+`++make`.
1750+
1751+Lifecycle of a Cell
1752+-------------------
1753+
1754+ ^
1755+ %. [cof p.kas q.kas]
1756+ ;~ cope
1757+ ;~ coax
1758+ |=([cof=cafe p=silk q=silk] ^$(cof cof, kas p.kas))
1759+ |=([cof=cafe p=silk q=silk] ^$(cof cof, kas q.kas))
1760+ ==
1761+ ::
1762+ |= [cof=cafe bor=cage heg=cage] ^- (bolt cage)
1763+ [p=cof q=[%0 ~ [%$ (slop q.bor q.heg)]]]
1764+ ==
1765+
1766+Silks autocons. The product of a cell of silks is a cell of the products
1767+of the silks, so we evaluate the two silks in parallel with `++coax` and
1768+slop together the results in a cell vase. We mark the product with `%$`,
1769+which means we know no more mark information than that it is a noun.
1770+
1771+ ++ coax :: bolt across
1772+ |* [hoc=(bolt) fun=(burg)]
1773+ ?- -.q.hoc
1774+ %0 =+ nuf=$:fun(..+<- p.hoc)
1775+ :- p=p.nuf
1776+ ^= q
1777+ ?- -.q.nuf
1778+ %0 [%0 p=(grom p.q.hoc p.q.nuf) q=[q.q.hoc q.q.nuf]]
1779+ %1 q.nuf
1780+ %2 q.nuf
1781+ ==
1782+ %1 =+ nuf=$:fun(..+<- p.hoc)
1783+ :- p=p.nuf
1784+ ^= q
1785+ ?- -.q.nuf
1786+ %0 q.hoc
1787+ %1 [%1 p=(grom p.q.nuf p.q.hoc)]
1788+ %2 q.nuf
1789+ ==
1790+ %2 hoc
1791+ ==
1792+
1793+If the first bolt is a value, we evaluate the burg to get the next bolt.
1794+If that also produces a value, we merge the dependency sets and produce
1795+a cell of the two values. Otherwise, we produce the block or error of
1796+the second bolt.
1797+
1798+If the first bolt is a block, we evaluate the burg to get the next bolt.
1799+If that produces a value, we just produce the block. If it produces a
1800+block, we merge the two block sets. If it produces an error, we produce
1801+that error.
1802+
1803+If the first bolt is already an error, we just pass that through.
1804+
1805+Note that `++coax` (and, indeed, `++cope`) is reasonable to use with
1806+`;~`.
1807+
1808+Lifecycle of a `%bake`
1809+----------------------
1810+
1811+ %bake
1812+ %+ cool |.(leaf/"ford: bake {<p.kas>} {<(tope q.kas)>}")
1813+ %+ cope (lima cof p.kas q.kas r.kas)
1814+ |= [cof=cafe vux=(unit vase)]
1815+ ?~ vux
1816+ (flaw cof (smyt (tope q.kas)) ~)
1817+ (fine cof [p.kas u.vux])
1818+
1819+This is one of the most critical silks. We are going to functionally
1820+produce the hook file at the given beam with the given heel. The result
1821+will be of the correct mark, even if we need to run conversion
1822+functions. The functionality is encapsulated in `++lime`. If it produces
1823+null, then we produce an error. Otherwise, we take the vase produced and
1824+give it the correct mark.
1825+
1826+ ++ lima :: load at depth
1827+ |= [cof=cafe for=mark bem=beam arg=heel]
1828+ ^- (bolt (unit vase))
1829+ %+ cope (lend cof bem)
1830+ |= [cof=cafe arc=arch]
1831+ ^- (bolt (unit vase))
1832+ ?: (~(has by r.arc) for)
1833+ (lace cof for bem(s [for s.bem]) arg)
1834+ =+ haz=(turn (~(tap by r.arc) ~) |=([a=@tas b=~] a))
1835+ ?~ haz (fine cof ~)
1836+ %+ cope (lion cof for -.bem haz)
1837+ |= [cof=cafe wuy=(unit (list ,@tas))]
1838+ ?~ wuy (fine cof ~)
1839+ ?> ?=(^ u.wuy)
1840+ %+ cope (make cof %bake i.u.wuy bem arg)
1841+ |= [cof=cafe hoc=cage]
1842+ %+ cope (lope cof i.u.wuy t.u.wuy -.bem q.hoc)
1843+ |= [cof=cafe vax=vase]
1844+ (fine cof ~ vax)
1845+
1846+First, we load the arch at the given beam with `++lend`. If we have a
1847+child named the mark, our job is straightforward, so we go ahead and
1848+load that with `++lace`.
1849+
1850+Otherwise, we iterate through our children. If we have no children, we
1851+produce null, signifying that we didn't find any way to convert to the
1852+requested mark. Otherwise, we call `++lion` to find a translation path
1853+from one of the available marks into the target mark. We recursively
1854+bake the child that has a path to the target mark, and then we call
1855+`++lope` to translate this mark into the target mark.
1856+
1857+We'll first discuss the direct case of when one of our children is of
1858+the correct mark.
1859+
1860+ ++ lace :: load and check
1861+ |= [cof=cafe for=mark bem=beam arg=heel]
1862+ ^- (bolt (unit vase))
1863+ =+ bek=`beak`[p.bem q.bem r.bem]
1864+ %+ cope (lend cof bem)
1865+ |= [cof=cafe arc=arch]
1866+ ?^ q.arc
1867+ (cope (cope (liar cof bem) (lake for bek)) fest)
1868+ ?: (~(has by r.arc) %hook)
1869+ %+ cope (fade cof %hook bem)
1870+ |= [cof=cafe hyd=hood]
1871+ (cope (cope (abut:(meow bem arg) cof hyd) (lake for bek)) fest)
1872+ (fine cof ~)
1873+
1874+First, we get the arch at the given beam with `++lend`. If this is a
1875+file, we load the file with `++liar` and coerce the type with `++lake`.
1876+Otherwise, we check to see if we have a hook file here. If so, we parse
1877+it with `++fade`, compile it with `++abut:meow`, and coerce the type
1878+with `++lake`.
1879+
1880+Otherwise, there is no way to translate this, so we produce null.
1881+
1882+`++fest` is one line, so we'll get that one out of the way first.
1883+
1884+ ++ fest |*([a=cafe b=*] (fine a [~ u=b])) :: bolt to unit
1885+
1886+This is just `++some` for bolts.
1887+
1888+We've delayed the discussion of `++fade` far too many times. It's not
1889+complicated, we just wanted to spare a premature discussion of `++make`
1890+and the `%bake` silk. We 're now able to discuss everything in `++fade`
1891+with ease.
1892+
1893+ ++ fade :: compile to hood
1894+ |= [cof=cafe for=mark bem=beam]
1895+ ^- (bolt hood)
1896+ %+ cool |.(leaf/"ford: fade {<[(tope bem)]>}")
1897+ %+ cope (make cof [%bake for bem ~])
1898+ |= [cof=cafe cay=cage]
1899+ %+ (clef %hood) (fine cof bem cay)
1900+ ^- (burg (pair beam cage) hood)
1901+ |= [cof=cafe bum=beam cay=cage]
1902+ =+ rul=(fair bem)
1903+ ?. ?=(@ q.q.cay)
1904+ (flaw cof ~)
1905+ =+ vex=((full rul) [[1 1] (trip q.q.cay)])
1906+ ?~ q.vex
1907+ (flaw cof [%leaf "syntax error: {<p.p.vex>} {<q.p.vex>}"] ~)
1908+ (fine cof p.u.q.vex)
1909+
1910+We first push a line onto a stack trace to say that we're parsing into a
1911+hood file.
1912+
1913+We bake the given beam with the given mark and no heel. Recall that
1914+baking gate, core, door, hoon, and hook files produces simply an atom of
1915+the text. We check to make sure that our value is an atom, failing
1916+otherwise.
1917+
1918+The parsing step is run within `++clef` so that the result is cached. We
1919+call `++fair` with the current beam to generate the parsing rule, and we
1920+parse the file. If parsing fails, we fail giving a syntax error with the
1921+line and column number. Otherwise, we produce the value.
1922+
1923+ ++ liar :: load vase
1924+ |= [cof=cafe bem=beam]
1925+ ^- (bolt vase)
1926+ =+ von=(ska %cx (tope bem))
1927+ ?~ von
1928+ [p=*cafe q=[%1 [[bem ~] ~ ~]]]
1929+ ?~ u.von
1930+ (flaw cof (smyt (tope bem)) ~)
1931+ (fine cof ?^(u.u.von [%cell %noun %noun] [%atom %$]) u.u.von)
1932+
1933+This takes a beam and loads the file at that location. If our sky
1934+function produces null, that means the resource is currently
1935+unavailable, so we block on it. If it produces `[~ ~]`, that means our
1936+resource is permanently unavailable, so we produce an error. Otherwise,
1937+we produce the value there with a type of either a cell of two nouns or
1938+an atom, depending on whether the value is a cell or not.
1939+
1940+Back in `++lima`, recall that we call `++lion` to find a translation
1941+path.
1942+
1943+ ++ lion :: translation search
1944+ |= [cof=cafe too=@tas bek=beak fro=(list ,@tas)]
1945+ ^- (bolt (unit (list ,@tas)))
1946+ =| war=(set ,@tas)
1947+ =< -:(apex (fine cof fro))
1948+ |%
1949+ ++ apex
1950+ |= rof=(bolt (list ,@tas))
1951+ ^- [(bolt (unit (list ,@tas))) _+>]
1952+ ?. ?=(%0 -.q.rof) [rof +>.$]
1953+ ?~ q.q.rof
1954+ [[p.rof [%0 p.q.rof ~]] +>.$]
1955+ =^ orf +>.$ (apse cof i.q.q.rof)
1956+ ?. ?=(%0 -.q.orf)
1957+ [orf +>.$]
1958+ ?~ q.q.orf
1959+ $(cof p.orf, q.q.rof t.q.q.rof)
1960+ [[p.orf [%0 (grom p.q.rof p.q.orf) q.q.orf]] +>.$]
1961+ ::
1962+ ++ apse
1963+ |= [cof=cafe for=@tas]
1964+ ^- [(bolt (unit (list ,@tas))) _+>]
1965+ ?: =(for too)
1966+ [(fine cof [~ too ~]) +>.$]
1967+ ?: (~(has in war) for) [(fine cof ~) +>]
1968+ =. war (~(put in war) for)
1969+ =^ hoc +>.$ (apex (lily cof for bek))
1970+ :_ +>.$
1971+ %+ cope hoc
1972+ |= [cof=cafe ked=(unit (list ,@tas))]
1973+ (fine cof ?~(ked ~ [~ for u.ked]))
1974+ --
1975+
1976+At a high level, we have `++apex` and `++apse`. `++apex` takes a list of
1977+marks to try in succession until we find one that can be translated into
1978+the target mark. On each one, it calls `++apse`, which takes a single
1979+mark and tries to find a translation path from this mark to the target.
1980+To do this, it sees which marks we know how to directly translate to,
1981+and calls `++apex` on this list. The result of this mututal recursion is
1982+a depth-first search of the translation graph to find the target mark.
1983+Since the translation graph is not necessarily acyclic, we maintain a
1984+set of marks that we've already tried.
1985+
1986+We kick off our search in `++apex`, starting with the given initial list
1987+of marks that we know how to get to.
1988+
1989+If `++apex` is called with a bolt other than a `%0` value bolt, we
1990+simply produce it. Otherwise, we check to see if the list of available
1991+marks to investigate is null. If so, then we're done, so we produce a
1992+`%0` bolt with a null list of accessible marks.
1993+
1994+Otherwise, we process this next mark with `++apse`, which will produce a
1995+possible list of marks from this one to the target mark. If it fails to
1996+produce a `%0` bolt, we just produce that. Otherwise, if it produces
1997+null, we can't get to our target through this mark, so we move on to the
1998+next one.
1999+
2000+If it doesn't produce null, then we have successfully found a
2001+translation path, so we produce it.
2002+
2003+In `++apse`, we first test to see if we've arrived at the target path.
2004+If so, we're done, so we produce a list including just ourself.
2005+Otherwise, we check to see if we've already tried this mark. If so, we
2006+know we can't succeed here, so we produce null. Otherwise, we put
2007+ourselves in the set of already-tried marks, and we move on.
2008+
2009+We call `++lily` to get the list of marks we can translate this one
2010+into.
2011+
2012+ ++ lily :: translation targets
2013+ |= [cof=cafe for=mark bek=beak]
2014+ ^- (bolt (list ,@tas))
2015+ =+ raf=(fang cof for bek)
2016+ ?: =(%2 -.q.raf) (fine p.raf ~)
2017+ %+ cope raf
2018+ |= [cof=cafe vax=vase]
2019+ %+ fine cof
2020+ %+ weld
2021+ ^- (list ,@tas)
2022+ ?. (slab %garb p.vax) ~
2023+ =+ gav=((soft (list ,@tas)) q:(slap vax [%cnzy %garb]))
2024+ ?~(gav ~ u.gav)
2025+ ?. (slab %grow p.vax) ~
2026+ =+ gow=(slap vax [%cnzy %grow])
2027+ (sloe p.gow)
2028+
2029+We call `++fang` to get the mark definition door. This is documented
2030+under `%vale`. If getting the mark fails, we produce null because we
2031+can't translate a non-existent mark into anything.
2032+
2033+Otherwise, we examine the door. The door may have a `++garb`, which is
2034+simply a list of marks which know how to translate from the current one.
2035+There must be a corresponding `++grab` in the definition of the other
2036+mark, though we don't check that here.
2037+
2038+The door may also have a `++grow`, which defines how to translate this
2039+mark into another one. Each arm in `++grow` is the name of a mark we can
2040+translate into. The call to `++sloe` simply produces a list of arm names
2041+in `++grow`.
2042+
2043+Back in `++apse:lion`, we take the list of translation targets we just
2044+found and call `++apex` on it. If we got back a null, we produce a null;
2045+otherwise, we produce the list of marks we got back plus the current
2046+mark.
2047+
2048+This concludes our discussion of `++lion`.
2049+
2050+The final piece of `++lima` is `++lope`, which performs the actual
2051+translation along the path we just computed.
2052+
2053+ ++ lope :: translation pipe
2054+ |= [cof=cafe for=mark yaw=(list mark) bek=beak vax=vase]
2055+ ^- (bolt vase)
2056+ ?~ yaw (fine cof vax)
2057+ %+ cope (link cof i.yaw for bek vax)
2058+ |= [cof=cafe yed=vase]
2059+ ^$(cof cof, for i.yaw, yaw t.yaw, vax yed)
2060+
2061+We iterate through our list, calling `++link` on every adjacent pair of
2062+marks, translating from one mark to the next until we finish the list of
2063+marks. A call to `++link` is equivalent to a `%cast` silk, so we
2064+document it there. After we've called performed every step in the
2065+translation pipeline, we're done.
2066+
2067+Lifecycle of a `%boil`
2068+----------------------
2069+
2070+ %boil
2071+ %+ cool |.(leaf/"ford: boil {<p.kas>} {<(tope q.kas)>} {<r.kas>}")
2072+ %+ cope (lamp cof q.kas)
2073+ |= [cof=cafe bem=beam]
2074+ %+ cope (lime cof p.kas bem r.kas)
2075+ |= [cof=cafe vax=vase]
2076+ (fine cof `cage`[p.kas vax])
2077+
2078+At a high level, we try to bake at the given beam, and if it fails, we
2079+go up a level and try again. This is the usual semantics of ford, and
2080+this should nearly always be preferred over directly baking.
2081+
2082+First, we normalize the version case to a number with `++lamp`. This
2083+allows caching to be based on revision number rather than something more
2084+ephemeral like a particular time.
2085+
2086+ ++ lamp :: normalize version
2087+ |= [cof=cafe bem=beam]
2088+ ^- (bolt beam)
2089+ =+ von=(ska %cw (tope bem(s ~)))
2090+ ?~ von [p=cof q=[%1 [bem ~] ~ ~]]
2091+ (fine cof bem(r [%ud ((hard ,@) (need u.von))]))
2092+
2093+We call the sky function with `%cw`, asking clay for the revision number
2094+at this case. If the case refers to a revision that isn't there yet, we
2095+produce a `%1` blocking bolt. Otherwise, we require that the value exist
2096+and that it's a number, both of which are guaranteed by clay. We produce
2097+this number.
2098+
2099+Next for `%boil` we call `++lime` to try to load the beam.
2100+
2101+ ++ lime :: load beam
2102+ |= [cof=cafe for=mark bem=beam arg=heel]
2103+ =+ [mob=bem mer=(flop arg)]
2104+ |- ^- (bolt vase)
2105+ %+ cope (lima cof for mob (flop mer))
2106+ |= [cof=cafe vux=(unit vase)]
2107+ ?^ vux (fine cof u.vux)
2108+ ?~ s.mob
2109+ (flaw cof (smyt (tope bem)) ~)
2110+ ^$(s.mob t.s.mob, mer [i.s.mob mer])
2111+
2112+We start at the given beam and try to bake it. If it succeeds, we're
2113+good. Otherwise, we pop off the top level of the path and put it in our
2114+heel (virtual path extension). We do this recursively until either we
2115+find something we can bake or we've gone all the way up to the root path
2116+of the desk, in which case we fail.
2117+
2118+Lifecycle of a `%call`
2119+----------------------
2120+
2121+ %call
2122+ %+ cool |.(leaf/"ford: call {<`@p`(mug kas)>}")
2123+ %. [cof p.kas q.kas]
2124+ ;~ cope
2125+ ;~ coax
2126+ |=([cof=cafe p=silk q=silk] ^$(cof cof, kas p))
2127+ |=([cof=cafe p=silk q=silk] ^$(cof cof, kas q))
2128+ ==
2129+ ::
2130+ |= [cof=cafe gat=cage sam=cage]
2131+ (maul cof q.gat q.sam)
2132+ ::
2133+ |= [cof=cafe vax=vase]
2134+ (fine cof %noun vax)
2135+ ==
2136+
2137+This is slam for silks. We process both of the given silks in parallel
2138+with `++coax`. We then slam the two produced vases together with
2139+`++maul` and mark the produced vase with `%noun` since we don't know any
2140+more specific mark.
2141+
2142+`++coax` is documented under Lifecycle of a Cell.
2143+
2144+Lifecycle of a `%cast`
2145+----------------------
2146+
2147+ %cast
2148+ %+ cool |.(leaf/"ford: cast {<p.kas>}")
2149+ %+ cope $(kas q.kas)
2150+ |= [cof=cafe cay=cage]
2151+ %+ cope (link cof p.kas p.cay [our %main %da now] q.cay)
2152+ |= [cof=cafe vax=vase]
2153+ (fine cof [p.kas vax])
2154+
2155+This is a request to convert data of one mark to another mark directly.
2156+We evaluate the given silk and pass the result into `++link`, which
2157+performs the actual translation. Note that this will not search for
2158+indirect conversion paths, so the conversion must be defined either in
2159+the `++grow` of the given mark or the `++grab` of the target mark.
2160+
2161+ ++ link :: translate
2162+ |= [cof=cafe too=mark for=mark bek=beak vax=vase]
2163+ ^- (bolt vase)
2164+ ?: =(too for) (fine cof vax)
2165+ ?: |(=(%noun for) =(%$ for))
2166+ ((lake too bek) cof vax)
2167+ %+ cope (fang cof for bek)
2168+ |= [cof=cafe pro=vase]
2169+ ?: &((slab %grow p.pro) (slab too p:(slap pro [%cnzy %grow])))
2170+ %+ cope (keel cof pro [[%& 6]~ vax]~)
2171+ |= [cof=cafe pox=vase]
2172+ (maim cof pox [%tsgr [%cnzy %grow] [%cnzy too]])
2173+ %+ cope (fang cof too bek)
2174+ |= [cof=cafe pro=vase]
2175+ =+ ^= zat ^- (unit vase)
2176+ ?. (slab %grab p.pro) ~
2177+ =+ gab=(slap pro [%cnzy %grab])
2178+ ?. (slab for p.gab) ~
2179+ `(slap gab [%cnzy for])
2180+ ?~ zat
2181+ (flaw cof [%leaf "ford: no link: {<[for too]>}"]~)
2182+ (maul cof u.zat vax)
2183+
2184+This performs one step in the translation pipeline. If the given and
2185+target marks are the same, we're done. If we're translating from a noun
2186+or the empty mark, we coerce with `++lake` (documented in `%vale`).
2187+Otherwise, we're translating from a user-defined mark.
2188+
2189+We load the definition of the given mark with `++fang`, and we check to
2190+see if it has an arm in `++grow` named the target mark. If so, we place
2191+our data in the sample of the door with `++keel` and slap the arm.
2192+`++keel` is equivalent to a `%mute` silk, so we document it there.
2193+
2194+If there is no arm in `++grow` of the given mark named the target mark,
2195+we suppose there must be an arm in `++grab` of the target mark named the
2196+given mark. We get the definition of the target mark and check to see if
2197+it has the required arm, failing if it doesn't. Finally, we slam the
2198+data against the correct arm, producing the translated data.
2199+
2200+If you're confused as to why the handling of `++grow` and `++grab` look
2201+superficially so different, remember that the correct arm in `++grow`
2202+does not have a sample while the one in `++grab` does. This means they
2203+must be called rather differently.
2204+
2205+Lifecycle of a `%diff`
2206+----------------------
2207+
2208+ %diff
2209+ %+ cool |.(leaf/"ford: diff {<`@p`(mug p.kas)>} {<`@p`(mug q.kas)>}")
2210+ (diff cof p.kas q.kas)
2211+
2212+We push debug information onto the trace and go right to `++diff`.
2213+
2214+ ++ diff
2215+ |= [cof=cafe kas=silk kos=silk]
2216+ ^- (bolt cage)
2217+ %. [cof kas kos]
2218+ ;~ cope
2219+ ;~ coax
2220+ |=([cof=cafe p=silk q=silk] (make cof p))
2221+ |=([cof=cafe p=silk q=silk] (make cof q))
2222+ ==
2223+ |= [cof=cafe cay=cage coy=cage]
2224+
2225+First, we process the two given silks to get our arguments.
2226+
2227+ ?. =(p.cay p.coy)
2228+ %+ flaw cof :_ ~
2229+ leaf/"diff on data of different marks: {(trip p.cay)} {(trip p.coy)}"
2230+
2231+If the two cages have different marks, then we can't diff them, so we
2232+complain.
2233+
2234+ %+ cope (fang cof p.cay [our %main %da now])
2235+ |= [cof=cafe pro=vase]
2236+
2237+We pull in the relevant mark's definition.
2238+
2239+ ?. (slab %grad p.pro)
2240+ (flaw cof leaf/"no ++grad" ~)
2241+ =+ gar=(slap pro [%cnzy %grad])
2242+ ?. (slab %form p.gar)
2243+ ?. (slab %sted p.gar)
2244+ (flaw cof leaf/"no ++form:grad nor ++sted:grad" ~)
2245+ =+ for=((soft ,@tas) q:(slap gar [%cnzy %sted]))
2246+ ?~ for
2247+ (flaw cof leaf/"bad ++sted:grad" ~)
2248+ (make cof %diff [%cast u.for kas] [%cast u.for kos])
2249+
2250+If there's no `++grad`, we complain. If there's no `++form:grad`, then
2251+we look for a `++sted:grad`. If we can't find either, or if
2252+`++sted:grad` isn't a term, then we complain. If `++sted:grad` exists
2253+and is a term, then it represents the mark we should use as a proxy to
2254+get our diff. So, we cast both our given cages to the new mark and start
2255+the dance again.
2256+
2257+ ?. (slab %diff p.gar)
2258+ (flaw cof leaf/"no ++diff:grad" ~)
2259+
2260+Otherwise, we expect a `++diff:grad`.
2261+
2262+ %+ cope (keel cof pro [[%& 6]~ q.cay]~)
2263+ |= [cof=cafe pox=vase]
2264+
2265+We put the first cage's data into the sample of the given mark's
2266+definition.
2267+
2268+ %+ cope
2269+ %^ maul cof
2270+ (slap (slap pox [%cnzy %grad]) [%cnzy %diff])
2271+ q.coy
2272+ |= [cof=cafe dif=vase]
2273+
2274+We run `++diff:grad` with a sample of the second cage's data.
2275+
2276+ =+ for=((soft ,@tas) q:(slap gar [%cnzy %form]))
2277+ ?~ for
2278+ (flaw cof leaf/"bad ++form:grad" ~)
2279+ (fine cof u.for dif)
2280+ ==
2281+
2282+We check that `++form:grad` exists, and we tag the result with it to
2283+give the final cage.
2284+
2285+Lifecycle of a `%done`
2286+----------------------
2287+
2288+ %done [cof %0 p.kas q.kas]
2289+
2290+This is trivial. We simply produce the given cage with the given set of
2291+dependencies. This is used when we already have a cage that we want to
2292+insert into another silk that requires a silk argument. It's analogous
2293+to the return operator in a monad -- which makes it sound way more
2294+complicated than it is.
2295+
2296+Lifecycle of a `%dude`
2297+----------------------
2298+
2299+ %dude (cool |.(p.kas) $(kas q.kas))
2300+
2301+This simply puts a given tank on the stack trace if the given silk
2302+produces an error. This is implemented as a simple call to `++cool`.
2303+
2304+Lifecycle of a `%dune`
2305+----------------------
2306+
2307+ %dune
2308+ ?~ q.kas [cof [%2 [%leaf "no data"]~]]
2309+ $(kas [%done p.kas u.q.kas])
2310+
2311+This is a sort of a `++need` for silks. If there is no data in the unit
2312+cage, we produce an error. Else, we simply produce the data in the cage.
2313+
2314+Lifcycle of a `%mute`
2315+---------------------
2316+
2317+ %mute (kale cof p.kas q.kas)
2318+
2319+This mutates a silk by putting the values of other silks at particular
2320+axes. This is useful in, for example, replacing the sample of the door
2321+in a mark definition.
2322+
2323+ ++ kale :: mutate
2324+ |= [cof=cafe kas=silk muy=(list (pair wing silk))]
2325+ ^- (bolt cage)
2326+ %+ cope
2327+ |- ^- (bolt (list (pair wing vase)))
2328+ ?~ muy (fine cof ~)
2329+ %+ cope (make cof q.i.muy)
2330+ |= [cof=cafe cay=cage]
2331+ %+ cope ^$(muy t.muy)
2332+ |= [cof=cafe rex=(list (pair wing vase))]
2333+ (fine cof [[p.i.muy q.cay] rex])
2334+ |= [cof=cafe yom=(list (pair wing vase))]
2335+ %+ cope (make cof kas)
2336+ |= [cof=cafe cay=cage]
2337+ %+ cope (keel cof q.cay yom)
2338+ |= [cof=cafe vax=vase]
2339+ (fine cof p.cay vax)
2340+
2341+First, we process each of the silks by calling `++make` on them. We pass
2342+the resultant vase and list of pairs of wings and silks to `++keel` to
2343+do the actual mutation. We assume the mutation doesn't change the mark
2344+of the main silk, so we mark the produced vase with the original mark.
2345+
2346+ ++ keel :: apply mutations
2347+ |= [cof=cafe suh=vase yom=(list (pair wing vase))]
2348+ ^- (bolt vase)
2349+ %^ maim cof
2350+ %+ slop suh
2351+ |- ^- vase
2352+ ?~ yom [[%atom %n] ~]
2353+ (slop q.i.yom $(yom t.yom))
2354+ ^- twig
2355+ :+ %cncb [%& 2]~
2356+ =+ axe=3
2357+ |- ^- (list (pair wing twig))
2358+ ?~ yom ~
2359+ :- [p.i.yom [%$ (peg axe 2)]]
2360+ $(yom t.yom, axe (peg axe 3))
2361+
2362+We first put the vases together in one big tuple starting with the
2363+subject and going through the mutations. We slap against this tuple a
2364+`%_` twig we directly construct. Since a `%_` twig takes a list of pairs
2365+of wings and twigs, we simply have to generate twigs referring to the
2366+correct axes in the subject. This is very easy since we just recur on
2367+axis 3 of whatever axis we were already at.
2368+
2369+Note the use of `%_` instead of `%=` enforces that our mutations don't
2370+change the type of the subject, which justifies our use of the original
2371+mark.
2372+
2373+Lifecycle of a `%pact`
2374+----------------------
2375+
2376+ %pact
2377+ %+ cool |.(leaf/"ford: pact {<`@p`(mug p.kas)>} {<`@p`(mug q.kas)>}")
2378+ (pact cof p.kas q.kas)
2379+
2380+We push debug information onto the trace and go right to `++pact`.
2381+
2382+ ++ pact :: patch
2383+ |= [cof=cafe kas=silk kos=silk]
2384+ ^- (bolt cage)
2385+ %. [cof kas kos]
2386+ ;~ cope
2387+ ;~ coax
2388+ |=([cof=cafe p=silk q=silk] (make cof p))
2389+ |=([cof=cafe p=silk q=silk] (make cof q))
2390+ ==
2391+ |= [cof=cafe cay=cage coy=cage]
2392+
2393+First, we process the two given silks to get our arguments.
2394+
2395+ %+ cope (fang cof p.cay [our %main %da now])
2396+ |= [cof=cafe pro=vase]
2397+
2398+We pull in the relevant mark's definition.
2399+
2400+ ?. (slab %grad p.pro)
2401+ (flaw cof leaf/"no ++grad" ~)
2402+ =+ gar=(slap pro [%cnzy %grad])
2403+ ?. (slab %form p.gar)
2404+ ?. (slab %sted p.gar)
2405+ (flaw cof leaf/"no ++form:grad nor ++sted:grad" ~)
2406+ =+ for=((soft ,@tas) q:(slap gar [%cnzy %sted]))
2407+ ?~ for
2408+ (flaw cof leaf/"bad ++sted:grad" ~)
2409+ (make cof %cast p.cay %pact [%cast u.for kas] kos)
2410+
2411+If there's no `++grad`, we complain. If there's no `++form:grad`, then
2412+we look for a `++sted:grad`. If we can't find either, or if
2413+`++sted:grad` isn't a term, then we complain. If `++sted:grad` exists
2414+and is a term, then it represents the mark we should use as a proxy to
2415+get our diff. So, we cast the first argument to the new mark, then try
2416+to patch. Afterward, we cast the result back to the original mark.
2417+
2418+ =+ for=((soft ,@tas) q:(slap gar [%cnzy %form]))
2419+ ?~ for
2420+ (flaw cof leaf/"bad ++form:grad" ~)
2421+ ?. =(u.for p.coy)
2422+ %+ flaw cof :_ ~
2423+ =< leaf/"pact on data with wrong form: {-} {+<} {+>}"
2424+ [(trip p.cay) (trip u.for) (trip p.coy)]
2425+
2426+If `++form:grad` isn't a term, or else our second argument isn't of that
2427+mark, we complain.
2428+
2429+ ?. (slab %pact p.gar)
2430+ (flaw cof leaf/"no ++pact:grad" ~)
2431+
2432+If we don't have a `++pact:grad`, we complain.
2433+
2434+ %+ cope (keel cof pro [[%& 6]~ q.cay]~)
2435+ |= [cof=cafe pox=vase]
2436+
2437+We put the first cage's data into the sample of the given mark's
2438+definition.
2439+
2440+ %+ cope
2441+ %^ maul cof
2442+ (slap (slap pox [%cnzy %grad]) [%cnzy %pact])
2443+ q.coy
2444+ |= [cof=cafe pat=vase]
2445+
2446+We run `++pact:grad` with a sample of the second cage's data, which is
2447+the diff.
2448+
2449+ (fine cof p.cay pat)
2450+ ==
2451+
2452+We tag the result with the mark of our first argument.
2453+
2454+Lifecycle of a `%plan`
2455+----------------------
2456+
2457+ %plan
2458+ %+ cope (abut:(meow p.kas q.kas) cof r.kas)
2459+ |= [cof=cafe vax=vase]
2460+ (fine cof %noun vax)
2461+
2462+This is a direct request to compile a hood at a given beam with a heel
2463+of the given path. We comply by calling `++abut` with the given
2464+arguments and producing the vase with a mark of `%noun`.
2465+
2466+Lifecycle of a `%reef`
2467+----------------------
2468+
2469+ %reef (fine cof %noun pit)
2470+
2471+This is one of the simplest silks. We simply produce our context, which
2472+is zuse compiled against hoon. The mark is a `%noun`.
2473+
2474+Lifcycle of a `%ride`
2475+---------------------
2476+
2477+ %ride
2478+ %+ cool |.(leaf/"ford: ride {<`@p`(mug kas)>}")
2479+ %+ cope $(kas q.kas)
2480+ |= [cof=cafe cay=cage]
2481+ %+ cope (maim cof q.cay p.kas)
2482+ |= [cof=cafe vax=vase]
2483+ (fine cof %noun vax)
2484+
2485+This slaps evaluates the given silk, then it slaps the result against
2486+the given twig. Since we don't know what of what mark (if any) is the
2487+result, we give it a mark of `%noun`.
2488+
2489+Lifecycle of a `%vale`
2490+----------------------
2491+
2492+ %vale
2493+ %+ cool |.(leaf/"ford: vale {<p.kas>} {<q.kas>} {<`@p`(mug r.kas)>}")
2494+ %+ cope (lave cof p.kas q.kas r.kas)
2495+ |= [cof=cafe vax=vase]
2496+ (fine cof `cage`[p.kas vax])
2497+
2498+This checks whether given data is of the given mark. If we don't have
2499+the definition of the mark, we check the given ship for it.
2500+
2501+We call `++lave` to perform the check, producing a vase. We produce this
2502+vase tagged with the given mark.
2503+
2504+ ++ lave :: validate
2505+ |= [cof=cafe for=mark his=ship som=*]
2506+ ^- (bolt vase)
2507+ ((lake for [our %main [%da now]]) cof [%noun som])
2508+
2509+This is a thinly-veiled wrapper over `++lake`. Note that, contrary to
2510+documented opinion, we do not in fact check the other ship's definition
2511+of a mark. This is likely a bug.
2512+
2513+At any rate, `++lake` coerces a noun into the correct type for a mark.
2514+
2515+ ++ lake :: check/coerce
2516+ |= [for=mark bek=beak]
2517+ |= [cof=cafe sam=vase]
2518+ ^- (bolt vase)
2519+ %+ cool |.(leaf/"ford: check {<[for bek `@p`(mug q.sam)]>}")
2520+ ?: ?=(?(%gate %core %door %hoon %hook) for)
2521+ :: ~& [%lake-easy for bek]
2522+ (fine cof sam)
2523+ %+ cope (fang cof for bek)
2524+ |= [cof=cafe tux=vase]
2525+ =+ bob=(slot 6 tux)
2526+ ?: (~(nest ut p.bob) | p.sam)
2527+ (fine cof sam)
2528+ ?. (slab %grab p.tux)
2529+ (flaw cof [%leaf "ford: no grab: {<[for bek]>}"]~)
2530+ =+ gab=(slap tux [%cnzy %grab])
2531+ ?. (slab %noun p.gab)
2532+ (flaw cof [%leaf "ford: no noun: {<[for bek]>}"]~)
2533+ %+ cope (maul cof (slap gab [%cnzy %noun]) [%noun q.sam])
2534+ |= [cof=cafe pro=vase]
2535+ ?: =(+<.q.pro q.sam)
2536+ (fine cof (slot 6 pro))
2537+ (flaw cof [%leaf "ford: invalid content: {<[for bek]>}"]~)
2538+
2539+This is going to coerce the sample into the correct type for the mark.
2540+First, we push a line onto the stack trace saying that we're checking
2541+the type. If the requested mark is a gate, core, door, hoon, or hook,
2542+then we don't do any more type information than just saying it's a noun,
2543+so we're done.
2544+
2545+Otherwise, we get the mark definition from our `/=main=/mar` directory
2546+with `++fang`, which we'll describe below.
2547+
2548+We check to see if our sample type nests within the type of the sample
2549+to the door. If so, then we're already of the correct type, so we're
2550+done.
2551+
2552+Otherwise, we check to see if there's a `++grab` in the door, and a
2553+`++noun` in the `++grab`. If not, there's no way we can translate to
2554+this mark, so we fail.
2555+
2556+If we have everything we need, we slam our sample (typed as a noun)
2557+against the `++noun` in `++grab`. If the sample of the door is the same
2558+as our sample, then the check succeeded, so we produce the well-typed
2559+sample of the door. Otherwise, we fail.
2560+
2561+ ++ fang :: protocol door
2562+ |= [cof=cafe for=mark bek=beak]
2563+ ^- (bolt vase)
2564+ =+ pax=/door/[for]/mar
2565+ =+ ^= bem ^- beam
2566+ :_ pax
2567+ ?: =(p.bek our) bek
2568+ =+ oak=[our %main %da now]
2569+ ?. =(~ (ska %cy (tope [oak pax]))) oak
2570+ bek
2571+ (cope (fade cof %hook bem) abut:(meow bem ~))
2572+
2573+A mark's definition is generally in
2574+`/=main=/mar/[mark-name]/door/hook'. If we don't find it there, we look in`/[given-beak]/mar/[mark-name]/door/hook'.
2575+We parse the mark definition with `++fade` and assemble it with
2576+`++abut:meow`. `++fade` is defined under the `%bake` silk.
docs/arvo/internals/gall.mdnew file+133
@@ -0,0 +1,133 @@
1+---
2+navhome: /docs
3+sort: 7
4+---
5+
6+
7+`%gall`
8+=======
9+
10+Our application server manager.
11+
12+It allows applications and vanes to send messages to applications and
13+subscribe to data streams. This requires `%gall` to be a sort of a
14+hypervisor. Messages coming into `%gall` are routed to the intended
15+application, and the response comes back along the same route. If the
16+intended target is on another ship, `%gall` will behind-the-scenes route
17+it through ames to the other ship to run. This provides an abstraction
18+where all apps on all ships are communicated with over the same
19+interface.
20+
21+`%gall` neither accepts events from unix nor produces effects. It exists
22+entirely for the benefit of other vanes and, in particular,
23+applications. Eyre exposes `%gall`'s interface over http, and ames does
24+the same over the ames network. `%gall` uses ford to compile and run the
25+applications.
26+
27+Cards
28+-----
29+
30+`%gall` accepts the following cards. The first three are the most
31+commonly used, while the others are primarily used internally.
32+
33+### `%mess`
34+
35+Sends a message to an app. This will result in a call to the app's
36+`++poke` arm. The response is exactly one of a `%nice` if the action
37+succeeded or a `%mean` if not.
38+
39+### `%show`
40+
41+Subscribes to a stream from an app. This will result in a call to the
42+app's either `++peek` or `++peer` arm. The first response will always be
43+either a `%nice` or a `%mean`, indicating whether or not the
44+subscription was successful. After the first response, there will be
45+zero or more responses of either `%rush` or `%rust`, which communicate
46+either a differntial or full update to the data stream. There may be a
47+`%mean`, which indicates that the subscription has been canceled and no
48+more responses will be received along this stream.
49+
50+
51+### `%nuke`
52+
53+Unsubscribes the current duct from its stream. This receives a response
54+of either a `%nice` or a `%mean`. Note that a response of `%nice` does
55+not imply that the current duct was in fact subscribed to any stream.
56+
57+### `%init`
58+
59+Initializes a ship's apps. This should be called exactly once for each
60+ship on the pier. This produces no moves in response.
61+
62+### `%sire`
63+
64+Instantiates a child app. The app will be at path `[p parent-path]`, and
65+it will be an instance of the `q` app. The only response will be `%gone`
66+when the child dies.
67+
68+
69+### `%rote`
70+
71+Signifies a remote request from ames. `r` should be of type `rook`. This
72+how an app on a foreign ship may send a `%mess`, `%show`, or `%nuke`
73+card. Note that `%gall` automatically converts `%mess`, `%show`, and
74+`%nuke` into ames messages behind the scenes, so the only entity that
75+should use `%rote` and `%roth` is ames. Formally, the response is either
76+a `%nice` or a `%mean`, which ames uses to give a positive or negative
77+ack. A logical response comes by passing a `%roth` card.
78+
79+
80+### `%roth`
81+
82+Gives the response received from a remote request. `r` should be of type
83+`roon`. This is how an app responds to a foreign request with a `%rush`,
84+`%rust`, `%nice`, or `%mean`. The response is either a `%nice` or a
85+`%mean`. Even though we, as the proverb goes, "never ack an ack", we do
86+need to acknowledge these responses since they're really independent
87+one-way messages.
88+
89+
90+### `%wipe`
91+
92+Wipes the given app from memory. This is generally considered a hack,
93+but it is sometimes useful during development to wipe the state of an
94+app. We don't guarantee that this actually completely wipes the app.
95+Generally, you want to use a `%cide` card if you actually want to kill
96+an app. This gives no response.
97+
98+
99+### `%cide`
100+
101+Kills an app and all its children. Even though it's not technically a
102+part of `%gall`'s interface since it's not in `++kiss` and can't be
103+called from the outside, it's worth mentioning `%cide`, which may be
104+called from within `%gall` apps. It should call `++part` to allow the
105+app any last words. This gives no response.
106+
107+Service Gates
108+-------------
109+
110+### `++poke`
111+
112+Handles incoming messages. Most commonly with an associated `%logo`. For
113+example `++poke-json` handles an incoming JSON request from `%eyre`.
114+
115+### `++peer`
116+
117+Handles incoming subscriptions.
118+
119+### `++pull`
120+
121+Handles dropping subscribers.
122+
123+### `++pour`
124+
125+Handles responses to `%pass` moves.
126+
127+### `++park`
128+
129+Save state on update.
130+
131+### `++prep`
132+
133+Load state on update.
docs/dev/hoon/leap-in/marks.md → docs/arvo/marks.mdrenamed+23−23
@@ -1,6 +1,7 @@
11---
2+navhome: /docs
23next: true
3−sort: 5
4+sort: 6
45title: Marks
56---
67
@@ -9,16 +10,16 @@ our own marks. Let's write a sample mark of our own, then chain
910it together with some preexisting ones to have fun with type
1011conversions.
1112
12−Let's make a small "cord" mark. "Cord" is a name we use for `@t`
13−text, but there's no predefined mark for it. This is
14−`/mar/cord.hoon`:
13+Let's make a small "examples-cord" mark. "Cord" is a name we use for `@t`
14+text, but there's no predefined mark for it. Let's put the following code in:
15+`/mar/examples/cord.hoon`:
1516
1617```
1718/? 314
18−|_ cod=@t
19+|_ cod/@t
1920++ grab
2021 |%
21− ++ atom |=(arg=@ `@t`(scot %ud arg))
22+ ++ atom |=(arg/@ `@t`(scot %ud arg))
2223 --
2324++ grow
2425 |%
@@ -34,7 +35,7 @@ case, the argument is the marked data.
3435
3536There are three possible top-level arms in the `|_` core,
3637`++grab`, `++grow`, and `++grad`. `++grad` is used for revision
37−control, and it's covered elsewhere. `++grab` specifies
38+controlv (it contains diff/patch logic), and is covered elsewhere. `++grab` specifies
3839functions to convert from another mark to the current mark.
3940`++grow` specifies how to convert from the current mark to
4041another one.
@@ -42,16 +43,15 @@ another one.
4243In our case, we only define one arm in `++grab`, namely `++atom`.
4344This allows us to convert any atom to a cord. `++scot` is a
4445standard library function in `hoon.hoon` which pretty-prints
45−atoms of various types. We want tot treat the atom as an
46+atoms of various types. We want to treat the atom as an
4647unsigned decimal number, so we give `%ud` and the given argument
4748to `++scot`. Thus, the form of an arm in `++grab` is
4849`|=(other-mark-type this-mark-value)`.
4950
5051In `++grow`, we just convert to the `md` mark, which is just a
5152`@t` internally, but it has fancy conversion functions to things
52−like html. `++md` isn't a function because the "argument" is the
53−`cod=@t` on the `|_` line. We just produce the new value
54−directly.
53+like html. `++md` isn't a function because the "argument" is
54+already a `@t`, so we can just produce the new value directly.
5555
5656Let's play around a bit with this mark. First, let's take a
5757marked atom and convert it to our new mark.
@@ -59,9 +59,9 @@ marked atom and convert it to our new mark.
5959```
6060~fintud-macrep:dojo> &atom 9
61619
62−~fintud-macrep:dojo> &cord &atom 9
62+~fintud-macrep:dojo> &examples-cord &atom 9
6363'9'
64−~fintud-macrep:dojo> &cord &atom &cord &atom 9
64+~fintud-macrep:dojo> &examples-cord &atom &examples-cord &atom 9
6565'57'
6666```
6767
@@ -73,9 +73,9 @@ same concept. They're not isomorphisms.
7373Let's play around a little more:
7474
7575```
76−~fintud-macrep:dojo> &md &cord &atom 17
76+~fintud-macrep:dojo> &md &examples-cord &atom 17
7777'17'
78−~fintud-macrep:dojo> &hymn &md &cord &atom 17
78+~fintud-macrep:dojo> &hymn &md &examples-cord &atom 17
7979[ [%html ~]
8080 [[%head ~] [[%title ~] [[%~. [%~. "Untitled"] ~] ~] ~] ~]
8181 [ [%body ~]
@@ -87,7 +87,7 @@ Let's play around a little more:
8787]
8888```
8989
90−Ooh, that was exciting. If you squint at that, but it looks an
90+That was exciting. If you squint at that, it looks an
9191awful lot like html. Our value `17` is still in there, in the
9292body. `urb` is the mark we render most web pages to. It makes
9393sure you have a complete skeleton of a web page. Of course, by
@@ -95,7 +95,7 @@ the time this gets to the web page, it's plain html. Let's do
9595the final step in the conversion.
9696
9797```
98−~fintud-macrep:dojo> &mime &hymn &md &cord &atom 17
98+~fintud-macrep:dojo> &mime &hymn &md &examples-cord &atom 17
9999[ [%text %html ~]
100100 p=121
101101 q='<html><head><title>Untitled</title></head><body><meta value="{}" name="frontmatter" urb:front="" /><p>17</p></body></html>'
@@ -104,26 +104,26 @@ the final step in the conversion.
104104
105105This is a mime-typed octet stream with type `/text/html`, length
106106121 bytes, and our lowly number `17` rendered to a web page.
107−`cord` was just one step in the chain.
107+`examples-cord` was just one step in the chain.
108108
109109Of course, arvo can infer some parts of this chain:
110110
111111```
112−~fintud-macrep:dojo> &cord 17
112+~fintud-macrep:dojo> &examples-cord 17
113113'17'
114114```
115115
116−Likewise, `md` is the only way to get from `cord` to `hymn`, so
116+Likewise, `md` is the only way to get from `examples-cord` to `hymn`, so
117117that can be omitted. If we omit the `hymn`, though, we get:
118118
119119```
120−~fintud-macrep:dojo> &mime &cord 17
120+~fintud-macrep:dojo> &mime &examples-cord 17
121121[[%text %x-markdown ~] p=1 q='7']
122122```
123123
124−Here, we converted straight from `cord` to `md` to `mime`. Arvo
124+Here, we converted straight from `examples-cord` to `md` to `mime`. Arvo
125125decided that was the most straightforward conversion, but it
126126gives a different result than passing it through the `hymn`
127127mark.
128128
129−The minimal correct input, then, is `&mime &hymn &cord &atom 17`.
129+The minimal correct input, then, is `&mime &hymn &examples-cord &atom 17`.
docs/dev/hoon/leap-in/network.md → docs/arvo/network.mdrenamed+72−78
@@ -1,28 +1,29 @@
11---
2+navhome: /docs
23next: false
3−sort: 2
4−title: Network Messages
4+sort: 3
5+title: Network messages
56---
67
8+# Network messages
9+
710Now we've learned enough hoon to do more interesting things.
811Let's get our planets to talk to each other.
912
1013All we've written up until now are just shell
11−commands that produce a value and then disappear. We need an
12−actual app to listen for messages from another planet. Let's
13−take a look at a very basic app that does this.
14+commands that produce a value and then disappear. To listen for and receive messages from other planets, we'll need an app. Let's look at a very simple one:
1415
1516```
1617:: There is no love that is not an echo
1718::
18−:::: /hoon/echo/ape
19+:::: /hoon/echo/examples/app
1920 ::
2021/? 314
2122!:
22−|_ [bowl state=~]
23+|_ {bowl state/$~}
2324++ poke-noun
24− |= arg=*
25− ^- [(list) _+>.$]
25+ |= arg/*
26+ ^- {(list) _+>.$}
2627 ~& [%argument arg]
2728 [~ +>.$]
2829--
@@ -37,19 +38,21 @@ with the following commands:
3738```
3839~fintud-macrep:dojo> |start %echo
3940>=
40−~fintud-macrep:dojo> :echo 5
41+~fintud-macrep:dojo> :examples-echo 5
4142[%argument 5]
4243>=
43−~fintud-macrep:dojo> :echo [1 2]
44+~fintud-macrep:dojo> :examples-echo [1 2]
4445[%argument [1 2]]
4546>=
4647```
4748
48−> There is currently a bug where the `%argument` lines are
49−> printed *above* the line you entered, so your output may not
50−> look exactly like this.
51−> `>=` means that a command was successfully received and
52−> executed.
49+<blockquote class="blockquote">
50+There is currently a bug where the `%argument` lines are
51+printed *above* the line you entered, so your output may not
52+look exactly like this.
53+`>=` means that a command was successfully received and
54+executed.
55+</blockquote>
5356
5457Most of the app code should be simple enough to guess its
5558function. The important part of this code is the definition of
@@ -70,13 +73,12 @@ we'll get to the correct way later on.
7073
7174But what does `++poke-noun` produce? Recall that `^-` casts to a
7275type. In this case, it's declaring that end result of the
73−function will be of type `[(list) _+>.$]`. But what does this
76+function will be of type `{(list) _+>.$}`. But what does this
7477mean?
7578
7679The phrase to remember is "a list of moves and our state". Urbit
77−is a message passing system XX should we mention event
78−driven operating system XX, so whenever we want to do something that
79−interacts with the rest of the system we send a message. Thus, a
80+is a message passing system, so whenever we want to do something that
81+interacts with the rest of the system, we send a message. Thus, a
8082move is arvo's equivalent of a syscall. The first thing that
8183`++poke-noun` produces is a list of messages, called
8284"moves". In this case, we don't actually want the system to do
@@ -89,17 +91,17 @@ app state is stored. It'll become clear why this is later on,
8991but for now pretend that `+>.$` is a magic invocation that means
9092"app state".
9193
92−Let's look at another example. Say we want to only accept a
94+Let's look at another example (edit your code in `/app/examples/echo/hoon` to reflect the code below). Say we want to only accept a
9395number, and then print out the square of that number.
9496
9597```
9698/? 314
9799!:
98−|_ [bowl state=~]
100+|_ {bowl state=~}
99101::
100102++ poke-atom
101− |= arg=@
102− ^- [(list) _+>.$]
103+ |= arg/@
104+ ^- {(list) _+>.$}
103105 ~& [%square (mul arg arg)]
104106 [~ +>.$]
105107--
@@ -107,9 +109,11 @@ number, and then print out the square of that number.
107109
108110A few things have changed. Firstly, we no longer accept
109111arbitrary nouns because we can only square atoms (integers, in
110−this case an unsigned one). Thus, our argument is now `arg=@`.
112+this case an unsigned one). Thus, our argument is now `arg/@`.
111113Secondly, it's `++poke-atom` rather than `++poke-noun`.
112114
115+# Intro to marks
116+
113117Are there other `++poke`s? Yes. In fact, `noun` and
114118`atom` are just two of arbitrarily many "marks". A mark is
115119fundamentally a type definition, but accessible at the arvo
@@ -133,9 +137,9 @@ commands:
133137```
134138~fintud-macrep:dojo> |start %square
135139>=
136−~fintud-macrep:dojo> :square 6
140+~fintud-macrep:dojo> :examples-square 6
137141gall: %square: no poke arm for noun
138−~fintud-macrep:dojo> :square &atom 6
142+~fintud-macrep:dojo> :examples-square &atom 6
139143[%square 36]
140144>=
141145```
@@ -146,37 +150,32 @@ gall: %square: no poke arm for noun
146150Marks are powerful, and they're the backbone of urbit's data
147151pipeline, so we'll be getting quite used to them.
148152
149−**Exercises**:
153+**Exercise**:
150154
151155- Write an app that computes fizzbuzz on its input (as in the
152156 previous section).
153157
154−- One way of representing strings is with double quoted strings
155− called "tapes". The hoon type is `++tape`, and there is a
156− corresponding mark with the same name. Write an app that
157− accepts a tape and prints out `(flop argument)`, where
158− `argument` is the input. What does this do?
158+# Sending a message to another ship
159159
160−
161−Let's write our first network message! Here's `/ape/pong.hoon`:
160+Let's write our first network message! Here's `/app/examples/pong.hoon`:
162161
163162```
164163/? 314
165164|%
166− ++ move ,[bone term wire *]
165+ ++ move {bone term wire *}
167166--
168167!:
169−|_ [bowl state=~]
168+|_ {bowl state=$~}
170169::
171170++ poke-urbit
172− |= to=@p
171+ |= to/@p
173172 ^- [(list move) _+>.$]
174173 [[[ost %poke /sending [to %pong] %atom 'howdy'] ~] +>.$]
175174::
176175++ poke-atom
177− |= arg=@
178− ^- [(list move) _+>.$]
179− ~& [%receiving (,@t arg)]
176+ |= arg/@
177+ ^- (list move) _+>.$}
178+ ~& [%receiving (@t arg)]
180179 [~ +>.$]
181180::
182181++ coup |=(* [~ +>.$])
@@ -186,15 +185,15 @@ Let's write our first network message! Here's `/ape/pong.hoon`:
186185Run it with these commands:
187186
188187```
189−~fintud-macrep:dojo> |start %pong
188+~fintud-macrep:dojo> |start %examples-pong
190189>=
191−~fintud-macrep:dojo> :pong &urbit ~sampel-sipnym
190+~fintud-macrep:dojo> :pong &examples-urbit ~sampel-sipnym
192191>=
193192```
194193
195194Replace `~sampel-sipnym` with another urbit. The easiest thing to
196−do is to start a [moon](), a sub-identity of your urbit. Don't
197−forget to start the `%pong` app on that urbit too. You should
195+do is to start a moon, a sub-identity of your urbit. If you don't know how to start a moon, see [the user admin section](/docs/using/admin/) Don't
196+forget to start the `%examples-pong` app on that urbit too. You should
198197see, on the foreign urbit, this output:
199198
200199```
@@ -202,15 +201,13 @@ see, on the foreign urbit, this output:
202201```
203202
204203Most of the code should be straightforward. In `++poke-atom`,
205−the only new thing is the expression `(,@t arg)`. As we already
206−know, `@t` is the type of "cord" text strings. `,` is the
207−irregular short form of `$,`an operator that turns a type into a
208−validator function (called a "clam" in hoon) -- that is, a
209−function whose domain is all nouns and range is the given type.
204+the only new thing is the expression `(@t arg)`. As we already
205+know, `@t` is the type of "cord" text strings. In Hoon, when types are called as functions, they serve as a validator function (called a "clam" in hoon) -- that is, a function whose domain is all nouns and range is the given type.
206+
210207In simpler terms, if a validator function is passed a value that
211208falls within its type, that value is produced. Otherwise, it
212209produces the default value (aka the "bunt") of its type. Here we call
213−this `,@t` function on the argument. This coerces the argument
210+this `@t` function on the argument. This coerces the argument
214211to text, so that we can print it out prettily no matter what
215212we're passed.
216213
@@ -227,28 +224,29 @@ with one element:
227224```
228225[ost %poke /sending [to-urbit-address %pong] %atom 'howdy']
229226```
230−###Moves
227+
228+### Moves
231229
232230The general form of a move is
233231
234− >-app/vane-specific part of move
232+-arvo part---->
235233`[bone term wire *]`
236− -arvo part---->
237− of move
234+
235+------------------------->app/vane-specific part of move
238236
239237Or, in pseudo-code:
240238
241239`["cause" sys-call/action tack-new-layer-on-cause action-specific
242240information]`
243241
244−Let's walk through each of these elements step by step
242+Let's walk through each of these elements step by step.
245243
246−####Bones ("cause")
244+#### Bones ("cause")
247245
248246If you look up `++bone` in `hoon.hoon`, you'll see that it's a
249247number (`@ud`), and that it's an opaque reference to a duct.
250−`++duct` in hoon.hoon is a list of `wire`s, where `wire` is an
251−alias for `path`. `++path` is a list of `span`s, which are ASCII
248+`++duct` in hoon.hoon is a list of `wire`s, where `++wire` is an
249+alias for `++path`. `++path` is a list of `++span`s, which are ASCII
252250text. Thus, a duct is a list of paths, and a bone is an opaque
253251reference to it (in the same way that a Unix file
254252descriptor is an opaque reference to a file structure). Thus, to
@@ -260,16 +258,14 @@ as a keystroke, network packet, file change, or timer event.
260258When arvo is given this event, it routes the event to appropriate
261259kernel module for handling.
262260
263−XX[short explanation of the composition of arvo should be here.]
264−
265261Sometimes, the module can immediately handle the event and
266262produce any necessary results. For example, when we poked the
267263`++poke-atom` arm above, we poked %gall, our application server,
268264which was able to respond to our poke directly. When the module
269−cannot service the request itself, it sends instructions to the other kernel
270−module or application to do a specified action, and produces the
271−result from that. Furthermore, when one module sends a message to another kernel
272−module or application, it also sends along the duct it was given
265+cannot service the request itself, it sends instructions to another kernel
266+module or application (the the %gall module) to do a specified action, and produces the result from that.
267+
268+Furthermore, when one module sends a message to another kernel module or application, it also sends along the duct it was given
273269with its new wire tacked onto the end. Now the duct has two entries,
274270with the unix even on the bottom and the kernel module that
275271handled it next. This process can continue indefinitely, adding
@@ -288,10 +284,10 @@ called is also the root cause for the network message we're
288284trying to send. Thus, we say to send the network message along the given bone
289285`ost`.
290286
291−#####Wire ('tack on new layer to duct')
287+##### Wire ('tack on new layer to duct')
292288
293289Of course, we have to push a new layer onto our duct
294−before passing it along (or responding to it directly) anywhere This
290+before passing it along (or responding to it directly) anywhere. This
295291layer can have any data we want in it, but we don't need anything
296292specific here, so we just use the wire `/sending`
297293(`/elem1/elem2/elem n` is one syntax used to create `++path`s and
@@ -302,7 +298,7 @@ handler as an argument. Although it's not required, it's
302298generally a good idea to make the wire human-readable for
303299bug-handling purposes.
304300
305−#####Term (sys-call)
301+##### Term (sys-call)
306302
307303Looking back at the general form of a move, there is a
308304`term`--which is text composed lowercase ascii and `-`, and has
@@ -313,8 +309,6 @@ the name of the syscall. Common ones include: `%poke`, to
313309message an app; `%warp`, to read from the filesystem; `%wait`, to
314310set a timer; and `%them`, to send an http request.
315311
316−XXDescribe where they can find a list of these things.
317−
318312The general form ends with `*` (a noun) since each type of move takes
319313different data. In our case, a `%poke` move takes a target
320314(urbit and app) and marked data and pokes the arm of the
@@ -327,17 +321,19 @@ When arvo receives a `%poke` move, it calls the appropriate
327321between apps on the same urbit as for sending messages between
328322apps on different urbits.
329323
330−> We said earlier that we're not expecting a response. This is
331−> not entirely true: the `++coup` is called when we receive
332−> acknowledgment that the `++poke` was called. We don't do
333−> anything with this information right now, but we could.
324+<blockquote class="blockquote">
325+We said earlier that we're not expecting a response. This is
326+not entirely true: the `++coup` is called when we receive
327+acknowledgment that the `++poke` was called. We don't do
328+anything with this information right now, but we could.
329+</blockquote>
334330
335331**Exercises**:
336332
337333- Extend either of the apps in the first two exercises to accept
338334 input over the network in the same way as `pong`.
339335
340−- Modify `pong` to print out a message when it receives an ack.
336+- Modify `examples-pong` to print out a message when it receives acknowledgement.
341337
342338- Write two apps, `even` and `odd`. When you pass an atom to
343339 `even`, check whether it's even. If so, divide it by two and
@@ -345,9 +341,7 @@ apps on different urbits.
345341 an atom, check whether it's equal to one. If so, terminate,
346342 printing "%success". Otherwise, check whether it's odd. If
347343 so, multiply it by three, add one, and recurse; otherwise, poke
348− `even` with it. multiply it by three and add one. When either
349− app receives a number, print it out along with the name of the
350− app. In the end, you should be able to watch Collatz's
344+ `even` with it. When either app receives a number, print it out along with the name of the app. In the end, you should be able to watch Collatz's
351345 conjecture play out between the two apps. Sample output:
352346
353347```
docs/arvo/security-driver.mdnew file+302
@@ -0,0 +1,302 @@
1+---
2+navhome: /docs
3+next: false
4+sort: 10
5+title: Security Drivers
6+---
7+
8+# Security Drivers
9+
10+A security driver is a file in `/=home=/sec/<tld>/<domain>/hoon`
11+that handles the authentication for all HTTP requests to
12+`https://<domain>.<tld>`. When anything in Urbit makes an HTTP
13+request through `%eyre` (our web server), it checks to see if we
14+have a security driver for the requested domain, and if so
15+filters the request through the driver. The security driver will
16+usually either decorate the request with the needed credentials
17+if it has them, or else it will guide the user through the
18+process of authenticating Urbit with the service.
19+
20+Each web service needs its own security driver, but most of them
21+are pretty standard. We recommend starting with an existing
22+security driver based on your needed authentication method (e.g.
23+basic auth, OAuth1, OAuth2), and changing whatever is specific to
24+your service.
25+
26+The best strategy for building security drivers is to copy a
27+similar one and tweak it until it works for you. The best
28+representatives are Github for Basic Authentication, Twitter for
29+OAuth1, Slack for OAuth2 when access tokens don't expire, and
30+Google APIs for OAuth2 when access tokens do expire. In most
31+cases you'll need to make very few changes to one of these
32+models.
33+
34+Still, it's worth seeing one or two built from the ground up.
35+Here, we'll build a connector for the Github API v3. The
36+simplest way to interact with the Github API is to just fetch
37+https://api.github.com from the dojo:
38+
39+ ~your-urbit:dojo> +https://api.github.com
40+
41+Github exposes a few endpoints to the general web, and the root
42+endpoint is one of them. This gives you a textual representation
43+of a JSON object that contains a bunch of urls to other parts of
44+Github's API. This is exactly the same response you would get
45+from just running `curl https://api.github.com` on UNIX.
46+
47+If we don't have a security driver for Github yet, many of the
48+endpoints won't be accessible, or they will only have publicly
49+accessible information. Most of what we care about requires us
50+to be authenticated.
51+
52+## Basic auth
53+
54+Here's a simple security driver:
55+
56+```
57+:: Test url +https://api.github.com/user
58+::
59+:::: /hoon/github/com/sec
60+ ::
61+/+ basic-auth
62+!:
63+|_ {bal/(bale keys:basic-auth) $~}
64+++ aut ~(standard basic-auth bal ~)
65+++ filter-request out-adding-header:aut
66+--
67+```
68+
69+Github supports authentication through either Basic
70+Authentication or OAuth2. We'll show the basic auth example
71+first, but in general we'd prefer OAuth2.
72+
73+Since this driver is for Github, put it in
74+`/=home=/sec/com/github/hoon`.
75+
76+To try this out, we first have to initialize our credentials with
77+`|init-auth-basic`, which prompts for the url of the service
78+(api.github.com), username, and password. It stores this
79+information in a manner that `%eyre` knows how to decode and send
80+put into your `bale`. Note that `|init-auth-basic` is standard for
81+basic auth, but other auth schemes (like OAuth) are initialized
82+in other ways.
83+
84+After you've run `|init-auth-basic`, you should be able to run
85+`+https://api.github.com/user` and get a response indicating who
86+you're logged in as.
87+
88+You can similarly POST:
89+
90+ ~your-urbit:dojo> +https://api.github.com/gists &json _(cork poja need) '{"files":{"file1.txt":{"content":"can\'t stop the signal"}}}'
91+
92+This creates a gist, go to `https://gist.github.com/<username>` to
93+see it.
94+
95+The `+url` syntax used in "source" position makes a GET request,
96+but if you pass it data it will make a POST request with that
97+data as the body. This request is authenticated seamlessly. You
98+can send data of any mark as long as it has a conversion path to
99+`%mime`.
100+
101+Let's take a look at the code and see if we can figure out what's
102+happening here:
103+
104+ /+ basic-auth
105+
106+First, we load a library called `basic-auth`. This library
107+exposes two items. `keys` is the type of the basic auth key,
108+which is essentially a base64'd username and password.
109+`standard` accepts a `bale` and produces a core with everything
110+we'll need to implement basic auth.
111+
112+Every security driver needs some amount of state, which is stored
113+in `bale`. `bale` contains:
114+
115+- `our`, our urbit name
116+- `now`, the current time
117+- `eny`, 256 bits of entropy
118+- `byk`, the urbit, desk and case which the security driver is
119+ running from
120+- `usr`, the particular identity we're logging in with
121+- `dom`, the site we're accessing
122+- `key`, the secrets required to authenticate requests. The type
123+ for this entry is supplied by the programmer as the argument to
124+ `++bale`. Thus, in our case, `key` in our bale is of type
125+ `keys:basic-auth`.
126+
127+Additionally, a security driver contains at least one out of the
128+five "special" arms:
129+
130+- `++filter-request` is a function which takes a hiss (http
131+ request) and produces a `sec-move` (defined in zuse), which is
132+ one of:
133+
134+ * `[%send hiss]`, which sends the new hiss. This is the
135+ case in, for example, basic auth, where all we need to do is
136+ add an extra header to the request.
137+ * `[%give httr]`, where httr is an http response. This
138+ immediately returns an http response to the sender.
139+ * `[%show purl]`, where a purl is a parsed url. This displays
140+ a message asking the user to visit the given url to continue
141+ the authentication process.
142+ * `[%redo ~]`, which redoes the request.
143+
144+ `%eyre` calls `++filter-request` just before sending an HTTP
145+ request to the specified domain. This allows the security
146+ driver to filter the requests, decorating them with
147+ authentication data.
148+
149+- `++filter-response` is a function which takes an httr and
150+ produces a `sec-move`. `%eyre` calls it after receiving an
151+ HTTP response from the specified domain. This allows the
152+ security driver to handle authentication errors, commonly
153+ caused by expired tokens, and retry the request.
154+
155+- `++receive-auth-query-string` is a function that takes a `quay`
156+ (list of query parameters) and produces a `sec-move`. `%eyre`
157+ calls it when it receives a request on the callback url.
158+ Generally, this happens in OAuth after the user has granted
159+ access to the urbit app, and the service makes a request to the
160+ callback url with the code. The security driver should then
161+ make a request to convert the code into an access token.
162+
163+- `++receive-auth-response` is a function that takes an httr and
164+ produces a `sec-move`. `%eyre` calls it when it gets a
165+ response to the request made in `++receive-auth-query-string`.
166+
167+- `++update` is a function which converts old state to a new
168+ format when the security driver gets updated. If you want to
169+ just get rid of the old state, define `++discard-state` as `~`.
170+
171+For basic auth, we only have to worry about `++filter-request`,
172+since all we need to do is add the correct header to each
173+request. Our `++aut` core contains a function
174+`++out-addding-header`, which does exactly what we want.
175+
176+Where do the keys come from, though? Remember we ran
177+`|init-auth-basic` to input them. This just prompts you for the
178+service url, username, and password, and it stores them next to
179+the driver. In our case, that's
180+`/=home=/sec/com/gitub/api/atom`. These keys are stored
181+encrypted, and you don't want to edit them directly. `%eyre`
182+loads them directly into your `bale`.
183+
184+## OAuth2
185+
186+Most services are better accessed through some form of OAuth.
187+Github can be accessed with OAuth2, which is a little more
188+complicated than basic auth, but not hugely so.
189+
190+The basic steps for OAuth2 are these:
191+
192+- create an app and get its client id and client secret (on
193+ Github)
194+- store these in Urbit (with `|init-oauth2`)
195+- try to make a request that requires authentication. The
196+ security driver should prompt you to visit a particular url.
197+- visit the url and click "authorize", which gives the app access
198+ to your account
199+- the security driver will turn the code it receives into an
200+ access token
201+- on every request, include that access token
202+
203+Creating an app is easy and
204+[well-documented](https://github.com/settings/applications/new).
205+If necessary, set the callback url to
206+`/~/ac/github.com/_state/in`, and note its client id and client
207+secret.
208+
209+Run `|init-oauth2`, which will prompt for the hostname
210+(api.github.com), client id, and client secret. This will store
211+the information, encrypted, in `/=home=/sec/com/github.atom`,
212+just as with Basic Authentication.
213+
214+Now we need a security driver. Use this:
215+
216+```
217+:: Test url +https://api.github.com/user
218+::
219+:::: /hoon/github/com/sec
220+ ::
221+/+ oauth2
222+!:
223+::::
224+ ::
225+|_ {bal/(bale keys:oauth2) tok/token:oauth2}
226+++ scopes :: comment out scopes to taste
227+ :~ 'user' 'user:email' 'user:follow' 'public_repo' 'repo'
228+ 'repo_deployment' 'repo:status' 'delete_repo' 'notifications'
229+ 'gist' 'read:repo_hook' 'write:repo_hook' 'admin:repo_hook'
230+ 'admin:org_hook' 'read:org' 'write:org' 'admin:org'
231+ 'read:public_key' 'write:public_key' 'admin:public_key'
232+ ==
233+:: ++aut is a "standard oauth2" core, which implements the
234+:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
235+:: and examples at the bottom of the file.
236+++ aut (~(standard oauth2 bal tok) . |=(tok/token:oauth2 +>(tok tok)))
237+++ filter-request
238+ %^ out-add-query-param:aut 'access_token'
239+ scope=~[%client %admin]
240+ oauth-dialog='https://github.com/login/oauth/authorize'
241+::
242+++ receive-auth-query-string
243+ %- in-code-to-token:aut
244+ url='https://github.com/login/oauth/api/access_token'
245+++ receive-auth-response bak-save-token:aut
246+--
247+```
248+
249+The oauth2 library provides the main "engine" in `standard`, just
250+like in basic auth, except that we also have to specify a
251+function to save the access token when we get it. It's worth
252+noting that this library is well documented in the source,
253+including examples: `/=home=/lib/oauth2/hoon`.
254+
255+Running `+http://api.github.com/user` tries to make a request to
256+Github with authentication. This loads into the bale the keys,
257+which are of type `keys:oauth2`, defined in the oauth2 library.
258+We don't have to worry about the specifics of these keys -- the
259+library handles them -- but they include the client id and the
260+client secret.
261+
262+Before the request is sent, `%eyre` calls `++filter-request` to
263+decorate it with authentication headers. Since we don't yet have
264+an access token, we need to prompt the user to visit the "dialog"
265+url. `++out-add-query-param` checks whether we have a token, and
266+if we don't it produces `%show` and a message telling the user to
267+visit the `oauth-dialog` url we provide, with the extra query
268+parameters added (client id, scopes, and state).
269+
270+When the user visits that url, Github will ask them to log in and
271+authorize the application. When they do so, Github will post a
272+request to `/~/ac/github.com/_state/in` with a code in the query
273+string. `%eyre` sends the query string to
274+`++receive-auth-query-string`, which is a function that takes a
275+quay and produces a `sec-move`. `++in-code-to-token` from our
276+`aut` takes the `code` parameter from the quay and uses it to
277+create a request to the given url. This request includes the
278+client id, the client secret, and the code we just got.
279+
280+Github's response to that request includes an access token in its
281+body. This is handled in `++receive-auth-response`.
282+`++bak-save-token` extracts that token and gives it to the
283+function that we passed in the definition of `++aut`. In our
284+case, we just save that token into our state for later usage.
285+
286+Now we have the credentials we need, so `++filter-request` is
287+called with the original request, and `++out-add-query-param`
288+passes the request through with the addition of the query
289+parameter `access_token`.
290+
291+Just like with Basic Authentication, you should be able to run
292+`+https://api.github.com/user` and get a response indicating who
293+you're logged in as.
294+
295+Some drivers a slightly more complicated. For example, Github's
296+access token's don't expire, but that's not the case for all
297+service. The googleapis driver shows the flow when the access
298+token can expire. Twitter uses OAuth1, for which we have another
299+library.
300+
301+Remember, of course, that the best strategy for building security
302+drivers is to copy a similar one and tweak it to taste.
docs/dev/hoon/leap-in/state.md → docs/arvo/state.mdrenamed+35−30
@@ -1,37 +1,42 @@
11---
2+navhome: /docs
23next: true
3−sort: 3
4+sort: 4
45title: State
56---
67
8+# State
9+
710In the last section we built a few small apps that sent moves.
811These apps were entirely stateless, however. Most useful apps
912require some amount of state. Let's build a trivial stateful
1013app. It'll keep a running the sum of all the atoms we poke it with.
11−Here's `ape/sum.hoon`:
14+Here's `app/examples/sum.hoon`:
1215
1316```
1417/? 314
1518!:
16−|_ [bowl state=@]
19+|_ {bowl state/@}
1720++ poke-atom
18− |= arg=@
19− ^- [(list) _+>.$]
21+ |= arg/@
22+ ^- {(list) _+>.$}
23+ ?: =(arg 0)
24+ [~ +>.$(state 0)]
2025 ~& [%so-far (add state arg)]
2126 [~ +>.$(state (add state arg))]
2227--
2328```
2429
25−We can start it with `|start %sum`, and then run it:
30+We can start it with `|start %examples-sum`, and then run it:
2631
2732```
28−~fintud-macrep:dojo> :sum &atom 5
33+~fintud-macrep:dojo> :examples-sum &atom 5
2934[%so-far 5]
3035>=
31−~fintud-macrep:dojo> :sum &atom 2
36+~fintud-macrep:dojo> :examples-sum &atom 2
3237[%so-far 7]
3338>=
34−~fintud-macrep:dojo> :sum &atom 15
39+~fintud-macrep:dojo> :examples-sum &atom 15
3540[%so-far 22]
3641>=
3742```
@@ -41,8 +46,7 @@ how?
4146
4247The state is stored as the second thing in the `|_` line. In our
4348case, it's simply an atom named `state`. We change it by
44−producing as our state not with (as before) `+>.$` but `+>.$(state (add state
45−arg))`. We've seen all these parts before, but you might not
49+producing as our state not with `+>.$` (as before), but with `+>.$(state (add state arg))`. We've seen all these parts before, but you might not
4650recognize them.
4751
4852Recall in the first chapter that we recursed with the expression
@@ -62,46 +66,47 @@ meaning that our state is an atom. Of course, `state` is just a
6266name we're assigning to it, and you're free to use whatever name
6367you want.
6468
65−Two points you may be wondering about. Firstly, `bowl` is a set
66−of general global state that is managed by the system. It
69+There are at least two points you may be wondering about. First, `bowl` is a set of general global state that is managed by the system. It
6770includes things like `now` (current time), `our` (our urbit
6871identity), and `eny` (256 bits of guaranteed-fresh entropy). For
6972the full list of things in `++bowl`, search for `++ bowl` (note
7073the double space) in `/arvo/zuse.hoon`.
7174
72−> This is a very common technique in learning hoon. While some
73−> documentation exists, often the easiest way to learn about an
74−> identifier you see in code is to search in `/arvo/zuse.hoon`
75−> and `/arvo/hoon.hoon` for it. These are our two "standard
76−> libraries", and they're usually not hard to read. Since
77−> urbit's codebase is relatively small (those two files are less
78−> than 15000 lines of code combined, and besides the standard
79−> library they include the hoon parser and compiler, plus the
80−> /arvo microkernel), you can usually use the code and the
81−> comments as reference doc.
82−
83−The second point is that urbit needs no "serialize to disk" step.
75+<blockquote class="blockquote">
76+This is a very common technique in learning hoon. While
77+documentation exists, often the easiest way to learn about an
78+identifier you see in code is to search in `/arvo/zuse.hoon`
79+and `/arvo/hoon.hoon` for it. These are our two "standard
80+libraries", and they're usually not hard to read. Since
81+urbit's codebase is relatively small (those two files are less
82+than 15000 lines of code combined, and besides the standard
83+library they include the hoon parser and compiler, plus the
84+/arvo microkernel), you can usually use the code and the
85+comments as reference doc.
86+</blockquote>
87+
88+The second thing is that urbit needs no "serialize to disk" step.
8489Everything you produce in the app state is persistent across
8590calls to the app, restarts of the urbit, and even power failure.
8691If you want to write to the filesystem, you can, but it's not
8792needed for persistence. Urbit has transactional events, which
88−makes it an [ACID operating system](). Thus, you don't have to
93+makes it an [ACID operating system](https://en.wikipedia.org/wiki/ACID). Thus, you don't have to
8994worry about persistence when programming in urbit or to ever go
9095through the hassle of having to set up and write to a database.
9196
9297**Exercises**:
9398
94−- Modify `:sum` to reset the counter when you poke it with zero.
99+- Modify `:examples-sum` to reset the counter when you poke it with zero.
95100
96101- Write an app that prints out the previous value you poked it
97102 with. Sample output:
98103
99104```
100−~fintud-macrep:dojo> :last 7
105+~fintud-macrep:dojo> :examples-last 7
101106[%last 0]
102107>=
103−~fintud-macrep:dojo> :last [1 2 3]
108+~fintud-macrep:dojo> :examples-last [1 2 3]
104109[%last 7]
105110>=
106−~fintud-macrep:dojo> :last 'howdy'
111+~fintud-macrep:dojo> :examples-last 'howdy'
107112[%last [1 2 3]]
docs/arvo/subject.mdnew file+105
@@ -0,0 +1,105 @@
1+---
2+navhome: /docs
3+sort: 2
4+next: true
5+title: The subject
6+---
7+
8+# The subject
9+
10+Now we're going to cover the boiler plate that we skimmed over
11+earlier.
12+
13+ :- %say |= *
14+ :- %noun
15+ =< (sum [1.000 2.000])
16+
17+This program is a cell of two elements: the first, `%say`, tells
18+the interpreter what to produce--in this case a value.
19+
20+The second element is `|=`, which we know produces a function.
21+`|=`'s first child is its argument(s), which in this case is any
22+noun (`*`). Its second child is the remainder of the program.
23+
24+Similarly, the rest of the program is a cell of the literal
25+`%noun`, which tells the shell that we're producing a value of
26+type `noun`, and the code that we run to actually produce our value of the type `noun`.
27+
28+`=<` is a rune that takes two children. The second child is the
29+context against which we run the first child. So in this case, we
30+are running the expression `(sum 1.000)` against everything
31+contained within the `|%`. In Hoon, we call the code executed the
32+"formula" and its context the "subject".
33+
34+```
35+::::::::::::::::::::::::::::::
36+=< (sum 1.000) :: formula
37+::::::::::::::::::::::::::::::
38+|% ::
39+++ three ::
40+ |= a/@ ::
41+ =| b/@ ::
42+ |- ^- @u ::
43+ ?: (lth a b) ::
44+ 0 ::
45+ (add b $(b (add 3 b))) ::
46+ ::
47+++ five ::
48+ |= a/@ :: subject
49+ =| b/@ ::
50+ |- ^- @ ::
51+ ?: (lte a b) ::
52+ 0 ::
53+ ?: =((mod b 3) 0) ::
54+ $(b (add b 5)) ::
55+ (add b $(b (add b 5))) ::
56+ ::
57+++ sum ::
58+ |= a/@u ::
59+ (add (five a) (three a)) ::
60+-- ::
61+::::::::::::::::::::::::::::::
62+```
63+
64+In nearly every language there is a similar concept of a
65+"context" in which expressions are executed. For example, in C
66+this includes things like the call stack, stack variables, and so
67+on.
68+
69+Hoon is unique in that this context is a first-class value.
70+Scheme allows a sort of reification of the context through
71+continutations, and some may see a parallel to Forth's stack, but
72+Hoon takes takes the concept one step further.
73+
74+Our starting subject is the standard library, which is defined in
75+`/arvo/hoon.hoon` and `/arvo/zuse.hoon`. This is where functions
76+like `add` are defined. When we define a core with `|%`, we
77+don't throw away the subject (i.e. the standard library); rather,
78+we stack the new core on top of the old subject so that both are
79+accessible.
80+
81+**Exercises**:
82+
83+- Pass `++sum` its arguments (`2000` and `3000`) from the
84+ commandline.
85+
86+- Comment out all of the arms of the `|%`. Now add another arm
87+ and call it `++add`, have it accept two arguments and procduce
88+ 42 (regardless of input). Change the `=<` line to `[(add 5 7)
89+ (^add 5 7)]`. Can you recognize what's happening?
90+
91+Cheatsheet:
92+
93+- To pass arguments from the command line to a program, you
94+ replace the `*` in the first line of the boiler plate to
95+ `{^ {{arg/TYPE ~} ~}}` where `TYPE` is replaced with the
96+ type of argument you're expecting. Then `+euler1 a` from
97+ the dojo sets `arg` to `a`.
98+- The empty list is `~`
99+- Lisp-style cons (construct a cell/prepend an element) is
100+ `[new-element list]`
101+- For example, the first three positive integers are `[1 2 3
102+ ~]`
103+- `gte` tests whether `a` is greater than or equal to `b`.
104+- `mod` runs the modulo operation on two atoms.
105+- See the basic math section in `/arvo/hoon.hoon` for more info.
docs/dev/hoon/leap-in/subscriptions.md → docs/arvo/subscriptions.mdrenamed+51−53
@@ -1,6 +1,7 @@
11---
2+navhome: /docs
23next: true
3−sort: 4
4+sort: 5
45title: Subscriptions
56---
67
@@ -10,46 +11,46 @@ more often we want to subscribe to updates from another app. You
1011could build a subscription model out of one-way pokes, but it's
1112such a common pattern that it's built into arvo.
1213
13−Let's take a look at two apps, `:source` and `:sink`. First,
14−`:source`:
14+Let's take a look at two apps, `:examples-source` and `:examples-sink`. First,
15+`:examples-source`:
1516
1617```
1718/? 314
1819!:
1920|%
20−++ move ,[bone %diff mark *]
21+++ move {bone $diff mark *}
2122--
22−|_ [hid=bowl state=~]
23+|_ {hid/bowl state/$~}
2324++ poke-noun
24− |= arg=*
25− ^- [(list move) _+>.$]
25+ |= arg/*
26+ ^- {(list move) _+>.$}
2627 :_ +>.$
2728 %+ turn (prey /the-path hid)
28− |=([o=bone *] [o %diff %noun arg])
29+ |=({o/bone *} `move`[o %diff %noun arg])
2930++ peer
30− |= pax=path
31− ^- [(list move) _+>.$]
31+ |= pax/path
32+ ^- {(list move) _+>.$}
3233 ~& [%subscribed-to pax=pax]
3334 [~ +>.$]
3435--
3536```
3637
37−And secondly, `:sink`:
38+And secondly, `:examples-sink`:
3839
3940```
4041/? 314
4142|%
42−++ move ,[bone card]
43+++ move {bone card}
4344++ card
44− $% [%peer wire [@p term] path]
45− [%pull wire [@p term] ~]
45+ $% {$peer wire {@p term} path}
46+ {$pull wire {@p term} $~}
4647 ==
4748--
4849!:
49−|_ [bowl available=?]
50+|_ {bowl available/?}
5051++ poke-noun
51− |= arg=*
52− ^- [(list move) _+>.$]
52+ |= arg/*
53+ ^- {(list move) _+>.$}
5354 ?: &(=(%on arg) available)
5455 [[[ost %peer /subscribe [our %source] /the-path] ~] +>.$(available |)]
5556 ?: &(=(%off arg) !available)
@@ -57,13 +58,13 @@ And secondly, `:sink`:
5758 ~& ?:(available %not-subscribed %subscribed)
5859 [~ +>.$]
5960++ diff-noun
60− |= [wir=wire arg=*]
61− ^- [(list move) _+>.$]
61+ |= {wir/wire arg/*}
62+ ^- {(list move) _+>.$}
6263 ~& [%recieved-data arg]
6364 [~ +>.$]
6465++ reap
65− |= [wir=wire error=(unit tang)]
66− ^- [(list move) _+>.$]
66+ |= {wir/wire error/(unit tang)}
67+ ^- {(list move) _+>.$}
6768 ?~ error
6869 ~& %successfully-subscribed
6970 [~ +>.$]
@@ -111,48 +112,46 @@ Cheat sheet:
111112 the `|_`, as it lies above it: hoon.hoon `=> |% w types =>
112113 |_`
113114
114−
115−
116115
117116```
118117
119118Here's some sample output of the two working together:
120119
121120```
122−~fintud-macrep:dojo> |start %source
121+~fintud-macrep:dojo> |start %examples-source
123122>=
124−~fintud-macrep:dojo> |start %sink
123+~fintud-macrep:dojo> |start %examples-sink
125124>=
126−~fintud-macrep:dojo> :sink %on
125+~fintud-macrep:dojo> :examples-sink %on
127126[%subscribed-to pax=/the-path]
128127%successfully-subscribed]
129128>=
130−~fintud-macrep:dojo> :source 5
129+~fintud-macrep:dojo> :examples-source 5
131130[%received-data 5]
132131>=
133−~fintud-macrep:dojo> :sink %off
132+~fintud-macrep:dojo> :examples-sink %off
134133>=
135−~fintud-macrep:dojo> :source 6
134+~fintud-macrep:dojo> :examples-source 6
136135>=
137−~fintud-macrep:dojo> :sink %on
136+~fintud-macrep:dojo> :examples-sink %on
138137[%subscribed-to pax=/the-path]
139138%successfully-subscribed]
140139>=
141−~fintud-macrep:dojo> :source 7
140+~fintud-macrep:dojo> :examples-source 7
142141[%received-data 7]
143142>=
144143```
145144
146−###:source
145+###:examples-source
147146
148147Hopefully you can get a sense for what's happening here. When we
149−poke `:sink` with `%on`, `:sink` subscribes to `:source`, and so
150−whenever we poke `:source`, `:sink` gets the update and prints it
151−out. Then we unsubscribe by poking `:sink` with `%off`, and
152−`:sink` stops getting updates. We then resubscribe.
148+poke `:examples-sink` with `%on`, `:examples-sink` subscribes to `:examples-source`, and so
149+whenever we poke `:examples-source`, `:examples-sink` gets the update and prints it
150+out. Then we unsubscribe by poking `:examples-sink` with `%off`, and
151+`:examples-sink` stops getting updates. We then resubscribe.
153152
154−There's a fair bit going on in this code, Let's look at
155−`:source` first.
153+There's a fair bit going on in this code. Let's look at
154+`:examples-source` first.
156155
157156Our definition of `move` is fairly specific, since we're only
158157going to sending one kind of move. The `%diff` move is a
@@ -176,12 +175,12 @@ In our case, we don't care what path you subscribed on, and all
176175we do is print out that you subscribed. Arvo keeps track of your
177176subscriptions, so you don't have to. You can access your
178177subscribers by looking at `sup` in the bowl that's passed in.
179−`sup` is of type `(map bone ,[@p path])`, which associates bones
178+`sup` is of type `(map bone {@p path})`, which associates bones
180179with the urbit who subscribed, and which path they subscribed on.
181−If you want to talk to your subscribers, send them messages along
180+If you want to communicate with your subscribers, send them messages along
182181their bone.
183182
184−`++poke-noun` spams the given arguement to all our subscribers.
183+`++poke-noun` "spams" the given arguement to all our subscribers.
185184There's a few things we haven't seen before. Firstly, `:_(a b)`
186185is the same as `[b a]`. It's just a convenient way of formatting
187186things when the first thing in a cell is much more complicated
@@ -199,20 +198,20 @@ who are subscribed on a path that begins with the given path.
199198"Prey" is short for "prefix".
200199
201200Now we have the list of relevant subscribers. This a list of
202−triples, `[bone @p path]`, where the only thing we really need is
201+triples, `{bone @p path}`, where the only thing we really need is
203202the bone because we don't care what urbit they are or what exact
204203path they subscribed on. Thus, our transformer function takes
205−`[o=bone *]` and produces `[o %diff %noun arg]`, which is a move
206−that means "tell bone `o` this subscription update: `[%noun
204+`{o/bone *}` and produces `[o %diff %noun arg]`, which is a move
205+that provides bone `o` with this subscription update: `[%noun
207206arg]`". This is fairly dense code, but what it's doing is
208207straightforward.
209208
210−###:sink
209+###:examples-sink
211210
212−`:source` should now make sense. `:sink` is a little longer,
211+`:examples-source` should now make sense. `:examples-sink` is a little longer,
213212but not much more complicated.
214213
215−In `:sink`, our definition of of `++move` is different. All
214+In `:examples-sink`, our definition of of `++move` is different. All
216215moves start with a `bone`, and we conventionally refer to the
217216second half as the "card", so that we can say a move is an action
218217that sends a card along a bone.
@@ -227,13 +226,13 @@ this, because its semantics are to cancel any subscriptions
227226coming over this duct. If your bone and wire are the same as
228227when you subscribed, then the cancellation will happen correctly.
229228
230−The only state we need for `:sink` is a loobean to tell whether
231−we're already subscribed to `:source`. We use `available=?`,
229+The only state we need for `:examples-sink` is a boolean to indicate whether
230+we're already subscribed to `:examples-source`. We use `available/?`,
232231where `?` is the sign of type boolean (similar to `*`, `@`) (which defaults to true).
233232
234233In `++poke-noun` we check our input to see both if it's `%on` and
235234we're available. If so, we produce the move to subscribe to
236−`:source`:
235+`:examples-source`:
237236
238237```
239238[ost %peer /subscribe [our %source] /the-path]
@@ -243,7 +242,7 @@ Also, we set available to false (`|`) with `+>.$(available |)`.
243242
244243Otherwise, if our input is `%off` and we're already subscribed
245244(i.e. `available` is false), then we unsubscribe from
246−`:source`:
245+`:examples-source`:
247246
248247```
249248[ost %pull /subscribe [our %source] ~]
@@ -273,7 +272,6 @@ Moving forward, `++reap` is given the wire we attempted to
273272subscribe over, possibly along with an error message in cases of
274273failure. `(unit type)` means "either `~` or `[~ type]`, which
275274means it's used like Haskell's "maybe" or C's nullability. If
276−`error` is `~`, then the subscription was successful, so we tell
275+`error` is `~`, then the subscription was successful and we tell
277276that to the user. Otherwise, we print out the error message.
278277
279−Excercises XX
docs/dev/hoon/leap-in/web-apps.md → docs/arvo/web-apps.mdrenamed+46−49
@@ -1,9 +1,12 @@
11---
2+navhome: /docs
23next: true
3−sort: 6
4+sort: 7
45title: Web Apps
56---
67
8+# Backend
9+
710We've done purely functional web pages as hook files, and we've
811done command line apps, so now let's interact with an app over
912the web. The fundamental concepts are no different than from the
@@ -14,26 +17,26 @@ javascript.
1417Let's create a small web app that counts the number of times you
1518poke it. There'll be a button to poke the app, and line of text
1619below it saying how many times the app has been poked. We can
17−update this by subscribing to that information from the app.
20+update this by subscribing our page to the relevant path on its app.
1821
19−Let's first write the app, `/ape/click.hoon`:
22+Let's first write the app, `/app/click.hoon`:
2023
2124```
2225/? 314
2326!:
2427|%
25−++ move ,[bone %diff %mark *]
28+++ move {bone $diff $mark *}
2629--
2730!:
28−|_ [hid=bowl clicks=@]
31+|_ {hid/bowl clicks/@}
2932++ poke-click
30− |= click=%click
33+ |= click/$click
3134 ~& [%poked +(clicks)]
3235 :_ +>.$(clicks +(clicks))
3336 %+ turn (prey /the-path hid)
34− |=([o=bone *] [o %diff %clicks +(clicks)])
37+ |=({o/bone *} [o %diff %clicks +(clicks)])
3538++ peer-the-path
36− |= pax=path
39+ |= pax/path
3740 [[[ost.hid %diff %clicks clicks] ~] +>.$]
3841--
3942```
@@ -48,12 +51,12 @@ number of clicks.
4851Let's take a look at the new marks. Here's `/mar/click.hoon`:
4952
5053```
51−|_ click=%click
54+|_ click/$click
5255++ grab
5356 |%
5457 ++ noun |=(* %click)
5558 ++ json
56− |= jon=^json
59+ |= jon/^json
5760 ?> =('click' (need (so:jo jon)))
5861 %click
5962 --
@@ -69,19 +72,20 @@ asserting the parsing succeeded with `need`, and asserting the
6972result was 'click' with `?>`, which asserts that its first child
7073is true.
7174
72−> Note the argument to `++json`is `jon=^json`. Why `^json`?
73−> `++json` shadows the type definition, so if we want to refer to
74−> the type, we have to prepend a `^`. This extends to multiple
75−> levels: `^^^foo` means "not the innermost `foo`, nor the next
76−> innermost, nor the next innermost, but the next innermost".
75+<blockquote class="blockquote">
76+Note the argument to `++json`is `jon/^json`. Why `^json`?
77+`++json` shadows the type definition, so if we want to refer to
78+the type, we have to prepend a `^`. This extends to multiple
79+levels: `^^^foo` means the fourth most innermost instance of `foo`.
7780
78−> `++jo` in `zuse` is a useful library for parsing complex json
79−> into hoon structures. In this case, the `:` between `so` and
80−> `jo` means 'inside of', because `so` is an arm contained within
81−> the core `jo`. Our case is actually simple enough that the
82−> `?>` line could have been `?> =([%s 'click'] jon)`.
81+`++jo` in `zuse` is a useful library for parsing complex json
82+into hoon structures. In this case, the `:` between `so` and
83+`jo` means 'inside of', because `so` is an arm contained within
84+the core `jo`. Our case is actually simple enough that the
85+`?>` line could have been `?> =([%s 'click'] jon)`.
86+</blockquote>
8387
84−We can test this mark from the command line:
88+We can test this mark from the command line (don't forget to start your app with `|start %click`)
8589
8690```
8791~fintud-macrep:dojo> &click %click
@@ -99,7 +103,7 @@ ford: cast %click
99103And `/mar/clicks.hoon`:
100104
101105```
102−|_ clicks=@
106+|_ clicks/@
103107++ grow
104108 |%
105109 ++ json
@@ -111,13 +115,15 @@ And `/mar/clicks.hoon`:
111115`clicks` is just an atom. We convert to json by creating an
112116object with a single field "clicks" with our value.
113117
114−> Be sure to checkout section 3bD, JSON and XML, in zuse.hoon
115−> `++joba` is just a function that takes a key-value pair and
116−> produces a JSON object with one element.
118+<blockquote class="blockquote">
119+Be sure to checkout section 3bD, JSON and XML, in zuse.hoon
120+`++joba` is just a function that takes a key-value pair and
121+produces a JSON object with one element.
122+</blockquote>
117123
118124```
119125~fintud-macrep:dojo> &json &clicks 6
120−[%o p={[p='clicks' q=[%n p=~.^]]}]
126+[%o p={[p='clicks' q=[%n p=~.6]]}]
121127~fintud-macrep:dojo> &mime &json &clicks 6
122128[[%text %json ~] p=12 q='{"clicks":6}']
123129```
@@ -143,14 +149,16 @@ the app from the command line.
143149 `:click` and print out the subscription updates on the command
144150 line.
145151
152+#Frontend
153+
146154That's all that's needed for the back end. The front end is just
147−some "sail" html and javascript. Here's `/pub/click/hymn.hook`:
155+some "sail" html (Hoon markup for XML) and javascript. Here's `/web/click.hoon`:
148156
149157```
150158;html
151159 ;head
152160 ;script(type "text/javascript", src "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js");
153− ;script(type "text/javascript", src "/~~/~/at/home/lib/urb.js");
161+ ;script(type "text/javascript", src "/~/at/lib/js/urb.js");
154162 ;title: Clickety!
155163 ==
156164 ;body
@@ -159,7 +167,7 @@ some "sail" html and javascript. Here's `/pub/click/hymn.hook`:
159167 ;div#err(class "disabled");
160168 ;div#clicks;
161169 ==
162− ;script(type "text/javascript", src "click/main.js");
170+ ;script(type "text/javascript", src "/click/main.js");
163171 ==
164172==
165173```
@@ -168,10 +176,12 @@ You should recognize the sail syntax from an earlier chapter.
168176Aside from jquery, we also include `urb.js`, which is a framework
169177for interacting with urbit.
170178
179+To view the frontend, point your browser at `ship-name.urbit.org/~~/click` if you're on the live network. If you're running a fake galaxy, navigate to whatever port it's running on, which is usually: `https://localhost:8443/~~/click`.
180+
171181We have a button labeled "Poke!" and a div with id `clicks` where
172182we'll put the number of clicks. We also include a small
173183javascript file where the client-side application logic can be
174−found. It's in `/pub/click/main.js`:
184+found. It's in `/web/click/main.js`:
175185
176186```
177187$(function() {
@@ -208,14 +218,10 @@ $(function() {
208218})
209219```
210220
211−We first set the default application to "click". A page can, of
212−course, talk to multiple apps by specifying on each message which
213−app to talk to.
214−
215221We set up two event handlers. When we click the button, we run
216−`window.urb.send`, which sends a poke to an app. The arguments
217−are data, parameters, and callback. The data is the specific
218−data to send. The parameters are all optional, but here's a list
222+`window.urb.send`, which sends a poke to the app specified as the first argument, in this case our :click app. The arguments
223+are data, parameters, and the callback. The data is the specific
224+data we want to send. The parameters are all optional, but here's a list
219225of the available ones:
220226
221227- `ship`: target urbit. Defaults to `window.urb.ship`, which
@@ -231,15 +237,10 @@ In our case, we specify only that the mark is "click".
231237The callback funciton is called when we receive an
232238acknowledgment. If there was an error, we put it in the `err`
233239div that we defined above. Otherwise, we printf to the console a
234−message saying the poke succeeded. A common pattern is to gray
235−out a button when you click it and only reenable it when you get
236−the positive acknowledgment.
240+message saying the poke succeeded. As is common, we gray
241+out the button when it is clicked. It is only reenabled when positive acknowledgement is received.
237242
238−We also call `window.urb.bind`, which subscribes to a data stream
239−on an app. It also takes three arguments: path, parameters, and
240−callback. The path is the path on the app to subscribe to. The
241−parameters are all optional (inded, we omit them entirely here),
242−but are similar to those for `send`:
243+Our second event handler is `window.urb.bind`, which is called immediately when the page is loaded, subscribing the page to the specified data stream on the app set with `urb.appl` (which is, in this case, :click). It also takes three arguments: path, parameters, and callback. The path is the path on the app to subscribe to. The parameters are all optional (indeed, we omit them entirely here), but are similar to those for `send`:
243244
244245- `ship`: target urbit. Defaults to `window.urb.ship`, which
245246 defaults to the urbit which served the page.
@@ -255,10 +256,6 @@ The callback function here just updates the data in the `clicks`
255256div. A truly robust app would intelligently handle errors, of
256257course.
257258
258−This app can be tested from the web by going to
259−`/~~/home/pub/click` on your server. Usually, this is
260−`ship-name.urbit.org/~~/home/pub/click`.
261−
262259Note that the app doesn't have anything web-specific in itself.
263260As far as it knows, it's just receiving pokes and subscriptions.
264261The javascript is fairly pure as well, sending and receiving json
docs/dev.mddeleted−28
@@ -1,28 +0,0 @@
1−---
2−logo: black
3−sort: 2
4−title: Developer doc
5−---
6−<div class="short">
7−
8−# Developer documentation
9−
10−Urbit has three programming layers: [Nock](dev/nock) (combinator nano-VM),
11−[Hoon](dev/hoon) (strict functional language), and [Arvo](dev/arvo) (functional
12−OS).
13−
14−To code in Urbit, the least you need to learn is Hoon, plus a
15−little bit of Arvo. Nock is a sort of functional assembly
16−language -- you don't need to know it, but it's useful to.
17−Nock is also the easiest thing in the world to learn.
18−
19−You can program for Arvo without knowing much about Arvo
20−internals, but again it helps. But you need to know Hoon.
21−Don't worry, it's easier than it looks.
22−
23−Alas, the developer doc is still under construction. We'll have
24−more soon.
25−
26−<list></list>
27−
28−</div>
docs/dev/arvo.mddeleted−13
@@ -1,13 +0,0 @@
1−---
2−logo: black
3−sort: 3
4−title: Arvo
5−---
6−<div class="short">
7−
8−# Arvo
9−
10−Arvo is a functional operating system. But hopefully you knew that! Sorry,
11−please watch this space for actual documentation.
12−
13−</div>
docs/dev/client.mddeleted−11
@@ -1,11 +0,0 @@
1−---
2−hide: true
3−logo: black
4−sort: 4
5−title: Frontend tools
6−---
7−
8−Frontend tools
9−==============
10−
11−<list></list>
docs/dev/client/tree.mddeleted−59
@@ -1,59 +0,0 @@
1−# `:tree`
2−
3−`:tree` is the web filesystem interface. Odds are this file has been rendered for you by `:tree`.
4−
5−`:tree` is a single-page app that uses a backend in `/home/tree` to load
6−contents from `%clay` as the user navigates around as `%json`. The frontend
7−lives in `/home/pub/tree` and is a fairly straightforward
8−[React](https://facebook.github.io/react/) /
9−[Flux](https://facebook.github.io/flux/) app.
10−
11−## Frontend
12−
13−The frontend code for `:tree` can be found in `/home/pub/tree/src/`.
14−
15−### CSS
16−
17−The CSS is written in [Stylus](https://learnboost.github.io/stylus/). The main entry point is `main.styl` and can be compiled with `stylus main.styl` which should output a `main.css`
18−
19−### JS
20−
21−The JS is written in [CoffeeScript](http://coffeescript.org/) and packaged with
22−[Browserify](http://browserify.org/). The main entry point is `main.coffee` and
23−is compiled with `browserify -t coffeeify main.coffee > main.js`. You'll need
24−to `npm install` first.
25−
26−Each page is loaded as JSON and then rendered using React on the page. This
27−allows us to write JSX in our markdown to implement simple components. Check
28−out `/home/pub/tree/src/js/components` to see the component library.
29−
30−You'll notice that some of these doc pages use things like `<list>` in the raw markdown files.
31−
32−## JSON API
33−Async provides loading by schema
34−
35−`{path name sein sibs next prev}` are all immediately accesible from the store
36−
37−a `getPath` method, if present (defaulting to current url), is used to determine the query root node.
38−
39−## JSON Internals
40−
41−### `/[desk]/tree/{path}.json`
42−`tree/json.hook` accepts a query string schema `q` in light noun encoding
43−
44− ++ schema (dict ,[term $|(mark schema)])
45− ++ dict |*(a=_,* $&([a (dict a)] a))
46−
47−which is normalized and type-checked to a `query` list of
48−- `[%kids query]`, the only recursive value, which executes for all subpaths
49− XX descent is only currently supported to a single level as a performance optimization
50−- `[%name %t]`, the node name
51−- `[%path %t]`, the current path
52−- `[%snip %r]`, a snippet, extracted via `react-snip-json`
53−- `[%head %r]`, the first `<h1/>`, extracted via `react-head-json`
54−- `[%body %r]`, the `react-json` body
55−- `[%meta %j]`, json frontmatter per the `mdy` mark definition
56−
57−The request types above are `%t` text, `%r` html-derived tree, and `%j`
58−arbitrary json; an example query, used by the main content renderer, is
59−`"q=body.r__kids_name.t"` (`body:'r' kids:{name:'t'}` )
docs/dev/contributing.mddeleted−213
@@ -1,213 +0,0 @@
1−---
2−sort: 6
3−title: Contributing
4−---
5−
6−# Contributing to urbit
7−
8−Thank you for your interest in contributing to urbit.
9−
10−## Development practice
11−
12−You may have an identity on the live network, but doing all your
13−development on the live network would be cumbersome and unnecessary.
14−Standard practice in urbit development is to work on a fake `~zod`. A
15−fake `~zod` will get its initial files from the `urb/zod/` directory
16−rather than trying to sync them over the network, which is invaluable
17−for working in Hoon. Also, a fake `~zod` or any fake urbit instances you
18−start do not talk to the live network, but to a fake network that exists
19−only on your computer.
20−
21−To start a fake `~zod`, the command is:
22−
23− bin/urbit -F -I zod -c [pier directory]
24−
25−To resume one that was already created, just as on the live network,
26−remove `-c` (but leave the rest of the options there). `-F` uses the
27−fake network, and `-I` starts an "imperial" instance - that is, an 8-bit
28−galaxy.
29−
30−## Kernel development
31−
32−Working on either C or non-kernel Hoon should not bring any surprises,
33−but the Hoon kernel (anything under `urb/zod/arvo/`) is bootstrapped
34−from `urbit.pill` in `urb/`, and must be manually recompiled if any
35−changes are made. The command to manually recompile the kernel and
36−install the new kernel is `|reset` in `dojo`. This rebuilds from the
37−`arvo` directory in the `home` desk in `%clay`. Currently, `|reset`
38−does not reload apps like `dojo` itself, which will still reference the
39−old kernel. To force them to reload, make a trivial edit to their main
40−source file (under the `ape` directory) in `%clay`.
41−
42−If you do any kernel development, be sure to read the section below about
43−pills.
44−
45−## Git practice
46−
47−Since we use the GitHub issue tracker, it is helpful to contribute via a
48−GitHub pull request. If you already know what you are doing, skip down
49−to the Style section.
50−
51−Start by cloning the repository on your work machine:
52−
53− git clone https://github.com/urbit/urbit
54−
55−And, additionally, fork the repository on GitHub by clicking the "Fork"
56−button. Add your fork as a remote:
57−
58− git remote add [username] https://github.com/[username]/urbit
59−
60−and set it as the default remote to push to:
61−
62− git config --local remote.pushDefault [username]
63−
64−This is good practice for any project that uses git. You will pull
65−upstream branches from urbit/urbit and push to your personal urbit fork
66−by default.
67−
68−Next, check out `test`, which is the mainline development branch, and
69−base a new branch on it to do your work on:
70−
71− git checkout test
72− git checkout -b [branch name]
73−
74−Now you are free to do your work on this branch. When finished, you may
75−want to clean up your commits:
76−
77− git rebase -i test
78−
79−Then you can push to your public fork with `git push` and make a pull
80−request via the GitHub UI. Make sure you request to merge your branch
81−into `test`, not `master`.
82−
83−After your changes are merged upstream, you can delete your branch (via
84−github UI or `git push :[branch]` remotely, and with `git branch -d`
85−locally).
86−
87−## Style
88−
89−The urbit project uses two-space indentation and avoids tab characters.
90−In C code, it should not be too difficult to mimic the style of the code
91−around you, which is just fairly standard K&R with braces on every
92−compound statement. One thing to watch out for is top-level sections in
93−source files that are denoted by comments and are actually indented one
94−level.
95−
96−Hoon will be a less familiar language to many contributors. Some of our
97−less obvious stylistic rules are:
98−
99−- Keep your source files 80 characters or less wide. Many urbit
100− developers use 80 character terminals/tmux panes/&c.
101−- Tab characters are actually a syntax error, so be extra sure your
102− editor is not inserting any. Trailing whitespace is *usually* not a
103− syntax error, but avoiding it is encouraged.
104−- The kernel convention is that line comments start at column 57 with
105− the `::` followed by 2 spaces. This leaves 20 characters for the
106− comment. Outside the kernel, things are less strict.
107−- Tall arms within a core are conventionally separated by empty comments
108− (just `::`) at the same indentation level as the initial `++` or `+-`.
109− The last arm in a core is not followed by an empty comment, because it
110− is visually closed by the `--` that closes the core. The empty comment
111− is also sometimes omitted in data structure definitions.
112−
113−## The kernel and pills
114−
115−urbit bootstraps itself using a binary blob called `urbit.pill`, which
116−we do indeed keep in version control. This creates some special
117−requirements. If you are not changing anything in the kernel (everything
118−under `urb/zod/arvo/`) then you can skim this section (please do not
119−skip it entirely, though). If you *are* working there, then this
120−section is critically important!
121−
122−The procedure for creating `urbit.pill` is often called "soliding". It
123−is somewhat similar to `|reset`, but instead of replacing your running
124−kernel, it writes the compiled kernel to a file. The command to solid
125−is, on a fakezod:
126−
127− .urbit/pill +solid
128−
129−When the compilation finishes, your `urbit.pill` will be found in the
130−`[pier]/.urb/put/` directory. Copy it into `urb/` and add it to your
131−commit.
132−
133−The requirement here is that every commit that changes the kernel must
134−come with an `urbit.pill` built from the same code in `urb/zod/arvo/`
135−for that commit. (Only changing the actual Hoon code counts, so a change
136−to a jet with no corresponding Hoon change does not require a new pill.)
137−This is so that checking out an arbitrary revision and starting up a
138−fakezod actually works as expected. However you do this is fine, but I
139−like to do it as part of my committing process - just before `git
140−commit`, I fire up a new fakezod. This will use the previous
141−`urbit.pill`, but the kernel code in `%clay` will be copied from
142−`urb/zod/arvo/`, so `+solid` will compile it. Then I copy `urbit.pill`
143−into `urb/` and make my commit.
144−
145−If you rebase or interactive rebase your commits, be sure to preserve
146−this property on all the commits you end up with. If multiple people
147−were collaborating on your branch, you may end up with conflicts in
148−`urbit.pill` and have to merge the branch into itself to resolve them.
149−Just do the same procedure to create a new, merged pill before
150−committing the merge. Otherwise, just make sure to use the correct
151−`urbit.pill` for each commit.
152−
153−## Debug urbit with `gdb`
154−
155−Follow the build instructions in README.md but run `make` with argument `DEBUG=yes`:
156−
157−(If you've already built urbit first run `make clean`.)
158−
159− make DEBUG=yes
160−
161−Run `gdb`, while loading `bin/urbit` and its symbol table:
162−
163− gdb bin/urbit
164−
165−Set a breakpoint on `main()` (optional):
166−
167− break main
168−
169−Run your urbit comet `mycomet`:
170−
171− run mycomet
172−
173−Continue from the breakpoint on `main()`:
174−
175− continue
176−
177−## What to work on
178−
179−If you are not thinking of contributing with a specific goal in mind,
180−the GitHub issue tracker is the first place you should look for ideas.
181−Issues are tagged with a priority and a difficulty. A good place to
182−start is on either a low-difficulty issue or a low-priority issue.
183−Higher priority issues are likely to be assigned to someone - if this is
184−the case, then contacting that person to coordinate before starting to
185−work is probably a good idea.
186−
187−There is also a "help wanted" tag for things that we are especially
188−eager to have outside contributions on. Check here first!
189−
190−## Staying in touch
191−
192−The urbit developers communicate on urbit itself. Joining the
193−`~doznec/urbit-meta` channel on `talk` is highly recommended.
194−Subscribing to `urbit-dev` on Google Groups is also recommended, since
195−this is where continuity breach notifications are sent.
196−
197−You can also contact one of the following people:
198−
199−- Philip Monk
200−
201− email: philip.monk@tlon.io
202−
203− urbit: `~wictuc-folrex`
204−
205− GitHub: [@philipcmonk](https://github.com/philipcmonk/)
206−
207−- Raymond Pasco
208−
209− email: ray@the.ug
210−
211− urbit: `~ramtev-wisbyt`
212−
213− GitHub: [@juped](https://github.com/juped/)
docs/dev/hoon.mddeleted−24
@@ -1,24 +0,0 @@
1−---
2−logo: black
3−sort: 2
4−title: Hoon
5−---
6−
7−<div class="short">
8−
9−# Hoon
10−
11−Hoon is a strict, typed, pure functional language. This site is
12−served by an urbit written in Hoon.
13−
14−If you're interested in learning the fundamentals of Hoon from
15−the bottom up, start with [Principles of
16−Hoon](hoon/principles).
17−
18−If you want to jump into building things right away and prefer to
19−learn from the top down, check out [Leap into
20−Hoon](hoon/leap-in/basic).
21−
22−Both of these are under active development.
23−
24−</div>
docs/dev/hoon/leap-in.mddeleted−8
@@ -1,8 +0,0 @@
1−---
2−hide: false
3−next: false
4−sort: 1
5−title: Leap into Hoon
6−---
7−
8−<list></list>
docs/dev/hoon/leap-in/generators.mddeleted−177
@@ -1,177 +0,0 @@
1−---
2−next: true
3−sort: 7
4−title: Using Generators with Apps
5−---
6−
7−Up until now we've poked apps directly. This requires the user
8−to specify the mark, and it requires the app to accept the
9−arguments in a way that's convenient for users to input. This is
10−the "plumbing" way to interact with apps. Generators are the
11−"porcelain" layer. This is why when you run a command like `+ls` or
12−`|merge`, there are no marks in sight.
13−
14−We've used generators before, back in [Basic
15−Operation](basic). At that point, we just used the generators
16−to produce values -- we didn't pipe their results into apps. In
17−the dojo cast, the role of a generator is to take a list of
18−arguments and produce a value, which is often, though not always,
19−piped into an app. Generators are pure, stateless functions, and
20−they cannot send moves.
21−
22−`+ls` and `+cat` are commonly-used generators that produce a directory
23−listing and print out a file, respectively. These are useful in
24−themselves, so we generally don't pipe the results into an app.
25−
26−Another generator is `+hood/merge`. Try running `+hood/merge`
27−with the normal arguments for `|merge`:
28−
29−```
30−~fintud-macrep:dojo> +hood/merge %home our %they
31−[syd=%home her=~fintud-macrep sud=%they gem=%auto]
32−~fintud-macrep:dojo> +hood/merge %home our %they, =gem %this
33−[syd=%home her=~fintud-macrep sud=%they gem=%auto]
34−```
35−
36−This didn't run any merge, it just constructed the command that,
37−if sent to `:hood`, would run it. Note first that, even though
38−it's not printed, this value has mark `kiln-merge`. Also, the
39−merge strategy `gem=%auto` was added automatically. Optional
40−arguments are straightforward with generators.
41−
42−In general, generators are prepended by either `+` or `|`. The
43−general form is `+generator`, but often generators are created
44−specifically to work with a single app, they're usually placed in
45−a subdirectory of gen and run with `|`. Thus, if `my-generator`
46−generator is made for use with `:my-app`, then `my-generator` is
47−put in `/gen/my-app/my-generator.hoon`, and can be run directly
48−with `+my-app/my-generator <args>`. If you want to pipe the
49−result into `:my-app`, then run `:my-app +my-app/my-generator
50−<args>`. Because this pattern is so common, this can be
51−abbreviated to `:my-app|my-generator <args>`. Because most
52−built-in commands are generators for the `:hood` app,
53−`:hood|generator <args>` can be shortened to `|generator <args>`.
54−
55−XXThe paragraph above is too long and confusing
56−
57−Let's write a generator for a modified version of `:pong` from
58−the chapter on [Network Messages](network). Recall that `:pong`
59−takes an urbit address, which is of mark `urbit`, and sends that
60−urbit the message `'howdy'`. First--without a generator--let's
61−make `:ping` that does the same, except that it lets the user
62−optionally specify the message as well.
63−
64−We'll need a new mark for our arguments. Let's call it
65−`ping-message`.
66−
67−> For app-specific marks, it's good style to prefix the name of
68−> the mark with the name of the app. Since many apps have
69−> several such marks, subdirectories in `/mar` are rendered as
70−> `-`, so that `ping-message` is written in
71−> (`/mar/ping/message.hoon`).
72−
73−```
74−|_ [to=@p message=@t]
75−++ grab
76− |%
77− ++ noun ,[@p @t]
78− --
79−--
80−```
81−
82−The app can easily be modified to use this (`/ape/ping.hoon`):
83−
84−```
85−/? 314
86−|%
87− ++ move ,[bone term wire *]
88−--
89−!:
90−|_ [bowl state=~]
91−::
92−++ poke-ping-message
93− |= [to=@p message=@t]
94− ^- [(list move) _+>.$]
95− [[[ost %poke /sending [to dap] %atom message] ~] +>.$]
96−::
97−++ poke-atom
98− |= arg=@
99− ^- [(list move) _+>.$]
100− ~& [%receiving (,@t arg)]
101− [~ +>.$]
102−::
103−++ coup |=(* `+>)
104−--
105−```
106−
107−Now we can run this with:
108−
109−```
110−~fintud-macrep:dojo> |start %ping
111−>=
112−~fintud-macrep:dojo> :ping &ping-message [~sampel-sipnym 'heyya']
113−>=
114−```
115−
116−And on `~sampel-sipnym`, assuming it's running `:ping` as well,
117−we see `[%receiving 'heyya']`.
118−
119−This is an annoying way to invoke the app, though. The `[]` are
120−mandatory, and optional arguments are hard. Let's make a
121−generator, `+send` to make everything nicer. Since it's specific
122−to `:ping`, let's put it in `/gen/ping/send.hoon`:
123−
124−```
125−:- %say
126−|= [^ [[to=@p message=?(~ [text=@t ~])] ~]]
127−[%ping-message to ?~(message 'howdy' text.message)]
128−```
129−
130−A couple of new things here. Firstly, `message=?(~ [text=@t ~])`
131−should be read as "the message is either null or a pair of text
132−and null". Generator argument lists are always null-terminated,
133−which makes it convenient to accept lists in tail position (which
134−are particularly annoying without generators). `?(a b)` is the
135−irregular form of `$?(a b)`, which is a union type. Thus, `?(a
136−b)` means the type of anything that's in either `a` or `b`.
137−Thus, in our case, `?(~ [text=@t ~])` is either null or a pair of
138−text and null.
139−
140−Secondly, `?~(a b c)` is a rune which means "if the `a` is null,
141−do `b`, else `c`". It is roughly equivalent to `?:(=(~ a) b c)`.
142−
143−> `?~(a b c)` is actually equivalent to `?:=(?=(~ a) b c)`,
144−> which, although identical at run time, is subtly different at
145−> compile time. Specifically, using `?=` rather than `=` means
146−> that we're checking whether `a` is in the *type* of `~`, and so
147−> the compiler knows that in the `b` case `a` is null, and in the
148−> `c` case `a` is not null. Since `=` is purely a runtime value
149−> check with no type implications, the compiler doesn't gain any
150−> information.
151−>
152−> At any rate, this is the reason why we can refer to
153−> `text.message` in the `c` clause. The compiler knows that
154−> `message` is not null, so it must have `text` within it. If
155−> you used `?:(=(~ message) 'howdy' text.message)` the compiler
156−> would complain that it doesn't know whether `message` has
157−> `text` within it.
158−
159−This is run as follows:
160−
161−```
162−~fintud-macrep:dojo> :ping|send ~sampel-sipnym
163−>=
164−~fintud-macrep:dojo> :ping|send ~sampel-sipnym 'how do you do'
165−>=
166−```
167−
168−Which causes `~sampel-sipnym` to print `[%receiving 'howdy']` and
169−`[%receiving 'how do you do']`.
170−
171−**Exercises**:
172−
173−- Create a generator for `:sum` from [State](state) so that
174− you can run `:sum|add 5` to add numbers to it.
175−
176−- Create a generator for `:click` from [Web Apps](web-apps) so
177− that you can run `:click|poke` to poke it.
docs/dev/hoon/library.mddeleted−7
@@ -1,7 +0,0 @@
1−Library
2−========
3−
4−<list dataPreview="true" titlesOnly="true"></list>
5−
6−
7−<search/>
docs/dev/hoon/library/0.mddeleted−39
@@ -1,39 +0,0 @@
1−volume 0, Kelvin Versioning.
2−===========================
3−
4−### `++hoon`
5−
6−Hoon version number Kelvin
7−
8−Traditional software versioning schema use fractions, and count up. Thus, they
9−can keep extending and revising their systems incrementally. This is generally
10−considered a good thing, and it generally is.
11−
12−In some cases, however, specifications needs to be permanently frozen.
13−This requirement is generally found in the context of standards. Some
14−standards are extensible or versionable, but some are not. ASCII, for
15−instance, is perma-frozen. So is IPv4 (its relationship to IPv6 is
16−little more than nominal - if they were really the same protocol, they'd
17−have the same ethertype). Moreover, many standards render themselves
18−incompatible in practice through excessive enthusiasm for extensibility.
19−They may not be perma-frozen, but they probably should be.
20−
21−As urbit is designed to be a standard, we devised a versioning scheme that will
22−allow it to eventually be frozen: Kelvin versioning. In Kelvin versioning,
23−releases count down by integer degrees Kelvin. At absolute zero, the system can
24−no longer be changed. At 1K, one more modification is possible. And so on. For
25−instance, Nock is at 5K. It might change, though it probably won't. Nouns
26−themselves are at 0K - it is impossible to imagine changing anything about
27−their three sentence definition.
28−
29−Source
30−------
31−
32− ++ hoon %164 :: version stub
33−
34−Examples
35−--------
36−
37− ~zod/try=> hoon
38− %163
39−
docs/dev/hoon/library/1.mddeleted−2237
@@ -1,2237 +0,0 @@
1−volume 1, Hoon Structures
2−=========================
3−
4−------------------------------------------------------------------------
5−
6−### `++abel`
7−
8−Biblical names in hoon are primarily aliases for the compiler.
9−
10−Source
11−------
12−
13− ++ abel typo :: original sin: type
14−
15−Examples
16−--------
17−
18− ~zod/try=> *abel
19− %void
20−
21−------------------------------------------------------------------------
22−
23−### `++axis`
24−
25−Nock axis
26−
27−A Nock axis inside a [noun](). After the leading 1, in binary, a `1` signfies
28−right and `0` left.
29−
30−Source
31−------
32−
33− ++ axis ,@ :: tree address
34−
35−Examples
36−--------
37−
38− ~zod/try=> *axis
39− 0
40−
41− ~zod/try=> :: 0 is not actually a valid axis
42− ~zod/try=> [[4 5] 6 7]
43− [[4 5] 6 7]
44− ~zod/try=> `axis`0b110
45− 6
46−
47−-----------------------------------------------------------------------
48−
49−### `++base`
50−
51−Base type
52−
53−A base type that [noun]()s are built from. A `++base` is either a noun, cell, boolean or
54−null labelled with an [odor]().
55−
56−Source
57−------
58−
59− ++ base ?([%atom p=odor] %noun %cell %bean %null) :: axils, @ * ^ ? ~
60−
61−Examples
62−--------
63−
64− ~zod/try=> *base
65− %null
66−
67− ~zod/try=> (ream '=|(^ !!)')
68− [%tsbr p=[%axil p=%cell] q=[%zpzp ~]]
69− ~zod/try=> :: p.p is a ++base
70− ~zod/try=> (ream '=|(@t !!)')
71− [%tsbr p=[%axil p=[%atom p=~.t]] q=[%zpzp ~]]
72− ~zod/try=> (ream '=|(? !!)')
73− [%tsbr p=[%axil p=%bean] q=[%zpzp ~]]
74−
75−------------------------------------------------------------------------
76−
77−### `++bean`
78−
79−Boolean
80−
81−`0`, `&`, or `%.y` are true, and `1`, `|`, and `%.n` are false.
82−
83−Source
84−------
85−
86− ++ bean ,? :: 0=&=yes, 1=|=no
87−
88−Examples
89−--------
90−
91− ~zod/try=> *bean
92− %.y
93−
94− ~zod/try=> `bean`&
95− %.y
96− ~zod/try=> `bean`|
97− %.n
98−
99−------------------------------------------------------------------------
100−
101−### `++beer`
102−
103−Tape builder
104−
105−Used to build [tape]()s internally.
106−
107−Source
108−------
109−
110− ++ beer $|(@ [~ p=twig]) :: simple embed
111−
112−Examples
113−--------
114−
115− ~zod/try=> `beer`'as'
116− 29.537
117− ~zod/try=> `beer`[~ (ream 'lan')]
118− [~ p=[%cnzz p=~[%lan]]]
119−
120−------------------------------------------------------------------------
121−
122−### `++beet`
123−
124−XML interpolation cases
125−
126−Used internally.
127−
128−Source
129−------
130−
131− ++ beet $| @ :: advanced embed
132− $% [%a p=twig] :: take tape
133− [%b p=twig] :: take manx
134− [%c p=twig] :: take marl
135− [%d p=twig] :: take $+(marl marl)
136− [%e p=twig q=(list tuna)] :: element literal
137− == ::
138−
139−------------------------------------------------------------------------
140−
141−### `++bloq`
142−
143−Blocksize
144−
145−Atom representing a blocksize, by convention expressed as a power of 2.
146−
147−
148−Source
149−------
150−
151− ++ bloq ,@ :: blockclass
152−
153−Examples
154−--------
155−
156− ~zod/try=> :: ++met measures how many bloqs long an atom is
157− ~zod/try=> (met 3 256)
158− 2
159− ~zod/try=> :: 256 is 2 bloqs of 2^3
160−
161−------------------------------------------------------------------------
162−
163−### `++calf`
164−
165−Cyclical backreferences
166−
167−Encodes cyclical backreferences in types. Used in pretty printing.
168−
169−Source
170−------
171−
172− ++ calf ,[p=(map ,@ud wine) q=wine] ::
173−
174−Examples
175−--------
176−
177− ~zod/try=> `calf`[~ %atom %ta]
178− [p={} q=[%atom p=%ta]]
179−
180− ~zod/try=> `calf`~(dole ut p:!>(*^))
181− [p={} q=[%plot p=~[%noun %noun]]]
182−
183− ~zod/try=> `calf`~(dole ut p:!>($:|-(?(~ [* $]))))
184− [ p={[p=1 q=[%pick p=~[[%pear p=%n q=0] [%plot p=~[%noun [%stop p=1]]]]]]}
185− q=[%stop p=1]
186− ]
187−
188−------------------------------------------------------------------------
189−
190−### `++char`
191−
192−Char
193−
194−A single character. [odor]() [`@tD`]() designates a single unicode byte. All
195−parsers consume [`++tape`]()s, which are lists of `++char`.
196−
197−
198−Source
199−------
200−
201− ++ char ,@tD :: UTF-8 byte
202−
203−Examples
204−--------
205−
206− ~zod/try=> *char
207− ''
208− ~zod/try> (char 97)
209− 'a'
210−
211−------------------------------------------------------------------------
212−
213−### `++chub`
214−
215−Attach jets
216−
217−Used by the compiler (implicitly by `%sgcn`) to attach jets.
218−
219−Source
220−------
221−
222− ++ chub :: registered battery
223− $: p=(pair chum tyre) :: definition
224− q=* :: battery
225− r=(unit (pair axis chub)) :: parent
226− == ::
227−
228−------------------------------------------------------------------------
229−
230−### `++chum`
231−
232−Jet hint information
233−
234−Jet hint information that must be present in the body of a `~/` or `~%`
235−rune. A `++chum` can optionally contain a kelvin version, jet vendor,
236−and "{major}.{minor}" version number.
237−
238−Source
239−------
240−
241− ++ chum $? lef=term :: jet name
242− [std=term kel=@] :: kelvin version
243− [ven=term pro=term kel=@] :: vendor and product
244− [ven=term pro=term ver=@ kel=@] :: all of the above
245− == ::
246−
247−Examples
248−--------
249−
250−XX there's a ++chum in zuse that's politely causing this not to work
251−
252− ~zod/try=> `chum`'hi'
253− lef=%hi
254−
255− ~zod/try=> (ream '~/(%lob.314 !!)')
256− [%sgfs p=[std=%lob kel=314] q=[%zpzp ~]]
257−
258−------------------------------------------------------------------------
259−
260−### `++clue`
261−
262−Attach jet
263−
264−Used by compiler to attach jets.
265−
266−Source
267−------
268−
269− ++ clue ,[p=axis q=chum r=tyre] :: battery definition
270−
271−XX implementation does not currenlty match docs
272−
273−------------------------------------------------------------------------
274−
275−### `++coil`
276−
277−Tuple of core information
278−
279−Variance `p`, subject type `q`, and `q`: optional compiled nock, and arms. Used as an
280−intermediate step within Section 2fB. Converted by `++core` to %core type.
281−
282−Source
283−------
284−
285− ++ coil $: p=?(%gold %iron %lead %zinc) :: core type
286− q=type ::
287− r=[p=?(~ ^) q=(map term foot)] ::
288− == ::
289−
290−------------------------------------------------------------------------
291−
292−### `++coin`
293−
294−Noun literal syntax cases
295−
296−Noun literal syntax cases: atoms, jammed nouns, and nestable tuples.
297−Parsed and printed using [`++so`]() and [`++co`]() cores.
298−
299−Source
300−------
301−
302− ++ coin $% [%$ p=dime] ::
303− [%blob p=*] ::
304− [%many p=(list coin)] ::
305− == ::
306−
307−Examples
308−--------
309−
310− ~zod/try=> `coin`(need (slay '~s1'))
311− [%$ p=[p=~.dr q=18.446.744.073.709.551.616]]
312− ~zod/try=> `coin`(need (slay '0x2b59'))
313− [%$ p=[p=~.ux q=11.097]]
314−
315− ~zod/try=> ~(rend co [%many ~[[%$ %ud 1] [%$ %tas 'a'] [%$ %s -2]]])
316− "._1_a_-2__"
317− ~zod/try=> ._1_a_-2__
318− [1 %a -2]
319−
320− ~zod/try=> `@uv`(jam [3 4])
321− 0v2cd1
322− ~zod/try=> (slay '~02cd1')
323− [~ [%blob p=[3 4]]]
324− ~zod/try=> ~02cd1
325− [3 4]
326−
327−------------------------------------------------------------------------
328−
329−### `++cord`
330−
331−UTF-8 text
332−
333−One of Hoon's two string types (the other being [`++tape`]()). A cord is an
334−atom of UTF-8 text. [`++trip`]() and [`++crip`]() convert between cord and
335−`++tape`.
336−
337−Source
338−------
339−
340− ++ cord ,@t :: text atom (UTF-8)
341−
342−Examples
343−--------
344−
345−Odor [`@t`]() designates a Unicode atom, little-endian: the first character
346−in the text is the low byte.
347−
348− ~zod/try=> `@ux`'foobar'
349− 0x7261.626f.6f66
350−
351− ~zod/try=> `@`'urbit'
352− 499.984.265.845
353− ~zod/try=> (cord 499.984.265.845)
354− 'urbit'
355−
356−------------------------------------------------------------------------
357−
358−### `++date`
359−
360−Point in time
361−
362−A boolean designating AD or BC, a year atom, a month
363−atom, and a [`++tarp`](), which is a day atom and a time.
364−
365−Source
366−------
367−
368− ++ date ,[[a=? y=@ud] m=@ud t=tarp] :: parsed date
369−
370−Examples
371−--------
372−
373−See also: [`++year`](), [`++yore`]() [`++stud`](), [`++dust`]()
374−
375− ~zod/try=> `date`(yore ~2014.6.6..21.09.15..0a16)
376− [[a=%.y y=2.014] m=6 t=[d=6 h=21 m=9 s=15 f=~[0xa16]]]
377−
378−------------------------------------------------------------------------
379−
380−### `++dime`
381−
382−Odor-atom pair
383−
384−Used in [`++coin`](). Convenience methods [`++scot`]() and [`++scow`]() (in
385−Section 2eL) print dimes as [`++cord`]() and [`++tape`](), respectively.
386−[`++slat`](), [`++slav`](), and [`++slaw`]() are used to parse atoms of
387−specific [odor]()s.
388−
389−Source
390−------
391−
392− ++ dime ,[p=@ta q=@] ::
393−
394−Examples
395−--------
396−
397− ~zod/try=> +>:(slay '0x123')
398− p=[p=~.ux q=291]
399−
400−------------------------------------------------------------------------
401−
402−### `++each`
403−
404−Mold of fork between two
405−
406−[mold]() generator: produces a dicriminated [fork]() between two types.
407−
408−Source
409−------
410−
411− ++ each |*([a=$+(* *) b=$+(* *)] $%([& p=a] [| p=b])) :: either a or b
412−
413−Examples
414−--------
415−
416− ~zod/try=> :type; *(each cord time)
417− [%.y p='']
418− {[%.y p=@t] [%.n p=@da]}
419−
420−------------------------------------------------------------------------
421−
422−### `++edge`
423−
424−Parsing location metadata
425−
426−Optional result `p` and parsing continuation `q`.
427−
428−Source
429−------
430−
431− ++ edge ,[p=hair q=(unit ,[p=* q=nail])] :: parsing output
432−
433−Examples
434−--------
435−
436−See also: Section 2eD, [`++rule`]()
437−
438− ~zod/try=> *edge
439− [p=[p=0 q=0] q=~]
440− ~zod/try=> (tall:vast [1 1] "a b")
441− [p=[p=1 q=2] q=[~ [p=[%cnzz p=~[%a]] q=[p=[p=1 q=2] q=" b"]]]]
442−
443−------------------------------------------------------------------------
444−
445−### `++foot`
446−
447−Cases of arms by variance model.
448−
449−`%ash` arms are [`dry`]() and [geometric]().
450−
451−Source
452−------
453−
454− ++ foot $% [%ash p=twig] :: dry arm, geometric
455− [%elm p=twig] :: wet arm, generic
456− [%oak ~] :: XX not used
457− [%yew p=(map term foot)] :: XX not used
458− == ::
459−
460−Examples
461−--------
462−
463−See also: [`++ap`](), [`++ut`]()
464−
465− ~zod/try=> *foot
466− [%yew p={}]
467−
468− ~zod/try=> (ream '|% ++ $ foo --')
469− [%brcn p={[p=%$ q=[%ash p=[%cnzz p=~[%foo]]]]}]
470− ~zod/try=> +<+:(ream '|% ++ $ foo --')
471− t=~[%ash %cnzz %foo]
472− ~zod/try=> (foot +<+:(ream '|% ++ $ foo --'))
473− [%ash p=[%cnzz p=~[%foo]]]
474− ~zod/try=> (foot +<+:(ream '|% +- $ foo --'))
475− [%elm p=[%cnzz p=~[%foo]]]
476−
477−------------------------------------------------------------------------
478−
479−### `++gate`
480−
481−Function
482−
483−A core with one arm, `$`--the empty name--which transforms a sample noun into a product
484−noun. If used [dryly]() as a type, the [subject]() must have a sample type of [`*`]().
485−
486−
487−Source
488−------
489−
490− ++ gate $+(* *) :: general gate
491−
492−Examples
493−--------
494−
495−See also: [`++lift`](), [`++cork`]()
496−
497− ~zod/try=> *gate
498− <1|mws [* <101.jzo 1.ypj %164>]>
499− ~zod/try=> `gate`|=(* 0)
500− <1|mws [* <101.jzo 1.ypj %164>]>
501−
502− ~zod/try=> (|=(a=* [a 'b']) 'c')
503− [99 'b']
504− ~zod/try=> (`gate`|=(a=* [a 'b']) 'c')
505− [99 98]
506−
507−------------------------------------------------------------------------
508−
509−### `++hair`
510−
511−Parsing line and column
512−
513−A pair of two [`@ud`]() used in parsing indicating line and column number.
514−
515−Source
516−------
517−
518− ++ hair ,[p=@ud q=@ud] :: parsing trace
519−
520−Examples
521−--------
522−
523− ~zod/try=> *hair
524− [p=0 q=0]
525−
526− ~zod/try=> `hair`[1 1] :: parsing starts at [1 1] as a convention.
527− [p=1 q=1]
528− ~zod/try=> ((plus ace) [1 1] " --")
529− [p=[p=1 q=4] q=[~ u=[p=[~~. " "] q=[p=[p=1 q=4] q="--"]]]]
530− ~zod/try=> `hair`p:((plus ace) [1 1] " --")
531− [p=1 q=4]
532−
533−------------------------------------------------------------------------
534−
535−### `++like`
536−
537−Mold generator for an edge
538−
539−`++like` generates an `++edge` with a parsed result set to a specific type.
540−
541−Source
542−------
543−
544− ++ like |* a=_,* :: generic edge
545− ?@ +.b ~ ::
546− :- ~ ::
547− u=[p=(a +>-.b) q=[p=(hair -.b) q=(tape +.b)]] ::
548−
549−Examples
550−--------
551− ~zod/try=> *(like char)
552− [p=[p=0 q=0] q=~]
553−
554− ~zod/try=> (ace [1 1] " a")
555− [p=[p=1 q=2] q=[~ [p=~~. q=[p=[p=1 q=2] q="a"]]]]
556− ~zod/try=> `(like char)`(ace [1 1] " a")
557− [p=[p=1 q=2] q=[~ [p=~~. q=[p=[p=1 q=2] q="a"]]]]
558− ~zod/try=> `(like ,@)`(ace [1 1] " a")
559− [p=[p=1 q=2] q=[~ [p=32 q=[p=[p=1 q=2] q="a"]]]]
560−
561−------------------------------------------------------------------------
562−
563−### `++limb`
564−
565− ++ limb $|(term $%([%& p=axis] [%| p=@ud q=term])) ::
566−
567−XX move to `++ut`
568−
569−Reference into subject by name/axis
570−
571−See also: section 2fC-2fD
572−
573− ~zod/try=> (ream '^^$')
574− [%cnzz p=~[[%.n p=2 q=%$]]]
575− ~zod/try=> (limb &2:(ream '^^$'))
576− [%.n p=2 q=%$]
577− ~zod/try=> (limb &2:(ream '^^^$'))
578− [%.n p=3 q=%$]
579−
580−------------------------------------------------------------------------
581−
582−### `++line`
583−
584−XX move to `++ut`
585−
586−Source
587−------
588−
589− ++ line ,[p=[%leaf p=odor q=@] q=tile] :: %kelp case
590−
591−
592−Examples
593−--------
594−
595− ~zod/try=> (ream '$%([1 a] [%2 b])')
596− [ %bccm
597− p
598− [ %kelp
599− p
600− [ i=[p=[%leaf p=~.ud q=1] q=[%herb p=[%cnzz p=~[%a]]]]
601− t=~[[p=[%leaf p=~.ud q=2] q=[%herb p=[%cnzz p=~[%b]]]]]
602− ]
603− ]
604− ]
605− ~zod/try=> &3:(ream '$%([1 a] [%2 b])')
606− p=[p=[%leaf p=%ud q=1] q=[%herb p=[%cnzz p=~[%a]]]]
607− ~zod/try=> (line &3:(ream '$%([1 a] [%2 b])'))
608− [p=[%leaf p=~.ud q=1] q=[%herb p=[%cnzz p=~[%a]]]]
609−
610−------------------------------------------------------------------------
611−
612−### `++list`
613−
614−List
615−
616−[mold]() generator. `++list` generates a mold of a null-termanated list of a
617−homogenous type.
618−
619−
620−Source
621−------
622−
623− ++ list |* a=_,* :: null-term list
624−
625−Examples
626−--------
627−
628−See also: [`++turn`](), [`++snag`]()
629−
630− ~zod/try=> *(list)
631− ~
632− ~zod/try=> `(list ,@)`"abc"
633− ~[97 98 99]
634− ~zod/try=> (snag 0 "abc")
635− ~~a
636−
637−------------------------------------------------------------------------
638−
639−### `++lone`
640−
641−Tile generator. `++lone` puts face of `p` on something.
642−
643−XX unused
644−
645−Source
646−------
647−
648− ++ lone |*(a=$+(* *) ,p=a) :: just one thing
649−
650−------------------------------------------------------------------------
651−
652−### `++mane`
653−
654−XML name
655−
656−An XML name (tag name or attribute name) with an optional namespace. Parsed by
657−[`++name`]() within [`++poxa`](), rendered by [`++name`]() within `++poxo`.
658−
659−Source
660−------
661−
662− ++ mane $|(@tas [@tas @tas]) :: XML name/space
663−
664−Examples
665−--------
666−
667−See also: [`++sail`]()
668−
669− ~zod/try=> *mane
670− %$
671−
672− ~zod/try=> `mane`n.g:`manx`;div:namespace;
673− %div
674− ~zod/try=> `mane`n.g:`manx`;div_namespace;
675− [%div %namespace]
676−
677−------------------------------------------------------------------------
678−
679−### `++manx`
680−
681−XML node.
682−
683−Parsed by [`++apex`]() within [`++poxa`](), rendered by [`++poxo`]().
684−
685−Source
686−------
687−
688− ++ manx ,[g=marx c=marl] :: XML node
689−
690−Examples
691−--------
692−
693−See also: [`++sail`]() doc
694−
695−------------------------------------------------------------------------
696−
697−### `++marl`
698−
699−List of XML nodes
700−
701−A list of [`++manx`]().
702−
703−Source
704−------
705−
706− ++ marl (list manx) :: XML node list
707−
708−Examples
709−--------
710−
711−
712−------------------------------------------------------------------------
713−
714−### `++mars`
715−
716−XML CDATA
717−
718−Implicitly produced by [`++chrd`]() within [`++poxa`]()
719−
720−Source
721−------
722−
723− ++ mars ,[t=[n=%$ a=[i=[n=%$ v=tape] t=~]] c=~] :: XML cdata
724−
725−Examples
726−--------
727−
728−------------------------------------------------------------------------
729−
730−### `++mart`
731−
732−List of XML attributes
733−
734−Each `++mart` is a list of pairs of [`++mane`]() and
735−[`++tape`]().
736−
737−Parsed by [`++attr`]() within [`++poxa`](), rendered by `++attr` within [`++poxo`]()
738−
739−Source
740−------
741−
742− ++ mart (list ,[n=mane v=tape]) :: XML attributes
743−
744−Examples
745−--------
746−
747−------------------------------------------------------------------------
748−
749−### `++marx`
750−
751−XML tag
752−
753−A `++marx` is a pair of a tag name, `++mane` and a list of attributes,
754−`++mart`. Parsed by [`++head`]() `++poxa`, rendered within `++poxo`.
755−
756−Source
757−------
758−
759− ++ marx ,[n=mane a=mart] :: XML tag
760−
761−Examples
762−--------
763−
764−------------------------------------------------------------------------
765−
766−### `++metl`
767−
768− ++ metl ?(%gold %iron %zinc %lead) :: core variance
769−
770−XX move to `++ut`
771−
772−See also: [`++coil`]()
773−
774−------------------------------------------------------------------------
775−
776−### `++noun`
777−
778− ++ noun ,* :: any noun
779−
780−Used nowhere XX
781−
782− ~zod/try=> `noun`~[1 2 3]
783− [1 2 3 0]
784−
785−------------------------------------------------------------------------
786−
787−### `++null`
788−
789− ++ null ,~ :: null, nil, etc
790−
791−Used nowhere XX
792−
793− ~zod/try=> :type; *null
794− ~
795− %~
796−
797−------------------------------------------------------------------------
798−
799−### `++odor`
800−
801−'type' of atom
802−
803−By convention, a short name for a category of atom. `++odor` is
804−circularly defined, with [`@ta`]() being the `++odor` of the ASCII subset
805−commonly used in urbit.
806−
807−Source
808−------
809−
810− ++ odor ,@ta :: atom format
811−
812−Examples
813−--------
814−
815−See also: [`++base`](), [odor reference]()
816−
817− ~zod/try=> `odor`%ux
818− ~.ux
819−
820−------------------------------------------------------------------------
821−
822−### `++tarp`
823−
824−Day through second
825−
826−The remaining part of a [`++date`](): day, hour, minute, second and a list
827−of [`@ux`]() for precision.
828−
829−Source
830−------
831−
832− @ud h=@ud m=@ud s=@ud f=(list ,@ux)] :: parsed time
833−
834−Examples
835−--------
836−
837−See also: [`++date`](), [`++yell`[]()/`++yule`]()
838−
839− ~zod/try=> -<-
840− ~2014.9.20..00.43.33..b52a
841− ~zod/try=> :: the time is always in your context at -<-
842− ~zod/try=> (yell -<-)
843− [d=106.751.991.820.278 h=0 m=43 s=39 f=~[0x54d1]]
844−
845− ~zod/try=> (yell ~d20)
846− [d=20 h=0 m=0 s=0 f=~]
847−
848−------------------------------------------------------------------------
849−
850−### `++time`
851−
852−Absolute date
853−
854−The `@da` odor designates an absolute date atom.
855−
856−Source
857−------
858−
859− ++ time ,@da :: galactic time
860−
861−Examples
862−--------
863−
864−See also: [`++date`](), [odor reference]()
865−
866− ~zod/try=> `time`-<-
867− ~2014.9.25..20.01.47..eeac
868− ~zod/try=> :: the time is always in your context at -<-
869− ~zod/try=> `time`~2014.1.1
870− ~2014.1.1
871−
872−------------------------------------------------------------------------
873−
874−### `++tree`
875−
876−Tree mold generator
877−
878−A `++tree` can be empty, or contain a node of a type and
879−left/right sub `++tree` of the same type. Pretty-printed with `{}`.
880−
881−Source
882−------
883−
884− ++ tree |* a=_,* :: binary tree
885−
886−Examples
887−--------
888−
889− ~zod/try=> `(tree ,[@ tape])`[[1 "hi"] [[2 "bye"] ~ ~] ~]
890− {[2 "bye"] [1 "hi"]}
891−
892−------------------------------------------------------------------------
893−
894−### `++nail`
895−
896−Location, remainder of parsed text
897−
898−Indicates parsing position `p`, and remaining text to be parsed `q`.
899−
900−Source
901−------
902−
903− ++ nail ,[p=hair q=tape] :: parsing input
904−
905−Examples
906−--------
907−
908− ~zod/try=> +<:;~(plug cab cab)
909− c=tub=[p=[p=0 q=0] q=""]
910− ~zod/try=> :: tub is a ++nail
911−
912−------------------------------------------------------------------------
913−
914−### `++numb`
915−
916− ++ numb ,@ :: just a number
917−
918−Used nowhere XX
919−
920−------------------------------------------------------------------------
921−
922−### `++pair`
923−
924−Mold of pair of types
925−
926−[mold]() generator. Produces a tuple of two of the types passed in.
927−
928−
929−Source
930−------
931−
932− ++ pair |*([a=$+(* *) b=$+(* *)] ,[p=a q=b]) :: just a pair
933−
934−
935−Examples
936−--------
937−
938− ~zod/try=> *(pair bean cord)
939− [p=%.y q='']
940−
941−------------------------------------------------------------------------
942−
943−### `++pass`
944−
945−Atom alias
946−
947−Used primarily in crypto.
948−
949−Source
950−------
951−
952− ++ pass ,@ :: public key
953−
954−------------------------------------------------------------------------
955−
956−### `++path`
957−
958−Filesystem path
959−
960−A `++path` is a list of [`++span`]()s aka [`@ta`](). Used in
961−`%clay` and `%eyre` extensively.
962−
963−Source
964−------
965−
966− ++ path (list span) :: filesys location
967−
968−Examples
969−--------
970−
971− ~zod/try=> `path`"abc"
972− /a/b/c
973−
974−------------------------------------------------------------------------
975−
976−### `++pint`
977−
978−Parsing range
979−
980−Mostly used for stacktraces. A `++pint` is a pair of
981−[`++hair`](), indicating from `p` to `q`.
982−
983−Source
984−------
985−
986− ++ pint ,[p=[p=@ q=@] q=[p=@ q=@]] :: line/column range
987−
988−Examples
989−--------
990−
991− ~zod/try=> !:(!!)
992− ! /~zod/try/~2014.9.20..01.22.04..52e3/:<[1 4].[1 6]>
993− ~zod/try=> :: !! always produces a crash
994− ~zod/try=> `pint`[[1 4] [1 6]]
995− [p=[p=1 q=4] q=[p=1 q=6]]
996−
997−------------------------------------------------------------------------
998−
999−### `++pole`
1000−
1001−Faceless list
1002−
1003−A [`++list`]() without the [face]()s `i` and `t`.
1004−
1005−Source
1006−------
1007−
1008− ++ pole |* a=_,* :: nameless list
1009−
1010−Examples
1011−--------
1012−
1013− ~zod/try=> `(pole char)`"asdf"
1014− [~~a [~~s [~~d [~~f ~]]]]
1015−
1016−------------------------------------------------------------------------
1017−
1018−### `++port`
1019−
1020−XX move to `++ut`
1021−
1022−Type and location of core-shaped thing? XX Compiler Internals
1023−
1024−Source
1025−------
1026−
1027− ++ port $: p=axis ::
1028− $= q ::
1029− $% [%& p=type] ::
1030− [%| p=axis q=(list ,[p=type q=foot])] ::
1031− == ::
1032− == ::
1033−
1034−Examples
1035−--------
1036−
1037− ~zod/try=> *port
1038− [p=0 q=[%.y p=%void]]
1039−
1040−------------------------------------------------------------------------
1041−
1042−### `++post`
1043−
1044−XX move to `++ut`
1045−
1046−Type and location of possibly core-shaped thing? XX Compiler Internals
1047−
1048−Source
1049−------
1050−
1051− ++ post $: p=axis ::
1052− $= q ::
1053− $% [0 p=type] ::
1054− [1 p=axis q=(list ,[p=type q=foot])] ::
1055− [2 p=twin q=type] ::
1056− == ::
1057− == ::
1058−
1059−Examples
1060−--------
1061−
1062− ~zod/try=> *post
1063− [p=0 q=[%0 p=%void]]
1064−
1065−------------------------------------------------------------------------
1066−
1067−### `++prop`
1068−
1069−XX move to `++ut`
1070−
1071−Verified core-shaped thing? XX Compiler Internals
1072−
1073− ~zod/try=> *prop
1074− [p=0 q=[p=~ q=~]]
1075−
1076−------------------------------------------------------------------------
1077−
1078−### `++qual`
1079−
1080−Mold of 4 type tuple
1081−
1082−A `++qual` is a tuple of four of the types passed in.
1083−
1084−Source
1085−------
1086−
1087− ++ qual |* [a=$+(* *) b=$+(* *) c=$+(* *) d=$+(* *)] :: just a quadruple
1088−
1089−Examples
1090−--------
1091−
1092− ~zod/try=> *(qual date time tape cord)
1093− [p=[[a=%.y y=0] m=0 t=[d=0 h=0 m=0 s=0 f=~]] q=~292277024401-.1.1 r="" s='']
1094−
1095−------------------------------------------------------------------------
1096−
1097−### `++rege`
1098−
1099−Regex caases
1100−
1101−`++rege` defines the cases of a regular expression.
1102−
1103−Source
1104−------
1105−
1106− ++ rege $| ?(%dote %ende %sart %empt %boun %bout) :: parsed regex
1107− [%brac p=@] :: p is 256 bitmask
1108− [%eith p=rege q=rege] :: either
1109− [%mant p=rege] :: greedy 0 or more
1110− [%plls p=rege] :: greedy 1 or more
1111− [%betw p=rege q=@u r=@u] :: between q and r
1112− [%bint p=rege q=@u] :: min q
1113− [%bant p=rege q=@u] :: exactly q
1114− [%manl p=rege] :: lazy 0 or more
1115− [%plll p=rege] :: lazy 1 or more
1116− [%betl p=rege q=@u r=@u] :: between q and r lazy
1117− [%binl p=rege q=@u] :: min q lazy
1118− == ::
1119−
1120−Examples
1121−--------
1122−
1123−See also: [`++rexp`](), [`++repg`](), [`++pars`]()
1124−
1125− ~zod/try=> (pars "[a-z]")
1126− [~ [%brac p=10.633.823.807.823.001.954.701.781.295.154.855.936]]
1127− ~zod/try=> (rexp "[a-z]" "abc1")
1128− [~ [~ {[p=0 q="a"]}]]
1129−
1130−------------------------------------------------------------------------
1131−
1132−### `++ring`
1133−
1134−Atom alias
1135−
1136−Used primarily in crypto.
1137−
1138−Source
1139−------
1140−
1141− ++ ring ,@ :: private key
1142−
1143−------------------------------------------------------------------------
1144−
1145−### `++rule`
1146−
1147−Parsing rule
1148−
1149−`++rule` is an empty parsing rule, but it is used to check
1150−that parsing rules match this with `_`.
1151−
1152−
1153−Source
1154−------
1155−
1156− ++ rule |=(tub=nail `edge`[p.tub ~ ~ tub]) :: parsing rule
1157−
1158−Examples
1159−--------
1160−
1161− ~zod/try=> *rule
1162− [p=[p=0 q=0] q=[~ [p=0 q=[p=[p=0 q=0] q=""]]]]
1163−
1164− ~zod/try=> ^+(rule [|=(a=nail [p.a ~])]:|6)
1165− <1.dww [tub=[p=[p=@ud q=@ud] q=""] <101.jzo 1.ypj %164>]>
1166− ~zod/try=> (^+(rule [|=(a=nail [p.a ~ u=['a' a]])]:|6) [1 1] "hi")
1167− [p=[p=1 q=1] q=[~ [p=97 q=[p=[p=1 q=1] q="hi"]]]]
1168− ~zod/try=> ([|=(a=nail [p.a ~ u=['a' a]])]:|6 [1 1] "hi")
1169− [[p=1 q=1] ~ u=['a' p=[p=1 q=1] q="hi"]]
1170−
1171−------------------------------------------------------------------------
1172−
1173−### `++span`
1174−
1175−ASCII atom
1176−
1177−A restricted text atom for canonical atom syntaxes. The prefix is `~.`.
1178−There are no escape sequences except `~~`, which means `~`, and `~-`,
1179−which means `_`. `-` and `.` encode themselves. No other characters
1180−besides numbers and lowercase letters are permitted.
1181−
1182−Source
1183−------
1184−
1185− ++ span ,@ta :: text-atom (ASCII)
1186−Examples
1187−--------
1188− ~zod/try=> *span
1189− ~.
1190−
1191− ~zod/try=> `@t`~.foo
1192− 'foo'
1193− ~zod/try=> `@t`~.foo.bar
1194− 'foo.bar'
1195− ~zod/try=> `@t`~.foo~~bar
1196− 'foo~bar'
1197− ~zod/try=> `@t`~.foo~-bar
1198− 'foo_bar'
1199− ~zod/try=> `@t`~.foo-bar
1200− 'foo-bar'
1201−
1202−------------------------------------------------------------------------
1203−
1204−### `++spot`
1205−
1206−Stack trace line
1207−
1208−A [`++spot`]() is what we print after crashing.
1209−
1210−Source
1211−------
1212−
1213− ++ spot ,[p=path q=pint] :: range in file
1214−
1215−Examples
1216−--------
1217−
1218− ~zod/try=> :into /=main=/bin/fail/hoon '!: !!'
1219− + /~zod/main/359/bin/fail/hoon
1220− ~zod/try=> :fail
1221− ! /~zod/main/~2014.9.22..18.40.56..ef04/bin/fail/:<[1 5].[1 7]>
1222− ! exit
1223−
1224−------------------------------------------------------------------------
1225−
1226−### `++tang`
1227−
1228− ++ tang (list tank) :: general error
1229−
1230−Unused XX
1231−
1232−------------------------------------------------------------------------
1233−
1234−### `++tank`
1235−
1236−Pretty-printing structure.
1237−
1238−A `++tank` is one of three cases: a `%leaf`
1239−is simply a string; a `%palm` is XX need more information; and a `%rose` is a
1240−list of `++tank` delimted by the strings in `p`.
1241−
1242−
1243−Source
1244−------
1245−
1246− ++ tank $% [%leaf p=tape] :: printing formats
1247− $: %palm :: backstep list
1248− p=[p=tape q=tape r=tape s=tape] ::
1249− q=(list tank) ::
1250− == ::
1251− $: %rose :: flat list
1252− p=[p=tape q=tape r=tape] :: mid open close
1253− q=(list tank) ::
1254− == ::
1255− ==
1256−
1257−Examples
1258−--------
1259−
1260− ~zod/try=> >(bex 20) (bex 19)<
1261− [%rose p=[p=" " q="[" r="]"] q=~[[%leaf p="1.048.576"] [%leaf p="524.288"]]]
1262− ~zod/try=> (wash [0 80] >(bex 20) (bex 19)<) :: at 80 cols
1263− <<"[1.048.576 524.288]">>
1264− ~zod/try=> (wash [0 15] >(bex 20) (bex 19)<) :: at 15 cols (two lines)
1265− <<"[ 1.048.576" " 524.288" "]">>
1266−
1267− ~zod/try=> [(bex 150) (bex 151)] :: at 80 cols
1268− [ 1.427.247.692.705.959.881.058.285.969.449.495.136.382.746.624
1269− 2.854.495.385.411.919.762.116.571.938.898.990.272.765.493.248
1270− ]
1271−
1272−------------------------------------------------------------------------
1273−
1274−### `++tape`
1275−
1276−List of chars
1277−
1278−One of Hoon's two string types, the other being [`++cord`](). A tape is a
1279−list of chars.
1280−
1281−Source
1282−------
1283−
1284− ++ tape (list char) :: like a string
1285−
1286−Examples
1287−--------
1288−
1289− ~zod/try=> `(list ,char)`"foobar"
1290− "foobar"
1291− ~zod/try=> `(list ,@)`"foobar"
1292− ~[102 111 111 98 97 114]
1293−
1294−------------------------------------------------------------------------
1295−
1296−### `++term`
1297−
1298−Hoon constants
1299−
1300−A restricted text atom for Hoon constants. The only characters permitted are
1301−lowercase ASCII, `-`, and `0-9`, the latter two of which can neither be the first or last
1302−character. The syntax for [`@tas`]() is the text itself, always preceded by `%`.
1303−This means a term is always [cubical](). The empty `@tas` has a special syntax,
1304−`$`.
1305−
1306−
1307−Source
1308−------
1309−
1310− ++ term ,@tas :: Hoon ASCII subset
1311−
1312−Examples
1313−--------
1314−
1315− ~zod/try=> *term
1316− %$
1317−
1318− ~zod/try=> %dead-fish9
1319− %dead-fish9
1320− ~zod/try=> -:!>(%dead-fish9)
1321− [%cube p=271.101.667.197.767.630.546.276 q=[%atom p=%tas]]
1322−
1323−------------------------------------------------------------------------
1324−
1325−### `++tiki`
1326−
1327−XX move to `++ut`
1328−
1329−Source
1330−------
1331−
1332− ++ tiki :: test case
1333−
1334−Examples
1335−--------
1336−
1337−A `++wing` or `++twig`.
1338−
1339− ~zod/try=> (ream '=+ a=4 ?-(a @ ~)')
1340− [ %tsls
1341− p=[%ktts p=p=%a q=[%dtzy p=%ud q=4]]
1342− q
1343− [ %wthz
1344− p=[%.y p=~ q=~[%a]]
1345− q=~[[p=[%axil p=[%atom p=~.]] q=[%bczp p=%null]]]
1346− ]
1347− ]
1348− ~zod/try=> (ream '=+ a=4 ?-(4 @ ~)')
1349− [ %tsls
1350− p=[%ktts p=p=%a q=[%dtzy p=%ud q=4]]
1351− q
1352− [ %wthz
1353− p=[%.n p=~ q=[%dtzy p=%ud q=4]]
1354− q=~[[p=[%axil p=[%atom p=~.]] q=[%bczp p=%null]]]
1355− ]
1356− ]
1357−
1358−------------------------------------------------------------------------
1359−
1360−### `++toga`
1361−
1362−Tree of faces
1363−
1364−A [face](), or tree of faces. A `++toga` is applied to anything assigned
1365−using [`^=`]().
1366−
1367−XX move to `++ut` and rune doc (for \^= examples)
1368−
1369−Source
1370−------
1371−
1372− ++ toga :: face control
1373− [2 p=toga q=toga] :: cell toga
1374− == ::
1375−
1376−Examples
1377−--------
1378−
1379− ~zod/try=> a=1
1380− a=1
1381− ~zod/try=> (ream 'a=1')
1382− [%ktts p=p=%a q=[%dtzy p=%ud q=1]]
1383− ~zod/try=> [a b]=[1 2 3]
1384− [a=1 b=[2 3]]
1385− ~zod/try=> (ream '[a b]=[1 2 3]')
1386− [ %ktts
1387− p=[%2 p=p=%a q=p=%b]
1388− q=[%cltr p=~[[%dtzy p=%ud q=1] [%dtzy p=%ud q=2] [%dtzy p=%ud q=3]]]
1389− ]
1390−
1391− ~zod/try=> [a ~]=[1 2 3]
1392− [a=1 2 3]
1393− ~zod/try=> (ream '[a ~]=[1 2 3]')
1394− [ %ktts
1395− p=[%2 p=p=%a q=[%0 ~]]
1396− q=[%cltr p=~[[%dtzy p=%ud q=1] [%dtzy p=%ud q=2] [%dtzy p=%ud q=3]]]
1397− ]
1398−
1399−------------------------------------------------------------------------
1400−
1401−### `++trap`
1402−
1403−Core with one arm `$`
1404−
1405−A trap is a core with one arm `++$`. Used when XX
1406−
1407−Source
1408−------
1409−
1410− ++ trap ,_|.(_*) :: makes perfect sense
1411−
1412−Examples
1413−--------
1414−
1415−See also: `|.`
1416−
1417− ~zod/try=> *trap
1418− <1.mws 101.jzo 1.ypj %164>
1419− ~zod/try=> (*trap)
1420− 0
1421− ~zod/try=> (|.(42))
1422− 42
1423−
1424−------------------------------------------------------------------------
1425−
1426−### `++trel`
1427−
1428−Mold of three types
1429−
1430−[`++mold`]() of the tuple of the three types passed in.
1431−
1432−Source
1433−------
1434−
1435− ++ trel |* [a=$+(* *) b=$+(* *) c=$+(* *)] :: just a triple
1436−
1437−Examples
1438−--------
1439−
1440− ~zod/try=> *(trel ,@ud ,@t ,@s)
1441− [p=0 q='' r=--0]
1442−
1443−------------------------------------------------------------------------
1444−
1445−### `++tuna`
1446−
1447−XML template tree
1448−
1449−An XML template tree.
1450−
1451−Source
1452−------
1453−
1454− ++ tuna :: tagflow
1455− [%d p=twig] :: dynamic list
1456− [%e p=twig q=(list tuna)] :: element
1457− [%f p=(list tuna)] :: subflow
1458− == ::
1459−
1460−Examples
1461−--------
1462−
1463−Leaf %a contains plain-text, %b an empty tag, %c a static list, %d a
1464−dynamic list, %e a full node element containing a twig and a list of
1465−tuna, and %f is a empty node.
1466−
1467−See also: [`++sail`]()
1468−
1469−------------------------------------------------------------------------
1470−
1471−### `++twig`
1472−
1473−Expression
1474−
1475−An expression, or AST.
1476−
1477−See Twig section of Hoon reference
1478−
1479−------------------------------------------------------------------------
1480−
1481−### `++tine`
1482−
1483−Switch statement cases
1484−
1485−In [`?-`](), for example, your list of cases is a `++tine`.
1486−
1487−Source
1488−------
1489−
1490− ++ tine (list ,[p=tile q=twig]) ::
1491−
1492−Examples
1493−--------
1494−
1495− ~zod/try=> (ream '?-(!! @ |, ^ &)')
1496− [ %wthz
1497− p=[%.n p=~ q=[%zpzp ~]]
1498− q
1499− ~[
1500− [p=[%axil p=[%atom p=~.]] q=[%dtzy p=%f q=1]]
1501− [p=[%axil p=%cell] q=[%dtzy p=%f q=0]]
1502− ]
1503− ]
1504− ~zod/try=> (tine |2:(ream '?-(!! @ |, ^ &)'))
1505− ~[
1506− [p=[%axil p=[%atom p=~.]] q=[%dtzy p=%f q=1]]
1507− [p=[%axil p=%cell] q=[%dtzy p=%f q=0]]
1508− ]
1509−
1510−------------------------------------------------------------------------
1511−
1512−### `++tusk`
1513−
1514−List of expressions
1515−
1516−List of [`++twig`]()s. In [`:*`](), for example, your contents is
1517−a `++tusk`.
1518−
1519−Source
1520−------
1521−
1522− ++ tusk (list twig) ::
1523−
1524−Examples
1525−--------
1526−
1527− ~zod/try=> (ream '[1 2 3]')
1528− [%cltr p=~[[%dtzy p=%ud q=1] [%dtzy p=%ud q=2] [%dtzy p=%ud q=3]]]
1529− ~zod/try=> (tusk +:(ream '[1 2 3]'))
1530− ~[[%dtzy p=%ud q=1] [%dtzy p=%ud q=2] [%dtzy p=%ud q=3]]
1531−
1532−------------------------------------------------------------------------
1533−
1534−### `++tyre`
1535−
1536−List, term to twig
1537−
1538−Associative list of [++term]() [`++twig`](), used in [jet]() hint processing.
1539−
1540−Source
1541−------
1542−
1543− ++ tyre (list ,[p=term q=twig]) ::
1544−
1545−------------------------------------------------------------------------
1546−
1547−### `++tyke`
1548−
1549−List of 'maybe' twigs
1550−
1551−List of [`++unit`]() [`++twig`](), or gaps left to be inferred, in [`++path`]()
1552−parsing. When you use a path such as `/=main=/pub/src/doc` the path is in fact
1553−a `++tyke`, where the `=` are inferred from your current path.
1554−
1555−
1556−Source
1557−------
1558−
1559− ++ tyke (list (unit twig)) ::
1560−
1561−Examples
1562−--------
1563−
1564− ~zod/try=> (scan "/==as=" porc:vast)
1565− [0 ~[~ ~ [~ [%dtzy p=%tas q=29.537]] ~]]
1566− ~zod/try=> `tyke`+:(scan "/==as=" porc:vast)
1567− ~[~ ~ [~ [%dtzy p=%tas q=29.537]] ~]
1568−
1569−------------------------------------------------------------------------
1570−
1571−### `++tram`
1572−
1573−List of changes
1574−
1575−List of changes by location in context. When using [`%=`](), for example,
1576−the list of changes is a `++tram`.
1577−
1578−Source
1579−------
1580−
1581− ++ tram (list ,[p=wing q=twig]) ::
1582−
1583−Examples
1584−--------
1585−
1586− ~zod/try=> (ream '$(a 1, b 2)')
1587− [ %cnts
1588− p=~[%$]
1589− q=~[[p=~[%a] q=[%dtzy p=%ud q=1]] [p=~[%b] q=[%dtzy p=%ud q=2]]]
1590− ]
1591− ~zod/try=> (tram +:(ream '$(a 1, b 2)'))
1592− ~[[p=~ q=[% p=0]] [p=~[%a] q=[%dtzy p=%ud q=1]] [p=~[%b] q=[%dtzy p=%ud q=2]]]
1593−
1594−------------------------------------------------------------------------
1595−
1596−### `++nock`
1597−
1598−Virtual machine. See [Nock doc]().
1599−
1600−
1601−Source
1602−------
1603−
1604− ++ nock $& [p=nock q=nock] :: autocons
1605− [%3 p=nock] :: cell test
1606− [%4 p=nock] :: increment
1607− [%5 p=nock q=nock] :: equality test
1608− [%6 p=nock q=nock r=nock] :: if, then, else
1609− [%7 p=nock q=nock] :: serial compose
1610− [%8 p=nock q=nock] :: push onto subject
1611− [%9 p=@ q=nock] :: select arm and fire
1612− [%10 p=?(@ [p=@ q=nock]) q=nock] :: hint
1613− [%11 p=nock] :: grab data from sky
1614− == ::
1615−
1616−Examples
1617−--------
1618−
1619− ~zod/try=> !=([+(.) 20 -<])
1620− [[4 0 1] [1 20] 0 4]
1621− ~zod/try=> (nock !=([+(.) 20]))
1622− [p=[%4 p=[%0 p=1]] q=[%1 p=20]]
1623−
1624−------------------------------------------------------------------------
1625−
1626−### `++tone`
1627−
1628−Intermediate Nock computation result
1629−
1630−Similar to [`++toon`](), but stack trace is not yet rendered.
1631−
1632−Source
1633−------
1634−
1635− ++ tone $% [%0 p=*] :: success
1636−
1637−Examples
1638−--------
1639−
1640− ~zod/try=> (mink [[20 21] 0 3] ,~)
1641− [%0 p=21]
1642−
1643− ~zod/try=> (mink [[0] !=(.^(cy//=main/1))] ,~)
1644− [%1 p=~[[31.075 1.685.027.454 1.852.399.981 49 0]]]
1645− ~zod/try=> (path [31.075 1.685.027.454 1.852.399.981 49 0])
1646− /cy/~zod/main/1
1647−
1648− ~zod/try=> (mink [[1 2] !=(~|(%hi +(.)))] ,~)
1649− [%2 p=~[[~.yelp 26.984]]]
1650− ~zod/try=> (mink [[1 2] !=(!:(+(.)))] ,~)
1651− [ %2
1652− p
1653− ~[
1654− [ ~.spot
1655− [ [ 1.685.027.454
1656− 7.959.156
1657− \/159.445.990.350.374.058.574.398.238.344.143.957.205.628.479.572.65\/
1658− 8.112.403.878.526
1659− \/ \/
1660− 0
1661− ]
1662− [1 20]
1663− 1
1664− 24
1665− ]
1666− ]
1667− ]
1668− ]
1669−
1670−------------------------------------------------------------------------
1671−
1672−### `++toon`
1673−
1674−Nock computation result
1675−
1676−Either success (`%0`), a block with list of requests blocked on (`%1`), or
1677−failure with stack trace (`%2`).
1678−
1679−Source
1680−------
1681−
1682− ++ toon $% [%0 p=*] :: success
1683−
1684−Examples
1685−--------
1686− ~zod/try=> (mock [[20 21] 0 3] ,~)
1687− [%0 p=21]
1688−
1689− ~zod/try=> (mock [[0] !=(.^(cy//=main/1))] ,~)
1690− [%1 p=~[[31.075 1.685.027.454 1.852.399.981 49 0]]]
1691− ~zod/try=> (path [31.075 1.685.027.454 1.852.399.981 49 0])
1692− /cy/~zod/main/1
1693−
1694− ~zod/try=> (mock [[1 2] !=(!:(+(.)))] ,~)
1695− [%2 p=~[[%leaf p="/~zod/try/~2014.9.23..18.34.32..d3c5/:<[1 20].[1 24]>"]]]
1696−
1697−------------------------------------------------------------------------
1698−
1699−### `++tune`
1700−
1701−
1702−Source
1703−------
1704−
1705− ++ tune $% [%0 p=vase] ::
1706−
1707−Examples
1708−--------
1709−Probably typed `tone`?
1710−
1711−------------------------------------------------------------------------
1712−
1713−### `++twin`
1714−
1715−Aliasing
1716−
1717−Used in `%bull` within [`++type`]() to typecheck aliased faces.
1718−
1719−Source
1720−------
1721−
1722− ++ twin ,[p=term q=wing r=axis s=type] :: alias info
1723−
1724−Examples
1725−--------
1726−
1727− ~zod/try=> (~(busk ut %cell %noun [%atom %ud]) %fal [%& 3]~)
1728− [ %bull
1729− p=[p=%fal q=~[[%.y p=3]] r=3 s=[%atom p=%ud]]
1730− q=[%cell p=%noun q=[%atom p=%ud]]
1731− ]
1732− ~zod/try=> &2:(~(busk ut %cell %noun [%atom %ud]) %fal [%& 3]~)
1733− p=[p=%fal q=~[[%.y p=3]] r=3 s=[%atom p=%ud]]
1734− ~zod/try=> (twin &2:(~(busk ut %cell %noun [%atom %ud]) %fal [%& 3]~))
1735− [p=%fal q=~[[%.y p=3]] r=3 s=[%atom p=%ud]]
1736−
1737−------------------------------------------------------------------------
1738−
1739−### `++type`
1740−
1741−See Type section of Hoon reference
1742−
1743−------------------------------------------------------------------------
1744−
1745−### `++typo`
1746−
1747−Pointer for `++type`
1748−
1749−Pointer for [`++type`](). `++typo` preserves the previous `++type` in your
1750−context when upating.
1751−
1752−Source
1753−------
1754−
1755− ++ typo type :: old type
1756−
1757−Examples
1758−--------
1759−
1760−See also: `++seem`, `++vise`, `++type`
1761−
1762−------------------------------------------------------------------------
1763−
1764−### `++udal`
1765−
1766−Source
1767−------
1768−
1769− ++ udal :: atomic change (%b)
1770−
1771−Examples
1772−--------
1773−------------------------------------------------------------------------
1774−
1775−### `++udon`
1776−
1777− ++ udon :: abstract delta
1778− $: p=umph :: preprocessor
1779− $= q :: patch
1780− $% [%a p=* q=*] :: trivial replace
1781− [%b p=udal] :: atomic indel
1782− [%c p=(urge)] :: list indel
1783− [%d p=upas q=upas] :: tree edit
1784− == ::
1785− == ::
1786−
1787−See `%clay` doc
1788−
1789−------------------------------------------------------------------------
1790−
1791−### `++umph`
1792−
1793− ++ umph :: change filter
1794− $| $? %a :: no filter
1795− %b :: jamfile
1796− %c :: LF text
1797− == ::
1798− $% [%d p=@ud] :: blocklist
1799− == ::
1800−
1801−See `%clay` doc
1802−
1803−------------------------------------------------------------------------
1804−
1805−### `++unce`
1806−
1807− ++ unce |* a=_,* :: change part
1808− $% [%& p=@ud] :: skip[copy]
1809− [%| p=(list a) q=(list a)] :: p -> q[chunk]
1810− == ::
1811−
1812−See `%clay` doc
1813−
1814−------------------------------------------------------------------------
1815−
1816−### `++unit`
1817−
1818−Maybe
1819−
1820−[mold]() generator. A `++unit` is either `~` or `[~ u=a]` where `a` is the
1821−type that was passed in.
1822−
1823−
1824−Source
1825−------
1826−
1827− ++ unit |* a=_,* :: maybe
1828−
1829−Examples
1830−--------
1831−
1832−See also: [`++bind`]()
1833−
1834− ~zod/try=> :type; *(unit time)
1835− ~
1836− u(@da)
1837− ~zod/try=> `(unit time)`[~ -<-]
1838− [~ ~2014.9.24..19.25.10..7dd5]
1839−
1840−------------------------------------------------------------------------
1841−
1842−### `++upas`
1843−
1844− ++ upas :: tree change (%d)
1845− $& [p=upas q=upas] :: cell
1846− $% [%0 p=axis] :: copy old
1847− [%1 p=*] :: insert new
1848− [%2 p=axis q=udon] :: mutate!
1849− == ::
1850−
1851−See `%clay` doc
1852−
1853−------------------------------------------------------------------------
1854−
1855−### `++urge`
1856−
1857− ++ urge |*(a=_,* (list (unce a))) :: list change
1858−
1859−See `%clay` doc
1860−
1861−------------------------------------------------------------------------
1862−
1863−### `++vase`
1864−
1865−Typed data. A `++vase` is used wherever typed data is explicitly worked
1866−with.
1867−
1868−
1869−Source
1870−------
1871−
1872− ++ vase ,[p=type q=*] :: type-value pair
1873−
1874−Examples
1875−--------
1876−See `%arvo` doc
1877−
1878− ~zod/try=> `vase`!>(~)
1879− [p=[%cube p=0 q=[%atom p=%n]] q=0]
1880−
1881−------------------------------------------------------------------------
1882−
1883−### `++vise`
1884−
1885−Convert during reboot
1886−
1887−Used to convert from previously-typed data during reboot.
1888−
1889−Source
1890−------
1891−
1892− ++ vise ,[p=typo q=*] :: old vase
1893−
1894−Examples
1895−--------
1896−
1897−See also: [`++typo`](), [`++seer`]()
1898−
1899−------------------------------------------------------------------------
1900−
1901−### `++wall`
1902−
1903−List of lines
1904−
1905−
1906−A `++wall` is used instead of a single [`++tape`]() with
1907−`\n`.
1908−
1909−Source
1910−------
1911−
1912− ++ wall (list tape) :: text lines (no \n)
1913−
1914−Examples
1915−--------
1916−
1917−See also: [`++wash`]()
1918−
1919− ~zod/try=> `wall`(wash [0 20] leaf/<(bex 256)>)
1920− <<
1921− "\/115.792.089.237.\/"
1922− " 316.195.423.570."
1923− " 985.008.687.907."
1924− " 853.269.984.665."
1925− " 640.564.039.457."
1926− " 584.007.913.129."
1927− " 639.936"
1928− "\/ \/"
1929− >>
1930−
1931−------------------------------------------------------------------------
1932−
1933−### `++wain`
1934−
1935− ++ wain (list cord) :: text lines (no \n)
1936−
1937−A list of lines. A `++wain` is used instead of a single [`++cord`]() with
1938−`\n`.
1939−
1940−See also: [`++lore`](), [`++role`]()
1941−
1942− ~zod/try=> `wain`/som/del/rok
1943− <|som del rok|>
1944− ~zod/try=> `wain`(lore ^:@t/=main=/bin/tree/hoon)
1945− <|
1946− !:
1947− :: /===/bin/tree/hoon
1948− |= ^
1949− |= [pax=path fla=$|(~ [%full ~])]
1950− =- ~[te/-]~
1951− =+ len=(lent pax)
1952− =+ rend=?~(fla |=(a=path +:(spud (slag len a))) spud)
1953− |- ^- wain
1954− =+ ark=;;(arch .^(cy/pax))
1955− =- ?~ q.ark -
1956− [(crip (rend pax)) -]
1957− %- zing
1958− %- turn :_ |=(a=@t ^$(pax (weld pax `path`/[a])))
1959− %- sort :_ aor
1960− %- turn :_ |=([a=@t ~] a)
1961− (~(tap by r.ark))
1962− |>
1963−
1964−------------------------------------------------------------------------
1965−
1966−### `++wing`
1967−
1968− ++ wing (list limb) ::
1969−
1970−Address in subject. A `++wing` is a path to a value in the subject. A
1971−term alone is the trivial case of a `++wing`.
1972−
1973−See also: `++twig`
1974−
1975− ~zod/try=> (ream 'a.+.c')
1976− [%cnzz p=~[%a [%.y p=3] %c]]
1977− ~zod/try=> (wing +:(ream 'a.+.c'))
1978− ~[%a [%.y p=3] %c]
1979−
1980−------------------------------------------------------------------------
1981−
1982−### `++wine`
1983−
1984−Printable type
1985−
1986−Used for pretty printing.
1987−
1988−Source
1989−------
1990−
1991− ++ wine $| ?(%noun %path %tank %void %wall %wool %yarn)
1992− [%list p=term q=wine] ::
1993− [%pear p=term q=@] ::
1994− [%pick p=(list wine)] ::
1995− [%plot p=(list wine)] ::
1996− [%stop p=@ud] ::
1997− [%tree p=term q=wine] ::
1998− [%unit p=term q=wine] ::
1999− == ::
2000−
2001−Examples
2002−--------
2003−
2004−See also: [`++calf`]()
2005−
2006− ~zod/try=> ~(dole ut p:!>(*@tas))
2007− [p={} q=[%atom p=%tas]]
2008− ~zod/try=> `wine`q:~(dole ut p:!>(*@tas))
2009− [%atom p=%tas]
2010−
2011− ~zod/try=> ~(dole ut p:!>(*path))
2012− [ p
2013− { [ p=1
2014− q
2015− [ %pick
2016− p
2017− ~[
2018− [%pear p=%n q=0]
2019− [%plot p=~[[%face p=%i q=[%atom p=%ta]] [%face p=%t q=[%stop p=1]]]]
2020− ]
2021− ]
2022− ]
2023− }
2024− q=%path
2025− ]
2026− ~zod/try=> `wine`q:~(dole ut p:!>(*path))
2027− %path
2028−
2029− ~zod/try=> ~(dole ut p:!>(*(map time cord)))
2030− [ p
2031− { [ p=1
2032− q
2033− [ %pick
2034− p
2035− ~[
2036− [%pear p=%n q=0]
2037− [ %plot
2038− p
2039− ~[
2040− [ %face
2041− p=%n
2042− q
2043− [ %plot
2044− p=~[[%face p=%p q=[%atom p=%da]] [%face p=%q q=[%atom p=%t]]]
2045− ]
2046− ]
2047− [%face p=%l q=[%stop p=1]]
2048− [%face p=%r q=[%stop p=1]]
2049− ]
2050− ]
2051− ]
2052− ]
2053− ]
2054− }
2055− q
2056− [ %tree
2057− p=%nlr
2058− q=[%plot p=~[[%face p=%p q=[%atom p=%da]] [%face p=%q q=[%atom p=%t]]]]
2059− ]
2060− ]
2061− ~zod/try=> `wine`q:~(dole ut p:!>(*(map time cord)))
2062− [ %tree
2063− p=%nlr
2064− q=[%plot p=~[[%face p=%p q=[%atom p=%da]] [%face p=%q q=[%atom p=%t]]]]
2065− ]
2066−
2067−------------------------------------------------------------------------
2068−
2069−### `++wonk`
2070−
2071−XX Not a model?
2072−
2073−Pull result out of a `++edge`, or crash if there's no result.
2074−
2075−Source
2076−------
2077−
2078− ++ wonk |*(veq=edge ?~(q.veq !! p.u.q.veq)) ::
2079−
2080−Examples
2081−--------
2082−
2083−See also: [`++edge`]()
2084−
2085− ~zod/try=> (wide:vast [1 1] "(add 2 2)")
2086− [ p=[p=1 q=10]
2087− q
2088− [ ~
2089− [ p=[%cnhp p=[%cnzz p=~[%add]] q=~[[%dtzy p=%ud q=2] [%dtzy p=%ud q=2]]]
2090− q=[p=[p=1 q=10] q=""]
2091− ]
2092− ]
2093− ]
2094− ~zod/try=> (wonk (wide:vast [1 1] "(add 2 2)"))
2095− [%cnhp p=[%cnzz p=~[%add]] q=~[[%dtzy p=%ud q=2] [%dtzy p=%ud q=2]]]
2096−
2097−------------------------------------------------------------------------
2098−
2099−### `++map`
2100−
2101−Map
2102−
2103−[mold]() generator. A `++map` is a [treap](http://en.wikipedia.org/wiki/Treap) of
2104−key, value pairs.
2105−
2106−
2107−Source
2108−------
2109−
2110− ++ map |* [a=_,* b=_,*] :: associative tree
2111−
2112−Examples
2113−--------
2114−
2115−See also: [`++by`]()
2116−
2117− ~zod/try=> :type; *(map ,@t ,@u)
2118− {}
2119− nlr([p=@t q=@u])
2120− ~zod/try=> `(map ,@ta ,@ud)`(mo (limo a/1 b/2 ~))
2121− {[p=~.a q=1] [p=~.b q=2]}
2122−
2123−------------------------------------------------------------------------
2124−
2125−### `++qeu`
2126−
2127−Queue
2128−
2129−[mold]() generator. An ordered [treap](http://en.wikipedia.org/wiki/Treap) of
2130−items.
2131−
2132−Source
2133−------
2134−
2135− ++ qeu |* a=_,* :: queue
2136− $|(~ [n=a l=(qeu a) r=(qeu a)]) ::
2137−
2138−See also: [`++to`]()
2139−
2140−Examples
2141−--------
2142−
2143− ~zod/try=> (qeu time)
2144− <1.qyo [* <1.sxx [a=<1.ebd [* <101.jzo 1.ypj %164>]> <101.jzo 1.ypj %164>]>]>
2145− ~zod/try=> (~(gas to *(qeu time)) [~2014.1.1 ~2014.1.2 ~])
2146− {~2014.1.2 ~2014.1.1}
2147−
2148−------------------------------------------------------------------------
2149−
2150−### `++set`
2151−
2152−Set
2153−
2154−[mold]() generator. A `++set` is a
2155−[treap](http://en.wikipedia.org/wiki/Treap) with unique values.
2156−
2157−Source
2158−------
2159−
2160− ++ set |* a=_,* :: set
2161− $|(~ [n=a l=(set a) r=(set a)]) ::
2162−
2163−Examples
2164−--------
2165−
2166−See also: [`++in`]()
2167−
2168− ~zod/try=> (sa "abc")
2169− {~~a ~~c ~~b}
2170− ~zod/try=> (~(put in (sa "abc")) %d)
2171− {~~d ~~a ~~c ~~b}
2172− ~zod/try=> (~(put in (sa "abc")) %a)
2173− {~~a ~~c ~~b}
2174−
2175−------------------------------------------------------------------------
2176−
2177−### `++jar`
2178−
2179−
2180−Tile generator. A [`++jar`]() is a [`++map`]() of [`++list`]().
2181−
2182−Source
2183−------
2184−
2185− ++ jar |*([a=_,* b=_,*] (map a (list b))) :: map of lists
2186−
2187−Examples
2188−--------
2189−
2190−See also: [`++ja`](), [`++by`](), [`++map`](), [`++list`]()
2191−
2192− ~zod/try=> =a (limo [1 2 ~])
2193− ~zod/try=> a
2194− [i=1 t=[i=2 t=~]]
2195− ~zod/try=> =b (limo [3 4 ~])
2196− ~zod/try=> b
2197− [i=3 t=[i=4 t=~]]
2198− ~zod/try=> =c (mo (limo [[%a a] [%b b] ~]))
2199− ~zod/try=> c
2200− {[p=%a q=[i=1 t=[i=2 t=~]]] [p=%b q=[i=3 t=[i=4 t=~]]]}
2201− ~zod/try=> (~(get ja c) %a)
2202− [i=1 t=[i=2 t=~]]
2203− ~zod/try=> (~(get ja c) %c)
2204− ~
2205−
2206−------------------------------------------------------------------------
2207−
2208−### `++jug`
2209−
2210−
2211−[mold]() generator. A `++jug` is a [`++map`]() of [`++set`]()s.
2212−
2213−Source
2214−------
2215−
2216− ++ jug |*([a=_,* b=_,*] (map a (set b))) :: map of sets
2217−
2218−Examples
2219−--------
2220−
2221−See also: `++ju`, `++by`, `++map`, `++set`
2222−
2223− ~zod/try=> =a (sa (limo [1 2 ~]))
2224− ~zod/try=> a
2225− {1 2}
2226− ~zod/try=> =b (sa (limo [3 4 ~]))
2227− ~zod/try=> b
2228− {4 3}
2229− ~zod/try=> =c (mo (limo [[%a a] [%b b] ~]))
2230− ~zod/try=> c
2231− {[p=%a q={1 2}] [p=%b q={4 3}]}
2232− ~zod/try=> (~(get ju c) %b)
2233− {4 3}
2234− ~zod/try=> (~(put ju c) [%b 5])
2235− {[p=%a q={1 2}] [p=%b q={5 4 3}]}
2236−
2237−------------------------------------------------------------------------
docs/dev/hoon/library/2a.mddeleted−678
@@ -1,678 +0,0 @@
1−2a - basic unsigned math
2−========================
3−
4−### `++add`
5−
6−Add
7−
8−Produces the sum of `a` and `b`.
9−
10−Accepts
11−-------
12−
13−`a` is an [atom]().
14−
15−`b` is an atom.
16−
17−Produces
18−--------
19−
20−An atom.
21−
22−Source
23−------
24−
25− ++ add :: add
26− ~/ %add
27− |= [a=@ b=@]
28− ^- @
29− ?: =(0 a) b
30− $(a (dec a), b +(b))
31−
32−Examples
33−--------
34−
35− ~zod/try=> (add 2 2)
36− 4
37− ~zod/try=> (add 1 1.000.000)
38− 1.000.001
39− ~zod/try=> (add 1.333 (mul 2 2))
40− 1.337
41−
42−------------------------------------------------------------------------
43−
44−### `++cap`
45−
46−Tree head
47−
48−Tests whether an `a` is in the head or tail of a [noun](). Produces the
49−[cube]() `%2` if it is within the head, or the cube `%3` if it is
50−within the tail.
51−
52−Accepts
53−-------
54−
55−`a` is an atom.
56−
57−Produces
58−--------
59−
60−A [cube]().
61−
62−Source
63−------
64−
65− ++ cap :: tree head
66− ~/ %cap
67− |= a=@
68− ^- ?(%2 %3)
69− ?- a
70− %2 %2
71− %3 %3
72− ?(%0 %1) !!
73− * $(a (div a 2))
74− ==
75− ::
76−
77−Examples
78−--------
79−
80− ~zod/try=> (cap 4)
81− %2
82− ~zod/try=> (cap 6)
83− %3
84− ~zod/try=> (cap (add 10 9))
85− %2
86−
87−------------------------------------------------------------------------
88−
89−### `++dec`
90−
91−Decrement
92−
93−Decrements `a` by `1`.
94−
95−Accepts
96−-------
97−
98−`a` is an [atom]().
99−
100−Produces
101−--------
102−
103−An atom.
104−
105−Source
106−------
107−
108− ++ dec :: decrement
109− ~/ %dec
110− |= a=@
111− ~| %decrement-underflow
112− ?< =(0 a)
113− =+ b=0
114− |- ^- @
115− ?: =(a +(b)) b
116− $(b +(b))
117− ::
118−
119−Examples
120−--------
121−
122− ~zod/try=> (dec 7)
123− 6
124− ~zod/try=> (dec 0)
125− ! decrement-underflow
126− ! exit
127−
128−------------------------------------------------------------------------
129−
130−### `++div`
131−
132−Divide
133−
134−Computes `a` divided by `b`.
135−
136−Accepts
137−-------
138−
139−`a` is an [atom]().
140−
141−`b` is an [atom]().
142−
143−Produces
144−--------
145−
146−An atom.
147−
148−Source
149−------
150−
151− ++ div :: divide
152− ~/ %div
153− |= [a=@ b=@]
154− ^- @
155− ~| 'div'
156− ?< =(0 b)
157− =+ c=0
158− |-
159− ?: (lth a b) c
160− $(a (sub a b), c +(c))
161− ::
162−
163−Examples
164−--------
165−
166− ~zod/try=> (div 4 2)
167− 2
168− ~zod/try=> (div 17 8)
169− 2
170− ~zod/try=> (div 20 30)
171− 0
172−
173−------------------------------------------------------------------------
174−
175−### `++fac`
176−
177−Factorial
178−
179−Computes the factorial of `a`.
180−
181−Accepts
182−-------
183−
184−`a` is an [atom]().
185−
186−Produces
187−--------
188−
189−An atom.
190−
191−Source
192−------
193−
194− ++ fac :: factorial
195− ~/ %fac
196− |= a=@
197− ^- @
198− ?: =(0 a) 1
199− (mul a $(a (dec a)))
200− ::
201−
202−Examples
203−--------
204−
205− ~zod/try=> (fac 3)
206− 6
207− ~zod/try=> (fac 0)
208− 1
209− ~zod/try=> (fac 11)
210− 39.916.800
211−
212−------------------------------------------------------------------------
213−
214−### `++gte`
215−
216−Greater-than/equal
217−
218−Tests whether `a` is greater than a number `b`.
219−
220−Accepts
221−-------
222−
223−`a` is an [atom]().
224−
225−`b` is an atom.
226−
227−Produces
228−--------
229−
230−A boolean.
231−
232−Source
233−------
234−
235− ++ gte :: greater-equal
236− ~/ %gte
237− |= [a=@ b=@]
238− ^- ?
239− !(lth a b)
240− ::
241−
242−Examples
243−--------
244−
245− ~zod/try=> (gte 100 10)
246− %.y
247− ~zod/try=> (gte 4 4)
248− %.y
249− ~zod/try=> (gte 3 4)
250− %.n
251−
252−------------------------------------------------------------------------
253−
254−### `++gth`
255−
256−Greater-than
257−
258−Tests whether `a` is greater than `b`.
259−
260−Accepts
261−-------
262−
263−`a` is an [atom]().
264−
265−`b` is an atom.
266−
267−Produces
268−--------
269−
270−A boolean.
271−
272−Source
273−------
274−
275− ++ gth :: greater-than
276− ~/ %gth
277− |= [a=@ b=@]
278− ^- ?
279− !(lte a b)
280− ::
281−
282−Examples
283−--------
284−
285− ~zod/try=> (gth 'd' 'c')
286− %.y
287− ~zod/try=> (gth ~h1 ~m61)
288− %.n
289−
290−------------------------------------------------------------------------
291−
292−### `++lte`
293−
294−Less-than/equal
295−
296−Tests whether `a` is less than or equal to `b`.
297−
298−Accepts
299−-------
300−
301−`a` is an [atom]().
302−
303−`b` is an atom.
304−
305−Produces
306−--------
307−
308−A boolean.
309−
310−Source
311−------
312−
313− ++ lte :: less-equal
314− ~/ %lte
315− |= [a=@ b=@]
316− |(=(a b) (lth a b))
317− ::
318−
319−Examples
320−--------
321−
322− ~zod/try=> (lte 4 5)
323− %.y
324− ~zod/try=> (lte 5 4)
325− %.n
326− ~zod/try=> (lte 5 5)
327− %.y
328− ~zod/try=> (lte 0 0)
329− %.y
330−
331−------------------------------------------------------------------------
332−
333−### `++lth`
334−
335−Less-than
336−
337−Tests whether `a` is less than `b`.
338−
339−Accepts
340−-------
341−
342−`a` is an [atom]().
343−
344−`b` is an atom.
345−
346−Produces
347−--------
348−
349−A boolean.
350−
351−Source
352−------
353−
354− ++ lth :: less-than
355− ~/ %lth
356− |= [a=@ b=@]
357− ^- ?
358− ?& !=(a b)
359− |-
360− ?| =(0 a)
361− ?& !=(0 b)
362− $(a (dec a), b (dec b))
363− == == ==
364− ::
365−
366−Examples
367−--------
368−
369− ~zod/try=> (lth 4 5)
370− %.y
371− ~zod/try=> (lth 5 4)
372− %.n
373− ~zod/try=> (lth 5 5)
374− %.n
375− ~zod/try=> (lth 5 0)
376− %.n
377−
378−------------------------------------------------------------------------
379−
380−### `++mas`
381−
382−Axis within head/tail?
383−
384−Computes the axis of `a` within either the head or tail of a noun (depends whether `a` lies within the the head or tail).
385−
386−Accepts
387−-------
388−
389−`a` is an [atom]().
390−
391−Produces
392−--------
393−
394−An atom.
395−
396−Source
397−------
398−
399− ++ mas :: tree body
400− ~/ %mas
401− |= a=@
402− ^- @
403− ?- a
404− 1 !!
405− 2 1
406− 3 1
407− * (add (mod a 2) (mul $(a (div a 2)) 2))
408− ==
409− ::
410−
411−Examples
412−--------
413−
414− ~zod/try=> (mas 3)
415− 1
416− ~zod/try=> (mas 4)
417− 2
418− ~zod/try=> (mas 5)
419− 3
420− ~zod/try=> (mas 6)
421− 2
422− ~zod/try=> (mas 0)
423− ! exit
424− ~zod/try=> (mas 1)
425− ! exit
426−
427−-----------------------------------------------------------------------
428−
429−### `++max`
430−
431−Maximum
432−
433−Computes the greater of `a` and `b`.
434−
435−Accepts
436−-------
437−
438−`a` is an [atom]().
439−
440−`b` is an atom.
441−
442−Produces
443−--------
444−
445−An atom.
446−
447−Source
448−------
449−
450− ++ max :: maximum
451− ~/ %max
452− |= [a=@ b=@]
453− ^- @
454− ?: (gth a b) a
455− b
456− ::
457−
458−Examples
459−--------
460−
461− ~zod/try=> (max 10 100)
462− 100
463− ~zod/try=> (max 10.443 9)
464− 10.443
465− ~zod/try=> (max 0 1)
466− 1
467−
468−------------------------------------------------------------------------
469−
470−### `++min`
471−
472−Minimum
473−
474−Computes the lesser of `a` and `b`.
475−
476−Accepts
477−-------
478−
479−`a` is an [atom]().
480−
481−`b` is an atom.
482−
483−Produces
484−--------
485−
486−An atom.
487−
488−Source
489−------
490−
491− ++ min :: minimum
492− ~/ %min
493− |= [a=@ b=@]
494− ^- @
495− ?: (lth a b) a
496− b
497− ::
498−
499−Examples
500−--------
501−
502− ~zod/try=> (min 10 100)
503− 10
504− ~zod/try=> (min 10.443 9)
505− 9
506− ~zod/try=> (min 0 1)
507− 0
508−
509−------------------------------------------------------------------------
510−
511−### `++mod`
512−
513−Modulus
514−
515−Computes the remainder of dividing `a` by `b`.
516−
517−Accepts
518−-------
519−
520−`a` is an [atom]().
521−
522−`b` is an atom.
523−
524−Produces
525−--------
526−
527−An atom.
528−
529−Source
530−------
531−
532− ++ mod :: remainder
533− ~/ %mod
534− |= [a=@ b=@]
535− ^- @
536− ?< =(0 b)
537− (sub a (mul b (div a b)))
538− ::
539−
540−Examples
541−--------
542−
543− ~zod/try=> (mod 5 2)
544− 1
545− ~zod/try=> (mod 5 5)
546− 0
547−
548−------------------------------------------------------------------------
549−
550−### `++mul`
551−
552−Multiply
553−
554−Multiplies `a` by `b`.
555−
556−Accepts
557−-------
558−
559−`a` is an [atom]().
560−
561−`b` is an atom.
562−
563−Produces
564−--------
565−
566−An atom.
567−
568−Source
569−------
570−
571− ++ mul :: multiply
572− ~/ %mul
573− |= [a=@ b=@]
574− ^- @
575− =+ c=0
576− |-
577− ?: =(0 a) c
578− $(a (dec a), c (add b c))
579− ::
580−
581−Examples
582−--------
583−
584− ~zod/try=> (mul 3 4)
585− 12
586− ~zod/try=> (mul 0 1)
587− 0
588−
589−------------------------------------------------------------------------
590−
591−### `++peg`
592−
593−Axis within axis
594−
595−Computes the axis of `b` within axis `a`.
596−
597−Accepts
598−-------
599−
600−`a` is an [atom]().
601−
602−`b` is an atom.
603−
604−Produces
605−--------
606−
607−An atom.
608−
609−Source
610−------
611−
612− ++ peg :: tree connect
613− ~/ %peg
614− |= [a=@ b=@]
615− ^- @
616− ?- b
617− 1 a
618− 2 (mul a 2)
619− 3 +((mul a 2))
620− * (add (mod b 2) (mul $(b (div b 2)) 2))
621− ==
622− ::
623−
624−Examples
625−--------
626−
627− ~zod/try=> (peg 4 1)
628− 4
629− ~zod/try=> (peg 4 2)
630− 8
631− ~zod/try=> (peg 8 45)
632− 269
633−
634−------------------------------------------------------------------------
635−
636−### `++sub`
637−
638−Subtract
639−
640−Subtracts `b` from `a`.
641−
642−Accepts
643−-------
644−
645−`a` is an [atom]().
646−
647−`b` is an [atom]().
648−
649−Produces
650−--------
651−
652−An atom.
653−
654−Source
655−------
656−
657− ++ sub :: subtract
658− ~/ %sub
659− |= [a=@ b=@]
660− ~| %subtract-underflow
661− ^- @
662− ?: =(0 b) a
663− $(a (dec a), b (dec b))
664−
665−Examples
666−--------
667−
668− ~zod/try=> (sub 10 5)
669− 5
670− ~zod/try=> (sub 243 44)
671− 199
672− ~zod/try=> (sub 5 0)
673− 5
674− ~zod/try=> (sub 0 5)
675− ! subtract-underflow
676− ! exit
677−
678−------------------------------------------------------------------------
docs/dev/hoon/library/2b.mddeleted−1320
@@ -1,1320 +0,0 @@
1−chapter 2b, basic containers
2−============================
3−
4−Section 2bA, units
5−------------------
6−
7−### `++biff`
8−
9−Unit as argument
10−
11−Applies a function `b` that produces a unit to the unwrapped value of [++unit]()
12−`a` (`u.a`). If `a` is empty, `~` is produced.
13−
14−Accepts
15−-------
16−
17−`a` is a unit.
18−
19−`b` is a function that accepts a noun and produces a unit.
20−
21−Produces
22−--------
23−
24−A unit.
25−
26−Source
27−------
28−
29− ++ biff :: apply
30− |* [a=(unit) b=$+(* (unit))]
31− ?~ a ~
32− (b u.a)
33−
34−Examples
35−--------
36−
37− ~zod/try=> (biff (some 5) |=(a=@ (some (add a 2))))
38− [~ u=7]
39− ~zod/try=> (biff ~ |=(a=@ (some (add a 2))))
40− ~
41−
42−------------------------------------------------------------------------
43−
44−### `++bind`
45−
46−Non-unit function to unit, producing unit
47−
48−Applies a function `b` to the value (`u.a`) of a [++unit]() `a`, producing
49−a unit. Used when you want a function that does not accept or produce a
50−unit to both accept and produce a unit.
51−
52−Accepts
53−-------
54−
55−`a` is a unit.
56−
57−`b` is a function.
58−
59−Produces
60−--------
61−
62−A unit.
63−
64−Source
65−------
66−
67− ++ bind :: argue
68− |* [a=(unit) b=gate]
69− ?~ a ~
70− [~ u=(b u.a)]
71−
72−Examples
73−--------
74−
75− ~zod/try=> (bind ((unit ,@) [~ 97]) ,@t)
76− [~ `a`]
77− ~zod/try=> =a |=(a=@ (add a 1))
78− ~zod/try=> (bind ((unit ,@) [~ 2]) a)
79− [~ 3]
80−
81−------------------------------------------------------------------------
82−
83−### `++bond`
84−
85−Replace null
86−
87−Replaces an empty [++unit]() `b` with the product of a called [trap]()
88−`a`. If the unit is not empty, then the original unit is produced.
89−
90−Accepts
91−-------
92−
93−`a` is a trap.
94−
95−`b` is a unit.
96−
97−Produces
98−--------
99−
100−Either the product of `a` or the value inside of unit `b`.
101−
102−Source
103−------
104−
105− ++ bond :: replace
106− |* a=trap
107− |* b=(unit)
108− ?~ b $:a
109− u.b
110−
111−Examples
112−--------
113−
114− ~zod/try=> (bex 10)
115− 1.024
116− ~zod/try=> ((bond |.((bex 10))) ~)
117− 1.024
118− ~zod/try=> ((bond |.((bex 10))) (slaw %ud '123'))
119− 123
120−
121−------------------------------------------------------------------------
122−
123−### `++both`
124−
125−Group unit values into pair
126−
127−Produces `~` if either `a` or `b` are empty. Otherwise, produces a
128−[++unit]() whose value is a cell of the values of two input units `a` and
129−`b`.
130−
131−Accepts
132−-------
133−
134−`a` is a unit.
135−
136−`b` is a unit.
137−
138−Produces
139−--------
140−
141−A unit of the two initial values.
142−
143−Source
144−------
145−
146− ++ both :: all the above
147− |* [a=(unit) b=(unit)]
148− ?~ a ~
149− ?~ b ~
150− [~ u=[u.a u.b]]
151−
152−Examples
153−--------
154−
155− ~zod/try=> (both (some 1) (some %b))
156− [~ u=[1 %b]]
157− ~zod/try=> (both ~ (some %b))
158− ~
159−
160−------------------------------------------------------------------------
161−
162−### `++clap`
163−
164−Apply function to two units
165−
166−Applies a binary function `c`--which does not usually accept or produce a [`++unit`]()--
167−to the values of two units, `a` and `b`, producing a unit.
168−
169−Accepts
170−-------
171−
172−`a` is a unit.
173−
174−`b` is a unit.
175−
176−`c` is a function that performs a binary operation.
177−
178−Produces
179−--------
180−
181−A unit.
182−
183−Source
184−------
185−
186− ++ clap :: combine
187− |* [a=(unit) b=(unit) c=_|=(^ +<-)]
188− ?~ a b
189− ?~ b a
190− [~ u=(c u.a u.b)]
191−
192−Examples
193−--------
194−
195− ~zod/try=> =u ((unit ,@t) [~ 'a'])
196− ~zod/try=> =v ((unit ,@t) [~ 'b'])
197− ~zod/try=> (clap u v |=([a=@t b=@t] (welp (trip a) (trip b))))
198− [~ u="ab"]
199− ~zod/try=> =a ((unit ,@u) [~ 1])
200− ~zod/try=> =b ((unit ,@u) [~ 2])
201− ~zod/try=> =c |=([a=@ b=@] (add a b))
202− ~zod/try=> (clap a b c)
203− [~ 3]
204−
205−
206−------------------------------------------------------------------------
207−
208−### `++drop`
209−
210−Unit to list
211−
212−Makes a [++list]() of the unwrapped value (`u.a`) of a [`++unit`]() `a`.
213−
214−Accepts
215−-------
216−
217−`a` is a unit.
218−
219−Produces
220−--------
221−
222−A list.
223−
224−Source
225−------
226−
227− ++ drop :: enlist
228− |* a=(unit)
229− ?~ a ~
230− [i=u.a t=~]
231−
232−Examples
233−--------
234−
235− ~zod/try=> =a ((unit ,@) [~ 97])
236− ~zod/try=> (drop a)
237− [i=97 t=~]
238− ~zod/try=> =a ((unit ,@) [~])
239− ~zod/try=> (drop a)
240− ~
241−
242−------------------------------------------------------------------------
243−
244−### `++fall`
245−
246−Give unit a default value
247−
248−Produces a default value `b` for a [`++unit`]() `a` in cases where `a` is null.
249−
250−Accepts
251−-------
252−
253−`a` is a unit.
254−
255−`b` is a [noun]() that's used as the default value.
256−
257−Produces
258−--------
259−
260−Either a noun `b` or the unwrapped value of unit `a`.
261−
262−Source
263−------
264−
265− ++ fall :: default
266− |* [a=(unit) b=*]
267− ?~(a b u.a)
268−
269−Examples
270−--------
271−
272− ~zod/try=> (fall ~ `a`)
273− `a`
274− ~zod/try=> (fall [~ u=0] `a`)
275− 0
276−
277−------------------------------------------------------------------------
278−
279−### `++lift`
280−
281−Curried bind
282−
283−Accepts a [`++gate`]() `a` and produces a function that accepts [`++unit`]()
284−`b` to which it applies `a`. Used when you want a function that does not accept
285−or produce a unit to both accept and produce a unit.
286−
287−Accepts
288−-------
289−
290−`a` is a gate.
291−
292−`b` is a unit.
293−
294−Produces
295−--------
296−
297−A unit.
298−
299−Source
300−------
301−
302− ++ lift :: lift gate (fmap)
303− |* a=gate :: flipped
304− |* b=(unit) :: curried
305− (bind b a) :: bind
306−
307−Examples
308−--------
309−
310− ~zod/try=> ((lift dec) `(unit ,@)`~)
311− ~
312− ~zod/try=> ((lift dec) `(unit ,@)`[~ 20])
313− [~ 19]
314−
315−------------------------------------------------------------------------
316−
317−### `++mate`
318−
319−Choose
320−
321−Accepts two units `a` and `b` whose values are expected to be
322−equivalent. If either is empty, then the value of the other is produced.
323−If neither are empty, it asserts that both values are the same and
324−produces that value. If the assertion fails, `++mate` crashes with
325−`'mate'` in the stack trace.
326−
327−Accepts
328−-------
329−
330−`a` is a unit.
331−
332−`b` is a unit.
333−
334−Produces
335−--------
336−
337−A unit or crash.
338−
339−Source
340−------
341−
342−++ mate :: choose
343− |* [a=(unit) b=(unit)]
344− ?~ b a
345− ?~ a b
346− ?.(=(u.a u.b) ~|('mate' !!) a)
347−
348−Examples
349−--------
350−
351− ~zod/try=> =a ((unit ,@) [~ 97])
352− ~zod/try=> =b ((unit ,@) [~ 97])
353− ~zod/try=> (mate a b)
354− [~ 97]
355− ~zod/try=> =a ((unit ,@) [~ 97])
356− ~zod/try=> =b ((unit ,@) [~])
357− ~zod/try=> (mate a b)
358− [~ 97]
359− ~zod/try=> =a ((unit ,@) [~ 97])
360− ~zod/try=> =b ((unit ,@) [~ 98])
361− ~zod/try=> (mate a b)
362− ! 'mate'
363− ! exit
364−
365−------------------------------------------------------------------------
366−
367−### `++need`
368−
369−Unwrap unit
370−
371−Retrieve the value from a [`++unit`]() and crash if the unit is null.
372−
373−Accepts
374−-------
375−
376−`a` is a unit.
377−
378−Produces
379−--------
380−
381−Either the unwrapped value of `a` (`u.a`), or crash.
382−
383−Source
384−------
385−
386− ++ need :: demand
387− |* a=(unit)
388− ?~ a !!
389− u.a
390−
391−Examples
392−--------
393−
394− ~zod/try=> =a ((unit ,[@t @t]) [~ ['a' 'b']])
395− ~zod/try=> (need a)
396− ['a' 'b']
397− ~zod/try=> =a ((unit ,@ud) [~ 17])
398− ~zod/try=> (need a)
399− 17
400− ~zod/try=> =a ((unit ,@) [~])
401− ~zod/try=> (need a)
402− ! exit
403−
404−------------------------------------------------------------------------
405−
406−### `++some`
407−
408−Wrap value in a unit
409−
410−Takes any atom `a` and produces a [`++unit`]() with the value set to `a`.
411−
412−Accepts
413−-------
414−
415−`a` is a [noun]().
416−
417−Produces
418−--------
419−
420−A unit.
421−
422−Source
423−------
424−
425− ++ some :: lift (pure)
426− |* a=*
427− [~ u=a]
428−
429−Examples
430−--------
431−
432− ~zod/try=> (some [`a` `b`])
433− [~ u=[`a` `b`]]
434− ~zod/try=> (some &)
435− [~ u=%.y]
436−
437−------------------------------------------------------------------------
438−
439−section 2bB, lists
440−------------------
441−
442−Reverse
443−
444−### `++flop`
445−
446−Produces the list `a` in reverse order.
447−
448−Accepts
449−-------
450−
451−`a` is a list.
452−
453−Produces
454−--------
455−
456−A list.
457−
458−Source
459−------
460−
461− ++ flop :: reverse
462− ~/ %flop
463− |* a=(list)
464− => .(a (homo a))
465− ^+ a
466− =+ b=`_a`~
467− |-
468− ?~ a b
469− $(a t.a, b [i.a b])
470−
471−
472−Examples
473−--------
474−
475− ~zod/try=> =a (limo [1 2 3 ~])
476− ~zod/try=> (flop a)
477− ~[3 2 1]
478−
479−### `++homo`
480−
481−Homogenize
482−
483−Produces a [`++list`]() whose type is a fork of all the contained types in the
484−list `a`. Used when you want to make all the types of the elements of a list the same.
485−
486−Accepts
487−-------
488−
489−`a` is a list.
490−
491−Produces
492−--------
493−
494−a list.
495−
496−Source
497−------
498−
499− ++ homo :: homogenize
500− |* a=(list)
501− ^+ =< $
502− |% +- $ ?:(_? ~ [i=(snag 0 a) t=$])
503− --
504− a
505−
506−Examples
507−--------
508−
509− ~zod/try=> lyst
510− [i=1 t=[i=97 t=[i=2 t=[i=98 t=[i=[~ u=10] t=~]]]]]
511− ~zod/try=> (homo lyst)
512− ~[1 97 2 98 [~ u=10]]
513− ~zod/try=> =a (limo [1 2 3 ~])
514− ~zod/try=> a
515− [i=1 t=[i=2 t=[i=3 t=~]]]
516− ~zod/try=> (homo a)
517− ~[1 2 3]
518−
519−### `++limo`
520−
521−List Constructor
522−
523−Turns a null-terminated tuple into a [`++list`]().
524−
525−Accepts
526−-------
527−
528−`a` is a null-terminated tuple.
529−
530−Produces
531−--------
532−
533−A list
534−
535−Source
536−------
537−
538− ++ limo :: listify
539− |* a=*
540− ^+ =< $
541− |% +- $ ?~(a ~ ?:(_? i=-.a t=$ $(a +.a)))
542− --
543− a
544−
545−Examples
546−--------
547−
548− ~zod/try=> (limo [1 2 3 ~])
549− [i=1 t=[i=2 t=[i=3 t=~]]]
550−
551−----------------------------------------------------------------------
552−
553−### `++lent`
554−
555−List length
556−
557−Produces the length of any [`++list`]() `a` as an atom.
558−
559−Accepts
560−-------
561−
562−`a` is a list.
563−
564−Produces
565−--------
566−
567−an atom.
568−
569−Source
570−------
571−
572− ++ lent :: length
573− ~/ %lent
574− |= a=(list)
575− ^- @
576− =+ b=0
577− |-
578− ?~ a b
579− $(a t.a, b +(b))
580−
581−Examples
582−--------
583−
584− ~zod/try=> (lent (limo [1 2 3 4 ~]))
585− 4
586− ~zod/try=> (lent (limo [1 'a' 2 'b' (some 10) ~]))
587− 5
588−
589−------------------------------------------------------------------------
590−
591−### `++levy`
592−
593−Logical "and" on list
594−
595−Computes the Boolean logical "and" on the results of [gate]() `b` applied to each individual element in [`++list`]() `a`.
596−
597−Accepts
598−-------
599−
600−`a` is a list.
601−
602−`b` is a gate.
603−
604−Produces
605−--------
606−
607−Source
608−------
609−
610− ++ levy
611− ~/ %levy :: all of
612− |* [a=(list) b=_|=(p=* .?(p))]
613− |- ^- ?
614− ?~ a &
615− ?. (b i.a) |
616− $(a t.a)
617−
618−Examples
619−--------
620−
621− ~zod/try=> =a |=(a=@ (lte a 1))
622− ~zod/try=> (levy (limo [0 1 2 1 ~]) a)
623− %.n
624− ~zod/try=> =a |=(a=@ (lte a 3))
625− ~zod/try=> (levy (limo [0 1 2 1 ~]) a)
626− %.y
627−
628−------------------------------------------------------------------------
629−
630−### `++lien`
631−
632−Logical "or" on list
633−
634− ++ lien :: some of
635− ~/ %lien
636− |* [a=(list) b=$+(* ?)]
637− |- ^- ?
638− ?~ a |
639− ?: (b i.a) &
640− $(a t.a)
641−
642−Computes the Boolean logical "or" on the results of applying [gate]() `b` to every element of [`++list`]() `a`.
643−
644−`a` is a list.
645−
646−`b` is a gate.
647−
648− ~zod/try=> =a |=(a=@ (gte a 1))
649− ~zod/try=> (lien (limo [0 1 2 1 ~]) a)
650− %.y
651− ~zod/try=> =a |=(a=@ (gte a 3))
652− ~zod/try=> (lien (limo [0 1 2 1 ~]) a)
653− %.n
654−
655−------------------------------------------------------------------------
656−
657−### `++murn`
658−
659−Maybe transform
660−
661−Passes each member of [`++list`]() `a` to [gate]() `b`, which must produce a
662−[`++unit`](). Produces a new list with all the results that do not produce
663−`~`.
664−
665−Accepts
666−-------
667−
668−`a` is a [list]().
669−
670−`b` is a [gate]() that produces a [unit]().
671−
672−Produces
673−--------
674−
675−A unit.
676−
677−Source
678−------
679−
680− ++ murn :: maybe transform
681− |* [a=(list) b=$+(* (unit))]
682− |-
683− ?~ a ~
684− =+ c=(b i.a)
685− ?~ c
686− $(a t.a)
687− [i=u.c t=$(a t.a)]
688−
689−Examples
690−--------
691−
692− ~zod/try=> =a |=(a=@ ?.((gte a 2) ~ (some (add a 10))))
693− ~zod/try=> (murn (limo [0 1 2 3 ~]) a)
694− [i=12 t=[i=13 t=~]]
695−
696−-------------------------------------------------------------
697−
698−### `++reap`
699−
700−Replicate
701−
702−Replicate: produces a [`++list`]() containing `a` copies of `b`.
703−
704−Accepts
705−-------
706−
707−`b` is a [noun]()
708−
709−Produces
710−--------
711−
712−A list.
713−
714−Source
715−------
716−
717− ++ reap :: replicate
718− |* [a=@ b=*]
719− |- ^- (list ,_b)
720− ?~ a ~
721− [b $(a (dec a))]
722−
723−Examples
724−--------
725−
726− ~zod/try=> (reap 20 %a)
727− ~[%a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a]
728− ~zod/try=> (reap 5 ~s1)
729− ~[~s1 ~s1 ~s1 ~s1 ~s1]
730− ~zod/try=> `@dr`(roll (reap 5 ~s1) add)
731− ~s5
732−
733−------------------------------------------------------------------------
734−
735−### `++reel`
736−
737−Right fold
738−
739−Right fold: moves right to left across a [`++list`]() `a`, recursively slamming
740−a binary [gate]() `b` with an element from `a` and an accumulator, producing
741−the final value of the accumulator.
742−
743−Accepts
744−-------
745−
746−`b` is a binary gate.
747−
748−Produces
749−--------
750−
751−The accumulator, which is a [noun]().
752−
753−Source
754−------
755−
756− ++ reel :: right fold
757− ~/ %reel
758− |* [a=(list) b=_|=([* *] +<+)]
759− |- ^+ +<+.b
760− ?~ a
761− +<+.b
762− (b i.a $(a t.a))
763−
764−Examples
765−--------
766−
767− ~zod/try=> =sum =|([p=@ q=@] |.((add p q)))
768− ~zod/try=> (reel (limo [1 2 3 4 5 ~]) sum)
769− 15
770− ~zod/try=> =a =|([p=@ q=@] |.((sub p q)))
771− ~zod/try=> (reel (limo [6 3 1 ~]) a)
772− 4
773− ~zod/try=> (reel (limo [3 6 1 ~]) a)
774− ! subtract-underflow
775− ! exit
776−
777−------------------------------------------------------------------------
778−
779−### `++roll`
780−
781−Left fold
782−
783−Left fold: moves left to right across a list `a`, recursively slamming a
784−binary [gate]() `b` with an element from the [`++list`]() and an accumulator,
785−producing the final value of the accumulator.
786−
787−Accepts
788−-------
789−
790−`b` is a binary [gate]().
791−
792−Produces
793−--------
794−
795−The accumulator, which is a [noun]().
796−
797−Source
798−------
799−
800− ++ roll :: left fold
801− ~/ %roll
802− |* [a=(list) b=_|=([* *] +<+)]
803− |- ^+ +<+.b
804− ?~ a
805− +<+.b
806− $(a t.a, b b(+<+ (b i.a +<+.b)))
807−
808−Examples
809−--------
810−
811− ~zod/try=> =sum =|([p=@ q=@] |.((add p q)))
812− ~zod/try=> (roll (limo [1 2 3 4 5 ~]) sum)
813− q=15
814− ~zod/try=> =a =|([p=@ q=@] |.((sub p q)))
815− ~zod/try=> (roll (limo [6 3 1 ~]) a)
816− ! subtract-underflow
817− ! exit
818− ~zod/try=> (roll (limo [1 3 6 ~]) a)
819− q=4
820−
821−------------------------------------------------------------------------
822−
823−### `++skid`
824−
825−Separate
826−
827−Seperates a [`++list`]() `a` into two lists - Those elements of `a` who produce
828−true when slammed to [gate]() `b` and those who produce `%.n`.
829−
830−Accepts
831−-------
832−
833−`b` is a gate that accepts one argument and produces a loobean.
834−
835−Produces
836−--------
837−
838−A cell of two lists.
839−
840−Source
841−------
842−
843− ++ skid :: separate
844− |* [a=(list) b=$+(* ?)]
845− |- ^+ [p=a q=a]
846− ?~ a [~ ~]
847− =+ c=$(a t.a)
848− ?:((b i.a) [[i.a p.c] q.c] [p.c [i.a q.c]])
849−
850−
851−Examples
852−--------
853−
854− ~zod/try=> =a |=(a=@ (gth a 1))
855− ~zod/try=> (skid (limo [0 1 2 3 ~]) a)
856− [p=[i=2 t=[i=3 t=~]] q=[i=0 t=[i=1 t=~]]]
857−
858−------------------------------------------------------------------------
859−
860−### `++skim`
861−
862−Suffix
863−
864−Cycles through the members of a list `a`, passing them to a gate `b` and
865−producing a list of all of the members that produce `%.y`. Inverse of
866−`++skip`.
867−
868−Accepts
869−-------
870−
871−`b` is a [gate]() that accepts one argument and produces a loobean.
872−
873−Produces
874−--------
875−
876−Source
877−------
878−
879−++ skim :: only
880− ~/ %skim
881− |* [a=(list) b=_|=(p=* .?(p))]
882− |-
883− ^+ a`
884− ?~ a ~
885− ?:((b i.a) [i.a $(a t.a)] $(a t.a))
886−
887−Examples
888−--------
889−
890− ~zod/try=> =a |=(a=@ (gth a 1))
891− ~zod/try=> (skim (limo [0 1 2 3 ~]) a)
892− [i=2 t=[i=3 t=~]]
893−
894−------------------------------------------------------------------------
895−
896−### `++skip`
897−
898−Except
899−
900−Cycles through the members of [`++list`]() `a`, passing them to a [gate]() `b`.
901−Produces a list of all of the members that produce `%.n`. Inverse of
902−`++skim`.
903−
904−Accepts
905−-------
906−
907−`b` is a [gate]() that accepts one argument and produces a loobean.
908−
909−Produces
910−--------
911−
912−A list of the same type as `a`.
913−
914−Source
915−------
916−
917− ++ skip :: except
918− ~/ %skip
919− |* [a=(list) b=_|=(p=* .?(p))]
920− |-
921− ^+ a
922− ?~ a ~
923− ?:((b i.a) $(a t.a) [i.a $(a t.a)])
924−
925−Examples
926−--------
927−
928− ~zod/try=> =a |=(a=@ (gth a 1))
929− ~zod/try=> (skip (limo [0 1 2 3 ~]) a)
930− [i=0 t=[i=1 t=~]]
931−
932−------------------------------------------------------------------------
933−
934−### `++scag`
935−
936−Prefix
937−
938−Accepts an atom `a` and [list]() `b`, producing the first `a` elements of
939−the front of the list.
940−
941−Accepts
942−-------
943−
944−`b` is a list.
945−
946−Produces
947−--------
948−
949−A list of the same type as `b`.
950−
951−Source
952−------
953−
954− ++ scag :: prefix
955− ~/ %scag
956− |* [a=@ b=(list)]
957− |- ^+ b
958− ?: |(?=(~ b) =(0 a)) ~
959− [i.b $(b t.b, a (dec a))]
960−
961−Examples
962−--------
963−
964− ~zod/try=> (scag 2 (limo [0 1 2 3 ~]))
965− [i=0 t=[i=1 t=~]]
966− ~zod/try=> (scag 10 (limo [1 2 3 4 ~]))
967− [i=1 t=[i=2 t=[i=3 t=[i=4 t=~]]]]
968−
969−------------------------------------------------------------------------
970−
971−### `++slag`
972−
973−Suffix
974−
975−Accepts an atom `a` and list `b`, producing the remaining elements from
976−`b` starting at `a`.
977−
978−Accepts
979−-------
980−
981−`b` is a [list]().
982−
983−Produces
984−--------
985−
986−A list of the same type as `b`.
987−
988−Source
989−------
990−
991− ++ slag :: suffix
992− ~/ %slag
993− |* [a=@ b=(list)]
994− |- ^+ b
995− ?: =(0 a) b
996− ?~ b ~
997− $(b t.b, a (dec a))
998−
999−Examples
1000−--------
1001−
1002− ~zod/try=> (slag 2 (limo [1 2 3 4 ~]))
1003− [i=3 t=[i=4 t=~]]
1004− ~zod/try=> (slag 1 (limo [1 2 3 4 ~]))
1005− [i=2 t=[i=3 t=[i=4 t=~]]]
1006−
1007−------------------------------------------------------------------------
1008−
1009−### `++snag`
1010−
1011−Index
1012−
1013−Accepts an atom `a` and a [`++list`]() `b`, producing the element at the index
1014−of `a`and failing if the list is null. Lists are 0-indexed.
1015−
1016−Accepts
1017−-------
1018−
1019−`b` is a [list]().
1020−
1021−Produces
1022−--------
1023−
1024−Produces an element of `b`, or crashes if no element exists at that index.
1025−
1026−Source
1027−------
1028−
1029− ++ snag :: index
1030− ~/ %snag
1031− |* [a=@ b=(list)]
1032− |-
1033− ?~ b
1034− ~|('snag-fail' !!)
1035− ?: =(0 a) i.b
1036− $(b t.b, a (dec a))
1037−
1038−Examples
1039−--------
1040−
1041− ~zod/try=> (snag 2 "asdf")
1042− ~~d
1043− ~zod/try=> (snag 0 `(list ,@ud)`~[1 2 3 4])
1044− 1
1045−
1046−------------------------------------------------------------------------
1047−
1048−### `++sort`
1049−
1050−Quicksort
1051−
1052−Quicksort: accepts a [`++list`]() `a` and a [gate]() `b` which accepts two nouns and
1053−produces a loobean. `++sort` then produces a list of the elements of `a`,
1054−sorted according to `b`.
1055−
1056−Accepts
1057−-------
1058−
1059−`b` is a gate that ccepts two nouns and produces a boolean.
1060−
1061−Produces
1062−--------
1063−
1064−A list
1065−
1066−Source
1067−------
1068−
1069− ++ sort :: quicksort
1070− ~/ %sort
1071− |* [a=(list) b=$+([* *] ?)]
1072− => .(a ^.(homo a))
1073− |- ^+ a
1074− ?~ a ~
1075− %+ weld
1076− $(a (skim t.a |=(c=_i.a (b c i.a))))
1077− ^+ t.a
1078− [i.a $(a (skim t.a |=(c=_i.a !(b c i.a))))]
1079−
1080−Examples
1081−--------
1082−
1083− ~zod/try=> =a =|([p=@ q=@] |.((gth p q)))
1084− ~zod/try=> (sort (limo [0 1 2 3 ~]) a)
1085− ~[3 2 1 0]
1086−
1087−------------------------------------------------------------------------
1088−
1089−### `++swag`
1090−
1091−Infix
1092−
1093−Similar to `substr` in Javascript: extracts a string infix, beginning at
1094−inclusive index `a`, producing `b` number of characters.
1095−
1096−Accepts
1097−-------
1098−
1099−`c` is a [list]().
1100−
1101−Produces
1102−--------
1103−
1104−A list of the same type as `c`.
1105−
1106−Source
1107−------
1108−
1109− ++ swag :: infix
1110− |* [[a=@ b=@] c=(list)]
1111− (scag b (slag a c))
1112−
1113−Examples
1114−--------
1115−
1116− ~zod/try=> (swag [2 5] "roly poly")
1117− "ly po"
1118− ~zod/try=> (swag [2 2] (limo [1 2 3 4 ~]))
1119− [i=3 t=[i=4 t=~]]
1120−
1121−------------------------------------------------------------------------
1122−
1123−### `++turn`
1124−
1125−Gate to list
1126−
1127−Accepts a [`++list`]() `a` and a [gate]() `b`. Produces a list with the gate applied
1128−to each element of the original list.
1129−
1130−Accepts
1131−-------
1132−
1133−`b` is a gate.
1134−
1135−Produces
1136−--------
1137−
1138−A list.
1139−
1140−Source
1141−------
1142−
1143− ++ turn :: transform
1144− ~/ %turn
1145− |* [a=(list) b=_,*]
1146− |-
1147− ?~ a ~
1148− [i=(b i.a) t=$(a t.a)]
1149−
1150−Examples
1151−--------
1152−
1153− ~zod/try=> (turn (limo [104 111 111 110 ~]) ,@t)
1154− <|h o o n|>
1155− ~zod/try=> =a |=(a=@ (add a 4))
1156− ~zod/try=> (turn (limo [1 2 3 4 ~]) a)
1157− ~[5 6 7 8]
1158−
1159−------------------------------------------------------------------------
1160−
1161−### `++weld`
1162−
1163−Concatenate
1164−
1165−Concatenate two [`++list`]()s `a` and `b`.
1166−
1167−Accepts
1168−-------
1169−
1170−`a` and `b` are [list]()s.
1171−
1172−Source
1173−------
1174−
1175− ++ weld :: concatenate
1176− ~/ %weld
1177− |* [a=(list) b=(list)]
1178− => .(a ^.(homo a), b ^.(homo b))
1179− |- ^+ b
1180− ?~ a b
1181− [i.a $(a t.a)]
1182−
1183−Examples
1184−--------
1185−
1186− ~zod/try=> (weld "urb" "it")
1187− ~[~~u ~~r ~~b ~~i ~~t]
1188− ~zod/try=> (weld (limo [1 2 ~]) (limo [3 4 ~]))
1189− ~[1 2 3 4]
1190−
1191−------------------------------------------------------------------------
1192−
1193−### `++welp`
1194−
1195−Perfect weld
1196−
1197−Concatenate two [`++list`]()s `a` and `b` without losing their type information
1198−to homogenization.
1199−
1200−Accepts
1201−-------
1202−
1203−`a` is a list.
1204−
1205−`b` is a list.
1206−
1207−Produces
1208−--------
1209−
1210−A list.
1211−
1212−Source
1213−------
1214−
1215− ++ welp :: perfect weld
1216− =| [* *]
1217− |%
1218− +- $
1219− ?~ +<-
1220− +<-(. +<+)
1221− +<-(+ $(+<- +<->))
1222− --
1223−
1224−Examples
1225−--------
1226−
1227− ~zod/try=> (welp "foo" "bar")
1228− "foobar"
1229− ~zod/arvo=/hoon/hoon> (welp ~[60 61 62] ~[%a %b %c])
1230− [60 61 62 %a %b %c ~]
1231− ~zod/arvo=/hoon/hoon> :type; (welp ~[60 61 62] ~[%a %b %c])
1232− [60 61 62 %a %b %c ~]
1233− [@ud @ud @ud %a %b %c %~]
1234− ~zod/arvo=/hoon/hoon> (welp [sa/1 so/2 ~] si/3)
1235− [[%sa 1] [%so 2] %si 3]
1236−
1237−------------------------------------------------------------------------
1238−
1239−### `++wild`
1240−
1241−XXDELETE
1242−
1243− ++ wild :: concatenate
1244− |* [a=(list) b=(list)]
1245− => .(a ^.(homo a), b ^.(homo b))
1246− |-
1247− ?~ a b
1248− [i=i.a $(a t.a)]
1249−
1250−Concatenates two lists `a` and `b`, homogenizing their types
1251−individually.
1252−
1253−`a` and `b` are [list]()s.
1254−
1255− ~zod/try=> (wild (limo ~[1 2 3]) (limo [4]~))
1256− ~[1 2 3 4]
1257− ~zod/try=> (wild (limo 60 61 62 ~) (limo %a %b %c ~))
1258− [i=60 [i=61 [i=62 ~[%a %b %c]]]]
1259− ~zod/try=> (weld (limo 60 61 62 ~) (limo %a %b %c ~))
1260− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.000 15].[10.016 57]>
1261− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.001 15].[10.016 57]>
1262− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.002 15].[10.016 57]>
1263− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.004 15].[10.016 57]>
1264− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.006 15].[10.016 57]>
1265− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.006 29].[10.006 44]>
1266− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.056 3].[10.061 13]>
1267− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.058 3].[10.061 13]>
1268− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.059 3].[10.061 13]>
1269− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.060 5].[10.060 47]>
1270− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.826 7].[9.844 35]>
1271− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.827 7].[9.844 35]>
1272− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.827 11].[9.838 13]>
1273− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.828 11].[9.838 13]>
1274− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.829 13].[9.831 47]>
1275− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.830 13].[9.831 47]>
1276− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.706 7].[9.712 25]>
1277− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.707 7].[9.712 25]>
1278− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.708 7].[9.712 25]>
1279− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.712 7].[9.712 25]>
1280− ! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.712 8].[9.712 25]>
1281− ! exit
1282−
1283−------------------------------------------------------------------------
1284−
1285−### `++zing`
1286−
1287−Cons
1288−
1289−Turns a [`++list`]() of lists into a single list by promoting the elements of
1290−each sublist into the higher.
1291−
1292−Accepts
1293−-------
1294−
1295−A list of lists.
1296−
1297−Produces
1298−--------
1299−
1300−A list.
1301−
1302−Source
1303−------
1304−
1305− ++ zing :: promote
1306− =| *
1307− |%
1308− +- $
1309− ?~ +<
1310− +<
1311− (welp +<- $(+< +<+))
1312− --
1313−
1314−Examples
1315−--------
1316−
1317− ~zod/try=> (zing (limo [(limo ['a' 'b' 'c' ~]) (limo ['e' 'f' 'g' ~]) (limo ['h' 'i' 'j' ~]) ~]))
1318− ~['a' 'b' 'c' 'e' 'f' 'g' 'h' 'i' 'j']
1319− ~zod/try=> (zing (limo [(limo [1 'a' 2 'b' ~]) (limo [3 'c' 4 'd' ~]) ~]))
1320− ~[1 97 2 98 3 99 4 100]
docs/dev/hoon/library/2c.mddeleted−3176
@@ -1,3176 +0,0 @@
1−chapter 2c, simple noun surgery
2−===============================
3−
4−section 2cA, bit surgery
5−------------------------
6−
7−### `++bex`
8−
9−Binary exponent
10−
11−Computes the result of `2^a`, producing an [atom]().
12−
13−Accepts
14−-------
15−
16−`a` is an atom.
17−
18−Produces
19−--------
20−
21−An atom.
22−
23−Source
24−------
25−
26− ++ bex :: binary exponent
27− ~/ %bex
28− |= a=@
29− ^- @
30− ?: =(0 a) 1
31− (mul 2 $(a (dec a)))
32−
33−Examples
34−--------
35−
36− ~zod/try=> (bex 4)
37− 16
38− ~zod/try=> (bex (add 19 1))
39− 1.048.576
40− ~zod/try=> (bex 0)
41− 1
42−
43−------------------------------------------------------------------------
44−
45−### `++xeb`
46−
47−Binary logarithm
48−
49−Computes the base-2 logarithm of `a`, producing an [atom]().
50−
51−Accepts
52−-------
53−
54−`a` is an atom.
55−
56−Produces
57−--------
58−
59−An atom.
60−
61−Source
62−------
63−
64− ++ xeb :: binary logarithm
65− :: ~/ %xeb
66− |= a=@
67− ^- @
68− (met 0 a)
69−
70−Examples
71−--------
72−
73− ~zod/try=> (xeb 31)
74− 5
75− ~zod/try=> (xeb 32)
76− 6
77− ~zod/try=> (xeb 49)
78− 6
79− ~zod/try=> (xeb 0)
80− 0
81− ~zod/try=> (xeb 1)
82− 1
83− ~zod/try=> (xeb 2)
84− 2
85−
86−------------------------------------------------------------------------
87−
88−### `++can`
89−
90−Assemble
91−
92−Produces an [atom]() from a list `b` of length-value pairs `p` and `q`,
93−where `p` is the length in bloqs of size `a`, and `q` is an atomic
94−value.
95−
96−Accepts
97−-------
98−
99−`a` is a block size (see [`++bloq`]()).
100−
101−`b` is a [`++list`]() of length value pairs, `p` and `q`.
102−
103−Produces
104−--------
105−
106−An atom.
107−
108−Source
109−------
110−
111− ++ can :: assemble
112− ~/ %can
113− |= [a=bloq b=(list ,[p=@ q=@])]
114− ^- @
115− ?~ b 0
116− (mix (end a p.i.b q.i.b) (lsh a p.i.b $(b t.b)))
117−
118−Examples
119−--------
120−
121− ~zod/try=> `@ub`(can 3 ~[[1 1]])
122− 0b1
123− ~zod/try=> `@ub`(can 0 ~[[1 255]])
124− 0b1
125− ~zod/try=> `@ux`(can 3 [3 0xc1] [1 0xa] ~)
126− 0xa00.00c1
127− ~zod/try=> `@ux`(can 3 [3 0xc1] [1 0xa] [1 0x23] ~)
128− 0x23.0a00.00c1
129− ~zod/try=> `@ux`(can 4 [3 0xc1] [1 0xa] [1 0x23] ~)
130− 0x23.000a.0000.0000.00c1
131− ~zod/try=> `@ux`(can 3 ~[[1 'a'] [2 'bc']])
132− 0x63.6261
133−
134−------------------------------------------------------------------------
135−
136−### `++cat`
137−
138−Concatenate
139−
140−Concatenates two [atom]()s, `b` and `c`, according to bloq size `a`, producing an
141−atom.
142−
143−Accepts
144−-------
145−
146−`a` is a block size (see [`++bloq`]()).
147−
148−`b` is an atom.
149−
150−`c` is an atom.
151−
152−Produces
153−--------
154−
155−An atom.
156−
157−Source
158−------
159−
160− ++ cat :: concatenate
161− ~/ %cat
162− |= [a=bloq b=@ c=@]
163− (add (lsh a (met a b) c) b)
164−
165−Examples
166−--------
167−
168− ~zod/try=> `@ub`(cat 3 1 0)
169− 0b1
170− ~zod/try=> `@ub`(cat 0 1 1)
171− 0b11
172− ~zod/try=> `@ub`(cat 0 2 1)
173− 0b110
174− ~zod/try=> `@ub`(cat 2 1 1)
175− 0b1.0001
176− ~zod/try=> `@ub`256
177− 0b1.0000.0000
178− ~zod/try=> `@ub`255
179− 0b1111.1111
180− ~zod/try=> `@ub`(cat 3 256 255)
181− 0b1111.1111.0000.0001.0000.0000
182− ~zod/try=> `@ub`(cat 2 256 255)
183− 0b1111.1111.0001.0000.0000
184− ~zod/try=> (cat 3 256 255)
185− 16.711.936
186−
187−------------------------------------------------------------------------
188−
189−### `++cut`
190−
191−Slice
192−
193−Slices `c` blocks of size `a` that are `b` blocks from the end of `d`.
194−
195−Accepts
196−-------
197−
198−`a` is a block size (see [++bloq]()).
199−
200−`b` is an [atom]().
201−
202−`c` is an atom.
203−
204−Produces
205−--------
206−
207−An atom.
208−
209−Source
210−------
211−
212− ++ cut :: slice
213− ~/ %cut
214− |= [a=bloq [b=@ c=@] d=@]
215− (end a c (rsh a b d))
216−
217−Examples
218−--------
219−
220− ~zod/try=> (cut 0 [1 1] 2)
221− 1
222− ~zod/try=> (cut 0 [2 1] 4)
223− 1
224− ~zod/try=> `@t`(cut 3 [0 3] 'abcdefgh')
225− 'abc'
226− ~zod/try=> `@t`(cut 3 [1 3] 'abcdefgh')
227− 'bcd'
228− ~zod/try=> `@ub`(cut 0 [0 3] 0b1111.0000.1101)
229− 0b101
230− ~zod/try=> `@ub`(cut 0 [0 6] 0b1111.0000.1101)
231− 0b1101
232− ~zod/try=> `@ub`(cut 0 [4 6] 0b1111.0000.1101)
233− 0b11.0000
234− ~zod/try=> `@ub`(cut 0 [3 6] 0b1111.0000.1101)
235− 0b10.0001
236−
237−------------------------------------------------------------------------
238−
239−### `++end`
240−
241−Tail
242−
243−Produces an [atom]() by taking the last `b` blocks of size `a` from `c`.
244−
245−Accepts
246−-------
247−
248−`a` is a block size (see [`++bloq`]()).
249−
250−`b` is an atom.
251−
252−`c` is an [atom]().
253−
254−Produces
255−--------
256−
257−An atom.
258−
259−
260−Source
261−------
262−
263− ++ end :: tail
264− ~/ %end
265− |= [a=bloq b=@ c=@]
266− (mod c (bex (mul (bex a) b)))
267−
268−Examples
269−--------
270−
271− ~zod/try=> `@ub`12
272− 0b1100
273− ~zod/try=> `@ub`(end 0 3 12)
274− 0b100
275− ~zod/try=> (end 0 3 12)
276− 4
277− ~zod/try=> `@ub`(end 1 3 12)
278− 0b1100
279− ~zod/try=> (end 1 3 12)
280− 12
281− ~zod/try=> `@ux`'abc'
282− 0x63.6261
283− ~zod/try=> `@ux`(end 3 2 'abc')
284− 0x6261
285− ~zod/try=> `@t`(end 3 2 'abc')
286− 'ab'
287−
288−------------------------------------------------------------------------
289−
290−### `++fil`
291−
292−Fill bloqstream
293−
294−Produces an [atom]() by repeating `c` for `b` blocks of size `a`.
295−
296−Accepts
297−-------
298−
299−`a` is a block size (see [`++bloq`]()).
300−
301−`b` is an atom.
302−
303−`c` is an [atom]().
304−
305−Produces
306−--------
307−
308−An atom.
309−
310−Source
311−------
312−
313− ++ fil :: fill bloqstream
314− |= [a=bloq b=@ c=@]
315− =+ n=0
316− =+ d=c
317− |- ^- @
318− ?: =(n b)
319− (rsh a 1 d)
320− $(d (add c (lsh a 1 d)), n +(n))
321−
322−Examples
323−--------
324−
325− ~zod/try=> `@t`(fil 3 5 %a)
326− 'aaaaa'
327− ~zod/try=> `@t`(fil 5 10 %ceeb)
328− 'ceebceebceebceebceebceebceebceebceebceeb'
329− ~zod/try=> `@t`(fil 4 10 %eced)
330− 'ʇʇʇʇʇʇʇʇʇʇed'
331− ~zod/try=> `@tas`(fil 4 10 %bf)
332− %bfbfbfbfbfbfbfbfbfbf
333−
334−------------------------------------------------------------------------
335−
336−### `++lsh`
337−
338−Left-shift
339−
340−Produces an [atom]() by left-shifting `c` by `b` blocks of size `a`.
341−
342−Accepts
343−-------
344−
345−`a` is a block size (see [`++bloq`]()).
346−
347−`b` is an atom.
348−
349−`c` is an atom.
350−
351−Produces
352−--------
353−
354−An atom.
355−
356−Source
357−------
358−
359− ++ lsh :: left-shift
360− ~/ %lsh
361− |= [a=bloq b=@ c=@]
362− (mul (bex (mul (bex a) b)) c)
363−
364−Examples
365−--------
366−
367− ~zod/try=> `@ub`1
368− 0b1
369− ~zod/try=> `@ub`(lsh 0 1 1)
370− 0b10
371− ~zod/try=> (lsh 0 1 1)
372− 2
373− ~zod/try=> `@ub`255
374− 0b1111.1111
375− ~zod/try=> `@ub`(lsh 3 1 255)
376− 0b1111.1111.0000.0000
377− ~zod/try=> (lsh 3 1 255)
378− 65.280
379−
380−------------------------------------------------------------------------
381−
382−### `++me
383−
384−Measure
385−
386−Computes the number of blocks of size `a` in `b`, producing an [atom]().
387−
388−`a` is a block size (see [`++bloq`]()).
389−
390−`b` is an atom.
391−
392−Source
393−------
394−
395− ++ met :: measure
396− ~/ %met
397− |= [a=bloq b=@]
398− ^- @
399− =+ c=0
400− |-
401− ?: =(0 b) c
402− $(b (rsh a 1 b), c +(c))
403−
404−Examples
405−--------
406−
407− ~zod/try=> (met 0 1)
408− 1
409− ~zod/try=> (met 0 2)
410− 2
411− ~zod/try=> (met 3 255)
412− 1
413− ~zod/try=> (met 3 256)
414− 2
415− ~zod/try=> (met 3 'abcde')
416− 5
417−
418−------------------------------------------------------------------------
419−
420−### `++rap`
421−
422−Assemble non-zero
423−
424−Concatenates a list of [atom]()s `b` using blocksize `a`, producing an atom.
425−
426−Accepts
427−-------
428−
429−`a` is a block size (see [`++bloq`]()).
430−
431−`b` is a [`++list`]() of [atom]()s.
432−
433−Produces
434−--------
435−
436−An atom.
437−
438−Source
439−------
440−
441− ++ rap :: assemble nonzero
442− ~/ %rap
443− |= [a=bloq b=(list ,@)]
444− ^- @
445− ?~ b 0
446− (cat a i.b $(b t.b))
447−
448−Examples
449−--------
450−
451− ~zod/try=> `@ub`(rap 2 (limo [1 2 3 4 ~]))
452− 0b100.0011.0010.0001
453− ~zod/try=> `@ub`(rap 1 (limo [1 2 3 4 ~]))
454− 0b1.0011.1001
455− ~zod/try=> (rap 0 (limo [0 0 0 ~]))
456− 0
457− ~zod/try=> (rap 0 (limo [1 0 1 ~]))
458− 3
459−
460−------------------------------------------------------------------------
461−
462−### `++rep`
463−
464−Assemble single
465−
466−Produces an [atom]() by assembling a list of atoms `b` using block size `a`.
467−
468−Accepts
469−-------
470−
471−`a` is a block size (see [`++bloq`]()).
472−
473−`b` is a list of atoms.
474−
475−Produces
476−--------
477−
478−An atom.
479−
480−Source
481−------
482−
483− ++ rep :: assemble single
484− ~/ %rep
485− |= [a=bloq b=(list ,@)]
486− ^- @
487− =+ c=0
488− |-
489− ?~ b 0
490− (con (lsh a c (end a 1 i.b)) $(c +(c), b t.b))
491−
492−Examples
493−--------
494−
495− ~zod/try=> `@ub`(rep 2 (limo [1 2 3 4 ~]))
496− 0b100.0011.0010.0001
497− ~zod/try=> (rep 0 (limo [0 0 1 ~]))
498− 4
499− ~zod/try=> (rep 0 (limo [0 0 0 1 ~]))
500− 8
501− ~zod/try=> (rep 0 (limo [0 1 0 0 ~]))
502− 2
503− ~zod/try=> (rep 0 (limo [0 1 0 1 ~]))
504− 10
505− ~zod/try=> (rep 0 (limo [0 1 0 1 0 1 ~]))
506− 42
507− ~zod/try=> `@ub`42
508− 0b10.1010
509−
510−------------------------------------------------------------------------
511−
512−### `++rip`
513−
514−Disassemble
515−
516−Produces a list of [atom]()s from the bits of `b` using block size `a`.
517−
518−Accepts
519−-------
520−
521−`a` is a block size (see [`++bloq`]()).
522−
523−`b` is an atom.
524−
525−Produces
526−--------
527−
528−A list of atoms.
529−
530−Source
531−------
532−
533− ++ rip :: disassemble
534− ~/ %rip
535− |= [a=bloq b=@]
536− ^- (list ,@)
537− ?: =(0 b) ~
538− [(end a 1 b) $(b (rsh a 1 b))]
539−
540−Examples
541−--------
542−
543− ~zod/try=> `@ub`155
544− 0b1001.1011
545− ~zod/try=> (rip 0 155)
546− ~[1 1 0 1 1 0 0 1]
547− ~zod/try=> (rip 2 155)
548− ~[11 9]
549− ~zod/try=> (rip 1 155)
550− ~[3 2 1 2]
551− ~zod/try=> `@ub`256
552− 0b1.0000.0000
553− ~zod/try=> (rip 0 256)
554− ~[0 0 0 0 0 0 0 0 1]
555− ~zod/try=> (rip 2 256)
556− ~[0 0 1]
557− ~zod/try=> (rip 3 256)
558− ~[0 1]
559−
560−------------------------------------------------------------------------
561−
562−### `++rsh`
563−
564−Right-shift
565−
566−Right-shifts `c` by `b` blocks of size `a`, producing an [atom]().
567−
568−Accepts
569−-------
570−
571−`a` is a block size (see [`++bloq`]()).
572−
573−`b` is an atom.
574−
575−`c` is an atom.
576−
577−Produces
578−--------
579−
580−An atom.
581−
582−Source
583−------
584−
585− ++ rsh :: right-shift
586− ~/ %rsh
587− |= [a=bloq b=@ c=@]
588− (div c (bex (mul (bex a) b)))
589−
590−Examples
591−--------
592−
593− ~zod/try=> `@ub`145
594− 0b1001.0001
595− ~zod/try=> `@ub`(rsh 1 1 145)
596− 0b10.0100
597− ~zod/try=> (rsh 1 1 145)
598− 36
599− ~zod/try=> `@ub`(rsh 2 1 145)
600− 0b1001
601− ~zod/try=> (rsh 2 1 145)
602− 9
603− ~zod/try=> `@ub`10
604− 0b1010
605− ~zod/try=> `@ub`(rsh 0 1 10)
606− 0b101
607− ~zod/try=> (rsh 0 1 10)
608− 5
609− ~zod/try=> `@ux`'abc'
610− 0x63.6261
611− ~zod/try=> `@t`(rsh 3 1 'abc')
612− 'bc'
613− ~zod/try=> `@ux`(rsh 3 1 'abc')
614− 0x6362
615−
616−------------------------------------------------------------------------
617−
618−### `++swap`
619−
620−Reverse block order
621−
622−Switches little endian to big and vice versa: produces an [atom]() by
623−reversing the block order of `b` using block size `a`.
624−
625−
626−Accepts
627−-------
628−
629−`a` is a block size (see [`++bloq`]()).
630−
631−`b` is an atom.
632−
633−Produces
634−--------
635−
636−An atom
637−
638−Source
639−------
640−
641− ++ swap |=([a=bloq b=@] (rep a (flop (rip a b)))) :: reverse bloq order
642−
643−Examples
644−--------
645−
646− ~zod/try=> `@ub`24
647− 0b1.1000
648− ~zod/try=> (swap 0 24)
649− 3
650− ~zod/try=> `@ub`3
651− 0b11
652− ~zod/try=> (swap 0 0)
653− 0
654− ~zod/try=> (swap 0 128)
655− 1
656−
657−------------------------------------------------------------------------
658−
659−section 2cB, bit logic
660−----------------------
661−
662−### `++con`
663−
664−Binary OR
665−
666−Computes the bit-wise logical OR of two [atom]()s, `a` and `b`, producing an
667−atom.
668−
669−Accepts
670−-------
671−
672−`a` is an atom
673−
674−`b` is an atom
675−
676−Produces
677−--------
678−
679−An atom.
680−
681−Source
682−------
683−
684− ++ con :: binary or
685− ~/ %con
686− |= [a=@ b=@]
687− =+ [c=0 d=0]
688− |- ^- @
689− ?: ?&(=(0 a) =(0 b)) d
690− %= $
691− a (rsh 0 1 a)
692− b (rsh 0 1 b)
693− c +(c)
694− d %+ add d
695− %^ lsh 0 c
696− ?& =(0 (end 0 1 a))
697− =(0 (end 0 1 b))
698− ==
699− ==
700−
701−Examples
702−--------
703−
704− ~zod/try=> (con 0b0 0b1)
705− 1
706− ~zod/try=> (con 0 1)
707− 1
708− ~zod/try=> (con 0 0)
709− 0
710− ~zod/try=> `@ub`(con 0b1111.0000 0b1.0011)
711− 0b1111.0011
712− ~zod/try=> (con 4 4)
713− 4
714− ~zod/try=> (con 10.000 234)
715− 10.234
716−
717−------------------------------------------------------------------------
718−
719−### `++dis`
720−
721−Binary AND
722−
723−Computes the bit-wise logical AND of two [atom]()s `a` and `b`, producing an
724−atom.
725−
726−Accepts
727−-------
728−
729−`a` is an atom.
730−
731−`b` is an atom.
732−
733−Produces
734−--------
735−
736−An atom.
737−
738−Source
739−------
740−
741− ++ dis :: binary and
742− ~/ %dis
743− |= [a=@ b=@]
744− =| [c=@ d=@]
745− |- ^- @
746− ?: ?|(=(0 a) =(0 b)) d
747− %= $
748− a (rsh 0 1 a)
749− b (rsh 0 1 b)
750− c +(c)
751− d %+ add d
752− %^ lsh 0 c
753− ?| =(0 (end 0 1 a))
754− =(0 (end 0 1 b))
755− ==
756− ==
757−
758−Examples
759−--------
760−
761− ~zod/try=> `@ub`9
762− 0b1001
763− ~zod/try=> `@ub`5
764− 0b101
765− ~zod/try=> `@ub`(dis 9 5)
766− 0b1
767− ~zod/try=> (dis 9 5)
768− 1
769− ~zod/try=> `@ub`534
770− 0b10.0001.0110
771− ~zod/try=> `@ub`987
772− 0b11.1101.1011
773− ~zod/try=> `@ub`(dis 534 987)
774− 0b10.0001.0010
775− ~zod/try=> (dis 534 987)
776− 530
777−
778−------------------------------------------------------------------------
779−
780−### `++mix`
781−
782−Binary XOR
783−
784−Produces the bit-wise logical XOR of `a` and `b`, producing an [atom]().
785−
786−Accepts
787−-------
788−
789−`a` is an atom
790−
791−`b` is an atom
792−
793−Produces
794−--------
795−
796−An atom.
797−
798−Source
799−------
800−
801− ++ mix :: binary xor
802− ~/ %mix
803− |= [a=@ b=@]
804− ^- @
805− =+ [c=0 d=0]
806− |-
807− ?: ?&(=(0 a) =(0 b)) d
808− %= $
809− a (rsh 0 1 a)
810− b (rsh 0 1 b)
811− c +(c)
812− d (add d (lsh 0 c =((end 0 1 a) (end 0 1 b))))
813− ==
814−
815−Examples
816−--------
817−
818− ~zod/try=> `@ub`2
819− 0b10
820− ~zod/try=> `@ub`3
821− 0b11
822− ~zod/try=> `@ub`(mix 2 3)
823− 0b1
824− ~zod/try=> (mix 2 3)
825− 1
826− ~zod/try=> `@ub`(mix 2 2)
827− 0b0
828− ~zod/try=> (mix 2 2)
829− 0
830−
831−------------------------------------------------------------------------
832−
833−### `++not`
834−
835−Binary NOT
836−
837−Computes the bit-wise logical NOT of the bottom `b` blocks of size `a`
838−of `c`.
839−
840−Accepts
841−-------
842−
843−`a` is a block size (see [`++bloq`]()).
844−
845−`b` is an [atom]().
846−
847−`c` is an atom.
848−
849−Produces
850−--------
851−
852−An atom.
853−
854−Source
855−------
856−
857− ++ not |= [a=bloq b=@ c=@] :: binary not (sized)
858− (mix c (dec (bex (mul b (bex a)))))
859−
860−Examples
861−--------
862−
863− ~zod/try=> `@ub`24
864− 0b1.1000
865− ~zod/try=> (not 0 5 24)
866− 7
867− ~zod/try=> `@ub`7
868− 0b111
869− ~zod/try=> (not 2 5 24)
870− 1.048.551
871− ~zod/try=> (not 2 5 1.048.551)
872− 24
873− ~zod/try=> (not 1 1 (not 1 1 10))
874− 10
875−
876−------------------------------------------------------------------------
877−
878−section 2cC, noun orders
879−------------------------
880−
881−### `++aor`
882−
883−Alphabetic order
884−
885−Computes whether `a` and `b` are in alphabetical order, producing a
886−boolean.
887−
888−Accepts
889−-------
890−
891−`a` is a [noun]().
892−
893−`b` is a noun.
894−
895−Produces
896−--------
897−
898−A boolean atom.
899−
900−
901−Source
902−------
903−
904− ++ aor :: alphabetic-order
905− ~/ %aor
906− |= [a=* b=*]
907− ^- ?
908− ?: =(a b) &
909− ?. ?=(@ a)
910− ?: ?=(@ b) |
911− ?: =(-.a -.b)
912− $(a +.a, b +.b)
913− $(a -.a, b -.b)
914− ?. ?=(@ b) &
915− |-
916− =+ [c=(end 3 1 a) d=(end 3 1 b)]
917− ?: =(c d)
918− $(a (rsh 3 1 a), b (rsh 3 1 b))
919− (lth c d)
920−
921−Examples
922−--------
923−
924− ~zod/try=> (aor 'a' 'b')
925− %.y
926− ~zod/try=> (aor 'b' 'a')
927− %.n
928− ~zod/try=> (aor "foo" "bar")
929− %.n
930− ~zod/try=> (aor "bar" "foo")
931− %.y
932− ~zod/try=> (aor "abcdefz" "abcdefa")
933− %.n
934− ~zod/try=> (aor "abcdefa" "abcdefz")
935− %.y
936− ~zod/try=> (aor 10.000 17.000)
937− %.y
938− ~zod/try=> (aor 10 9)
939− %.n
940−
941−------------------------------------------------------------------------
942−
943−### `++dor`
944−
945−Numeric order
946−
947−Computes whether `a` and `b` are in ascending numeric order, producing a
948−boolean.
949−
950−Accepts
951−-------
952−
953−`a` is a [noun]().
954−
955−`b` is a noun.
956−
957−Produces
958−--------
959−
960−A boolean atom.
961−
962−Source
963−------
964−
965− ++ dor :: d-order
966− ~/ %dor
967− |= [a=* b=*]
968− ^- ?
969− ?: =(a b) &
970− ?. ?=(@ a)
971− ?: ?=(@ b) |
972− ?: =(-.a -.b)
973− $(a +.a, b +.b)
974− $(a -.a, b -.b)
975− ?. ?=(@ b) &
976− (lth a b)
977−
978−Examples
979−--------
980−
981− ~zod/try=> (dor 1 2)
982− %.y
983− ~zod/try=> (dor 2 1)
984− %.n
985− ~zod/try=> (dor ~[1 2 3] ~[1 2 4])
986− %.y
987− ~zod/try=> (dor ~[1 2 4] ~[1 2 3])
988− %.n
989− ~zod/try=> (dor (limo ~[99 100 10.000]) ~[99 101 10.000])
990− %.y
991− ~zod/try=> (dor ~[99 101 10.999] (limo ~[99 100 10.000]))
992− %.n
993−
994−------------------------------------------------------------------------
995−
996−### `++gor`
997−
998−Hash order
999−
1000−XX revisit
1001−
1002−Accepts
1003−-------
1004−
1005−`a` is a [noun]().
1006−
1007−`b` is a noun.
1008−
1009−Produces
1010−--------
1011−
1012−A boolean [atom]().
1013−
1014−Source
1015−------
1016−
1017− ++ gor :: g-order
1018− ~/ %gor
1019− |= [a=* b=*]
1020− ^- ?
1021− =+ [c=(mug a) d=(mug b)]
1022− ?: =(c d)
1023− (dor a b)
1024− (lth c d)
1025−
1026−Examples
1027−--------
1028−
1029− ~zod/try=> (gor 'd' 'c')
1030− %.y
1031− ~zod/try=> 'd'
1032− 'd'
1033− ~zod/try=> 'c'
1034− ~zod/try=> `@ud`'d'
1035− 100
1036− ~zod/try=> `@ud`'c'
1037− 99
1038− ~zod/try=> (mug 'd')
1039− 1.628.185.714
1040− ~zod/try=> (mug 'c')
1041− 1.712.073.811
1042− ~zod/try=> (gor 'd' 'c')
1043− %.y
1044− ~zod/try=> (gor 'c' 'd')
1045− %.n
1046− ~zod/try=> (gor "foo" "bar")
1047− %.n
1048− ~zod/try=> (gor (some 10) (limo [1 2 3 ~]))
1049− %.n
1050−
1051−------------------------------------------------------------------------
1052−
1053−### `++hor`
1054−
1055−Hash order
1056−
1057−XX revisit
1058−
1059−Recursive hash comparator gate.
1060−
1061−Accepts
1062−-------
1063−
1064−`a` is a [noun]().
1065−
1066−`b` is a noun.
1067−
1068−Produces
1069−--------
1070−
1071−A boolean [atom]().
1072−
1073−
1074−Source
1075−------
1076−
1077− ++ hor :: h-order
1078− ~/ %hor
1079− |= [a=* b=*]
1080− ^- ?
1081− ?: ?=(@ a)
1082− ?. ?=(@ b) &
1083− (gor a b)
1084− ?: ?=(@ b) |
1085− ?: =(-.a -.b)
1086− (gor +.a +.b)
1087− (gor -.a -.b)
1088−
1089−Examples
1090−--------
1091−
1092− ~zod/try=> (hor . 1)
1093− %.n
1094− ~zod/try=> (hor 1 2)
1095− %.y
1096− ~zod/try=> (hor "abc" "cba")
1097− %.y
1098− ~zod/try=> (hor 'c' 'd')
1099− %.n
1100−
1101−------------------------------------------------------------------------
1102−
1103−### `++vor`
1104−
1105−Double hash comparator gate.
1106−
1107−XX revisit
1108−
1109−Accepts
1110−-------
1111−
1112−`a` is a [noun]()
1113−
1114−`b` is a noun
1115−
1116−Produces
1117−-------
1118−
1119−Source
1120−------
1121−
1122− ++ vor :: v-order
1123− ~/ %vor
1124− |= [a=* b=*]
1125− ^- ?
1126− =+ [c=(mug (mug a)) d=(mug (mug b))]
1127− ?: =(c d)
1128− (dor a b)
1129− (lth c d)
1130−
1131−Examples
1132−--------
1133−
1134− ~zod/try=> (vor 'f' 'g')
1135− %.y
1136− ~zod/try=> (vor 'a' 'z')
1137− %.n
1138− ~zod/try=> (vor 43.326 41.106)
1139− %.n
1140−
1141−section 2cD, insecure hashing
1142−-----------------------------
1143−
1144−### `++fnv`
1145−
1146−Hashes an atom with the 32-bit FNV non-cryptographic hash algorithm.
1147−Multiplies `a` by the prime number 16,777,619 and then takes the block
1148−of size 5 off the product's end, producing an [atom]().
1149−
1150−Accepts
1151−-------
1152−
1153−`a` is an atom.
1154−
1155−Produces
1156−--------
1157−
1158−An atom.
1159−
1160−
1161−Source
1162−------
1163−
1164− ++ fnv |=(a=@ (end 5 1 (mul 16.777.619 a))) :: FNV scrambler
1165−
1166−Examples
1167−--------
1168−
1169− ~zod/try=> (fnv 10.000)
1170− 272.465.456
1171− ~zod/try=> (fnv 10.001)
1172− 289.243.075
1173− ~zod/try=> (fnv 1)
1174− 16.777.619
1175−
1176−------------------------------------------------------------------------
1177−
1178−### `++mum`
1179−
1180−XX document
1181−
1182−Accepts
1183−-------
1184−
1185−Produces
1186−--------
1187−
1188−Source
1189−------
1190−
1191− ++ mum :: mug with murmur3
1192− ~/ %mum
1193− |= a=*
1194− |^ (trim ?@(a a (mix $(a -.a) (mix 0x7fff.ffff $(a +.a)))))
1195− ++ spec :: standard murmur3
1196− |= [syd=@ key=@]
1197− ?> (lte (met 5 syd) 1)
1198− =+ ^= row
1199− |= [a=@ b=@]
1200− (con (end 5 1 (lsh 0 a b)) (rsh 0 (sub 32 a) b))
1201− =+ mow=|=([a=@ b=@] (end 5 1 (mul a b)))
1202− =+ len=(met 5 key)
1203− =- =. goc (mix goc len)
1204− =. goc (mix goc (rsh 4 1 goc))
1205− =. goc (mow goc 0x85eb.ca6b)
1206− =. goc (mix goc (rsh 0 13 goc))
1207− =. goc (mow goc 0xc2b2.ae35)
1208− (mix goc (rsh 4 1 goc))
1209− ^= goc
1210− =+ [inx=0 goc=syd]
1211− |- ^- @
1212− ?: =(inx len) goc
1213− =+ kop=(cut 5 [inx 1] key)
1214− =. kop (mow kop 0xcc9e.2d51)
1215− =. kop (row 15 kop)
1216− =. kop (mow kop 0x1b87.3593)
1217− =. goc (mix kop goc)
1218− =. goc (row 13 goc)
1219− =. goc (end 5 1 (add 0xe654.6b64 (mul 5 goc)))
1220− $(inx +(inx))
1221− ::
1222− ++ trim :: 31-bit nonzero
1223− |= key=@
1224− =+ syd=0xcafe.babe
1225− |- ^- @
1226− =+ haz=(spec syd key)
1227− =+ ham=(mix (rsh 0 31 haz) (end 0 31 haz))
1228− ?.(=(0 ham) ham $(syd +(syd)))
1229− --
1230− ::
1231−
1232−Examples
1233−--------
1234−
1235− ~zod/try=> (mum 10.000)
1236− 1.232.632.901
1237− ~zod/try=> (mum 10.001)
1238− 658.093.079
1239− ~zod/try=> (mum 1)
1240− 818.387.364
1241− ~zod/try=> (mum (some 10))
1242− 1.177.215.703
1243− ~zod/try=> (mum ~[1 2 3 4 5])
1244− 1.517.902.092
1245−
1246−### `++mug`
1247−
1248−Hashes `a` with the 31-bit nonzero FNV-1a non-cryptographic hash
1249−algorithm, producing an [atom]().
1250−
1251−Accepts
1252−-------
1253−
1254−A is a [noun]().
1255−
1256−Produces
1257−--------
1258−
1259−An atom.
1260−
1261−Source
1262−------
1263−
1264− ++ mug :: 31bit nonzero FNV1a
1265− ~/ %mug
1266− |= a=*
1267− ?^ a
1268− =+ b=[p=$(a -.a) q=$(a +.a)]
1269− |- ^- @
1270− =+ c=(fnv (mix p.b (fnv q.b)))
1271− =+ d=(mix (rsh 0 31 c) (end 0 31 c))
1272− ?. =(0 c) c
1273− $(q.b +(q.b))
1274− =+ b=2.166.136.261
1275− |- ^- @
1276− =+ c=b
1277− =+ [d=0 e=(met 3 a)]
1278− |- ^- @
1279− ?: =(d e)
1280− =+ f=(mix (rsh 0 31 c) (end 0 31 c))
1281− ?. =(0 f) f
1282− ^$(b +(b))
1283− $(c (fnv (mix c (cut 3 [d 1] a))), d +(d))
1284−
1285−Examples
1286−--------
1287−
1288− ~zod/try=> (mug 10.000)
1289− 178.152.889
1290− ~zod/try=> (mug 10.001)
1291− 714.838.017
1292− ~zod/try=> (mug 1)
1293− 67.918.732
1294− ~zod/try=> (mug (some 10))
1295− 1.872.403.737
1296− ~zod/try=> (mug (limo [1 2 3 4 5 ~]))
1297− 1.067.931.605
1298−
1299−section 2cE, phonetic base
1300−--------------------------
1301−
1302−### `++po`
1303−
1304−++ po
1305− ~/ %po
1306− =+ :- ^= sis :: prefix syllables
1307− 'dozmarbinwansamlitsighidfidlissogdirwacsabwissib\
1308− /rigsoldopmodfoglidhopdardorlorhodfolrintogsilmir\
1309− /holpaslacrovlivdalsatlibtabhanticpidtorbolfosdot\
1310− /losdilforpilramtirwintadbicdifrocwidbisdasmidlop\
1311− /rilnardapmolsanlocnovsitnidtipsicropwitnatpanmin\
1312− /ritpodmottamtolsavposnapnopsomfinfonbanporworsip\
1313− /ronnorbotwicsocwatdolmagpicdavbidbaltimtasmallig\
1314− /sivtagpadsaldivdactansidfabtarmonranniswolmispal\
1315− /lasdismaprabtobrollatlonnodnavfignomnibpagsopral\
1316− /bilhaddocridmocpacravripfaltodtiltinhapmicfanpat\
1317− /taclabmogsimsonpinlomrictapfirhasbosbatpochactid\
1318− /havsaplindibhosdabbitbarracparloddosbortochilmac\
1319− /tomdigfilfasmithobharmighinradmashalraglagfadtop\
1320− /mophabnilnosmilfopfamdatnoldinhatnacrisfotribhoc\
1321− /nimlarfitwalrapsarnalmoslandondanladdovrivbacpol\
1322− /laptalpitnambonrostonfodponsovnocsorlavmatmipfap'
1323− ^= dex :: suffix syllables
1324− 'zodnecbudwessevpersutletfulpensytdurwepserwylsun\
1325− /rypsyxdyrnuphebpeglupdepdysputlughecryttyvsydnex\
1326− /lunmeplutseppesdelsulpedtemledtulmetwenbynhexfeb\
1327− /pyldulhetmevruttylwydtepbesdexsefwycburderneppur\
1328− /rysrebdennutsubpetrulsynregtydsupsemwynrecmegnet\
1329− /secmulnymtevwebsummutnyxrextebfushepbenmuswyxsym\
1330− /selrucdecwexsyrwetdylmynmesdetbetbeltuxtugmyrpel\
1331− /syptermebsetdutdegtexsurfeltudnuxruxrenwytnubmed\
1332− /lytdusnebrumtynseglyxpunresredfunrevrefmectedrus\
1333− /bexlebduxrynnumpyxrygryxfeptyrtustyclegnemfermer\
1334− /tenlusnussyltecmexpubrymtucfyllepdebbermughuttun\
1335− /bylsudpemdevlurdefbusbeprunmelpexdytbyttyplevmyl\
1336− /wedducfurfexnulluclennerlexrupnedlecrydlydfenwel\
1337− /nydhusrelrudneshesfetdesretdunlernyrsebhulryllud\
1338− /remlysfynwerrycsugnysnyllyndyndemluxfedsedbecmun\
1339− /lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes'
1340− |%
1341−
1342−Provides the phonetic syllables and name generators for the Urbit naming
1343−system. The two faces, `sis` and `dex` are available to the arms
1344−contained in this section.
1345−
1346−------------------------------------------------------------------------
1347−
1348−### `++ind`
1349−
1350−Parse prefix
1351−
1352−Produces the byte of the right-hand syllable `a`.
1353−
1354−Accepts
1355−-------
1356−
1357−`a` is an [atom]().
1358−
1359−Produces
1360−--------
1361−
1362−A [`++unit`]() of an atom.
1363−
1364−Source
1365−------
1366−
1367− ++ ind ~/ %ind :: parse prefix
1368− |= a=@
1369− =+ b=0
1370− |- ^- (unit ,@)
1371− ?:(=(256 b) ~ ?:(=(a (tod b)) [~ b] $(b +(b))))
1372−
1373−Examples
1374−--------
1375−
1376− ~zod/try=> (ind:po 'zod')
1377− [~ 0]
1378− ~zod/try=> (ind:po 'zam')
1379− ~
1380− ~zod/try=> (ind:po 'del')
1381− [~ 37]
1382−
1383−------------------------------------------------------------------------
1384−
1385−### `++ins`
1386−
1387−Parse suffix
1388−
1389−Produces the byte of the left-hand phonetic syllable `b`.
1390−
1391−Accepts
1392−-------
1393−
1394−`a` is an [atom]().
1395−
1396−Produces
1397−--------
1398−A [`++unit`]() of an atom.
1399−
1400−Source
1401−------
1402−
1403− ++ ins ~/ %ins :: parse suffix
1404− |= a=@
1405− =+ b=0
1406− |- ^- (unit ,@)
1407− ?:(=(256 b) ~ ?:(=(a (tos b)) [~ b] $(b +(b))))
1408−
1409−Examples
1410−--------
1411−
1412− ~zod/try=> (ins:po 'mar')
1413− [~ 1]
1414− ~zod/try=> (ins:po 'son')
1415− [~ 164]
1416− ~zod/try=> (ins:po 'pit')
1417− [~ 242]
1418− ~zod/try=> (ins:po 'pok')
1419− ~
1420−
1421−------------------------------------------------------------------------
1422−
1423−### `++tod`
1424−
1425−Fetch prefix
1426−
1427−Produces the phonetic prefix syllable from index `a` within `dex` as an
1428−[atom]().
1429−
1430−Accepts
1431−-------
1432−
1433−`a` is an atom
1434−
1435−Produces
1436−--------
1437−
1438−An atom.
1439−
1440−
1441−Source
1442−------
1443−
1444− ++ tod ~/ %tod :: fetch prefix
1445− |=(a=@ ?>((lth a 256) (cut 3 [(mul 3 a) 3] dex)))
1446−
1447−Examples
1448−--------
1449−
1450− ~zod/try=> `@t`(tod:po 1)
1451− 'nec'
1452− ~zod/try=> `@t`(tod:po 98)
1453− 'dec'
1454− ~zod/try=> `@t`(tod:po 0)
1455− 'zod'
1456− ~zod/try=> `@t`(tod:po 150)
1457− 'ryg'
1458− ~zod/try=> `@t`(tod:po 255)
1459− 'fes'
1460− ~zod/try=> `@t`(tod:po 256)
1461− ! exit
1462−
1463−------------------------------------------------------------------------
1464−
1465−### `++tos`
1466−
1467−Fetch suffix
1468−
1469−Produces the phonetic prefix syllable from index `a` within `sis` as an
1470−[atom]().
1471−
1472−Accepts
1473−-------
1474−
1475−`a` is an atom.
1476−
1477−Produces
1478−--------
1479−
1480−An atom.
1481−
1482−Source
1483−------
1484−
1485− ++ tos ~/ %tos :: fetch suffix
1486− |=(a=@ ?>((lth a 256) (cut 3 [(mul 3 a) 3] sis)))
1487−
1488−Examples
1489−--------
1490−
1491− ~zod/try=> `@t`(tos:po 0)
1492− 'doz'
1493− ~zod/try=> `@t`(tos:po 120)
1494− 'fab'
1495− ~zod/try=> `@t`(tos:po 43)
1496− 'pid'
1497− ~zod/try=> `@t`(tos:po 253)
1498− 'mat'
1499−
1500−------------------------------------------------------------------------
1501−
1502−section 2cF, signed and modular ints
1503−------------------------------------
1504−
1505−### `++si`
1506−
1507− ++ si !: :: signed integer
1508− |%
1509−
1510−Container core for the signed integer functions.
1511−
1512−------------------------------------------------------------------------
1513−
1514−### `++abs`
1515−
1516−Absolute value
1517−
1518−Produces the absolute value of a signed integer.
1519−
1520−Accepts
1521−-------
1522−
1523−`a` is a signed integer, [`@s`]().
1524−
1525−Produces
1526−--------
1527−
1528−An [atom]().
1529−
1530−Source
1531−------
1532−
1533− ++ abs |=(a=@s (add (end 0 1 a) (rsh 0 1 a))) :: absolute value
1534−
1535−Examples
1536−--------
1537−
1538− ~zod/try=> (abs:si -2)
1539− 2
1540− ~zod/try=> (abs:si -10.000)
1541− 10.000
1542− ~zod/try=> (abs:si --2)
1543− 2
1544−
1545−------------------------------------------------------------------------
1546−
1547−### `++dif`
1548−
1549−Difference
1550−
1551−Produces the difference between two signed integers `b` and `c`.
1552−
1553−Accepts
1554−-------
1555−
1556−`a` is a signed integer, [`@s`]().
1557−
1558−`b` is a signed integer, `@s`.
1559−
1560−Produces
1561−--------
1562−
1563−A [`@s`]().
1564−
1565−
1566−Source
1567−------
1568−
1569− ++ dif |= [a=@s b=@s] :: subtraction
1570− (sum a (new !(syn b) (abs b)))
1571−
1572−Examples
1573−--------
1574−
1575− ~zod/try=> (dif:si --10 -7)
1576− --17
1577− ~zod/try=> (dif:si --10 --7)
1578− --3
1579− ~zod/try=> (dif:si `@s`0 --7)
1580− -7
1581− ~zod/try=> (dif:si `@s`0 `@s`7)
1582− --4
1583−
1584−------------------------------------------------------------------------
1585−
1586−### `++dul`
1587−
1588−Modulus
1589−
1590−Produces the modulus of two signed integers.
1591−
1592−Accepts
1593−-------
1594−
1595−`a` is a signed integer, `@s`.
1596−
1597−`b` is an [atom]().
1598−
1599−Produces
1600−--------
1601−
1602−An atom.
1603−
1604−Source
1605−------
1606−
1607− ++ dul |= [a=@s b=@] :: modulus
1608− =+(c=(old a) ?:(-.c (mod +.c b) (sub b +.c)))
1609−
1610−Examples
1611−--------
1612−
1613− ~zod/try=> (dul:si --9 3)
1614− 0
1615− ~zod/try=> (dul:si --9 4)
1616− 1
1617− ~zod/try=> (dul:si --9 5)
1618− 4
1619− ~zod/try=> (dul:si --9 6)
1620− 3
1621− ~zod/try=> (dul:si --90 --10)
1622− 10
1623−
1624−------------------------------------------------------------------------
1625−
1626−### `++fra`
1627−
1628−Divide
1629−
1630−Produces the quotient of two signed integers.
1631−
1632−Accepts
1633−-------
1634−
1635−`a` is a signed integer, [`@s`].
1636−
1637−`b` is a signed integer, `@s`.
1638−
1639−Produces
1640−--------
1641−
1642−An [atom]().
1643−
1644−Source
1645−------
1646−
1647− ++ fra |= [a=@s b=@s] :: divide
1648− (new =(0 (mix (syn a) (syn b))) (div (abs a) (abs b)))
1649−
1650−Examples
1651−--------
1652−
1653− ~zod/try=> (fra:si --10 -2)
1654− -5
1655− ~zod/try=> (fra:si -20 -5)
1656− --4
1657−
1658−------------------------------------------------------------------------
1659−
1660−### `++new`
1661−
1662−Signed integer
1663−
1664−Produces a signed integer from a loobean sign value `a` and an [atom]() `b`.
1665−
1666−Accepts
1667−-------
1668−
1669−`a` is a loobean.
1670−
1671−`b` is an atom.
1672−
1673−Produces
1674−--------
1675−
1676−A [`@s`]()
1677−
1678−Source
1679−------
1680−
1681− ++ new |= [a=? b=@] :: [sign value] to @s
1682− `@s`?:(a (mul 2 b) ?:(=(0 b) 0 +((mul 2 (dec b)))))
1683−
1684−Examples
1685−--------
1686−
1687− ~zod/try=> (new:si [& 10])
1688− --10
1689− ~zod/try=> (new:si [| 10])
1690− -10
1691− ~zod/try=> (new:si [%.y 7])
1692− --7
1693−
1694−------------------------------------------------------------------------
1695−
1696−### `++old`
1697−
1698−[sign value]
1699−
1700−Produces the cell `[sign value]` representations of a signed integer.
1701−
1702−Accepts
1703−-------
1704−
1705−`a` is a [`@s`]().
1706−
1707−Produces
1708−--------
1709−
1710−A cell of a boolean and an [atom]().
1711−
1712−Source
1713−------
1714−
1715− ++ old |=(a=@s [(syn a) (abs a)]) :: [sign value]
1716−
1717−Examples
1718−--------
1719−
1720− ~zod/try=> (old:si 7)
1721− ! type-fail
1722− ! exit
1723− ~zod/try=> (old:si -7)
1724− [%.n 7]
1725− ~zod/try=> (old:si --7)
1726− [%.y 7]
1727− ~zod/try=> (old:si `@s`7)
1728− [%.n 4]
1729− ~zod/try=> (old:si -0)
1730− [%.y 0]
1731−
1732−------------------------------------------------------------------------
1733−
1734−### `++pro`
1735−
1736−Multiply
1737−
1738−Produces the product of two signed integers.
1739−
1740−Accepts
1741−-------
1742−
1743−`a` is a [`@s`]().
1744−
1745−`b` is a `@s`.
1746−
1747−Produces
1748−--------
1749−
1750−A `@s`.
1751−
1752−Source
1753−------
1754−
1755− ++ pro |= [a=@s b=@s] :: multiplication
1756− (new =(0 (mix (syn a) (syn b))) (mul (abs a) (abs b)))
1757−
1758−Examples
1759−--------
1760−
1761− ~zod/try=> (pro:si -4 --2)
1762− -8
1763− ~zod/try=> (pro:si -4 -2)
1764− --8
1765− ~zod/try=> (pro:si --10.000.000 -10)
1766− -100.000.000
1767− ~zod/try=> (pro:si -1.337 --0)
1768− --0
1769−
1770−------------------------------------------------------------------------
1771−
1772−### `++rem`
1773−
1774−Remainder
1775−
1776−Produces the remainder from a division of two signed integers.
1777−
1778−Accepts
1779−-------
1780−
1781−`a` is a [`@s`]().
1782−
1783−`b` is a `@s`.
1784−
1785−Produces
1786−--------
1787−
1788−A `@sd`.
1789−
1790−Source
1791−------
1792−
1793− ++ rem |=([a=@s b=@s] (dif a (pro b (fra a b)))) :: remainder
1794−
1795−Examples
1796−--------
1797−
1798− ~zod/try=> (rem:si -10 -4)
1799− -2
1800− ~zod/try=> (rem:si --10 --4)
1801− --2
1802− ~zod/try=> (rem:si --10 -4)
1803− --2
1804− ~zod/try=> (rem:si --7 --3)
1805− --1
1806− ~zod/try=> (rem:si --0 --10.000)
1807− --0
1808−
1809−------------------------------------------------------------------------
1810−
1811−### `++sum`
1812−
1813−Add
1814−
1815−Sum two signed integers.
1816−
1817−Accepts
1818−-------
1819−
1820−`b` is a [`@s`]().
1821−
1822−`c` is a signed integer `@s`.
1823−
1824−Produces
1825−--------
1826−
1827−A `@s`.
1828−
1829−Source
1830−------
1831−
1832− ++ sum |= [a=@s b=@s] :: addition
1833− ~| %si-sum
1834− =+ [c=(old a) d=(old b)]
1835− ?: -.c
1836− ?: -.d
1837− (new & (add +.c +.d))
1838− ?: (gte +.c +.d)
1839− (new & (sub +.c +.d))
1840− (new | (sub +.d +.c))
1841− ?: -.d
1842− ?: (gte +.c +.d)
1843− (new | (sub +.c +.d))
1844− (new & (sub +.d +.c))
1845− (new | (add +.c +.d))
1846−
1847−Examples
1848−--------
1849−
1850− ~zod/try=> (sum:si --10 --10)
1851− --20
1852− ~zod/try=> (sum:si --10 -0)
1853− --10
1854− ~zod/try=> (sum:si -10 -7)
1855− -17
1856− ~zod/try=> (sum:si -10 --7)
1857− -3
1858−
1859−------------------------------------------------------------------------
1860−
1861−### `++sun`
1862−
1863−Signed from unsigned
1864−
1865−Produces a signed integer from an unsigned integer.
1866−
1867−Note that the result must be manually cast to some [`@s`]() odor to be
1868−inferred as an unsigned integer in the type system.
1869−
1870−Accepts
1871−-------
1872−
1873−`a` is a [`@u`]().
1874−
1875−Produces
1876−--------
1877−
1878−A [`@s`]().
1879−
1880−Source
1881−------
1882−
1883− ++ sun |=(a=@u (mul 2 a)) :: @u to @s
1884−
1885−Examples
1886−--------
1887−
1888− ~zod/try=> `@s`10
1889− --5
1890− ~zod/try=> (sun:si 10)
1891− 20
1892− ~zod/try=> `@s`(sun:si 10)
1893− --10
1894− ~zod/try=> `@sd`(sun:si 10)
1895− --10
1896− ~zod/try=> `@sd`(sun:si 12.345)
1897− --12.345
1898−
1899−------------------------------------------------------------------------
1900−
1901−### `++syn`
1902−
1903−Sign
1904−
1905−Produce the sign of a signed integer, where `&` is posiitve, and `|` is negative.
1906−
1907−Accepts
1908−-------
1909−
1910−`a` is a [`@s`]().
1911−
1912−Produces
1913−--------
1914−
1915−A boolean.
1916−
1917−Source
1918−------
1919−
1920− ++ syn |=(a=@s =(0 (end 0 1 a))) :: sign test
1921−
1922−Examples
1923−--------
1924−
1925− ~zod/try=> (syn:si -2)
1926− %.n
1927− ~zod/try=> (syn:si --2)
1928− %.y
1929− ~zod/try=> (syn:si -0)
1930− %.y
1931−
1932−------------------------------------------------------------------------
1933−
1934−### `++cmp`
1935−
1936−Compare
1937−
1938−Compare two signed integers.
1939−
1940−Accepts
1941−-------
1942−
1943−`b` is a [`@s`]().
1944−
1945−`c` is a `@s`.
1946−
1947−Produces
1948−--------
1949−
1950−A `@s`.
1951−
1952−Source
1953−------
1954−
1955− ++ cmp |= [a=@s b=@s] :: compare
1956− ^- @s
1957− ?: =(a b)
1958− --0
1959− ?: (syn a)
1960− ?: (syn b)
1961− ?: (gth a b)
1962− --1
1963− -1
1964− --1
1965− ?: (syn b)
1966− -1
1967− ?: (gth a b)
1968− -1
1969− --1
1970−
1971−Examples
1972−--------
1973−
1974− ~zod/try=> (cmp:si --10 --10)
1975− --0
1976− ~zod/try=> (cmp:si --10 -0)
1977− --1
1978− ~zod/try=> (cmp:si -10 -7)
1979− -1
1980− ~zod/try=> (cmp:si -10 --7)
1981− -1
1982−
1983−
1984−### `++fe` :: modulo bloq
1985−
1986−Modulo bloq
1987−
1988−Core containing XX
1989−
1990−Accepts
1991−-------
1992−
1993−`a` is a [`++bloq`]().
1994−
1995−Source
1996−------
1997−
1998− |_ a=bloq
1999−
2000−### `++dif`
2001−
2002−Produces the difference between two [atom]()s in the modular basis
2003−representation.
2004−
2005−Accepts
2006−-------
2007−
2008−`a` is a [`++bloq`]().
2009−
2010−`b` is an atom.
2011−
2012−`c` is an atom.
2013−
2014−Produces
2015−--------
2016−
2017−A [`@s`]()
2018−
2019−Source
2020−------
2021−
2022− ++ dif |=([b=@ c=@] (sit (sub (add out (sit b)) (sit c))))
2023−
2024−Examples
2025−--------
2026−
2027− ~zod/try=> (~(dif fe 3) 63 64)
2028− 255
2029− ~zod/try=> (~(dif fe 3) 5 10)
2030− 251
2031− ~zod/try=> (~(dif fe 3) 0 1)
2032− 255
2033− ~zod/try=> (~(dif fe 0) 9 10)
2034− 1
2035− ~zod/try=> (~(dif fe 0) 9 11)
2036− 0
2037− ~zod/try=> (~(dif fe 0) 9 12)
2038− 1
2039− ~zod/try=> (~(dif fe 2) 9 12)
2040− 13
2041− ~zod/try=> (~(dif fe 2) 63 64)
2042− 15
2043−
2044−------------------------------------------------------------------------
2045−
2046−### `++inv`
2047−
2048−Invert mod field
2049−
2050−Inverts the order of the modular field.
2051−
2052−Accepts
2053−-------
2054−
2055−`b` is a [`++bloq`]().
2056−
2057−Produces
2058−--------
2059−
2060−An atom.
2061−
2062−
2063−Source
2064−------
2065−
2066− ++ inv |=(b=@ (sub (dec out) (sit b)))
2067−
2068−Examples
2069−--------
2070−
2071− ~zod/try=> (~(inv fe 3) 255)
2072− 0
2073− ~zod/try=> (~(inv fe 3) 256)
2074− 255
2075− ~zod/try=> (~(inv fe 3) 0)
2076− 255
2077− ~zod/try=> (~(inv fe 3) 1)
2078− 254
2079− ~zod/try=> (~(inv fe 3) 2)
2080− 253
2081− ~zod/try=> (~(inv fe 3) 55)
2082− 200
2083−
2084−------------------------------------------------------------------------
2085−
2086−### `++net`
2087−
2088−Reverse bytes
2089−
2090−Revereses bytes within block.
2091−
2092−Accepts
2093−-------
2094−
2095−`b` is a [`++bloq`]().
2096−
2097−Produces
2098−--------
2099−
2100−An atom.=
2101−
2102−Source
2103−------
2104−
2105− ++ net |= b=@ ^- @
2106− => .(b (sit b))
2107− ?: (lte a 3)
2108− b
2109− =+ c=(dec a)
2110− %+ con
2111− (lsh c 1 $(a c, b (cut c [0 1] b)))
2112− $(a c, b (cut c [1 1] b))
2113−
2114−Examples
2115−--------
2116−
2117− ~zod/try=> (~(net fe 3) 64)
2118− 64
2119− ~zod/try=> (~(net fe 3) 128)
2120− 128
2121− ~zod/try=> (~(net fe 3) 255)
2122− 255
2123− ~zod/try=> (~(net fe 3) 256)
2124− 0
2125− ~zod/try=> (~(net fe 3) 257)
2126− 1
2127− ~zod/try=> (~(net fe 3) 500)
2128− 244
2129− ~zod/try=> (~(net fe 3) 511)
2130− 255
2131− ~zod/try=> (~(net fe 3) 512)
2132− 0
2133− ~zod/try=> (~(net fe 3) 513)
2134− 1
2135− ~zod/try=> (~(net fe 3) 0)
2136− 0
2137− ~zod/try=> (~(net fe 3) 1)
2138− 1
2139− ~zod/try=> (~(net fe 0) 1)
2140− 1
2141− ~zod/try=> (~(net fe 0) 2)
2142− 0
2143− ~zod/try=> (~(net fe 0) 3)
2144− 1
2145− ~zod/try=> (~(net fe 6) 1)
2146− 72.057.594.037.927.936
2147− ~zod/try=> (~(net fe 6) 2)
2148− 144.115.188.075.855.872
2149− ~zod/try=> (~(net fe 6) 3)
2150− 216.172.782.113.783.808
2151− ~zod/try=> (~(net fe 6) 4)
2152− 288.230.376.151.711.744
2153− ~zod/try=> (~(net fe 6) 5)
2154− 360.287.970.189.639.680
2155− ~zod/try=> (~(net fe 6) 6)
2156− 432.345.564.227.567.616
2157− ~zod/try=> (~(net fe 6) 7)
2158− 504.403.158.265.495.552
2159− ~zod/try=> (~(net fe 6) 512)
2160− 562.949.953.421.312
2161− ~zod/try=> (~(net fe 6) 513)
2162− 72.620.543.991.349.248
2163−
2164−------------------------------------------------------------------------
2165−
2166−### `++out`
2167−
2168−Max integer value
2169−
2170−The maximum integer value that the current block can store.
2171−
2172−Accepts
2173−-------
2174−
2175−A [`++bloq`]().
2176−
2177−Produces
2178−--------
2179−
2180−An [atom]().
2181−
2182−Source
2183−------
2184−
2185− ++ out (bex (bex a))
2186−
2187−Examples
2188−--------
2189−
2190− ~zod/try=> ~(out fe 0)
2191− 2
2192− ~zod/try=> ~(out fe 1)
2193− 4
2194− ~zod/try=> ~(out fe 2)
2195− 16
2196− ~zod/try=> ~(out fe 3)
2197− 256
2198− ~zod/try=> ~(out fe 4)
2199− 65.536
2200− ~zod/try=> ~(out fe 10)
2201− \/179.769.313.486.231.590.772.930.519.078.902.473.361.797.697.894.230.657.\/
2202− 273.430.081.157.732.675.805.500.963.132.708.477.322.407.536.021.120.113.
2203− 879.871.393.357.658.789.768.814.416.622.492.847.430.639.474.124.377.767.
2204− 893.424.865.485.276.302.219.601.246.094.119.453.082.952.085.005.768.838.
2205− 150.682.342.462.881.473.913.110.540.827.237.163.350.510.684.586.298.239.
2206− 947.245.938.479.716.304.835.356.329.624.224.137.216
2207− \/ \/
2208−
2209−------------------------------------------------------------------------
2210−
2211−### `++rol`
2212−
2213−Roll left
2214−
2215−Roll `d` to the left by `c` `b`-sized blocks.
2216−
2217−Accepts
2218−-------
2219−
2220−`a` is a [`++bloq`]().
2221−
2222−`b` is a `++bloq`.
2223−
2224−`c` is an atom.
2225−
2226−`d` is an atom.
2227−
2228−Produces
2229−--------
2230−
2231−An atom.
2232−
2233−Source
2234−------
2235−
2236− ++ rol |= [b=bloq c=@ d=@] ^- @ :: roll left
2237− =+ e=(sit d)
2238− =+ f=(bex (sub a b))
2239− =+ g=(mod c f)
2240− (sit (con (lsh b g e) (rsh b (sub f g) e)))
2241−
2242−Examples
2243−--------
2244−
2245− ~zod/try=> `@ux`(~(rol fe 6) 4 3 0xabac.dedf.1213)
2246− 0x1213.0000.abac.dedf
2247− ~zod/try=> `@ux`(~(rol fe 6) 4 2 0xabac.dedf.1213)
2248− 0xdedf.1213.0000.abac
2249− ~zod/try=> `@t`(~(rol fe 5) 3 1 'dfgh')
2250− 'hdfg'
2251− ~zod/try=> `@t`(~(rol fe 5) 3 2 'dfgh')
2252− 'ghdf'
2253− ~zod/try=> `@t`(~(rol fe 5) 3 0 'dfgh')
2254− 'dfgh'
2255−
2256−------------------------------------------------------------------------
2257−
2258−### `++ror`
2259−
2260−Roll right
2261−
2262−Roll `d` to the right by `c` `b`-sized blocks.
2263−
2264−Accepts
2265−-------
2266−
2267−`a` is a [`++bloq`]().
2268−
2269−`b` is a `++bloq`.
2270−
2271−`c` is an [atom]().
2272−
2273−`d` is an atom.
2274−
2275−Produces
2276−--------
2277−
2278−An atom.
2279−
2280−Source
2281−------
2282−
2283− ++ ror |= [b=bloq c=@ d=@] ^- @ :: roll right
2284− =+ e=(sit d)
2285− =+ f=(bex (sub a b))
2286− =+ g=(mod c f)
2287− (sit (con (rsh b g e) (lsh b (sub f g) e)))
2288−
2289−Examples
2290−--------
2291−
2292− ~zod/try=> `@ux`(~(ror fe 6) 4 1 0xabac.dedf.1213)
2293− 0x1213.0000.abac.dedf
2294− ~zod/try=> `@ux`(~(ror fe 6) 3 5 0xabac.dedf.1213)
2295− 0xacde.df12.1300.00ab
2296− ~zod/try=> `@ux`(~(ror fe 6) 3 3 0xabac.dedf.1213)
2297− 0xdf12.1300.00ab.acde
2298− ~zod/try=> `@t`(~(rol fe 5) 3 0 'hijk')
2299− 'hijk'
2300− ~zod/try=> `@t`(~(rol fe 5) 3 1 'hijk')
2301− 'khij'
2302− ~zod/try=> `@t`(~(rol fe 5) 3 2 'hijk')
2303− 'jkhi'
2304−
2305−------------------------------------------------------------------------
2306−
2307−### `++sum`
2308−
2309−Sum
2310−
2311−Sum two numbers in this modular field.
2312−
2313−Accepts
2314−-------
2315−
2316−`a` is a [`++bloq`]().
2317−
2318−`b` is an [atom]().
2319−
2320−`c` is an atom.
2321−
2322−Produces
2323−--------
2324−
2325−An atom.
2326−
2327−Source
2328−------
2329−
2330− ++ sum |=([b=@ c=@] (sit (add b c))) :: wrapping add
2331−
2332−Examples
2333−--------
2334−
2335− ~zod/try=> (~(sum fe 3) 10 250)
2336− 4
2337− ~zod/try=> (~(sum fe 0) 0 1)
2338− 1
2339− ~zod/try=> (~(sum fe 0) 0 2)
2340− 0
2341− ~zod/try=> (~(sum fe 2) 14 2)
2342− 0
2343− ~zod/try=> (~(sum fe 2) 14 3)
2344− 1
2345− ~zod/try=> (~(sum fe 4) 10.000 256)
2346− 10.256
2347− ~zod/try=> (~(sum fe 4) 10.000 100.000)
2348− 44.464
2349−
2350−### `++sit`
2351−
2352−Atom in mod block representation
2353−
2354−Produce an [atom]() in the current modular block representation.
2355−
2356−Accepts
2357−-------
2358−
2359−`a` is a [`++bloq`]().
2360−
2361−`b` is an atom.
2362−
2363−Produces
2364−--------
2365−
2366−An atom.
2367−
2368−Source
2369−------
2370−
2371− ++ sit |=(b=@ (end a 1 b)) :: enforce modulo
2372−
2373−Examples
2374−--------
2375−
2376− ~zod/try=> (~(sit fe 3) 255)
2377− 255
2378− ~zod/try=> (~(sit fe 3) 256)
2379− 0
2380− ~zod/try=> (~(sit fe 3) 257)
2381− 1
2382− ~zod/try=> (~(sit fe 2) 257)
2383− 1
2384− ~zod/try=> (~(sit fe 2) 10.000)
2385− 0
2386− ~zod/try=> (~(sit fe 2) 100)
2387− 4
2388− ~zod/try=> (~(sit fe 2) 19)
2389− 3
2390− ~zod/try=> (~(sit fe 2) 17)
2391− 1
2392− ~zod/try=> (~(sit fe 0) 17)
2393− 1
2394− ~zod/try=> (~(sit fe 0) 0)
2395− 0
2396− ~zod/try=> (~(sit fe 0) 1)
2397− 1
2398−
2399−------------------------------------------------------------------------
2400−
2401−section 2cG, floating point
2402−---------------------------
2403−
2404−XX awaiting interface rewrite
2405−
2406−section 2cH, urbit time
2407−-----------------------
2408−
2409−Note that entering '-\<-' in the shell produces the current time in @da
2410−format. We use this for many of our examples.
2411−
2412− ~zod/try=> -<-
2413− ~2014.8.4..19.39.59..9288
2414−
2415−### `++year`
2416−
2417−Accept a parsed date of form `[[a=? y=@ud] m=@ud t=tarp]` and produce
2418−its `@d`representation.
2419−
2420−Accepts
2421−-------
2422−
2423−`det` is a [`++date`]()
2424−
2425−Produces
2426−--------
2427−
2428−A [`@d`]().
2429−
2430−Source
2431−------
2432−
2433− ++ year :: date to @d
2434− |= det=date
2435− ^- @d
2436− =+ ^= yer
2437− ?: a.det
2438− (add 292.277.024.400 y.det)
2439− (sub 292.277.024.400 (dec y.det))
2440− =+ day=(yawn yer m.det d.t.det)
2441− (yule day h.t.det m.t.det s.t.det f.t.det)
2442−
2443−Examples
2444−--------
2445−
2446− ~zod/try=> (year [[a=%.y y=2.014] m=8 t=[d=4 h=20 m=4 s=57 f=~[0xd940]]])
2447− 0x8000000d227df4e9d940000000000000
2448−
2449−------------------------------------------------------------------------
2450−
2451−### `++yore`
2452−
2453−Produces a `++date` from a `@d`
2454−
2455−Accepts
2456−-------
2457−
2458−`now` is a `@d`.
2459−
2460−Produces
2461−--------
2462−
2463−A [`++date`]().
2464−
2465−Source
2466−------
2467−
2468− ++ yore :: @d to date
2469− |= now=@d
2470− ^- date
2471− =+ rip=(yell now)
2472− =+ ger=(yall d.rip)
2473− :- ?: (gth y.ger 292.277.024.400)
2474− [a=& y=(sub y.ger 292.277.024.400)]
2475− [a=| y=+((sub 292.277.024.400 y.ger))]
2476− [m.ger d.ger h.rip m.rip s.rip f.rip]
2477−
2478−Examples
2479−--------
2480−
2481− ~zod/try=> (yore -<-)
2482− [[a=%.y y=2.014] m=8 t=[d=4 h=20 m=17 s=1 f=~[0x700d]]]
2483− ~zod/try=> (yore -<-)
2484− [[a=%.y y=2.014] m=8 t=[d=4 h=20 m=28 s=53 f=~[0x7b82]]]
2485−
2486−### `++yell`
2487−
2488−Produce a parsed daily time format from an atomic date.
2489−
2490−`now` is a `@d`.
2491−
2492−Source
2493−------
2494−
2495− ++ yell :: tarp from @d
2496− |= now=@d
2497− ^- tarp
2498− =+ sec=(rsh 6 1 now)
2499− =+ ^= fan
2500− =+ [muc=4 raw=(end 6 1 now)]
2501− |- ^- (list ,@ux)
2502− ?: |(=(0 raw) =(0 muc))
2503− ~
2504− => .(muc (dec muc))
2505− [(cut 4 [muc 1] raw) $(raw (end 4 muc raw))]
2506− =+ day=(div sec day:yo)
2507− => .(sec (mod sec day:yo))
2508− =+ hor=(div sec hor:yo)
2509− => .(sec (mod sec hor:yo))
2510− =+ mit=(div sec mit:yo)
2511− => .(sec (mod sec mit:yo))
2512− [day hor mit sec fan]
2513−
2514−Examples
2515−--------
2516−
2517− ~zod/try=> (yell ~2014.3.20..05.42.53..7456)
2518− [d=106.751.991.820.094 h=5 m=42 s=53 f=~[0x7456]]
2519− ~zod/try=> (yell ~2014.6.9..19.09.40..8b66)
2520− [d=106.751.991.820.175 h=19 m=9 s=40 f=~[0x8b66]]
2521− ~zod/try=> (yell ~1776.7.4)
2522− [d=106.751.991.733.273 h=0 m=0 s=0 f=~]
2523−
2524−------------------------------------------------------------------------
2525−
2526−### `++yule`
2527−
2528−Daily time to time atom
2529−
2530−Accept a [`++tarp`](/doc/hoon/library/1#++tarp), a parsed daily time, and produces a time atom,
2531−`@d`.
2532−
2533−Accepts
2534−-------
2535−
2536−`rip` is a [`++tarp`](/doc/hoon/library/1#++tarp).
2537−
2538−Produces
2539−--------
2540−
2541−A [`@d`]().
2542−
2543−Source
2544−------
2545−
2546− ++ yule :: time atom
2547− |= rip=tarp
2548− ^- @d
2549− =+ ^= sec ;: add
2550− (mul d.rip day:yo)
2551− (mul h.rip hor:yo)
2552− (mul m.rip mit:yo)
2553− s.rip
2554− ==
2555− =+ ^= fac =+ muc=4
2556− |- ^- @
2557− ?~ f.rip
2558− 0
2559− => .(muc (dec muc))
2560− (add (lsh 4 muc i.f.rip) $(f.rip t.f.rip))
2561− (con (lsh 6 1 sec) fac)
2562−
2563−Examples
2564−--------
2565−
2566− ~zod/try=> =murica (yell ~1776.7.4)
2567− ~zod/try=> murica
2568− [d=106.751.991.733.273 h=0 m=0 s=0 f=~]
2569− ~zod/try=> (yule murica)
2570− 0x8000000b62aaf5800000000000000000
2571− ~zod/try=> `@da`(yule murica)
2572− ~1776.7.4
2573− ~zod/try=> `@da`(yule (yell ~2014.3.20..05.42.53..7456))
2574− ~2014.3.20..05.42.53..7456
2575− ~zod/try=> `tarp`[31 12 30 0 ~]
2576− [d=31 h=12 m=30 s=0 f=~]
2577− ~zod/try=> `@dr`(yule `tarp`[31 12 30 0 ~])
2578− ~d31.h12.m30
2579−
2580−------------------------------------------------------------------------
2581−
2582−### `++yall`
2583−
2584−Time since beginning of time
2585−
2586−Produce the date tuple of `[y=@ud m=@ud d=@ud]` of the year, month, and
2587−day from a number of days from the beginning of time.
2588−
2589−Accepts
2590−-------
2591−
2592−`day` is a [`@ud`]()
2593−
2594−Produces
2595−--------
2596−
2597−
2598−Source
2599−------
2600−
2601− ++ yall :: day # to day of year
2602− |= day=@ud
2603− ^- [y=@ud m=@ud d=@ud]
2604− =+ [era=0 cet=0 lep=_?]
2605− => .(era (div day era:yo), day (mod day era:yo))
2606− => ^+ .
2607− ?: (lth day +(cet:yo))
2608− .(lep &, cet 0)
2609− => .(lep |, cet 1, day (sub day +(cet:yo)))
2610− .(cet (add cet (div day cet:yo)), day (mod day cet:yo))
2611− =+ yer=(add (mul 400 era) (mul 100 cet))
2612− |- ^- [y=@ud m=@ud d=@ud]
2613− =+ dis=?:(lep 366 365)
2614− ?. (lth day dis)
2615− =+ ner=+(yer)
2616− $(yer ner, day (sub day dis), lep =(0 (end 0 2 ner)))
2617− |- ^- [y=@ud m=@ud d=@ud]
2618− =+ [mot=0 cah=?:(lep moy:yo moh:yo)]
2619− |- ^- [y=@ud m=@ud d=@ud]
2620− =+ zis=(snag mot cah)
2621− ?: (lth day zis)
2622− [yer +(mot) +(day)]
2623− $(mot +(mot), day (sub day zis))
2624−
2625−Examples
2626−--------
2627−
2628− ~zod/try=> (yall 198)
2629− [y=0 m=7 d=17]
2630− ~zod/try=> (yall 90.398)
2631− [y=247 m=7 d=3]
2632− ~zod/try=> (yall 0)
2633− [y=0 m=1 d=1]
2634−
2635−------------------------------------------------------------------------
2636−
2637−### `++yawn`
2638−
2639−Days since beginning of time
2640−
2641−Inverse of `yall`, computes number of days A.D. from y/m/d date as the
2642−tuple `[yer=@ud mot=@ud day=@ud]`.
2643−
2644−Accepts
2645−-------
2646−
2647−`yer` is an unsigned decimal, `@ud`.
2648−
2649−`mon` is an unsigned decimal, `@ud`.
2650−
2651−`day` is an unsigned decimal, `@ud`.
2652−
2653−Produces
2654−--------
2655−
2656−A [`@ud`]().
2657−
2658−Source
2659−------
2660−
2661− ++ yawn :: days since Jesus
2662− |= [yer=@ud mot=@ud day=@ud]
2663− ^- @ud
2664− => .(mot (dec mot), day (dec day))
2665− => ^+ .
2666− %= .
2667− day
2668− =+ cah=?:((yelp yer) moy:yo moh:yo)
2669− |- ^- @ud
2670− ?: =(0 mot)
2671− day
2672− $(mot (dec mot), cah (slag 1 cah), day (add day (snag 0 cah)))
2673− ==
2674− |- ^- @ud
2675− ?. =(0 (mod yer 4))
2676− =+ ney=(dec yer)
2677− $(yer ney, day (add day ?:((yelp ney) 366 365)))
2678− ?. =(0 (mod yer 100))
2679− =+ nef=(sub yer 4)
2680− $(yer nef, day (add day ?:((yelp nef) 1.461 1.460)))
2681− ?. =(0 (mod yer 400))
2682− =+ nec=(sub yer 100)
2683− $(yer nec, day (add day ?:((yelp nec) 36.525 36.524)))
2684− (add day (mul (div yer 400) (add 1 (mul 4 36.524))))
2685−
2686−Examples
2687−--------
2688−
2689− ~zod/try=> (yawn 2.014 8 4)
2690− 735.814
2691− ~zod/try=> (yawn 1.776 7 4)
2692− 648.856
2693− ~zod/try=> (yawn 1.990 10 11)
2694− 727.116
2695−
2696−------------------------------------------------------------------------
2697−
2698−### `++yelp`
2699−
2700−Leap-week?
2701−
2702−Determines whether a year contains an ISO 8601 leap week. Produces a
2703−loobean.
2704−
2705−Accepts
2706−-------
2707−
2708−`yer` is an unsigned decimal, `@ud`.
2709−
2710−Produces
2711−--------
2712−
2713−A boolean.
2714−
2715−Source
2716−------
2717−
2718− ++ yelp :: leap year
2719− |= yer=@ud ^- ?
2720− &(=(0 (mod yer 4)) |(!=(0 (mod yer 100)) =(0 (mod yer 400))))
2721−
2722−Examples
2723−--------
2724−
2725− ~zod/try=> (yelp 2.014)
2726− %.n
2727− ~zod/try=> (yelp 2.008)
2728− %.y
2729− ~zod/try=> (yelp 0)
2730− %.y
2731− ~zod/try=> (yelp 14.011)
2732− %.n
2733−
2734−------------------------------------------------------------------------
2735−
2736−### `++yo`
2737−
2738− ++ yo :: time constants core
2739−
2740−Useful constants for interacting with earth time.
2741−
2742−### `++cet`
2743−
2744−Days in a century. Derived by multiplying the number of days in a year
2745−(365) by the number of years in a century (100), then adding the number
2746−days from leap years in a century (24).
2747−
2748−Produces
2749−--------
2750−
2751−An [atom]().
2752−
2753−Source
2754−------
2755−
2756− |% ++ cet 36.524 :: (add 24 (mul 100 365))
2757−
2758−Examples
2759−--------
2760−
2761− ~zod/try=> cet:yo
2762− 36.524
2763− ~zod/try=> (add 365 cet:yo)
2764− 36.889
2765− ~zod/try=> (sub (add 24 (mul 100 365)) cet:yo)
2766− 0
2767−
2768−------------------------------------------------------------------------
2769−
2770−### `++day`
2771−
2772−Number of seconds in a day.
2773−
2774−Produces
2775−--------
2776−
2777−An [atom]().
2778−
2779−Source
2780−------
2781−
2782− ++ day 86.400 :: (mul 24 hor)
2783−
2784−Examples
2785−--------
2786−
2787− ~zod/try=> day:yo
2788− 86.400
2789− ~zod/try=> (add 60 day:yo)
2790− 86.460
2791−
2792−------------------------------------------------------------------------
2793−
2794−### `++era`
2795−
2796−XX Revisit
2797−
2798−Produces
2799−--------
2800−
2801−An [atom]().
2802−
2803−Source
2804−------
2805−
2806− ++ era 146.097 :: (add 1 (mul 4 cet))
2807−
2808−Examples
2809−--------
2810−
2811−
2812−------------------------------------------------------------------------
2813−
2814−### `++hor`
2815−
2816−Seconds in hour
2817−
2818−The number of seconds in an hour. Derived by multiplying the number of
2819−seconds in a minute by the minutes in an hour.
2820−
2821−Produces
2822−--------
2823−
2824−An [atom]().
2825−
2826−Source
2827−------
2828−
2829− ++ hor 3.600 :: (mul 60 mit)
2830−
2831−Examples
2832−--------
2833−
2834− ~zod/try=> hor:yo
2835− 3.600
2836− ~zod/try=> (div hor:yo 60)
2837− 60
2838−
2839−------------------------------------------------------------------------
2840−
2841−### `++jes`
2842−
2843−XX Revisit
2844−
2845−Produces
2846−--------
2847−
2848−An atom.
2849−
2850−Source
2851−------
2852−
2853− ++ jes 106.751.991.084.417 :: (mul 730.692.561 era)
2854−
2855−Examples
2856−--------
2857−
2858− ~zod/try=> jes:yo
2859− 106.751.991.084.417
2860−
2861−------------------------------------------------------------------------
2862−
2863−### `++mit`
2864−
2865−Seconds in minute
2866−
2867−The number of seconds in a minute.
2868−
2869−Produces
2870−--------
2871−
2872−An [atom]().
2873−
2874−Source
2875−------
2876−
2877− ++ mit 60
2878−
2879−Examples
2880−--------
2881−
2882− ~zod/try=> mit:yo
2883− 60
2884−
2885−------------------------------------------------------------------------
2886−
2887−### `++moh`
2888−
2889−Days in month
2890−
2891−The days in each month of the Gregorian common year. A list of unsigned
2892−decimal atoms (Either 28, 30, or 31) denoting the number of days in the
2893−month at the year at that index.
2894−
2895−Produces
2896−--------
2897−
2898−A [`++list`]() of [`@ud`]()
2899−
2900−Source
2901−------
2902−
2903− ++ moh `(list ,@ud)`[31 28 31 30 31 30 31 31 30 31 30 31 ~]
2904−
2905−Examples
2906−--------
2907−
2908− ~zod/try=> moh:yo
2909− ~[31 28 31 30 31 30 31 31 30 31 30 31]
2910− ~zod/try=> (snag 4 moh:yo)
2911− 31
2912−
2913−------------------------------------------------------------------------
2914−
2915−### `++moy`
2916−
2917−Moh with leapyear
2918−
2919−The days in each month of the Gregorian leap-year. A list of unsigned
2920−decimal atoms (Either 29,30, or 31) denoting the number of days in the
2921−month at the leap-year at that index.
2922−
2923−Examples
2924−--------
2925−
2926−A [`++list`]() of [`@ud`]()
2927−
2928−Source
2929−------
2930−
2931− ++ moy `(list ,@ud)`[31 29 31 30 31 30 31 31 30 31 30 31 ~]
2932−
2933−Examples
2934−--------
2935−
2936− ~zod/try=> moy:yo
2937− ~[31 29 31 30 31 30 31 31 30 31 30 31]
2938− ~zod/try=> (snag 1 moy:yo)
2939− 29
2940−
2941−------------------------------------------------------------------------
2942−
2943−### `++qad`
2944−
2945−Seconds in 4 years
2946−
2947−The number of seconds in four years. Derived by adding one second to the
2948−number of seconds in four years.
2949−
2950−Produces
2951−--------
2952−
2953−An [atom]().
2954−
2955−Source
2956−------
2957−
2958− ++ qad 126.144.001 :: (add 1 (mul 4 yer))
2959−
2960−Examples
2961−--------
2962−
2963− ~zod/try=> qad:yo
2964− 126.144.001
2965−
2966−------------------------------------------------------------------------
2967−
2968−### `++yer`
2969−
2970−Seconds in year
2971−
2972−The number of seconds in a year. Derived by multiplying the number of
2973−seconds in a day by 365.
2974−
2975−Produces
2976−--------
2977−
2978−An [atom]().
2979−
2980−Source
2981−------
2982−
2983− ++ yer 31.536.000 :: (mul 365 day)
2984−
2985−Examples
2986−--------
2987−
2988− ~zod/try=> yer:yo
2989− 31.536.000
2990−
2991−------------------------------------------------------------------------
2992−
2993−section 2cI, almost macros
2994−--------------------------
2995−
2996−### `++cury`
2997−
2998−Curry a gate, binding the head of its sample
2999−
3000−Accepts
3001−-------
3002−
3003−`a` is a [gate]().
3004−
3005−`b` is a [noun]().
3006−
3007−Produces
3008−--------
3009−
3010−A [gate]().
3011−
3012−Source
3013−------
3014−
3015− ++ cury
3016− |* [a=_|=(^ _*) b=*]
3017− |* c=_+<+.a
3018− (a b c)
3019−
3020−Examples
3021−--------
3022−
3023− ~zod/try=> =mol (cury add 2)
3024− ~zod/try=> (mol 4)
3025− 6
3026− ~zod/try=> (mol 7)
3027− 9
3028−
3029−------------------------------------------------------------------------
3030−
3031−### `++curr`
3032−
3033−Right curry
3034−
3035−Right curry a gate, binding the tail of its sample
3036−
3037−Accepts
3038−-------
3039−
3040−`a` is a [gate]().
3041−
3042−`c` is a [noun]().
3043−
3044−Produces
3045−--------
3046−
3047−
3048−Source
3049−------
3050−
3051− ++ curr
3052− |* [a=_|=(^ _*) c=*]
3053− |* b=_+<+.a
3054− (a b c)
3055−
3056−Examples
3057−--------
3058−
3059− ~zod/try=> =tep (curr scan sym)
3060− ~zod/try=> `@t`(tep "asd")
3061− 'asd'
3062− ~zod/try=> `@t`(tep "lek-om")
3063− 'lek-om'
3064−
3065−------------------------------------------------------------------------
3066−
3067−### `++cork`
3068−Build `f` such that `(f x) .= (b (a x))`.
3069−
3070−`a` is a noun.
3071−
3072−`b` is a gate.
3073−
3074−Source
3075−------
3076−
3077− ++ cork |*([a=_,* b=gate] (corl b a)) :: compose forward
3078−
3079−Examples
3080−--------
3081−
3082− ~zod/try=> (:(cork dec dec dec) 20)
3083− 17
3084− ~zod/try=> =mal (mo (limo a/15 b/23 ~))
3085− ~zod/try=> ((cork ~(got by mal) dec) %a)
3086− 14
3087− ~zod/try=> ((cork ~(got by mal) dec) %b)
3088− 22
3089−
3090−------------------------------------------------------------------------
3091−
3092−### `++corl`
3093−
3094−Gate compose
3095−
3096−XX Revisit
3097−
3098−`a` is a gate.
3099−
3100−`b` is a noun.
3101−
3102−Source
3103−------
3104−
3105− ++ corl :: compose backwards
3106− |* [a=gate b=_,*]
3107− |= c=_+<.b
3108− (a (b c))
3109−
3110−Examples
3111−--------
3112−
3113− ~zod/try=> ((corl (lift bex) (slat %ud)) '2')
3114− [~ 4]
3115−
3116−------------------------------------------------------------------------
3117−
3118−### `++hard`
3119−
3120−Demands that a specific type be produced, crashing the program is it is
3121−not.
3122−
3123−Source
3124−------
3125−
3126− ++ hard
3127− |* han=$+(* *)
3128− |= fud=* ^- han
3129− ~| %hard
3130− =+ gol=(han fud)
3131− ?>(=(gol fud) gol)
3132−
3133−Examples
3134−--------
3135−
3136− ~zod/try=> ((hard (list)) (limo [1 2 3 ~]))
3137− ~[1 2 3]
3138− ~zod/try=> ((hard ,@) (add 2 2))
3139− 4
3140− ~zod/try=> ((hard ,@t) (crip "Tape to cord, bro!"))
3141− 'Tape to cord, bro'
3142− ~zod/try=> ((hard tape) (crip "...Tape to cord, bro?..."))
3143− ! hard
3144− ! exit
3145−
3146−------------------------------------------------------------------------
3147−
3148−### `++soft`
3149−
3150−Politely requests a specific type to be produced, producing null if it
3151−is not.
3152−
3153−Source
3154−------
3155−
3156− ++ soft
3157− |* han=$+(* *)
3158− |= fud=* ^- (unit han)
3159− =+ gol=(han fud)
3160− ?.(=(gol fud) ~ [~ gol])
3161−
3162−Examples
3163−--------
3164−
3165− ~zod/try=> ((soft ,%4) (add 2 2))
3166− [~ %4]
3167− ~zod/try=> ((soft ,@) (add 2 2))
3168− [~ 4]
3169− ~zod/try=> ((soft ,%5) (add 2 2))
3170− ~
3171− ~zod/try=> ((soft ,@t) (crip "Tape to cord, Woohoo!"))
3172− [~ 'Tape to cord, Woohoo!']
3173− ~zod/try=> ((soft ,@t) (trip 'Cmon man... Tape to cord? Please?!'))
3174− ~
3175−
3176−------------------------------------------------------------------------
docs/dev/hoon/library/2db.mddeleted−813
@@ -1,813 +0,0 @@
1−section 2dB, maps
2−=================
3−
4−### `++ept`
5−
6−Map invariant.
7−
8− ++ ept :: map invariant
9− |= a=(tree ,[p=* q=*])
10− ?~ a
11− &
12− ?& ?~(l.a & ?&((vor p.n.a p.n.l.a) (hor p.n.l.a p.n.a)))
13− ?~(r.a & ?&((vor p.n.a p.n.r.a) (hor p.n.a p.n.r.a)))
14− ==
15−
16−Computes whether `a` is a [map](), producing a loobean.
17−
18−`a` is a [tree]().
19−
20− ~zod/try=> m
21− {[p='d' q=5] [p='a' q=1] [p='c' q=4] [p='b' q=[2 3]]}
22− ~zod/try=> (ept m)
23− %.y
24− ~zod/try=> b
25− {'bonita' 'madeleine' 'daniel' 'john'}
26− ~zod/try=> (ept b)
27− ! type-fail
28− ! exit
29−
30−------------------------------------------------------------------------
31−
32−### `++ja`
33−
34−Jar engine
35−
36− ++ ja :: jar engine
37− |/ a=(jar)
38−
39−A container arm for `++jar` operation arms. A `++jar` is a `++map` of
40−`++list`s. The contained arms inherit the [sample]() jar.
41−
42−`a` is a [jar]().
43−
44− ~zod/try=> ~(. ja (mo (limo a/"ho" b/"he" ~)))
45− <2.dgz [nlr([p={%a %b} q=""]) <414.fvk 101.jzo 1.ypj %164>]>
46−
47−------------------------------------------------------------------------
48−
49−### `+-get:ja`
50−
51−Grab value by key
52−
53− +- get :: grab value by key
54− |* b=*
55− =+ c=(~(get by a) b)
56− ?~(c ~ u.c)
57−
58−Produces a list retrieved from jar `a` using the key `b`.
59−
60−`a` is a [`++jar`](/doc/hoon/library/1#++jar).
61−
62−`b` is a key of the same type as the keys in `a`.
63−
64− ~zod/try=> =l (mo `(list ,[@t (list ,@)])`[['a' `(list ,@)`[1 2 3 ~]] ['b' `(list ,@)`[4 5 6 ~]] ~])
65− ~zod/try=> l
66− {[p='a' q=~[1 2 3]] [p='b' q=~[4 5 6]]}
67− ~zod/try=> (~(get ja l) 'a')
68− ~[1 2 3]
69− ~zod/try=> (~(get ja l) 'b')
70− ~[4 5 6]
71− ~zod/try=> (~(get ja l) 'c')
72− ~
73−
74−------------------------------------------------------------------------
75−
76−### `+-add:ja`
77−
78−Prepend to list
79−
80− +- add :: adds key-list pair
81− |* [b=* c=*]
82− =+ d=(get(+< a) b)
83− (~(put by a) b [c d])
84−
85−Produces jar `a` with value `c` prepended to the list located at key
86−`b`.
87−
88−`a` is a [jar]().
89−
90−`b` is a key of the same type as the keys in `a`.
91−
92−`c` is a value of the same type as the values in `a`.
93−
94− ~zod/try=> =l (mo `(list ,[@t (list ,@)])`[['a' `(list ,@)`[1 2 3 ~]] ['b' `(list ,@)`[4 5 6 ~]] ~])
95− ~zod/try=> l
96− {[p='a' q=~[1 2 3]] [p='b' q=~[4 5 6]]}
97− ~zod/try=> (~(add ja l) 'b' 7)
98− {[p='a' q=~[1 2 3]] [p='b' q=~[7 4 5 6]]}
99− ~zod/try=> (~(add ja l) 'a' 100)
100− {[p='a' q=~[100 1 2 3]] [p='b' q=~[4 5 6]]}
101− ~zod/try=> (~(add ja l) 'c' 7)
102− {[p='a' q=~[1 2 3]] [p='c' q=~[7]] [p='b' q=~[4 5 6]]}
103− ~zod/try=> (~(add ja l) 'c' `(list ,@)`[7 8 9 ~])
104− ! type-fail
105− ! exit
106−
107−------------------------------------------------------------------------
108−
109−### `++ju`
110−
111−Jug operations
112−
113− ++ ju :: jug engine
114− |/ a=(jug)
115−
116−Container arm for jug operation arms. A `++jug` is a `++map` of
117−`++sets`. The contained arms inherit its [sample]() jug, `a`.
118−
119−`a` is a [jug]().
120−
121− ~zod/try=> ~(. ju (mo (limo a/(sa "ho") b/(sa "he") ~)))
122− <2.dgz [nlr([p={%a %b} q={nlr(^$1{@tD $1}) nlr(^$3{@tD $3})}]) <414.fvk 101.jzo 1.ypj %164>]>
123−
124−### `+-del:ju`
125−
126−Remove
127−
128− +- del :: delete at key b
129− |* [b=* c=*]
130− ^+ a
131− =+ d=(get(+< a) b)
132− =+ e=(~(del in d) c)
133− ?~ e
134− (~(del by a) b)
135− (~(put by a) b e)
136−
137−Produces jug `a` with value `c` removed from set located at key `b`.
138−
139−`a` is a [jug]().
140−
141−`b` is a key of the same type as the keys in `a`.
142−
143−`c` is the value of the same type of the keys in `a` that is to be
144−removed.
145−
146− ~zod/try=> s
147− {[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
148− ~zod/try=> (~(del ju s) 'a' 1)
149− {[p='a' q={3 2}] [p='b' q={5 4 6}]}
150− ~zod/try=> (~(del ju s) 'c' 7)
151− {[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
152−
153−------------------------------------------------------------------------
154−
155−### `+-get:ju`
156−
157−Retrieve set
158−
159− +- get :: gets set by key
160− |* b=*
161− =+ c=(~(get by a) b)
162− ?~(c ~ u.c)
163−
164−Produces a set retrieved from jar `a` using key `b`.
165−
166−`a` is a [jar]().
167−
168−`b` is a key of the same type as the keys in `a`.
169−
170− ~zod/try=> s
171− {[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
172− ~zod/try=> (~(get ju s) 'a')
173− {1 3 2}
174− ~zod/try=> (~(get ju s) 'b')
175− {5 4 6}
176− ~zod/try=> (~(get ju s) 'c')
177− ~
178−
179−------------------------------------------------------------------------
180−
181−### `+-has:ju`
182−
183−Check contents
184−
185− +- has :: existence check
186− |* [b=* c=*]
187− ^- ?
188− (~(has in (get(+< a) b)) c)
189−
190−Computes whether a value `c` exists within the set located at key `b`
191−with jar `a`. Produces a loobean.
192−
193−`a` is a [set]().
194−
195−`b` is a key as a [noun]().
196−
197−`c` is a value as a [noun]().
198−
199− ~zod/try=> s
200− {[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
201− ~zod/try=> (~(has ju s) 'a' 3)
202− %.y
203− ~zod/try=> (~(has ju s) 'b' 6)
204− %.y
205− ~zod/try=> (~(has ju s) 'a' 7)
206− %.n
207− ~zod/try=> (~(has jus s) 'c' 7)
208− ! -find-limb.jus
209− ! find-none
210− ! exit
211− ~zod/try=> (~(has ju s) 'c' 7)
212− %.n
213−
214−------------------------------------------------------------------------
215−
216−### `+-put:ju`
217−
218−Add key-set pair
219−
220− +- put :: adds key-element pair
221− |* [b=* c=*]
222− ^+ a
223− =+ d=(get(+< a) b)
224− (~(put by a) b (~(put in d) c))
225−
226−Produces jar `a` with `c` added to the set value located at key `b`.
227−
228−`a` is a [set]().
229−
230−`b` is a key as a [noun]().
231−
232−`c` is a [value]().
233−
234− ~zod/try=> s
235− {[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
236− ~zod/try=> (~(put ju s) 'a' 7)
237− {[p='a' q={7 1 3 2}] [p='b' q={5 4 6}]}
238− ~zod/try=> (~(put ju s) 'a' 1)
239− {[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
240− ~zod/try=> (~(put ju s) 'c' 7)
241− {[p='a' q={1 3 2}] [p='c' q={7}] [p='b' q={5 4 6}]}
242−
243−------------------------------------------------------------------------
244−
245−### `++by`
246−
247−Map operations
248−
249− ++ by :: map engine
250− ~/ %by
251− |/ a=(map)
252−
253−Container arm for map operation arms. A map is a set of key, value
254−pairs. The contained arms inherit it's [sample]() [map](), `a`.
255−
256−`a` is a [map]().
257−
258− ~zod/try=> ~(. by (mo (limo [%a 1] [%b 2] ~)))
259− <19.irb [nlr([p={%a %b} q=@ud]) <414.rvm 101.jzo 1.ypj %164>]>
260−
261−------------------------------------------------------------------------
262−
263−### `+-all:by`
264−
265−Logical AND
266−
267− +- all :: logical AND
268− ~/ %all
269− |* b=$+(* ?)
270− |- ^- ?
271− ?~ a
272− &
273− ?&((b q.n.a) $(a l.a) $(a r.a))
274−
275−Computes the logical AND on the results of slamming every element in map
276−`a` with gate `b`. Produces a loobean.
277−
278−`a` is a [map]().
279−
280−`b` is a [wet gate]().
281−
282− ~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
283− ~zod/try=> (~(all by b) |=(a=* ?@(a & |)))
284− %.n
285− ~zod/try=> =a (mo `(list ,[@t @u])`[['a' 1] ['b' 2] ['c' 3] ['d' 4] ['e' 5] ~])
286− ~zod/try=> (~(all by a) |=(a=@ (lte a 6)))
287− %.y
288− ~zod/try=> (~(all by a) |=(a=@ (lte a 4)))
289− %.n
290−
291−------------------------------------------------------------------------
292−
293−### `+-any:by`
294−
295−Logical OR
296−
297− +- any :: logical OR
298− ~/ %any
299− |* b=$+(* ?)
300− |- ^- ?
301− ?~ a
302− |
303− ?|((b q.n.a) $(a l.a) $(a r.a))
304−
305−Computes the logical OR on the results of slamming every element with
306−gate `b`. Produces a loobean.
307−
308−`a` is a [map]().
309−
310−`b` is a [wet gate]().
311−
312− ~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
313− ~zod/try=> (~(all by b) |=(a=* ?@(a & |)))
314− %.y
315− ~zod/try=> =a (mo `(list ,[@t @u])`[['a' 1] ['b' 2] ['c' 3] ['d' 4] ['e' 5] ~])
316− ~zod/try=> (~(any by a) |=(a=@ (lte a 4)))
317− %.y
318−
319−------------------------------------------------------------------------
320−
321−### `+-del:by`
322−
323−Delete
324−
325− +- del :: delete at key b
326− ~/ %del
327− |* b=*
328− |- ^+ a
329− ?~ a
330− ~
331− ?. =(b p.n.a)
332− ?: (gor b p.n.a)
333− [n.a $(a l.a) r.a]
334− [n.a l.a $(a r.a)]
335− |- ^- ?(~ _a)
336− ?~ l.a r.a
337− ?~ r.a l.a
338− ?: (vor p.n.l.a p.n.r.a)
339− [n.l.a l.l.a $(l.a r.l.a)]
340− [n.r.a $(r.a l.r.a) r.r.a]
341−
342−Produces map `a` with the element located at key `b` removed.
343−
344−`a` is a [map]().
345−
346−`b` is a key as a [noun]().
347−
348− ~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
349− ~zod/try=> (~(del by b) `a`)
350− {[p=`b` q=[2 3]]}
351−
352−------------------------------------------------------------------------
353−
354−### `+-dig:by`
355−
356−Axis of key
357−
358− +- dig :: axis of key
359− |= b=*
360− =+ c=1
361− |- ^- (unit ,@)
362− ?~ a ~
363− ?: =(b p.n.a) [~ u=(peg c 2)]
364− ?: (gor b p.n.a)
365− $(a l.a, c (peg c 6))
366− $(a r.a, c (peg c 7))
367−
368−Produce the axis of key `b` within map `a`.
369−
370−`a` is a [map]().
371−
372−`b` is a key as a [noun]().
373−
374− ~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
375− ~zod/try=> (~(dig by b) `b`)
376− [~ 2]
377−
378−------------------------------------------------------------------------
379−
380−### `+-gas:by`
381−
382−Concatenate
383−
384− +- gas :: concatenate
385− ~/ %gas
386− |* b=(list ,[p=* q=*])
387− => .(b `(list ,_?>(?=(^ a) n.a))`b)
388− |- ^+ a
389− ?~ b
390− a
391− $(b t.b, a (put(+< a) p.i.b q.i.b))
392−
393−Insert a list of key-value pairs `b` into map `a`.
394−
395−`a` is a [map]().
396−
397−`b` is a [list]() of [cells]() of key-value nouns `p` and `q`.
398−
399− ~zod/try=> =a (mo `(list ,[@t *])`[[`a` 1] [`b` 2] ~])
400− ~zod/try=> =b `(list ,[@t *])`[[`c` 3] [`d` 4] ~]
401− ~zod/try=> (~(gas by a) b)
402− {[p=`d` q=4] [p=`a` q=1] [p=`c` q=3] [p=`b` q=2]}
403−
404−------------------------------------------------------------------------
405−
406−### `+-get:by`
407−
408−Grab unit value
409−
410− +- get :: unit value by key
411− ~/ %get
412− |* b=*
413− |- ^- ?(~ [~ u=_?>(?=(^ a) q.n.a)])
414− ?~ a
415− ~
416− ?: =(b p.n.a)
417− [~ u=q.n.a]
418− ?: (gor b p.n.a)
419− $(a l.a)
420− $(a r.a)
421−
422−Produce the unit value of the value located at key `b` within map `a`.
423−
424−`a` is a [map]()
425−
426−`b` is a [key]() as a [noun]()
427−
428− ~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
429− ~zod/try=> (~(get by b) `b`)
430− [~ [2 3]]
431−
432−------------------------------------------------------------------------
433−
434−### `+-got:by`
435−
436−Assert
437−
438− +- got
439− |* b=*
440− %- need
441− %- get(+< a) b
442−
443−Produce the value located at key `b` within map `a`. Crash if key `b`
444−does not exist.
445−
446−`a` is a [map]().
447−
448−`b` is a [key]().
449−
450− ~zod/try=> =m (mo `(list ,[@t *])`[['a' 1] ['b' 2] ~])
451− ~zod/try=> m
452− {[p='a' q=1] [p='b' q=2]}
453− ~zod/try=> (~(get by m) 'a')
454− [~ 1]
455− ~zod/try=> (~(got by m) 'a')
456− 1
457− ~zod/try=> (~(got by m) 'c')
458− ! exit
459−
460−------------------------------------------------------------------------
461−
462−### `+-has:by`
463−
464−Key existence check
465−
466− +- has :: key existence check
467− ~/ %has
468− |* b=*
469− !=(~ (get(+< a) b))
470−
471−Checks whether map `a` contains an element with key `b`, producing a
472−loobean.
473−
474−`a` is a [map]().
475−
476−`b` is a key as a [noun]().
477−
478− ~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
479− ~zod/try=> (~(has by b) `b`)
480− %.y
481− ~zod/try=> (~(has by b) `c`)
482− %.n
483−
484−------------------------------------------------------------------------
485−
486−### `+-int:by`
487−
488−Intersection
489−
490− +- int :: intersection
491− ~/ %int
492− |* b=_a
493− |- ^+ a
494− ?~ b
495− ~
496− ?~ a
497− ~
498− ?: (vor p.n.a p.n.b)
499− ?: =(p.n.b p.n.a)
500− [n.b $(a l.a, b l.b) $(a r.a, b r.b)]
501− ?: (hor p.n.b p.n.a)
502− %- uni(+< $(a l.a, b [n.b l.b ~])) $(b r.b)
503− %- uni(+< $(a r.a, b [n.b ~ r.b])) $(b l.b)
504− ?: =(p.n.a p.n.b)
505− [n.b $(b l.b, a l.a) $(b r.b, a r.a)]
506− ?: (hor p.n.a p.n.b)
507− %- uni(+< $(b l.b, a [n.a l.a ~])) $(a r.a)
508− %- uni(+< $(b r.b, a [n.a ~ r.a])) $(a l.a)
509−
510−Produces a map of the (key) intersection between two maps of the same
511−type, `a` and `b`. If both maps have an identical key that point to
512−different values, the element from map `b` is used.
513−
514−`a` is a [map]().
515−
516−`b` is a [map]().
517−
518− ~zod/try=> =n (mo `(list ,[@t *])`[['a' 1] ['c' 3] ~])
519− ~zod/try=> n
520− {[p='a' q=1] [p='c' q=3]}
521− ~zod/try=> m
522− {[p='a' q=1] [p='b' q=2]}
523− ~zod/try=> (~(int by m) n)
524− {[p='a' q=1]}
525− ~ravpel-holber/try=> =p (mo `(list ,[@t *])`[['a' 2] ['b' 2] ~])
526− ~zod/try=> p
527− {[p='a' q=2] [p='b' q=2]}
528− ~zod/try=> (~(int by p) n)
529− {[p='a' q=2]}
530− ~zod/try=> =q (mo `(list ,[@t *])`[['a' 2] ['c' 2] ~])
531− ~zod/try=> q
532− {[p='a' q=2] [p='b' q=2]}
533− ~zod/try=> (~(int by p) q)
534− {[p='a' q=2] [p='b' q=2]}
535− ~zod/try=> =o (mo `(list ,[@t *])`[['c' 3] ['d' 4] ~])
536− ~zod/try=> (~(int by m) o)
537− {}
538−
539−
540−------------------------------------------------------------------------
541−
542−### `+-mar:by`
543−
544−Assert and Add
545−
546− +- mar :: add with validation
547− |* [b=_?>(?=(^ a) p.n.a) c=(unit ,_?>(?=(^ a) q.n.a))]
548− ?~ c
549− (del b)
550− (put b u.c)
551−
552−Produces map `a` with the addition of a key-value pair, where the value
553−is a nonempty unit.
554−
555−Accept a noun and a unit of a noun of the type of the map's keys and
556−values, respectively. Validate that the value is not null and put the
557−pair in the map. If the value is null, delete the key.
558−
559−XX This arm is broken, asana task 15186618346453
560−
561− ~zod/try=> m
562− {[p='a' q=1] [p='b' q=2]}
563− ~zod/try=> (~(mar by m) 'c' (some 3))
564− ! -find-limb.n
565− ! find-none
566− ! exit
567− ~zod/try=> (~(mar by m) 'c' ~)
568− ! -find-limb.n
569− ! find-none
570− ! exit
571− ~zod/try=> (~(mar by m) 'b' ~)
572− ! -find-limb.n
573− ! find-none
574− ! exit
575−
576−------------------------------------------------------------------------
577−
578−### `+-put:by`
579−
580−Add key-value pair
581−
582− +- put :: adds key-value pair
583− ~/ %put
584− |* [b=* c=*]
585− |- ^+ a
586− ?~ a
587− [[b c] ~ ~]
588− ?: =(b p.n.a)
589− ?: =(c q.n.a)
590− a
591− [[b c] l.a r.a]
592− ?: (gor b p.n.a)
593− =+ d=$(a l.a)
594− ?> ?=(^ d)
595− ?: (vor p.n.a p.n.d)
596− [n.a d r.a]
597− [n.d l.d [n.a r.d r.a]]
598− =+ d=$(a r.a)
599− ?> ?=(^ d)
600− ?: (vor p.n.a p.n.d)
601− [n.a l.a d]
602− [n.d [n.a l.a l.d] r.d]
603−
604−Produces `a` with the addition of the key-value pair of `b` and `c`.
605−
606−`a` is a [map]().
607−
608−`b` is a key of the same type as the keys in `a`.
609−
610−`c` is a value of the same type of the values in `a`.
611−
612− ~zod/try=> m
613− {[p='a' q=1] [p='b' q=2]}
614− ~zod/try=> (~(put by m) 'c' 3)
615− {[p='a' q=1] [p='c' q=3] [p='b' q=2]}
616− ~zod/try=> (~(put by m) "zod" 26)
617− ! type-fail
618− ! exit
619− ~zod/try=> (~(put by m) 'a' 2)
620− {[p='a' q=2] [p='b' q=2]}
621−
622−------------------------------------------------------------------------
623−
624−### `+-rep:by`
625−
626− +- rep :: replace by product
627− |* [b=* c=_,*]
628− |-
629− ?~ a b
630− $(a r.a, b $(a l.a, b (c q.n.a b)))
631−
632−Accumulate using gate from values in map
633−
634−XX interface changing.
635−
636−------------------------------------------------------------------------
637−
638−### `+-rib:by`
639−
640− +- rib :: transform + product
641− |* [b=* c=_,*]
642− |- ^+ [b a]
643− ?~ a [b ~]
644− =+ d=(c n.a b)
645− =. n.a +.d
646− =+ e=$(a l.a, b -.d)
647− =+ f=$(a r.a, b -.e)
648− [-.f [n.a +.e +.f]]
649−
650−Replace values with accumulator
651−
652−XX interface changing, possibly disappearing
653−
654−------------------------------------------------------------------------
655−
656−### `+-run:by`
657−
658−Transform values
659−
660− +- run :: turns to tuples
661− |* b=_,*
662− |-
663− ?~ a a
664− a(n (b q.n.a), l $(a l.a), r $(a r.a))
665−
666−Iterates over every value in set `a` using gate `b`. Produces a map.
667−
668−`a` is a [map]().
669−
670−`b` is a [wet gate]().
671−
672− ~zod/try=> m
673− {[p='a' q=1] [p='b' q=2]}
674− ~zod/try=> ^+(m (~(run by m) dec))
675− {[p='a' q=0] [p='b' q=1]}
676− ~zod/try=> `(map ,@tas ,@t)`(~(run by m) (cury scot %ux))
677− {[p=%a q='0x1'] [p=%b q='0x2']}
678−
679−------------------------------------------------------------------------
680−
681−### `+-tap:by`
682−
683−Listify pairs
684−
685− +- tap :: listify pairs
686− ~/ %tap
687− |= b=(list ,_?>(?=(^ a) n.a))
688− ^+ b
689− ?~ a
690− b
691− $(a r.a, b [n.a $(a l.a)])
692−
693−Produces the list of all elements in map `a` that is prepended to list
694−`b`, which is empty by default.
695−
696−`a` is a [map]().
697−
698−`b` is a [list]().
699−
700− {[p='a' q=1] [p='b' q=2]}
701− ~zod/try=> `*`m
702− [[98 2] [[97 1] 0 0] 0]
703− ~zod/try=> (~(tap by m))
704− ~[[p='b' q=2] [p='a' q=1]]
705− ~zod/try=> `*`(~(tap by m))
706− [[98 2] [97 1] 0]
707−
708−------------------------------------------------------------------------
709−
710−### `+-uni:by`
711−
712−Union
713−
714− +- uni :: union, merge
715− ~/ %uni
716− |* b=_a
717− |- ^+ a
718− ?~ b
719− a
720− ?~ a
721− b
722− ?: (vor p.n.a p.n.b)
723− ?: =(p.n.b p.n.a)
724− [n.b $(a l.a, b l.b) $(a r.a, b r.b)]
725− ?: (hor p.n.b p.n.a)
726− $(a [n.a $(a l.a, b [n.b l.b ~]) r.a], b r.b)
727− $(a [n.a l.a $(a r.a, b [n.b ~ r.b])], b l.b)
728− ?: =(p.n.a p.n.b)
729− [n.b $(b l.b, a l.a) $(b r.b, a r.a)]
730− ?: (hor p.n.a p.n.b)
731− $(b [n.b $(b l.b, a [n.a l.a ~]) r.b], a r.a)
732− $(b [n.b l.b $(b r.b, a [n.a ~ r.a])], a l.a)
733−
734−Produces a map of the union between the keys of `a` and `b`. If `b`
735−shares a key with `a`, the tuple from `a` is preserved.
736−
737−`a` is a [map]().
738−
739−`b` is a [map]().
740−
741− ~zod/try=> m
742− {[p='a' q=1] [p='b' q=2]}
743− ~zod/try=> o
744− {[p='d' q=4] [p='c' q=3]}
745− ~zod/try=> (~(uni by m) o)
746− {[p='d' q=4] [p='a' q=1] [p='c' q=3] [p='b' q=2]}
747− ~zod/try=> (~(uni by m) ~)
748− {[p='a' q=1] [p='b' q=2]}
749− ~zod/try=> n
750− {[p='a' q=1] [p='c' q=9]}
751− ~zod/try=> (~(uni by o) n)
752− {[p='d' q=4] [p='a' q=1] [p='c' q=3]}
753− ~zod/try=> =n (mo `(list ,[@t *])`[['a' 1] ['c' 9] ~])
754− ~zod/try=> n
755− {[p='a' q=1] [p='c' q=9]}
756− ~zod/try=> (~(uni by o) n)
757− {[p='d' q=4] [p='a' q=1] [p='c' q=9]}
758−
759−------------------------------------------------------------------------
760−
761−### `+-urn:by`
762−
763−Turn (with key)
764−
765− +- urn :: turn
766− |* b=$+([* *] *)
767− |-
768− ?~ a ~
769− [n=[p=p.n.a q=(b p.n.a q.n.a)] l=$(a l.a) r=$(a r.a)]
770−
771−Iterates over every value in map `a` using gate `b`, which accepts both
772−the key and the value of each element as its sample.
773−
774−`a` is a [map]().
775−
776−`b` is a [wet gate]() that accepts two nouns (a key and a value) and
777−produces a noun (the new value).
778−
779− ~zod/try=> m
780− {[p='a' q=1] [p='b' q=2]}
781− ~zod/try=> (~(urn by m) |=(a=[p=* q=*] q.a))
782− {[p='a' q=1] [p='b' q=2]}
783− ~zod/try=> (~(urn by m) |=(a=[p=* q=*] 7))
784− {[p='a' q=7] [p='b' q=7]}
785− ~zod/try=> (~(urn by m) |=(a=[p=* q=*] p.a))
786− {[p='a' q=97] [p='b' q=98]}
787−
788−------------------------------------------------------------------------
789−
790−### `+-wyt:by`
791−
792−Depth
793−
794− +- wyt :: depth of map
795− |- ^- @
796− ?~(a 0 +((add $(a l.a) $(a r.a))))
797−
798−Produce the depth of the tree map `a`.
799−
800−`a` is a [map]().
801−
802− ~zod/try=> m
803− {[p='a' q=1] [p='b' q=2]}
804− ~zod/try=> o
805− {[p='d' q=4] [p='c' q=3]}
806− ~zod/try=> ~(wyt by m)
807− 2
808− ~zod/try=> ~(wyt by o)
809− 2
810− ~zod/try=> ~(wyt by (~(uni by m) o))
811− 4
812−
813−------------------------------------------------------------------------
docs/dev/hoon/library/2dd.mddeleted−112
@@ -1,112 +0,0 @@
1−section 2dD, casual containers
2−==============================
3−
4−### `++mo`
5−
6−Map from list
7−
8−Produces a map of key-value pairs from the left-right cell pairs of list
9−
10−Accepts
11−-------
12−
13−`a` is a [`++list`]().
14−
15−Produces
16−--------
17−
18−A [`++map]()
19−
20−Source
21−------
22−
23− ++ mo :: map from list
24− |* a=(list)
25− => .(a `_(homo a)`a)
26− => .(a `(list ,[p=_-<.a q=_->.a])`a)
27− =+ b=*(map ,_?>(?=(^ a) p.i.a) ,_?>(?=(^ a) q.i.a))
28− (~(gas by b) a)
29− ::
30−
31−Examples
32−--------
33−
34− ~zod/try=> (mo `(list ,[@t *])`[[`a` 1] [`b` 2] ~])
35− {[p=`a` q=1] [p=`b` q=2]}
36−
37−------------------------------------------------------------------------
38−
39−### `++sa`
40−
41−Set from list
42−
43−Produces a set of the elements in list `a`.
44−
45−Accepts
46−-------
47−
48−`a` is a [list]().
49−
50−Produces
51−--------
52−
53−A [`++set`]().
54−
55−Source
56−------
57−
58− ++ sa :: set from list
59− |* a=(list)
60− => .(a `_(homo a)`a)
61− =+ b=*(set ,_?>(?=(^ a) i.a))
62− (~(gas in b) a)
63− ::
64−
65−
66−Examples
67−--------
68−
69− ~zod/try=> (sa `(list ,@)`[1 2 3 4 5 ~])
70− {5 4 1 3 2}
71− ~zod/try=> (sa `(list ,[@t *])`[[`a` 1] [`b` 2] ~])
72− {[`a` 1] [`b` 2]}
73−
74−------------------------------------------------------------------------
75−
76−### `++qu`
77−
78−Queue from list
79−
80−Produces a queue from list `a`.
81−
82−Accepts
83−-------
84−
85−`a` is a [list]().
86−
87−Produces
88−--------
89−
90−A [`++que`]().
91−
92−Source
93−------
94−
95− ++ qu :: queue from list
96− |* a=(list)
97− => .(a `_(homo a)`a)
98− =+ b=*(qeu ,_?>(?=(^ a) i.a))
99− (~(gas to b) a)
100−
101−
102−Examples
103−--------
104−
105− ~zod/try=> (qu `(list ,@ud)`~[1 2 3 5])
106− {5 3 2 1}
107− ~zod/try=> (qu "sada")
108− {'a' 'd' 'a' 's'}
109− ~zod/try=> ~(top to (qu "sada"))
110− [~ 's']
111−
112−------------------------------------------------------------------------
docs/dev/hoon/library/2eb.mddeleted−93
@@ -1,93 +0,0 @@
1−section 2eB, parsing (tracing)
2−==============================
3−
4−### `++last`
5−
6−Farther trace
7−
8−Compares two line-column pairs, called [`++hair`]()s, `zyc` and `naz`, producing whichever
9−is further along.
10−
11−Accepts
12−-------
13−
14−`naz` is a [hair]().
15−
16−`zyc` is a [hair]().
17−
18−Produces
19−--------
20−
21−a `++hair`.
22−
23−Source
24−------
25−
26− ++ last |= [zyc=hair naz=hair] :: farther trace
27− ^- hair
28− ?: =(p.zyc p.naz)
29− ?:((gth q.zyc q.naz) zyc naz)
30− ?:((gth p.zyc p.naz) zyc naz)
31− ::
32−
33−
34−Examples
35−--------
36−
37− ~zod/try=> (last [1 1] [1 2])
38− [p=1 q=2]
39− ~zod/try=> (last [2 1] [1 2])
40− [p=2 q=1]
41− ~zod/try=> (last [0 0] [99 0])
42− [p=99 q=0]
43− ~zod/try=> (last [7 7] [7 7])
44− [p=7 q=7]
45−
46−------------------------------------------------------------------------
47−
48−### `++lust`
49−
50−Detect newline
51−
52−Advances the [`++hair`]() `naz` by a row if the [`++char`]() `weq` is a newline, or by a
53−column if `weq` is any other character.
54−
55−Accepts
56−-------
57−
58−`weq` is a char.
59−
60−`naz` is a hair.
61−
62−Produces
63−--------
64−
65−A hair.
66−
67−Source
68−------
69−
70− ++ lust |= [weq=char naz=hair] :: detect newline
71− ^- hair
72− ?:(=(10 weq) [+(p.naz) 1] [p.naz +(q.naz)])
73−
74−
75−Examples
76−--------
77−
78− ~zod/try=> (lust `a` [1 1])
79− [p=1 q=2]
80− ~zod/try=> (lust `@t`10 [1 1])
81− [p=2 q=1]
82− ~zod/try=> (lust '9' [10 10])
83− [p=10 q=11]
84− /~zod/try=> (roll "maze" [.(+<+ [1 1])]:lust)
85− [1 5]
86− /~zod/try=> %- roll :_ [.(+<+ [1 1])]:lust
87− """
88− Sam
89− lokes
90− """
91− [2 6]
92−
93−------------------------------------------------------------------------
docs/dev/hoon/library/2ee.mddeleted−305
@@ -1,305 +0,0 @@
1−section 2ee, parsing (composers)
2−================================
3−
4−### `++bass`
5−
6−Parser modifier: [LSB](http://en.wikipedia.org/wiki/Least_significant_bit)
7−ordered [`++list`]() as atom of a [`++base`]().
8−
9−Accepts
10−-------
11−
12−`wuc` is an atom.
13−
14−`tyd` is a [`++rule`]().
15−
16−Produces
17−--------
18−
19−A [`++rule`]().
20−
21−Source
22−------
23−
24− ++ bass
25− |* [wuc=@ tyd=_rule]
26− %+ cook
27− |= waq=(list ,@)
28− %+ roll
29− waq
30− =|([p=@ q=@] |.((add p (mul wuc q))))
31− tyd
32−
33−Examples
34−--------
35−
36− ~zod/try=> (scan "123" (bass 10 (star dit)))
37− q=123
38− ~zod/try=> (scan "123" (bass 8 (star dit)))
39− q=83
40− ~zod/try=> `@ub`(scan "123" (bass 8 (star dit)))
41− 0b101.0011
42−
43−------------------------------------------------------------------------
44−
45−### `++boss`
46−
47−Parser modifier: [LSB](http://en.wikipedia.org/wiki/Least_significant_bit)
48−ordered [`++list`]() as atom of a [`++base`]().
49−
50−Accepts
51−-------
52−
53−`wuc` is an atom.
54−
55−`tyd` is a [`++rule`]().
56−
57−Produces
58−--------
59−
60−A [`++rule`]().
61−
62−Source
63−------
64−
65− ++ boss
66− |* [wuc=@ tyd=_rule]
67− %+ cook
68− |= waq=(list ,@)
69− %+ reel
70− waq
71− =|([p=@ q=@] |.((add p (mul wuc q))))
72− tyd
73−
74−Examples
75−--------
76−
77− ~zod/try=> (scan "123" (boss 10 (star dit)))
78− q=321
79− ~zod/try=> `@t`(scan "bam" (boss 256 (star alp)))
80− 'bam'
81− ~zod/try=> `@ux`(scan "bam" (boss 256 (star alp)))
82− 0x6d.6162
83−
84−------------------------------------------------------------------------
85−
86−### `++ifix`
87−
88−Surround
89−
90−Parser modifier: surround with pair of [`++rule`]()s, the output of which is
91−discarded.
92−
93−Accepts
94−-------
95−
96−`fel` is a pair of `++rule`s.
97−
98−`hof` is a `++rule`.
99−
100−Produces
101−--------
102−
103−A `++rule`.
104−
105−Source
106−------
107−
108− ++ ifix
109− |* [fel=[p=_rule q=_rule] hof=_rule]
110− ;~(pfix p.fel ;~(sfix hof q.fel))
111−
112−Examples
113−--------
114−
115− ~zod/try=> (scan "-40-" (ifix [hep hep] dem))
116− q=40
117− ~zod/try=> (scan "4my4" (ifix [dit dit] (star alf)))
118− "my"
119−
120−------------------------------------------------------------------------
121−
122−### `++more`
123−
124−Parse list with delimiter
125−
126−Parser modifier: Parse a list of matches using a delimiter [`++rule`]().
127−
128−Accepts
129−-------
130−
131−`bus` is a `++rule`.
132−
133−`fel` is a `++rule`.
134−
135−Produces
136−--------
137−
138−A `++rule`.
139−
140−Source
141−------
142−
143− ++ more
144− |* [bus=_rule fel=_rule]
145− ;~(pose (most bus fel) (easy ~))
146−
147−Examples
148−--------
149−
150− ~zod/try=> (scan "" (more ace dem))
151− ~
152− ~zod/try=> (scan "40 20" (more ace dem))
153− [q=40 ~[q=20]]
154− ~zod/try=> (scan "40 20 60 1 5" (more ace dem))
155− [q=40 ~[q=20 q=60 q=1 q=5]]
156−
157−------------------------------------------------------------------------
158−
159−### `++most`
160−
161−Parse list of at least one match
162−
163−Parser modifier: parse a [`++list`]() of at least one match using a delimiter [`++rule`]().
164−
165−Accepts
166−-------
167−
168−`bus` is a `++rule`.
169−
170−`fel` is a `++rule`.
171−
172−Produces
173−--------
174−
175−A `++rule`.
176−
177−Source
178−------
179−
180− ++ most
181− |* [bus=_rule fel=_rule]
182− ;~(plug fel (star ;~(pfix bus fel)))
183−
184−Examples
185−--------
186−
187− ~zod/try=> (scan "40 20" (most ace dem))
188− [q=40 ~[q=20]]
189− ~zod/try=> (scan "40 20 60 1 5" (most ace dem))
190− [q=40 ~[q=20 q=60 q=1 q=5]]
191− ~zod/try=> (scan "" (most ace dem))
192− ! {1 1}
193− ! exit
194−
195−------------------------------------------------------------------------
196−
197−### `++plus`
198−
199−List of at least one match.
200−
201−Parser modifier: parse [`++list`]() of at least one match.
202−
203−Accepts
204−-------
205−
206−`fel` is a [`++rule`]().
207−
208−Produces
209−--------
210−
211−A `++rule`.
212−
213−Source
214−------
215−
216− ++ plus |*(fel=_rule ;~(plug fel (star fel)))
217−
218−Examples
219−--------
220−
221− ~zod/try=> (scan ">>>>" (cook lent (plus gar)))
222− 4
223− ~zod/try=> (scan "- - " (plus ;~(pose ace hep)))
224− [~~- " - "]
225− ~zod/try=> `tape`(scan "- - " (plus ;~(pose ace hep)))
226− "- - "
227− ~zod/try=> `(pole ,@t)`(scan "- - " (plus ;~(pose ace hep)))
228− ['-' [' ' [' ' ['-' [' ' ~]]]]]
229−
230−------------------------------------------------------------------------
231−
232−### `++slug`
233−
234−Use gate to parse delimited list
235−
236−Parser modifier: By composing with a [gate](), parse a delimited [`++list`]() of
237−matches.
238−
239−Accepts
240−-------
241−
242−`bus` is a [`++rule`]().
243−
244−`fel` is a `++rule`.
245−
246−Produces
247−--------
248−
249−A `++rule`.
250−
251−Source
252−------
253−
254− ++ slug
255− |* raq=_|*([a=* b=*] [a b])
256− |* [bus=_rule fel=_rule]
257− ;~((comp raq) fel (stir +<+.raq raq ;~(pfix bus fel)))
258−
259−Examples
260−--------
261−
262− ~zod/try=> (scan "20+5+110" ((slug add) lus dem))
263− 135
264− ~zod/try=> `@t`(scan "a b c" ((slug |=(a=[@ @t] (cat 3 a))) ace alp))
265− 'abc'
266−
267−------------------------------------------------------------------------
268−
269−### `++star`
270−
271−List of matches
272−
273−Parser modifier: parse [`++list`]() of matches.
274−
275−Accepts
276−-------
277−
278−`fel` is a [`++rule`]().
279−
280−Produces
281−--------
282−
283− ++ star :: 0 or more times
284− |* fel=_rule
285− (stir `(list ,_(wonk *fel))`~ |*([a=* b=*] [a b]) fel)
286−
287−Examples
288−--------
289−
290− ~zod/try=> (scan "aaaaa" (just 'a'))
291− ! {1 2}
292− ! 'syntax-error'
293− ! exit
294− ~zod/try=> (scan "aaaaa" (star (just 'a')))
295− "aaaaa"
296− ~zod/try=> (scan "abcdef" (star (just 'a')))
297− ! {1 2}
298− ! 'syntax-error'
299− ! exit
300− ~zod/try=> (scan "abcabc" (star (jest 'abc')))
301− <|abc abc|>
302− ~zod/try=> (scan "john smith" (star (shim 0 200)))
303− "john smith"
304−
305−------------------------------------------------------------------------
docs/dev/hoon/library/2eg.mddeleted−211

This diff is too big to show here.

docs/dev/hoon/library/2eh.mddeleted−686

This diff is too big to show here.

docs/dev/hoon/library/2ei.mddeleted−163

This diff is too big to show here.

docs/dev/hoon/library/2ek.mddeleted−264

This diff is too big to show here.

docs/dev/hoon/library/2el.mddeleted−2863

This diff is too big to show here.

docs/dev/hoon/library/2em.mddeleted−758

This diff is too big to show here.

docs/dev/hoon/library/2eo.mddeleted−578

This diff is too big to show here.

docs/dev/hoon/library/2ez.mddeleted−250

This diff is too big to show here.

docs/dev/hoon/library/3bc.mddeleted−526

This diff is too big to show here.

docs/dev/hoon/library/3bd.mddeleted−2922

This diff is too big to show here.

docs/dev/hoon/library/3be.mddeleted−1316

This diff is too big to show here.

docs/dev/hoon/library/3bf.mddeleted−394

This diff is too big to show here.

docs/dev/hoon/library/3bh.mddeleted−572

This diff is too big to show here.

docs/dev/hoon/library/3bi.mddeleted−3559

This diff is too big to show here.

docs/dev/hoon/principles.mddeleted−18

This diff is too big to show here.

docs/dev/hoon/principles/0-nouns.mddeleted−286

This diff is too big to show here.

docs/dev/hoon/principles/1-twigs.mddeleted−286

This diff is too big to show here.

docs/dev/hoon/principles/2-syntax.mddeleted−476

This diff is too big to show here.

docs/dev/hoon/principles/3-program.mddeleted−350

This diff is too big to show here.

docs/dev/hoon/principles/4-functions.mddeleted−327

This diff is too big to show here.

docs/dev/hoon/reference.mddeleted−7

This diff is too big to show here.

docs/dev/hoon/reference/cheat-sheet.mddeleted−532

This diff is too big to show here.

docs/dev/hoon/reference/odors.mddeleted−686

This diff is too big to show here.

docs/dev/hoon/reference/pronunciation.mddeleted−68

This diff is too big to show here.

docs/dev/hoon/runes.mddeleted−132

This diff is too big to show here.

docs/dev/hoon/runes/bc/bcbr.mddeleted−41

This diff is too big to show here.

docs/dev/hoon/runes/bc/bccb.mddeleted−52

This diff is too big to show here.

docs/dev/hoon/runes/bc/bccl.mddeleted−44

This diff is too big to show here.

docs/dev/hoon/runes/bc/bccn.mddeleted−52

This diff is too big to show here.

docs/dev/hoon/runes/bc/bcls.mddeleted−57

This diff is too big to show here.

docs/dev/hoon/runes/bc/bcpm.mddeleted−30

This diff is too big to show here.

docs/dev/hoon/runes/bc/bctr.mddeleted−41

This diff is too big to show here.

docs/dev/hoon/runes/bc/bcts.mddeleted−59

This diff is too big to show here.

docs/dev/hoon/runes/bc/bcwt.mddeleted−42

This diff is too big to show here.

docs/dev/hoon/runes/br/brcb.mddeleted−99

This diff is too big to show here.

docs/dev/hoon/runes/br/brcn.mddeleted−115

This diff is too big to show here.

docs/dev/hoon/runes/br/brdt.mddeleted−101

This diff is too big to show here.

docs/dev/hoon/runes/br/brfs.mddeleted−89

This diff is too big to show here.

docs/dev/hoon/runes/br/brhp.mddeleted−62

This diff is too big to show here.

docs/dev/hoon/runes/br/brkt.mddeleted−85

This diff is too big to show here.

docs/dev/hoon/runes/br/brls.mddeleted−49

This diff is too big to show here.

docs/dev/hoon/runes/br/brtr.mddeleted−58

This diff is too big to show here.

docs/dev/hoon/runes/br/brts.mddeleted−60

This diff is too big to show here.

docs/dev/hoon/runes/br/brwt.mddeleted−48

This diff is too big to show here.

docs/dev/hoon/runes/cl/clcb.mddeleted−50

This diff is too big to show here.

docs/dev/hoon/runes/cl/clfs.mddeleted−37

This diff is too big to show here.

docs/dev/hoon/runes/cl/clhp.mddeleted−79

This diff is too big to show here.

docs/dev/hoon/runes/cl/clkt.mddeleted−61

This diff is too big to show here.

docs/dev/hoon/runes/cl/clls.mddeleted−54

This diff is too big to show here.

docs/dev/hoon/runes/cl/clsg.mddeleted−67

This diff is too big to show here.

docs/dev/hoon/runes/cl/cltr.mddeleted−56

This diff is too big to show here.

docs/dev/hoon/runes/cn/cncb.mddeleted−74

This diff is too big to show here.

docs/dev/hoon/runes/cn/cndt.mddeleted−53

This diff is too big to show here.

docs/dev/hoon/runes/cn/cnhp.mddeleted−46

This diff is too big to show here.

docs/dev/hoon/runes/cn/cnkt.mddeleted−29

This diff is too big to show here.

docs/dev/hoon/runes/cn/cnls.mddeleted−52

This diff is too big to show here.

docs/dev/hoon/runes/cn/cnsg.mddeleted−77

This diff is too big to show here.

docs/dev/hoon/runes/cn/cntr.mddeleted−48

This diff is too big to show here.

docs/dev/hoon/runes/cn/cnts.mddeleted−68

This diff is too big to show here.

docs/dev/hoon/runes/dt/dtkt.mddeleted−51

This diff is too big to show here.

docs/dev/hoon/runes/dt/dtls.mddeleted−66

This diff is too big to show here.

docs/dev/hoon/runes/dt/dttr.mddeleted−50

This diff is too big to show here.

docs/dev/hoon/runes/dt/dtts.mddeleted−71

This diff is too big to show here.

docs/dev/hoon/runes/dt/dtwt.mddeleted−53

This diff is too big to show here.

docs/dev/hoon/runes/dt/dtzy.mddeleted−47

This diff is too big to show here.

docs/dev/hoon/runes/dt/dtzz.mddeleted−47

This diff is too big to show here.

docs/dev/hoon/runes/hx/hxgl.mddeleted−61

This diff is too big to show here.

docs/dev/hoon/runes/hx/hxgr.mddeleted−83

This diff is too big to show here.

docs/dev/hoon/runes/kt/ktbr.mddeleted−46

This diff is too big to show here.

docs/dev/hoon/runes/kt/ktdt.mddeleted−38

This diff is too big to show here.

docs/dev/hoon/runes/kt/kthp.mddeleted−58

This diff is too big to show here.

docs/dev/hoon/runes/kt/ktls.mddeleted−67

This diff is too big to show here.

docs/dev/hoon/runes/kt/ktpm.mddeleted−46

This diff is too big to show here.

docs/dev/hoon/runes/kt/ktsg.mddeleted−41

This diff is too big to show here.

docs/dev/hoon/runes/kt/ktts.mddeleted−53

This diff is too big to show here.

docs/dev/hoon/runes/kt/ktwt.mddeleted−36

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgbc.mddeleted−37

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgbr.mddeleted−28

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgcb.mddeleted−36

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgcn.mddeleted−55

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgfs.mddeleted−38

This diff is too big to show here.

docs/dev/hoon/runes/sg/sggl.mddeleted−45

This diff is too big to show here.

docs/dev/hoon/runes/sg/sggr.mddeleted−43

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgls.mddeleted−44

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgpm.mddeleted−63

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgts.mddeleted−44

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgwt.mddeleted−59

This diff is too big to show here.

docs/dev/hoon/runes/sg/sgzp.mddeleted−59

This diff is too big to show here.

docs/dev/hoon/runes/sm.mddeleted−42

This diff is too big to show here.

docs/dev/hoon/runes/sm/smcl.mddeleted−65

This diff is too big to show here.

docs/dev/hoon/runes/sm/smcn.mddeleted−82

This diff is too big to show here.

docs/dev/hoon/runes/sm/smdq.mddeleted−46

This diff is too big to show here.

docs/dev/hoon/runes/sm/smhp.mddeleted−45

This diff is too big to show here.

docs/dev/hoon/runes/sm/smls.mddeleted−48

This diff is too big to show here.

docs/dev/hoon/runes/sm/smsg.mddeleted−157

This diff is too big to show here.

docs/dev/hoon/runes/sm/smsm.mddeleted−47

This diff is too big to show here.

docs/dev/hoon/runes/sm/smtr.mddeleted−50

This diff is too big to show here.

docs/dev/hoon/runes/sm/smzz.mddeleted−79

This diff is too big to show here.

docs/dev/hoon/runes/ts/tsbr.mddeleted−47

This diff is too big to show here.

docs/dev/hoon/runes/ts/tscl.mddeleted−43

This diff is too big to show here.

docs/dev/hoon/runes/ts/tsdt.mddeleted−52

This diff is too big to show here.

docs/dev/hoon/runes/ts/tsgl.mddeleted−60

This diff is too big to show here.

docs/dev/hoon/runes/ts/tsgr.mddeleted−57

This diff is too big to show here.

docs/dev/hoon/runes/ts/tshp.mddeleted−55

This diff is too big to show here.

docs/dev/hoon/runes/ts/tskt.mddeleted−67

This diff is too big to show here.

docs/dev/hoon/runes/ts/tsls.mddeleted−56

This diff is too big to show here.

docs/dev/hoon/runes/ts/tssg.mddeleted−45

This diff is too big to show here.

docs/dev/hoon/runes/ts/tstr.mddeleted−48

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtbr.mddeleted−54

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtcl.mddeleted−38

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtdt.mddeleted−45

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtgl.mddeleted−40

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtgr.mddeleted−40

This diff is too big to show here.

docs/dev/hoon/runes/wt/wthp.mddeleted−85

This diff is too big to show here.

docs/dev/hoon/runes/wt/wthz.mddeleted−52

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtkt.mddeleted−62

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtkz.mddeleted−34

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtls.mddeleted−104

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtlz.mddeleted−35

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtpm.mddeleted−48

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtpt.mddeleted−53

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtpz.mddeleted−34

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtsg.mddeleted−46

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtsz.mddeleted−37

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtts.mddeleted−39

This diff is too big to show here.

docs/dev/hoon/runes/wt/wttz.mddeleted−35

This diff is too big to show here.

docs/dev/hoon/runes/wt/wtzp.mddeleted−46

This diff is too big to show here.

docs/dev/hoon/runes/zp/zpcb.mddeleted−57

This diff is too big to show here.

docs/dev/hoon/runes/zp/zpcm.mddeleted−31

This diff is too big to show here.

docs/dev/hoon/runes/zp/zpfs.mddeleted−59

This diff is too big to show here.

docs/dev/hoon/runes/zp/zpgr.mddeleted−57

This diff is too big to show here.

docs/dev/hoon/runes/zp/zpsm.mddeleted−38

This diff is too big to show here.

docs/dev/hoon/runes/zp/zpts.mddeleted−50

This diff is too big to show here.

docs/dev/hoon/runes/zp/zpwt.mddeleted−39

This diff is too big to show here.

docs/dev/hoon/runes/zp/zpzp.mddeleted−42

This diff is too big to show here.

docs/dev/interpreter.mddeleted−12

This diff is too big to show here.

docs/dev/nock.mddeleted−52

This diff is too big to show here.

docs/dev/nock/reference.mddeleted−737

This diff is too big to show here.

docs/dev/nock/tutorial.mddeleted−1044

This diff is too big to show here.

docs/hoon.mdnew file+8

This diff is too big to show here.

docs/hoon/advanced.mdnew file+198

This diff is too big to show here.

docs/hoon/basic.mdnew file+183

This diff is too big to show here.

docs/hoon/concepts.mdnew file+236

This diff is too big to show here.

docs/hoon/demo.mdnew file+63

This diff is too big to show here.

docs/hoon/examples.mdnew file+597

This diff is too big to show here.

docs/hoon/exercises.mdnew file+16

This diff is too big to show here.

docs/hoon/exercises/data-structures.mdnew file+62

This diff is too big to show here.

docs/hoon/exercises/fizzbuzz.mdnew file+38

This diff is too big to show here.

docs/hoon/exercises/life.mdnew file+121

This diff is too big to show here.

docs/hoon/exercises/lists.mdnew file+40

This diff is too big to show here.

docs/hoon/exercises/math.mdnew file+27

This diff is too big to show here.

docs/hoon/library.mdnew file+9

This diff is too big to show here.

docs/hoon/library/1a.mdnew file+509

This diff is too big to show here.

docs/hoon/library/1b.mdnew file+147

This diff is too big to show here.

docs/hoon/library/1c.mdnew file+292

This diff is too big to show here.

docs/hoon/library/2a.mdnew file+457

This diff is too big to show here.

docs/hoon/library/2b.mdnew file+900

This diff is too big to show here.

docs/hoon/library/2c.mdnew file+676

This diff is too big to show here.

docs/hoon/library/2d.mdnew file+227

This diff is too big to show here.

docs/hoon/library/2e.mdnew file+160

This diff is too big to show here.

docs/hoon/library/2f.mdnew file+279

This diff is too big to show here.

docs/hoon/library/2g.mdnew file+6

This diff is too big to show here.

docs/dev/hoon/library/2da.md → docs/hoon/library/2h.mdrenamed+112−140

This diff is too big to show here.

docs/hoon/library/2i.mdnew file+589

This diff is too big to show here.

docs/hoon/library/2j.mdnew file+224

This diff is too big to show here.

docs/dev/hoon/library/2dc.md → docs/hoon/library/2k.mdrenamed+71−62

This diff is too big to show here.

docs/hoon/library/2l.mdnew file+6

This diff is too big to show here.

docs/hoon/library/2m.mdnew file+6

This diff is too big to show here.

docs/hoon/library/2n.mdnew file+201

This diff is too big to show here.

docs/hoon/library/2o.mdnew file+151

This diff is too big to show here.

docs/dev/hoon/library/2ea.md → docs/hoon/library/2p.mdrenamed+46−40

This diff is too big to show here.

docs/hoon/library/2q.mdnew file+256

This diff is too big to show here.

docs/hoon/library/3a.mdnew file+947

This diff is too big to show here.

docs/hoon/library/3b.mdnew file+6

This diff is too big to show here.

docs/hoon/library/3c.mdnew file+600

This diff is too big to show here.

docs/dev/hoon/library/2ey.md → docs/hoon/library/3d.mdrenamed+111−160

This diff is too big to show here.

docs/dev/hoon/library/2ex.md → docs/hoon/library/3e.mdrenamed+20−71

This diff is too big to show here.

docs/dev/hoon/library/2en.md → docs/hoon/library/3f.mdrenamed+315−296

This diff is too big to show here.

docs/hoon/library/3g.mdnew file+339

This diff is too big to show here.

docs/hoon/library/4a.mdnew file+211

This diff is too big to show here.

docs/dev/hoon/library/2ej.md → docs/hoon/library/4b.mdrenamed+427−255

This diff is too big to show here.

docs/hoon/library/4c.mdnew file+361

This diff is too big to show here.

docs/hoon/library/4d.mdnew file+98

This diff is too big to show here.

docs/dev/hoon/library/2ed.md → docs/hoon/library/4e.mdrenamed+149−102

This diff is too big to show here.

docs/dev/hoon/library/2ec.md → docs/hoon/library/4f.mdrenamed+493−232

This diff is too big to show here.

docs/hoon/library/4g.mdnew file+175

This diff is too big to show here.

docs/dev/hoon/library/2ef.md → docs/hoon/library/4h.mdrenamed+246−210

This diff is too big to show here.

docs/hoon/library/4i.mdnew file+6

This diff is too big to show here.

docs/hoon/library/4j.mdnew file+1656

This diff is too big to show here.

docs/hoon/library/4k.mdnew file+1268

This diff is too big to show here.

docs/hoon/library/4l.mdnew file+603

This diff is too big to show here.

docs/hoon/library/4m.mdnew file+421

This diff is too big to show here.

docs/hoon/library/4n.mdnew file+459

This diff is too big to show here.

docs/hoon/library/4o.mdnew file+728

This diff is too big to show here.

docs/hoon/library/5a.mdnew file+6

This diff is too big to show here.

docs/hoon/library/5b.mdnew file+6

This diff is too big to show here.

docs/hoon/library/5c.mdnew file+6

This diff is too big to show here.

docs/hoon/library/5d.mdnew file+6

This diff is too big to show here.

docs/hoon/library/5e.mdnew file+6

This diff is too big to show here.

docs/hoon/library/5f.mdnew file+178

This diff is too big to show here.

docs/hoon/library/5g.mdnew file+5

This diff is too big to show here.

docs/hoon/library/zuse.mdnew file+8

This diff is too big to show here.

docs/dev/hoon/library/3bb.md → docs/hoon/library/zuse/core/crua.mdrenamed+5−2

This diff is too big to show here.

docs/dev/hoon/library/3bg.md → docs/hoon/library/zuse/core/epur.mdrenamed+4−539

This diff is too big to show here.

docs/dev/hoon/library/3ba.md → docs/hoon/library/zuse/core/fu.mdrenamed+8−2

This diff is too big to show here.

docs/hoon/library/zuse/core/jo.mdnew file+953

This diff is too big to show here.

docs/hoon/library/zuse/core/poja.mdnew file+720

This diff is too big to show here.

docs/hoon/library/zuse/core/poxa.mdnew file+445

This diff is too big to show here.

docs/hoon/library/zuse/core/poxo.mdnew file+260

This diff is too big to show here.

docs/hoon/library/zuse/core/yu.mdnew file+217

This diff is too big to show here.

docs/dev/hoon/library/2ep.md → docs/hoon/library/zuse/diff.mdrenamed+8−2

This diff is too big to show here.

docs/hoon/library/zuse/gate/clan.mdnew file+45

This diff is too big to show here.

docs/hoon/library/zuse/gate/dawn.mdnew file+44

This diff is too big to show here.

docs/hoon/library/zuse/gate/daws.mdnew file+42

This diff is too big to show here.

docs/hoon/library/zuse/gate/deal.mdnew file+49

This diff is too big to show here.

docs/hoon/library/zuse/gate/deft.mdnew file+53

This diff is too big to show here.

docs/hoon/library/zuse/gate/dust.mdnew file+47

This diff is too big to show here.

docs/hoon/library/zuse/gate/earl.mdnew file+45

This diff is too big to show here.

docs/hoon/library/zuse/gate/earn.mdnew file+185

This diff is too big to show here.

docs/hoon/library/zuse/gate/fain.mdnew file+61

This diff is too big to show here.

docs/hoon/library/zuse/gate/feel.mdnew file+52

This diff is too big to show here.

docs/hoon/library/zuse/gate/file.mdnew file+49

This diff is too big to show here.

docs/hoon/library/zuse/gate/foal.mdnew file+48

This diff is too big to show here.

docs/hoon/library/zuse/gate/fray.mdnew file+43

This diff is too big to show here.

docs/hoon/library/zuse/gate/fuel.mdnew file+82

This diff is too big to show here.

docs/hoon/library/zuse/gate/furl.mdnew file+55

This diff is too big to show here.

docs/hoon/library/zuse/gate/glam.mdnew file+89

This diff is too big to show here.

docs/hoon/library/zuse/gate/glon.mdnew file+221

This diff is too big to show here.

docs/hoon/library/zuse/gate/gnom.mdnew file+43

This diff is too big to show here.

docs/hoon/library/zuse/gate/jape.mdnew file+43

This diff is too big to show here.

docs/hoon/library/zuse/gate/jesc.mdnew file+46

This diff is too big to show here.

docs/hoon/library/zuse/gate/joba.mdnew file+45

This diff is too big to show here.

docs/hoon/library/zuse/gate/jobe.mdnew file+39

This diff is too big to show here.

docs/hoon/library/zuse/gate/jone.mdnew file+45

This diff is too big to show here.

docs/hoon/library/zuse/gate/lead.mdnew file+53

This diff is too big to show here.

docs/hoon/library/zuse/gate/mang.mdnew file+60

This diff is too big to show here.

docs/hoon/library/zuse/gate/meat.mdnew file+53

This diff is too big to show here.

docs/hoon/library/zuse/gate/moon.mdnew file+45

This diff is too big to show here.

docs/hoon/library/zuse/gate/mung.mdnew file+60

This diff is too big to show here.

docs/hoon/library/zuse/gate/perk.mdnew file+54

This diff is too big to show here.

docs/hoon/library/zuse/gate/pojo.mdnew file+83

This diff is too big to show here.

docs/hoon/library/zuse/gate/saxo.mdnew file+42

This diff is too big to show here.

docs/hoon/library/zuse/gate/scanf.mdnew file+88

This diff is too big to show here.

docs/hoon/library/zuse/gate/sein.mdnew file+61

This diff is too big to show here.

docs/hoon/library/zuse/gate/sifo.mdnew file+51

This diff is too big to show here.

docs/hoon/library/zuse/gate/stud.mdnew file+63

This diff is too big to show here.

docs/hoon/library/zuse/gate/taco.mdnew file+32

This diff is too big to show here.

docs/hoon/library/zuse/gate/tact.mdnew file+39

This diff is too big to show here.

docs/hoon/library/zuse/gate/tame.mdnew file+59

This diff is too big to show here.

docs/hoon/library/zuse/gate/tell.mdnew file+44

This diff is too big to show here.

docs/hoon/library/zuse/gate/tome.mdnew file+51

This diff is too big to show here.

docs/hoon/library/zuse/gate/tope.mdnew file+35

This diff is too big to show here.

docs/hoon/library/zuse/gate/txml.mdnew file+37

This diff is too big to show here.

docs/hoon/library/zuse/gate/unt.mdnew file+40

This diff is too big to show here.

docs/hoon/library/zuse/gate/urld.mdnew file+53

This diff is too big to show here.

docs/hoon/library/zuse/gate/urle.mdnew file+56

This diff is too big to show here.

docs/hoon/library/zuse/mold/udal.mdnew file+15

This diff is too big to show here.

docs/hoon/library/zuse/mold/udon.mdnew file+20

This diff is too big to show here.

docs/hoon/library/zuse/mold/umph.mdnew file+18

This diff is too big to show here.

docs/hoon/library/zuse/mold/unce.mdnew file+13

This diff is too big to show here.

docs/hoon/library/zuse/mold/upas.mdnew file+17

This diff is too big to show here.

docs/hoon/library/zuse/mold/urge.mdnew file+12

This diff is too big to show here.

docs/dev/hoon/library/2ew.md → docs/hoon/library/zuse/rsa.mdrenamed+4−39

This diff is too big to show here.

docs/hoon/mission.mdnew file+46

This diff is too big to show here.

docs/hoon/reference.mdnew file+77

This diff is too big to show here.

docs/hoon/syntax.mdnew file+368

This diff is too big to show here.

docs/hoon/troubleshooting.mdnew file+189

This diff is too big to show here.

docs/hoon/twig.mdnew file+75

This diff is too big to show here.

docs/hoon/twig/atom.mdnew file+16

This diff is too big to show here.

docs/hoon/twig/atom/knit.mdnew file+45

This diff is too big to show here.

docs/hoon/twig/atom/path.mdnew file+30

This diff is too big to show here.

docs/hoon/twig/atom/rock.mdnew file+37

This diff is too big to show here.

docs/hoon/twig/atom/sand.mdnew file+57

This diff is too big to show here.

docs/hoon/twig/bar-core.mdnew file+19

This diff is too big to show here.

docs/hoon/twig/bar-core/cab-door.mdnew file+72

This diff is too big to show here.

docs/hoon/twig/bar-core/cen-core.mdnew file+43

This diff is too big to show here.

docs/hoon/twig/bar-core/dot-trap.mdnew file+54

This diff is too big to show here.

docs/hoon/twig/bar-core/hep-loop.mdnew file+44

This diff is too big to show here.

docs/hoon/twig/bar-core/tar-gill.mdnew file+49

This diff is too big to show here.

docs/hoon/twig/bar-core/tis-gate.mdnew file+44

This diff is too big to show here.

docs/hoon/twig/buc-mold.mdnew file+52

This diff is too big to show here.

docs/hoon/twig/buc-mold/base.mdnew file+33

This diff is too big to show here.

docs/hoon/twig/buc-mold/cab-shoe.mdnew file+41

This diff is too big to show here.

docs/hoon/twig/buc-mold/cen-book.mdnew file+44

This diff is too big to show here.

docs/hoon/twig/buc-mold/col-bank.mdnew file+43

This diff is too big to show here.

docs/hoon/twig/buc-mold/hep-lamb.mdnew file+37

This diff is too big to show here.

docs/hoon/twig/buc-mold/ket-bush.mdnew file+39

This diff is too big to show here.

docs/hoon/twig/buc-mold/pat-claw.mdnew file+41

This diff is too big to show here.

docs/hoon/twig/buc-mold/tis-coat.mdnew file+37

This diff is too big to show here.

docs/hoon/twig/buc-mold/wut-pick.mdnew file+47

This diff is too big to show here.

docs/hoon/twig/cen-call.mdnew file+15

This diff is too big to show here.

docs/hoon/twig/cen-call/cab-keep.mdnew file+39

This diff is too big to show here.

docs/hoon/twig/cen-call/dot-lace.mdnew file+25

This diff is too big to show here.

docs/hoon/twig/cen-call/hep-call.mdnew file+44

This diff is too big to show here.

docs/hoon/twig/cen-call/ket-calq.mdnew file+24

This diff is too big to show here.

docs/hoon/twig/cen-call/lus-calt.mdnew file+24

This diff is too big to show here.

docs/hoon/twig/cen-call/sig-open.mdnew file+35

This diff is too big to show here.

docs/hoon/twig/cen-call/tis-make.mdnew file+44

This diff is too big to show here.

docs/hoon/twig/col-cell.mdnew file+15

This diff is too big to show here.

docs/hoon/twig/col-cell/cab-scon.mdnew file+25

This diff is too big to show here.

docs/hoon/twig/col-cell/hep-cons.mdnew file+43

This diff is too big to show here.

docs/hoon/twig/col-cell/ket-conq.mdnew file+29

This diff is too big to show here.

docs/hoon/twig/col-cell/lus-cont.mdnew file+29

This diff is too big to show here.

docs/hoon/twig/col-cell/sig-conl.mdnew file+34

This diff is too big to show here.

docs/hoon/twig/col-cell/tar-conp.mdnew file+37

This diff is too big to show here.

docs/hoon/twig/dot-nock.mdnew file+13

This diff is too big to show here.

docs/hoon/twig/dot-nock/ket-wish.mdnew file+24

This diff is too big to show here.

docs/hoon/twig/dot-nock/lus-bump.mdnew file+30

This diff is too big to show here.

docs/hoon/twig/dot-nock/tar-nock.mdnew file+39

This diff is too big to show here.

docs/hoon/twig/dot-nock/tis-same.mdnew file+36

This diff is too big to show here.

docs/hoon/twig/dot-nock/wut-deep.mdnew file+25

This diff is too big to show here.

docs/hoon/twig/ket-cast.mdnew file+17

This diff is too big to show here.

docs/hoon/twig/ket-cast/bar-iron.mdnew file+40

This diff is too big to show here.

docs/hoon/twig/ket-cast/hep-cast.mdnew file+42

This diff is too big to show here.

docs/hoon/twig/ket-cast/lus-like.mdnew file+26

This diff is too big to show here.

docs/hoon/twig/ket-cast/sig-burn.mdnew file+25

This diff is too big to show here.

docs/hoon/twig/ket-cast/tis-name.mdnew file+33

This diff is too big to show here.

docs/hoon/twig/ket-cast/wut-lead.mdnew file+39

This diff is too big to show here.

docs/hoon/twig/limb.mdnew file+23

This diff is too big to show here.

docs/hoon/twig/limb/limb.mdnew file+70

This diff is too big to show here.

docs/hoon/twig/limb/wing.mdnew file+49

This diff is too big to show here.

docs/hoon/twig/sem-make.mdnew file+13

This diff is too big to show here.

docs/hoon/twig/sem-make/col-wad.mdnew file+31

This diff is too big to show here.

docs/hoon/twig/sem-make/fas-nub.mdnew file+20

This diff is too big to show here.

docs/hoon/twig/sem-make/sem-fry.mdnew file+49

This diff is too big to show here.

docs/hoon/twig/sem-make/sig-dip.mdnew file+64

This diff is too big to show here.

docs/hoon/twig/sig-hint.mdnew file+14

This diff is too big to show here.

docs/hoon/twig/sig-hint/bar-show.mdnew file+28

This diff is too big to show here.

docs/hoon/twig/sig-hint/buc-poll.mdnew file+27

This diff is too big to show here.

docs/hoon/twig/sig-hint/cab-lurk.mdnew file+28

This diff is too big to show here.

docs/hoon/twig/sig-hint/cen-fast.mdnew file+94

This diff is too big to show here.

docs/hoon/twig/sig-hint/fas-funk.mdnew file+31

This diff is too big to show here.

docs/hoon/twig/sig-hint/gal-thin.mdnew file+32

This diff is too big to show here.

docs/hoon/twig/sig-hint/gar-hint.mdnew file+38

This diff is too big to show here.

docs/hoon/twig/sig-hint/lus-memo.mdnew file+44

This diff is too big to show here.

docs/hoon/twig/sig-hint/pam-dump.mdnew file+28

This diff is too big to show here.

docs/hoon/twig/sig-hint/tis-ddup.mdnew file+35

This diff is too big to show here.

docs/hoon/twig/sig-hint/wut-warn.mdnew file+30

This diff is too big to show here.

docs/hoon/twig/sig-hint/zap-peep.mdnew file+30

This diff is too big to show here.

docs/hoon/twig/tis-flow.mdnew file+34

This diff is too big to show here.

docs/hoon/twig/tis-flow/bar-new.mdnew file+39

This diff is too big to show here.

docs/hoon/twig/tis-flow/col-fix.mdnew file+29

This diff is too big to show here.

docs/hoon/twig/tis-flow/dot-set.mdnew file+36

This diff is too big to show here.

docs/hoon/twig/tis-flow/fas-var.mdnew file+37

This diff is too big to show here.

docs/hoon/twig/tis-flow/gal-rap.mdnew file+29

This diff is too big to show here.

docs/hoon/twig/tis-flow/gar-per.mdnew file+25

This diff is too big to show here.

docs/hoon/twig/tis-flow/hep-nip.mdnew file+34

This diff is too big to show here.

docs/hoon/twig/tis-flow/ket-sip.mdnew file+42

This diff is too big to show here.

docs/hoon/twig/tis-flow/lus-pin.mdnew file+33

This diff is too big to show here.

docs/hoon/twig/tis-flow/sem-rev.mdnew file+30

This diff is too big to show here.

docs/hoon/twig/tis-flow/tar-aka.mdnew file+38

This diff is too big to show here.

docs/hoon/twig/wut-test.mdnew file+31

This diff is too big to show here.

docs/hoon/twig/wut-test/bar-or.mdnew file+31

This diff is too big to show here.

docs/hoon/twig/wut-test/col-if.mdnew file+43

This diff is too big to show here.

docs/hoon/twig/wut-test/dot-lest.mdnew file+40

This diff is too big to show here.

docs/hoon/twig/wut-test/gal-deny.mdnew file+28

This diff is too big to show here.

docs/hoon/twig/wut-test/gar-sure.mdnew file+27

This diff is too big to show here.

docs/hoon/twig/wut-test/hep-case.mdnew file+51

This diff is too big to show here.

docs/hoon/twig/wut-test/ket-ifcl.mdnew file+37

This diff is too big to show here.

docs/hoon/twig/wut-test/lus-deft.mdnew file+43

This diff is too big to show here.

docs/hoon/twig/wut-test/pam-and.mdnew file+31

This diff is too big to show here.

docs/hoon/twig/wut-test/pat-ifat.mdnew file+33

This diff is too big to show here.

docs/hoon/twig/wut-test/sig-ifno.mdnew file+34

This diff is too big to show here.

docs/hoon/twig/wut-test/tis-fits.mdnew file+41

This diff is too big to show here.

docs/hoon/twig/wut-test/zap-not.mdnew file+33

This diff is too big to show here.

docs/hoon/twig/zap-wild.mdnew file+11

This diff is too big to show here.

docs/hoon/twig/zap-wild/gar-wrap.mdnew file+28

This diff is too big to show here.

docs/hoon/twig/zap-wild/tis-code.mdnew file+27

This diff is too big to show here.

docs/hoon/twig/zap-wild/wut-need.mdnew file+28

This diff is too big to show here.

docs/hoon/twig/zap-wild/zap-fail.mdnew file+27

This diff is too big to show here.

docs/nock.mdnew file+9

This diff is too big to show here.

docs/nock/definition.mdnew file+168

This diff is too big to show here.

docs/nock/example.mdnew file+365

This diff is too big to show here.

docs/nock/explanation.mdnew file+562

This diff is too big to show here.

docs/nock/implementations.mdnew file+9

This diff is too big to show here.

docs/nock/implementations/c.mdnew file+212

This diff is too big to show here.

docs/nock/implementations/clojure.mdnew file+125

This diff is too big to show here.

docs/nock/implementations/haskell.mdnew file+63

This diff is too big to show here.

docs/nock/implementations/hoon.mdnew file+54

This diff is too big to show here.

docs/nock/implementations/python.mdnew file+95

This diff is too big to show here.

docs/nock/implementations/ruby.mdnew file+139

This diff is too big to show here.

docs/nock/implementations/scala.mdnew file+86

This diff is too big to show here.

docs/theory.mddeleted−26

This diff is too big to show here.

docs/theory/network-goals.mddeleted−565

This diff is too big to show here.

docs/theory/old.mddeleted−21

This diff is too big to show here.

docs/theory/part-i.mddeleted−512

This diff is too big to show here.

docs/theory/part-ii.mddeleted−462

This diff is too big to show here.

docs/theory/whitepaper.mddeleted−2347

This diff is too big to show here.

docs/user.mddeleted−25

This diff is too big to show here.

docs/user/appliance.mddeleted−274

This diff is too big to show here.

docs/user/basic.mddeleted−149

This diff is too big to show here.

docs/user/clay.mddeleted−418

This diff is too big to show here.

docs/user/dojo.mddeleted−547

This diff is too big to show here.

docs/user/launch.mddeleted−112

This diff is too big to show here.

docs/user/talk.mddeleted−313

This diff is too big to show here.

docs/user/tour.mddeleted−209

This diff is too big to show here.

docs/using.mdnew file+8

This diff is too big to show here.

docs/using/admin.mdnew file+99

This diff is too big to show here.

docs/using/filesystem.mdnew file+240

This diff is too big to show here.

docs/using/install.mdnew file+82

This diff is too big to show here.

docs/using/layout.mdnew file+107

This diff is too big to show here.

docs/using/messaging.mdnew file+194

This diff is too big to show here.

docs/using/setup.mdnew file+88

This diff is too big to show here.

docs/using/shell.mdnew file+277

This diff is too big to show here.

docs/using/web.mdnew file+299

This diff is too big to show here.

docs/using/web/blog.mdnew file+95

This diff is too big to show here.

docs/using/web/comments.mdnew file+43

This diff is too big to show here.

docs/using/web/static.mdnew file+127

This diff is too big to show here.