/- *plum, *xray /+ *plume, libxray=xray :: :: This code pretty-prints a variety of things using the `xray` and :: `plum` libraries: :: :: - `render-vase`: Renders the data in a vase.=$-(vase wain) :: - `render-hoon`: Pretty-prints a `hoon` AST as hoon code. :: - `render-type`: Pretty-prints a type as a hoon expression. :: - `render-type-simple`: Debug-print for the `type` structure. :: - `render-vase-with-type`: Pretty print a vase: both value and type. :: :: There's a lot of logic here, but most of it is fairly :: straight-forward. :: :: XX Output for cords is ugly. Why ~~a instead of 'a'? :: |^ ^- $: render-vase=$-(vase wain) render-hoon=$-(hoon wain) render-type=$-(type wain) type-to-plum=$-(type plum) type-to-tank=$-(type tank) vase-to-tank=$-(vase tank) render-type-simple=$-(type wain) render-vase-with-type=$-(vase wain) == :* render-vase render-hoon render-type type-to-plum type-to-tank vase-to-tank render-type-simple render-vase-with-type == :: +| %utils :: +$ battery (map term (pair what (map term hoon))) :: +| %render :: ++ render-vase-with-type |= =vase ^- wain :: =/ =ximage (xray-type:libxray 1 p.vase) :: :: ~& %noun-to-plum =/ val=plum (noun-to-plum ximage q.vase) :: :: ~& %type-to-plum =/ typ=plum (spec-to-plum (ximage-to-spec:libxray ximage)) :: =/ result=plum (sexp 'vase' (sexp 'type' typ ~) (sexp 'val' val ~) ~) :: :: ~& %convert-to-wain ~(tall plume result) :: ++ render-vase |= =vase ^- wain ~(tall plume (vase-to-plum vase)) :: ++ render-type-simple |= =type ^- wain ~(tall plume (type-to-plum-simple type 100)) :: ++ render-type |= =type ^- wain ~(tall plume (type-to-plum type)) :: :: Pretty-print a hoon. :: ++ render-hoon |= =hoon ^- wain ~(tall plume (hoon-to-plum 999 hoon)) :: :: Pretty-print a type given as a string. :: ++ render-type-from-cord |= =cord ^- wain =/ t=type -:(ride -:!>(..libxray) cord) ~(tall plume (type-to-plum t)) :: :: This is just a helper function for testing out this code. It just digs :: through a type and finds hoon values referenced within that type, :: and then renders the result. :: ++ render-all-hoons-inside-of-type |= =type ^- wain ?. ?=([%core *] type) [%zpzp ~] =* tomes=(list tome) ~(val by q.r.q.type) =* hoons=(list hoon) (turn tomes |=(t=tome [%cltr ~(val by q.t)])) ~(tall plume (hoon-to-plum 999 [%cltr hoons])) :: +| %to-plum :: :: Pretty-print a vase. :: ++ vase-to-plum |= v=vase ^- plum (noun-to-plum (xray-type:libxray 1 p.v) q.v) :: :: Pretty-print a type. :: ++ type-to-plum |= t=type ^- plum (spec-to-plum (ximage-to-spec:libxray (xray-type:libxray 1 t))) :: :: Pretty-print a type to a tank. :: ++ type-to-tank |= t=type ^- tank :+ %rose [~ ~ ~] %+ turn (render-type t) |=(=cord leaf+(trip cord)) :: :: Pretty-print a vase to a tank. :: ++ vase-to-tank |= v=vase ^- tank :+ %rose [~ ~ ~] %+ turn (render-vase v) |=(=cord leaf+(trip cord)) :: :: Render an `axis`. :: ++ axis-to-cord |= p=@ ^- cord ?: =(p 1) '.' ?: =(p 2) '-' ?: =(p 3) '+' (cat 3 '+' (scot %ud p)) :: :: Render a limb. A limb is either an empty atom (which is rendered as :: '$') or an axis. :: :: XX The code for handling the `%|` ("by name") case is obviously :: wrong (the `runt` call does nothing, for example), but I'm not sure :: what it was trying to do in the first place. :: ++ limb-to-plum |= =limb ^- plum ?@ limb ?: .=('' limb) '$' limb ?- -.limb %& (axis-to-cord p.limb) :: [%| p=@ud q=(unit term) ] %| (crip (runt [0 p.limb] ?~(q.limb "," (trip u.q.limb)))) == :: :: Render a wing :: ++ wing-to-plum |= =wing ^- plum :+ %tree [wide=`['.' ~] tall=~] (turn `^wing`wing limb-to-plum) :: :: In the spec for a battery, there's a `(map term spec)`. This :: transforms one of those into a list of plums, one per `term/spec` :: pair. :: ++ battery-spec-to-plum-list |= =(map term spec) %+ turn ~(tap by map) |= [=term =spec] :- %sbrk :+ %tree [wide=~ tall=`['' ~]] [term (spec-to-plum spec) ~] :: :: Given a rune and a spec for a core, transform that into a plum. :: ++ core-spec-to-plum |= [=knot =spec =(map term spec)] ^- plum :- %sbrk :+ %tree [~ `[knot ~]] :~ (spec-to-plum spec) :+ %tree [~ tall=`['' `['++' '--']]] (battery-spec-to-plum-list map) == :: :: Convert a "standard name" into a plum. :: ++ stud-to-plum |= =stud ^- plum ?@ stud stud :+ %tree [wide=`['/' ~] tall=~] `(list plum)`[auth.stud type.stud] :: :: Convert a woof (an interpolated expression inside of a string literal) :: to a plum. :: ++ woof-to-plum |= =woof ^- plum |^ ?@ woof woof =* fmt [wide=`[' ' `['{' '}']] tall=~] :+ %tree fmt (turn (unwrap-woof-tuple +.woof) |=(h=hoon (hoon-to-plum 999 h))) :: :: Woofs contain one or more hoons, and if there are more than one, :: it's encoded with a %cltr ast node. This just simplifies both :: cases down into a list of subhoons. :: ++ unwrap-woof-tuple |= =hoon ^- (list ^hoon) ?: ?=([%cltr *] hoon) p.hoon ~[hoon] -- :: :: This is just a trivial helper function. It's only here because this :: xpat is used repeatedly in `hoon-to-plum`. :: ++ hoons-to-plum-list |= =hoon=(list hoon) ^. (list plum) (turn hoon-list |=(h=hoon (hoon-to-plum 999 h))) :: :: XX Placeholder for rendering a chum to a plum. :: ++ chum-to-plum |= =chum ^- plum %todo-chum :: :: XX Placeholder for rendering a tyre to a plum :: ++ tyre-to-plum |= =tyre ^- plum %todo-tyre :: :: Generate a list of plums from a list of matches. This would be :: trivial, but we also need to append commas on each match (besides :: the last) when `matches` is rendered in wide mode. :: ++ matches-to-plum-list |= matches=(list (pair spec hoon)) ^- (list plum) %- add-trailing-commas-to-wide-form %+ turn matches |= [=spec =hoon] ^- (pair plum plum) [(spec-to-plum spec) (hoon-to-plum 999 hoon)] :: :: Generate a list of plums from a list of updates. This would be :: trivial, but we also need to append commas on each update (besides :: the last) when the update-list is rendered in wide mode. :: ++ updates-to-plum-list |= =update=(list (pair wing hoon)) ^- (list plum) %- add-trailing-commas-to-wide-form %+ turn update-list |= [=wing =hoon] ^- (pair plum plum) [(wing-to-plum wing) (hoon-to-plum 999 hoon)] :: :: This adds commas to a list of pair of hoons, but only in wide form. :: :: For example, in wide form with commas: :: :: %=($ a 1, b 2) :: :: In tall form without commas: :: :: %= $ a 1 b 2 == :: :: It's important that this not be wrapped in an %sbrk, since we need :: to be sure that this is rendered in wide mode if-and-only-if our :: parent is rendered in wide mode. :: ++ add-trailing-commas-to-wide-form |= plums=(list (pair plum plum)) =| acc=(list (list plum)) |^ ^- (list plum) ?~ plums (zing (flop acc)) =/ x=plum p.i.plums =/ y=plum q.i.plums ?~ t.plums $(plums t.plums, acc [~[x y] acc]) $(plums t.plums, acc [~[x (comma y)] acc]) ++ comma |= =sub=plum ^- plum :+ %tree :- [~ '' [~ '' ',']] [~ '' ~] ~[sub-plum] -- :: :: Render a hoon as a plum. Given the helper functions above, this is :: fairly straightforward. It is a big-ass switch, though. :: ++ hoon-to-plum |= [maxdepth=@ x=hoon] |^ ^- plum ?+ x %autocons [%$ @] (axis-to-cord p.x) [%base *] (spec [%base p.x]) [%bust *] (simple-wide '*' '' '' (spec [%base p.x]) ~) [%dbug *] (hn q.x) :: p.x is irrelevant [%eror *] %assembly-error [%hand *] %ast-node-hand [%note *] (hn q.x) :: p.x is irrelevant [%fits *] %ast-node-fits [%knit *] (simple-wide '"' '' '"' (turn p.x woof-to-plum)) [%leaf *] (spec x) [%limb *] p.x [%lost *] (hn p.x) :: for internal use [%rock *] ?^ q.x !! (cat 3 '%' (crip (scow p.x `@`q.x))) [%sand *] ?^ q.x !! (crip (scow p.x `@`q.x)) [%tell *] (simple-wide '<' ' ' '>' (hoons p.x)) [%tune *] ?@(p.x p.x %todo-tune) [%wing *] (simple-wide '' '.' '' (turn p.x limb)) [%yell *] (simple-wide '>' ' ' '<' (hoons p.x)) [%xray *] (xray-to-plum p.x) [%brcb *] (chapter '|_' `(spec p.x) r.x) :: skip aliases [%brcl *] (rune '|:' ~ ~ (hoons ~[p q]:x)) [%brcn *] (chapter '|%' ~ q.x) :: Ignoring p.x [%brdt *] (rune '|.' ~ ~ (hoons ~[p]:x)) [%brkt *] (chapter '|^' `(hn p.x) q.x) [%brhp *] (rune '|-' ~ ~ (hn p.x) ~) [%brsg *] (rune '|~' ~ ~ (spec p.x) (hn q.x) ~) [%brtr *] (rune '|*' ~ ~ (spec p.x) (hn q.x) ~) [%brts *] (rune '|=' ~ ~ (spec p.x) (hn q.x) ~) [%brpt *] (chapter '|@' ~ q.x) :: Ignoring p.x [%brwt *] (rune '|?' ~ ~ (hn p.x) ~) [%clcb *] (rune ':_' ~ ~ (hoons ~[p q]:x)) [%clkt *] (rune ':^' ~ ~ (hoons ~[p q r s]:x)) [%clhp *] (rune ':-' ~ `['[' spc ']'] (hoons ~[p q]:x)) [%clls *] (rune ':+' ~ `['[' spc ']'] (hoons ~[p q r]:x)) [%clsg *] (rune ':~' `'==' `['~[' spc ']'] (hoons p.x)) [%cltr *] ?~ p.x '~' ?~ +.p.x (hn -.p.x) (rune ':*' `'==' `['[' spc ']'] (hoons p.x)) [%cncb *] (rune '%_' `'==' ~ (wing p.x) (updates q.x)) [%cndt *] (rune '%.' ~ ~ (hoons ~[p q]:x)) [%cnhp *] (rune '%-' ~ `['(' spc ')'] (hoons ~[p q]:x)) [%cncl *] (rune '%:' `'==' `['(' spc ')'] (hoons [p q]:x)) [%cntr *] (rune '%*' `'==' ~ (wing p.x) (hn q.x) (updates r.x)) [%cnkt *] (rune '%^' ~ ~ (hoons ~[p q r s]:x)) [%cnls *] (rune '%+' ~ ~ (hoons ~[p q r]:x)) [%cnsg *] (rune '%~' `'==' `['~(' spc ')'] (wing p.x) (hoons [q r]:x)) [%cnts *] ?~ q.x (wing p.x) (rune '%=' `'==' ~ (wing p.x) (updates q.x)) [%dtkt *] (rune '.^' ~ ~ (spec p.x) (hn q.x) ~) [%dtls *] (rune '.+' ~ `['+(' spc ')'] (hoons ~[p]:x)) [%dttr *] (rune '.*' ~ ~ (hoons ~[p q]:x)) [%dtts *] (rune '.=' ~ `['=(' spc ')'] (hoons ~[p q]:x)) [%dtwt *] (rune '.?' ~ ~ (hoons ~[p.x])) [%ktbr *] (rune '^|' ~ ~ (hoons ~[p.x])) [%ktdt *] (rune '^.' ~ ~ (hoons ~[p q]:x)) [%ktls *] (rune '^+' ~ ~ (hoons ~[p q]:x)) [%kthp *] (rune '^-' ~ ~ ~[(spec p.x) (hn q.x)]) [%ktpm *] (rune '^&' ~ ~ (hoons ~[p]:x)) [%ktsg *] (rune '^~' ~ ~ (hoons ~[p]:x)) [%ktts *] (rune '^=' ~ `['' '=' ''] ~[(skin p.x) (hn q.x)]) [%ktwt *] (rune '^?' ~ ~ (hoons ~[p]:x)) [%kttr *] (rune '^*' ~ ~ ~[(spec p.x)]) [%ktcl *] (rune '^:' ~ ~ ~[(spec p.x)]) [%sgbr *] (rune '~|' ~ ~ (hoons ~[p q]:x)) [%sgcb *] (rune '~_' ~ ~ (hoons ~[p q]:x)) [%sgcn *] (rune '~%' ~ ~ (chum p.x) (hn q.x) (tyre r.x) (hn s.x) ~) [%sgfs *] (rune '~/' ~ ~ (chum p.x) (hn q.x) ~) [%sggl *] (rune '~<' ~ ~ (hint p.x) (hn q.x) ~) [%sggr *] (rune '~>' ~ ~ (hint p.x) (hn q.x) ~) [%sgbc *] (rune '~$' ~ ~ p.x (hn q.x) ~) [%sgls *] (rune '~+' ~ ~ (hn q.x) ~) :: Ignoring p.x [%sgpm *] (rune '~&' ~ ~ (hoons ~[q r]:x)) :: Ignoring p.x [%sgts *] (rune '~=' ~ ~ (hoons ~[p q]:x)) [%sgwt *] (rune '~?' ~ ~ (hoons ~[q r s]:x)) :: Ignoring p.x [%sgzp *] (rune '~!' ~ ~ (hoons ~[p q]:x)) [%mcts *] %ast-node-mcts [%mccl *] (rune ';:' `'==' `[':(' spc ')'] (hoons [p q]:x)) [%mcfs *] (rune ';/' ~ ~ (hoons ~[p]:x)) [%mcgl *] (rune ';<' ~ ~ (spec p.x) (hoons ~[q r s]:x)) [%mcsg *] (rune ';~' `'==' ~ (hoons [p q]:x)) [%mcmc *] (rune ';;' ~ ~ ~[(spec p.x) (hn q.x)]) [%tsbr *] (rune '=|' ~ ~ ~[(spec p.x) (hn q.x)]) [%tscl *] (tiscol-to-plum p.x q.x) [%tsfs *] (rune '=/' ~ ~ (skin p.x) (hn q.x) (hn r.x) ~) [%tsmc *] (rune '=;' ~ ~ [(skin p.x) (hoons ~[q r]:x)]) [%tsdt *] (rune '=.' ~ ~ [(wing p.x) (hoons ~[q r]:x)]) [%tswt *] (rune '=?' ~ ~ [(wing p.x) (hoons ~[q r s]:x)]) :: XX %tsld to %tsgl, but should be %tsgr? (to match =>) [%tsgl *] (rune '=>' ~ `['' ':' ''] (hoons ~[p q]:x)) [%tshp *] (rune '=-' ~ ~ (hoons ~[p q]:x)) :: XX %tsbn to %tsgr, but should be %tsgl? (to match =<) [%tsgr *] (rune '=<' ~ ~ (hoons ~[p q]:x)) [%tskt *] (rune '=^' ~ ~ [(skin p.x) (wing q.x) (hoons ~[r s]:x)]) [%tsls *] (rune '=+' ~ ~ (hoons ~[p q]:x)) [%tssg *] (rune '=~' `'==' ~ (hoons p:x)) [%tstr *] ?~ q.p.x (rune '=*' ~ ~ p.p.x (hoons ~[q r]:x)) (rune '=*' ~ ~ (spec [%bcts p.p.x u.q.p.x]) (hoons ~[q r]:x)) [%tscm *] (rune '=,' ~ ~ (hoons ~[p q]:x)) [%wtbr *] (rune '?|' `'--' `['|(' ' ' ')'] (hoons p:x)) [%wthp *] (rune '?-' `'==' ~ (wing p.x) (matches q.x)) [%wtcl *] (rune '?:' ~ ~ (hoons ~[p q r]:x)) [%wtdt *] (rune '?.' ~ ~ (hoons ~[p q r]:x)) [%wtkt *] (rune '?^' ~ ~ [(wing p.x) (hoons ~[q r]:x)]) [%wtgl *] (rune '?<' ~ ~ (hoons ~[p q]:x)) [%wtgr *] (rune '?>' ~ ~ (hoons ~[p q]:x)) [%wtls *] (rune '?+' `'==' ~ (wing p.x) (hn q.x) (matches r.x)) [%wtpm *] (rune '?&' `'==' `['&(' ' ' ')'] (hoons p:x)) [%wtpt *] (rune '?@' ~ ~ (wing p.x) (hoons ~[q r]:x)) [%wtsg *] (rune '?~' ~ ~ (wing p.x) (hoons ~[q r]:x)) [%wthx *] (rune '?#' ~ ~ (skin p.x) (wing q.x) ~) [%wtts *] (rune '?=' ~ ~ (spec p.x) (wing q.x) ~) [%wtzp *] (rune '?!' ~ `['!' '' ''] (hoons ~[p]:x)) [%zpcm *] (rune '!,' ~ ~ (hoons ~[p q]:x)) [%zpgr *] (rune '!>' ~ ~ (hoons ~[p]:x)) [%zpmc *] (rune '!;' ~ ~ (hoons ~[p q]:x)) [%zpts *] (rune '!=' ~ ~ (hoons ~[p]:x)) [%zppt *] (rune '!@' ~ ~ (wingseq p.x) (hoons ~[q r]:x)) [%zpwt *] (hn q.x) :: Ignore p.x [%zpzp ~] '!!' == ++ hoons hoons-to-plum-list ++ battery battery-to-plum-list ++ chapter chapters-to-plum ++ chum chum-to-plum ++ hint hint-to-plum ++ hn |= h=hoon (hoon-to-plum (dec maxdepth) h) ++ limb limb-to-plum ++ matches matches-to-plum-list ++ skin skin-to-plum ++ spc ' ' ++ spec spec-to-plum ++ tyre tyre-to-plum ++ updates updates-to-plum-list ++ wing wing-to-plum ++ wingseq wingseq-to-plum :: :: Here's an example of what a hint looks like. :: :: ~>(%mean.[%leaf "need"] !!) :: :: The actual form that we're printing here looks something like this: :: :: %mean.[%leaf "need"] :: :: XX I'm not sure if the `[%leaf "need"]` bit represents a literal :: AST fragment or an expression that evaluates to `[%leaf "need"]`. I'm :: going to assume the latter for now. :: ++ tiscol-to-plum |= [updates=(list [^wing hoon]) body=hoon] ^- plum =/ rem=(list (pair ^wing hoon)) updates :: Note [TisCol Order] =/ acc=hoon body %+ hoon-to-plum (dec maxdepth) |- ^- hoon ?~ rem acc $(rem t.rem, acc `hoon`[%tsdt `^wing`p.i.rem `hoon`q.i.rem `hoon`acc]) :: :: Note [TisCol Order] :: ~~~~~~~~~~~~~~~~~~~ :: By accumulating over the updates list from the front, we are :: effectively reversing the assignment order of the forms in `.=`. :: This is semantically correct: :: :: > =a 3 :: > =b 4 :: > =: a 4 b a == b :: 3 :: > +hoon-printer !, *hoon =: a 4 b a == b :: <|=.(b a =.(a 4 b))|> :: > =.(a 4 =.(b a b)) :: 4 :: > =.(b a =.(a 4 b)) :: 3 -- :: :: Pretty-print a hint. :: ++ hint-to-plum |= hint=$@(term (pair term hoon)) ^- plum ?@ hint (cat 3 '%' hint) :+ %tree [wide=`['.' ~] tall=~] :~ (cat 3 '%' p.hint) (hoon-to-plum 999 q.hint) == :: :: Pretty-print a hoon battery. :: ++ battery-to-plum-list |= =(map term hoon) ^- (list plum) %+ turn ~(tap by map) |= [=term =hoon] =/ fmt [wide=`[' ' ~] tall=`['' ~]] :- %sbrk :+ %tree fmt [term (hoon-to-plum 999 hoon) ~] :: :: Pretty-print a core. :: ++ core-to-plum |= [=knot head=(unit plum) =(map term hoon)] ^- plum =* kids (battery-to-plum-list map) :- %sbrk :- %tree ?~ head :- [~ `[knot `['++' '--']]] kids :- [~ `[knot ~]] :~ u.head =* battery-fmt [~ `['' `['++' '--']]] [%tree battery-fmt kids] == :: :: XX Document this :: :: XX What's a cleaner way to implement this? :: ++ chapters-to-plum |= [=knot head=(unit plum) =(map term tome)] ^- plum =/ chapters=(list (pair term tome)) ~(tap by map) =* with-chapters (chapters-to-plum-verbose knot head map) =* without-chaps (core-to-plum knot head q.q.i.chapters) ?~ chapters with-chapters ?~ t.chapters ?: .=('' p.i.chapters) without-chaps with-chapters with-chapters :: :: XX Document this. :: ++ chapters-to-plum-verbose |= [=knot head=(unit plum) =(map term tome)] ^- plum =/ chaps=(list (pair term tome)) ~(tap by map) :+ %tree [~ `[knot `['' '--']]] =/ kids=(list plum) %+ turn chaps chapter-to-plum ?~ head kids [u.head kids] :: :: XX Document this. :: ++ chapter-to-plum |= [nm=knot [* bat=(map term hoon)]] ^- plum :+ %tree [~ `['+|' ~]] :~ (cat 3 '%' nm) :+ %tree [~ `['' `['++' '']]] (battery-to-plum-list bat) == :: :: XX Document this. :: ++ chapters-to-plum-list |= =(map term tome) ^- (list plum) %+ turn ~(tap by map) |= [=term [* hoons=(^map term hoon)]] ^- plum ?: =(term '') :+ %tree [wide=~ tall=[~ '' ~]] (battery-to-plum-list hoons) (rune '+|' ~ ~ [(cat 3 '%' term) (battery-to-plum-list hoons)]) :: :: XX Document this. :: ++ xray-to-plum |= =manx:hoot ^- plum %ast-node-xray :: XX Punt :: :: Render a plum to a skin. :: ++ skin-to-plum |= =skin ^- plum ?@ skin skin %todo-complex-skin :: XX Punt :: :: Render a list of wings a plum that looks something like "a:b:c" :: ++ wingseq-to-plum |= =(list wing) ^- plum =* fmt [wide=`[':' ~] tall=~] [%tree fmt (turn list wing-to-plum)] :: :: Renders a spec to a plum. Similarly to `hoon-to-plum`, given all of :: the helper functions this becomes quite simple. It does have a lot of :: cases, though. :: ++ spec-to-plum |^ |= =spec ^- plum ?- -.spec %base ?- p.spec %noun '*' %cell '^' %flag '?' %null '~' %void '!!' [%atom *] (cat 3 '@' p.p.spec) == %dbug $(spec q.spec) %leaf =+((scot p.spec q.spec) ?:(=('~' -) - (cat 3 '%' -))) %like tree/[[`[':' ~] ~] (turn `(list wing)`+.spec wing-to-plum)] %loop (cat 3 '$' p.spec) %name $(spec q.spec) %made $(spec q.spec) %over $(spec q.spec) %make =+ (lent q.spec) :- %sbrk :+ %tree :- wide=`[' ' `['(' ')']] :- ~ ?: |((gth - 3) =(- 0)) ['%:' `['' '==']] :_ ~ ?: =(- 3) '%^' ?: =(- 2) '%+' '%-' [(dohoon p.spec) (turn q.spec ..$)] %bcbc (core-spec-to-plum '$$' p.spec q.spec) %bcbr (subtree (fixed '$|') $(spec p.spec) (dohoon q.spec) ~) %bccb (dohoon p.spec) %bccl :- %sbrk :+ %tree [`[' ' `['[' ']']] `['$:' `['' '==']]] (turn `(list ^spec)`+.spec ..$) %bccn (subtree (varying '$%' '==') (turn `(list ^spec)`+.spec ..$)) %bcdt (core-spec-to-plum '$.' p.spec q.spec) %bcgl (subtree (fixed '$<') $(spec p.spec) $(spec q.spec) ~) %bcgr (subtree (fixed '$>') $(spec p.spec) $(spec q.spec) ~) %bchp (subtree (fixed '$-') $(spec p.spec) $(spec q.spec) ~) %bckt (subtree (fixed '$^') $(spec p.spec) $(spec q.spec) ~) %bcls (subtree (fixed '$+') (stud-to-plum p.spec) $(spec q.spec) ~) %bcfs (core-spec-to-plum '$/' p.spec q.spec) %bcmc (subtree (fixed '$;') (dohoon p.spec) ~) %bcpm (subtree (fixed '$&') $(spec p.spec) (dohoon q.spec) ~) %bcsg (subtree (fixed '$~') (dohoon p.spec) $(spec q.spec) ~) %bctc (core-spec-to-plum '$`' p.spec q.spec) %bcts :- %sbrk :+ %tree [`['=' ~] `['$=' ~]] :~ (skin-to-plum p.spec) $(spec q.spec) == %bcpt (subtree (fixed '$@') $(spec p.spec) $(spec q.spec) ~) %bcwt :- %sbrk :+ %tree [`[' ' `['?(' ')']] `['$?' `['' '==']]] (turn `(list ^spec)`+.spec ..$) %bczp (core-spec-to-plum '$.' p.spec q.spec) == :: ++ varying |= [intro=knot final=knot] [`[' ' `[(cat 3 intro '(') ')']] `[intro `['' final]]] :: ++ dohoon |= h=hoon (hoon-to-plum 999 h) :: -- :: ++ noun-to-plum |= [xt=ximage =top=noun] ^- plum :: =/ img xtable.xt :: |^ (main root.xt top-noun) :: ++ main |= [i=xkey n=*] ^- plum =/ x=xray (focus-on:libxray img i) ?~ pats.x (render-with-xdat i (need xdat.x) n) (render-with-xpat u.pats.x n) :: ++ tree-noun-to-list |= n=* ^- (list *) ?@ n ~ :- -.n %- zing :~ (tree-noun-to-list +.+.n) (tree-noun-to-list -.+.n) == :: ++ noun-to-list |= n=* ^- (list *) ?@ n ~ [-.n $(n +.n)] :: ++ render-tree |= [elt=xkey noun=*] ^- plum ?~ noun '~' =/ ns=(list *) (tree-noun-to-list noun) =/ ps=(list plum) (turn ns |=(n=* (main elt n))) =/ elems=plum (rune ':~' `'==' `['~[' ' ' ']'] ps) (rune '%-' ~ `['(' ' ' ')'] ~['tree' elems]) :: ++ render-list |= [elt=xkey noun=*] ^- plum ?~ noun '~' =/ ns=(list *) (noun-to-list noun) =/ ps=(list plum) (turn ns |=(n=* (main elt n))) (rune ':~' `'==' `['~[' ' ' ']'] ps) :: ++ render-unit |= [i=xkey n=*] ^- plum ?~ n '~' (tuple-plum ~['~' (main i +:n)]) :: ++ tuple-plum |= kids=(list plum) ^- plum =/ n (lent kids) (rune ':*' `['=='] `['[' ' ' ']'] kids) :: ++ render-atom |= [=aura =atom] ^- cord ?: =(aura '') (scot %ud atom) (scot aura atom) :: ++ render-const |= [=aura const=@ =atom] ^- plum ?: =(~.n aura) '~' (cat 3 '%' (render-atom aura atom)) :: ++ untyped-noun :: XX Where is the existing code for doing this? |= [n=*] :: Can I just use that? ^- plum ?@ n (render-atom 'ud' n) (tuple-plum ~[(untyped-noun -:n) (untyped-noun +:n)]) :: ++ render-tuple |= [i=xkey n=*] ^- plum =/ acc=(list plum) ~ %- tuple-plum %- flop |- ^- (list plum) :: =/ x=xray (focus-on:libxray img i) =/ d=xdat (need xdat.x) :: ?^ pats.x [(main i n) acc] ?. ?=([%cell *] d) [(main i n) acc] %= $ acc [(main head.d -:n) acc] n +:n i tail.d == :: ++ render-with-xdat |= [i=xkey d=xdat n=*] ^- plum ?- d %void '!!' %noun (untyped-noun n) [%cell *] (render-tuple i n) [%atom *] ?^ n ~& [%not-an-atom i d n] !! ?~ constant.d (render-atom aura.d n) (render-const aura.d u.constant.d n) [%face *] (main xray.d n) [%pntr *] !! [%core *] (render-core garb.d xray.d batt.d) [%fork *] (render-fork i n) == :: ++ render-fork |= [i=xkey n=*] ^- plum :: =/ x=xray (focus-on:libxray img i) ?~ xrole.x ~& x '%evil-fork' =/ r=xrole u.xrole.x :: ?- r %void !! %noun !! %atom !! %tall !! %wide !! [%constant *] !! [%instance *] !! [%union *] :: ~& %render-union ?> ?=(^ n) =/ hd=* -:n ?> ?=(@ hd) :: =/ pairs=(list (pair atom xkey)) ~(tap by map.r) |- ?~ pairs '%bad-union-fork' ?. =(p.i.pairs hd) $(pairs t.pairs) (main q.i.pairs n) [%option *] :: ~& %render-option =/ pairs=(list (pair atom xkey)) ~(tap by map.r) |- ?~ pairs '%bad-option-fork' ?. =(p.i.pairs n) $(pairs t.pairs) (main q.i.pairs n) [%junction *] :: ~& %render-junction (main ?@(n flat.r deep.r) n) [%conjunction *] :: ~& %render-conjunction ?> ?=(^ n) =/ hd=* -:n (main ?@(hd tall.r wide.r) n) [%misjunction *] :: ~& %render-misjunction '%misjunction' == :: ++ render-gate |= [=sample=xkey =product=xkey] ^- plum %- spec-to-plum :* %bchp (ximage-to-spec:libxray sample-xkey img) (ximage-to-spec:libxray product-xkey img) == :: ++ render-core |= [=garb xray=xkey =xbat] ^- plum :: =/ cvt-arms |= m=(map term xkey) ^- (map term hoon) %- ~(gas by *(map term hoon)) %+ turn ~(tap by m) |= [t=term i=xkey] =. t ?:(=('' t) '$' t) ^- [term hoon] :- t [%zpzp ~] :: =/ batt=(map term tome) %- ~(gas by *(map term tome)) %+ turn ~(tap by xbat) |= [nm=term w=what arms=(map term xkey)] [nm w (cvt-arms arms)] :: (hoon-to-plum 999 [%brcn p.garb batt]) :: ++ path-to-plum |= =path ^- plum =/ fmt=plumfmt [[~ '/' [~ '/' '']] ~] [%tree fmt path] :: ++ nock-to-plum |= n=nock ^- plum (untyped-noun n) :: ++ tour-to-plum |= t=tour ^- plum '%tour' :: XX TODO :: ++ render-with-xpat |= [p=xpat n=*] ^- plum ?- p %hoon (hoon-to-plum 999 ;;(hoon n)) %json (json-to-plum ;;(json n)) %manx (manx-to-plum ;;(manx n)) %nock (nock-to-plum ;;(nock n)) %path (path-to-plum ;;(path n)) %plum ;;(plum n) %skin (skin-to-plum ;;(skin n)) %spec (spec-to-plum ;;(spec n)) %tape (tape-to-plum ;;(tape n)) %tour (tour-to-plum ;;(tour n)) %type =/ ttp type-to-plum ;;(plum .*(ttp(+< n) [9 2 0 1])) %vase =/ vtp vase-to-plum =/ =plum ;;(plum .*(vtp(+< n) [9 2 0 1])) (rune '!>' ~ ~ ~[plum]) [%gate *] (render-gate sample.p product.p) [%gear *] '%gear' :: XX TODO [%list *] (render-list item.p n) [%tree *] (render-tree item.p n) [%unit *] (render-unit item.p n) == :: ++ tape-to-plum |= =tape ^- plum (simple-wide '"' '' '"' `(list plum)`tape) :: -- :: ++ type-to-plum-simple |^ main :: ++ main |= [ty=type maxdepth=@ud] ^- plum ?: =(0 maxdepth) 'DEEP' =/ d (dec maxdepth) ?- ty %void '!!' %noun '*' [%atom *] (sexp 'atom' p.ty ?~(q.ty '~' (scot %ud u.q.ty)) ~) [%cell *] (sexp 'cons' (main p.ty d) (main q.ty d) ~) [%core *] =/ payload (sexp 'payload' (main p.ty d) ~) (sexp 'core' (arms q.ty) payload ~) [%face *] (sexp 'face' (type-face-to-plum p.ty) (main q.ty d) ~) [%fork *] =/ forks %+ turn ~(tap in p.ty) |=(t=type (main t d)) (sexp 'fork' forks) [%hint *] (sexp 'hint' 'hint' (main q.ty d) ~) [%hold *] 'HOLD' == :: ++ arms |= =coil ^- plum =/ arms (arm-names q.r.coil) =. arms (turn arms |=(c=cord ?:(=('' c) '$' c))) ?: (gte (lent arms) 50) 'KERNEL' (sexp 'arms' (chapters-to-plum-list q.r.coil)) :: :: Given a battery expression (from a hoon expression), produce a list :: of arm names. :: ++ arm-names |= =battery ^- (list term) %- zing %+ turn ~(val by battery) |= [=what arms=(map term hoon)] ^- (list term) ~(tap in ~(key by arms)) :: ++ type-face-to-plum |= f=$@(term tune) ^- plum ?@ f f (tune-to-plum f) :: ++ tune-to-plum |= =tune ^- plum =/ aliases p.tune =/ bridges q.tune =/ fmt [[~ ' ' [~ '[' ']']] ~] =/ aliases :- %sbrk [%tree fmt 'aliases' (turn ~(tap by p.tune) alias-to-plum)] =/ bridges :- %sbrk [%tree fmt 'bridges' (turn q.tune |=(h=hoon (hoon-to-plum 999 h)))] :- %sbrk [%tree fmt 'tune' bridges aliases ~] :: ++ alias-to-plum |= [=term =(unit hoon)] ^- plum =/ fmt [[~ ' ' [~ '(' ')']] ~] [%sbrk [%tree fmt 'alias' term ?~(unit '~' (hoon-to-plum 999 u.unit)) ~]] :: -- :: ++ json-to-plum :: :: Note that `arrayfmt` and `objfmt` use core-like formatting in :: the tall case. This is kind-of a hack but works well! :: =/ arrfmt=plumfmt :- wide=`[' ' `['[' ']']] tall=`['[ ' `['' ']']] :: =/ objfmt=plumfmt :- wide=`[' ' `['{' '}']] tall=`['{ ' `['' '}']] :: :: Note that `kidfmt` uses the magical "ace-ace" rune to get :: 4-space indentation. =/ kidfmt=plumfmt [wide=`['' ~] tall=`[' ' `['' '']]] :: =/ colfmt=plumfmt [wide=`[' ' ~] tall=`['' `['' '']]] :: |^ jsn :: ++ str |= t=@t ^- cord (cat 3 '"' (cat 3 t '"')) :: XX Escaping :: ++ key |= t=@t ^- cord (cat 3 (str t) ':') :: ++ kid |= kids=(list plum) ^- plum [%tree kidfmt kids] :: ++ jsn |= j=json ^- plum ?- j ~ 'null' [%a *] (arr p.j) [%b *] ?:(p.j 'true' 'false') [%o *] (obj p.j) [%n *] p.j [%s *] (str p.j) == :: ++ arr |= l=(list json) ^- plum [%sbrk [%tree arrfmt (seq (turn l jsn))]] :: ++ obj |= m=(map @t json) ^- plum [%sbrk [%tree objfmt (seq (turn ~(tap by m) col))]] :: ++ col |= [k=@t v=json] ^- plum [%sbrk [%tree colfmt ~[(key k) (kid (jsn v) ~)]]] :: :: :: Adds a comma to the end of every plum but the last. :: ++ seq |= ps=(list plum) ^- (list plum) =/ acc=(list plum) ~ |- ?~ ps (flop acc) ?~ t.ps (flop [i.ps acc]) %= $ acc [(com i.ps) acc] ps `(list plum)`t.ps == :: ++ lst |= ps=(list plum) ^- (list plum) =/ acc=(list plum) ~ |- ?~ ps (flop acc) ?~ t.ps (flop [(com i.ps) acc]) %= $ acc [i.ps acc] ps `(list plum)`t.ps == :: :: Adds a comma at the end of a plum in both wide and tall modes. :: ++ com |= p=plum ^- plum ?- p @ (cat 3 p ',') [%sbrk *] [%sbrk (com kid.p)] [%para *] p [%tree *] ?. ?& ?=(^ tall.fmt.p) ?| =(' ' intro.u.tall.fmt.p) =('' intro.u.tall.fmt.p) == == p(fmt (hak fmt.p)) p(kids (lst kids.p)) == :: :: Nasty hack to add a trailing comma to an element in a sequence. :: :: Everything that can appear in a sequence has a plum that is :: either a cord or has a `plumfmt` that contains a terminator :: character (possibly empty) in both wide and tall formats. :: :: This routine fudges a `plumfmt` value so that a trailing comma :: will be inserted at the end :: ++ hak |= fmt=plumfmt ^- plumfmt :: %= fmt wide ?~ wide.fmt wide.fmt ?~ enclose.u.wide.fmt wide.fmt =. q.u.enclose.u.wide.fmt (cat 3 q.u.enclose.u.wide.fmt ',') wide.fmt tall ?~ tall.fmt tall.fmt ?~ indef.u.tall.fmt tall.fmt =. final.u.indef.u.tall.fmt (cat 3 final.u.indef.u.tall.fmt ',') tall.fmt == :: -- :: ++ manx-to-plum |= [[tag-name=mane attrs=mart] kids=marl] ^- plum |^ result :: ++ result `plum`[%sbrk [%tree outfmt toptag childs ~]] ++ outfmt ^- plumfmt :- `['' `['' endtag]] `['' [~ '' endtag]] :: ++ tagstr (mane-to-cord tag-name) :: ++ toptag =/ a atribs ?~ a (cat 3 topstr '>') [%sbrk [%tree topfmt a]] :: ++ txtstr ^- (unit plum) =/ res (manx-text [[tag-name attrs] kids]) ?~ res res `(crip u.res) :: `[%para '' ~[(crip u.res)]] :: :: Note that `kidfmt` uses "the ace-ace rune" (scare quotes) to :: get indentation. :: ++ childs ^- plum =/ body txtstr ?~ body [%tree kidfmt (turn kids manx-to-plum)] [%tree kidfmt [u.body (turn kids manx-to-plum)]] ++ kidfmt ^- plumfmt :- `['' `['' '']] `[' ' `['' '']] :: ++ topfmt =/ widetopstr (cat 3 topstr ' ') :- wide=[~ ' ' [~ widetopstr '>']] tall=[~ topstr [~ '' '>']] ++ topstr (cat 3 '<' tagstr) ++ atribs (turn (drop-body attrs) attr-to-plum) :: ++ endtag (cat 3 '')) ++ endfmt [[~ '' [~ '']] ~] :: ++ atrfmt [[~ '="' [~ '' '"']] ~] :: XX Escaping :: :: All attributes except the bullshit '' attribute. (It indicates :: the tag body). :: ++ drop-body |= l=mart ^- mart =/ acc=mart ~ |- ^- mart ?~ l (flop acc) ?: =('' n.i.l) $(l t.l) $(l t.l, acc [i.l acc]) :: ++ manx-text |= [[=mane =mart] =marl] ^- (unit tape) ?~ mart ~ ?: =('' n.i.mart) `v.i.mart $(mart t.mart) :: ++ attr-to-plum |= [m=mane t=tape] ^- plum [%tree atrfmt (mane-to-cord m) (crip t) ~] :: ++ mane-to-cord |= m=mane ^- cord ?@ m m (cat 3 -:m (cat 3 ':' +:m)) :: -- --