mirror of
https://github.com/urbit/shrub.git
synced 2024-12-04 04:35:02 +03:00
703 lines
19 KiB
Plaintext
703 lines
19 KiB
Plaintext
:: "Hello world" sample generator
|
|
::
|
|
:::: /hoon/hello/gen
|
|
::
|
|
/? 310
|
|
::
|
|
::::
|
|
::
|
|
:- %say
|
|
|= {^ {{subject=type ~} ~}}
|
|
:- %txt
|
|
^- wain
|
|
=< =/ spec=spec ~(structure cosmetic subject)
|
|
=/ plum=plum (spec-to-plum spec)
|
|
~(tall plume plum)
|
|
|%
|
|
++ cosmetic
|
|
=| :: coat: contextual metadata
|
|
::
|
|
$= coat
|
|
$: :: trace: type analysis stack
|
|
::
|
|
trace=(set type)
|
|
==
|
|
=| :: load: accumulating metadata (state)
|
|
::
|
|
$= load
|
|
$: :: count: cumulative blocks detected
|
|
:: pairs: blocking numbers and specs
|
|
::
|
|
count=@ud
|
|
pairs=(map type (pair @ud spec))
|
|
==
|
|
::
|
|
:: sut: type we're analyzing
|
|
::
|
|
|_ sut/type
|
|
::
|
|
:: +structure: make cosmetic spec from :sut
|
|
::
|
|
++ structure
|
|
^- spec
|
|
:: spec: raw analysis product
|
|
::
|
|
=^ spec load specify
|
|
:: if we didn't block, just use it
|
|
::
|
|
?: =(~ pairs.load) spec
|
|
:: otherwise, insert hygienic recursion
|
|
::
|
|
:+ %bcbc spec
|
|
%- ~(gas by *(map term ^spec))
|
|
%+ turn
|
|
~(tap by pairs.load)
|
|
|= [=type index=@ud spec=^spec]
|
|
[(synthetic index) spec]
|
|
::
|
|
:: +pattern: pattern and context for data inspection
|
|
::
|
|
++ pattern
|
|
^- $: :: main: rendering pattern
|
|
:: context: recursion points by counter
|
|
::
|
|
main=plot
|
|
loop=(map @ud plot)
|
|
==
|
|
!!
|
|
::
|
|
:: +synthetic: convert :number to a synthetic name
|
|
::
|
|
++ synthetic
|
|
|= number=@ud
|
|
^- @tas
|
|
?: (lte number 26)
|
|
(add 'a' number)
|
|
(cat 3 (add 'a' (mod number 26)) $(number (div number 26)))
|
|
::
|
|
:: +specify: make spec that matches :sut
|
|
::
|
|
++ specify
|
|
^- [spec _load]
|
|
=< entry
|
|
|%
|
|
:: +entry: make spec at potential entry point
|
|
::
|
|
++ entry
|
|
^- [spec _load]
|
|
:: if, we are already inside :sut
|
|
::
|
|
?: (~(has in trace.coat) sut)
|
|
:: then, produce and record a block reference
|
|
::
|
|
=+ [%loop (synthetic count.load)]
|
|
:- -
|
|
%_ load
|
|
count +(count.load)
|
|
pairs (~(put by pairs.load) sut [count.load -])
|
|
==
|
|
:: else, filter main loop for block promotion
|
|
::
|
|
=^ spec load main(trace.coat (~(put in trace.coat) sut))
|
|
:: loc: output block record for :sut
|
|
::
|
|
=/ loc (~(get by pairs.load) sut)
|
|
:: if we did not find :sut inside itself, not a true entry point
|
|
::
|
|
?~ loc
|
|
[spec load]
|
|
:: else produce a block reference and record the analysis
|
|
::
|
|
:- [%loop (synthetic p.u.loc)]
|
|
load(pairs (~(put by pairs.load) sut [p.u.loc spec]))
|
|
::
|
|
:: +main: make spec from any type
|
|
::
|
|
++ main
|
|
^- [spec _load]
|
|
?- sut
|
|
%void :_(load [%base %void])
|
|
%noun :_(load [%base %noun])
|
|
::
|
|
[%atom *] (atom p.sut q.sut)
|
|
[%cell *] (cell p.sut q.sut)
|
|
[%core *] (core p.sut q.sut)
|
|
[%face *] (face p.sut q.sut)
|
|
[%form *] !! :: (form(sut p.p.sut) q.p.sut)
|
|
[%fork *] (fork p.sut)
|
|
[%hold *] entry(sut ~(repo ut sut))
|
|
==
|
|
::
|
|
:: +form: rationalize structure from type (stub)
|
|
::
|
|
++ form
|
|
|= =spec
|
|
^- [^spec _load]
|
|
:_ load
|
|
|- ^- ^spec
|
|
:: reform a spec left as a type annotation
|
|
::
|
|
?+ -.spec spec
|
|
:: incomplete
|
|
::
|
|
%dbug $(spec q.spec)
|
|
%like :: hub: type of context
|
|
:: poy: reference
|
|
::
|
|
=/ hub %- ~(play ut sut)
|
|
|- ^- hoon
|
|
?~ q.spec [%$ 1]
|
|
[%tsgl [%wing i.q.spec] $(q.spec t.q.spec)]
|
|
=/ poy (~(fond ut hub) %free p.spec)
|
|
:: if we have a simple arm
|
|
::
|
|
?: ?=([%& * * %| *] poy)
|
|
:: then keep the spec
|
|
::
|
|
spec
|
|
!!
|
|
==
|
|
::
|
|
:: +atom: convert atomic type to spec
|
|
::
|
|
++ atom
|
|
|= $: :: aura: flavor of atom
|
|
:: constant: one value, or all values
|
|
::
|
|
aura=term
|
|
constant=(unit @)
|
|
==
|
|
:: pure function
|
|
::
|
|
:_ load ^- spec
|
|
:: if atom is not constant
|
|
::
|
|
?~ constant
|
|
:: %base: flavored atom with arbitrary value
|
|
::
|
|
[%base atom/aura]
|
|
:: %leaf: flavored constant
|
|
::
|
|
[%leaf aura u.constant]
|
|
::
|
|
:: +cell: convert a %cell to a spec
|
|
::
|
|
++ cell
|
|
|= $: :: left: head of cell
|
|
:: rite: tail of cell
|
|
::
|
|
left=type
|
|
rite=type
|
|
==
|
|
^- [spec _load]
|
|
:: head: cosmetic structure of head
|
|
:: tail: cosmetic structure of tail
|
|
::
|
|
=^ head load main(sut left)
|
|
=^ tail load main(sut rite)
|
|
:_ load
|
|
:: %bccl: raw tuple
|
|
::
|
|
?: ?=(%bccl -.tail)
|
|
[%bccl head +.tail]
|
|
[%bccl head tail ~]
|
|
::
|
|
:: +core: convert a %core to a spec
|
|
::
|
|
++ core
|
|
|= $: :: payload: data
|
|
:: battery: code
|
|
::
|
|
payload=type
|
|
battery=coil
|
|
==
|
|
^- [spec _load]
|
|
:: payload-spec: converted payload
|
|
::
|
|
=^ payload-spec load main(sut payload)
|
|
:: arms: all arms in the core, as hoons
|
|
::
|
|
=/ arms
|
|
^- (list (pair term hoon))
|
|
%- zing
|
|
^- (list (list (pair term hoon)))
|
|
%+ turn ~(tap by q.s.battery)
|
|
|= [term =tomb]
|
|
^- (list (pair term hoon))
|
|
%+ turn ~(tap by q.tomb)
|
|
|= [=term =what =foot]
|
|
^- (pair @tas hoon)
|
|
[term p.foot]
|
|
:: arm-specs: all arms in the core, as specs
|
|
::
|
|
=^ arm-specs load
|
|
|- ^- [(list (pair term spec)) _load]
|
|
?~ arms [~ load]
|
|
=^ mor load $(arms t.arms)
|
|
=^ les load
|
|
main(sut [%hold [%core payload battery] q.i.arms])
|
|
[[[p.i.arms les] mor] load]
|
|
:: arm-map: all arms in the core, as a a spec map
|
|
::
|
|
=* arm-map (~(gas by *(map term spec)) arm-specs)
|
|
:_ load
|
|
?- p.battery
|
|
%lead [%bczp payload-spec arm-map]
|
|
%gold [%bcdt payload-spec arm-map]
|
|
%zinc [%bctc payload-spec arm-map]
|
|
%iron [%bcnt payload-spec arm-map]
|
|
==
|
|
::
|
|
:: +face: convert a %face to a +spec
|
|
::
|
|
++ face
|
|
|= $: :: decor: decoration
|
|
:: content: decorated content
|
|
::
|
|
decor=(pair what $@(term tune))
|
|
content=type
|
|
==
|
|
^- [spec _load]
|
|
=^ body load main(sut content)
|
|
:_ load
|
|
?@ q.decor [%bcts q.decor body]
|
|
:: discard aliases, etc
|
|
::
|
|
body
|
|
::
|
|
:: +fork: convert a %fork to a +spec
|
|
::
|
|
++ fork
|
|
|= types=(set type)
|
|
^- [spec _load]
|
|
:: type-list: type set as a list
|
|
::
|
|
=/ type-list ~(tap by types)
|
|
:: specs: type set as a list of specs
|
|
::
|
|
=^ specs load
|
|
|- ^- [(list spec) _load]
|
|
?~ type-list [~ load]
|
|
=^ mor load $(type-list t.type-list)
|
|
=^ les load main(sut i.type-list)
|
|
[[les mor] load]
|
|
?< ?=(~ specs)
|
|
:_(load [%bcwt specs])
|
|
--
|
|
::
|
|
:: +explore:cosmetic: convert :sut to an inspection pattern (+plot).
|
|
::
|
|
++ explore
|
|
^- [plot _.]
|
|
=< [- +>]
|
|
|^ ^- [plot _.]
|
|
?+ sut !!
|
|
%void :_(. [%base %void])
|
|
%noun :_(. [%base %noun])
|
|
==
|
|
++ foo !!
|
|
--
|
|
--
|
|
::
|
|
++ plume
|
|
|_ =plum
|
|
::
|
|
:: +flat: print as a single line
|
|
::
|
|
++ flat
|
|
text:linear
|
|
::
|
|
:: +tall: print as multiple lines
|
|
::
|
|
++ tall
|
|
^- wain
|
|
%+ turn window
|
|
|= [indent=@ud text=tape]
|
|
(crip (runt [indent ' '] text))
|
|
::
|
|
:: +adjust: adjust lines to right
|
|
::
|
|
++ adjust
|
|
|= [tab=@ud =(list [length=@ud text=tape])]
|
|
(turn list |=([@ud tape] [(add tab +<-) +<+]))
|
|
::
|
|
:: +window: print as list of tabbed lines
|
|
::
|
|
++ window
|
|
^- (list [indent=@ud text=tape])
|
|
:: memoize for random access
|
|
::
|
|
~+
|
|
:: trivial text
|
|
::
|
|
?@ plum [0 (trip plum)]~
|
|
?- -.plum
|
|
:: %|: text wrap
|
|
::
|
|
%| :: wrapping stub, should wrap text to 40 characters
|
|
::
|
|
[0 +:linear]~
|
|
::
|
|
:: %&: text tree
|
|
::
|
|
%& :: trial: attempt at wide form
|
|
::
|
|
=/ trial ?~(wide.plum ~ [~ u=linear])
|
|
:: if wide form is available or optimal
|
|
::
|
|
?: ?& ?=(^ trial)
|
|
?| ?=(~ tall.plum)
|
|
(lte length.u.trial 40)
|
|
== ==
|
|
:: then produce wide form
|
|
::
|
|
[0 text.u.trial]~
|
|
:: else assert tall style (you gotta set either wide or tall)
|
|
::
|
|
?> ?=(^ tall.plum)
|
|
:: blocks: subwindows
|
|
:: prelude: intro as tape
|
|
::
|
|
=/ blocks (turn list.plum |=(=^plum window(plum plum)))
|
|
=/ prelude (trip intro.u.tall.plum)
|
|
:: if, :indef is empty
|
|
::
|
|
?~ indef.u.tall.plum
|
|
:: then, print in sloping mode
|
|
::
|
|
:: if, no children
|
|
::
|
|
?: =(~ blocks)
|
|
:: then, the prelude if any
|
|
::
|
|
?~(prelude ~ [0 prelude]~)
|
|
:: else, format children and inject any prelude
|
|
::
|
|
^- (list [indent=@ud text=tape])
|
|
:: concatenate child blocks into a single output
|
|
::
|
|
%- zing
|
|
:: count: number of children
|
|
:: index: current child from 1 to n
|
|
::
|
|
=/ count (lent blocks)
|
|
=/ index 1
|
|
|- ^+ blocks
|
|
?~ blocks ~
|
|
:_ $(blocks t.blocks, index +(index))
|
|
^- (list [indent=@ud text=tape])
|
|
:: indent: backstep indentation level
|
|
::
|
|
=/ indent (mul 2 (sub count index))
|
|
:: unless, we're on the first block
|
|
::
|
|
?. =(1 index)
|
|
:: else, apply normal backstep indentation
|
|
::
|
|
(adjust indent i.blocks)
|
|
:: then, apply and/or inject prelude
|
|
::
|
|
:: this fixes the naive representations
|
|
::
|
|
:: :+
|
|
:: foo
|
|
:: bar
|
|
:: baz
|
|
::
|
|
:: and
|
|
::
|
|
:: :-
|
|
:: foo
|
|
:: bar
|
|
::
|
|
=. indent (max indent (add 2 (lent prelude)))
|
|
=. i.blocks (adjust indent i.blocks)
|
|
?~ i.blocks ?~(prelude ~ [0 prelude]~)
|
|
?~ prelude i.blocks
|
|
:_ t.i.blocks
|
|
:- 0
|
|
~| [%indent indent]
|
|
~| [%prelude prelude]
|
|
~| [%kids list.plum]
|
|
~| [%blocks blocks]
|
|
%+ weld prelude
|
|
(runt [(sub indent.i.i.blocks (lent prelude)) ' '] text.i.i.blocks)
|
|
::
|
|
:: else, print in vertical mode
|
|
::
|
|
:: prefix: before each entry
|
|
:: finale: after all entries
|
|
::
|
|
=/ prefix (trip sigil.u.indef.u.tall.plum)
|
|
=/ finale (trip final.u.indef.u.tall.plum)
|
|
:: if, no children, then, just prelude and finale
|
|
::
|
|
?: =(~ blocks)
|
|
%+ weld
|
|
?~(prelude ~ [0 prelude]~)
|
|
?~(finale ~ [0 finale]~)
|
|
:: if no :prefix
|
|
::
|
|
?: =(~ prefix)
|
|
:: kids: flat list of child lines
|
|
:: tab: amount to indent kids
|
|
::
|
|
=/ kids `(list [indent=@ud text=tape])`(zing blocks)
|
|
=* tab =+((lent prelude) ?+(- 2 %0 0, %1 2, %2 4))
|
|
:: indent kids by tab
|
|
::
|
|
=. kids (turn kids |=([@ud tape] [(add tab +<-) +<+]))
|
|
:: prepend or inject prelude
|
|
::
|
|
=. kids
|
|
?: =(~ prelude) kids
|
|
:: if no kids, or prelude doesn't fit
|
|
::
|
|
?: |(?=(~ kids) (gte +((lent prelude)) indent.i.kids))
|
|
:: don't inject, just add to head if needed
|
|
::
|
|
[[0 prelude] kids]
|
|
:: inject: prelude
|
|
::
|
|
=* inject %+ weld
|
|
prelude
|
|
%+ runt
|
|
[(sub indent.i.kids (lent prelude)) ' ']
|
|
text.i.kids
|
|
[[0 inject] t.kids]
|
|
:: append finale
|
|
::
|
|
?~ finale kids
|
|
(weld kids ^+(kids [0 finale]~))
|
|
:: else, with :prefix
|
|
:: tab: amount to indent
|
|
::
|
|
=* tab (add 2 (lent prelude))
|
|
:: append :finale
|
|
::
|
|
=- ?~ finale -
|
|
(weld - ^+(- [0 finale]~))
|
|
^- (list [indent=@ud text=tape])
|
|
%- zing
|
|
:: combine each subtree with the prefix
|
|
::
|
|
%+ turn blocks
|
|
|= =(list [indent=@ud text=tape])
|
|
^+ +<
|
|
=. list (turn list |=([@ud tape] [(add tab +<-) +<+]))
|
|
?~ list ~
|
|
:_ t.list
|
|
:- 0
|
|
%+ weld
|
|
prefix
|
|
(runt [(sub indent.i.list (lent prefix)) ' '] text.i.list)
|
|
==
|
|
::
|
|
:: +linear: make length and tape
|
|
::
|
|
++ linear
|
|
^- $: length=@ud
|
|
text=tape
|
|
==
|
|
:: memoize for random access
|
|
::
|
|
~+
|
|
:: atomic plums are just text
|
|
::
|
|
?@ plum [(met 3 plum) (trip plum)]
|
|
?- -.plum
|
|
:: %|: text wrap
|
|
::
|
|
%| :: lay the text out flat, regardless of length
|
|
::
|
|
|- ^- [length=@ud text=tape]
|
|
?~ list.plum [0 ~]
|
|
=/ next $(list.plum t.list.plum)
|
|
=/ this [length=(met 3 i.list.plum) text=(trip i.list.plum)]
|
|
:- (add +(length.this) length.next)
|
|
(weld text.this `tape`[' ' text.next])
|
|
::
|
|
:: %&: text tree
|
|
::
|
|
%& :: if there is no wide representation
|
|
::
|
|
?~ wide.plum
|
|
:: then lay out a window, then separate with double-spaces
|
|
::
|
|
=/ window window
|
|
|- ^- [length=@ud text=tape]
|
|
?~ window [0 ~]
|
|
=/ next $(window t.window)
|
|
:- :(add (lent text.i.window) 2 length.next)
|
|
?~(text.next text.i.window :(weld text.i.window " " text.next))
|
|
::
|
|
:: else use wide layout
|
|
::
|
|
=- :: add enclosure if any
|
|
::
|
|
?~ enclose.u.wide.plum body
|
|
=* clamps u.enclose.u.wide.plum
|
|
=/ close [(trip -.clamps) (trip +.clamps)]
|
|
:- :(add length.body (lent -.close) (lent +.close))
|
|
:(weld -.close text.body +.close)
|
|
::
|
|
:: body: body of wide rendering
|
|
::
|
|
^= body
|
|
=/ stop (trip delimit.u.wide.plum)
|
|
|- ^- [length=@ud text=tape]
|
|
?~ list.plum [0 ~]
|
|
=/ next $(list.plum t.list.plum)
|
|
=/ this linear(plum i.list.plum)
|
|
?~ text.next this
|
|
:- :(add length.this (lent stop) length.next)
|
|
:(weld text.this stop text.next)
|
|
==
|
|
--
|
|
:: highly unsatisfactory temporary converter
|
|
::
|
|
++ plum-to-tank
|
|
|= =plum
|
|
^- tank
|
|
?@ plum [%leaf (trip plum)]
|
|
?- -.plum
|
|
%| :+ %rose
|
|
["" " " ""]
|
|
(turn list.plum |=(@ta [%leaf (trip +<)]))
|
|
%& =/ list (turn list.plum ..$)
|
|
?~ tall.plum
|
|
?> ?=(^ wide.plum)
|
|
=? enclose.u.wide.plum ?=(~ enclose.u.wide.plum) `['{' '}']
|
|
:+ %rose
|
|
:* (trip delimit.u.wide.plum)
|
|
(trip +<:enclose.u.wide.plum)
|
|
(trip +>:enclose.u.wide.plum)
|
|
==
|
|
list
|
|
?: ?=(^ indef.u.tall.plum)
|
|
:+ %rose
|
|
:* (trip sigil.u.indef.u.tall.plum)
|
|
(weld (trip intro.u.tall.plum) "[")
|
|
(weld "]" (trip final.u.indef.u.tall.plum))
|
|
==
|
|
list
|
|
:+ %palm
|
|
:* (weld (trip intro.u.tall.plum) "(")
|
|
""
|
|
""
|
|
")"
|
|
==
|
|
list
|
|
==
|
|
++ limb-to-plum
|
|
|= =limb
|
|
?- -.limb
|
|
%& (scot %ui p.limb)
|
|
%| (crip (runt [0 p.limb] ?~(q.limb "," (trip u.q.limb))))
|
|
==
|
|
::
|
|
++ wing-to-plum
|
|
|= =wing
|
|
^- plum
|
|
:+ %&
|
|
[`['.' ~] ~]
|
|
(turn wing limb-to-plum)
|
|
::
|
|
++ battery-to-plum
|
|
|= =(map term spec)
|
|
%+ turn ~(tap by map)
|
|
|= [=term =spec]
|
|
:+ %&
|
|
[`[' ' ~] `['' ~]]
|
|
[term (spec-to-plum spec) ~]
|
|
::
|
|
++ core-to-plum
|
|
|= [=knot =spec =(map term spec)]
|
|
^- plum
|
|
:+ %&
|
|
[~ `[knot ~]]
|
|
:~ (spec-to-plum spec)
|
|
:+ %&
|
|
[~ `['' `['++' '--']]]
|
|
(battery-to-plum map)
|
|
==
|
|
::
|
|
++ varying
|
|
|= [intro=knot final=knot]
|
|
[`[' ' `[(cat 3 intro '(') ')']] `[intro `['' final]]]
|
|
::
|
|
++ fixed
|
|
|= @ta
|
|
[`[' ' `[(cat 3 +< '(') ')']] `[+< ~]]
|
|
::
|
|
++ standard
|
|
|= =stud
|
|
^- plum
|
|
?@ stud stud
|
|
:+ %&
|
|
[`['/' ~] ~]
|
|
`(list plum)`[auth.stud type.stud]
|
|
::
|
|
++ hoon-to-plum
|
|
|= =hoon
|
|
^- plum
|
|
%hooon
|
|
::
|
|
++ 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 &/[[`[':' ~] ~] (turn `(list wing)`+.spec wing-to-plum)]
|
|
%loop (cat 3 '!' p.spec)
|
|
%over $(spec q.spec)
|
|
%make =+ (lent q.spec)
|
|
:+ %&
|
|
:- `[' ' `['(' ')']]
|
|
:- ~
|
|
?: |((gth - 3) =(- 0))
|
|
['%:' `['' '==']]
|
|
:_ ~
|
|
?: =(- 3) '%^'
|
|
?: =(- 2) '%+' '%-'
|
|
[(hoon-to-plum p.spec) (turn q.spec ..$)]
|
|
%bcbc (core-to-plum '$$' p.spec q.spec)
|
|
%bcbr &/[(fixed '$|') $(spec p.spec) (hoon-to-plum q.spec) ~]
|
|
%bccb (hoon-to-plum p.spec)
|
|
%bccl :+ %&
|
|
[`[' ' `['[' ']']] `['$:' `['' '==']]]
|
|
(turn `(list ^spec)`+.spec ..$)
|
|
%bccn &/[(varying '$%' '==') (turn `(list ^spec)`+.spec ..$)]
|
|
%bcdt (core-to-plum '$.' p.spec q.spec)
|
|
%bcgl &/[(fixed '$<') $(spec p.spec) $(spec q.spec) ~]
|
|
%bcgr &/[(fixed '$>') $(spec p.spec) $(spec q.spec) ~]
|
|
%bchp &/[(fixed '$-') $(spec p.spec) $(spec q.spec) ~]
|
|
%bckt &/[(fixed '$-') $(spec p.spec) $(spec q.spec) ~]
|
|
%bcls &/[(fixed '$+') (standard p.spec) $(spec q.spec) ~]
|
|
%bcnt (core-to-plum '$/' p.spec q.spec)
|
|
%bcmc &/[(fixed '$;') (hoon-to-plum p.spec) ~]
|
|
%bcpd &/[(fixed '$&') $(spec p.spec) (hoon-to-plum q.spec) ~]
|
|
%bcsg &/[(fixed '$~') (hoon-to-plum p.spec) $(spec q.spec) ~]
|
|
%bctc (core-to-plum '$`' p.spec q.spec)
|
|
%bcts :+ %&
|
|
[`['=' ~] `['$=' ~]]
|
|
:~ ?@(p.spec p.spec q.p.spec)
|
|
$(spec q.spec)
|
|
==
|
|
%bcvt &/[(fixed '$@') $(spec p.spec) $(spec q.spec) ~]
|
|
%bcwt :+ %&
|
|
[`[' ' `['?(' ')']] `['$?' `['' '==']]]
|
|
(turn `(list ^spec)`+.spec ..$)
|
|
%bczp (core-to-plum '$.' p.spec q.spec)
|
|
==
|
|
--
|