mirror of
https://github.com/urbit/shrub.git
synced 2024-11-24 13:06:09 +03:00
commit
ba51599e15
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a0a913185fc286fed27b3a6297e6917c65db26e8798b54e2c98a5c2bbf847eb1
|
||||
size 4495580
|
||||
oid sha256:9942a8b27a470fa4992f0ec4be33d7246d84a407da4f766bb4327da07d458ca7
|
||||
size 4477237
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:20057d491e10d2ba0afce72833dd45e78b746fc3a33122337ad346f9addfca66
|
||||
size 1320607
|
||||
oid sha256:92f96229ed78f7fe229f35be8145b4f14436800b7c4a0c68fb3e631eb6a3d993
|
||||
size 1305392
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1f7e5913134048073737c5ba380fabc9c3819a37038a1db8b657c9605d9e9bc9
|
||||
size 6324130
|
||||
oid sha256:ae9cf9424cb0f4ce515d477646844dfdab57a2cbd1f3b1e2d65662cce1d09654
|
||||
size 6306749
|
||||
|
@ -26,24 +26,27 @@ done
|
||||
|
||||
# Update :lens, :dojo and dependencies
|
||||
# FIXME: reduce this list
|
||||
cp $ARVO/app/lens.hoon ./pier/home/app/
|
||||
cp $ARVO/app/dojo.hoon ./pier/home/app/
|
||||
cp $ARVO/lib/base64.hoon ./pier/home/lib/
|
||||
cp $ARVO/lib/server.hoon ./pier/home/lib/
|
||||
cp $ARVO/lib/sole.hoon ./pier/home/lib/
|
||||
cp $ARVO/lib/xray.hoon ./pier/home/lib/
|
||||
cp $ARVO/app/lens.hoon ./pier/home/app/
|
||||
cp $ARVO/app/dojo.hoon ./pier/home/app/
|
||||
cp $ARVO/lib/base64.hoon ./pier/home/lib/
|
||||
cp $ARVO/lib/plume.hoon ./pier/home/lib/
|
||||
cp $ARVO/lib/server.hoon ./pier/home/lib/
|
||||
cp $ARVO/lib/sole.hoon ./pier/home/lib/
|
||||
cp $ARVO/lib/xray.hoon ./pier/home/lib/
|
||||
cp $ARVO/lib/pprint.hoon ./pier/home/lib/
|
||||
|
||||
mkdir -p ./pier/home/mar/lens/
|
||||
|
||||
cp $ARVO/mar/lens/* ./pier/home/mar/lens/
|
||||
cp $ARVO/mar/lens/* ./pier/home/mar/lens/
|
||||
|
||||
cp $ARVO/sur/lens.hoon ./pier/home/sur/
|
||||
cp $ARVO/sur/sole.hoon ./pier/home/sur/
|
||||
cp $ARVO/sur/lens.hoon ./pier/home/sur/
|
||||
cp $ARVO/sur/plum.hoon ./pier/home/sur/
|
||||
cp $ARVO/sur/sole.hoon ./pier/home/sur/
|
||||
cp $ARVO/sur/xray.hoon ./pier/home/sur/
|
||||
|
||||
# Update +solid and its dependencies
|
||||
cp $ARVO/lib/pill.hoon ./pier/home/lib/
|
||||
cp $ARVO/gen/solid.hoon ./pier/home/gen/
|
||||
cp $ARVO/lib/pill.hoon ./pier/home/lib/
|
||||
cp $ARVO/gen/solid.hoon ./pier/home/gen/
|
||||
|
||||
chmod -R u+rw ./pier/home/
|
||||
|
||||
|
420
pkg/arvo/lib/plume.hoon
Normal file
420
pkg/arvo/lib/plume.hoon
Normal file
@ -0,0 +1,420 @@
|
||||
/- *plum
|
||||
::
|
||||
:: This library includes `plume`, the actual pretty printing logic,
|
||||
:: and a handful of utilities for constructing plums.
|
||||
::
|
||||
:: Generally, you'll just use `plume` like this:
|
||||
::
|
||||
:: ~(tall plume plum) :: Pretty print `plum` in tall mode.
|
||||
:: ~(flat plume plum) :: Pretty print `plum` in wide mode.
|
||||
::
|
||||
:: There is probably no reason to look at the utility routines unless
|
||||
:: you are writing something to generate `plum`s.
|
||||
::
|
||||
:: This is the pretty-printer. Use the `flat` arm to render a plum
|
||||
:: into a single line and use the `tall` arm to get a nice multi-line
|
||||
:: rendering that switches to wide mode if there's enough space.
|
||||
::
|
||||
:: For details about how this works and what exactly it does in various
|
||||
:: cases, take a look at the docs for `plum`, `plumfmt`, and at the
|
||||
:: docs on the arms of this door.
|
||||
::
|
||||
^? |%
|
||||
++ plume
|
||||
|_ =plum
|
||||
::
|
||||
:: An line, indented by `indent` spaces.
|
||||
::
|
||||
+$ line [indent=@ud text=tape]
|
||||
::
|
||||
:: An sequence of indented lines.
|
||||
::
|
||||
+$ block (list line)
|
||||
::
|
||||
:: +flat: print as a single line
|
||||
::
|
||||
++ flat
|
||||
^- wain
|
||||
text:linear
|
||||
::
|
||||
:: +tall: print as multiple lines
|
||||
::
|
||||
++ tall
|
||||
^- wain
|
||||
%+ turn window
|
||||
|= line
|
||||
(crip (runt [indent ' '] text))
|
||||
::
|
||||
:: +adjust: adjust lines to right
|
||||
::
|
||||
++ adjust
|
||||
|= [tab=@ud =block] ^- ^block
|
||||
(turn block |=([@ud tape] [(add tab +<-) +<+]))
|
||||
::
|
||||
:: Prepend `n` spaces to a tape.
|
||||
::
|
||||
++ prepend-spaces
|
||||
|= [n=@ t=tape] ^- tape
|
||||
(runt [n ' '] t)
|
||||
::
|
||||
:: +window: print as list of tabbed lines
|
||||
::
|
||||
++ window
|
||||
^- block
|
||||
~+ :: for random access
|
||||
?@ plum [0 (trip plum)]~ :: trivial text
|
||||
?- -.plum
|
||||
::
|
||||
:: %para: Line-wrappable paragraph. This is a stub; it should
|
||||
:: wrap text to 40 characters.
|
||||
::
|
||||
%para
|
||||
[0 +:linear]~
|
||||
::
|
||||
:: %sbrk: nested subexpression
|
||||
::
|
||||
:: This is an opportunity to switch to wide mode. First, try
|
||||
:: rendered in wide mode. If that's possible and the result
|
||||
:: isn't too big, use that. Otherwise recurse into the subplum
|
||||
:: without switching to wide mode.
|
||||
::
|
||||
%sbrk
|
||||
=/ sub kid.plum
|
||||
?+ sub
|
||||
window(plum sub)
|
||||
[%tree *]
|
||||
=/ wideresult
|
||||
?~(wide.fmt.sub ~ [~ u=linear])
|
||||
?: ?&(?=(^ wideresult) (lte length.u.wideresult 40))
|
||||
[0 text.u.wideresult]~
|
||||
window(plum sub)
|
||||
==
|
||||
::
|
||||
:: %tree: Try to render a text tree in tall mode.
|
||||
::
|
||||
:: We want to render this in tall mode. First, verify that there
|
||||
:: the plum has a tall render (if not, fall back to `linear`
|
||||
:: formatting), then render all the subplums, and then render
|
||||
:: them in one of three ways:
|
||||
::
|
||||
:: - If the `plumfmt` contains an `indef` and that indef has
|
||||
:: no prefix, then this is a variable-arity rune with a
|
||||
:: terminator: Use vertical formatting.
|
||||
::
|
||||
:: - If the `plumfmt` contains an `indef` and that indef DOES have
|
||||
:: a prefix, then this is something that looks like a core: Use
|
||||
:: `core-like` formatting.
|
||||
::
|
||||
:: - Otherwise, this is a rune with a fixed number of arguments
|
||||
:: Render the subplums using backstep indentation.
|
||||
::
|
||||
:: There's also a special case where something has exactly one sub-plum.
|
||||
:: where something has exactly one sub-block. For example, we
|
||||
:: want this output:
|
||||
::
|
||||
:: |-
|
||||
:: foo
|
||||
::
|
||||
%tree
|
||||
?~ tall.fmt.plum [0 text:linear]~
|
||||
=/ prelude (trip intro.u.tall.fmt.plum)
|
||||
|^ =/ blocks (turn kids.plum |=(=^plum window(plum plum)))
|
||||
=/ prelude (trip intro.u.tall.fmt.plum)
|
||||
?~ indef.u.tall.fmt.plum
|
||||
?: =(1 (lent blocks))
|
||||
[[0 prelude] (zing blocks)]
|
||||
(backstep prelude blocks)
|
||||
=/ prefix (trip sigil.u.indef.u.tall.fmt.plum)
|
||||
=/ finale (trip final.u.indef.u.tall.fmt.plum)
|
||||
?~ blocks %+ weld
|
||||
?~(prelude ~ [0 prelude]~)
|
||||
?~(finale ~ [0 finale]~)
|
||||
?~ prefix (running prelude blocks finale)
|
||||
(core-like prelude prefix blocks finale)
|
||||
--
|
||||
==
|
||||
::
|
||||
:: Render a plum in tall-mode using backstep indentation. Here,
|
||||
:: we are rendering things that look something like this:
|
||||
::
|
||||
:: :+ foo
|
||||
:: bar
|
||||
:: baz
|
||||
::
|
||||
++ backstep
|
||||
|= [prelude=tape blocks=(list block)]
|
||||
^- block
|
||||
%- zing
|
||||
=/ nkids (lent blocks)
|
||||
=/ idx 1
|
||||
|- ^- (list block)
|
||||
?~ blocks ~
|
||||
:_ $(blocks t.blocks, idx +(idx))
|
||||
^- block
|
||||
=/ indent (mul 2 (sub nkids idx))
|
||||
?. =(1 idx) (adjust indent i.blocks)
|
||||
(rune-inline-with-block prelude indent i.blocks)
|
||||
::
|
||||
:: To make things look a bit nicer, we want to put the first
|
||||
:: sub-block on the same line as the rune. We want this:
|
||||
::
|
||||
:: :- foo
|
||||
:: baz
|
||||
::
|
||||
:: Instead of this:
|
||||
::
|
||||
:: :-
|
||||
:: foo
|
||||
:: baz
|
||||
::
|
||||
:: This handles the "foo" case.
|
||||
::
|
||||
++ rune-inline-with-block
|
||||
|= [rune=tape indent=@ blk=block]
|
||||
^- block
|
||||
=. indent (max indent (add 2 (lent rune)))
|
||||
=. blk (adjust indent blk)
|
||||
?~ rune blk
|
||||
?~ blk [0 rune]~
|
||||
:_ t.blk
|
||||
:- 0
|
||||
%+ weld rune
|
||||
=/ spaces-btwn (sub indent.i.blk (lent rune))
|
||||
(prepend-spaces spaces-btwn text.i.blk)
|
||||
::
|
||||
:: Render a tall hoon with running indentation. Here, we are
|
||||
:: rendering things that look sopmething like:
|
||||
::
|
||||
:: :~ foo
|
||||
:: bar
|
||||
:: baz
|
||||
:: ==
|
||||
::
|
||||
:: So, there's basically three cases here: Either the prelude
|
||||
:: is a rune, the prelude is empty, or prelude is some other
|
||||
:: random-ass thing.
|
||||
::
|
||||
:: - If there is no prelude, then just combine all of the
|
||||
:: sub-blocks together unaltered.
|
||||
:: - If it's a rune (two-characters wide), then combine the
|
||||
:: rune and the first line into one line (separated by two
|
||||
:: spaces) and indent the rest of the lines by four spaces.
|
||||
:: - If the rune is some other random-ass thing (has a length
|
||||
:: that isn't 0 or 2), then render the prelude alone on the
|
||||
:: first line and then combine the sub-blocks together,
|
||||
:: all indented by another two spaces.
|
||||
::
|
||||
:: Regardless, if there's a finale, stick it on the end without
|
||||
:: any indentation.
|
||||
::
|
||||
++ running
|
||||
|= [prelude=tape blocks=(list block) finale=tape]
|
||||
^- block
|
||||
=/ result=block (zing blocks)
|
||||
=. result
|
||||
?+ (lent prelude)
|
||||
[[0 prelude] (adjust 2 result)] :: unusual prelude
|
||||
%0 :: empty prelude
|
||||
result
|
||||
%2 :: rune prelude
|
||||
(rune-inline-with-block prelude 4 result)
|
||||
==
|
||||
?~ finale result
|
||||
(snoc result [0 finale])
|
||||
::
|
||||
:: This renders sub-blocks where each sub-block needs to be
|
||||
:: prefixed by some tape. For example:
|
||||
::
|
||||
:: |%
|
||||
:: ++ foo
|
||||
:: bar
|
||||
:: ++ baz
|
||||
:: qux
|
||||
:: --
|
||||
::
|
||||
++ core-like
|
||||
|= [prelude=tape prefix=tape blocks=(list block) finale=tape]
|
||||
^- block
|
||||
=/ clear (add 2 (lent prefix))
|
||||
=/ result
|
||||
^- block
|
||||
%- zing
|
||||
^- (list block)
|
||||
%+ turn blocks
|
||||
|= blk=block
|
||||
^- block
|
||||
^+ +<
|
||||
=* tab ?~(blk 0 (sub clear (min clear indent.i.blk)))
|
||||
=. blk (adjust tab blk)
|
||||
?~ blk ~
|
||||
:_ t.blk
|
||||
:- 0
|
||||
%+ weld prefix
|
||||
(runt [(sub indent.i.blk (lent prefix)) ' '] text.i.blk)
|
||||
=. result
|
||||
?~ finale result
|
||||
(snoc result [0 finale])
|
||||
?~ prelude result
|
||||
[[0 prelude] result]
|
||||
::
|
||||
:: +linear: Render a plum onto a single line, even if it only has a
|
||||
:: wide form.
|
||||
::
|
||||
++ linear
|
||||
^- [length=@ud text=tape]
|
||||
~+ :: ~+ for random access
|
||||
?@ plum [(met 3 plum) (trip plum)] :: Just a cord.
|
||||
?- -.plum
|
||||
::
|
||||
:: This is already in wide mode, so %sbrk nodes don't matter here.
|
||||
::
|
||||
%sbrk
|
||||
linear(plum kid.plum)
|
||||
::
|
||||
:: %para: To write a wrappable text paragraph to a single line,
|
||||
:: we just combine all the lines into one, interspersing single
|
||||
:: spaces chars.
|
||||
::
|
||||
%para
|
||||
|- ^- [length=@ud text=tape]
|
||||
?~ lines.plum [0 ~]
|
||||
=/ next $(lines.plum t.lines.plum)
|
||||
=/ this [length=(met 3 i.lines.plum) text=(trip i.lines.plum)]
|
||||
:- (add +(length.this) length.next)
|
||||
(weld text.this `tape`[' ' text.next])
|
||||
::
|
||||
:: Render a text tree to a single line.
|
||||
::
|
||||
%tree
|
||||
|^ ^- [length=@ud text=tape]
|
||||
?~ wide.fmt.plum (force-wide window)
|
||||
=/ body (render-body delimit.u.wide.fmt.plum kids.plum)
|
||||
?~ enclose.u.wide.fmt.plum body
|
||||
(wrap-with-enclose u.enclose.u.wide.fmt.plum body)
|
||||
::
|
||||
:: Given a list of subplums and a delimiter, render all the
|
||||
:: subplums onto a single line, and combine them into a single
|
||||
:: string by interspersing the delimiter.
|
||||
::
|
||||
++ render-body
|
||||
|= [delimit=cord kids=(list ^plum)]
|
||||
=/ stop (trip delimit)
|
||||
|- ^- [length=@ud text=tape]
|
||||
?~ kids [0 ~]
|
||||
=/ next $(kids t.kids)
|
||||
=/ this linear(plum i.kids)
|
||||
?~ text.next this
|
||||
:- :(add length.this (lent stop) length.next)
|
||||
:(weld text.this stop text.next)
|
||||
::
|
||||
:: Wrap a wide-form-rendered result with the `enclose` cords
|
||||
:: from its `plumefmt`.
|
||||
::
|
||||
++ wrap-with-enclose
|
||||
|= [clamps=(pair cord cord) body=[length=@ text=tape]]
|
||||
^- [length=@ud text=tape]
|
||||
::
|
||||
=/ close [(trip -.clamps) (trip +.clamps)]
|
||||
:- :(add length.body (lent -.close) (lent +.close))
|
||||
:(weld -.close text.body +.close)
|
||||
::
|
||||
:: Given the result of rendering a plum in tall form, combine
|
||||
:: all the lines into one by separating each by two spaces.
|
||||
::
|
||||
++ force-wide
|
||||
|= render=(list [@ud text=tape])
|
||||
^- [length=@ud text=tape]
|
||||
::
|
||||
?~ render [0 ~]
|
||||
=/ next (force-wide t.render)
|
||||
:- :(add (lent text.i.render) 2 length.next)
|
||||
?~(text.next text.i.render :(weld text.i.render " " text.next))
|
||||
--
|
||||
==
|
||||
--
|
||||
::
|
||||
:: Convenience function to build a `plumfmt` for a rune with a fixed
|
||||
:: number of parameters.
|
||||
::
|
||||
++ fixed
|
||||
|= rune=@ta
|
||||
^- plumfmt
|
||||
[wide=`[' ' `[(cat 3 +< '(') ')']] tall=`[+< ~]]
|
||||
::
|
||||
:: Same as `fixed` but only outputs in `tall` mode.
|
||||
::
|
||||
++ tall-fixed
|
||||
|= rune=cord
|
||||
^- (unit [cord (unit [cord cord])])
|
||||
`[rune ~]
|
||||
::
|
||||
:: Convenience function to build a the `tall` part of a `plumfmt` for
|
||||
:: a running-style rune (one that takes a variable number of parameters
|
||||
:: and has a terminator).
|
||||
::
|
||||
++ tall-running
|
||||
|= [rune=cord sigil=cord term=cord]
|
||||
^- (unit [cord (unit [cord cord])])
|
||||
`[rune `[sigil term]]
|
||||
::
|
||||
:: Convenience function for rendering a rune into a plum. This takes
|
||||
:: a rune, an optional tall-form terminator, optionally a short-form (if
|
||||
:: you don't supply a short-form, it'll just construct the standard
|
||||
:: wide-form (e.g. "?~(x x ~)") for you, and a list of sub-plums.
|
||||
::
|
||||
++ rune
|
||||
|= $: rune=cord
|
||||
term=(unit cord)
|
||||
short=(unit [cord cord cord])
|
||||
kids=(list plum)
|
||||
==
|
||||
^. plum
|
||||
|^ :- %sbrk
|
||||
:+ %tree
|
||||
:- (rune-wide-form rune short)
|
||||
?~ term (tall-fixed rune)
|
||||
(tall-running rune '' u.term)
|
||||
kids
|
||||
::
|
||||
:: If you just give this a rune, it'll build the standard wide-form.
|
||||
:: Otherwise, it'll just use the one that you gave it.
|
||||
::
|
||||
++ rune-wide-form
|
||||
|= [rune=cord short=(unit [fst=cord mid=cord lst=cord])]
|
||||
^- (unit (pair cord (unit [cord cord])))
|
||||
=* fst (cat 3 rune '(')
|
||||
=* std `[' ' `[fst ')']]
|
||||
?~ short std
|
||||
`[mid.u.short `[fst.u.short lst.u.short]]
|
||||
--
|
||||
::
|
||||
:: Just a helper function for constructing a wide-form %tree plum.
|
||||
::
|
||||
++ simple-wide
|
||||
|= [init=cord sep=cord end=cord kids=(list plum)]
|
||||
^- plum
|
||||
=/ fmt=plumfmt [wide=[~ sep [~ init end]] tall=~]
|
||||
[%tree fmt kids]
|
||||
::
|
||||
:: Convenience function that builds a plum for a subexpression. The
|
||||
:: `%sbrk` tells the pretty-printer that this is a valid place to
|
||||
:: switch from tall mode to wide mode.
|
||||
::
|
||||
++ subtree
|
||||
|= [p=plumfmt q=(list plum)]
|
||||
^- plum
|
||||
[%sbrk [%tree p q]]
|
||||
::
|
||||
:: Convenience for generating plums that look like s-expressions. Useful
|
||||
:: for quickly getting decent-looking debug output.
|
||||
::
|
||||
++ sexp
|
||||
|= [sym=cord kids=(list plum)]
|
||||
^- plum
|
||||
=/ head=cord (cat 3 '(' sym)
|
||||
=/ headspc=cord (cat 3 head ' ')
|
||||
=/ symcol=cord (cat 3 sym ':')
|
||||
=/ fmt=plumfmt [[~ ' ' [~ headspc ')']] [~ symcol [~ '' '']]]
|
||||
?~ kids (cat 3 '(' (cat 3 sym ')'))
|
||||
[%sbrk [%tree fmt kids]]
|
||||
--
|
@ -1,4 +1,6 @@
|
||||
/+ libxray=xray
|
||||
/- *plum, *xray
|
||||
/+ *plume,
|
||||
libxray=xray
|
||||
::
|
||||
:: This code pretty-prints a variety of things using the `xray` and
|
||||
:: `plum` libraries:
|
||||
@ -117,14 +119,18 @@
|
||||
++ type-to-tank
|
||||
|= t=type
|
||||
^- tank
|
||||
[%plum (type-to-plum t)]
|
||||
:+ %rose [~ ~ ~]
|
||||
%+ turn (render-type t)
|
||||
|=(=cord leaf+(trip cord))
|
||||
::
|
||||
:: Pretty-print a vase to a tank.
|
||||
::
|
||||
++ vase-to-tank
|
||||
|= v=vase
|
||||
^- tank
|
||||
[%plum (vase-to-plum v)]
|
||||
:+ %rose [~ ~ ~]
|
||||
%+ turn (render-vase v)
|
||||
|=(=cord leaf+(trip cord))
|
||||
::
|
||||
:: Render an `axis`.
|
||||
::
|
||||
|
@ -1,3 +1,4 @@
|
||||
/- *plum, *xray
|
||||
::
|
||||
:: # Type Analysis
|
||||
::
|
||||
@ -1864,4 +1865,77 @@
|
||||
(~(uni by q.q.i.chapters) $(chapters t.chapters))
|
||||
::
|
||||
--
|
||||
::
|
||||
:: Left-fold over a list.
|
||||
::
|
||||
:: This is `roll`, but with explicit type parameters.
|
||||
::
|
||||
++ fold
|
||||
|* [state=mold elem=mold]
|
||||
|= [[st=state xs=(list elem)] f=$-([state elem] state)]
|
||||
^- state
|
||||
|-
|
||||
?~ xs st
|
||||
$(xs t.xs, st (f st i.xs))
|
||||
::
|
||||
:: This is basically a `mapM` over a list using the State monad.
|
||||
::
|
||||
:: Another way to think about this is that it is the same as `turn`,
|
||||
:: except that a state variable `st` is threaded through the
|
||||
:: execution. The list is processed from left to right.
|
||||
::
|
||||
:: This is `spin`, but with explicit type parameters.
|
||||
::
|
||||
++ traverse
|
||||
|* [state=mold in=mold out=mold]
|
||||
|= [[st=state xs=(list in)] f=$-([state in] [out state])]
|
||||
^- [(list out) state]
|
||||
?~ xs [~ st]
|
||||
=^ r st (f st i.xs)
|
||||
=^ rs st $(xs t.xs, st st)
|
||||
[[r rs] st]
|
||||
::
|
||||
:: `traverse` over a set.
|
||||
::
|
||||
++ traverse-set
|
||||
|* [state=mold input=mold out=mold]
|
||||
|= [[st=state xs=(set input)] f=$-([state input] [out state])]
|
||||
^- [(set out) state]
|
||||
::
|
||||
=^ elems st ((traverse state input out) [st ~(tap in xs)] f)
|
||||
:_ st (~(gas in *(set out)) elems)
|
||||
::
|
||||
:: `traverse` over a map, also passing the key to the folding function.
|
||||
::
|
||||
++ traverse-map
|
||||
|* [state=mold key=mold in=mold out=mold]
|
||||
|= [[st=state dict=(map key in)] f=$-([state key in] [out state])]
|
||||
^- [(map key out) state]
|
||||
::
|
||||
=^ pairs=(list (pair key out)) st
|
||||
%+ (traverse state (pair key in) (pair key out))
|
||||
[st ~(tap by dict)]
|
||||
|= [st=state k=key x=in]
|
||||
^- [(pair key out) state]
|
||||
=^ v st (f st k x)
|
||||
[[k v] st]
|
||||
::
|
||||
:_ st
|
||||
(~(gas by *(map key out)) pairs)
|
||||
::
|
||||
:: Given a map, return its inverse: For each value, what are the set
|
||||
:: of associated keys?
|
||||
::
|
||||
++ reverse-map
|
||||
|* [key=mold val=mold]
|
||||
|= tbl=(map key val)
|
||||
=/ init *(map val (set key))
|
||||
^- _init
|
||||
%+ (fold _init (pair key val))
|
||||
[init ~(tap by tbl)]
|
||||
|= [acc=_init k=key v=val]
|
||||
^- _init
|
||||
=/ mb-keys (~(get by acc) v)
|
||||
=/ keys=(set key) ?~(mb-keys ~ u.mb-keys)
|
||||
(~(put by acc) v (~(put in keys) k))
|
||||
--
|
||||
|
55
pkg/arvo/sur/plum.hoon
Normal file
55
pkg/arvo/sur/plum.hoon
Normal file
@ -0,0 +1,55 @@
|
||||
^? |%
|
||||
::
|
||||
+$ tile :: XX: ?@(knot (pair styl knot))
|
||||
::
|
||||
cord
|
||||
::
|
||||
:: A `plum` is the intermediate representation for the pretty-printer. It
|
||||
:: encodes hoon-shaped data with the least amount of structured needed
|
||||
:: for formating.
|
||||
::
|
||||
:: A `plum` is either a
|
||||
::
|
||||
:: - `cord`: A simple cord
|
||||
:: - `[%para *]`: A wrappable paragraph.
|
||||
:: - `[%tree *]`: A formatted plum tree
|
||||
:: - `[%sbrk *]`: An indication of a nested subexpression.
|
||||
::
|
||||
:: The formatter will use the tall mode unless:
|
||||
::
|
||||
:: - A plum has only a `wide` style.
|
||||
:: - The plum is in `%sbrk` form and its subplum (`kid`), when
|
||||
:: formatted in wide mode, can fit on a single line.
|
||||
::
|
||||
+$ plum
|
||||
$@ cord
|
||||
$% [%para prefix=tile lines=(list @t)]
|
||||
[%tree fmt=plumfmt kids=(list plum)]
|
||||
[%sbrk kid=plum]
|
||||
==
|
||||
::
|
||||
:: A `plumfmt` is a description of how to render a `plum`. A `plumfmt`
|
||||
:: must include a `wide`, a `tall`, or both.
|
||||
::
|
||||
:: A `wide` is a description of how to render a plum in a single
|
||||
:: line. The nested (`kids`) sub-plums will be interleaved with `delimit`
|
||||
:: strings, and, if `enclose` is set, then the output will be enclosed
|
||||
:: with `p.u.enclose` and `q.u.enclose`.
|
||||
::
|
||||
:: For example, to build a plumfmt for string literals, we could write:
|
||||
::
|
||||
:: [wide=[~ '' [~ '"' '"']] tall=~]
|
||||
::
|
||||
:: A `tall` is a description of how to render a plum across multiple
|
||||
:: lines. The output will be prefixed by `intro`, suffixed by
|
||||
:: `final.u.indef`, and each subplum prefixed by `sigil.u.indef`.
|
||||
::
|
||||
:: For example, to build a plumfmt for cores, we could write:
|
||||
::
|
||||
:: [wide=~ tall=`['' `['++' '--']]]
|
||||
::
|
||||
+$ plumfmt
|
||||
$: wide=(unit [delimit=tile enclose=(unit (pair tile tile))])
|
||||
tall=(unit [intro=tile indef=(unit [sigil=tile final=tile])])
|
||||
==
|
||||
--
|
176
pkg/arvo/sur/xray.hoon
Normal file
176
pkg/arvo/sur/xray.hoon
Normal file
@ -0,0 +1,176 @@
|
||||
|
||||
::
|
||||
:: These are the public types for the `xray` library. Analysing a type
|
||||
:: yields an `ximage`, and everything else here is just some structure
|
||||
:: within that.
|
||||
::
|
||||
:: `ximage`s can be printed as specs (hoon syntax for types), and can
|
||||
:: be used to pretty-print typed data.
|
||||
::
|
||||
^? |%
|
||||
::
|
||||
:: An `xtable` is a graph of types referenced by the top-level type,
|
||||
:: and the `root` `key` points to the node which corresponds to the
|
||||
:: type under analysis.
|
||||
::
|
||||
+$ ximage [root=xkey =xtable]
|
||||
::
|
||||
:: A `xkey` is just an identifier for a node in the xray graph.
|
||||
::
|
||||
+$ xkey @
|
||||
::
|
||||
:: An `xtable` is the xray graph itself. It contains one node for for
|
||||
:: the type that was analyzed and one node for every type referenced
|
||||
:: within that type.
|
||||
::
|
||||
:: The `next` field is the the next available xkey (used when inserting
|
||||
:: new xrays), `xrays` maps keys to graph nodes and `type-map` gives
|
||||
:: the xkey corresponding to a type.
|
||||
::
|
||||
:: The `type-map` is basically just the reverse of the `xrays` map. It
|
||||
:: doesn't contain any new information, but is needed for performance
|
||||
:: reasons.
|
||||
::
|
||||
+$ xtable [next=xkey xrays=(map xkey xray) =type=(map type xkey)]
|
||||
::
|
||||
:: An `xray` is a node in the `ximage` graph. It contains everything
|
||||
:: we know about a certain `type`. `key` is its identifier in the graph,
|
||||
:: `type` is the type that it's an xray of, and `xdat` is the basic
|
||||
:: information we derived about the type. The basic references to other
|
||||
:: nodes are inside the `xdat` structure, though some of the other
|
||||
:: fields may contain references as well.
|
||||
::
|
||||
:: - `xshape` is some more information about the xshape of data within
|
||||
:: a cell.
|
||||
:: - `xrole` expands on `xshape`, adding further information about the
|
||||
:: xrole that a node has within a fork.
|
||||
:: - `pats` is used for printing data: we want to know if this type
|
||||
:: can be printed as a list, as json, as a tape literal, etc.
|
||||
:: - `recipes` contains information about how a type was
|
||||
:: constructed. It's used to get much nicer output when printing types.
|
||||
:: - `studs` contains "standards names". I actually don't know what this is.
|
||||
:: - `helps` contains all the documentation about a type.
|
||||
:: - `loop` indicates whether or not a node references itself. The list
|
||||
:: type is cyclical, for example. This is used when printing an
|
||||
:: `ximage`.
|
||||
::
|
||||
+$ xray
|
||||
$: =xkey
|
||||
=type
|
||||
xdat=(unit xdat)
|
||||
xrole=(unit xrole)
|
||||
pats=(unit xpat)
|
||||
studs=(set stud)
|
||||
recipes=(set recipe)
|
||||
helps=(set help)
|
||||
xshape=(unit xshape)
|
||||
loop=(unit ?)
|
||||
==
|
||||
::
|
||||
:: - `%void` -- impossible to create.
|
||||
:: - `%noun` -- could be any noun.
|
||||
:: - `%atom` -- An atom of some aura, possibly constant
|
||||
:: - `%cell` -- A cell with a head and a tail.
|
||||
:: - `%core` -- A core, its garb, its context type, and the types of
|
||||
:: each of its arms.
|
||||
:: - `%face` -- A face on another type.
|
||||
:: - `%fork` -- Could be one or more other types.
|
||||
:: - `%pntr` -- This is an internal hack, it should never survive
|
||||
:: analysis; ignore.
|
||||
::
|
||||
+$ xdat
|
||||
$@ ?(%noun %void)
|
||||
$% [%atom =aura constant=(unit @)]
|
||||
[%cell head=xkey tail=xkey]
|
||||
[%core =garb xray=xkey batt=xbat]
|
||||
[%face face=$@(term tune) xray=xkey]
|
||||
[%fork =(set xkey)]
|
||||
[%pntr xray=xkey]
|
||||
==
|
||||
::
|
||||
:: The basic xshape of a type:
|
||||
::
|
||||
:: - `%void` -- impossible to create.
|
||||
:: - `%noun` -- could be any noun.
|
||||
:: - `%atom` -- always some type of atom; never a cell
|
||||
:: - `%cell` -- always some type of cell; never an atom.
|
||||
:: - `%junc` -- is a fork of a cell type and an atom type.
|
||||
::
|
||||
+$ xshape ?(%void %noun %atom %cell %junc)
|
||||
::
|
||||
:: A `xrole` is the of a type, including a more refined understanding
|
||||
:: of what xrole it plays within a fork.
|
||||
::
|
||||
:: Nodes referenced within a `xrole` often do not actually exist in the
|
||||
:: original type, since we need to reorganize forks in order to make
|
||||
:: them more coherent.
|
||||
::
|
||||
:: - `%void` -- impossible to create.
|
||||
:: - `%noun` -- could be any noun.
|
||||
:: - `%atom` -- always some type of atom; never a cell
|
||||
:: - `%constant` -- a cell type whose head is a constant atom.
|
||||
:: - `%tall` -- a cell type whose head is an atom.
|
||||
:: - `%wide` -- a cell type whose head is also a cell
|
||||
:: - `%instance` -- a cell type whose head is a constant atom.
|
||||
:: - `%option` -- a union of types which are all constant atoms.
|
||||
:: - `%union` -- a union of types which are all instances (cells whose
|
||||
:: head is a constant atom).
|
||||
:: - `%junction` -- a union of an atom type and a cell type.
|
||||
:: - `%conjunction` -- a union of two cell types, one of them %wide
|
||||
:: and the other %tall.
|
||||
:: - `%misjunction` -- any other union type. There's no efficient way
|
||||
:: to tell which branch to take when analyzing a fork which is a
|
||||
:: %misjunction, and the type is probably improperly constructed.
|
||||
::
|
||||
+$ xrole
|
||||
$@ $? %void %noun %atom %tall %wide ==
|
||||
$% [%constant =atom]
|
||||
[%instance =atom]
|
||||
[%option =(map atom xkey)]
|
||||
[%union =(map atom xkey)]
|
||||
[%junction flat=xkey deep=xkey]
|
||||
[%conjunction wide=xkey tall=xkey]
|
||||
[%misjunction one=xkey two=xkey]
|
||||
==
|
||||
::
|
||||
:: This is just a utility type, it encodes the "battery" structure
|
||||
:: within a core.
|
||||
::
|
||||
:: It's a map from chapter names to the documentation and arms within
|
||||
:: that chapter.
|
||||
::
|
||||
+$ xbat (map term (pair what (map term xkey)))
|
||||
::
|
||||
:: A recipe tells us how a type was constructed.
|
||||
::
|
||||
:: - `%direct` is a simple type like `term`, or `xray`.
|
||||
:: - `%synthetic` is a constructed type, like `(list @)`.
|
||||
::
|
||||
+$ recipe
|
||||
$% [%direct =term]
|
||||
[%synthetic =term =(list xkey)]
|
||||
==
|
||||
::
|
||||
:: A `xpat` is high-level information about the shape of a type. This
|
||||
:: is used for printing data.
|
||||
::
|
||||
:: This is fairly heuristic. [%a %b %c ~] is recognized as a `path`,
|
||||
:: `[3 ~[4 5 6]]` is recognized as a list, etc.
|
||||
::
|
||||
:: Most of the xpats have names that make their purpose obvious:
|
||||
:: for example, the %tape xpat means that data of type type can be
|
||||
:: printed as if it had the `tape` type. However, `%gear` and `%gate`
|
||||
:: might not be entirely obvious.
|
||||
::
|
||||
:: - The %gear xpat is any core with a cell subject.
|
||||
:: - The %gate xpat is a core that looks like a gate.
|
||||
::
|
||||
+$ xpat
|
||||
$@ ?(%hoon %manx %json %nock %path %plum %skin %spec %tape %tour %type %vase)
|
||||
$% [%gate sample=xkey product=xkey]
|
||||
[%gear sample=xkey context=xkey batt=xbat]
|
||||
[%list item=xkey]
|
||||
[%tree item=xkey]
|
||||
[%unit item=xkey]
|
||||
==
|
||||
--
|
File diff suppressed because it is too large
Load Diff
@ -39,11 +39,10 @@
|
||||
::
|
||||
:: miscellaneous systems types
|
||||
::+|
|
||||
++ ares (unit {p/term q/(list tank)}) :: possible error
|
||||
:: +capped-queue: a +qeu with a maximum number of entries
|
||||
::
|
||||
++ capped-queue
|
||||
|* item-type=mold
|
||||
|$ [item-type]
|
||||
$: queue=(qeu item-type)
|
||||
size=@ud
|
||||
max-size=_64
|
||||
@ -54,44 +53,53 @@
|
||||
:: :key-type to :val-type. Detailed docs for this type can be found there.
|
||||
::
|
||||
++ clock
|
||||
|* $: :: key-type: mold of keys
|
||||
::
|
||||
key-type=mold
|
||||
:: val-type: mold of values
|
||||
::
|
||||
val-type=mold
|
||||
==
|
||||
$: lookup=(map key-type [val=val-type fresh=@ud])
|
||||
queue=(qeu key-type)
|
||||
size=@ud
|
||||
max-size=_2.048
|
||||
depth=_1
|
||||
==
|
||||
|$ :: key-type: mold of keys
|
||||
:: val-type: mold of values
|
||||
::
|
||||
[key-type val-type]
|
||||
$: lookup=(map key-type [val=val-type fresh=@ud])
|
||||
queue=(qeu key-type)
|
||||
size=@ud
|
||||
max-size=_2.048
|
||||
depth=_1
|
||||
==
|
||||
::
|
||||
++ coop (unit ares) :: possible error
|
||||
:: +disc: a desk on a ship; can be used as a beak that varies with time
|
||||
::
|
||||
+$ disc [=ship =desk]
|
||||
++ life @ud :: ship key revision
|
||||
++ rift @ud :: ship continuity
|
||||
++ mime {p/mite q/octs} :: mimetyped data
|
||||
++ octs {p/@ud q/@} :: octet-stream
|
||||
++ sock {p/ship q/ship} :: outgoing [our his]
|
||||
+$ deco ?(~ $bl $br $un) :: text decoration
|
||||
+$ json :: normal json value
|
||||
$@ ~ :: null
|
||||
$% [%a p=(list json)] :: array
|
||||
[%b p=?] :: boolean
|
||||
[%o p=(map @t json)] :: object
|
||||
[%n p=@ta] :: number
|
||||
[%s p=@t] :: string
|
||||
== ::
|
||||
+$ life @ud :: ship key revision
|
||||
+$ rift @ud :: ship continuity
|
||||
+$ mime (pair mite octs) :: mimetyped data
|
||||
+$ octs (pair @ud cord) :: octet-stream
|
||||
+$ sock (pair ship ship) :: outgoing [our his]
|
||||
::+|
|
||||
::
|
||||
++ roof (room vase) :: namespace
|
||||
+$ roof (room vase) :: namespace
|
||||
++ room :: either namespace
|
||||
|* vase/mold :: vase or maze
|
||||
$- $: ref/* :: reference type
|
||||
lyc/(unit (set ship)) :: leakset
|
||||
car/term :: perspective
|
||||
bem/beam :: path
|
||||
|$ [vase] :: vase or maze
|
||||
$- $: ref=* :: reference type
|
||||
lyc=(unit (set ship)) :: leakset
|
||||
car=term :: perspective
|
||||
bem=beam :: path
|
||||
== ::
|
||||
%- unit :: ~: unknown
|
||||
%- unit :: ~ ~: invalid
|
||||
(cask vase) :: marked cargo
|
||||
::
|
||||
++ turf (list @t) :: domain, tld first
|
||||
+$ stub (list (pair stye (list @c))) :: styled unicode
|
||||
+$ stye (pair (set deco) (pair tint tint)) :: decos/bg/fg
|
||||
+$ styl %+ pair (unit deco) :: cascading style
|
||||
(pair (unit tint) (unit tint)) ::
|
||||
+$ styx (list $@(@t (pair styl styx))) :: styled text
|
||||
+$ tint ?($r $g $b $c $m $y $k $w $~) :: text color
|
||||
::
|
||||
+$ turf (list @t) :: domain, tld first
|
||||
:: ::
|
||||
:::: ++jstd :: json standards structures
|
||||
:: ::::
|
||||
@ -890,7 +898,6 @@
|
||||
{$ud p/@ud} :: number
|
||||
== ::
|
||||
++ cass {ud/@ud da/@da} :: cases for revision
|
||||
++ coop (unit ares) :: e2e ack
|
||||
++ crew (set ship) :: permissions group
|
||||
++ dict {src/path rul/real} :: effective permission
|
||||
++ dome :: project state
|
||||
@ -1166,7 +1173,6 @@
|
||||
{$sav p/path q/@} :: save to file
|
||||
{$url p/@t} :: activate url
|
||||
== ::
|
||||
++ deco ?(~ $bl $br $un) :: text decoration
|
||||
++ dill-belt :: new belt
|
||||
$% {$aro p/?($d $l $r $u)} :: arrow key
|
||||
{$bac ~} :: true backspace
|
||||
|
Loading…
Reference in New Issue
Block a user