@@ -1,2576 +0,0 @@
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 hoon]`.
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=hoon q=silk] :: silk thru hoon
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=hoon] 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 hoon 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 hoons or references to hoons 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=hoon] :: /~ hoon by hand
185− [%arg p=hoon] :: /$ 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=hoon 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 in the [runes
202−documentation](https://urbit.org/docs/arvo/internals/runes), so we will here
203−only give a description of the data structure itself.
204−
205−A `%ape` horn is simply a hoon 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 hoon and a horn, where the hoon 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=hoon] :: direct hoon
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=hoon q=silk] :: silk thru hoon
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 hoon 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 hoons 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−requiring 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 hoons are parsed with
533−`++tall:vast`, which is the just the Hoon parser for a tall-form rune.
534−
535−References to external hoons 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−hoon. The wide form is a tuple of one or more ace-separated wide-form
604−hoons parsed with `++wide:vast` and surrounded by `[` and `]`. The tall
605−form is a single tall form hoon 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 hoon and a horn. The wide
669−form is a wide-form hoon 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 hoon, 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 hoon)) :: structure/complex
705− zog=(set term) :: structure guard
706− bil=(map term (pair hoof hoon)) :: libraries known
707− lot=(list term) :: library stack
708− zeg=(set term) :: library guard
709− boy=(list hoon) :: 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 hoons 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 hoons 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 hoons, 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−hoon, 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 hoon 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 hoons into a `=~`, push this
962−onto our old list of body hoons, 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 hoon defined in `/path/to/hoon/hoon`, our
990−body must refer to `hoon: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 hoons 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 hoons.
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 hoons 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 already
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 three 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 hoons.
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 hoons 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−hoongs 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 hoons. Next, we slap our preamble (structures and libraries)
1184−against zuse. First, we construct our preamble in `++able`.
1185−
1186− ++ able :: assemble preamble
1187− ^- hoon
1188− :+ %tsgr
1189− ?:(=(~ rop) [%$ 1] [%brcn (~(run by rop) |=([* a=hoon] [%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=hoon]
1201− ^- (bolt vase)
1202− %+ (clef %slap) (fine cof vax gen)
1203− |= [cof=cafe vax=vase gen=hoon]
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 hoon. In other words, we're compiling the hoon
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 hoon 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 hoon 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−hoon 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−hoons 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− ^- hoon
2355− :+ %cncb [%& 2]~
2356− =+ axe=3
2357− |- ^- (list (pair wing hoon))
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−`%_` hoon we directly construct. Since a `%_` hoon takes a list of pairs
2365−of wings and hoons, we simply have to generate hoons 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 hoon. 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.