@@ -11,6 +11,7 @@
1111:: +parse [file=path src=@t] (each module error)
1212:: +parse-tokens [file=path toks=(list token)] (each module error)
1313:: +golden [file=path src=@t] [tokens=@t tree=@t]
14+:: +golden-types [file=path src=@t] @t (partial inference)
1415:: +show-tokens (list token) @t
1516:: +show-module module @t
1617:: +show-error [src=@t error] @t
@@ -19,14 +20,20 @@
1920:: fails: an error it finds is its last token (2.0), and +layout-error
2021:: takes it out.
2122::
22−:: Status: the types, the printers, +golden and the layout pass
23−:: (+layout, +lexer) work. +parse-tokens is a stub that returns an
24−:: error; it is implemented next, against the design below. Choices the
23+:: Status: the syntax types, the printers, +golden, the layout pass (+layout,
24+:: +lexer) and the parser (+parse-tokens, +parser) work, and +golden
25+:: checks every tree's spans (+check-spans, section 1). Choices the
2526:: doc leaves open are marked "(doc question)": they follow the most
2627:: likely reading and are listed, with the doc's words, for the doc's
27−:: author to settle. The golden corpus's "expect:" lines give each
28−:: error's position. The layout pass's errors sit there, except where
29−:: the parser finds an earlier error first, as in `++ 2nd 5` (2.0, 2.8).
28+:: author to settle. Those the author has settled, in the Decisions
29+:: tab's rows of 2026-10-30, are marked "(Decisions)" beside the rule
30+:: decided. The golden corpus's "expect:" lines give each error's
31+:: position. A partial inference fragment is in %type-inference; its
32+:: output explicitly says the module has not been checked. The layout
33+:: pass's errors sit there, except where the
34+:: parser finds an earlier error first, as in `++ 2nd 5`, or moves one
35+:: back to the start of its text, as in `++ x @sd` (2.0, 2.8, and
36+:: section 3, Errors).
3037::
3138:: ===================================================================
3239:: 1. Positions
@@ -46,12 +53,18 @@
4653:: so does editor tooling later. A node starts at its first token and
4754:: ends where its last token ends: its closing token if it has one, else
4855:: its last child's last token, never a layout token. So an open
49−:: bracket, a body, ?-'s arms and $?'s cases end with their last line's
56+:: bracket, a body, ?-'s arms and a +$'s cases end with their last line's
5057:: code, not at the line that closes them. Every node's span holds its
5158:: children's spans, in source order. The printed tree shows starts
5259:: only, and milestone 1's errors use starts only, so ends are first
53−:: tested by milestone 2's excerpts; the parser's own tests should check
54−:: the two rules above on every golden tree.
60+:: used by milestone 2's excerpts. Until then +check-spans tests the two
61+:: rules above on every tree +golden prints, and a tree that breaks one
62+:: ends with a line "SPAN ERROR: (<kind> <start> to <end>) <why>". It
63+:: finds each node's end from the tokens alone, matching each opener
64+:: with its closer on the line, so a node that stops at a child where
65+:: its closer follows fails it, and +check-spans-test plants such
66+:: wrong ends to show that it does (tools/hoon check-spans-test prints
67+:: the empty list, <<>>, when it passes).
5568::
5669:: ===================================================================
5770:: 2. The layout pass (+layout)
@@ -61,17 +74,30 @@
6174:: crosses a line break, and only layout tokens join lines.
6275::
6376:: 2.0 Errors. +layout never fails. Where the text breaks a rule of this
64−:: section, it emits one error token, [%error msg], at the first
65−:: character that breaks it, and stops reading. The parser accepts no
66−:: error token, so it reports whichever comes first, its own error or
67−:: this one (section 3, Errors). Every error, from either stage, points
68−:: at the first character where the text stops being the start of any
69−:: valid module: everything before it could still be right. Hoon's
70−:: parser reports errors the same way, and the golden corpus's expect
71−:: lines assume it. It also puts `++ x ]` on line 1 before a bad string
72−:: on line 9, which a lexer that failed first would report instead. The
73−:: positions below follow from it. Messages quote code in backticks, as
74−:: the parser's do (section 3, Errors).
77+:: section, it emits one error token, [%error msg from c], at the first
78+:: character that breaks it, and stops reading. from is where the text it
79+:: was reading began, c is that text's first character, and the token is
80+:: tight when that text follows the previous token with no space. Where
81+:: the lexer has already cut a token from the front of that text, as 100
82+:: from 1000, the parser takes that token before it reaches the error, so
83+:: the text the error token stands for begins at the error: from is the
84+:: error's own place, and c the character there (2.8, +err-on). The
85+:: parser accepts no error token, so it reports whichever comes first,
86+:: its own error or this one (section 3, Errors). Every error, from
87+:: either stage, points at the first character where the text stops being
88+:: the start of any valid module: everything before it could still be
89+:: right. Hoon's parser reports errors the same way, and the golden
90+:: corpus's expect lines assume it. It also puts `++ x ]` on line 1
91+:: before a bad string on line 9, which a lexer that failed first would
92+:: report instead. The positions below follow from it, for text that
93+:: could begin a token where it stands; where the parser's place can't
94+:: begin with c at all, the parser moves the error back to from, as
95+:: `++ x @sd` at the @ (section 3, Errors). Spaces and comments emit
96+:: nothing (2.3, 2.6), so where a line ends before what it needs, the
97+:: error is just past the line's last token, not at its trailing
98+:: spaces or comment: `++ x ^- :: c` above a deeper line fails at 1:8
99+:: (section 3, Errors). Messages quote code in backticks, as the
100+:: parser's do.
75101::
76102:: 2.1 Lines. The text is split at every \0a. A final \0a ends the last
77103:: line rather than starting an empty one. Lines are numbered from 1.
@@ -120,7 +146,7 @@
120146:: The layout pass knows nothing of brackets: it emits INDENT, NEWLINE and
121147:: DEDENT by column alone. The parser decides what takes an indented
122148:: block: a bracket left open at the end of its line, a rune's body, ?-'s
123−:: arms, $?'s cases, a +$ mold on the next line. A bracket opened and
149+:: arms, and a +$'s cases on the next lines. A bracket opened and
124150:: closed on one line is just tokens.
125151::
126152:: 2.6 Tokens. After the indentation, tokens are read left to right;
@@ -143,15 +169,26 @@
143169:: else is an error at 3rd, "the loobeans are `%.y` and
144170:: `%.n`"
145171:: %& %| term literals, [%f 0] and [%f 1]
172+:: %$ the empty term, [%tas 0]
146173:: %a... term literal: % and a name [a-z][a-z0-9-]*, [%tas name];
147174:: a capital or _ right after it is an error there,
148175:: "names are lowercase letters, digits and -"
149−:: %0... term literal: % and digits [0-9]+, [%ud value]
150−:: (doc question: digits only, as the EBNF says, so
151−:: %1000 is a term and %1.000 an error at the dot); a
152−:: letter, _, - or . right after it is an error there,
153−:: "unexpected `a`: a numeric term is `%` and digits
154−:: only, as %1000"
176+:: %0... term literal: % and a decimal written as a number
177+:: literal's is, [%ud value]: %0, %42, %1.000
178+:: (Decisions). The run of [0-9a-zA-Z.] after the % is
179+:: read as a number literal's run (2.8) and fails at
180+:: the same character of the run: %1000 at its fourth
181+:: digit, as 1000 does, and %1.0 just past its run.
182+:: But %0 alone is a term, so anything in the run after
183+:: its 0 fails there, as the second 0 of %007 and the x
184+:: of %0x1f. That holds for every run of 0 and a letter,
185+:: which fails at the letter whether Hoon reads the run
186+:: as another aura or not (2.0): %0x and %0xg at the x,
187+:: as %0x1f, though 0x and 0xg as numbers fail at the
188+:: character after the x, since nothing goes on from
189+:: the 0 of %0. The message is "a numeric term is
190+:: `%` and a decimal, digits in groups of three joined
191+:: by dots, as %1.000" (+numeric-term)
155192:: % anything else after it: error at 2nd, "`%` begins a
156193:: term, a loobean or `%/`"
157194:: /- /% /= import glyphs at column 1, where imports go; anywhere
@@ -160,10 +197,11 @@
160197:: / glyph, then a path segment may follow (2.7)
161198:: ++ +$ + glyphs
162199:: |=( |= |$ glyphs
163−:: $?( $? $-( glyphs; $- followed by anything but ( is an error
200+:: $-( glyph; $- followed by anything but ( is an error
164201:: at 3rd, "`$-` has only the wide form `$-(sample
165202:: product)`"
166−:: ^- ?- !! ? glyphs (? alone is the loobean mold)
203+:: ^- ?- !! ? glyphs (? alone is the loobean mold; ? then a
204+:: character of Hoon's other ? runes is left out, below)
167205:: @ aura: @, then [a-z]*, then at most one [A-Z]; the
168206:: token holds the text after @. An aura starting @s or
169207:: @r is an error at 2nd: "signed and floating-point
@@ -183,10 +221,10 @@
183221:: at it, "this `}` closes no `{`"
184222:: | $ ^ followed by nothing above or in the table below:
185223:: an error at 2nd, "`|` begins `|=`, `|=(` or `|$`",
186−:: "`$` begins `$?`, `$?(` or `$-(`", "`^` begins `^-`"
224+:: "`$` begins `$-(`", "`^` begins `^-`"
187225:: : followed by anything but :, an error at 2nd: the
188−:: table's :~ :* and a:b, else "a comment starts with
189−:: `::`"
226+:: table's :~ :* :- :+ :^ :_ and a:b, else "a comment
227+:: starts with `::`"
190228:: anything else an error at it, naming it: "unexpected `,`", with a
191229:: hint where one helps (+unexpected): for , . - and <,
192230:: what Jibb writes instead
@@ -194,32 +232,46 @@
194232:: Hoon forms the doc leaves out are errors with the doc's reason, as
195233:: "`|%` is left out: modules are records". Each points where the text
196234:: stops being Jibb: at its second character when its first can begin
197−:: Jibb there, else at its first.
235+:: some Jibb token, else at its first. Where the parser's place can't
236+:: begin with that first character, the parser moves the error to it
237+:: (2.0): `|%` at the top of a file fails at the |, `++ x |%` at the %.
238+:: The doc's list says "such as" of the tall forms and the wide ones,
239+:: so Hoon's runes of the same kinds get the same reason (doc
240+:: question):
198241::
199242:: |% |_ |* 2nd modules are records
200243:: |- 2nd gates recurse by name
201−:: $( 1st gates recurse by name; no expression starts $
202−:: $% 2nd $? covers unions
203−:: ?+ ?: 2nd ?- is the branch (?:: is ? and a comment)
244+:: $( 2nd gates recurse by name (at the $ where an
245+:: expression goes, as no expression starts $)
246+:: $? $% 2nd a union is a +$ with its cases below
247+:: ?: ?+ 2nd ?- is the branch, and so for Hoon's other ?
248+:: runes, ?~ ?= ?. ?@ ?^ ?& ?| ?< ?> (?:: is ?
249+:: and a comment)
204250:: ?! 2nd eq and not are gates
205251:: .= 1st eq and not are gates
206252:: !x 2nd not is a gate: ! then anything but ! or >
207253:: !> /+ 2nd code also runs in the browser
208−:: =< => .* 1st names never shadow, and . reads imports too
254+:: =< => 2nd names never shadow, and . reads imports too
255+:: .* 1st the same
209256:: a:b 2nd of the :, right after a name: names never
210257:: shadow, and . reads imports too; write a.b
211258:: :~ :* 2nd indentation covers them; write ~[…] or […]
212−:: %: %= 2nd indentation covers them
213−:: == -- 1st the closers are left out: indentation covers
214−:: them
259+:: :- :+ :^ :_ 2nd indentation covers them; write a cell as [a b]
260+:: %: %- %+ 2nd indentation covers them; a call is (f a b)
261+:: %^ %~
262+:: %= 2nd indentation covers it; write a change, m(a=b)
263+:: == 2nd the closers are left out: indentation covers
264+:: -- 1st them
215265:: ~| 2nd ~& covers debugging
266+:: ;: 1st nest the calls, as (add a (add b c))
216267:: ; 1st Sail's ; runes are left out: layout is Jibb's
217268:: elements
218269:: ' 1st there is no '…' form: strings are "…"
219270::
220271:: The parser finds the doc's other left-out forms (section 3, Errors):
221−:: =(a b), =/, *mold, ^-(…) and ?-(…). The lexer can't, since =( =/ and *
222−:: begin valid Jibb too: open=(not open.s), scry=/todos, a * mold.
272+:: =(a b), =/, *mold, ^-(…), ?-(…) and ~&(…), and Hoon's =+ =? and =.
273+:: The lexer can't, since = and * begin valid Jibb too: open=(not
274+:: open.s), scry=/todos, a * mold.
223275::
224276:: 2.7 Paths. Right after a / or %/ glyph, a run of knot characters
225277:: [a-z0-9._~-] is one knot token, tight. So /posts/~zod is / knot / knot;
@@ -240,24 +292,47 @@
240292::
241293:: 2.8 Literals. The lexer takes a literal's run (2.6), then reads it
242294:: with Hoon's own parser, (nuck:so [[line col] run]), whose edge says
243−:: how much it read and how far it looked (p.edge):
295+:: how much it read and how far it looked (p.edge). Some runs never
296+:: reach it, since they begin an aura Jibb doesn't write, whatever
297+:: follows, or text Hoon's parser crashes on:
298+:: - 0b, 0c, 0i and 0w: an error at 2nd, "Jibb writes no @uw
299+:: literals" and so on. Hoon's parser would read 0b, or a 0c1 whose
300+:: checksum fails, as the number 0 and an error past the run.
301+:: - ~- (a @c), "Jibb writes no @c literals", and ~~ (a cord), "Jibb
302+:: writes no @t literals; strings are "…"", at 2nd. Hoon's reader of
303+:: @c crashes on a control character, as in ~-~1.
304+:: - ~0 and a base-32 digit, at 3rd: Hoon's parser reads a blob there
305+:: and cues it, which can run out of memory, past what mule catches.
306+:: No Jibb literal goes on so, since a year has no leading 0: after
307+:: a letter it is "Jibb writes no blob literals", after a digit the
308+:: date's message (+literal-msg). ~0.1.1 is a date (below).
309+:: - A year BC of 0 or past 292.277.024.401, as in ~0-.1.1, at the -
310+:: that makes it BC: Hoon's +year crashes on it (+year-bc).
311+:: - A fifth sub-second group, after a duration's .. or a date's
312+:: second .., at the dot that begins it: "a date or duration takes
313+:: at most four sub-second groups", as Hoon's do, since its +yule
314+:: crashes on a fifth (+fifth-group).
315+:: A date or duration is also read under mule, so that any other crash
316+:: is an error at the run's start, "Jibb can't read this literal"; other
317+:: runs aren't, since mule costs about a millisecond a call. Then:
244318:: - It read the whole run, as an aura Jibb takes: the token. Numbers
245319:: take %ud, %ux and %uv: 1.000, 0x1f, 0v5.fdf99 (Hoon reads 0x1F
246320:: too). ~ runs take %p, %da, %dr and %ta: ~zod, ~sampel-palnet,
247−:: ~2026.10.23..14.30.00, ~h1.m30, ~.my-post.
248−:: - It read the run or part of it as an aura Jibb doesn't take: 0w1,
249−:: 0i1, ~~a (a cord), ~-a (a @c). An error at 2nd, "Jibb writes no
250−:: @uw literals". A run starting 0b, 0c, 0i or 0w gets that error
251−:: before nuck:so reads it, since no Jibb literal goes on that way:
252−:: Hoon's parser would read 0b, or a 0c1 whose checksum fails, as
253−:: the number 0 and an error past the run.
321+:: ~2026.10.23..14.30.00, ~h1.m30, ~.my-post. Its value is Hoon's,
322+:: as every literal reads exactly as Hoon reads it (Decisions):
323+:: ~0.1.1 is 1 BC and prints as ~1-.1.1, ~2026.2.31 is ~2026.3.3,
324+:: and years BC and sub-second groups are dates.
325+:: - It read the run or part of it as another aura Jibb doesn't take:
326+:: an error at 2nd that names the aura, as "Jibb writes no @if
327+:: literals".
254328:: - It read only part of the run, as an aura Jibb takes: that part is
255329:: a token, then an error token at p.edge, the furthest character
256330:: Hoon's parser looked at, where Hoon reports it too. 1000 is the
257331:: token 100 and an error at its fourth digit ("a decimal is digits
258332:: in groups of three joined by dots, as 1.000": each kind of literal
259333:: has its message, +literal-msg); 0v5.fdfz9 is 0v5 and an error at the
260−:: z; ~2026.10.29..14.30 is ~2026.10.29 and an error just past the
334+:: z; ~2026.10.29..14.30, the minute form print-date writes, is no
335+:: literal (Decisions) but ~2026.10.29 and an error just past the
261336:: run. The token lets the parser report an earlier error first: in
262337:: `++ 2nd 5` it finds the number 2 where a name goes, at 1:4.
263338:: When it read a ship, or only the ~ of a run that goes on with a
@@ -266,18 +341,22 @@
266341:: d h m or s, if that is later: Hoon's parser reads a syllable's
267342:: three letters before it looks them up, so it looks past that
268343:: letter. `++ x ~x` fails at the x, 1:7, as no syllable starts with
269−:: x, and ~sampel-palnez at the z.
270−:: A run that starts as a date BC does, ~ and a year then -, fails at the
271−:: - if the year is 0 or past 292.277.024.401, before nuck:so sees it:
272−:: Hoon's +year crashes on those years, as in ~0-.1.1 (+year-bc).
273−:: The token is [%lit [form aura val]]: form names the literal rule that
274−:: matched, aura and val are the dime Hoon's parser gives. Terms,
275−:: loobeans and the bare ~ are read by hand (2.6).
276−::
277−:: 2.9 Strings. A " starts a string, which ends on the same line. Up to
278−:: the closing ":
279−:: \\ \" \{ and \ with two lowercase hex digits are escapes, as in
280−:: Hoon's tapes (doc question: the doc names only \{ and \"). Any
344+:: x, and ~sampel-palnez at the z. The error token's from is the
345+:: error's own place, not the run's start, since the parser has
346+:: taken the run's first part as a token by the time it reaches the
347+:: error (2.0, +err-on): so `+$ x ~x` fails at the x too, the ~
348+:: being a mold, and `+$ x %1.0` at 1:10, as `++ x %1.0` does.
349+:: The token is [%lit [form aura val txt]]: form names the literal rule
350+:: that matched, aura and val are the dime Hoon's parser gives, and txt
351+:: is the literal as written. A numeric term's decimal is read as a
352+:: number's run is, here, from the character after its % (2.6,
353+:: +numeric-term); the other terms, loobeans and the bare ~ are read by
354+:: hand (2.6).
355+::
356+:: 2.9 Strings. A " starts a string, which ends on the same line, as each
357+:: of its {…} does (Decisions). Up to the closing ":
358+:: \\ \" \{ and \ with two lowercase hex digits are escapes, Hoon's
359+:: (Decisions), so \\ writes a backslash and \0a a line feed. Any
281360:: other \ is an error at the first character that can't continue
282361:: the escape: the one after the \, or a bad second hex digit (2.2's
283362:: error if it is a tab or another control character)
@@ -293,18 +372,18 @@
293372:: parser reads head expr { mid expr } tail. The lexer keeps a stack of
294373:: open interpolations, since strings nest inside them. Inside an
295374:: interpolation a : is an error at it, "a comment can't start inside
296−:: `{…}`", and so is a {; inside a string, :: is text. A line that ends
297−:: inside a string or an interpolation is an error at its end, "this
298−:: string has no closing `\"` on its line" or "this `{` has no `}` on its
299−:: line". Token texts hold the decoded text. Spaces after { and before }
300−:: are allowed, as after any opener.
375+:: `{…}`", and so is a {; inside a string, :: is text (Decisions). A
376+:: line that ends inside a string or an interpolation is an error at
377+:: its end, "this string has no closing `\"` on its line" or "this `{`
378+:: has no `}` on its line". Token texts hold the decoded text. Spaces
379+:: after { and before } are allowed, as after any opener (Decisions).
301380::
302381:: 2.10 What fails here. Bad characters (2.2), an indented first line and
303382:: a dedent to no open level (2.4), characters that start no token or a
304−:: left-out form (2.6), malformed literals, auras, type variables and
305−:: wings (2.6, 2.8), a character that no token lets follow a path
306−:: segment, a ~. knot or a numeric term (2.6, 2.7), and unclosed strings
307−:: and interpolations, bad escapes and stray { or } (2.9). Everything
383+:: left-out form (2.6), malformed literals and numeric terms, auras,
384+:: type variables and wings (2.6, 2.8), a character that no token lets
385+:: follow a path segment or a ~. knot (2.7), and unclosed strings and
386+:: interpolations, bad escapes and stray { or } (2.9). Everything
308387:: else is the parser's: brackets that don't match or don't close, a
309388:: missing or extra space, a deeper line that nothing takes, a token
310389:: where it can't go.
@@ -313,14 +392,15 @@
313392:: 3. The parser (+parse-tokens)
314393:: ===================================================================
315394::
316−:: Hand-written recursive descent over the token list: one arm per EBNF
317−:: rule, each taking the remaining tokens and returning (pare node): the
318−:: node and the tokens after it, or an error. Steps chain with ;< and
319−:: +then, so an error stops the parse:
395+:: Hand-written recursive descent over the token list (+parser): one
396+:: arm per EBNF rule, each taking the remaining tokens and returning
397+:: (pare node): the node and the tokens after it, or an error. Steps
398+:: chain with ;< and +then, so an error stops the parse (+read-cast):
320399::
321−:: ;< [s=shape ts=(list token)] then (mold ts)
322−:: ;< [e=expr ts=(list token)] then (expr-or-body ts)
323−:: [%& [%cast [beg.at.rune end:(span-of e)] s e] ts]
400+:: ;< [s=shape after=(list token)] then (read-mold ts)
401+:: ;< [e=expr more=(list token)] then
402+:: (read-expr-or-body "the mold" after)
403+:: [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
324404::
325405:: Why: after the layout pass the grammar is LL(2). Each choice is made by
326406:: the next token, at most with the one after it and whether it is tight:
@@ -340,11 +420,27 @@
340420:: descent is shorter, and each error names what its construct expected.
341421:: An operand that isn't where an expression starts (a call's argument,
342422:: an item, a pair's or unit's operand, the wide gate's body) can't be a
343−:: rune, so there |= is a constructor and needs its term at once:
344−:: (state.cart |= %got) is an error at the space after |=, 1:20. Loops
345−:: over many items (definitions, arms, lines, items) may recurse: vere's
346−:: stack takes ten million plain frames, so no Jibb file nests or runs
347−:: long enough to overflow it.
423+:: rune, so there |= is a constructor and needs its term at once, or
424+:: the ( of the wide gate: in ++ x (state.cart |= %got) the space after
425+:: |= is an error, 1:20. A loop over many items (definitions, arms,
426+:: lines, items) is a trap whose every step, through +then, is a tail
427+:: call, so a long module grows no stack. Nesting does, by a few frames
428+:: a level: 100.000 nested parentheses parse, closed on their line or
429+:: left open above one deeper line, and so do 100.000 nested calls,
430+:: ++ x (f (f … ~[ above one deeper line, and a 20.000-line module.
431+:: Brackets left open on one line close together at one test each
432+:: (+shut), with no look back at their tokens. +golden's tree stops
433+:: indenting past 64 levels (4.2), so its size grows with the text's,
434+:: not with its square, and its time a little faster than the nesting:
435+:: tools/golden takes 12 s, 23 s and 70 s on 10.000, 30.000 and
436+:: 100.000 such calls, 8 s of it starting urbit and building the
437+:: library, and most of the rest printing the tree, 46 MB at 100.000.
438+::
439+:: @iko decided 2026-10-30 (Decisions): "No `$?`: a `+$` with its cases
440+:: on the lines below is a union, so every union written in Jibb has a
441+:: name; one case is just that mold; a mold that isn't a union counts as
442+:: a union of one case for tags and `|=%tag`; a generic's `|$` comes right
443+:: after the `+$`'s name; tags anywhere".
348444::
349445:: The EBNF and its nodes (see the types below):
350446:: module { import NEWLINE } { definition NEWLINE }, then the end
@@ -352,38 +448,60 @@
352448:: "expected a definition, found `/-`; imports come first"
353449:: import /- name -> %sur; /% term -> %mark; /= name pathlit ->
354450:: %jibb. /% takes % and a name only: no mark is called %0,
355−:: %& or %| (doc question)
356−:: definition +$ name mold, or the mold alone on a deeper line ->
357−:: %mold (both layouts give one node); ++ name expr or body
358−:: -> %value (a body becomes a %body expr)
451+:: %& or %| (doc question). /='s path has a segment, as it
452+:: names a module's file: /= card / is an error just past
453+:: the / (doc question)
454+:: definition +$ name, optional |$ [vars], then a mold on its line or
455+:: cases below -> %mold; one case is that mold, several
456+:: are %union. The optional generic wraps either in %generic.
457+:: ++ name expr or body -> %value (a body becomes a %body expr)
359458:: body INDENT { definition NEWLINE } expr DEDENT -> %body
360459:: call one operand is that operand; more -> %call head args
361−:: operand literal -> %lit or %str; pathlit -> %path (not in the
362−:: EBNF's operand, but in the Literals table: doc
363−:: question); qath -> %qath; ref -> %wing; change -> %change;
364−:: pair -> %pair; unit -> %unit; group -> %group; list ->
365−:: %list; tuple -> %tuple; gate -> %gate-wide; ctor -> %ctor
460+:: operand literal -> %lit or %str; pathlit -> %path, as a path
461+:: literal is an expression (Decisions); !! -> %crash, as
462+:: !! is an operand (Decisions), so f !!, [a !!], ~[!!],
463+:: `!!, a+!!, m(a=!!) and |=(a !!) need no parentheses;
464+:: qath -> %qath; ref -> %wing; change -> %change; pair ->
465+:: %pair; unit -> %unit; group -> %group; list -> %list;
466+:: tuple -> %tuple; gate -> %gate-wide; ctor -> %ctor
366467:: group ( expr ) -> %group of the expr. The open form ( {operand}
367468:: open -> %group of the call whose elements are the first
368469:: line's operands, then one per line; one element alone is
369−:: just grouped. A ( followed by a rune is the closed form.
370−:: Lines of an open group or list take no name= (doc
371−:: question)
470+:: just grouped. A ( alone at the end of its line puts the
471+:: head on the first deeper line (Decisions), and needs
472+:: that line, as () is no group. A ( followed by a rune is
473+:: the closed form. Lines of an open group or list take no
474+:: name= (doc question)
372475:: change every item and line has name= (the EBNF's "items named")
373−:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch;
374−:: !! -> %crash. !! is not an operand, so [a !!] needs
375−:: [a (!!)] (doc question)
476+:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch.
477+:: !! is an operand, not a rune (Decisions): alone where an
478+:: expression goes it is a call of one operand, and !! a
479+:: is a call whose head is !!, for the checker to judge
376480:: sample the sample of |= and |=(…): a field, except that a bare
377481:: name binds (%bind) wherever it stands in the sample: the
378482:: whole sample, as |= x and |=(p title.p), or a field of a
379483:: cell sample at any depth, as b in |= [a=@ b], which is
380−:: a %cell of samples (doc question). A name inside a mold,
381−:: as a in (list a), $-(a b) or $?(a b), is a mold
484+:: a %cell of samples (Decisions: every bare name in a
485+:: sample binds, at any depth). A name inside a mold, as a
486+:: in (list a) or $-(a b), is a mold. A cell
487+:: sample's [ has no open form, as a cell pattern's hasn't
488+:: (Decisions)
382489:: mold aura -> %aura; * -> %noun; !! -> %void; ? -> %flag;
383490:: ~ term loobean -> %const; ref -> %ref; typevar -> %tvar;
384491:: pathmold -> %path; ( ref mold … ) -> %apply; [ field … ]
385−:: -> %cell; $? with cases below, and $?( … ) -> %union;
386−:: $-( mold mold ) -> %fn; |$ [ typevar … ] mold -> %generic
492+:: -> %cell; $-( mold mold ) -> %fn. Only a +$ definition
493+:: introduces %union or %generic.
494+:: A mold's ( and [ may be left open at the end of their
495+:: line, as an expression's brackets can (Decisions):
496+:: ( ref { mold } mlines -> %apply, the name staying on
497+:: the first line, so ( alone there is an error at the end
498+:: of its line, where the name goes; [ { field } flines ->
499+:: %cell, [ alone too.
500+:: mlines and flines are INDENT and one mold or field per
501+:: deeper line, which may itself open, to the DEDENT; a
502+:: second item on a line, or a closer, is an error. The
503+:: node is the closed form's, ending with its last item.
504+:: $-( has no open form.
387505:: field name=mold -> %face; =name -> %pun; mold -> %bare
388506:: pattern term number ship loobean ~ -> %lit (dates, durations and
389507:: knots are errors); string without {…} -> %str; * -> %any;
@@ -392,24 +510,50 @@
392510:: What the EBNF leaves out, and how this design fills it in:
393511:: - Rules it names but doesn't define: string, ship, date, duration,
394512:: knotlit, decimal, hex, base32, lower, upper and digit. They are
395−:: Hoon's literals (the Literals table; Decisions: "Hoon's runes as
396−:: keywords, and its literals"), read as 2.6, 2.8 and 2.9 say.
513+:: Hoon's literals, exactly (the Literals table; Decisions: 1000 is
514+:: an error, ~2026.2.31 is ~2026.3.3, years BC and sub-second groups
515+:: are dates, and print-date's minute form is no literal), read as
516+:: 2.6, 2.8 and 2.9 say; a numeric term's decimal is a number's.
397517:: - A string's interpolations: str alone, or str-head expr { str-mid
398518:: expr } str-tail, where each expr is a full expression.
399519:: - Spaces, comments and blank lines: the layout pass, and Spacing
400520:: below.
401−:: - pathlit as an operand (above), with / alone the empty path.
402−:: - knot may be empty: only / alone uses that, as the empty path; //
403−:: and a trailing / are errors (doc question).
404−:: - Open brackets in molds: mold has no open form, so a mold's [ or (
405−:: closes on its line, and only $? takes lines below (doc question).
406−:: - Two brackets left open on one line, as (column ~[: the last one
407−:: takes the deeper lines, and the other is then unclosed, an error
408−:: (doc question).
409−:: - Local definitions: the EBNF takes them in every body (of ++, |=,
410−:: ^-, ~& and arms), the Runes prose says "inside a gate"; the parser
411−:: takes them in every body and leaves the rest to the checker (doc
412−:: question).
521+:: - knot may be empty: only / alone uses that, as the empty path in
522+:: an expression or a mold, not in an import; // and a trailing /
523+:: are errors (doc question).
524+:: - Several brackets left open on one line, which its layout comment
525+:: allows and its productions can't say (Decisions): the deeper
526+:: lines go to the last bracket or rune left open on the line, and
527+:: every bracket open before it closes with it, at the first line
528+:: that isn't deeper, with no closer, ending where its last item
529+:: ends. So (column ~ ~[ above its items is (column ~ ~[…]), and
530+:: the next line at its depth goes to what holds that line. This
531+:: holds for every bracket before the last, whether or not it has
532+:: an open form of its own, as the Decisions say "the brackets
533+:: before it close with it": an expression's ( [ and ~[, a change's
534+:: (, |=(, a mold's ( [ and $-(, an application path's (…), and
535+:: a cell sample's [. A segment's ( holds an expression as an
536+:: expression's ( does and needs only its ), so %/a/(f ~[ above its
537+:: items is %/a/(f ~[…]), as $-(, which has no open form
538+:: either, closes so; a sample's [ that closes so leaves its gate no
539+:: body. A cell pattern's [ and |$'s [ hold no other bracket, and
540+:: an interpolation's {…} closes on its line (2.9). A rune's body
541+:: or arms that took the lines close the brackets before the rune
542+:: too: (|= a above its body is a group holding the gate. A bracket
543+:: closes so when the last item it read ends on a later line than
544+:: its opener, which needs no look back (+shut). One that still
545+:: needs a part after that item, as |=( or $-( with only its
546+:: sample, can't close so, and neither can a rune before the last
547+:: opener that needs deeper lines of its own: errors at the end of
548+:: the line (Errors below). A mold's ( never needs more than its )
549+:: once it holds its name: one that is the last opener on its line
550+:: takes the deeper lines as its open form (Decisions), and one
551+:: before a later opener holds that mold after its name and closes
552+:: with it.
553+:: - Local definitions: at the start of any body, a gate's, an arm's,
554+:: a ^-'s, a ~&'s or a ++'s, as the EBNF's body takes them
555+:: (Decisions); +$ as well as ++, as the Runes prose's "likewise"
556+:: says.
413557:: - Where errors point: the doc says only "line, column and an
414558:: excerpt"; 2.0 and Errors below say where.
415559::
@@ -419,16 +563,18 @@
419563:: lines, fields and samples), =name (pun); in a path or application
420564:: path, each / and the segment after it, and all of a typed segment,
421565:: [id=@ud]
422−:: - either way: right after an opener ( [ ~[ |=( $?( $-( or {, and
566+:: - either way: right after an opener ( [ ~[ |=( $-( or {, and
423567:: right before a closer ) ] or } (the theme example writes `[ space=`),
424568:: the ( and ) of an application path's segment included; inside
425569:: them the expression is spaced as anywhere else, as %/x/(f a)
426−:: A missing space is an error at the tight token, and so is a space
427−:: inside a tight form, at the space (Errors). A rune with children, and
428−:: an import glyph, is followed by a space (or, for $? with its cases
429−:: below, the end of the line). Items are separated by one or more
430−:: spaces; how many isn't checked. This is how the parser makes "one
431−:: space between items; more for alignment" precise (doc question).
570+:: A missing space is an error at the tight token, and a space inside
571+:: a tight form, or the end of the line there, is one where it starts
572+:: (Errors). A rune with children, and an import glyph, is followed by
573+:: a space.
574+:: Items are separated by one or more spaces; how many isn't checked,
575+:: and a line may end in spaces. Spacing beyond this is style, which
576+:: the formatter keeps: "one space between items; more for alignment"
577+:: (Decisions).
432578::
433579:: Errors. The parser stops at the first token it can't accept and
434580:: reports "expected <what>, found <token>", with an optional "; <hint>",
@@ -439,38 +585,131 @@
439585:: the same depth" (NEWLINE), "a shallower line" (DEDENT), or "the end of
440586:: the file" (an empty span, 2.5). Each error points at the first
441587:: character that can't begin a valid module (2.0):
442−:: - At the token's start; for a layout token, at the start of the
443−:: line it begins, or just past the last token at the end of the
444−:: file (+where). So `++ view` above `++ main view` is an error at
588+:: - At a token the place can't take: just past the part of it that
589+:: could still begin what the place takes (+fail-in, +prefix). That
590+:: is none when the place can't begin with its first character, so
591+:: `++ 2nd 5` fails at the 2, 1:4; a wing's first name where a name
592+:: goes, so `++ a.b 1` fails at the dot, 1:5; else one character,
593+:: as the % of %.y where a term goes, the ~ of ~zod where a mold
594+:: goes (~ alone is one), or a + or ? alone. A layout token is at
595+:: the start of the line it begins, or just past the last token at
596+:: the end of the file (+where), where another line, deeper or not,
597+:: would have done. So `++ view` above `++ main view` is an error at
445598:: 2:1, the line that isn't deeper.
446599:: - Where a tight form needs its next token at once (after name+, `,
447−:: |= in an operand, name=, the = of a pun, a path's / and %/, a
448−:: typed segment's parts) and finds a space: at the end of the
449−:: previous token, where the space starts, "expected a term right
450−:: after `|=`, found a space" (+fail-space). A wing and a ( after a
451−:: space are no error: that is a call.
452−:: - At an error token: the lexer's position and message, unchanged.
453−:: - Three pattern errors point inside their token, where it stops
454−:: being a pattern: a date, duration or knot at its second character
455−:: (~ alone is null, and no ship goes on so), ~[ at its [, and a
456−:: string with {…} at its {.
600+:: |= in an operand, name=, the = of a pun, a / after a path
601+:: segment, a typed segment's parts) and finds a space or the end
602+:: of the line: at the end of the previous token, where the space or
603+:: the line's end starts, as "expected an operand right after `+`,
604+:: found the end of the line" (+fail-space). No later line can give
605+:: a tight form its next token. A wing and a ( after a space are no
606+:: error: that is a call; nor is / or %/ alone, a whole path. A
607+:: change's item is name=, so a name there with no = right after it
608+:: fails just past the name, whatever follows: `m(b c)` at the
609+:: space, `m(b)` at the ), `m(a"x)` at the " with the layout pass's
610+:: message after the parser's (+unnamed, +moved). `m(a==1)` has its
611+:: =, and fails at the second, where the layout pass does.
612+:: - Where the place needs text on its own line and the line ends,
613+:: whatever line comes next: at the end of that line, just past its
614+:: last token, "found the end of the line" (+fail-line), as no later
615+:: line can supply it. That is a rune's part on its line (|='s
616+:: sample, ^-'s mold, ~&'s value, ?-'s subject, |$'s [), a
617+:: name after ++ or +$, an import's parts, and what a bracket that
618+:: closes on its line still needs: one with no open form ($-(
619+:: |=(, a cell sample's or cell pattern's [, |$'s [, an application
620+:: path's (…), a ( before a rune), or a mold's ( before its name,
621+:: which stays on the first line (Decisions); the bracket adds "this
622+:: bracket closes on its line" (+unclosed-want). So `++ x ^-` above
623+:: a deeper line fails at 1:8, "expected a mold, found the end of the
624+:: line". Spaces and a comment after the last token
625+:: emit nothing (2.3, 2.6), so they don't move the end of the line:
626+:: `++ x ^- :: c` fails at 1:8 too. At the end of the file the place
627+:: is the same, and the message says "the end of the file".
628+:: - At an error token: the lexer's position and message, unless the
629+:: text it was reading begins with a character the place can't
630+:: begin with. Then at that character, the lexer's message after
631+:: the parser's (+moved): `++ x @sd` is "expected an expression,
632+:: found `@`; signed and floating-point auras are left out of Jibb"
633+:: at the @, while `+$ x @sd` fails at the s. The place includes
634+:: what could still go on before it: after a call's operand and a
635+:: space, another operand, so `++ x a ?:` fails at the ? and `++ x
636+:: a |%` at the % (+read-operands), as `++ x !! |%` does, !! being
637+:: an operand; after a mold or an import that ends a line, nothing,
638+:: so `+$ x @ |%` fails at the | (+bad-end-in), and so after an
639+:: open mold bracket's line's one item; tight after an item, a
640+:: closer, or after a name the ( . + or = of a change, wing, pair
641+:: or face (+tight-error, which doesn't look at what the item was,
642+:: though it takes no = after a call's operand). A : stays where
643+:: the lexer put it, since it could begin a comment. An error token
644+:: after a space or on a later line, where a tight form needed its
645+:: next token, comes after the tight form's error (+fail-space).
646+:: - At layout tokens followed by an error token whose text begins
647+:: the line, both errors are at the line's start, and the lexer's
648+:: message, about that text, says more: a line `==` that closes a
649+:: ?- is "the closer `==` is left out: indentation covers it", not
650+:: "expected the end of the body" (+lexer-error).
651+:: - Where a line's last open bracket or rune took the deeper lines
652+:: while something before it on the line still needs more: deeper
653+:: lines of its own (a ~&'s body, a ?-'s arms, a tall |='s or ^-'s
654+:: body when nothing on the line gives one), a part after the one
655+:: that took them (|=('s body, $-('s product), or the } of an
656+:: interpolation (2.9): at the end of that line, since no later
657+:: line can supply it (+doomed). The brackets before the last close
658+:: with the deeper lines instead (What the EBNF leaves out), so a
659+:: gate whose cell sample's [ closed so still has no body.
660+:: `++ x ~& a ~[` above deeper lines is "expected `~&`'s body on
661+:: deeper lines, found the end of the line; the deeper lines go to
662+:: the last bracket or rune left open on this line", at 1:13.
663+:: - Pattern errors point inside their token, where it stops being a
664+:: pattern: a date or knot at its second character (~ alone is
665+:: null, and no ship goes on so), a duration just past its unit
666+:: letter (~d begins ships, as ~dur), ~[ at its [, and a string
667+:: with {…} at its {.
457668:: In a bracket, a closer that doesn't match is "expected `]` to close
458669:: the `~[` at 1:6, found `)`", checked before spacing; after an item, a
459670:: tight token that isn't a closer is "expected a space between items,
460−:: found `M`". Hints name the left-out forms the lexer can't see (2.6):
461−:: where an expression starts, = followed tight by ( is "=(a b) is left
462−:: out: eq is a gate", = followed tight by / is "=/ is left out: ++
463−:: defines values", and * is "*mold is left out: no defaults"; ^- or ?-
464−:: followed tight by ( is "the wide form ^-(…) is left out: indentation
465−:: covers it". Examples:
671+:: found `M`". A bracket that closes on its line names, at a closer that
672+:: doesn't match or at its line's end, what it still needs: its closer
673+:: once it holds all it needs, else its next part, as `$-(@)` and `$-(@]`
674+:: are "expected a mold, the product", and `$-(]` "expected a
675+:: mold", `|=(]` and `|= []` "expected a sample", `|=(a]` "expected the
676+:: gate's body" (+unclosed-want). So does a group's ( with nothing after
677+:: it on its line, as () is no group: `()` and `(]` are "expected an
678+:: expression", and a ( alone whose next line isn't deeper "expected the
679+:: call's head on a deeper line" (+read-group). A ) or ] that closes no
680+:: bracket opened before it on its line adds "this `)` closes no bracket"
681+:: (+stray), and a closer on a line of an open bracket "a bracket open at
682+:: the end of its line takes no closer: its items end at the first line
683+:: that isn't deeper". Hints name the left-out forms the lexer can't see
684+:: (2.6): where an expression starts, = followed tight by ( is "=(a b) is
685+:: left out: eq is a gate"; = followed tight by / is "=/ is left out: ++
686+:: defines values", and so for Hoon's =+ =? and =.; * is "*mold is left
687+:: out: no defaults"; ^-, ?- or ~& followed tight by ( is "the wide form
688+:: ^-(…) is left out: indentation covers it". Others name likely slips:
689+:: |= and a space where an operand goes, "a gate in an operand is |=(a
690+:: body)", or before a term "a case's constructor takes its term with no
691+:: space, as |=%got"; name= in a pattern, "patterns take no `name=`: a
692+:: bare name binds, as [a b]"; a capital or a wing where a name goes, "a
693+:: name starts with a lowercase letter" and "a name has no `.`"; a lone +
694+:: where a definition goes, "`+` begins `++` or `+$`"; a mold's ( alone
695+:: at the end of its line, "a `(` keeps the mold's name on its first
696+:: line"; a second item on a line of an open mold bracket, "a bracket
697+:: open at the end of its line takes one field per line" (or mold). The
698+:: messages quote that code in backticks (2.0), as in "`=(a b)` is left
699+:: out: eq is a gate".
700+:: Examples:
466701:: expected `]` or an item on a deeper line, found a line at the same
467702:: depth
703+:: expected `]` or a field on a deeper line, found a line at the same
704+:: depth
468705:: expected the end of the line, found a deeper line; only a bracket
469706:: open at the end of a line, or a rune's body, takes deeper lines
470707:: expected an expression, found `^-`; inside a call, a rune goes in
471708:: parentheses
472−:: expected a named item, found `x`; a change's items are named, as in
709+:: expected a named item, found `1`; a change's items are named, as in
473710:: m(done=%.y)
711+:: expected `=` right after `b`, found a space; a change's items are
712+:: named, as in m(done=%.y)
474713:: Messages of milestone 1 are golden-tested, so their wording is fixed
475714:: by the tests once written.
476715::
@@ -483,8 +722,8 @@
483722:: 4.1 Tokens (+show-tokens): one token per line, "<line>:<col>" at
484723:: +where, then "tight " if the token is tight, then the kind and the
485724:: text. Kinds: glyph (with its text), INDENT, DEDENT, NEWLINE, name, wing,
486−:: lit (the literal as Hoon prints its dime: 1.000, 0x1f, ~zod, ~h1.m30,
487−:: ~.knot; terms as %add, %0, %& and %|; loobeans %.y and %.n; null ~),
725+:: lit (the literal as written: 1.000, 0x1f, ~zod, ~h1.m30, ~.knot;
726+:: terms as %add, %1.000, %& and %|; loobeans %.y and %.n; null ~),
488727:: str, str-head, str-mid and str-tail (quoted, with \\ \" \{ and \XX
489728:: escapes), knot, aura (@ud), tvar, and ERROR with its message (+golden
490729:: prints the rendered error instead). A layout token prints at the
@@ -518,7 +757,10 @@
518757:: (a string's quoted text, an application path's knots). A node whose
519758:: kids are all leaves prints on one line; otherwise each kid goes on its
520759:: own line, indented two more spaces, and the closing parens end the
521−:: last kid's line. (module …) always breaks. Bare fields and samples
760+:: last kid's line. (module …) always breaks. Past 64 levels the indent
761+:: stops growing: a deeper line starts with 128 spaces and its depth
762+:: between bars, as `|65| (group 1:69`, so the printed tree's size is
763+:: linear in the text's however deep it nests. Bare fields and samples
522764:: print as their mold, and a cell sample as (cell …) of its samples, a
523765:: bare name there as (bind …); unnamed items print as their expr;
524766:: strings print text pieces quoted, between their interpolated exprs;
@@ -533,7 +775,7 @@
533775:: (apply 2:17 list (aura 2:23 @t)))
534776:: (face 2:27 open (flag 2:32))))
535777:: (mold 3:1 cart-action
536−:: (union 3:16
778+:: (union 4:3
537779:: (cell 4:3
538780:: (const 4:4 %add)
539781:: (face 4:9 item (aura 4:14 @t)))
@@ -621,7 +863,7 @@
621863 [%knot p=@ta] :: path segment
622864 [%aura p=@ta] :: @ud as 'ud', @ as ''
623865 [%tvar p=@t] :: M
624− [%error p=tape] :: 2.0: what broke
866+ [%error p=tape from=loc c=@] :: 2.0: what broke
625867 ==
626868::
627869:: +glyph: a token that is its text, and the layout tokens
@@ -629,29 +871,31 @@
629871+$ glyph
630872 $? %indent %dedent %newline :: layout
631873 %'(' %')' %'[' %']' :: brackets
632− %'~[' %'|=(' %'$?(' %'$-(' :: openers
874+ %'~[' %'|=(' %'$-(' :: openers
633875 %'%/' %'/' :: paths
634876 %'+' %'`' %'=' :: pair, unit, face
635− %'*' %'?' :: noun, loobean mold
636− %'++' %'+$' %'|=' %'|$' %'$?' :: runes
877+ %'*' %'?' %'_' :: noun, loobean, type hole
878+ %'++' %'+$' %'|=' %'|$' :: runes
637879 %'^-' %'~&' %'?-' %'!!' :: runes
638880 %'/-' %'/%' %'/=' :: imports
639881 ==
640882::
641883:: +lit: a literal other than a string, as Hoon's parsers read it
642884::
643−:: form is the literal rule that matched; aura and val are the dime
644−:: nuck:so gives, or for terms and loobeans:
885+:: form is the literal rule that matched; txt is the literal as
886+:: written, which the printers show, since Hoon's own printing of
887+:: some auras (@da) differs between Hoon versions; aura and val are
888+:: the dime nuck:so gives, or for terms and loobeans:
645889:: %number 1.000 0x1f 0v5.fdf99 %ud %ux %uv
646890:: %ship ~zod %p
647891:: %date ~2026.10.23 %da
648892:: %duration ~h1.m30 %dr
649893:: %knot ~.my-post %ta
650−:: %term %add %0 %& %| %tas 'add', %ud 0, %f 0, %f 1
894+:: %term %add %1.000 %& %| %$ %tas 'add', %ud 1.000, %f 0, %f 1, %tas 0
651895:: %loobean %.y %.n %f 0, %f 1
652896:: %null ~ %n 0
653897::
654−+$ lit [form=lit-form aura=@ta val=@]
898++$ lit [form=lit-form aura=@ta val=@ txt=@t]
655899+$ lit-form
656900 ?(%number %ship %date %duration %knot %term %loobean %null)
657901::
@@ -772,24 +1016,25 @@
7721016 [%const at=span =lit] :: ~ %add %.y
7731017 [%ref at=span names=(list term)] :: state item.todo
7741018 [%tvar at=span name=@t] :: M
1019+ [%hole at=span ~] :: _
7751020 [%path at=span segs=(list pseg)] :: / /todos /todo/[id=@ud]
7761021 [%apply at=span ref=(list term) args=(list shape)] :: (list @t)
7771022 [%cell at=span fields=(list field)] :: [text=@t done=?]
778− [%union at=span cases=(list shape)] :: $? below, or $?(%a %b)
1023+ [%union at=span cases=(list shape)] :: several +$ cases below
7791024 [%fn at=span sample=shape product=shape] :: $-(@t M)
780− [%generic at=span vars=(list @t) body=shape] :: |$ [M] $? …
1025+ [%generic at=span vars=(list @t) body=shape] :: +$ name |$ [M] …
7811026 ==
7821027::
783−:: +pseg: a path mold's segment, a knot or [name=aura]
1028+:: +pseg: a path mold's segment, a knot, [name=aura], or [name=_]
7841029::
785−+$ pseg $%([%knot p=@ta] [%typed at=span name=term aura=@ta])
1030++$ pseg $%([%knot p=@ta] [%typed at=span name=term aura=@ta] [%inferred at=span name=term hole-at=span])
7861031::
7871032+| %api
7881033::
7891034:: +layout: source to tokens (design: section 2)
7901035::
791−:: Never fails: an error it finds is its last token, [%error msg], at
792−:: the error's position (2.0). +lexer does the work.
1036+:: Never fails: an error it finds is its last token, [%error msg from
1037+:: c], at the error's position (2.0). +lexer does the work.
7931038::
7941039++ layout
7951040 |= [file=path src=@t]
@@ -816,22 +1061,21 @@
8161061:: +parse-tokens: tokens to tree (design: section 3)
8171062::
8181063:: It accepts no error token, so it fails at the first of its own
819−:: error and the layout pass's (2.0). The stub reports an error token
820−:: that comes first, as the parser will, and fails otherwise.
1064+:: error and the layout pass's (2.0). +parser does the work.
8211065::
8221066++ parse-tokens
8231067 |= [file=path toks=(list token)]
8241068 ^- (each module error)
825− ?: ?=([[* * [%error *]] *] toks)
826− (fail file toks "a module")
827− =/ at=loc ?~(toks [1 1] (where i.toks))
828− [%| file line.at col.at "parser not implemented"]
1069+ (~(read-module parser file toks) toks)
8291070::
8301071:: +golden: both stages printed, or the rendered error
8311072::
8321073:: tokens: the layout pass's tokens, or its error if it found one
8331074:: tree: the parser's tree, or the first error of either stage, which
834−:: the parser reports since it accepts no error token (2.0)
1075+:: the parser reports since it accepts no error token (2.0). A tree
1076+:: whose spans break section 1's rules (+check-spans) gets a last
1077+:: line saying how, "SPAN ERROR: …", so every golden case checks
1078+:: them.
8351079::
8361080++ golden
8371081 |= [file=path src=@t]
@@ -843,8 +1087,13 @@
8431087 =/ par (parse-tokens file toks)
8441088 ?: ?=(%| -.par) (show-error src p.par)
8451089 :: a parser that accepted an error token would be wrong; say so
846− ?^ bad (show-error src u.bad)
847− (show-module p.par)
1090+ ?^ bad
1091+ %^ cat 3 (show-error src u.bad)
1092+ '\0aPARSER ERROR: the parser accepted an error token'
1093+ =/ tree=@t (show-module p.par)
1094+ =/ why=(unit tape) (check-spans p.par toks)
1095+ ?~ why tree
1096+ (cat 3 tree (crip "\0aSPAN ERROR: {u.why}"))
8481097::
8491098+| %lexer
8501099::
@@ -952,10 +1201,37 @@
9521201 ::
9531202 :: +err: the error token, at column c of this line (2.0)
9541203 ::
1204+ :: It also records where the text it was reading began, from, and
1205+ :: that text's first character: the parser moves the error there
1206+ :: when the place it is in can't begin with that character (section
1207+ :: 3, Errors). Like any token, it is tight when that text follows the
1208+ :: last token with no space.
1209+ ::
9551210 ++ err
9561211 |= [c=@ud msg=tape]
9571212 ^+ cor
958− cor(out [[[[lin c] [lin c]] | [%error msg]] out])
1213+ (err-from c msg [lin col] ?~(cs 0 i.cs))
1214+ ::
1215+ :: +err-from: +err, where the text began at from with first
1216+ ::
1217+ ++ err-from
1218+ |= [c=@ud msg=tape from=loc first=@]
1219+ ^+ cor
1220+ cor(out [[[[lin c] [lin c]] =(from pend) [%error msg from first]] out])
1221+ ::
1222+ :: +err-on: +err after a token cut from the front of the text that
1223+ :: fails, as 100 from 1000 or %1 from %1.0: the parser has taken that
1224+ :: token by the time it reaches the error, so the error token's text
1225+ :: begins at the error, column c, and its first character is the one
1226+ :: there (0 past the end of the text). The parser then never moves
1227+ :: it back (2.0, 2.8).
1228+ ::
1229+ ++ err-on
1230+ |= [c=@ud msg=tape]
1231+ ^+ cor
1232+ ?: (lth c col) (err c msg)
1233+ =/ rest=tape (slag (sub c col) cs)
1234+ (err-from c msg [lin c] ?~(rest 0 i.rest))
9591235 ::
9601236 :: +put: a token from beg to end on this line, with rest the text
9611237 :: after it, which starts at end
@@ -1013,19 +1289,20 @@
10131289 ?: =('%' a) (percent b c)
10141290 ?: =('=' a)
10151291 ?: |(=('<' b) =('>' b))
1016− %+ err col
1292+ %+ err +(col)
10171293 "`={[b ~]}` is left out: names never shadow, and `.` reads imports too"
10181294 ?: =('=' b)
1019− (err col "the closer `==` is left out: indentation covers it")
1295+ (err +(col) "the closer `==` is left out: indentation covers it")
10201296 (emit 1 %'=')
10211297 ?: =('`' a) (emit 1 %'`')
10221298 ?: =('*' a) (emit 1 %'*')
1299+ ?: =('_' a) (emit 1 %'_')
10231300 ?: =('~' a)
10241301 ?: =('[' b) (emit 2 %'~[')
10251302 ?: =('&' b) (emit 2 %'~&')
10261303 ?: =('|' b) (err +(col) "`~|` is left out: `~&` covers debugging")
10271304 =/ n=@ud (run-len t.cs knot-mask)
1028− ?: =(0 n) (emit 1 [%lit %null %n 0])
1305+ ?: =(0 n) (emit 1 [%lit %null %n 0 '~'])
10291306 (literal +(n))
10301307 ?: =('/' a)
10311308 ?: &(=(1 col) |(=('-' b) =('%' b) =('=' b)))
@@ -1046,23 +1323,25 @@
10461323 ?: =('-' b) (err +(col) "`|-` is left out: gates recurse by name")
10471324 (err +(col) "`|` begins `|=`, `|=(` or `|$`")
10481325 ?: =('$' a)
1049− ?: &(=('?' b) =('(' c)) (emit 3 %'$?(')
1050− ?: =('?' b) (emit 2 %'$?')
1326+ ?: =('?' b)
1327+ (err +(col) "`$?` is left out: a union is a `+$` with its cases below")
10511328 ?: &(=('-' b) =('(' c)) (emit 3 %'$-(')
10521329 ?: =('-' b)
10531330 (err (add 2 col) "`$-` has only the wide form `$-(sample product)`")
1054− ?: =('(' b) (err col "`$(…)` is left out: gates recurse by name")
1055− ?: =('%' b) (err +(col) "`$%` is left out: `$?` covers unions")
1056− (err +(col) "`$` begins `$?`, `$?(` or `$-(`")
1331+ ?: =('(' b) (err +(col) "`$(…)` is left out: gates recurse by name")
1332+ ?: =('%' b) (err +(col) "`$%` is left out: a union is a `+$` with its cases below")
1333+ (err +(col) "`$` begins `$-(`")
10571334 ?: =('^' a)
10581335 ?: =('-' b) (emit 2 %'^-')
10591336 (err +(col) "`^` begins `^-`")
10601337 ?: =('?' a)
10611338 ?: =('-' b) (emit 2 %'?-')
1062− ?: =('+' b) (err +(col) "`?+` is left out: `?-` is the branch")
10631339 ?: &(=(':' b) !=(':' c))
10641340 (err +(col) "`?:` is left out: `?-` is the branch")
10651341 ?: =('!' b) (err +(col) "`?!` is left out: eq and not are gates")
1342+ :: Hoon's other ? runes; nothing in Jibb goes tight after a ? mold
1343+ ?: (in b wut-mask)
1344+ (err +(col) "`?{[b ~]}` is left out: `?-` is the branch")
10661345 (emit 1 %'?')
10671346 ?: =('!' a)
10681347 ?: =('!' b) (emit 2 %'!!')
@@ -1088,6 +1367,9 @@
10881367 (err +(col) "`:~` is left out: indentation covers it; write ~[…]")
10891368 ?: =('*' b)
10901369 (err +(col) "`:*` is left out: indentation covers it; write […]")
1370+ ?: |(=('-' b) =('+' b) =('^' b) =('_' b))
1371+ %+ err +(col)
1372+ "`:{[b ~]}` is left out: indentation covers it; write a cell as [a b]"
10911373 ?: &(=(pend [lin col]) ?=([[* * ?([%name *] [%wing *])] *] out))
10921374 %+ err +(col)
10931375 %+ weld "`a:b` is left out: names never shadow, "
@@ -1104,6 +1386,8 @@
11041386 (err col "the closer `--` is left out: indentation covers it")
11051387 (err col (unexpected a))
11061388 ?: =(';' a)
1389+ ?: =(':' b)
1390+ (err col "`;:` is left out: nest the calls, as (add a (add b c))")
11071391 (err col "Sail's `;` runes are left out: layout is Jibb's elements")
11081392 ?: =('\'' a) (err col "there is no '…' form: strings are \"…\"")
11091393 ?: =('{' a)
@@ -1136,29 +1420,58 @@
11361420 ^+ cor
11371421 ?: =('/' b) segment:(emit 2 %'%/')
11381422 ?: =('.' b)
1139− ?: =('y' c) (emit 3 [%lit %loobean %f 0])
1140− ?: =('n' c) (emit 3 [%lit %loobean %f 1])
1423+ ?: =('y' c) (emit 3 [%lit %loobean %f 0 '%.y'])
1424+ ?: =('n' c) (emit 3 [%lit %loobean %f 1 '%.n'])
11411425 (err (add 2 col) "the loobeans are `%.y` and `%.n`")
1142− ?: =('&' b) (emit 2 [%lit %term %f 0])
1143− ?: =('|' b) (emit 2 [%lit %term %f 1])
1144− ?: =(':' b) (err +(col) "`%:` is left out: indentation covers it")
1426+ ?: =('&' b) (emit 2 [%lit %term %f 0 '%&'])
1427+ ?: =('|' b) (emit 2 [%lit %term %f 1 '%|'])
1428+ ?: =('$' b) (emit 2 [%lit %term %tas 0 '%$'])
1429+ ?: |(=(':' b) =('-' b) =('+' b) =('^' b) =('~' b))
1430+ %+ err +(col)
1431+ "`%{[b ~]}` is left out: indentation covers it; a call is (f a b)"
11451432 ?: =('=' b)
11461433 %+ err +(col)
11471434 "`%=` is left out: indentation covers it; write a change, as m(a=b)"
11481435 =/ rest=tape ?~(cs ~ t.cs)
11491436 ?: (is-lower b)
11501437 =/ n=@ud (run-len rest name-mask)
1151− => (emit +(n) [%lit %term %tas (crip (scag n rest))])
1438+ =/ nam=tape (scag n rest)
1439+ => (emit +(n) [%lit %term %tas (crip nam) (crip ['%' nam])])
11521440 ?. &(?=(^ cs) |((is-upper i.cs) =('_' i.cs))) cor
11531441 (err col "names are lowercase letters, digits and -")
1154− ?: (is-digit b)
1155− =/ n=@ud (run-len rest digit-mask)
1156− => (emit +(n) [%lit %term %ud (decimal (scag n rest))])
1157− ?. &(?=(^ cs) (in i.cs term-tail-mask)) cor
1158− %+ err col
1159− "unexpected `{[i.cs ~]}`: a numeric term is `%` and digits only, as %1000"
1442+ ?: (is-digit b) (numeric-term (scag (run-len rest number-mask) rest))
11601443 (err +(col) "`%` begins a term, a loobean or `%/`")
11611444 ::
1445+ :: +numeric-term: % and a decimal, whose run, the characters a number
1446+ :: literal's run takes, is run (2.6)
1447+ ::
1448+ :: The decimal is a number literal's (2.8): nuck:so reads the run,
1449+ :: and the error, if any, is where it stopped looking, one column on
1450+ :: for the %, so %1000 fails at its fourth digit as 1000 does. %0
1451+ :: alone is a term and no decimal goes on from its 0, so anything
1452+ :: after the 0 fails at once, as the x of %0x1f. Whatever was read
1453+ :: is a term token before the error token, as a number literal's is,
1454+ :: and the error token begins at the error (+err-on), so a place
1455+ :: that takes the term keeps the error there: `+$ x %1.0` fails at
1456+ :: 1:10, as `++ x %1.0` does.
1457+ ::
1458+ ++ numeric-term
1459+ |= run=tape
1460+ ^+ cor
1461+ =/ n=@ud (lent run)
1462+ =/ red=[used=@ud val=@ud at=@ud]
1463+ ?: =('0' ?~(run 0 i.run)) [1 0 (add 2 col)]
1464+ =/ ed=(like coin) (nuck:so [[lin +(col)] run])
1465+ ?~ q.ed [0 0 q.p.ed]
1466+ =/ con=coin p.u.q.ed
1467+ ?. ?=([%$ %ud @] con) [0 0 q.p.ed]
1468+ [(sub n (lent q.q.u.q.ed)) q.p.con q.p.ed]
1469+ =/ lex=lexeme
1470+ [%lit %term %ud val.red (crip ['%' (scag used.red run)])]
1471+ ?: =(used.red n) (emit +(n) lex)
1472+ ?: =(0 used.red) (err-from at.red term-msg [lin col] '%')
1473+ (err-on:(emit +(used.red) lex) at.red term-msg)
1474+ ::
11621475 :: +name: a name, or a wing, names joined by dots (2.6)
11631476 ::
11641477 ++ name
@@ -1207,9 +1520,20 @@
12071520 =/ run=tape (scag n cs)
12081521 =/ a=@ ?~(run 0 i.run)
12091522 =/ b=@ ?~(run 0 ?~(t.run 0 i.t.run))
1210− :: 0b 0c 0i 0w begin auras Jibb doesn't write, whatever follows
1523+ :: 0b 0c 0i 0w, ~- and ~~ begin auras Jibb doesn't write, whatever
1524+ :: follows; Hoon's reader of ~- (@c) crashes on a control character
12111525 ?: &(=('0' a) |(=('b' b) =('c' b) =('i' b) =('w' b)))
12121526 (err +(col) "Jibb writes no @u{[b ~]} literals")
1527+ ?: &(=('~' a) =('-' b)) (err +(col) "Jibb writes no @c literals")
1528+ ?: &(=('~' a) =('~' b))
1529+ (err +(col) "Jibb writes no @t literals; strings are \"…\"")
1530+ :: ~0 and a base-32 digit begin a blob, which Hoon's reader cues, and
1531+ :: cue can run out of memory, which nothing catches; no Jibb literal
1532+ :: goes on so (a date's year has no leading 0)
1533+ =/ c=@ ?~(run 0 ?~(t.run 0 ?~(t.t.run 0 i.t.t.run)))
1534+ ?: &(=('~' a) =('0' b) (in c b32-mask))
1535+ ?: (is-digit c) (err (add 2 col) (literal-msg run %da))
1536+ (err (add 2 col) "Jibb writes no blob literals")
12131537 :: a year BC that Hoon's dates can't hold, which its date code
12141538 :: crashes on: an error at the - that makes it BC
12151539 =/ bc=(unit [at=@ud y=@ud]) (year-bc col run)
@@ -1217,7 +1541,18 @@
12171541 (err at.u.bc "there is no year 0 BC: 1 BC is ~1-, as ~1-.1.1")
12181542 ?: &(?=(^ bc) (gth y.u.bc 292.277.024.401))
12191543 (err at.u.bc "Hoon's dates begin in 292.277.024.401 BC")
1220− =/ ed (nuck:so [[lin col] run])
1544+ :: a fifth sub-second group, which Hoon's +yule crashes on
1545+ =/ five=(unit @ud) (fifth-group run)
1546+ ?^ five
1547+ %+ err (add col u.five)
1548+ "a date or duration takes at most four sub-second groups"
1549+ :: Hoon's date code reads dates and durations, and has crashed on
1550+ :: forms the checks above now stop; it runs under mule, in case
1551+ =/ try=(each (like coin) tang)
1552+ ?. (is-time run) [%& (nuck:so [[lin col] run])]
1553+ (mule |.((nuck:so [[lin col] run])))
1554+ ?: ?=(%| -.try) (err col "Jibb can't read this literal")
1555+ =/ ed=(like coin) p.try
12211556 ?~ q.ed (err q.p.ed (literal-msg run %$))
12221557 =/ used=@ud (sub n (lent q.q.u.q.ed))
12231558 =/ con=coin p.u.q.ed
@@ -1228,7 +1563,7 @@
12281563 %+ err +(col)
12291564 %+ weld "Jibb writes no @{(trip p.p.con)} literals"
12301565 ?:(=(%t p.p.con) "; strings are \"…\"" "")
1231− =/ lex=lexeme [%lit u.form p.p.con q.p.con]
1566+ =/ lex=lexeme [%lit u.form p.p.con q.p.con (crip (scag used run))]
12321567 ?: =(used n)
12331568 ?. =(%ta p.p.con) (emit n lex)
12341569 :: a ~. knot is followed as a path segment is (2.7)
@@ -1245,7 +1580,9 @@
12451580 =? at &(=('~' a) (is-lower b) ?=(?(%n %p) p.p.con))
12461581 =/ dur=@ud ?:(|(=('d' b) =('h' b) =('m' b) =('s' b)) 2 1)
12471582 (min at (add col (max dur (ship-stop run))))
1248− (err:(emit used lex) at (literal-msg run p.p.con))
1583+ :: the run's first part is a token, which the parser takes before
1584+ :: it reaches the error, so the error token begins at the error
1585+ (err-on:(emit used lex) at (literal-msg run p.p.con))
12491586 ::
12501587 :: +text: a string's text, from its opening " or the } that closes
12511588 :: an interpolation, through the " or { that ends it (2.9). mid: it
@@ -1306,6 +1643,9 @@
13061643 ~
13071644::
13081645++ non-ascii "non-ASCII text outside a string or comment"
1646+++ term-msg
1647+ %+ weld "a numeric term is `%` and a decimal, "
1648+ "digits in groups of three joined by dots, as %1.000"
13091649++ bad-escape "a `\\` begins `\\\\`, `\\\"`, `\\\{` or two hex digits"
13101650++ bad-hex "a `\\` escape takes two lowercase hex digits, as `\\0a`"
13111651::
@@ -1324,8 +1664,32 @@
13241664:: after a path segment (2.7): printable, but not a knot character,
13251665:: / ( [ ) ] } or :
13261666++ seg-bad-mask 0x1800.0001.57ff.ffff.f800.1cfe.0000.0000
1327−:: after a numeric term: a-z A-Z _ - .
1328−++ term-tail-mask 0x7ff.fffe.87ff.fffe.0000.6000.0000.0000
1667+:: after a ? glyph, Hoon's ? runes but ?- ?: and ?! (2.6): + ~ = . @ ^ & | < >
1668+++ wut-mask 0x5000.0000.4000.0001.7000.4840.0000.0000
1669+:: base-32 digits: 0-9 a-v
1670+++ b32-mask 0x7f.fffe.0000.0000.03ff.0000.0000.0000
1671+::
1672+:: What may begin each place the parser reads (section 3, Errors):
1673+:: an expression a-z 0-9 " ( [ ~ % / ` | ^ ? !
1674+:: an operand a-z 0-9 " ( [ ~ % / ` | !
1675+:: a mold a-z A-Z @ * ! ? ~ % / ( [ $ _
1676+:: a pattern a-z 0-9 " ~ % * [
1677+:: and what may go tight after an operand: . ( + = after a name, a
1678+:: closer ) ] }, or the : of a comment
1679+::
1680+++ expr-mask 0x57ff.ffff.4800.0000.83ff.8126.0000.0000
1681+++ operand-mask 0x57ff.ffff.0800.0000.03ff.8126.0000.0000
1682+++ mold-mask 0x47ff.fffe.8fff.ffff.8000.8532.0000.0000
1683+++ bar-mask 0x1000.0000.0000.0000.0000.0000.0000.0000
1684+++ pattern-mask 0x47ff.fffe.0800.0000.03ff.0424.0000.0000
1685+++ after-mask 0x2000.0000.2000.0000.2400.4b00.0000.0000
1686+++ plus-mask 0x800.0000.0000 :: +
1687+++ cen-mask 0x20.0000.0000 :: %
1688+++ fas-mask 0x8000.0000.0000 :: /
1689+++ tis-mask 0x2000.0000.0000.0000 :: =
1690+++ pat-mask 0x1.0000.0000.0000.0000 :: @
1691+++ sel-mask 0x800.0000.0000.0000.0000.0000 :: [
1692+++ ser-mask 0x2000.0000.0000.0000.0000.0000 :: ]
13291693::
13301694:: +cont-mask: UTF-8 continuation bytes, 10xx.xxxx, which start no
13311695:: column (1)
@@ -1427,6 +1791,62 @@
14271791 ?. ?=([%'-' *] rest) ~
14281792 `[(add col +((lent ds))) (decimal ds)]
14291793::
1794+:: +fifth-group: where in a ~ literal's run, counting from its ~, the
1795+:: dot that begins a fifth sub-second group is, if the first four are
1796+:: well formed
1797+::
1798+:: Sub-seconds follow a duration's first .. or a date's second, as in
1799+:: ~s1..0000 and ~2026.10.23..14.30.00..0000: groups of four
1800+:: lowercase hex digits joined by dots. Hoon's reader takes any
1801+:: number, and its +yule crashes on a fifth (2.8).
1802+::
1803+++ fifth-group
1804+ |= run=tape
1805+ ^- (unit @ud)
1806+ =/ b=@ ?.(?=([%'~' @ *] run) 0 i.t.run)
1807+ =/ k=@ud
1808+ ?: (is-digit b) 2
1809+ ?:(|(=('d' b) =('h' b) =('m' b) =('s' b)) 1 0)
1810+ ?: =(0 k) ~
1811+ =/ past=(unit [i=@ud cs=tape]) (past-dots k 0 run)
1812+ ?~ past ~
1813+ =/ i=@ud i.u.past
1814+ =/ cs=tape cs.u.past
1815+ =/ g=@ud 1
1816+ |- ^- (unit @ud)
1817+ =/ quad=tape (scag 4 cs)
1818+ ?. &(=(4 (lent quad)) (levy quad is-hex)) ~
1819+ =. cs (slag 4 cs)
1820+ =. i (add 4 i)
1821+ ?. ?=([%'.' *] cs) ~
1822+ ?: =(4 g) `i
1823+ $(g +(g), i +(i), cs t.cs)
1824+::
1825+:: +past-dots: where the text past the k-th .. of cs starts, counting
1826+:: from i, and that text
1827+::
1828+++ past-dots
1829+ |= [k=@ud i=@ud cs=tape]
1830+ ^- (unit [i=@ud cs=tape])
1831+ ?~ cs ~
1832+ ?. &(=('.' i.cs) ?=(^ t.cs) =('.' i.t.cs))
1833+ $(i +(i), cs t.cs)
1834+ ?: =(1 k) `[(add 2 i) t.t.cs]
1835+ $(k (dec k), i (add 2 i), cs t.t.cs)
1836+::
1837+:: +is-time: whether a ~ literal's run starts as a date or a duration
1838+:: does, which Hoon's date code reads (2.8)
1839+::
1840+++ is-time
1841+ |= run=tape
1842+ ^- ?
1843+ ?. ?=([%'~' @ *] run) |
1844+ ?: (is-digit i.t.run) &
1845+ ?& |(=('d' i.t.run) =('h' i.t.run) =('m' i.t.run) =('s' i.t.run))
1846+ ?=([@ @ @ *] run)
1847+ (is-digit i.t.t.run)
1848+ ==
1849+::
14301850:: +ship-stop: how many characters of a ~ literal's run, from its ~,
14311851:: could still begin a ship (2.8)
14321852::
@@ -1544,11 +1964,8 @@
15441964 ^- @t
15451965 =/ kids=(list sexp)
15461966 (weld (turn imports.mod sexp-import) (turn defs.mod sexp-def))
1547− =/ lines=wall
1548− ?~ kids ~["(module)"]
1549− :- "(module"
1550− (close (zing (turn kids |=(k=sexp (render 2 k)))))
1551− (of-wain:format (turn lines crip))
1967+ ?~ kids '(module)'
1968+ (of-wain:format (render kids))
15521969::
15531970:: +show-error: "<file>:<line>:<col>: <message>", the line, a caret
15541971::
@@ -1595,6 +2012,7 @@
15952012 %indent "a deeper line"
15962013 %dedent "a shallower line"
15972014 %newline "a line at the same depth"
2015+ %'`' "`` ` ``"
15982016 ==
15992017 ?- -.x
16002018 %name "`{(trip p.x)}`"
@@ -1643,24 +2061,17 @@
16432061 ?~ t.ns (trip i.ns)
16442062 "{(trip i.ns)}.{$(ns t.ns)}"
16452063::
1646−:: +show-lit: a literal as Hoon prints it
2064+:: +show-lit: a literal as written for atoms read by nuck:so, whose
2065+:: printing differs between Hoon versions (@da), and for terms, whose
2066+:: one form is as written (%1.000); loobeans and ~ in their one form
16472067::
16482068++ show-lit
16492069 |= l=lit
16502070 ^- tape
16512071 ?- form.l
1652− %number (scow aura.l val.l)
1653− %ship (scow %p val.l)
1654− %date (scow %da val.l)
1655− %duration (scow %dr val.l)
1656− %knot (scow %ta val.l)
2072+ ?(%number %ship %date %duration %knot %term) (trip txt.l)
16572073 %loobean ?:(=(0 val.l) "%.y" "%.n")
16582074 %null "~"
1659− %term
1660− ?+ aura.l (weld "%" (trip val.l))
1661− %ud (weld "%" (a-co:co val.l))
1662− %f ?:(=(0 val.l) "%&" "%|")
1663− ==
16642075 ==
16652076::
16662077:: +show-quoted: text as a Jibb string, with \\ \" \{ and \XX escapes
@@ -1698,6 +2109,7 @@
16982109 ?- -.s
16992110 %knot (weld "/" (trip p.s))
17002111 %typed "/[{(trip name.s)}=@{(trip aura.s)}]"
2112+ %inferred "/[{(trip name.s)}=_]"
17012113 ==
17022114::
17032115++ show-tvars
@@ -1715,20 +2127,60 @@
17152127 [%node head=tape kids=(list sexp)]
17162128 ==
17172129::
1718−:: +render: a node as lines, at an indent
2130+:: +render: a module's kids as the tree's lines (4.2)
17192131::
1720−:: On one line when every kid is a leaf: an atom, or a node whose kids
1721−:: are all atoms (a string's text, a path's knots). Else each kid on
1722−:: its own lines, two spaces deeper.
2132+:: A node whose kids are all leaves goes on one line; else its head,
2133+:: then each kid a level deeper, and its ) at the end of its last
2134+:: kid's last line; (module …) always breaks. Each line is built once,
2135+:: from its depth: a line deeper than 64 levels keeps 64 levels'
2136+:: indent and says its depth, as |65| (group 3:1 …), so printing is
2137+:: linear in the tree's size however deep it nests. Each line becomes
2138+:: a cord as soon as it is built: as a tape, a character takes some
2139+:: 24 bytes, and holding the lines of a tree 100.000 levels deep made
2140+:: +golden half again as slow.
17232141::
17242142++ render
1725− |= [ind=@ud s=sexp]
1726− ^- wall
1727− =/ pad=tape (reap ind ' ')
1728− ?: ?=(%atom -.s) ~[(weld pad p.s)]
1729− ?: (levy kids.s is-leaf) ~[(weld pad (flat s))]
1730− :- "{pad}({head.s}"
1731− (close (zing (turn kids.s |=(k=sexp (render (add ind 2) k)))))
2143+ |= kids=(list sexp)
2144+ ^- wain
2145+ =/ acc=(list pline) ~[[0 "(module" 0]]
2146+ =. acc
2147+ |- ^- (list pline)
2148+ ?~ kids acc
2149+ $(kids t.kids, acc (put-sexp 1 i.kids acc))
2150+ (flop (turn (shut-last acc) |=(l=pline (crip (show-pline l)))))
2151+::
2152+:: +pline: a printed line: its depth, its text, and how many )s end it
2153+::
2154++$ pline [dep=@ud txt=tape shut=@ud]
2155+::
2156+:: +put-sexp: a node's lines at depth dep, last first, onto acc
2157+::
2158+++ put-sexp
2159+ |= [dep=@ud s=sexp acc=(list pline)]
2160+ ^- (list pline)
2161+ ?: ?=(%atom -.s) [[dep p.s 0] acc]
2162+ ?: (levy kids.s is-leaf) [[dep (flat s) 0] acc]
2163+ =/ ks=(list sexp) kids.s
2164+ =. acc [[dep "({head.s}" 0] acc]
2165+ |- ^- (list pline)
2166+ ?~ ks (shut-last acc)
2167+ $(ks t.ks, acc (put-sexp +(dep) i.ks acc))
2168+::
2169+:: +shut-last: one more ) at the end of the last line
2170+::
2171+++ shut-last
2172+ |= acc=(list pline)
2173+ ^- (list pline)
2174+ ?~ acc ~
2175+ [i.acc(shut +(shut.i.acc)) t.acc]
2176+::
2177+++ show-pline
2178+ |= l=pline
2179+ ^- tape
2180+ =/ pad=tape
2181+ ?: (lte dep.l 64) (reap (mul 2 dep.l) ' ')
2182+ "{(reap 128 ' ')}|{(a-co:co dep.l)}| "
2183+ :(weld pad txt.l (reap shut.l ')'))
17322184::
17332185++ is-leaf
17342186 |= s=sexp
@@ -1742,15 +2194,6 @@
17422194 ?: ?=(%atom -.s) p.s
17432195 "({head.s}{(zing (turn kids.s |=(k=sexp (weld " " (flat k)))))})"
17442196::
1745−:: +close: end the last line with )
1746−::
1747−++ close
1748− |= w=wall
1749− ^- wall
1750− ?~ w ~
1751− ?~ t.w ~[(weld i.w ")")]
1752− [i.w $(w t.w)]
1753−::
17542197:: +nod: a node's sexp: "kind line:col extra" and its kids
17552198::
17562199++ nod
@@ -1878,6 +2321,7 @@
18782321 %const (nod "const" at.s (show-lit lit.s) ~)
18792322 %ref (nod "ref" at.s (show-names names.s) ~)
18802323 %tvar (nod "tvar" at.s (trip name.s) ~)
2324+ %hole (nod "hole" at.s "" ~)
18812325 %path (nod "path" at.s (show-psegs segs.s) ~)
18822326 %apply (nod "apply" at.s (show-names ref.s) (turn args.s sexp-shape))
18832327 %cell (nod "cell" at.s "" (turn fields.s sexp-field))
@@ -1916,35 +2360,11596 @@
19162360::
19172361:: +fail: the error "expected <want>, found <the next token>"
19182362::
1919−:: At an error token, the layout pass's error instead (2.0). The token
1920−:: list always ends with NEWLINE or an error token (2.5), and the
1921−:: parser stops at either, so it never runs out; if it did, the error
1922−:: would sit at 1:1.
2363+:: At the layout pass's error instead (+lexer-error). The token list
2364+:: always ends with NEWLINE or an error token (2.5), and the parser
2365+:: stops at either, so it never runs out; if it did, the error would
2366+:: sit at 1:1.
19232367::
19242368++ fail
19252369 |= [file=path toks=(list token) want=tape]
19262370 ^- [%| p=error]
19272371 ?~ toks [%| file 1 1 "expected {want}, found the end of the tokens"]
1928− ?: ?=([%error *] lex.i.toks)
1929− [%| file line.beg.at.i.toks col.beg.at.i.toks p.lex.i.toks]
2372+ =/ lex=(unit error) (lexer-error file toks)
2373+ ?^ lex [%| u.lex]
19302374 =/ l=loc (where i.toks)
19312375 [%| file line.l col.l "expected {want}, found {(show-found i.toks)}"]
19322376::
1933−:: +fail-space: a tight form found a space before its next token
2377+:: +lexer-error: the layout pass's error, where the parser fails at it
2378+::
2379+:: At an error token, its error. At layout tokens followed by an error
2380+:: token whose text begins the line, both errors point at the line's
2381+:: start (+where), and the layout pass's message, about that text,
2382+:: says more: a line `==` closing a ?- is "the closer `==` is left
2383+:: out", not "expected the end of the body".
2384+::
2385+++ lexer-error
2386+ |= [file=path toks=(list token)]
2387+ ^- (unit error)
2388+ ?~ toks ~
2389+ ?: ?=([%error *] lex.i.toks)
2390+ `[file line.beg.at.i.toks col.beg.at.i.toks p.lex.i.toks]
2391+ ?. (is-layout i.toks) ~
2392+ =/ l=loc (where i.toks)
2393+ =/ rest=(list token) t.toks
2394+ |- ^- (unit error)
2395+ ?~ rest ~
2396+ ?: (is-layout i.rest) $(rest t.rest)
2397+ ?. ?=([%error *] lex.i.rest) ~
2398+ ?. =(l from.lex.i.rest) ~
2399+ `[file line.l col.l p.lex.i.rest]
2400+::
2401+:: +fail-in: +fail where the next token begins a place, such as an
2402+:: expression or a mold, whose first character is one of the mask can
2403+::
2404+:: The error points at the first character where the text stops being
2405+:: the start of any valid module (2.0), so at a token the place can't
2406+:: take, just past the part of it the place could: none if the place
2407+:: can't begin with its first character; a wing's first name, as in
2408+:: `++ a.b`, where a name goes; else that first character, as the ~ of
2409+:: ~zod where a mold goes (~ alone is one). At an error token whose
2410+:: text begins with a character the place can't, the error moves to
2411+:: that character, with the layout pass's message: `++ x @sd` fails
2412+:: at the @, since no expression begins with @, while `+$ x @sd`
2413+:: fails at the s. Every place that reaches this at a layout token
2414+:: needs text on its line, so the error is at the line's end
2415+:: (+fail-line): `++ x ^-` above a deeper line fails at 1:8.
2416+::
2417+++ fail-in
2418+ |= [file=path toks=(list token) want=tape can=@]
2419+ ^- [%| p=error]
2420+ ?~ toks (fail file toks want)
2421+ =* t i.toks
2422+ ?: ?=([%error *] lex.t)
2423+ :: a : could begin a comment anywhere, which this leaves out
2424+ ?: |(=(':' c.lex.t) (in c.lex.t can)) (fail file toks want)
2425+ [%| (moved file want t)]
2426+ ?: (is-layout t) (fail-line file toks want "")
2427+ =/ n=@ud (prefix t can)
2428+ =/ e=[%| p=error] (fail file toks want)
2429+ e(col.p (add n col.p.e))
2430+::
2431+:: +prefix: how many of the first characters of a token that a place
2432+:: can't take could still begin it, the place beginning with a
2433+:: character of the mask can (+fail-in)
2434+::
2435+++ prefix
2436+ |= [t=token can=@]
2437+ ^- @ud
2438+ ?. (in (first-char t) can) 0
2439+ ?. ?=([%wing *] lex.t) 1
2440+ ?~(p.lex.t 1 (met 3 i.p.lex.t))
2441+::
2442+:: +first-char: a token's first character, or one like it: a number
2443+:: begins with a digit, ~zod with ~ and %add with %
2444+::
2445+++ first-char
2446+ |= t=token
2447+ ^- @
2448+ =/ x=lexeme lex.t
2449+ ?@ x ?:(?=(?(%indent %dedent %newline) x) 0 (end 3 x))
2450+ ?- -.x
2451+ %name (end 3 p.x)
2452+ %wing ?~(p.x 0 (end 3 i.p.x))
2453+ %str '"'
2454+ %str-head '"'
2455+ %str-mid '}'
2456+ %str-tail '}'
2457+ %knot (end 3 p.x)
2458+ %aura '@'
2459+ %tvar (end 3 p.x)
2460+ %error c.x
2461+ ::
2462+ %lit
2463+ ?- form.p.x
2464+ %number '0'
2465+ ?(%term %loobean) '%'
2466+ ?(%ship %date %duration %knot %null) '~'
2467+ ==
2468+ ==
2469+::
2470+:: +fail-space: a tight form found no next token right after prev
19342471::
1935−:: The error sits where the space starts, just past prev, the token
1936−:: that needs its next one at once (section 3, Errors). If the next
1937−:: token is a layout or error token, it is +fail's error instead.
2472+:: The error sits just past prev, the token that needs its next one
2473+:: at once, where the space or the end of the line starts (section 3,
2474+:: Errors): no deeper line can supply a tight form's next token. So
2475+:: does an error token past a space or on a later line, whose error
2476+:: comes after. A tight error token's text begins right after prev,
2477+:: and its error is +fail's. why is a hint, if not empty.
19382478::
19392479++ fail-space
1940− |= [file=path prev=token toks=(list token) want=tape]
2480+ |= [file=path prev=token toks=(list token) want=tape why=tape]
19412481 ^- [%| p=error]
1942− ?: ?| ?=(~ toks)
1943− ?=(?(%indent %dedent %newline) lex.i.toks)
1944− ?=([%error *] lex.i.toks)
2482+ =/ at=loc end.at.prev
2483+ ?: &(?=(^ toks) ?=([%error *] lex.i.toks) =(at from.lex.i.toks))
2484+ (fail file toks want)
2485+ =/ found=tape
2486+ ?~ toks "the end of the file"
2487+ =* t i.toks
2488+ ?: (is-layout t)
2489+ ?:(=(beg.at.t end.at.t) "the end of the file" "the end of the line")
2490+ ?: &(?=([%error *] lex.t) !=(line.at line.from.lex.t))
2491+ "the end of the line"
2492+ "a space"
2493+ =/ msg=tape
2494+ "expected {want} right after {(show-found prev)}, found {found}"
2495+ [%| file line.at col.at ?~(why msg "{msg}; {why}")]
2496+::
2497+:: +fail-line: +fail where the place needs text on the line that toks
2498+:: ends, as a rune's mold or what a bracket that closes on its line
2499+:: still needs: at a layout token, at the end of that line, just past
2500+:: its last token, where the token's span starts, "found the end of the
2501+:: line", since no later line can supply it (2.0, section 3, Errors).
2502+:: At the end of the file that is where +fail puts it. why is a hint,
2503+:: if not empty, given only at the end of a line.
2504+::
2505+++ fail-line
2506+ |= [file=path toks=(list token) want=tape why=tape]
2507+ ^- [%| p=error]
2508+ ?. ?& ?=(^ toks)
2509+ (is-layout i.toks)
2510+ !=(beg.at.i.toks end.at.i.toks)
19452511 ==
19462512 (fail file toks want)
1947− :+ %| file
1948− :+ line.end.at.prev col.end.at.prev
1949− "expected {want} right after {(show-found prev)}, found a space"
2513+ =/ at=loc beg.at.i.toks
2514+ =/ msg=tape "expected {want}, found the end of the line"
2515+ [%| file line.at col.at ?~(why msg "{msg}; {why}")]
2516+::
2517+:: +fail-why: +fail with a hint after its message, "; <why>"
2518+::
2519+:: The layout pass's error (+lexer-error) stays as it is (2.0).
2520+::
2521+++ fail-why
2522+ |= [file=path toks=(list token) want=tape why=tape]
2523+ ^- [%| p=error]
2524+ =/ e=[%| p=error] (fail file toks want)
2525+ ?^ (lexer-error file toks) e
2526+ e(msg.p (weld msg.p.e "; {why}"))
2527+::
2528+:: +fail-in-why: +fail-in with a hint, as +fail-why
2529+::
2530+++ fail-in-why
2531+ |= [file=path toks=(list token) want=tape can=@ why=tape]
2532+ ^- [%| p=error]
2533+ =/ e=[%| p=error] (fail-in file toks want can)
2534+ ?: &(?=(^ toks) ?=([%error *] lex.i.toks)) e
2535+ ?^ (lexer-error file toks) e
2536+ e(msg.p (weld msg.p.e "; {why}"))
2537+::
2538+:: +tight-error: the error at an error token tight after an operand or
2539+:: an item, if its text's first character can't go there: the layout
2540+:: pass's message, at that character (+fail-in)
2541+::
2542+:: What may go tight after an item is a closer, a comment's :, or,
2543+:: after a name, the ( . + or = of a change, a wing, a pair or a face
2544+:: (after-mask, which doesn't look at what the item was).
2545+::
2546+++ tight-error
2547+ |= [file=path toks=(list token)]
2548+ ^- (unit error)
2549+ (tight-error-in file toks after-mask)
2550+::
2551+:: +tight-error-in: +tight-error where what may go tight is can, as no
2552+:: = goes tight after a call's operand, which takes no face
2553+::
2554+++ tight-error-in
2555+ |= [file=path toks=(list token) can=@]
2556+ ^- (unit error)
2557+ ?. ?=([[* %& [%error *]] *] toks) ~
2558+ ?: (in c.lex.i.toks can) ~
2559+ `(moved file "a space between items" i.toks)
2560+::
2561+:: +moved: an error token's error, moved to the first character of the
2562+:: text it was reading, which can't go where it is (+fail-in): "expected
2563+:: <want>, found <that character>; <the layout pass's message>"
2564+::
2565+++ moved
2566+ |= [file=path want=tape t=token]
2567+ ^- error
2568+ ?. ?=([%error *] lex.t) [file line.beg.at.t col.beg.at.t "expected {want}"]
2569+ =* x lex.t
2570+ ?: =(from.x beg.at.t) [file line.from.x col.from.x p.x]
2571+ =/ what=tape ?:(=('"' c.x) "a string" "`{[c.x ~]}`")
2572+ [file line.from.x col.from.x "expected {want}, found {what}; {p.x}"]
2573+::
2574+:: Token tests for the parser
2575+::
2576+:: +is-layout: INDENT, DEDENT or NEWLINE
2577+::
2578+++ is-layout
2579+ |= t=token
2580+ ^- ?
2581+ ?=(?(%indent %dedent %newline) lex.t)
2582+::
2583+:: +is-closer: ) or ], or the } that ends an interpolation
2584+::
2585+++ is-closer
2586+ |= t=token
2587+ ^- ?
2588+ ?| =(%')' lex.t)
2589+ =(%']' lex.t)
2590+ ?=([?(%str-mid %str-tail) *] lex.t)
2591+ ==
2592+::
2593+:: +ends-call: a token that ends a call, or the operands on a group's
2594+:: first line, without an error of their own: a layout token, a
2595+:: closer, or the layout pass's error
2596+::
2597+++ ends-call
2598+ |= t=token
2599+ ^- ?
2600+ ?| (is-layout t)
2601+ (is-closer t)
2602+ ?=([%error *] lex.t)
2603+ ==
2604+::
2605+:: +tail-can: what may begin text that goes on, on its line, after an
2606+:: expression: more operands, as after a call or !!, or after a rune
2607+:: what may go on after its last part (+bad-end-in)
2608+::
2609+++ tail-can
2610+ |= e=expr
2611+ ^- @
2612+ ?+ -.e operand-mask
2613+ %cast $(e val.e)
2614+ %gate $(e body.e)
2615+ ==
2616+::
2617+:: +def-can: +tail-can after a definition: nothing after a mold
2618+::
2619+++ def-can
2620+ |= d=def
2621+ ^- @
2622+ ?- -.d
2623+ %mold 0
2624+ %value (tail-can val.d)
2625+ ==
2626+::
2627+:: +is-operand-start: a token an operand starts with; where an operand
2628+:: goes, |= is the constructor's (section 3)
2629+::
2630+++ is-operand-start
2631+ |= t=token
2632+ ^- ?
2633+ ?| ?=(?(%'%/' %'/' %'`' %'(' %'~[' %'[' %'|=(' %'|=' %'!!') lex.t)
2634+ ?=([?(%lit %str %str-head %name %wing) *] lex.t)
2635+ ==
2636+::
2637+:: +is-rune: a rune that is never an operand: ^- ~& ?-
2638+::
2639+++ is-rune
2640+ |= t=token
2641+ ^- ?
2642+ ?=(?(%'^-' %'~&' %'?-') lex.t)
2643+::
2644+:: +is-ctor: |= with a term tight after it, a case's constructor
2645+::
2646+++ is-ctor
2647+ |= ts=(list token)
2648+ ^- ?
2649+ ?=([[* * %'|='] [* %& [%lit %term *]] *] ts)
2650+::
2651+:: +is-rune-start: a rune where an expression starts; |= is a rune
2652+:: there unless it is the constructor
2653+::
2654+++ is-rune-start
2655+ |= ts=(list token)
2656+ ^- ?
2657+ ?~ ts |
2658+ ?| (is-rune i.ts)
2659+ &(=(%'|=' lex.i.ts) !(is-ctor ts))
2660+ ==
2661+::
2662+:: +text-piece: a string's text as its pieces: none when it is empty
2663+::
2664+++ text-piece
2665+ |= txt=@t
2666+ ^- (list piece)
2667+ ?:(=('' txt) ~ ~[[%text txt]])
2668+::
2669+:: +names-of: a name's or a wing's names
2670+::
2671+++ names-of
2672+ |= x=lexeme
2673+ ^- (list term)
2674+ ?+ x ~
2675+ [%name *] ~[p.x]
2676+ [%wing *] p.x
2677+ ==
2678+::
2679+:: +call-of: a call's elements as one expression: one alone is itself
2680+::
2681+++ call-of
2682+ |= els=(list expr)
2683+ ^- expr
2684+ ?~ els [%crash *span ~]
2685+ ?~ t.els i.els
2686+ [%call [beg:(span-of i.els) end:(span-of (rear t.els))] i.els t.els]
2687+::
2688+:: +bracket-node: a tuple, list or change from its items, ending at fin
2689+::
2690+++ bracket-node
2691+ |= $: kind=?(%tuple %list %change)
2692+ op=token
2693+ target=(unit [t=token names=(list term)])
2694+ its=(list item)
2695+ fin=loc
2696+ ==
2697+ ^- expr
2698+ ?- kind
2699+ %tuple [%tuple [beg.at.op fin] its]
2700+ %list [%list [beg.at.op fin] (turn its |=(i=item val.i))]
2701+ ::
2702+ %change
2703+ =/ beg=loc ?~(target beg.at.op beg.at.t.u.target)
2704+ :^ %change [beg fin] ?~(target ~ names.u.target)
2705+ (turn its |=(i=item ^-(edit [at.i ?~(face.i %$ u.face.i) val.i])))
2706+ ==
2707+::
2708++| %parser
2709+::
2710+:: +parser: section 3's recursive descent over one file's tokens
2711+::
2712+:: Each +read- arm reads one rule of the EBNF from the head of the
2713+:: tokens it is given and returns (pare node): the node and the
2714+:: tokens after it, or the first error. It decides by the next token,
2715+:: at most with the one after it and whether that one is tight
2716+:: (section 3), so it never backtracks. A loop over items is a trap
2717+:: whose every step, through +then, is a tail call, so a long module
2718+:: grows no stack; only nesting does, and a line's nesting is bounded
2719+:: by its length. all is the whole token list, which only errors
2720+:: read (+stray).
2721+::
2722+++ parser
2723+ |_ [file=path all=(list token)]
2724+ ::
2725+ :: +bad: "expected <want>, found <the next token>" (+fail)
2726+ ::
2727+ ++ bad
2728+ |= [ts=(list token) want=tape]
2729+ ^- [%| p=error]
2730+ (fail file ts want)
2731+ ::
2732+ :: +bad-why: +bad with a hint (+fail-why)
2733+ ::
2734+ ++ bad-why
2735+ |= [ts=(list token) want=tape why=tape]
2736+ ^- [%| p=error]
2737+ (fail-why file ts want why)
2738+ ::
2739+ :: +bad-in: +bad where a place begins whose first characters are the
2740+ :: mask can (+fail-in)
2741+ ::
2742+ ++ bad-in
2743+ |= [ts=(list token) want=tape can=@]
2744+ ^- [%| p=error]
2745+ (fail-in file ts want can)
2746+ ::
2747+ :: +bad-in-why: +bad-in with a hint (+fail-in-why)
2748+ ::
2749+ ++ bad-in-why
2750+ |= [ts=(list token) want=tape can=@ why=tape]
2751+ ^- [%| p=error]
2752+ (fail-in-why file ts want can why)
2753+ ::
2754+ :: +bad-space: a tight form that found no next token right after prev
2755+ :: (+fail-space)
2756+ ::
2757+ ++ bad-space
2758+ |= [prev=token ts=(list token) want=tape]
2759+ ^- [%| p=error]
2760+ (fail-space file prev ts want "")
2761+ ::
2762+ :: +bad-at: an error inside a token, or at the end of a line
2763+ ::
2764+ ++ bad-at
2765+ |= [at=loc msg=tape]
2766+ ^- [%| p=error]
2767+ [%| file line.at col.at msg]
2768+ ::
2769+ :: +closing: what a bracket op still needs, its closer close
2770+ ::
2771+ ++ closing
2772+ |= [op=token close=tape]
2773+ ^- tape
2774+ "`{close}` to close the {(show-found op)} at {(show-loc beg.at.op)}"
2775+ ::
2776+ :: +bad-end: a line that should end and goes on, after a call
2777+ ::
2778+ ++ bad-end
2779+ |= ts=(list token)
2780+ ^- [%| p=error]
2781+ (bad-end-in ts operand-mask)
2782+ ::
2783+ :: +bad-end-in: +bad-end after a construct that text beginning with
2784+ :: a character of the mask can could still go on, as more operands go
2785+ :: on a call; at an error token whose text can't, at that text's
2786+ :: start (+fail-in): +$ x @ ?: fails at the ?
2787+ ::
2788+ ++ bad-end-in
2789+ |= [ts=(list token) can=@]
2790+ ^- [%| p=error]
2791+ =/ want=tape "the end of the line"
2792+ ?: ?=([[* * %indent] *] ts)
2793+ %^ bad-why ts want
2794+ %+ weld "only a bracket open at the end of a line, "
2795+ "or a rune's body, takes deeper lines"
2796+ ?: &(?=(^ ts) (stray i.ts))
2797+ (bad-why ts want "this {(show-found i.ts)} closes no bracket")
2798+ ?. ?=([[* * [%error *]] *] ts) (bad ts want)
2799+ =/ ok=@ ?:(tight.i.ts after-mask can)
2800+ ?: |(=(':' c.lex.i.ts) (in c.lex.i.ts ok)) (bad ts want)
2801+ [%| (moved file want i.ts)]
2802+ ::
2803+ :: +no-gap: a token tight where a space goes, after a rune, a name, a
2804+ :: sample or a pattern; at an error token, whose text can't go tight
2805+ :: there unless it is a comment's :, at that text's start (+fail-in)
2806+ ::
2807+ ++ no-gap
2808+ |= [ts=(list token) want=tape]
2809+ ^- [%| p=error]
2810+ ?. &(?=([[* * [%error *]] *] ts) !=(':' c.lex.i.ts)) (bad ts want)
2811+ [%| (moved file want i.ts)]
2812+ ::
2813+ :: +no-space: a token tight after an item, where a space goes
2814+ ::
2815+ ++ no-space
2816+ |= ts=(list token)
2817+ ^- [%| p=error]
2818+ =/ te=(unit error) (tight-error file ts)
2819+ ?^ te [%| u.te]
2820+ ?. ?=([[* * %'='] *] ts) (bad ts "a space between items")
2821+ %^ bad-why ts "a space between items"
2822+ "`name=value` goes in a cell, as [a=1], or a change, as m(a=1)"
2823+ ::
2824+ :: +no-space-pattern: +no-space in a cell pattern
2825+ ::
2826+ ++ no-space-pattern
2827+ |= ts=(list token)
2828+ ^- [%| p=error]
2829+ ?. ?=([[* * %'='] *] ts) (no-space ts)
2830+ %^ bad-why ts "a space between items"
2831+ "patterns take no `name=`: a bare name binds, as [a b]"
2832+ ::
2833+ :: +no-operand: a token where an expression or an operand goes that
2834+ :: starts none (can: what may start one), with a hint for the left-out
2835+ :: forms the lexer can't see (2.6) and other likely slips
2836+ ::
2837+ ++ no-operand
2838+ |= [ts=(list token) can=@]
2839+ ^- [%| p=error]
2840+ =/ want=tape "an expression"
2841+ ?: ?=([[* * %'='] [* %& %'('] *] ts)
2842+ (bad-why ts want "`=(a b)` is left out: eq is a gate")
2843+ ?: ?=([[* * %'='] [* %& %'/'] *] ts)
2844+ (bad-why ts want "`=/` is left out: `++` defines values")
2845+ ?: ?=([[* * %'='] [* %& %'+'] *] ts)
2846+ (bad-why ts want "`=+` is left out: `++` defines values")
2847+ ?: ?=([[* * %'='] [* %& %'?'] *] ts)
2848+ (bad-why ts want "`=?` is left out: `++` defines values")
2849+ ?: ?& ?=([[* * %'='] [* %& [%error *]] *] ts)
2850+ =('.' c.lex.i.t.ts)
2851+ ==
2852+ (bad-why ts want "`=.` is left out: `++` defines values")
2853+ ?: ?=([[* * %'*'] *] ts)
2854+ (bad-why ts want "`*mold` is left out: no defaults")
2855+ ?: ?=([[* * %'+'] *] ts)
2856+ (bad-why ts want "a pair takes no spaces, as gap+%s2")
2857+ ?: ?=([[* * %'?'] *] ts)
2858+ %: bad-in-why ts want can
2859+ "`?` alone is the loobean mold, and `?-` the branch"
2860+ ==
2861+ ?: &(?=(^ ts) (is-rune i.ts))
2862+ (bad-in-why ts want can "a rune here goes in parentheses")
2863+ ?: &(?=(^ ts) (stray i.ts))
2864+ (bad-why ts want "this {(show-found i.ts)} closes no bracket")
2865+ (bad-in ts want can)
2866+ ::
2867+ :: +no-name: a token where a name goes that isn't one
2868+ ::
2869+ ++ no-name
2870+ |= ts=(list token)
2871+ ^- [%| p=error]
2872+ ?: ?=([[* * [%tvar *]] *] ts)
2873+ (bad-why ts "a name" "a name starts with a lowercase letter")
2874+ ?: ?=([[* * [%wing *]] *] ts)
2875+ (bad-in-why ts "a name" lower-mask "a name has no `.`")
2876+ (bad-in ts "a name" lower-mask)
2877+ ::
2878+ :: +unclosed: where the closer of the bracket op opened should be, once
2879+ :: it holds all it needs (+unclosed-want)
2880+ ::
2881+ ++ unclosed
2882+ |= [op=token close=tape ts=(list token)]
2883+ ^- [%| p=error]
2884+ (unclosed-want (closing op close) ts)
2885+ ::
2886+ :: +unclosed-want: what a bracket still needs where ts begins, want:
2887+ :: its closer once it is complete, else its next part, as "a mold,
2888+ :: the product" in $-(@. At a layout token, the bracket being one
2889+ :: that closes on its line, the error is at the end of that line,
2890+ :: as no later line can close it (+fail-line)
2891+ ::
2892+ ++ unclosed-want
2893+ |= [want=tape ts=(list token)]
2894+ ^- [%| p=error]
2895+ (fail-line file ts want "this bracket closes on its line")
2896+ ::
2897+ :: +bad-line: +bad where what is wanted goes on the line (+fail-line)
2898+ ::
2899+ ++ bad-line
2900+ |= [ts=(list token) want=tape]
2901+ ^- [%| p=error]
2902+ (fail-line file ts want "")
2903+ ::
2904+ :: +unclosed-open: a bracket that may be left open, whose line ends
2905+ :: with neither its closer nor deeper lines, nor an item that took
2906+ :: them (+shut); noun names its items
2907+ ::
2908+ ++ unclosed-open
2909+ |= [op=token close=tape noun=tape ts=(list token)]
2910+ ^- [%| p=error]
2911+ ?. ?=([[* * ?(%newline %dedent)] *] ts) (unclosed op close ts)
2912+ (bad ts "`{close}` or {noun} on a deeper line")
2913+ ::
2914+ :: +wide-rune: a rune followed tight; txt( is a left-out wide form
2915+ ::
2916+ ++ wide-rune
2917+ |= [txt=tape ts=(list token)]
2918+ ^- [%| p=error]
2919+ =/ want=tape "a space after `{txt}`"
2920+ ?. ?=([[* * %'('] *] ts) (no-gap ts want)
2921+ %^ bad-why ts want
2922+ "the wide form `{txt}(…)` is left out: indentation covers it"
2923+ ::
2924+ :: +unnamed: a change's item or line without its name=
2925+ ::
2926+ :: A name could still begin one, so the error is just past it, as
2927+ :: a tight form's is (+fail-space): `m(b c)` at the space, `m(b)`
2928+ :: at the ). So is an error token's text there, unless it begins
2929+ :: with the =: `m(a"x)` at the ", with the layout pass's message
2930+ :: after the parser's (+moved), but `m(a==1)` at the lexer's error,
2931+ :: the second =. So is a wing's first name: `m(a.b=1)` fails at the
2932+ :: dot (+fail-in). At an error token whose text can't begin a name,
2933+ :: at that text, as `m( @sd` at the @ (+fail-in).
2934+ ::
2935+ ++ unnamed
2936+ |= ts=(list token)
2937+ ^- [%| p=error]
2938+ =/ why=tape "a change's items are named, as in m(done=%.y)"
2939+ ?: ?=([[* * [%error *]] *] ts) (bad-in ts "a named item" lower-mask)
2940+ ?: ?=([[* * [%wing *]] *] ts)
2941+ (bad-in-why ts "a named item" lower-mask why)
2942+ ?. ?=([[* * [%name *]] *] ts) (bad-why ts "a named item" why)
2943+ =/ want=tape "`=` right after {(show-found i.ts)}"
2944+ ?: ?& ?=([* [* * [%error *]] *] ts)
2945+ =(end.at.i.ts from.lex.i.t.ts)
2946+ !=('=' c.lex.i.t.ts)
2947+ ==
2948+ [%| (moved file want i.t.ts)]
2949+ ?: &(?=([* [* %& *] *] ts) !?=([* [* * [%error *]] *] ts))
2950+ (bad-why t.ts want why)
2951+ (fail-space file i.ts t.ts "`=`" why)
2952+ ::
2953+ :: +doomed: where a part of a line, read from ts up to after, took
2954+ :: the deeper lines while what holds it needs more: deeper lines of
2955+ :: its own (a rune's body or arms), a part after it (the body of
2956+ :: |=(, the product of $-(), or the } of an interpolation, which
2957+ :: closes on its line (2.9). A bracket that needs none of these
2958+ :: closes with the deeper lines instead (+shut). No later line can
2959+ :: give it that, so the error is at the end of the line that took
2960+ :: them (section 3, Errors). want is what it needs. Only an error path
2961+ :: calls this, and it looks only when after begins with NEWLINE or
2962+ :: DEDENT, so it costs nothing on the way to a tree.
2963+ ::
2964+ ++ doomed
2965+ |= [ts=(list token) after=(list token) want=tape]
2966+ ^- (unit [%| p=error])
2967+ ?. ?=([[* * ?(%newline %dedent)] *] after) ~
2968+ =/ ind=(unit token) (took ts after)
2969+ ?~ ind ~
2970+ :- ~
2971+ %+ bad-at beg.at.u.ind
2972+ ;: weld
2973+ "expected {want}, found the end of the line; the deeper lines "
2974+ "go to the last bracket or rune left open on this line"
2975+ ==
2976+ ::
2977+ :: +shut: whether the bracket op closes before ts with no closer, as
2978+ :: a bracket left open before the last bracket or rune on its line
2979+ :: does: ts begins a line that isn't deeper, and the bracket's last
2980+ :: item, whose span is last, took the deeper lines (section 3)
2981+ ::
2982+ :: An item ends on a later line than op only if it read the deeper
2983+ :: lines, as no token crosses a line. So this looks at no token but
2984+ :: the next, and brackets nested on one line that close together
2985+ :: cost one test each.
2986+ ::
2987+ ++ shut
2988+ |= [op=token last=(unit span) ts=(list token)]
2989+ ^- ?
2990+ ?~ last |
2991+ ?& ?=([[* * ?(%newline %dedent)] *] ts)
2992+ (gth line.end.u.last line.beg.at.op)
2993+ ==
2994+ ::
2995+ :: +took: the INDENT among the tokens from ts up to after, if any
2996+ ::
2997+ ++ took
2998+ |= [ts=(list token) after=(list token)]
2999+ ^- (unit token)
3000+ ?~ after ~
3001+ =/ stop=loc beg.at.i.after
3002+ |- ^- (unit token)
3003+ ?~ ts ~
3004+ ?. (loc-lth beg.at.i.ts stop) ~
3005+ ?: ?=(%indent lex.i.ts) `i.ts
3006+ $(ts t.ts)
3007+ ::
3008+ :: +stray: whether a ) or ] closes no bracket opened before it on its
3009+ :: line, or none inside the interpolation it is in
3010+ ::
3011+ ++ stray
3012+ |= t=token
3013+ ^- ?
3014+ ?. ?=(?(%')' %']') lex.t) |
3015+ =| open=(list ?)
3016+ =/ ts=(list token) all
3017+ |- ^- ?
3018+ ?~ ts |
3019+ =* u i.ts
3020+ ?: =(at.u at.t) |(?=(~ open) !i.open)
3021+ ?: (is-layout u) $(ts t.ts, open ~)
3022+ ?: ?=(?(%'(' %'[' %'~[' %'|=(' %'$-(') lex.u)
3023+ $(ts t.ts, open [& open])
3024+ ?: ?=([%str-head *] lex.u) $(ts t.ts, open [| open])
3025+ ?: ?=([%str-mid *] lex.u) $(ts t.ts, open [| ?~(open ~ t.open)])
3026+ ?: |(?=(?(%')' %']') lex.u) ?=([%str-tail *] lex.u))
3027+ $(ts t.ts, open ?~(open ~ t.open))
3028+ $(ts t.ts)
3029+ ::
3030+ :: +read-module: { import NEWLINE } { definition NEWLINE }, then the
3031+ :: end of the tokens
3032+ ::
3033+ ++ read-module
3034+ |= ts=(list token)
3035+ ^- (each module error)
3036+ =| ims=(list import)
3037+ |- ^- (each module error)
3038+ ?: ?=([[* * ?(%'/-' %'/%' %'/=')] *] ts)
3039+ ;< [im=import after=(list token)] then (read-import ts)
3040+ ?. ?=([[* * %newline] *] after) (bad-end-in after 0)
3041+ $(ims [im ims], ts t.after)
3042+ =| defs=(list def)
3043+ |- ^- (each module error)
3044+ ?~ ts [%& (flop ims) (flop defs)]
3045+ ?: ?=([[* * ?(%'/-' %'/%' %'/=')] *] ts)
3046+ (bad-why ts "a definition" "imports come first")
3047+ :: what may begin the line: a definition, or before any, an import
3048+ =/ can=@ ?~(defs (con plus-mask fas-mask) plus-mask)
3049+ ;< [d=def after=(list token)] then (read-def ts can)
3050+ ?. ?=([[* * %newline] *] after) (bad-end-in after (def-can d))
3051+ $(defs [d defs], ts t.after)
3052+ ::
3053+ :: +read-import: /- name, /% term, or /= name pathlit
3054+ ::
3055+ ++ read-import
3056+ |= ts=(list token)
3057+ ^- (pare import)
3058+ ?~ ts (bad ts "an import")
3059+ =* g i.ts
3060+ =/ rest=(list token) t.ts
3061+ ?: &(?=(^ rest) tight.i.rest)
3062+ (no-gap rest "a space after {(show-found g)}")
3063+ ?: =(%'/%' lex.g)
3064+ ?: ?=([[* * [%lit %term %tas *]] *] rest)
3065+ ?: =(0 val.p.lex.i.rest)
3066+ (bad-in rest "a mark's term, as `%todo-action`" cen-mask)
3067+ [%& [%mark [beg.at.g end.at.i.rest] val.p.lex.i.rest] t.rest]
3068+ =/ want=tape "a mark's term, as `%todo-action`"
3069+ ?. ?=([[* * [%name *]] *] rest) (bad-in rest want cen-mask)
3070+ (bad-why rest want "`/%` takes no face: it names the type after its mark")
3071+ ?. ?=([[* * [%name *]] *] rest) (no-name rest)
3072+ =* nam i.rest
3073+ ?. =(%'/=' lex.g)
3074+ [%& [%sur [beg.at.g end.at.nam] p.lex.nam] t.rest]
3075+ =/ more=(list token) t.rest
3076+ ?: &(?=(^ more) tight.i.more) (no-gap more "a space after the name")
3077+ ?. ?=([[* * %'/'] *] more)
3078+ (bad-in more "a module's path, as /ui/components/card" fas-mask)
3079+ ;< [[sp=span segs=(list @ta)] after=(list token)] then
3080+ (read-pathlit i.more t.more |)
3081+ [%& [%jibb [beg.at.g end.sp] p.lex.nam segs] after]
3082+ ::
3083+ :: +read-pathlit: after a path's /, its knots, each after a tight /
3084+ :: and tight itself; / alone is the empty path where empty allows it,
3085+ :: in an expression but not an import (doc question)
3086+ ::
3087+ ++ read-pathlit
3088+ |= [sl=token ts=(list token) empty=?]
3089+ ^- (pare [span (list @ta)])
3090+ ?. ?=([[* %& [%knot *]] *] ts)
3091+ ?: &(?=(^ ts) tight.i.ts !(is-closer i.ts))
3092+ (bad ts "a path segment")
3093+ ?. empty (bad-space sl ts "a path segment")
3094+ [%& [at.sl ~] ts]
3095+ =/ segs=(list @ta) ~[p.lex.i.ts]
3096+ =/ fin=loc end.at.i.ts
3097+ =/ rest=(list token) t.ts
3098+ |- ^- (pare [span (list @ta)])
3099+ ?. ?=([[* %& %'/'] *] rest)
3100+ [%& [[beg.at.sl fin] (flop segs)] rest]
3101+ =/ nex=(list token) t.rest
3102+ ?: ?=([[* %& [%knot *]] *] nex)
3103+ $(segs [p.lex.i.nex segs], fin end.at.i.nex, rest t.nex)
3104+ ?: &(?=(^ nex) tight.i.nex) (bad nex "a path segment")
3105+ (bad-space i.rest nex "a path segment")
3106+ ::
3107+ :: +read-def: ++ name, then an expression or a body; +$ name, then a
3108+ :: mold on its line or cases on deeper lines. can is what may begin
3109+ :: a line where a definition goes (+fail-in).
3110+ ::
3111+ ++ read-def
3112+ |= [ts=(list token) can=@]
3113+ ^- (pare def)
3114+ ?~ ts (bad ts "a definition")
3115+ =* rune i.ts
3116+ ?: =(%'++' lex.rune)
3117+ ;< [nam=term after=(list token)] then (read-def-name rune t.ts)
3118+ ;< [e=expr more=(list token)] then
3119+ (read-expr-or-body "the name" after)
3120+ [%& [%value [beg.at.rune end:(span-of e)] nam e] more]
3121+ ?: (is-closer rune)
3122+ %^ bad-why ts "a definition"
3123+ "this closes no bracket, as one open at the end of its line needs none"
3124+ =/ want=tape
3125+ ?.((in '/' can) "a definition" "an import or a definition")
3126+ ?: =(%'+' lex.rune)
3127+ (bad-in-why ts want can "`+` begins `++` or `+$`")
3128+ ?. =(%'+$' lex.rune) (bad-in ts want can)
3129+ ;< [nam=term after=(list token)] then (read-def-name rune t.ts)
3130+ ?: &(?=(^ after) tight.i.after)
3131+ (no-gap after "a space after the name")
3132+ ?: ?=([[* * [%error *]] *] after)
3133+ (bad-in after "a mold" (con mold-mask bar-mask))
3134+ ?: ?=([[* * ?(%'|=' %'|=(')] *] after)
3135+ %: bad-in-why after "a mold" (con mold-mask bar-mask)
3136+ "a gate's mold is $-(sample product)"
3137+ ==
3138+ ;< [s=shape more=(list token)] then
3139+ ?: ?=([[* * %'|$'] *] after)
3140+ (read-generic i.after t.after)
3141+ (read-def-body after)
3142+ [%& [%mold [beg.at.rune end:(span-of s)] nam s] more]
3143+ ::
3144+ :: +hoon-union: a tight ( immediately after a ? mold
3145+ ::
3146+ ++ hoon-union
3147+ |= [ts=(list token) after=(list token)]
3148+ ^- ?
3149+ ?. ?=([[* %& %'('] *] after) |
3150+ |- ^- ?
3151+ ?~ ts |
3152+ ?: =(t.ts after) =(%'?' lex.i.ts)
3153+ $(ts t.ts)
3154+ ::
3155+ :: +read-def-body: one mold on the definition line or its cases below
3156+ ::
3157+ ++ read-def-body
3158+ |= ts=(list token)
3159+ ^- (pare shape)
3160+ ?. ?=([[* * %indent] *] ts)
3161+ ?: ?=([[* * ?(%newline %dedent)] *] ts)
3162+ (bad ts "a mold, on its line or a deeper one")
3163+ ;< [s=shape more=(list token)] then (read-mold ts)
3164+ ?: (hoon-union ts more)
3165+ (bad-why more "the end of the line" "a union is a `+$` with its cases below")
3166+ ?: ?=([[* * %indent] *] more)
3167+ %^ bad-why more "the end of the line"
3168+ "a `+$` takes one mold on its line or its cases below, not both"
3169+ [%& s more]
3170+ =| cs=(list shape)
3171+ =/ rest=(list token) t.ts
3172+ |- ^- (pare shape)
3173+ ;< [c=shape after=(list token)] then (read-mold rest)
3174+ ?: (hoon-union rest after)
3175+ (bad-why after "the end of the line" "a union is a `+$` with its cases below")
3176+ ?: ?=([[* * %newline] *] after) $(cs [c cs], rest t.after)
3177+ ?: ?=([[* * %dedent] *] after)
3178+ ?~ cs [%& c t.after]
3179+ =/ cases=(list shape) (flop [c cs])
3180+ [%& [%union [beg:(span-of (rear cs)) end:(span-of c)] cases] t.after]
3181+ ?: ?=([[* * %'='] *] after)
3182+ %^ bad-why after "the end of the line"
3183+ "a `+$`'s lines below are its cases; a record's fields go in a [ left open on the `+$` line"
3184+ ?: ?=([[* * %indent] *] after) (bad-end after)
3185+ ?: &(?=(^ after) (stray i.after)) (bad-end after)
3186+ (bad-why after "the end of the line" "a union takes one case per line")
3187+ ::
3188+ :: +read-def-name: after ++ or +$, a space and a name
3189+ ::
3190+ ++ read-def-name
3191+ |= [rune=token ts=(list token)]
3192+ ^- (pare term)
3193+ ?: &(?=(^ ts) tight.i.ts)
3194+ (no-gap ts "a space after {(show-found rune)}")
3195+ ?. ?=([[* * [%name *]] *] ts) (no-name ts)
3196+ [%& p.lex.i.ts t.ts]
3197+ ::
3198+ :: +read-expr-or-body: a space and an expression on the line, or a
3199+ :: body on deeper lines; what names what comes before, for errors
3200+ ::
3201+ ++ read-expr-or-body
3202+ |= [what=tape ts=(list token)]
3203+ ^- (pare expr)
3204+ ?: ?=([[* * %indent] *] ts) (read-body t.ts)
3205+ ?: ?=([[* * ?(%newline %dedent)] *] ts)
3206+ (bad ts "an expression, or a body on deeper lines")
3207+ ?: &(?=(^ ts) tight.i.ts) (no-gap ts "a space after {what}")
3208+ (read-expr ts)
3209+ ::
3210+ :: +read-body: after its INDENT, { definition NEWLINE } expr DEDENT
3211+ ::
3212+ ++ read-body
3213+ |= ts=(list token)
3214+ ^- (pare expr)
3215+ =| defs=(list def)
3216+ |- ^- (pare expr)
3217+ ?: ?=([[* * ?(%'++' %'+$')] *] ts)
3218+ ;< [d=def after=(list token)] then (read-def ts plus-mask)
3219+ ?: ?=([[* * %newline] *] after) $(defs [d defs], ts t.after)
3220+ ?. ?=([[* * %dedent] *] after) (bad-end-in after (def-can d))
3221+ (bad after "the body's final expression, after its definitions")
3222+ ?: ?=([[* * %'+'] *] ts)
3223+ %: bad-in-why ts "a definition or an expression" plus-mask
3224+ "`+` begins `++` or `+$`"
3225+ ==
3226+ ;< [e=expr after=(list token)] then (read-expr ts)
3227+ ?: ?=([[* * %dedent] *] after)
3228+ =/ ds=(list def) (flop defs)
3229+ =/ beg=loc ?~(ds beg:(span-of e) beg:(span-of i.ds))
3230+ [%& [%body [beg end:(span-of e)] ds e] t.after]
3231+ ?. ?=([[* * %newline] *] after) (bad-end-in after (tail-can e))
3232+ %^ bad-why after "the end of the body"
3233+ "a body's final expression is its last line"
3234+ ::
3235+ :: +read-expr: a rune, or a call
3236+ ::
3237+ ++ read-expr
3238+ |= ts=(list token)
3239+ ^- (pare expr)
3240+ ?~ ts (bad ts "an expression")
3241+ =* t i.ts
3242+ ?+ lex.t (read-call ts)
3243+ %'|=' ?:((is-ctor ts) (read-call ts) (read-gate t t.ts))
3244+ %'^-' (read-cast t t.ts)
3245+ %'~&' (read-trace t t.ts)
3246+ %'?-' (read-branch t t.ts)
3247+ ==
3248+ ::
3249+ :: +read-call: operand { operand }; one operand alone is itself
3250+ ::
3251+ ++ read-call
3252+ |= ts=(list token)
3253+ ^- (pare expr)
3254+ ;< [els=(list expr) after=(list token)] then (read-operands ts)
3255+ ?~ els (no-operand ts expr-mask)
3256+ [%& (call-of els) after]
3257+ ::
3258+ :: +read-operands: a call's operands, or those on a group's first
3259+ :: line, to the end of the call; each after the first follows a space
3260+ ::
3261+ ++ read-operands
3262+ |= ts=(list token)
3263+ ^- (pare (list expr))
3264+ =| els=(list expr)
3265+ |- ^- (pare (list expr))
3266+ ?~ ts [%& (flop els) ts]
3267+ =* t i.ts
3268+ ?: (ends-call t)
3269+ :: an error token whose text can't go tight after an operand
3270+ =/ te=(unit error)
3271+ :: after-mask without its =
3272+ ?~(els ~ (tight-error-in file ts (mix after-mask tis-mask)))
3273+ ?^ te [%| u.te]
3274+ :: or, past a space, can't begin one (+fail-in)
3275+ ?: ?& ?=(^ els) ?=([%error *] lex.t) !tight.t
3276+ !=(':' c.lex.t) !(in c.lex.t operand-mask)
3277+ ==
3278+ [%| (moved file "an expression" t)]
3279+ [%& (flop els) ts]
3280+ ?: &(tight.t ?=(^ els)) (no-space ts)
3281+ ?: (is-operand-start t)
3282+ ;< [e=expr more=(list token)] then (read-operand ts)
3283+ $(els [e els], ts more)
3284+ ?: &(?=(^ els) (is-rune t))
3285+ %: bad-in-why ts "an expression" operand-mask
3286+ "inside a call, a rune goes in parentheses"
3287+ ==
3288+ (no-operand ts ?~(els expr-mask operand-mask))
3289+ ::
3290+ :: +read-operand: one operand, told by its first token and, after a
3291+ :: name or a wing, by a tight ( or +
3292+ ::
3293+ ++ read-operand
3294+ |= ts=(list token)
3295+ ^- (pare expr)
3296+ ?~ ts (bad ts "an expression")
3297+ =* t i.ts
3298+ ?+ lex.t (no-operand ts operand-mask)
3299+ [%lit *] [%& [%lit at.t p.lex.t] t.ts]
3300+ [%str *] [%& [%str at.t (text-piece p.lex.t)] t.ts]
3301+ [%str-head *] (read-string t t.ts)
3302+ [%name *] (read-ref t t.ts)
3303+ [%wing *] (read-ref t t.ts)
3304+ %'%/' (read-qath t t.ts)
3305+ %'/' (read-path t t.ts)
3306+ %'`' (read-unit t t.ts)
3307+ %'(' (read-group t t.ts)
3308+ %'~[' (read-bracket %list t ~ t.ts)
3309+ %'[' (read-bracket %tuple t ~ t.ts)
3310+ %'|=(' (read-gate-wide t t.ts)
3311+ %'|=' (read-ctor t t.ts)
3312+ %'!!' [%& [%crash at.t ~] t.ts]
3313+ ==
3314+ ::
3315+ :: +read-ref: after a name or wing, a tight ( makes a change, and
3316+ :: after a name a tight + a pair; else it is a wing
3317+ ::
3318+ ++ read-ref
3319+ |= [t=token ts=(list token)]
3320+ ^- (pare expr)
3321+ =/ names=(list term) (names-of lex.t)
3322+ ?: ?=([[* %& %'('] *] ts)
3323+ (read-bracket %change i.ts `[t names] t.ts)
3324+ ?: &(?=([[* %& %'+'] *] ts) ?=([%name *] lex.t))
3325+ (read-pair t p.lex.t i.ts t.ts)
3326+ [%& [%wing at.t names] ts]
3327+ ::
3328+ :: +read-pair: name+operand, with no spaces
3329+ ::
3330+ ++ read-pair
3331+ |= [t=token tag=term lus=token ts=(list token)]
3332+ ^- (pare expr)
3333+ ?: |(?=(~ ts) !tight.i.ts) (bad-space lus ts "an operand")
3334+ ;< [v=expr after=(list token)] then (read-operand ts)
3335+ [%& [%pair [beg.at.t end:(span-of v)] tag v] after]
3336+ ::
3337+ :: +read-unit: ` and an operand, with no space
3338+ ::
3339+ ++ read-unit
3340+ |= [tic=token ts=(list token)]
3341+ ^- (pare expr)
3342+ ?: |(?=(~ ts) !tight.i.ts) (bad-space tic ts "an operand")
3343+ ;< [v=expr after=(list token)] then (read-operand ts)
3344+ [%& [%unit [beg.at.tic end:(span-of v)] v] after]
3345+ ::
3346+ :: +read-ctor: |= and a term, with no space: a case's constructor
3347+ ::
3348+ :: Where an operand goes, |= can only be a constructor or begin |=(,
3349+ :: so a tall gate there fails at the space after |=.
3350+ ::
3351+ ++ read-ctor
3352+ |= [bar=token ts=(list token)]
3353+ ^- (pare expr)
3354+ ?: |(?=(~ ts) !tight.i.ts)
3355+ %: fail-space file bar ts "`(` or a term"
3356+ ?: ?=([[* * [%lit %term *]] *] ts)
3357+ "a case's constructor takes its term with no space, as |=%got"
3358+ "a gate in an operand is |=(a body)"
3359+ ==
3360+ ?. ?=([[* * [%lit %term *]] *] ts) (bad-in ts "a term" cen-mask)
3361+ [%& [%ctor [beg.at.bar end.at.i.ts] p.lex.i.ts] t.ts]
3362+ ::
3363+ :: +read-path: a path literal, as /posts/~zod, an operand (Decisions)
3364+ ::
3365+ ++ read-path
3366+ |= [sl=token ts=(list token)]
3367+ ^- (pare expr)
3368+ ;< [[sp=span segs=(list @ta)] after=(list token)] then
3369+ (read-pathlit sl ts &)
3370+ [%& [%path sp segs] after]
3371+ ::
3372+ :: +read-qath: %/, then its segments, knots or (expr), each after a
3373+ :: tight / and tight itself; %/ alone is the root
3374+ ::
3375+ ++ read-qath
3376+ |= [cen=token ts=(list token)]
3377+ ^- (pare expr)
3378+ ?. ?=([[* %& ?([%knot *] %'(')] *] ts)
3379+ ?: &(?=(^ ts) tight.i.ts !(is-closer i.ts))
3380+ (bad ts "a path segment")
3381+ [%& [%qath at.cen ~] ts]
3382+ =| segs=(list qseg)
3383+ |- ^- (pare expr)
3384+ ;< [[s=qseg fin=loc] after=(list token)] then (read-qseg ts)
3385+ ?. ?=([[* %& %'/'] *] after)
3386+ [%& [%qath [beg.at.cen fin] (flop [s segs])] after]
3387+ =/ nex=(list token) t.after
3388+ ?: ?=([[* %& ?([%knot *] %'(')] *] nex)
3389+ $(segs [s segs], ts nex)
3390+ ?: &(?=(^ nex) tight.i.nex) (bad nex "a path segment")
3391+ (bad-space i.after nex "a path segment")
3392+ ::
3393+ :: +read-qseg: an application path's segment, a knot or (expr), and
3394+ :: where it ends: at its ), or with the deeper lines when its expr
3395+ :: took them, as any bracket before the last on its line (+shut)
3396+ ::
3397+ ++ read-qseg
3398+ |= ts=(list token)
3399+ ^- (pare [qseg loc])
3400+ ?: ?=([[* * [%knot *]] *] ts)
3401+ [%& [[%knot p.lex.i.ts] end.at.i.ts] t.ts]
3402+ ?. ?=([[* * %'('] *] ts) (bad ts "a path segment")
3403+ =* par i.ts
3404+ ?: &(?=(^ t.ts) (is-layout i.t.ts)) (unclosed-want "an expression" t.ts)
3405+ ;< [e=expr after=(list token)] then (read-expr t.ts)
3406+ ?: ?=([[* * %')'] *] after)
3407+ [%& [[%expr e] end.at.i.after] t.after]
3408+ ?: (shut par `(span-of e) after)
3409+ [%& [[%expr e] end:(span-of e)] after]
3410+ (unclosed par ")" after)
3411+ ::
3412+ :: +read-string: after its str-head, a string's interpolations and
3413+ :: text: expr { str-mid expr } str-tail
3414+ ::
3415+ ++ read-string
3416+ |= [head=token ts=(list token)]
3417+ ^- (pare expr)
3418+ =/ ps=(list piece)
3419+ ?.(?=([%str-head *] lex.head) ~ (text-piece p.lex.head))
3420+ =/ op=token head
3421+ |- ^- (pare expr)
3422+ ;< [e=expr after=(list token)] then (read-expr ts)
3423+ =. ps [[%expr e] ps]
3424+ ?: ?=([[* * [%str-mid *]] *] after)
3425+ $(ps (weld (text-piece p.lex.i.after) ps), op i.after, ts t.after)
3426+ ?. ?=([[* * [%str-tail *]] *] after)
3427+ =/ brace=loc [line.end.at.op (dec (max 2 col.end.at.op))]
3428+ =/ want=tape "`}` to close the `\{` at {(show-loc brace)}"
3429+ =/ dm (doomed ts after want)
3430+ ?^ dm u.dm
3431+ (bad after want)
3432+ =. ps (weld (text-piece p.lex.i.after) ps)
3433+ [%& [%str [beg.at.head end.at.i.after] (flop ps)] t.after]
3434+ ::
3435+ :: +read-group: ( expr ), or ( { operand } and its lines below, left
3436+ :: open
3437+ ::
3438+ :: A ( followed by a rune is the closed form. Else the group holds
3439+ :: its first line's operands and then its lines as one call, or the
3440+ :: one element alone; with ( alone, the first line below is the
3441+ :: head. Either form closes with the deeper lines, with no ), when
3442+ :: the last thing on its line took them (+shut). A ( with nothing
3443+ :: after it on its line needs those lines, as () is no group: so
3444+ :: where they don't come it wants the call's head on a deeper line,
3445+ :: and at a closer or an error token an expression (+no-operand),
3446+ :: which moves an error token whose text no expression begins
3447+ :: with to that text, as `( @sd` at the @ (+fail-in).
3448+ ::
3449+ ++ read-group
3450+ |= [par=token ts=(list token)]
3451+ ^- (pare expr)
3452+ ?: (is-rune-start ts)
3453+ ;< [e=expr after=(list token)] then (read-expr ts)
3454+ ?: ?=([[* * %')'] *] after)
3455+ [%& [%group [beg.at.par end.at.i.after] e] t.after]
3456+ ?: (shut par `(span-of e) after)
3457+ [%& [%group [beg.at.par end:(span-of e)] e] after]
3458+ (unclosed par ")" after)
3459+ ;< [els=(list expr) after=(list token)] then (read-operands ts)
3460+ ?: ?=([[* * %indent] *] after)
3461+ ;< [ls=(list item) more=(list token)] then
3462+ (read-lines %group t.after)
3463+ =/ inner=expr (call-of (weld els (turn ls |=(i=item val.i))))
3464+ [%& [%group [beg.at.par end:(span-of inner)] inner] more]
3465+ ?~ els
3466+ ?: ?=([[* * ?(%newline %dedent)] *] after)
3467+ (bad after "the call's head on a deeper line")
3468+ (no-operand after expr-mask)
3469+ ?: ?=([[* * %')'] *] after)
3470+ [%& [%group [beg.at.par end.at.i.after] (call-of els)] t.after]
3471+ =/ inner=expr (call-of els)
3472+ ?: (shut par `(span-of inner) after)
3473+ [%& [%group [beg.at.par end:(span-of inner)] inner] after]
3474+ (unclosed-open par ")" "an argument" after)
3475+ ::
3476+ :: +read-bracket: a tuple's, list's or change's items, to its closer
3477+ :: on the line, or to the end of its lines below when left open, or
3478+ :: with its last item's lines when that took the deeper lines (+shut)
3479+ ::
3480+ ++ read-bracket
3481+ |= $: kind=?(%tuple %list %change)
3482+ op=token
3483+ target=(unit [t=token names=(list term)])
3484+ ts=(list token)
3485+ ==
3486+ ^- (pare expr)
3487+ =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
3488+ =| its=(list item)
3489+ |- ^- (pare expr)
3490+ ?~ ts (bad ts "an item")
3491+ =* t i.ts
3492+ ?: =(close lex.t)
3493+ [%& (bracket-node kind op target (flop its) end.at.t) t.ts]
3494+ ?: (is-closer t) (unclosed op (trip close) ts)
3495+ ?: ?=(%indent lex.t)
3496+ ;< [ls=(list item) more=(list token)] then (read-lines kind t.ts)
3497+ =/ every=(list item) (weld (flop its) ls)
3498+ =/ fin=loc ?~(every end.at.op end.at:(rear every))
3499+ [%& (bracket-node kind op target every fin) more]
3500+ ?: &(?=(^ its) (shut op `at.i.its ts))
3501+ [%& (bracket-node kind op target (flop its) end.at.i.its) ts]
3502+ ?: ?=(?(%newline %dedent) lex.t)
3503+ (unclosed-open op (trip close) "an item" ts)
3504+ ?: &(tight.t ?=(^ its)) (no-space ts)
3505+ ;< [i=item more=(list token)] then (read-item kind ts)
3506+ $(its [i its], ts more)
3507+ ::
3508+ :: +read-item: [ name= ] operand; a tuple's item may be named, a
3509+ :: change's must be, a list's is not
3510+ ::
3511+ ++ read-item
3512+ |= [kind=?(%tuple %list %change) ts=(list token)]
3513+ ^- (pare item)
3514+ ?: &(!?=(%list kind) ?=([[* * [%name *]] [* %& %'='] *] ts))
3515+ =* nam i.ts
3516+ =/ rest=(list token) t.t.ts
3517+ ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3518+ ;< [v=expr after=(list token)] then (read-operand rest)
3519+ [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
3520+ ?: ?=(%change kind) (unnamed ts)
3521+ ?: &(?=(^ ts) (is-rune i.ts))
3522+ %: bad-in-why ts "an expression" operand-mask
3523+ "inside brackets, a rune goes in parentheses"
3524+ ==
3525+ ;< [v=expr after=(list token)] then (read-operand ts)
3526+ [%& [(span-of v) ~ v] after]
3527+ ::
3528+ :: +read-lines: after an open bracket's INDENT, its lines, an item
3529+ :: each, to its DEDENT
3530+ ::
3531+ ++ read-lines
3532+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
3533+ ^- (pare (list item))
3534+ =| ls=(list item)
3535+ |- ^- (pare (list item))
3536+ ;< [l=item after=(list token)] then (read-line kind ts)
3537+ ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
3538+ ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
3539+ ?. ?=([[* * ?(%')' %']')] *] after) (bad-end-in after (tail-can val.l))
3540+ (closer-after after)
3541+ ::
3542+ :: +closer-after: a ) or ] after an open bracket's line's item
3543+ ::
3544+ ++ closer-after
3545+ |= ts=(list token)
3546+ ^- [%| p=error]
3547+ %^ bad-why ts "the end of the line"
3548+ "a bracket open at the end of its line takes no closer"
3549+ ::
3550+ :: +closer-first: an open bracket's line that starts with a ) or ],
3551+ :: where want, its item, goes
3552+ ::
3553+ ++ closer-first
3554+ |= [ts=(list token) want=tape]
3555+ ^- (unit [%| p=error])
3556+ ?. ?=([[* * ?(%')' %']')] *] ts) ~
3557+ :- ~
3558+ %^ bad-why ts want
3559+ %+ weld "a bracket open at the end of its line takes no closer: "
3560+ "its items end at the first line that isn't deeper"
3561+ ::
3562+ :: +read-line: an open bracket's line, [ name= ] expr; a tuple's may
3563+ :: be named, a change's must be, a list's and a group's are not
3564+ :: (doc question)
3565+ ::
3566+ ++ read-line
3567+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
3568+ ^- (pare item)
3569+ =/ cf (closer-first ts "an item")
3570+ ?^ cf u.cf
3571+ ?: ?& ?=(?(%tuple %change) kind)
3572+ ?=([[* * [%name *]] [* %& %'='] *] ts)
3573+ ==
3574+ =* nam i.ts
3575+ =/ rest=(list token) t.t.ts
3576+ ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3577+ ;< [v=expr after=(list token)] then (read-expr rest)
3578+ [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
3579+ ?: ?=(%change kind) (unnamed ts)
3580+ ;< [v=expr after=(list token)] then (read-expr ts)
3581+ [%& [(span-of v) ~ v] after]
3582+ ::
3583+ :: +read-gate-wide: |=( sample operand ), the one wide expression; it
3584+ :: closes with its body's lines when its body took the deeper lines
3585+ :: (+shut), but a sample that took them leaves it no body (+doomed)
3586+ ::
3587+ ++ read-gate-wide
3588+ |= [op=token ts=(list token)]
3589+ ^- (pare expr)
3590+ ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3591+ (unclosed-want "a sample" ts)
3592+ ;< [s=sample after=(list token)] then (read-sample ts)
3593+ ?: (hoon-union ts after)
3594+ (bad-why after "a space after the sample" "a union is a `+$` with its cases below")
3595+ ?: &(?=(^ after) |((is-closer i.after) (is-layout i.after)))
3596+ =/ dm (doomed ts after "the gate's body")
3597+ ?^ dm u.dm
3598+ (unclosed-want "the gate's body" after)
3599+ ?: &(?=(^ after) tight.i.after)
3600+ (no-gap after "a space after the sample")
3601+ ?: &(?=(^ after) (is-rune i.after))
3602+ %: bad-in-why after "an expression" operand-mask
3603+ "the wide gate's body is an operand, so a rune goes in parentheses"
3604+ ==
3605+ ;< [b=expr more=(list token)] then (read-operand after)
3606+ ?: ?=([[* * %')'] *] more)
3607+ [%& [%gate-wide [beg.at.op end.at.i.more] s b] t.more]
3608+ ?: (shut op `(span-of b) more)
3609+ [%& [%gate-wide [beg.at.op end:(span-of b)] s b] more]
3610+ ?. &(?=(^ more) !tight.i.more (is-operand-start i.more))
3611+ (unclosed op ")" more)
3612+ %^ bad-why more (closing op ")")
3613+ "the wide gate's body is one operand, so a call goes in parentheses"
3614+ ::
3615+ :: +read-gate: |= sample, then an expression or a body
3616+ ::
3617+ ++ read-gate
3618+ |= [bar=token ts=(list token)]
3619+ ^- (pare expr)
3620+ ?: &(?=(^ ts) tight.i.ts)
3621+ :: a % could begin a constructor's term, as |=%got
3622+ ?: =('%' (first-char i.ts)) (bad-in ts "a term" cen-mask)
3623+ (no-gap ts "a space after `|=`")
3624+ ;< [s=sample after=(list token)] then (read-sample ts)
3625+ ?: (hoon-union ts after)
3626+ (bad-why after "a space after the sample" "a union is a `+$` with its cases below")
3627+ =/ dm (doomed ts after "an expression, or a body on deeper lines")
3628+ ?^ dm u.dm
3629+ ;< [e=expr more=(list token)] then
3630+ (read-expr-or-body "the sample" after)
3631+ [%& [%gate [beg.at.bar end:(span-of e)] s e] more]
3632+ ::
3633+ :: +read-cast: ^- mold, then an expression or a body
3634+ ::
3635+ ++ read-cast
3636+ |= [ket=token ts=(list token)]
3637+ ^- (pare expr)
3638+ ?: &(?=(^ ts) tight.i.ts) (wide-rune "^-" ts)
3639+ ;< [s=shape after=(list token)] then (read-mold ts)
3640+ ?: (hoon-union ts after)
3641+ (bad-why after "a space after the mold" "a union is a `+$` with its cases below")
3642+ =/ dm (doomed ts after "an expression, or a body on deeper lines")
3643+ ?^ dm u.dm
3644+ ;< [e=expr more=(list token)] then
3645+ (read-expr-or-body "the mold" after)
3646+ [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
3647+ ::
3648+ :: +read-trace: ~& expr, then its body below
3649+ ::
3650+ ++ read-trace
3651+ |= [sig=token ts=(list token)]
3652+ ^- (pare expr)
3653+ ?: &(?=(^ ts) tight.i.ts) (wide-rune "~&" ts)
3654+ ;< [v=expr after=(list token)] then (read-expr ts)
3655+ ?. ?=([[* * %indent] *] after)
3656+ =/ dm (doomed ts after "`~&`'s body on deeper lines")
3657+ ?^ dm u.dm
3658+ (bad after "`~&`'s body on deeper lines")
3659+ ;< [b=expr more=(list token)] then (read-body t.after)
3660+ [%& [%trace [beg.at.sig end:(span-of b)] v b] more]
3661+ ::
3662+ :: +read-branch: ?- expr, then its arms below, one per line
3663+ ::
3664+ ++ read-branch
3665+ |= [wut=token ts=(list token)]
3666+ ^- (pare expr)
3667+ ?: &(?=(^ ts) tight.i.ts) (wide-rune "?-" ts)
3668+ ;< [s=expr after=(list token)] then (read-expr ts)
3669+ ?. ?=([[* * %indent] *] after)
3670+ =/ dm (doomed ts after "`?-`'s arms on deeper lines")
3671+ ?^ dm u.dm
3672+ (bad after "`?-`'s arms on deeper lines")
3673+ =| arms=(list arm)
3674+ =/ rest=(list token) t.after
3675+ |- ^- (pare expr)
3676+ ;< [a=arm more=(list token)] then (read-arm rest)
3677+ ?: ?=([[* * %newline] *] more) $(arms [a arms], rest t.more)
3678+ ?. ?=([[* * %dedent] *] more) (bad-end-in more (tail-can val.a))
3679+ [%& [%branch [beg.at.wut end.at.a] s (flop [a arms])] t.more]
3680+ ::
3681+ :: +read-arm: a pattern, then an expression or a body
3682+ ::
3683+ ++ read-arm
3684+ |= ts=(list token)
3685+ ^- (pare arm)
3686+ ;< [p=pattern after=(list token)] then (read-pattern ts)
3687+ ?: ?=([[* %& %'+'] *] after)
3688+ %^ bad-why after "a space after the pattern"
3689+ "patterns take no pairs: write a cell, as [%gap %s2]"
3690+ ?: ?=([[* %& %'='] *] after)
3691+ %^ bad-why after "a space after the pattern"
3692+ "patterns take no `name=`: a bare name binds, as [a b]"
3693+ ;< [e=expr more=(list token)] then
3694+ (read-expr-or-body "the pattern" after)
3695+ [%& [[beg:(span-of p) end:(span-of e)] p e] more]
3696+ ::
3697+ :: +read-pattern: a term, number, string, ship, loobean, ~, * or name,
3698+ :: or a cell of patterns
3699+ ::
3700+ :: Where a pattern can't take a token, the error points where the
3701+ :: token stops being a pattern's start (+fail-in): a date or knot
3702+ :: at its second character, since ~ alone is null; a duration at its
3703+ :: third, as ~s could begin the ship ~sev; ~[ at its [; a string
3704+ :: with {…} at its {; a wing at its first dot.
3705+ ::
3706+ ++ read-pattern
3707+ |= ts=(list token)
3708+ ^- (pare pattern)
3709+ ?~ ts (bad ts "a pattern")
3710+ =* t i.ts
3711+ ?+ lex.t (bad-in ts "a pattern" pattern-mask)
3712+ [%lit *]
3713+ =* l p.lex.t
3714+ ?: ?=(?(%number %ship %term %loobean %null) form.l)
3715+ [%& [%lit at.t l] t.ts]
3716+ =/ what=tape
3717+ ?- form.l
3718+ %date "dates"
3719+ %duration "durations"
3720+ %knot "knots"
3721+ ==
3722+ =/ n=@ud ?:(?=(%duration form.l) 2 1)
3723+ %+ bad-at [line.beg.at.t (add n col.beg.at.t)]
3724+ ;: weld
3725+ "expected a pattern, found {(show-found t)}; patterns take no "
3726+ what
3727+ ": compare values with ?- (eq a b)"
3728+ ==
3729+ ::
3730+ [%str *] [%& [%str at.t p.lex.t] t.ts]
3731+ %'*' [%& [%any at.t ~] t.ts]
3732+ [%name *] [%& [%bind at.t p.lex.t] t.ts]
3733+ %'[' (read-cell-pattern t t.ts)
3734+ %'`' (bad-why ts "a pattern" "patterns take no units: write [~ x]")
3735+ ::
3736+ [%wing *]
3737+ %: bad-in-why ts "a pattern" pattern-mask
3738+ "a name in a pattern binds anew, so it has no `.`"
3739+ ==
3740+ ::
3741+ [%str-head *]
3742+ %+ bad-at [line.end.at.t (dec (max 2 col.end.at.t))]
3743+ %+ weld "expected a pattern, found a string with `\{…}`; "
3744+ "patterns take strings without `\{…}`"
3745+ ::
3746+ %'~['
3747+ %+ bad-at [line.beg.at.t +(col.beg.at.t)]
3748+ "expected a pattern, found `~[`; patterns take no lists"
3749+ ==
3750+ ::
3751+ :: +read-cell-pattern: [ pattern { pattern } ], closed on its line
3752+ ::
3753+ ++ read-cell-pattern
3754+ |= [op=token ts=(list token)]
3755+ ^- (pare pattern)
3756+ =| ps=(list pattern)
3757+ |- ^- (pare pattern)
3758+ ?: ?=([[* * %']'] *] ts)
3759+ ?~ ps (bad ts "a pattern")
3760+ [%& [%cell [beg.at.op end.at.i.ts] (flop ps)] t.ts]
3761+ ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3762+ ?~ ps (unclosed-want "a pattern" ts)
3763+ (unclosed op "]" ts)
3764+ ?: &(?=(^ ps) ?=(^ ts) tight.i.ts) (no-space-pattern ts)
3765+ ;< [p=pattern after=(list token)] then (read-pattern ts)
3766+ $(ps [p ps], ts after)
3767+ ::
3768+ :: +read-sample: a gate's sample, a field, except that a bare name
3769+ :: binds, alone or in a cell sample at any depth (section 3). A cell
3770+ :: sample's [ has no open form, but closes with the deeper lines when
3771+ :: its last item took them (+shut), which leaves the gate no body
3772+ ::
3773+ ++ read-sample
3774+ |= ts=(list token)
3775+ ^- (pare sample)
3776+ ?: ?=([[* * [%name *]] [* %& %'='] *] ts) (read-face ts)
3777+ ?: ?=([[* * [%name *]] *] ts) [%& [%bind at.i.ts p.lex.i.ts] t.ts]
3778+ ?: ?=([[* * %'='] *] ts) (read-pun i.ts t.ts)
3779+ ?: &(?=(^ ts) (is-layout i.ts)) (bad-line ts "a sample")
3780+ ?: ?=([[* * [%error *]] *] ts)
3781+ (bad-in ts "a mold" (con mold-mask tis-mask))
3782+ ?. ?=([[* * %'['] *] ts)
3783+ ;< [s=shape after=(list token)] then (read-mold ts)
3784+ [%& [%bare (span-of s) s] after]
3785+ =* op i.ts
3786+ =| ss=(list sample)
3787+ =/ rest=(list token) t.ts
3788+ |- ^- (pare sample)
3789+ ?: ?=([[* * %']'] *] rest)
3790+ ?~ ss (bad rest "a sample")
3791+ [%& [%cell [beg.at.op end.at.i.rest] (flop ss)] t.rest]
3792+ ?: &(?=(^ ss) (shut op `(span-of i.ss) rest))
3793+ [%& [%cell [beg.at.op end:(span-of i.ss)] (flop ss)] rest]
3794+ ?: &(?=(^ rest) |((is-closer i.rest) (is-layout i.rest)))
3795+ ?~ ss (unclosed-want "a sample" rest)
3796+ (unclosed op "]" rest)
3797+ ?: &(?=(^ ss) ?=(^ rest) tight.i.rest) (no-space rest)
3798+ ;< [s=sample after=(list token)] then (read-sample rest)
3799+ ?: (hoon-union rest after)
3800+ (bad-why after "a space between items" "a union is a `+$` with its cases below")
3801+ $(ss [s ss], rest after)
3802+ ::
3803+ :: +read-field: a cell mold's field: name=mold, =name, or a mold
3804+ ::
3805+ ++ read-field
3806+ |= ts=(list token)
3807+ ^- (pare field)
3808+ ?: ?=([[* * [%name *]] [* %& %'='] *] ts) (read-face ts)
3809+ ?: ?=([[* * %'='] *] ts) (read-pun i.ts t.ts)
3810+ :: = begins a pun here, as a mold's first characters begin a mold
3811+ ?: ?=([[* * [%error *]] *] ts)
3812+ (bad-in ts "a mold" (con mold-mask tis-mask))
3813+ ;< [s=shape after=(list token)] then (read-mold ts)
3814+ [%& [%bare (span-of s) s] after]
3815+ ::
3816+ :: +read-face: name=mold, with no spaces
3817+ ::
3818+ ++ read-face
3819+ |= ts=(list token)
3820+ ^- (pare field)
3821+ ?. ?=([[* * [%name *]] [* * %'='] *] ts) (bad ts "a name")
3822+ =* nam i.ts
3823+ =/ rest=(list token) t.t.ts
3824+ ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a mold")
3825+ ;< [s=shape after=(list token)] then (read-mold rest)
3826+ [%& [%face [beg.at.nam end:(span-of s)] p.lex.nam s] after]
3827+ ::
3828+ :: +read-pun: =name, with no space, for name=name
3829+ ::
3830+ ++ read-pun
3831+ |= [tis=token ts=(list token)]
3832+ ^- (pare field)
3833+ ?: |(?=(~ ts) !tight.i.ts) (bad-space tis ts "a name")
3834+ ?. ?=([[* * [%name *]] *] ts) (no-name ts)
3835+ [%& [%pun [beg.at.tis end.at.i.ts] p.lex.i.ts] t.ts]
3836+ ::
3837+ :: +read-mold: one mold
3838+ ::
3839+ ++ read-mold
3840+ |= ts=(list token)
3841+ ^- (pare shape)
3842+ ?~ ts (bad ts "a mold")
3843+ =* t i.ts
3844+ ?+ lex.t (bad-in ts "a mold" mold-mask)
3845+ [%aura *] [%& [%aura at.t p.lex.t] t.ts]
3846+ %'*' [%& [%noun at.t ~] t.ts]
3847+ %'!!' [%& [%void at.t ~] t.ts]
3848+ %'?' [%& [%flag at.t ~] t.ts]
3849+ %'_' [%& [%hole at.t ~] t.ts]
3850+ [%name *] [%& [%ref at.t ~[p.lex.t]] t.ts]
3851+ [%wing *] [%& [%ref at.t p.lex.t] t.ts]
3852+ [%tvar *] [%& [%tvar at.t p.lex.t] t.ts]
3853+ %'/' (read-pathmold t t.ts)
3854+ %'(' (read-apply t t.ts)
3855+ %'[' (read-cell-mold t t.ts)
3856+ %'$-(' (read-fn t t.ts)
3857+ %'|$' %: bad-in-why ts "a mold" mold-mask
3858+ "`|$` goes right after a `+$`'s name, as in +$ result |$ [V E]"
3859+ ==
3860+ ::
3861+ ?(%'|=' %'|=(')
3862+ %: bad-in-why ts "a mold" mold-mask
3863+ "a gate's mold is $-(sample product)"
3864+ ==
3865+ ::
3866+ [%lit *]
3867+ ?. ?=(?(%null %term %loobean) form.p.lex.t)
3868+ (bad-in ts "a mold" mold-mask)
3869+ [%& [%const at.t p.lex.t] t.ts]
3870+ ==
3871+ ::
3872+ :: +read-molds: molds after an application name, to its ) or its last
3873+ :: mold's deeper lines (+shut). Each follows a space; ( may be left
3874+ :: open, with one mold per deeper line (mlines).
3875+ ::
3876+ ++ read-molds
3877+ |= [op=token ts=(list token)]
3878+ ^- (pare [(list shape) loc])
3879+ =| ms=(list shape)
3880+ |- ^- (pare [(list shape) loc])
3881+ ?: ?=([[* * %')'] *] ts)
3882+ ?~ ms (bad ts "a mold")
3883+ [%& [(flop ms) end.at.i.ts] t.ts]
3884+ ?: ?=([[* * %indent] *] ts)
3885+ ;< [ls=(list shape) more=(list token)] then (read-mlines t.ts)
3886+ =/ every=(list shape) (weld (flop ms) ls)
3887+ [%& [every ?~(every end.at.op end:(span-of (rear every)))] more]
3888+ ?: (shut op ?~(ms ~ `(span-of i.ms)) ts)
3889+ [%& [(flop ms) ?~(ms end.at.op end:(span-of i.ms))] ts]
3890+ ?: ?=([[* * ?(%newline %dedent)] *] ts)
3891+ (unclosed-open op ")" "a mold" ts)
3892+ ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3893+ ?~ ms (unclosed-want "a mold" ts)
3894+ (unclosed op ")" ts)
3895+ ?: &(?=(^ ts) tight.i.ts) (no-space ts)
3896+ ;< [m=shape after=(list token)] then (read-mold ts)
3897+ ?: (hoon-union ts after)
3898+ (bad-why after "a space between items" "a union is a `+$` with its cases below")
3899+ $(ms [m ms], ts after)
3900+ ::
3901+ :: +read-apply: ( ref mold { mold } ), or ( ref { mold } and its
3902+ :: lines below, left open; the name stays on the first line
3903+ ::
3904+ ++ read-apply
3905+ |= [op=token ts=(list token)]
3906+ ^- (pare shape)
3907+ =/ want=tape "a mold's name, as in (list @t)"
3908+ ?: &(?=(^ ts) (is-layout i.ts))
3909+ %: fail-line file ts want
3910+ "a `(` keeps the mold's name on its first line"
3911+ ==
3912+ ?. ?=([[* * ?([%name *] [%wing *])] *] ts) (bad-in ts want lower-mask)
3913+ ;< [[ms=(list shape) fin=loc] after=(list token)] then
3914+ (read-molds op t.ts)
3915+ [%& [%apply [beg.at.op fin] (names-of lex.i.ts) ms] after]
3916+ ::
3917+ :: +read-fn: $-( mold mold ), closed on its line, or with the product
3918+ :: when that took the deeper lines (+shut); a sample that took them
3919+ :: leaves it no product (+doomed)
3920+ ::
3921+ ++ read-fn
3922+ |= [op=token ts=(list token)]
3923+ ^- (pare shape)
3924+ ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3925+ (unclosed-want "a mold" ts)
3926+ ;< [a=shape after=(list token)] then (read-mold ts)
3927+ ?: (hoon-union ts after)
3928+ (bad-why after "a space between items" "a union is a `+$` with its cases below")
3929+ =/ want=tape "a mold, the product"
3930+ ?: &(?=(^ after) |((is-closer i.after) (is-layout i.after)))
3931+ =/ dm (doomed ts after want)
3932+ ?^ dm u.dm
3933+ (unclosed-want want after)
3934+ ?: &(?=(^ after) tight.i.after) (no-space after)
3935+ ;< [b=shape more=(list token)] then (read-mold after)
3936+ ?: (hoon-union after more)
3937+ (bad-why more "a space between items" "a union is a `+$` with its cases below")
3938+ ?: ?=([[* * %')'] *] more)
3939+ [%& [%fn [beg.at.op end.at.i.more] a b] t.more]
3940+ ?: (shut op `(span-of b) more)
3941+ [%& [%fn [beg.at.op end:(span-of b)] a b] more]
3942+ (unclosed op ")" more)
3943+ ::
3944+ :: +read-cell-mold: [ field { field } ], or [ { field } and its lines
3945+ :: below, left open (flines), or closed with its last field's lines
3946+ :: when that took the deeper lines (+shut)
3947+ ::
3948+ ++ read-cell-mold
3949+ |= [op=token ts=(list token)]
3950+ ^- (pare shape)
3951+ =| fs=(list field)
3952+ |- ^- (pare shape)
3953+ ?: ?=([[* * %']'] *] ts)
3954+ ?~ fs (bad ts "a mold")
3955+ [%& [%cell [beg.at.op end.at.i.ts] (flop fs)] t.ts]
3956+ ?: ?=([[* * %indent] *] ts)
3957+ ;< [ls=(list field) more=(list token)] then (read-flines t.ts)
3958+ =/ every=(list field) (weld (flop fs) ls)
3959+ =/ fin=loc ?~(every end.at.op end:(span-of (rear every)))
3960+ [%& [%cell [beg.at.op fin] every] more]
3961+ ?: &(?=(^ fs) (shut op `(span-of i.fs) ts))
3962+ [%& [%cell [beg.at.op end:(span-of i.fs)] (flop fs)] ts]
3963+ ?: ?=([[* * ?(%newline %dedent)] *] ts)
3964+ (unclosed-open op "]" "a field" ts)
3965+ ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3966+ (unclosed op "]" ts)
3967+ ?: &(?=(^ fs) ?=(^ ts) tight.i.ts) (no-space ts)
3968+ ;< [f=field after=(list token)] then (read-field ts)
3969+ ?: (hoon-union ts after)
3970+ (bad-why after "a space between items" "a union is a `+$` with its cases below")
3971+ $(fs [f fs], ts after)
3972+ ::
3973+ :: +read-mlines: after a mold's open ('s INDENT, one mold per line, to
3974+ :: its DEDENT
3975+ ::
3976+ ++ read-mlines
3977+ |= ts=(list token)
3978+ ^- (pare (list shape))
3979+ =| ms=(list shape)
3980+ |- ^- (pare (list shape))
3981+ =/ cf (closer-first ts "a mold")
3982+ ?^ cf u.cf
3983+ ;< [m=shape after=(list token)] then (read-mold ts)
3984+ ?: (hoon-union ts after)
3985+ (bad-why after "the end of the line" "a union is a `+$` with its cases below")
3986+ ?: ?=([[* * %newline] *] after) $(ms [m ms], ts t.after)
3987+ ?: ?=([[* * %dedent] *] after) [%& (flop [m ms]) t.after]
3988+ (mold-line-end after "mold")
3989+ ::
3990+ :: +read-flines: after a mold's open ['s INDENT, one field per line, to
3991+ :: its DEDENT
3992+ ::
3993+ ++ read-flines
3994+ |= ts=(list token)
3995+ ^- (pare (list field))
3996+ =| fs=(list field)
3997+ |- ^- (pare (list field))
3998+ =/ cf (closer-first ts "a field")
3999+ ?^ cf u.cf
4000+ ;< [f=field after=(list token)] then (read-field ts)
4001+ ?: (hoon-union ts after)
4002+ (bad-why after "the end of the line" "a union is a `+$` with its cases below")
4003+ ?: ?=([[* * %newline] *] after) $(fs [f fs], ts t.after)
4004+ ?: ?=([[* * %dedent] *] after) [%& (flop [f fs]) t.after]
4005+ (mold-line-end after "field")
4006+ ::
4007+ :: +mold-line-end: what goes on after the one mold or field of an open
4008+ :: mold bracket's line (noun: which); nothing does but its end
4009+ ::
4010+ ++ mold-line-end
4011+ |= [ts=(list token) noun=tape]
4012+ ^- [%| p=error]
4013+ ?: ?=([[* * ?(%')' %']')] *] ts) (closer-after ts)
4014+ ?: |(?=(~ ts) tight.i.ts (is-layout i.ts) ?=([%error *] lex.i.ts))
4015+ (bad-end-in ts 0)
4016+ %^ bad-why ts "the end of the line"
4017+ "a bracket open at the end of its line takes one {noun} per line"
4018+ ::
4019+ :: +read-generic: |$ [ typevar { typevar } ], then a definition body
4020+ ::
4021+ ++ read-generic
4022+ |= [bar=token ts=(list token)]
4023+ ^- (pare shape)
4024+ ?: &(?=(^ ts) tight.i.ts) (wide-rune "|$" ts)
4025+ ?. ?=([[* * %'['] *] ts)
4026+ (bad-in ts "`[` and its type variables, as in |$ [M]" sel-mask)
4027+ =* op i.ts
4028+ =| vs=(list @t)
4029+ =/ rest=(list token) t.ts
4030+ |- ^- (pare shape)
4031+ ?: ?=([[* * %']'] *] rest)
4032+ ?~ vs (bad rest "a type variable")
4033+ =/ more=(list token) t.rest
4034+ ?: &(?=(^ more) tight.i.more) (no-gap more "a space after `]`")
4035+ ;< [b=shape after=(list token)] then (read-def-body more)
4036+ [%& [%generic [beg.at.bar end:(span-of b)] (flop vs) b] after]
4037+ ?: &(?=(^ rest) |((is-closer i.rest) (is-layout i.rest)))
4038+ ?~ vs (unclosed-want "a type variable" rest)
4039+ (unclosed op "]" rest)
4040+ ?: &(?=(^ vs) ?=(^ rest) tight.i.rest) (no-space rest)
4041+ ?. ?=([[* * [%tvar *]] *] rest)
4042+ (bad-in rest "a type variable" upper-mask)
4043+ $(vs [p.lex.i.rest vs], rest t.rest)
4044+ ::
4045+ :: +read-pathmold: / [ segment { / segment } ], each / and segment
4046+ :: tight; / alone is the empty path
4047+ ::
4048+ ++ read-pathmold
4049+ |= [sl=token ts=(list token)]
4050+ ^- (pare shape)
4051+ ?. ?=([[* %& ?([%knot *] %'[')] *] ts)
4052+ ?: &(?=(^ ts) tight.i.ts !(is-closer i.ts))
4053+ (bad ts "a path segment")
4054+ [%& [%path at.sl ~] ts]
4055+ =| segs=(list pseg)
4056+ |- ^- (pare shape)
4057+ ;< [[s=pseg fin=loc] after=(list token)] then (read-pseg ts)
4058+ ?. ?=([[* %& %'/'] *] after)
4059+ [%& [%path [beg.at.sl fin] (flop [s segs])] after]
4060+ =/ nex=(list token) t.after
4061+ ?: ?=([[* %& ?([%knot *] %'[')] *] nex)
4062+ $(segs [s segs], ts nex)
4063+ ?: &(?=(^ nex) tight.i.nex) (bad nex "a path segment")
4064+ (bad-space i.after nex "a path segment")
4065+ ::
4066+ :: +read-pseg: a path mold's knot, [name=aura], or [name=_] with no
4067+ :: spaces, and where it ends
4068+ ::
4069+ ++ read-pseg
4070+ |= ts=(list token)
4071+ ^- (pare [pseg loc])
4072+ ?: ?=([[* * [%knot *]] *] ts)
4073+ [%& [[%knot p.lex.i.ts] end.at.i.ts] t.ts]
4074+ ?. ?=([[* * %'['] *] ts) (bad ts "a path segment")
4075+ =* op i.ts
4076+ =/ r1=(list token) t.ts
4077+ ?: |(?=(~ r1) !tight.i.r1) (bad-space op r1 "a name")
4078+ ?. ?=([[* * [%name *]] *] r1) (no-name r1)
4079+ =/ r2=(list token) t.r1
4080+ ?: |(?=(~ r2) !tight.i.r2) (bad-space i.r1 r2 "`=`")
4081+ ?. ?=([[* * %'='] *] r2) (bad-in r2 "`=`" tis-mask)
4082+ =/ r3=(list token) t.r2
4083+ ?: |(?=(~ r3) !tight.i.r3) (bad-space i.r2 r3 "an aura or type hole")
4084+ ?. ?=([[* * ?([%aura *] %'_')] *] r3) (bad-in r3 "an aura or type hole" (con pat-mask (bex 95)))
4085+ =/ r4=(list token) t.r3
4086+ ?: |(?=(~ r4) !tight.i.r4) (bad-space i.r3 r4 "`]`")
4087+ ?. ?=([[* * %']'] *] r4) (bad-in r4 "`]`" ser-mask)
4088+ =/ at=span [beg.at.op end.at.i.r4]
4089+ =/ seg=pseg
4090+ ?: ?=(%'_' lex.i.r3) [%inferred at p.lex.i.r1 at.i.r3]
4091+ [%typed at p.lex.i.r1 p.lex.i.r3]
4092+ [%& [seg end.at.i.r4] t.r4]
4093+ --
4094+::
4095++| %span-check
4096+::
4097+:: +outline: a node as +check-spans sees it
4098+::
4099+:: lead lists the kinds (+kind-of) of token the node may start with,
4100+:: or is ~ when it starts with its first child; stop says where it
4101+:: ends (+stop).
4102+::
4103++$ outline
4104+ $~ [%$ *span ~ %kid ~]
4105+ $: kind=@tas
4106+ at=span
4107+ lead=(list @)
4108+ =stop
4109+ kids=(list outline)
4110+ ==
4111+::
4112+:: +stop: where a node ends, by the tokens of its text alone
4113+::
4114+:: %kid with its last child
4115+:: %one where its first token ends: a name, a literal
4116+:: %two where the token after its first ends: |=%got, =msg, /- todo
4117+:: %shut at the closer of its first token, an opener closed on its
4118+:: line; or with its last child, if that opener is left open
4119+:: or is a rune with its body below
4120+:: %shut2 likewise from the token after its first, a change's (
4121+:: %run at the end of the path it starts: then each tight / and
4122+:: knot, and each tight [ or ( to its closer; or with its
4123+:: last child, if a ( is left open
4124+:: %run3 likewise from its third token, an import's path
4125+:: %string at the str-tail that ends its string, past each str-mid
4126+::
4127++$ stop ?(%kid %one %two %shut %shut2 %run %run3 %string)
4128+::
4129+:: +tinfo: a token as +check-spans sees it: its kind, its end, and the
4130+:: next token's start and whether that is tight, unless it is a layout
4131+:: token
4132+::
4133++$ tinfo [kind=@ end=loc nex=(unit [beg=loc tight=?])]
4134+::
4135+:: +check-spans: whether a module's spans follow section 1's rules
4136+::
4137+:: A node starts at its first token and ends where its last token
4138+:: ends, never at a layout token: at its own token where it has one
4139+:: there (a rune, a name, an opener), else where its first child does;
4140+:: and at the token +stop names, which it finds from the tokens alone,
4141+:: matching each opener with its closer on the line. Its children's
4142+:: spans lie inside its own in source order, and so do the module's
4143+:: imports and definitions. Gives the first node that breaks a rule,
4144+:: and how, or ~. +check-spans-test checks that it catches spans a
4145+:: parser bug could give.
4146+::
4147+++ check-spans
4148+ |= [mod=module toks=(list token)]
4149+ ^- (unit tape)
4150+ %+ check-outlines toks
4151+ (weld (turn imports.mod outline-import) (turn defs.mod outline-def))
4152+::
4153+:: +check-outlines: +check-spans over the outlines of a module's nodes
4154+::
4155+++ check-outlines
4156+ |= [toks=(list token) os=(list outline)]
4157+ ^- (unit tape)
4158+ (check-kids (index-tokens toks) ~ os)
4159+::
4160+:: +index-tokens: each token that isn't a layout token, by its start,
4161+:: and each opener's closer on its line, by their starts
4162+::
4163+:: A str-head opens an interpolation that a str-mid or str-tail
4164+:: closes, and a str-mid opens the next. Openers still open at the end
4165+:: of a line have no closer.
4166+::
4167+++ index-tokens
4168+ |= toks=(list token)
4169+ ^- [info=(map loc tinfo) mat=(map loc loc)]
4170+ =| info=(map loc tinfo)
4171+ =| mat=(map loc loc)
4172+ =| open=(list loc)
4173+ |- ^- [info=(map loc tinfo) mat=(map loc loc)]
4174+ ?~ toks [info mat]
4175+ =* t i.toks
4176+ ?: (is-layout t) $(toks t.toks, open ~)
4177+ =/ k=@ (kind-of t)
4178+ =/ nex=(unit [beg=loc tight=?])
4179+ ?: |(?=(~ t.toks) (is-layout i.t.toks)) ~
4180+ `[beg.at.i.t.toks tight.i.t.toks]
4181+ =. info (~(put by info) beg.at.t [k end.at.t nex])
4182+ ?: ?=(?(%'(' %'[' %'~[' %'|=(' %'$-(' %str-head) k)
4183+ $(toks t.toks, open [beg.at.t open])
4184+ ?. ?=(?(%')' %']' %str-mid %str-tail) k) $(toks t.toks)
4185+ ?~ open $(toks t.toks)
4186+ %= $
4187+ toks t.toks
4188+ mat (~(put by mat) i.open beg.at.t)
4189+ open ?:(?=(%str-mid k) [beg.at.t t.open] t.open)
4190+ ==
4191+::
4192+:: +kind-of: a token's kind: a glyph, or its lexeme's tag
4193+::
4194+++ kind-of
4195+ |= t=token
4196+ ^- @
4197+ ?@(lex.t lex.t -.lex.t)
4198+::
4199+:: +check-kids: nodes in source order, inside the span in, each checked
4200+::
4201+++ check-kids
4202+ |= $: idx=[info=(map loc tinfo) mat=(map loc loc)]
4203+ in=(unit span)
4204+ os=(list outline)
4205+ ==
4206+ ^- (unit tape)
4207+ =| prev=(unit span)
4208+ |- ^- (unit tape)
4209+ ?~ os ~
4210+ =* o i.os
4211+ ?: &(?=(^ in) (loc-lth beg.at.o beg.u.in))
4212+ `(span-bad o "starts before its parent")
4213+ ?: &(?=(^ in) (loc-lth end.u.in end.at.o))
4214+ `(span-bad o "ends after its parent")
4215+ ?: &(?=(^ prev) (loc-lth beg.at.o end.u.prev))
4216+ `(span-bad o "starts before the node before it ends")
4217+ =/ bad=(unit tape) (check-outline idx o)
4218+ ?^ bad bad
4219+ $(prev `at.o, os t.os)
4220+::
4221+:: +check-outline: one node's start and end, then its children
4222+::
4223+++ check-outline
4224+ |= [idx=[info=(map loc tinfo) mat=(map loc loc)] o=outline]
4225+ ^- (unit tape)
4226+ =* ks kids.o
4227+ =/ head=(unit span) ?~(ks ~ `at.i.ks)
4228+ =/ tail=(unit span) ?~(ks ~ `at:(rear ks))
4229+ ?. (loc-lth beg.at.o end.at.o) `(span-bad o "is empty")
4230+ :: the start: its own token, or its first child's
4231+ =/ start=(unit tape)
4232+ ?~ lead.o
4233+ ?~ head `"has no token or child to start with"
4234+ ?: =(beg.at.o beg.u.head) ~
4235+ `"should start where its first child does, at {(show-loc beg.u.head)}"
4236+ =/ t=(unit tinfo) (~(get by info.idx) beg.at.o)
4237+ ?~ t `"starts where no token does"
4238+ ?. (lien `(list @)`lead.o |=(a=@ =(a kind.u.t)))
4239+ `"starts at a token of a kind it can't start with"
4240+ ?: &(?=(^ head) !(loc-lth beg.at.o beg.u.head))
4241+ `"should start with its own token, before its first child"
4242+ ~
4243+ ?^ start `(span-bad o u.start)
4244+ :: the end: where +stop says
4245+ =/ want=(unit loc) (stop-of idx o tail)
4246+ ?~ want `(span-bad o "has no end that its tokens give")
4247+ ?. =(u.want end.at.o)
4248+ `(span-bad o "should end at {(show-loc u.want)}")
4249+ (check-kids idx `at.o ks)
4250+::
4251+:: +stop-of: where a node should end, from its stop, the tokens, and
4252+:: its last child's span, tail
4253+::
4254+++ stop-of
4255+ |= $: idx=[info=(map loc tinfo) mat=(map loc loc)]
4256+ o=outline
4257+ tail=(unit span)
4258+ ==
4259+ ^- (unit loc)
4260+ =* info info.idx
4261+ =/ first=(unit tinfo) (~(get by info) beg.at.o)
4262+ :: the token after the one at beg, if it is on the same line
4263+ =/ after
4264+ |= beg=loc
4265+ ^- (unit loc)
4266+ =/ t=(unit tinfo) (~(get by info) beg)
4267+ ?~ t ~
4268+ ?~ nex.u.t ~
4269+ `beg.u.nex.u.t
4270+ :: the end of the token at beg
4271+ =/ end-at
4272+ |= beg=loc
4273+ ^- (unit loc)
4274+ =/ t=(unit tinfo) (~(get by info) beg)
4275+ ?~(t ~ `end.u.t)
4276+ :: the closer of the opener at beg, else the last child
4277+ =/ shut
4278+ |= beg=loc
4279+ ^- (unit loc)
4280+ =/ c=(unit loc) (~(get by mat.idx) beg)
4281+ ?^ c (end-at u.c)
4282+ ?~(tail ~ `end.u.tail)
4283+ :: a path from the token at beg: each tight / and knot after it, and
4284+ :: each tight [ or ( to its closer, or a ( left open to the end of
4285+ :: the last child, whose lines it closed with
4286+ =/ run
4287+ |= beg=loc
4288+ ^- (unit loc)
4289+ |- ^- (unit loc)
4290+ =/ t=(unit tinfo) (~(get by info) beg)
4291+ ?~ t ~
4292+ =/ n nex.u.t
4293+ ?. &(?=(^ n) tight.u.n) `end.u.t
4294+ =/ nk=(unit tinfo) (~(get by info) beg.u.n)
4295+ ?~ nk `end.u.t
4296+ ?: ?=(?(%'/' %knot) kind.u.nk) $(beg beg.u.n)
4297+ ?. ?=(?(%'[' %'(') kind.u.nk) `end.u.t
4298+ =/ c=(unit loc) (~(get by mat.idx) beg.u.n)
4299+ ?^ c $(beg u.c)
4300+ ?. &(?=(%'(' kind.u.nk) ?=(^ tail)) `end.u.t
4301+ `end.u.tail
4302+ ?- stop.o
4303+ %kid ?~(tail ~ `end.u.tail)
4304+ %one (end-at beg.at.o)
4305+ %shut (shut beg.at.o)
4306+ %run (run beg.at.o)
4307+ %two =/(n (after beg.at.o) ?~(n ~ (end-at u.n)))
4308+ %shut2 =/(n (after beg.at.o) ?~(n ~ (shut u.n)))
4309+ ::
4310+ %run3
4311+ =/ n (after beg.at.o)
4312+ ?~ n ~
4313+ =/ m (after u.n)
4314+ ?~ m ~
4315+ (run u.m)
4316+ ::
4317+ %string
4318+ =/ beg=loc beg.at.o
4319+ |- ^- (unit loc)
4320+ =/ c=(unit loc) (~(get by mat.idx) beg)
4321+ ?~ c ~
4322+ =/ t=(unit tinfo) (~(get by info) u.c)
4323+ ?~ t ~
4324+ ?: ?=(%str-tail kind.u.t) `end.u.t
4325+ $(beg u.c)
4326+ ==
4327+::
4328+:: +span-bad: a span check's error, naming the node by kind and span
4329+::
4330+++ span-bad
4331+ |= [o=outline why=tape]
4332+ ^- tape
4333+ "({(trip kind.o)} {(show-loc beg.at.o)} to {(show-loc end.at.o)}) {why}"
4334+::
4335+:: +loc-lth: whether a comes before b
4336+::
4337+++ loc-lth
4338+ |= [a=loc b=loc]
4339+ ^- ?
4340+ ?| (lth line.a line.b)
4341+ &(=(line.a line.b) (lth col.a col.b))
4342+ ==
4343+::
4344+++ outline-import
4345+ |= i=import
4346+ ^- outline
4347+ ?- -.i
4348+ %sur [%sur at.i ~[%'/-'] %two ~]
4349+ %mark [%mark at.i ~[%'/%'] %two ~]
4350+ %jibb [%jibb at.i ~[%'/='] %run3 ~]
4351+ ==
4352+::
4353+++ outline-def
4354+ |= d=def
4355+ ^- outline
4356+ ?- -.d
4357+ %mold [%mold at.d ~[%'+$'] %kid ~[(outline-shape shape.d)]]
4358+ %value [%value at.d ~[%'++'] %kid ~[(outline-expr val.d)]]
4359+ ==
4360+::
4361+++ outline-expr
4362+ |= e=expr
4363+ ^- outline
4364+ ?- -.e
4365+ %lit [%lit at.e ~[%lit] %one ~]
4366+ %str (outline-str at.e pieces.e)
4367+ %path [%path at.e ~[%'/'] %run ~]
4368+ %wing [%wing at.e ~[%name %wing] %one ~]
4369+ %pair [%pair at.e ~[%name] %kid ~[(outline-expr val.e)]]
4370+ %unit [%unit at.e ~[%'`'] %kid ~[(outline-expr val.e)]]
4371+ %group [%group at.e ~[%'('] %shut ~[(outline-expr inner.e)]]
4372+ %list [%list at.e ~[%'~['] %shut (turn items.e outline-expr)]
4373+ %tuple [%tuple at.e ~[%'['] %shut (turn items.e outline-item)]
4374+ %ctor [%ctor at.e ~[%'|='] %two ~]
4375+ %crash [%crash at.e ~[%'!!'] %one ~]
4376+ ::
4377+ %qath
4378+ =/ ks=(list outline)
4379+ %+ murn segs.e
4380+ |=(s=qseg ?.(?=(%expr -.s) ~ `(outline-expr p.s)))
4381+ [%qath at.e ~[%'%/'] %run ks]
4382+ ::
4383+ %change
4384+ =/ ks=(list outline) (turn edits.e outline-edit)
4385+ [%change at.e ~[%name %wing] %shut2 ks]
4386+ ::
4387+ %gate-wide
4388+ =/ ks=(list outline)
4389+ ~[(outline-sample sample.e) (outline-expr body.e)]
4390+ [%gate-wide at.e ~[%'|=('] %shut ks]
4391+ ::
4392+ %call
4393+ [%call at.e ~ %kid [(outline-expr head.e) (turn args.e outline-expr)]]
4394+ ::
4395+ %gate
4396+ =/ ks=(list outline)
4397+ ~[(outline-sample sample.e) (outline-expr body.e)]
4398+ [%gate at.e ~[%'|='] %kid ks]
4399+ ::
4400+ %cast
4401+ =/ ks=(list outline) ~[(outline-shape shape.e) (outline-expr val.e)]
4402+ [%cast at.e ~[%'^-'] %kid ks]
4403+ ::
4404+ %trace
4405+ =/ ks=(list outline) ~[(outline-expr val.e) (outline-expr then.e)]
4406+ [%trace at.e ~[%'~&'] %kid ks]
4407+ ::
4408+ %branch
4409+ =/ ks=(list outline)
4410+ [(outline-expr subject.e) (turn arms.e outline-arm)]
4411+ [%branch at.e ~[%'?-'] %kid ks]
4412+ ::
4413+ %body
4414+ =/ ks=(list outline)
4415+ (snoc (turn defs.e outline-def) (outline-expr final.e))
4416+ [%body at.e ~ %kid ks]
4417+ ==
4418+::
4419+++ outline-str
4420+ |= [at=span ps=(list piece)]
4421+ ^- outline
4422+ =/ ks=(list outline)
4423+ (murn ps |=(p=piece ?.(?=(%expr -.p) ~ `(outline-expr p.p))))
4424+ ?~ ks [%str at ~[%str] %one ~]
4425+ [%str at ~[%str-head] %string ks]
4426+::
4427+++ outline-item
4428+ |= i=item
4429+ ^- outline
4430+ ?~ face.i [%item at.i ~ %kid ~[(outline-expr val.i)]]
4431+ [%face at.i ~[%name] %kid ~[(outline-expr val.i)]]
4432+::
4433+++ outline-edit
4434+ |= e=edit
4435+ ^- outline
4436+ [%edit at.e ~[%name] %kid ~[(outline-expr val.e)]]
4437+::
4438+++ outline-arm
4439+ |= a=arm
4440+ ^- outline
4441+ [%arm at.a ~ %kid ~[(outline-pattern pat.a) (outline-expr val.a)]]
4442+::
4443+++ outline-sample
4444+ |= s=sample
4445+ ^- outline
4446+ ?- -.s
4447+ %bind [%bind at.s ~[%name] %one ~]
4448+ %face [%face at.s ~[%name] %kid ~[(outline-shape shape.s)]]
4449+ %pun [%pun at.s ~[%'='] %two ~]
4450+ %cell [%cell at.s ~[%'['] %shut (turn items.s outline-sample)]
4451+ %bare [%bare at.s ~ %kid ~[(outline-shape shape.s)]]
4452+ ==
4453+::
4454+++ outline-pattern
4455+ |= p=pattern
4456+ ^- outline
4457+ ?- -.p
4458+ %lit [%lit at.p ~[%lit] %one ~]
4459+ %str [%str at.p ~[%str] %one ~]
4460+ %any [%any at.p ~[%'*'] %one ~]
4461+ %bind [%bind at.p ~[%name] %one ~]
4462+ %cell [%cell at.p ~[%'['] %shut (turn items.p outline-pattern)]
4463+ ==
4464+::
4465+++ outline-shape
4466+ |= s=shape
4467+ ^- outline
4468+ ?- -.s
4469+ %aura [%aura at.s ~[%aura] %one ~]
4470+ %noun [%noun at.s ~[%'*'] %one ~]
4471+ %void [%void at.s ~[%'!!'] %one ~]
4472+ %flag [%flag at.s ~[%'?'] %one ~]
4473+ %const [%const at.s ~[%lit] %one ~]
4474+ %ref [%ref at.s ~[%name %wing] %one ~]
4475+ %tvar [%tvar at.s ~[%tvar] %one ~]
4476+ %hole [%hole at.s ~[%'_'] %one ~]
4477+ %apply [%apply at.s ~[%'('] %shut (turn args.s outline-shape)]
4478+ %cell [%cell at.s ~[%'['] %shut (turn fields.s outline-sample)]
4479+ ::
4480+ %path
4481+ =/ ks=(list outline)
4482+ %+ murn segs.s
4483+ |= g=pseg
4484+ ^- (unit outline)
4485+ ?- -.g
4486+ %knot ~
4487+ %typed `[%typed at.g ~[%'['] %shut ~]
4488+ %inferred `[%typed at.g ~[%'['] %shut ~[[%hole hole-at.g ~[%'_'] %one ~]]]
4489+ ==
4490+ [%path at.s ~[%'/'] %run ks]
4491+ ::
4492+ %union
4493+ =/ ks=(list outline) (turn cases.s outline-shape)
4494+ [%union at.s ~ %kid ks]
4495+ ::
4496+ %fn
4497+ =/ ks=(list outline)
4498+ ~[(outline-shape sample.s) (outline-shape product.s)]
4499+ [%fn at.s ~[%'$-('] %shut ks]
4500+ ::
4501+ %generic
4502+ [%generic at.s ~[%'|$'] %kid ~[(outline-shape body.s)]]
4503+ ==
4504+::
4505+:: +check-spans-test: +check-spans's own test: ~, or what went wrong
4506+::
4507+:: Each case parses a source, checks that its spans pass, then moves
4508+:: the span of every node of a kind that starts at a place, as a
4509+:: parser bug would, and checks that +check-spans says so. Run it as
4510+:: tools/hoon check-spans-test, which prints <<>> when every case
4511+:: passes.
4512+::
4513+++ check-spans-test
4514+ ^- (list tape)
4515+ =/ cases=(list [src=@t bends=(list [kind=@tas beg=loc at=span])])
4516+ :~ :: a closed bracket ending before its closer, or at its parent's
4517+ :- '++ x [a [b c]]'
4518+ ~[[%tuple [1 9] [1 9] [1 13]] [%item [1 9] [1 9] [1 13]]]
4519+ :- '++ x [a [b c]]'
4520+ ~[[%tuple [1 9] [1 9] [1 15]] [%item [1 9] [1 9] [1 15]]]
4521+ :: a bracket starting at its parent's opener
4522+ :- '++ x [[b c] a]'
4523+ ~[[%tuple [1 7] [1 6] [1 12]] [%item [1 7] [1 6] [1 12]]]
4524+ :: a group without its ), a list at the next line, a call with )
4525+ :- '++ x ~[\0a (f a)\0a++ y 1'
4526+ :~ [%group [2 3] [2 3] [2 7]]
4527+ [%list [1 6] [1 6] [2 7]]
4528+ [%value [1 1] [1 1] [2 7]]
4529+ ==
4530+ :- '++ x ~[\0a (f a)\0a++ y 1'
4531+ ~[[%list [1 6] [1 6] [3 1]] [%value [1 1] [1 1] [3 1]]]
4532+ ['++ x ~[\0a (f a)\0a++ y 1' ~[[%call [2 4] [2 4] [2 8]]]]
4533+ :: a literal running on to the next one's end
4534+ ['++ x f 1 2' ~[[%lit [1 8] [1 8] [1 11]]]]
4535+ :: a path, a string, a change and a union cut short
4536+ ['++ x f /a/b c' ~[[%path [1 8] [1 8] [1 10]]]]
4537+ ['++ x f "a{b}c" d' ~[[%str [1 8] [1 8] [1 13]]]]
4538+ ['++ x m(a=1) b' ~[[%change [1 6] [1 6] [1 11]]]]
4539+ :- '+$ x\0a %a\0a %b'
4540+ ~[[%union [2 3] [2 3] [2 5]] [%mold [1 1] [1 1] [2 5]]]
4541+ :: a mold's cell before its closer, a typed segment past its own
4542+ :- '+$ x [a=[@ @] b=@]'
4543+ ~[[%cell [1 9] [1 9] [1 13]] [%face [1 7] [1 7] [1 13]]]
4544+ :- '+$ x [p=/a/[id=@ud]]'
4545+ :~ [%typed [1 12] [1 12] [1 21]]
4546+ [%path [1 9] [1 9] [1 21]]
4547+ [%face [1 7] [1 7] [1 21]]
4548+ ==
4549+ :: an inferred path aura's hole spanning its = as well
4550+ ['+$ x /a/[id=_]' ~[[%hole [1 13] [1 12] [1 14]]]]
4551+ :: an import's path cut short
4552+ ['/= c /ui/c' ~[[%jibb [1 1] [1 1] [1 11]]]]
4553+ :: brackets that close with the deeper lines, cut at their line's
4554+ :: end: a group and a list, an application path's (, a wide gate,
4555+ :: and a mold's [ left open
4556+ ['++ x (f ~[\0a 1' ~[[%group [1 6] [1 6] [1 11]]]]
4557+ ['++ x (f ~[\0a 1' ~[[%list [1 9] [1 9] [1 11]]]]
4558+ ['++ x %/a/(f ~[\0a 1' ~[[%qath [1 6] [1 6] [1 10]]]]
4559+ ['++ g |=(a ~[\0a 1' ~[[%gate-wide [1 6] [1 6] [1 13]]]]
4560+ :- '+$ x [\0a a=@\0a b=@'
4561+ ~[[%cell [1 6] [1 6] [2 6]] [%mold [1 1] [1 1] [2 6]]]
4562+ ==
4563+ %- zing
4564+ %+ turn cases
4565+ |= [src=@t bends=(list [kind=@tas beg=loc at=span])]
4566+ ^- (list tape)
4567+ =/ name=tape "`{(trip src)}`, {<bends>}"
4568+ =/ toks=(list token) (layout /test/jibb src)
4569+ =/ res (parse-tokens /test/jibb toks)
4570+ ?: ?=(%| -.res) ~["{name}: doesn't parse: {msg.p.res}"]
4571+ =/ os=(list outline)
4572+ %+ weld (turn imports.p.res outline-import)
4573+ (turn defs.p.res outline-def)
4574+ =/ true=(unit tape) (check-outlines toks os)
4575+ ?^ true ~["{name}: its true spans fail: {u.true}"]
4576+ =/ bent=(list outline)
4577+ =/ o=(list outline) os
4578+ |- ^- (list outline)
4579+ ?~ bends o
4580+ $(bends t.bends, o (bend-outlines o kind.i.bends beg.i.bends at.i.bends))
4581+ ?: =(bent os) ~["{name}: no such node"]
4582+ ?^ (check-outlines toks bent) ~
4583+ ~["{name}: not caught"]
4584+::
4585+:: +bend-outlines: os, with the span of each node of kind kind that
4586+:: starts at beg set to at, as a parser bug could set it
4587+::
4588+++ bend-outlines
4589+ |= [os=(list outline) kind=@tas beg=loc at=span]
4590+ ^- (list outline)
4591+ ?~ os ~
4592+ =/ o=outline i.os
4593+ =? at.o &(=(kind kind.o) =(beg beg.at.o)) at
4594+ :- o(kids $(os kids.o))
4595+ $(os t.os)
4596+::
4597++| %type-inference
4598+::
4599+:: Preliminary type inference substrate. These types are internal and do
4600+:: not yet represent every Jibb mold. In particular this is not a complete
4601+:: module checker. A substitution is an association list whose first entry
4602+:: for a variable is its binding. The occurs check prevents infinite types;
4603+:: recursive named molds need their own representation, not cyclic vars.
4604+:: Each top-level inferred definition generalizes its free variables, and
4605+:: a use instantiates them afresh. Binders inside a gate stay monomorphic;
4606+:: capital variables in molds share one allocation within the definition.
4607+:: Atom constraints tied to an explicit capital or an inferred sample
4608+:: are generalized and printed. Other aura variables remain unsupported until
4609+:: their defaulting and inferred generalization are implemented.
4610+:: Restricted-number promotion considers written capitals only; if there
4611+:: are none, it skips the otherwise unnecessary environment traversal.
4612+:: Bare @ is a separate unrestricted atom type. A directional fit check
4613+:: permits concrete atoms to widen to it, never the reverse. A fit that
4614+:: needs a not-yet-implemented constraint remains unsupported. Named unions
4615+:: retain origin and ordered arguments, including phantom arguments, apart
4616+:: from their display name. Generic cases must be disjoint for all arguments.
4617+:: Unnamed union printing is informational; it is not Jibb syntax.
4618+::
4619+:: `proj` is a reserved, type-directed operation, not an ordinary gate.
4620+:: The supported fragment selects uniquely faced fields from a known record
4621+:: in source order (reordering is a doc question). It records the original
4622+:: call, source and target types, and source axes with its definition;
4623+:: A single selected field keeps its face and uses one source axis.
4624+:: Checked module interfaces retain that evidence and their source, including
4625+:: the private prelude dependency. A later lowerer must replace the call by
4626+:: an inline gate applied to the operand once; no lowering is implemented yet.
4627+:: Ordinary fits never insert a projection. Unknown or variable-origin record
4628+:: spines, nested projected fields and projections in
4629+:: recursive groups remain unsupported. Directional fits bound faced-spine
4630+:: proofs to fewer than 1,024 cells; the projection planner has a separate
4631+:: 4,096-step bound. These are inference limits, not language limits.
4632+::
4633+:: Supported API imports derive request-gate types atomically for multiple
4634+:: paths, including one typed segment or one diff fold per case. Their checked
4635+:: ordinary definitions, mark molds and supported poke constructor are also
4636+:: exported. A selected /sur mold is checked through its trusted reader result;
4637+:: unused cores and other bindings are not independently validated. APIs
4638+:: with /= imports, separate scry paths, multiple parameters or diffs, or a
4639+:: parameter together with a fold remain unsupported. The unchanged todo API
4640+:: fits this fragment, including named closed fold gates.
4641+::
4642+:: Each case's source-derived schema and canonical API identity travel in a
4643+:: dependency closure bound to the exact supplied bundle, prelude, scope and
4644+:: trusted reader results. Unknown cached entries are rebuilt. Request-bearing
4645+:: closures are limited to 256 source paths and requests. This is type
4646+:: inference only: no request lowering, runtime schema validator or proof that
4647+:: an arbitrary ask value is watchable is supplied.
4648+::
4649+:: A closed gate sample may omit one outer face from a known input slot when
4650+:: its product is identical. Distinct written names, nested value faces,
4651+:: ambiguous cell tails and raw-variable-origin fits retain their prior rules.
4652+::
4653+:: In one synthetic eval of a 48-module deep and 48-module wide request-free
4654+:: graph, baseline versus certificate inference took 21.53 s versus 23.10 s
4655+:: elapsed (21.10 s versus 22.34 s CPU), including startup. The deep cache's
4656+:: jam grew from 2,402 to 4,209 bytes (+1,807 bytes). These single-run figures
4657+:: are not production memory or performance benchmarks.
4658+::
4659++$ itype
4660+ $~ [%var 0]
4661+ $% [%var id=@ud]
4662+ [%avar id=@ud]
4663+ [%rvar id=@ud]
4664+ [%nvar id=@ud]
4665+ [%rnvar id=@ud]
4666+ [%atom aura=@ta]
4667+ [%any-atom ~]
4668+ [%flag ~]
4669+ [%noun ~]
4670+ [%empty ~]
4671+ [%tag id=@ud literal=lit constructor=?]
4672+ [%const literal=lit]
4673+ [%collection name=term args=(list itype)]
4674+ [%recursive module=term name=term label=(unit @t)]
4675+ [%jrec at=path name=term label=(unit @t) head=term aura=@ta tail=term]
4676+ [%grec at=path name=term label=(unit @t) proof=shape args=(list itype)]
4677+ [%union cases=(list itype) origin=(unit [at=path name=term]) label=(unit @t) args=(list itype)]
4678+ [%face name=term body=itype]
4679+ [%fn sample=itype product=itype]
4680+ [%cell hed=itype tal=itype]
4681+ ==
4682++$ ibinding [id=@ud val=itype]
4683++$ isub (list ibinding)
4684++$ ipending [id=@ud literal=lit]
4685+::
4686+++ itype-lookup
4687+ |= [n=@ud sub=isub]
4688+ ^- (unit itype)
4689+ ?~ sub ~
4690+ ?: =(n id.i.sub) `val.i.sub
4691+ $(sub t.sub)
4692+::
4693+++ itype-walk
4694+ |= [t=itype sub=isub]
4695+ ^- itype
4696+ ?+ -.t t
4697+ %var
4698+ =/ found=(unit itype) (itype-lookup id.t sub)
4699+ ?~ found t
4700+ ?: &(|(?=(%rvar -.u.found) ?=(%rnvar -.u.found)) =(id.t +.u.found)) u.found
4701+ $(t u.found)
4702+ %avar
4703+ =/ found=(unit itype) (itype-lookup id.t sub)
4704+ ?~ found t
4705+ ?: &(|(?=(%rvar -.u.found) ?=(%rnvar -.u.found)) =(id.t +.u.found)) u.found
4706+ $(t u.found)
4707+ %rvar
4708+ =/ found=(unit itype) (itype-lookup id.t sub)
4709+ ?~ found t
4710+ ?: &(|(?=(%rvar -.u.found) ?=(%rnvar -.u.found)) =(id.t +.u.found)) u.found
4711+ $(t u.found)
4712+ %nvar
4713+ =/ found=(unit itype) (itype-lookup id.t sub)
4714+ ?~ found t
4715+ ?: &(|(?=(%rvar -.u.found) ?=(%rnvar -.u.found)) =(id.t +.u.found)) u.found
4716+ $(t u.found)
4717+ %rnvar
4718+ =/ found=(unit itype) (itype-lookup id.t sub)
4719+ ?~ found t
4720+ ?: &(|(?=(%rvar -.u.found) ?=(%rnvar -.u.found)) =(id.t +.u.found)) u.found
4721+ $(t u.found)
4722+ %tag
4723+ =/ found=(unit itype) (itype-lookup id.t sub)
4724+ ?~ found t
4725+ ?: &(|(?=(%rvar -.u.found) ?=(%rnvar -.u.found)) =(id.t +.u.found)) u.found
4726+ $(t u.found)
4727+ ==
4728+::
4729+:: Prove only emptiness; unknown types are never treated as empty.
4730+:: A shared node budget bounds each proof attempt.
4731+++ itype-empty-cases
4732+ |= [xs=(list itype) sub=isub fuel=@ud]
4733+ ^- (unit [empty=? left=@ud])
4734+ ?~ xs `[& fuel]
4735+ =/ first=(unit [empty=? left=@ud]) (itype-empty-proof i.xs sub fuel)
4736+ ?~ first ~
4737+ ?. empty.u.first `[| left.u.first]
4738+ $(xs t.xs, fuel left.u.first)
4739+++ itype-empty-proof
4740+ |= [typ=itype sub=isub fuel=@ud]
4741+ ^- (unit [empty=? left=@ud])
4742+ ?: =(0 fuel) ~
4743+ =. fuel (dec fuel)
4744+ =. typ (itype-walk typ sub)
4745+ ?- -.typ
4746+ %empty `[& fuel]
4747+ %face $(typ body.typ)
4748+ %cell
4749+ =/ left=(unit [empty=? left=@ud]) $(typ hed.typ)
4750+ ?~ left ~
4751+ ?: empty.u.left `[& left.u.left]
4752+ $(typ tal.typ, fuel left.u.left)
4753+ %union (itype-empty-cases cases.typ sub fuel)
4754+ * `[| fuel]
4755+ ==
4756+:: Prove reachability separately from emptiness. An unresolved fixed
4757+:: recursive type is not presumed inhabited. A written, still-unconstrained
4758+:: capital is existentially inhabited for pattern reachability; the normal
4759+:: definition-boundary checks reject subsequently constrained capitals.
4760+++ itype-inhabited-cases
4761+ |= [xs=(list itype) sub=isub caps=icaps fuel=@ud pending=?]
4762+ ^- (unit [result=?(%yes %no %unknown) left=@ud])
4763+ ?~ xs `[?:(pending %unknown %no) fuel]
4764+ =/ first=(unit [result=?(%yes %no %unknown) left=@ud])
4765+ (itype-inhabited-proof i.xs sub caps fuel)
4766+ ?~ first ~
4767+ ?: =(%yes result.u.first) first
4768+ $(xs t.xs, fuel left.u.first, pending |(pending =(%unknown result.u.first)))
4769+++ itype-inhabited-proof
4770+ |= [typ=itype sub=isub caps=icaps fuel=@ud]
4771+ ^- (unit [result=?(%yes %no %unknown) left=@ud])
4772+ ?: =(0 fuel) ~
4773+ =. fuel (dec fuel)
4774+ =. typ (itype-walk typ sub)
4775+ ?- -.typ
4776+ %empty `[%no fuel]
4777+ ?(%atom %any-atom %flag %const %noun %avar %rvar %nvar %rnvar %fn %jrec) `[%yes fuel]
4778+ %var
4779+ ?: (lien caps |=(c=icap (hole-same-variable typ (itype-walk [%var id.c] sub)))) `[%yes fuel]
4780+ `[%unknown fuel]
4781+ %face $(typ body.typ)
4782+ %cell
4783+ =/ head=(unit [result=?(%yes %no %unknown) left=@ud]) $(typ hed.typ)
4784+ ?~ head ~
4785+ ?: =(%no result.u.head) head
4786+ =/ tail=(unit [result=?(%yes %no %unknown) left=@ud]) $(typ tal.typ, fuel left.u.head)
4787+ ?~ tail ~
4788+ ?: =(%no result.u.tail) tail
4789+ ?: |(=(%unknown result.u.head) =(%unknown result.u.tail)) `[%unknown left.u.tail]
4790+ `[%yes left.u.tail]
4791+ %union (itype-inhabited-cases cases.typ sub caps fuel |)
4792+ %collection
4793+ ?. &(|(=(%list name.typ) =(%unit name.typ)) ?=([* ~] args.typ)) `[%unknown fuel]
4794+ `[%yes fuel]
4795+ %grec ?:((grec-tree-proof name.typ proof.typ) `[%yes fuel] `[%unknown fuel])
4796+ * `[%unknown fuel]
4797+ ==
4798+++ itype-live-cases
4799+ |= [xs=(list itype) sub=isub caps=icaps fuel=@ud]
4800+ ^- (unit (list itype))
4801+ ?~ xs `~
4802+ =/ first=(unit [result=?(%yes %no %unknown) left=@ud])
4803+ (itype-inhabited-proof i.xs sub caps fuel)
4804+ ?~ first ~
4805+ ?: =(%unknown result.u.first) ~
4806+ =/ rest=(unit (list itype)) $(xs t.xs, fuel left.u.first)
4807+ ?~ rest ~
4808+ ?: =(%no result.u.first) rest
4809+ `[i.xs u.rest]
4810+::
4811+++ itype-occurs
4812+ |= [n=@ud t=itype sub=isub]
4813+ ^- ?
4814+ =. t (itype-walk t sub)
4815+ ?- -.t
4816+ %var =(n id.t)
4817+ %avar =(n id.t)
4818+ %rvar =(n id.t)
4819+ %nvar =(n id.t)
4820+ %rnvar =(n id.t)
4821+ %atom |
4822+ %any-atom |
4823+ %flag |
4824+ %noun |
4825+ %empty |
4826+ %tag =(n id.t)
4827+ %const |
4828+ %union |((lien cases.t |=(c=itype (itype-occurs n c sub))) (lien args.t |=(c=itype (itype-occurs n c sub))))
4829+ %recursive |
4830+ %jrec |
4831+ %grec (lien args.t |=(c=itype (itype-occurs n c sub)))
4832+ %collection (lien args.t |=(c=itype (itype-occurs n c sub)))
4833+ %face $(t body.t)
4834+ %fn |($(t sample.t) $(t product.t))
4835+ %cell |($(t hed.t) $(t tal.t))
4836+ ==
4837+::
4838+:: +itype-unify: consistent substitutions, or ~ for a mismatch
4839+::
4840+:: Different concrete auras conflict. A variable may become an atom or
4841+:: a function, but cannot contain itself. Aura-only variables and faces
4842+:: require further distinctions before this supports general Jibb.
4843+::
4844+++ itype-unify
4845+ |= [a=itype b=itype sub=isub]
4846+ ^- (unit isub)
4847+ =. a (itype-walk a sub)
4848+ =. b (itype-walk b sub)
4849+ ?: =(a b) `sub
4850+ ?: &(?=(%grec -.a) ?=(%grec -.b))
4851+ ?. &(=(at.a at.b) =(name.a name.b)) ~
4852+ (itype-unify-args args.a args.b sub)
4853+ ?: &(?=(%jrec -.a) ?=(%jrec -.b))
4854+ ?:(&(=(at.a at.b) =(name.a name.b) =(head.a head.b) =(aura.a aura.b) =(tail.a tail.b)) `sub ~)
4855+ ?: &(?=(%recursive -.a) ?=(%recursive -.b))
4856+ ?:(&(=(module.a module.b) =(name.a name.b)) `sub ~)
4857+ ?: &(?=(%union -.a) ?=(%union -.b))
4858+ ?. =(origin.a origin.b) ~
4859+ ?: &(?=(~ args.a) ?=(~ args.b)) ?:(=(cases.a cases.b) `sub ~)
4860+ ?~ origin.a ~
4861+ (itype-unify-args args.a args.b sub)
4862+ ?: &(?=(%collection -.a) ?=(%collection -.b))
4863+ ?. =(name.a name.b) ~
4864+ (itype-unify-args args.a args.b sub)
4865+ ?: ?=(%var -.a)
4866+ ?: (itype-occurs id.a b sub) ~
4867+ `[[id.a b] sub]
4868+ ?: ?=(%var -.b)
4869+ ?: (itype-occurs id.b a sub) ~
4870+ `[[id.b a] sub]
4871+ :: Arithmetic's aura variable excludes loobeans; decimal literals
4872+ :: remain defaultable until a later constraint makes them concrete.
4873+ ?: &(?=(%nvar -.a) ?=(%rvar -.b))
4874+ `[[id.b [%rnvar id.a]] [id.a [%rnvar id.a]] sub]
4875+ ?: &(?=(%rvar -.a) ?=(%nvar -.b))
4876+ `[[id.a [%rnvar id.b]] [id.b [%rnvar id.b]] sub]
4877+ ?: &(?=(%rnvar -.a) ?=(%rvar -.b)) `[[id.b a] sub]
4878+ ?: &(?=(%rvar -.a) ?=(%rnvar -.b)) `[[id.a b] sub]
4879+ ?: &(?=(%rnvar -.a) ?=(%nvar -.b)) `[[id.b a] sub]
4880+ ?: &(?=(%nvar -.a) ?=(%rnvar -.b)) `[[id.a b] sub]
4881+ ?: &(?=(%rnvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
4882+ ?: &(?=(%avar -.a) ?=(%rnvar -.b)) `[[id.a b] sub]
4883+ ?: ?=(%rnvar -.a)
4884+ ?. |(?=(%rnvar -.b) ?=(%atom -.b)) ~
4885+ `[[id.a b] sub]
4886+ ?: ?=(%rnvar -.b)
4887+ ?. ?=(%atom -.a) ~
4888+ `[[id.b a] sub]
4889+ ?: &(?=(%avar -.a) ?=(%rvar -.b)) `[[id.a b] sub]
4890+ ?: &(?=(%rvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
4891+ ?: ?=(%rvar -.a)
4892+ ?. |(?=(%rvar -.b) ?=(%atom -.b)) ~
4893+ `[[id.a b] sub]
4894+ ?: ?=(%rvar -.b)
4895+ ?. ?=(%atom -.a) ~
4896+ `[[id.b a] sub]
4897+ :: The narrower decimal constraint survives a match with an atom
4898+ :: variable; decimal syntax alone does not make it a loobean.
4899+ ?: &(?=(%nvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
4900+ ?: &(?=(%avar -.a) ?=(%nvar -.b)) `[[id.a b] sub]
4901+ ?: ?=(%nvar -.a)
4902+ ?. |(?=(%nvar -.b) ?=(%atom -.b)) ~
4903+ `[[id.a b] sub]
4904+ ?: ?=(%nvar -.b)
4905+ ?. ?=(%atom -.a) ~
4906+ `[[id.b a] sub]
4907+ ?: ?=(%avar -.a)
4908+ ?. |(?=(%avar -.b) ?=(%atom -.b) ?=(%any-atom -.b) ?=(%flag -.b)) ~
4909+ `[[id.a b] sub]
4910+ ?: ?=(%avar -.b)
4911+ ?. |(?=(%atom -.a) ?=(%any-atom -.a) ?=(%flag -.a)) ~
4912+ `[[id.b a] sub]
4913+ ?: &(?=(%const -.a) ?=(%const -.b))
4914+ ?:(=(val.literal.a val.literal.b) `sub ~)
4915+ ?: &(?=(%atom -.a) ?=(%atom -.b)) ~
4916+ ?: &(?=(%face -.a) ?=(%face -.b))
4917+ ?. =(name.a name.b) ~
4918+ $(a body.a, b body.b)
4919+ ?: &(?=(%fn -.a) ?=(%fn -.b))
4920+ =/ first=(unit isub) $(a sample.a, b sample.b)
4921+ ?~ first ~
4922+ $(a product.a, b product.b, sub u.first)
4923+ ?: &(?=(%cell -.a) ?=(%cell -.b))
4924+ =/ first=(unit isub) $(a hed.a, b hed.b)
4925+ ?~ first ~
4926+ $(a tal.a, b tal.b, sub u.first)
4927+ ~
4928+::
4929+++ itype-unify-args
4930+ |= [as=(list itype) bs=(list itype) sub=isub]
4931+ ^- (unit isub)
4932+ ?~ as ?~(bs `sub ~)
4933+ ?~ bs ~
4934+ =/ next=(unit isub) (itype-unify i.as i.bs sub)
4935+ ?~ next ~
4936+ $(as t.as, bs t.bs, sub u.next)
4937+::
4938+:: +itype-fit: one-way widening from an actual type to an expected type
4939+::
4940+:: An unknown variable used where @ is expected gains a fresh atom
4941+:: constraint. Function compatibility involving @ remains unknown.
4942+::
4943++$ ifit $%([%ok sub=isub next=@ud] [%bad ~] [%unknown ~])
4944+++ itype-has-any-atom
4945+ |= [t=itype sub=isub]
4946+ ^- ?
4947+ =. t (itype-walk t sub)
4948+ ?- -.t
4949+ %var |
4950+ %avar |
4951+ %rvar |
4952+ %nvar |
4953+ %rnvar |
4954+ %atom |
4955+ %any-atom &
4956+ %flag |
4957+ %noun |
4958+ %empty |
4959+ %tag |
4960+ %const |
4961+ %union |((lien cases.t |=(c=itype (itype-has-any-atom c sub))) (lien args.t |=(c=itype (itype-has-any-atom c sub))))
4962+ %recursive |
4963+ %jrec |
4964+ %grec (lien args.t |=(c=itype (itype-has-any-atom c sub)))
4965+ %collection (lien args.t |=(c=itype (itype-has-any-atom c sub)))
4966+ %face $(t body.t)
4967+ %fn |($(t sample.t) $(t product.t))
4968+ %cell |($(t hed.t) $(t tal.t))
4969+ ==
4970+::
4971+::
4972+:: Hoon aura families are textual prefixes: @tD is in @t, and @uvJ
4973+:: is in @uv and @u. Jibb permits widening toward the prefix only.
4974+::
4975+++ aura-prefix
4976+ |= [parent=@ta child=@ta]
4977+ ^- ?
4978+ =/ a=tape (trip parent)
4979+ =/ b=tape (trip child)
4980+ |-
4981+ ?~ a &
4982+ ?~ b |
4983+ ?. =(i.a i.b) |
4984+ $(a t.a, b t.b)
4985+::
4986+:: Related auras in a structural unification need a common-type rule;
4987+:: until that rule is implemented, report an unknown rather than error.
4988+::
4989+++ itype-family-related-collection-args
4990+ |= [as=(list itype) bs=(list itype) sub=isub]
4991+ ^- ?
4992+ ?~ as |
4993+ ?~ bs |
4994+ ?: (itype-family-related i.as i.bs sub) &
4995+ $(as t.as, bs t.bs)
4996+::
4997+++ itype-family-related
4998+ |= [a=itype b=itype sub=isub]
4999+ ^- ?
5000+ =. a (itype-walk a sub)
5001+ =. b (itype-walk b sub)
5002+ ?: &(?=(%atom -.a) ?=(%atom -.b))
5003+ ?. !=(aura.a aura.b) |
5004+ |((aura-prefix aura.a aura.b) (aura-prefix aura.b aura.a))
5005+ ?: &(?=(%collection -.a) ?=(%collection -.b))
5006+ ?. =(name.a name.b) |
5007+ (itype-family-related-collection-args args.a args.b sub)
5008+ ?: &(?=(%face -.a) ?=(%face -.b))
5009+ ?. =(name.a name.b) |
5010+ $(a body.a, b body.b)
5011+ ?: &(?=(%cell -.a) ?=(%cell -.b))
5012+ |($(a hed.a, b hed.b) $(a tal.a, b tal.b))
5013+ ?: &(?=(%fn -.a) ?=(%fn -.b))
5014+ |($(a sample.a, b sample.b) $(a product.a, b product.b))
5015+ |
5016+::
5017+:: A branch whose two result types are already concrete can use an
5018+:: explicitly present parent aura (or @) as its result. This does not
5019+:: guess a parent for sibling auras or solve variable-dependent joins.
5020+::
5021+++ itype-has-fixed-atom
5022+ |= typ=itype
5023+ ^- ?
5024+ ?- -.typ
5025+ %var |
5026+ %avar |
5027+ %rvar |
5028+ %nvar |
5029+ %rnvar |
5030+ %atom &
5031+ %any-atom &
5032+ %flag &
5033+ %noun |
5034+ %empty |
5035+ %tag &
5036+ %const &
5037+ %union |((lien cases.typ |=(c=itype (itype-has-fixed-atom c))) (lien args.typ |=(c=itype (itype-has-fixed-atom c))))
5038+ %recursive |
5039+ %jrec |
5040+ %grec (lien args.typ |=(c=itype (itype-has-fixed-atom c)))
5041+ %collection (lien args.typ |=(c=itype (itype-has-fixed-atom c)))
5042+ %face $(typ body.typ)
5043+ %fn |($(typ sample.typ) $(typ product.typ))
5044+ %cell |($(typ hed.typ) $(typ tal.typ))
5045+ ==
5046+::
5047+++ itype-concrete-join
5048+ |= [a=itype b=itype sub=isub]
5049+ ^- (unit itype)
5050+ =. a (itype-walk a sub)
5051+ =. b (itype-walk b sub)
5052+ ?: &(?=(%atom -.a) ?=(%atom -.b))
5053+ ?: (aura-prefix aura.a aura.b) `a
5054+ ?: (aura-prefix aura.b aura.a) `b
5055+ ~
5056+ ?: &(?=(%any-atom -.a) |(?=(%atom -.b) ?=(%flag -.b))) `a
5057+ ?: &(?=(%any-atom -.b) |(?=(%atom -.a) ?=(%flag -.a))) `b
5058+ ~
5059+::
5060+:: Unifying an already-bound tuple with a faced position would need to
5061+:: update the bound type. Until substitutions can retain that information,
5062+:: variable-dependent face merges stay unresolved.
5063+::
5064+++ itype-has-face
5065+ |= [t=itype sub=isub]
5066+ ^- ?
5067+ =. t (itype-walk t sub)
5068+ ?- -.t
5069+ %grec (lien args.t |=(c=itype (itype-has-face c sub)))
5070+ %collection (lien args.t |=(c=itype (itype-has-face c sub)))
5071+ %face &
5072+ %cell |($(t hed.t) $(t tal.t))
5073+ %fn |($(t sample.t) $(t product.t))
5074+ * |
5075+ ==
5076+::
5077+:: Closed function samples may omit a slot face, but a known name must
5078+:: match another known name. Keep nested value faces and require exact
5079+:: invariant compatibility; a faced tail against a cell is ambiguous.
5080+++ itype-closed-slot-match
5081+ |= [a=itype b=itype]
5082+ ^- ?
5083+ ?: &(?=(%face -.a) ?=(%face -.b))
5084+ ?. =(name.a name.b) |
5085+ ?=(^ (itype-unify body.a body.b ~))
5086+ ?: ?=(%face -.a) ?=(^ (itype-unify body.a b ~))
5087+ ?: ?=(%face -.b) ?=(^ (itype-unify a body.b ~))
5088+ ?=(^ (itype-unify a b ~))
5089+++ itype-closed-sample-match
5090+ |= [a=itype b=itype fuel=@ud]
5091+ ^- ?
5092+ ?: =(0 fuel) |
5093+ ?. &(?=(%cell -.a) ?=(%cell -.b)) |
5094+ ?. (itype-closed-slot-match hed.a hed.b) |
5095+ =/ x=itype tal.a
5096+ =/ y=itype tal.b
5097+ ?: &(?=(%cell -.x) ?=(%cell -.y))
5098+ ?=(^ (itype-unify x y ~))
5099+ ?: |(&(?=(%face -.x) ?=(%cell -.y)) &(?=(%cell -.x) ?=(%face -.y))) |
5100+ (itype-closed-slot-match x y)
5101+++ itype-closed-gates-match
5102+ |= [a=itype b=itype]
5103+ ^- ?
5104+ ?. &(?=(%fn -.a) ?=(%fn -.b)) |
5105+ ?. &(?=(%cell -.sample.a) ?=(%cell -.sample.b)) |
5106+ ?. =(product.a product.b) |
5107+ ?^ (itype-vars a) |
5108+ ?^ (itype-vars b) |
5109+ ?: |((itype-has-tag a) (itype-has-tag b)) |
5110+ ?. (itype-closed-sample-match sample.a sample.b 1.024) |
5111+ ?=(^ (itype-unify product.a product.b ~))
5112+::
5113+++ itype-face-asym-collection-args
5114+ |= [as=(list itype) bs=(list itype) sub=isub]
5115+ ^- ?
5116+ ?~ as |
5117+ ?~ bs |
5118+ ?: (itype-face-asym i.as i.bs sub) &
5119+ $(as t.as, bs t.bs)
5120+::
5121+++ itype-face-asym
5122+ |= [a=itype b=itype sub=isub]
5123+ ^- ?
5124+ =. a (itype-walk a sub)
5125+ =. b (itype-walk b sub)
5126+ ?: &(?=(%grec -.a) ?=(%grec -.b))
5127+ ?. &(=(at.a at.b) =(name.a name.b)) |
5128+ (itype-face-asym-collection-args args.a args.b sub)
5129+ ?: &(?=(%collection -.a) ?=(%collection -.b))
5130+ ?. =(name.a name.b) |
5131+ (itype-face-asym-collection-args args.a args.b sub)
5132+ ?: &(?=(%face -.a) ?=(%face -.b)) $(a body.a, b body.b)
5133+ ?: ?=(%face -.a) !|(?=(%var -.b) ?=(%avar -.b) ?=(%rvar -.b) |(?=(%nvar -.b) ?=(%rnvar -.b)))
5134+ ?: ?=(%face -.b) !|(?=(%var -.a) ?=(%avar -.a) ?=(%rvar -.a) |(?=(%nvar -.a) ?=(%rnvar -.a)))
5135+ ?: &(?=(%cell -.a) ?=(%cell -.b)) |($(a hed.a, b hed.b) $(a tal.a, b tal.b))
5136+ ?: &(?=(%fn -.a) ?=(%fn -.b)) |($(a sample.a, b sample.b) $(a product.a, b product.b))
5137+ |
5138+::
5139+:: A successful cast keeps any explicit faces from either side while
5140+:: retaining the target's aura choices. Both faces have already matched.
5141+::
5142+++ itype-merge-faces
5143+ |= [actual=itype expected=itype sub=isub]
5144+ ^- itype
5145+ =. actual (itype-walk actual sub)
5146+ =. expected (itype-walk expected sub)
5147+ ?: &(?=(%face -.actual) ?=(%face -.expected))
5148+ [%face name.expected $(actual body.actual, expected body.expected)]
5149+ ?: ?=(%face -.actual)
5150+ [%face name.actual $(actual body.actual)]
5151+ ?: ?=(%face -.expected)
5152+ [%face name.expected $(expected body.expected)]
5153+ ?: &(?=(%cell -.actual) ?=(%cell -.expected))
5154+ [%cell $(actual hed.actual, expected hed.expected) $(actual tal.actual, expected tal.expected)]
5155+ expected
5156+::
5157+:: Positional call arguments do not write the sample's enclosing field
5158+:: labels. Ignore one raw sample-slot face per written argument while
5159+:: checking value faces as usual. An unknown or variable-bound cell spine
5160+:: cannot justify this distinction, so keep the existing conservative guard.
5161+++ itype-positional-slot-face-asym
5162+ |= [actual=itype expected=itype sub=isub]
5163+ ^- ?
5164+ ?: &(?=(%fn -.actual) ?=(%fn -.expected) (itype-closed-gates-match actual expected)) |
5165+ (itype-face-asym actual expected sub)
5166+::
5167+++ itype-positional-face-asym
5168+ |= [args=(list expr) actual=itype expected=itype sub=isub]
5169+ ^- ?
5170+ ?~ args &
5171+ ?~ t.args
5172+ =/ slot=itype expected
5173+ =? slot ?=(%face -.slot) body.slot
5174+ (itype-positional-slot-face-asym actual slot sub)
5175+ ?. &(?=(%cell -.actual) ?=(%cell -.expected)) &
5176+ =/ slot=itype hed.expected
5177+ =? slot ?=(%face -.slot) body.slot
5178+ ?: (itype-positional-slot-face-asym hed.actual slot sub) &
5179+ $(args t.args, actual tal.actual, expected tal.expected)
5180+::
5181+++ itype-output-may-be-cell
5182+ |= [t=itype sub=isub]
5183+ ^- ?
5184+ =. t (itype-walk t sub)
5185+ ?- -.t
5186+ %var &
5187+ %cell &
5188+ %union &
5189+ %recursive &
5190+ %jrec &
5191+ %grec &
5192+ %noun &
5193+ %collection &
5194+ %face $(t body.t)
5195+ %fn |($(t sample.t) $(t product.t))
5196+ * |
5197+ ==
5198+::
5199+++ pending-tags
5200+ |= [tags=(list ipending) sub=isub]
5201+ ^- ?
5202+ ?~ tags |
5203+ ?~ (itype-lookup id.i.tags sub) &
5204+ $(tags t.tags)
5205+::
5206+++ pending-null
5207+ |= [tags=(list ipending) sub=isub]
5208+ ^- ?
5209+ ?~ tags |
5210+ ?: &(?=(%null form.literal.i.tags) ?=(~ (itype-lookup id.i.tags sub))) &
5211+ $(tags t.tags)
5212+::
5213+:: Tags remain constrained until a mold selects a case or permitted atom
5214+:: type. Never generalize an unresolved tag through aliases or cells.
5215+::
5216+++ itype-has-tag
5217+ |= t=itype
5218+ ^- ?
5219+ ?- -.t
5220+ %tag &
5221+ %grec (lien args.t |=(c=itype (itype-has-tag c)))
5222+ %collection (lien args.t |=(c=itype (itype-has-tag c)))
5223+ %face $(t body.t)
5224+ %fn |($(t sample.t) $(t product.t))
5225+ %cell |($(t hed.t) $(t tal.t))
5226+ %union |((lien cases.t |=(c=itype (itype-has-tag c))) (lien args.t |=(c=itype (itype-has-tag c))))
5227+ * |
5228+ ==
5229+::
5230+++ itype-has-union
5231+ |= t=itype
5232+ ^- ?
5233+ ?- -.t
5234+ %union &
5235+ %grec (lien args.t |=(c=itype (itype-has-union c)))
5236+ %collection (lien args.t |=(c=itype (itype-has-union c)))
5237+ %face $(t body.t)
5238+ %fn |($(t sample.t) $(t product.t))
5239+ %cell |($(t hed.t) $(t tal.t))
5240+ * |
5241+ ==
5242+::
5243+:: Until a visible generic alias can be selected, expanding a named
5244+:: generic union would hide phantom arguments and its origin. This is a
5245+:: limitation of partial inference, not the unnamed-union print notation.
5246+::
5247+++ itype-has-hidden-generic
5248+ |= t=itype
5249+ ^- ?
5250+ ?- -.t
5251+ %union
5252+ ?: &(?=(~ label.t) ?=(^ args.t)) &
5253+ (lien (weld args.t cases.t) |=(c=itype (itype-has-hidden-generic c)))
5254+ %grec |(?=(~ label.t) (lien args.t |=(c=itype (itype-has-hidden-generic c))))
5255+ %collection (lien args.t |=(c=itype (itype-has-hidden-generic c)))
5256+ %face $(t body.t)
5257+ %fn |($(t sample.t) $(t product.t))
5258+ %cell |($(t hed.t) $(t tal.t))
5259+ * |
5260+ ==
5261+::
5262+++ itype-has-recursive
5263+ |= t=itype
5264+ ^- ?
5265+ ?- -.t
5266+ %recursive &
5267+ %jrec &
5268+ %grec &
5269+ %collection (lien args.t |=(c=itype (itype-has-recursive c)))
5270+ %union (lien (weld args.t cases.t) |=(c=itype (itype-has-recursive c)))
5271+ %face $(t body.t)
5272+ %cell |($(t hed.t) $(t tal.t))
5273+ %fn |($(t sample.t) $(t product.t))
5274+ * |
5275+ ==
5276+::
5277+++ itype-has-hidden-recursive
5278+ |= t=itype
5279+ ^- ?
5280+ ?- -.t
5281+ %recursive ?=(~ label.t)
5282+ %jrec ?=(~ label.t)
5283+ %grec |(?=(~ label.t) (lien args.t |=(c=itype (itype-has-hidden-recursive c))))
5284+ %collection (lien args.t |=(c=itype (itype-has-hidden-recursive c)))
5285+ %union (lien (weld args.t cases.t) |=(c=itype (itype-has-hidden-recursive c)))
5286+ %face $(t body.t)
5287+ %cell |($(t hed.t) $(t tal.t))
5288+ %fn |($(t sample.t) $(t product.t))
5289+ * |
5290+ ==
5291+::
5292+++ itype-fit-cases
5293+ |= [actual=itype cases=(list itype) sub=isub next=@ud]
5294+ ^- ifit
5295+ =/ good=(unit ifit) ~
5296+ =/ pending=? |
5297+ |-
5298+ ?~ cases
5299+ ?: pending [%unknown ~]
5300+ ?~ good [%bad ~]
5301+ u.good
5302+ =/ trial=ifit (itype-fit actual i.cases sub next)
5303+ ?- -.trial
5304+ %unknown $(cases t.cases, pending &)
5305+ %bad $(cases t.cases)
5306+ %ok
5307+ ?^ good [%unknown ~]
5308+ $(cases t.cases, good `trial)
5309+ ==
5310+::
5311+:: A constructor needs a case whose head has the same literal noun as its
5312+:: tag. An unresolved or opaque case may reveal one later, so it cannot
5313+:: prove a mismatch or a unique match. A broad atom mold is not a case.
5314+::
5315+++ itype-fit-ctor-cases
5316+ |= [tag=lit sample=itype cases=(list itype) sub=isub next=@ud]
5317+ ^- ifit
5318+ =/ found=(unit ifit) ~
5319+ =/ pending=? |
5320+ |-
5321+ ?~ cases
5322+ ?: pending [%unknown ~]
5323+ ?~ found [%bad ~]
5324+ u.found
5325+ =/ raw=itype i.cases
5326+ ?: ?=(%var -.raw)
5327+ $(cases t.cases, pending &)
5328+ =/ c=itype (itype-walk raw sub)
5329+ ?: ?=(?(%var %tag %recursive %jrec %grec %union %face) -.c)
5330+ $(cases t.cases, pending &)
5331+ ?. ?=(%cell -.c) $(cases t.cases)
5332+ =/ raw-head=itype hed.c
5333+ ?: ?=(%var -.raw-head)
5334+ $(cases t.cases, pending &)
5335+ =/ head=itype (itype-walk raw-head sub)
5336+ :: A single faced, explicitly atom-only head cannot be the tag case.
5337+ :: Do not follow variables or peel nested faces for this negative proof.
5338+ ?: ?=(%face -.head)
5339+ ?: ?=(?(%atom %any-atom %flag %avar %rvar %nvar %rnvar) -.body.head)
5340+ $(cases t.cases)
5341+ $(cases t.cases, pending &)
5342+ ?: ?=(?(%var %tag %recursive %jrec %grec %union) -.head)
5343+ $(cases t.cases, pending &)
5344+ ?. ?=(%const -.head) $(cases t.cases)
5345+ ?. =(val.literal.head val.tag) $(cases t.cases)
5346+ :: Equal heads can have disjoint payloads. Test each from the original
5347+ :: substitution; a unique success is usable only with no unknown rival.
5348+ =/ trial=ifit (itype-fit sample tal.c sub next)
5349+ ?- -.trial
5350+ %bad $(cases t.cases)
5351+ %unknown $(cases t.cases, pending &)
5352+ %ok
5353+ ?^ found [%unknown ~]
5354+ $(cases t.cases, found `trial)
5355+ ==
5356+::
5357+++ itype-fit
5358+ |= [actual=itype expected=itype sub=isub next=@ud]
5359+ ^- ifit
5360+ =/ result=ifit (itype-fit-inner actual expected sub next | |)
5361+ ?: ?=(%ok -.result) result
5362+ =/ source=itype (itype-walk actual sub)
5363+ ?. ?=(?(%empty %face %cell %union) -.source) result
5364+ =/ empty=(unit [empty=? left=@ud]) (itype-empty-proof actual sub 256)
5365+ ?~ empty [%unknown ~]
5366+ ?: empty.u.empty [%ok sub next]
5367+ result
5368+++ itype-fit-inner
5369+ |= [actual=itype expected=itype sub=isub next=@ud skip-width=? spine-proof=?]
5370+ ^- ifit
5371+ ?: &(!skip-width ?=(%cell -.actual) ?=(%cell -.expected) |((width-spine-exhausted actual 1.024) (width-spine-exhausted expected 1.024)))
5372+ [%unknown ~]
5373+ =/ known=(unit [source=iwfields target=iwfields])
5374+ ?: skip-width ~
5375+ (width-known-shape actual expected sub)
5376+ =/ too-wide=? ?~(known | (gth (lent order.source.u.known) (lent order.target.u.known)))
5377+ ?: too-wide [%unknown ~]
5378+ =/ spine-checked=? |(spine-proof ?=(^ known))
5379+ =/ uncertain=?
5380+ |(?=(%var -.actual) ?=(%avar -.actual) ?=(%rvar -.actual) |(?=(%nvar -.actual) ?=(%rnvar -.actual)) ?=(%var -.expected) ?=(%avar -.expected) ?=(%rvar -.expected) |(?=(%nvar -.expected) ?=(%rnvar -.expected)))
5381+ =/ actual-open=?
5382+ |(?=(%var -.actual) ?=(%avar -.actual) ?=(%rvar -.actual) |(?=(%nvar -.actual) ?=(%rnvar -.actual)))
5383+ =. actual (itype-walk actual sub)
5384+ =. expected (itype-walk expected sub)
5385+ ?: =(actual expected) [%ok sub next]
5386+ ?: &(?=(%empty -.expected) |(?=(%cell -.actual) ?=(%face -.actual) ?=(%union -.actual) ?=(%grec -.actual) ?=(%recursive -.actual))) [%unknown ~]
5387+ :: The relation of the source loobean mold to explicit @f is not yet
5388+ :: established. Keep it unsupported rather than asserting a mismatch.
5389+ ?: &(?=(%flag -.actual) ?=(%atom -.expected) =(%f aura.expected)) [%unknown ~]
5390+ :: Any value can be used where a noun is expected. An unresolved
5391+ :: bare tag is fixed as a constant; a constructor still needs a gate.
5392+ ?: ?=(%noun -.expected)
5393+ ?: ?=(%tag -.actual)
5394+ ?: constructor.actual [%unknown ~]
5395+ [%ok [[id.actual expected] sub] next]
5396+ [%ok sub next]
5397+ :: An arbitrary noun is not known to fit a narrower type.
5398+ ?: &(?=(%noun -.actual) !?=(%var -.expected)) [%unknown ~]
5399+ ?: &(!uncertain ?=(%grec -.actual) ?=(%face -.expected)) $(expected body.expected)
5400+ ?: &(!uncertain ?=(%face -.actual) ?=(%grec -.expected)) $(actual body.actual)
5401+ ?: &(?=(%grec -.actual) ?=(%grec -.expected))
5402+ ?. &(=(at.actual at.expected) =(name.actual name.expected)) [%unknown ~]
5403+ =/ matched=(unit isub) (itype-unify-args args.actual args.expected sub)
5404+ ?~ matched [%unknown ~]
5405+ [%ok u.matched next]
5406+ ?: &(|(?=(%grec -.actual) ?=(%grec -.expected)) !|(?=(%var -.actual) ?=(%var -.expected))) [%unknown ~]
5407+ ?: &(!uncertain ?=(%jrec -.actual) ?=(%face -.expected)) $(expected body.expected)
5408+ ?: &(!uncertain ?=(%face -.actual) ?=(%jrec -.expected)) $(actual body.actual)
5409+ ?: &(?=(%jrec -.actual) ?=(%jrec -.expected))
5410+ ?:(&(=(at.actual at.expected) =(name.actual name.expected) =(head.actual head.expected) =(aura.actual aura.expected) =(tail.actual tail.expected)) [%ok sub next] [%bad ~])
5411+ ?: &(|(?=(%jrec -.actual) ?=(%jrec -.expected)) !|(?=(%var -.actual) ?=(%var -.expected))) [%unknown ~]
5412+ ?: &(?=(%recursive -.actual) ?=(%recursive -.expected))
5413+ ?:(&(=(module.actual module.expected) =(name.actual name.expected)) [%ok sub next] [%bad ~])
5414+ ?: &(|(?=(%recursive -.actual) ?=(%recursive -.expected)) !|(?=(%var -.actual) ?=(%var -.expected))) [%unknown ~]
5415+ ?: &(?=(%union -.actual) ?=(%union -.expected))
5416+ ?. =(origin.actual origin.expected) [%unknown ~]
5417+ ?: &(?=(~ args.actual) ?=(~ args.expected))
5418+ ?:(=(cases.actual cases.expected) [%ok sub next] [%unknown ~])
5419+ ?~ origin.actual [%unknown ~]
5420+ =/ unified=(unit isub) (itype-unify-args args.actual args.expected sub)
5421+ ?^ unified [%ok u.unified next]
5422+ [%unknown ~]
5423+ :: A known union can instantiate an unconstrained sample directly;
5424+ :: preserve unknown results for variable-bound union origins.
5425+ ?: &(!actual-open ?=(%union -.actual) ?=(%var -.expected))
5426+ ?~ origin.actual [%unknown ~]
5427+ =/ normalized=itype (itype-normalize actual sub)
5428+ ?: |((itype-has-tag normalized) (itype-has-recursive normalized) (itype-has-any-atom actual sub)) [%unknown ~]
5429+ =/ unified=(unit isub) (itype-unify actual expected sub)
5430+ ?~ unified [%unknown ~]
5431+ [%ok u.unified next]
5432+ :: A concrete union value in a tuple may acquire the expected field's
5433+ :: face. A variable-bound union still needs face propagation support.
5434+ ?: &(!uncertain ?=(%union -.actual) ?=(%face -.expected))
5435+ $(expected body.expected)
5436+ ?: ?=(%union -.actual) [%unknown ~]
5437+ ?: &(?=(%union -.expected) |(?=(%avar -.actual) ?=(%rvar -.actual) |(?=(%nvar -.actual) ?=(%rnvar -.actual)))) [%unknown ~]
5438+ ?: &(?=(%union -.expected) !?=(%var -.actual))
5439+ (itype-fit-cases actual cases.expected sub next)
5440+ ?: ?=(%tag -.actual)
5441+ ?: ?=(%var -.expected)
5442+ =/ u=(unit isub) (itype-unify actual expected sub)
5443+ ?~ u [%bad ~]
5444+ [%ok u.u next]
5445+ ?: |(?=(%avar -.expected) ?=(%rvar -.expected) |(?=(%nvar -.expected) ?=(%rnvar -.expected))) [%unknown ~]
5446+ ?: ?=(%face -.expected) $(expected body.expected)
5447+ ?: constructor.actual
5448+ ?. ?=(%fn -.expected) [%bad ~]
5449+ =/ product=itype (itype-walk product.expected sub)
5450+ =/ cases=(list itype) ?:(?=(%union -.product) cases.product ~[product])
5451+ =/ trial=ifit (itype-fit-ctor-cases literal.actual sample.expected cases sub next)
5452+ ?. ?=(%ok -.trial) trial
5453+ [%ok [[id.actual expected] sub.trial] next.trial]
5454+ :: Zero may be the empty list. A nested cell fit lacks the context
5455+ :: needed to resolve it here, so do not report a definite mismatch.
5456+ ?: &(?=(%collection -.expected) =(%list name.expected) =(0 val.literal.actual))
5457+ [%unknown ~]
5458+ ?: ?=(%const -.expected)
5459+ ?:(=(val.literal.actual val.literal.expected) [%ok [[id.actual expected] sub] next] [%bad ~])
5460+ ?: ?=(%atom -.expected)
5461+ ?: |(=(%tas aura.expected) =(%ta aura.expected))
5462+ [%ok [[id.actual expected] sub] next]
5463+ [%bad ~]
5464+ ?: ?=(%flag -.expected)
5465+ ?:(|(=(0 val.literal.actual) =(1 val.literal.actual)) [%ok [[id.actual expected] sub] next] [%bad ~])
5466+ ?: ?=(%any-atom -.expected) [%ok [[id.actual expected] sub] next]
5467+ [%bad ~]
5468+ ?: ?=(%const -.actual)
5469+ ?: ?=(%var -.expected)
5470+ =/ u=(unit isub) (itype-unify actual expected sub)
5471+ ?~ u [%bad ~]
5472+ [%ok u.u next]
5473+ ?: |(?=(%avar -.expected) ?=(%rvar -.expected) |(?=(%nvar -.expected) ?=(%rnvar -.expected))) [%unknown ~]
5474+ ?: ?=(%face -.expected) $(expected body.expected)
5475+ ?: &(?=(%collection -.expected) =(%list name.expected) =(0 val.literal.actual))
5476+ [%unknown ~]
5477+ ?: ?=(%const -.expected)
5478+ ?:(=(val.literal.actual val.literal.expected) [%ok sub next] [%bad ~])
5479+ ?: ?=(%atom -.expected)
5480+ :: A loobean singleton must not silently widen into another aura.
5481+ ?: =(%loobean form.literal.actual)
5482+ ?: =(%f aura.expected) [%unknown ~]
5483+ [%bad ~]
5484+ ?: |(=(%tas aura.expected) =(%ta aura.expected)) [%ok sub next]
5485+ [%bad ~]
5486+ ?: ?=(%flag -.expected)
5487+ ?:(|(=(0 val.literal.actual) =(1 val.literal.actual)) [%ok sub next] [%bad ~])
5488+ ?: ?=(%any-atom -.expected) [%ok sub next]
5489+ [%bad ~]
5490+ ?: &(uncertain (itype-face-asym actual expected sub)) [%unknown ~]
5491+ :: A known face labels the same noun. Peel it before applying the
5492+ :: directional unrestricted-atom rule, preserving raw-variable guards.
5493+ ?: &(!uncertain ?=(%any-atom -.actual) ?=(%face -.expected))
5494+ $(expected body.expected, skip-width |, spine-proof |)
5495+ ?: &(!uncertain ?=(%any-atom -.expected) ?=(%face -.actual))
5496+ $(actual body.actual, skip-width |, spine-proof |)
5497+ ?: ?=(%any-atom -.expected)
5498+ ?: |(?=(%atom -.actual) ?=(%avar -.actual) ?=(%rvar -.actual) |(?=(%nvar -.actual) ?=(%rnvar -.actual)) ?=(%flag -.actual)) [%ok sub next]
5499+ ?: ?=(%var -.actual)
5500+ =/ unified=(unit isub) (itype-unify actual [%avar next] sub)
5501+ ?~ unified [%bad ~]
5502+ [%ok u.unified +(next)]
5503+ [%bad ~]
5504+ ?: ?=(%any-atom -.actual)
5505+ ?: ?=(%var -.expected)
5506+ =/ unified=(unit isub) (itype-unify actual expected sub)
5507+ ?~ unified [%bad ~]
5508+ [%ok u.unified next]
5509+ ?: |(?=(%avar -.expected) ?=(%rvar -.expected) |(?=(%nvar -.expected) ?=(%rnvar -.expected))) [%unknown ~]
5510+ [%bad ~]
5511+ ?: &(?=(%atom -.actual) ?=(%atom -.expected))
5512+ ?: (aura-prefix aura.expected aura.actual) [%ok sub next]
5513+ ?: &((aura-prefix aura.actual aura.expected) uncertain) [%unknown ~]
5514+ [%bad ~]
5515+ ?: &(?=(%cell -.actual) ?=(%cell -.expected))
5516+ =/ first=ifit $(actual hed.actual, expected hed.expected, skip-width |, spine-proof |)
5517+ ?. ?=(%ok -.first) first
5518+ $(actual tal.actual, expected tal.expected, sub sub.first, next next.first, skip-width spine-checked, spine-proof spine-checked)
5519+ :: A field may add a face to an occurrence of the very same type
5520+ :: variable. Binding that variable to a face around itself would fail
5521+ :: the occurs check, but its underlying type has already matched.
5522+ ?: &(?=(%var -.actual) ?=(%face -.expected) =(actual (itype-walk body.expected sub)))
5523+ [%ok sub next]
5524+ :: Differing variables and faces need propagation that is not yet
5525+ :: represented. Binding one to the face can create a false mismatch.
5526+ ?: &(?=(%var -.actual) ?=(%face -.expected)) [%unknown ~]
5527+ ?: &(?=(%face -.actual) ?=(%var -.expected)) [%unknown ~]
5528+ ?: &(?=(%var -.actual) (itype-has-any-atom expected sub))
5529+ [%unknown ~]
5530+ ?: |(?=(%var -.actual) ?=(%var -.expected))
5531+ =/ unified=(unit isub) (itype-unify actual expected sub)
5532+ ?~ unified
5533+ ?: |(?=(%face -.actual) ?=(%face -.expected)) [%unknown ~]
5534+ ?: |((itype-has-recursive (itype-normalize actual sub)) (itype-has-recursive (itype-normalize expected sub))) [%unknown ~]
5535+ ?: (itype-family-related actual expected sub) [%unknown ~]
5536+ [%bad ~]
5537+ [%ok u.unified next]
5538+ ?: &(?=(%face -.actual) ?=(%face -.expected))
5539+ ?. =(name.actual name.expected) [%bad ~]
5540+ $(actual body.actual, expected body.expected, skip-width |, spine-proof |)
5541+ ?: ?=(%face -.actual) $(actual body.actual, skip-width |, spine-proof |)
5542+ ?: ?=(%face -.expected) $(expected body.expected, skip-width |, spine-proof |)
5543+ ?: &(!uncertain (itype-closed-gates-match actual expected)) [%ok sub next]
5544+ ?: (itype-face-asym actual expected sub) [%unknown ~]
5545+ ?: |((itype-has-any-atom actual sub) (itype-has-any-atom expected sub))
5546+ [%unknown ~]
5547+ =/ unified=(unit isub) (itype-unify actual expected sub)
5548+ ?~ unified
5549+ ?: |((itype-has-union (itype-normalize actual sub)) (itype-has-union (itype-normalize expected sub))) [%unknown ~]
5550+ ?: |((itype-has-recursive (itype-normalize actual sub)) (itype-has-recursive (itype-normalize expected sub))) [%unknown ~]
5551+ ?: (itype-family-related actual expected sub) [%unknown ~]
5552+ [%bad ~]
5553+ [%ok u.unified next]
5554+::
5555+++ itype-unify-test
5556+ ^- (list tape)
5557+ =/ a=itype [%var 0]
5558+ =/ b=itype [%var 1]
5559+ =/ txt=itype [%atom %t]
5560+ =/ num=itype [%atom %ud]
5561+ =/ same=itype [%fn a a]
5562+ =/ mismatch=itype [%fn txt num]
5563+ =/ fine=itype [%fn txt txt]
5564+ =/ sub=(unit isub) (itype-unify a b ~)
5565+ ?~ sub ~["variables should unify"]
5566+ =/ sub2=(unit isub) (itype-unify b txt u.sub)
5567+ ?~ sub2 ~["a chained variable should unify"]
5568+ =/ problems=(list tape) ~
5569+ =? problems !=((itype-walk a u.sub2) txt)
5570+ ["substitutions should follow chains" problems]
5571+ =? problems ?=(^ (itype-unify txt num ~))
5572+ ["different concrete auras should conflict" problems]
5573+ =? problems ?=(^ (itype-unify a [%fn a txt] ~))
5574+ ["occurs check should reject an infinite type" problems]
5575+ =? problems ?=(^ (itype-unify same mismatch ~))
5576+ ["a shared type variable should reject incompatible arguments" problems]
5577+ =? problems ?=(~ (itype-unify same fine ~))
5578+ ["a shared type variable should accept equal arguments" problems]
5579+ =/ list-a=itype [%collection %list ~[a]]
5580+ =/ list-t=itype [%collection %list ~[txt]]
5581+ =/ list-n=itype [%collection %list ~[num]]
5582+ =? problems ?=(^ (itype-unify a list-a ~))
5583+ ["occurs check should look through collection arguments" problems]
5584+ =? problems !=((itype-vars list-a) ~[0])
5585+ ["generalization should see collection argument variables" problems]
5586+ =? problems !=((itype-rename list-a ~[[0 num]]) list-n)
5587+ ["instantiation should rename collection argument variables" problems]
5588+ =? problems ?=(^ (itype-unify list-t list-n ~))
5589+ ["collection arguments with different auras should conflict" problems]
5590+ =? problems ?=(^ (itype-unify list-t [%collection %unit ~[txt]] ~))
5591+ ["different collection names should conflict" problems]
5592+ =? problems !(itype-family-related list-t [%collection %list ~[[%atom 'tD']]] ~)
5593+ ["collection arguments should preserve aura-family uncertainty" problems]
5594+ =? problems !(itype-face-asym [%collection %list ~[[%face %x txt]]] list-t ~)
5595+ ["collection arguments should preserve face uncertainty" problems]
5596+ =/ recursive=itype [%recursive %fixture %chain `'chain.fixture']
5597+ =/ same-recursive=itype [%recursive %fixture %chain ~]
5598+ =/ other-recursive=itype [%recursive %other %chain `'chain.other']
5599+ =? problems ?=(~ (itype-unify recursive same-recursive ~))
5600+ ["recursive identity should not depend on its visible name" problems]
5601+ =? problems ?=(^ (itype-unify recursive other-recursive ~))
5602+ ["recursive identity should include the source module" problems]
5603+ =/ recursive-fit=ifit (itype-fit recursive txt ~ 0)
5604+ =? problems !?=(%unknown -.recursive-fit)
5605+ ["opaque recursive types should not be unfolded by a fit" problems]
5606+ =/ nested-fit=ifit
5607+ (itype-fit [%collection %list ~[a]] list-t ~[[0 recursive]] 1)
5608+ =? problems !?=(%unknown -.nested-fit)
5609+ ["recursive types behind substitutions should remain uncertain" problems]
5610+ problems
5611+::
5612+:: The expression inference below is deliberately a fragment: bindings,
5613+:: simple gates, calls, fixed-aura literals, and some interpolated strings. The
5614+:: result for unsupported syntax is a diagnostic, never a checked module.
5615+::
5616++$ ischeme [typ=itype vars=(list @ud)]
5617++$ ienv (list [name=term scheme=ischeme])
5618++$ imold-types (list [name=term template=ischeme])
5619++$ iderived [name=term agent=term mark=term]
5620++$ iwidth-definition [name=term original=expr typ=itype sub=isub projections=(list iwprojection)]
5621++$ iwidth-dependency [at=path source=(unit @t) definitions=(list iwidth-definition)]
5622+:: Nonrecursive request evidence is compiler-owned metadata, not a property
5623+:: of an arbitrary ask value. Reader graphs and source inputs are trusted.
5624++$ irequest-evidence
5625+ [api-at=path name=term path=iapi-path-typed api-source=@t public-source=@t internal-source=@t prelude-values=(list term) prelude-molds=(list term) externals=iexternals marks=imark-externals]
5626+:: A unit distinguishes a verified empty closure from a detached legacy file.
5627+:: The opaque prelude is an exact trusted input, not a recursive interface mold.
5628++$ irequest-graph
5629+ [paths=(set path) requests=(list irequest-evidence) bundle-input=* prelude-input=* prelude-values=(list term) prelude-molds=(list term) externals=iexternals marks=imark-externals]
5630++$ ifile [values=ienv molds=imold-types at=path derived=(list iderived) elaborations=(list iwidth-definition) dependencies=(list iwidth-dependency) source=(unit @t) graph=(unit irequest-graph)]
5631++$ ijimports (list [face=term interface=ifile])
5632++$ icap [name=@t id=@ud at=span]
5633++$ icaps (list icap)
5634++$ iparams (list [name=@t typ=itype])
5635++$ imolds (list [name=term body=shape])
5636+:: A caller supplies the exact noun returned by +read-mold:jibb-import.
5637+:: This core has no Ford dependencies; unrecognized payloads fail closed.
5638++$ iexternals (list [module=term name=term result=*])
5639++$ imark-externals (list [mark=term result=*])
5640+:: Hole obligations survive discarded expressions until their owning
5641+:: definition has inferred; their source spans support unresolved reports.
5642++$ ihole [id=@ud at=span]
5643+:: Recursive-mold unfolding spends fuel in the threaded inference state.
5644+:: Retries can restart from an earlier state, so this bounds an attempt,
5645+:: not all parsing or module-checking work.
5646+:: Experimental: only closed, uniquely faced records have known axes.
5647++$ iwfield [name=term axis=@ud typ=itype]
5648++$ iwfields [order=(list iwfield) index=(map term iwfield)]
5649++$ iwstep [name=term axis=@ud]
5650++$ iwidth-result [steps=(list iwstep) sub=isub next=@ud]
5651++$ iwprojection [at=span original=expr source=itype target=itype steps=(list iwstep)]
5652+++ width-scan
5653+ |= [typ=itype sub=isub axis=@ud fuel=@ud]
5654+ ^- (unit iwfields)
5655+ =/ order=(list iwfield) ~
5656+ =/ index=(map term iwfield) *(map term iwfield)
5657+ |-
5658+ ?: =(0 fuel) ~
5659+ ?: |(?=(%var -.typ) ?=(%avar -.typ) ?=(%rvar -.typ) ?=(%nvar -.typ) ?=(%rnvar -.typ)) ~
5660+ ?: ?=(%face -.typ)
5661+ =/ entry=iwfield [name.typ axis body.typ]
5662+ ?: ?=(^ (~(get by index) name.entry)) ~
5663+ `[(flop [entry order]) (~(put by index) name.entry entry)]
5664+ ?. ?=(%cell -.typ) ~
5665+ =/ head=itype hed.typ
5666+ ?: |(?=(%var -.head) ?=(%avar -.head) ?=(%rvar -.head) ?=(%nvar -.head) ?=(%rnvar -.head)) ~
5667+ ?. ?=(%face -.head) ~
5668+ =/ entry=iwfield [name.head (mul 2 axis) body.head]
5669+ ?: ?=(^ (~(get by index) name.entry)) ~
5670+ $(typ tal.typ, axis +((mul 2 axis)), fuel (dec fuel), order [entry order], index (~(put by index) name.entry entry))
5671+++ width-in-order
5672+ |= [source=(list iwfield) target=(list iwfield)]
5673+ ^- ?
5674+ ?~ target &
5675+ ?~ source |
5676+ ?: =(name.i.source name.i.target) $(source t.source, target t.target)
5677+ $(source t.source)
5678+++ width-fit-fields
5679+ |= [source=(map term iwfield) target=(list iwfield) sub=isub next=@ud]
5680+ ^- (unit iwidth-result)
5681+ ?~ target `[~ sub next]
5682+ =/ found=(unit iwfield) (~(get by source) name.i.target)
5683+ ?~ found ~
5684+ =/ fit=ifit (itype-fit typ.u.found typ.i.target sub next)
5685+ ?. ?=(%ok -.fit) ~
5686+ =/ rest=(unit iwidth-result) $(target t.target, sub sub.fit, next next.fit)
5687+ ?~ rest ~
5688+ `[[[name.i.target axis.u.found] steps.u.rest] sub.u.rest next.u.rest]
5689+++ width-spine-exhausted
5690+ |= [t=itype fuel=@ud]
5691+ ^- ?
5692+ ?: =(0 fuel) &
5693+ ?. ?=(%cell -.t) |
5694+ ?. ?=(%face -.hed.t) |
5695+ $(t tal.t, fuel (dec fuel))
5696+++ width-known-shape
5697+ |= [actual=itype expected=itype sub=isub]
5698+ ^- (unit [source=iwfields target=iwfields])
5699+ ?. &(?=(%cell -.actual) ?=(%cell -.expected)) ~
5700+ =/ source=(unit iwfields) (width-scan actual sub 1 1.024)
5701+ =/ target=(unit iwfields) (width-scan expected sub 1 1.024)
5702+ ?~ source ~
5703+ ?~ target ~
5704+ `[u.source u.target]
5705+::
5706+++ width-shape
5707+ |= [actual=itype expected=itype sub=isub]
5708+ ^- (unit [source=iwfields target=iwfields])
5709+ ?. &(?=(%cell -.actual) ?=(%cell -.expected)) ~
5710+ =/ source=(unit iwfields) (width-scan actual sub 1 4.096)
5711+ =/ target=(unit iwfields) (width-scan expected sub 1 4.096)
5712+ ?~ source ~
5713+ ?~ target ~
5714+ ?. (gth (lent order.u.source) (lent order.u.target)) ~
5715+ `[u.source u.target]
5716+++ width-proj-shape
5717+ |= [actual=itype expected=itype sub=isub]
5718+ ^- (unit [source=iwfields target=iwfields])
5719+ ?. &(|(?=(%cell -.actual) ?=(%face -.actual)) |(?=(%cell -.expected) ?=(%face -.expected))) ~
5720+ =/ source=(unit iwfields) (width-scan actual sub 1 4.096)
5721+ =/ target=(unit iwfields) (width-scan expected sub 1 4.096)
5722+ ?~ source ~
5723+ ?~ target ~
5724+ ?: (lth (lent order.u.source) (lent order.u.target)) ~
5725+ `[u.source u.target]
5726+::
5727+++ width-project
5728+ |= [shape=[source=iwfields target=iwfields] sub=isub next=@ud]
5729+ ^- (unit iwidth-result)
5730+ ?. (width-in-order order.source.shape order.target.shape) ~
5731+ (width-fit-fields index.source.shape order.target.shape sub next)
5732+::
5733+:: Provisional, globally budgeted gate-free proof. %no includes a
5734+:: gate-bearing witness; an uninhabited sibling could invalidate it.
5735+:: Input types must be resolved and normalized under valid substitutions,
5736+:: from trusted source-backed interfaces and reader results. Collection
5737+:: list/unit names rely on their existing identity invariant; this arm
5738+:: does not validate fabricated internal types.
5739++$ igf-segment
5740+ $% [%field name=term]
5741+ [%head ~]
5742+ [%tail ~]
5743+ [%item ~]
5744+ [%case index=@ud]
5745+ ==
5746++$ igate-free [verdict=?(%yes %no %unknown) inhabited=? left=@ud path=(unit (list igf-segment))]
5747+++ gate-free-types
5748+ |= [types=(list itype) fuel=@ud path=(list igf-segment) index=@ud]
5749+ ^- igate-free
5750+ ?~ types [%yes | fuel ~]
5751+ ?: =(0 fuel) [%unknown | 0 ~]
5752+ =/ first=igate-free (gate-free-type i.types fuel [[%case index] path])
5753+ ?: =(%no verdict.first) first
5754+ =/ rest=igate-free $(types t.types, fuel left.first, index +(index))
5755+ ?: =(%no verdict.rest) rest
5756+ =/ inhabited=? |(inhabited.first inhabited.rest)
5757+ ?: |(=(%unknown verdict.first) =(%unknown verdict.rest)) [%unknown inhabited left.rest ~]
5758+ [%yes inhabited left.rest ~]
5759+++ gate-free-type
5760+ |= [typ=itype fuel=@ud path=(list igf-segment)]
5761+ ^- igate-free
5762+ ?: =(0 fuel) [%unknown | 0 ~]
5763+ =. fuel (dec fuel)
5764+ ?- -.typ
5765+ %fn [%no & fuel `(flop path)]
5766+ %atom [%yes & fuel ~]
5767+ %any-atom [%yes & fuel ~]
5768+ %flag [%yes & fuel ~]
5769+ %const [%yes & fuel ~]
5770+ %face $(typ body.typ, path [[%field name.typ] path])
5771+ %cell
5772+ =/ head=igate-free $(typ hed.typ, path [[%head ~] path])
5773+ =/ tail=igate-free $(typ tal.typ, fuel left.head, path [[%tail ~] path])
5774+ =/ inhabited=? &(inhabited.head inhabited.tail)
5775+ ?: |(&(=(%yes verdict.head) !inhabited.head) &(=(%yes verdict.tail) !inhabited.tail)) [%yes | left.tail ~]
5776+ ?: &(=(%no verdict.head) inhabited.tail) head(left left.tail)
5777+ ?: &(=(%no verdict.tail) inhabited.head) tail
5778+ ?: |(!=(%yes verdict.head) !=(%yes verdict.tail)) [%unknown inhabited left.tail ~]
5779+ [%yes inhabited left.tail ~]
5780+ %collection
5781+ ?. |(=(%list name.typ) =(%unit name.typ)) [%unknown | fuel ~]
5782+ ?. ?=([* ~] args.typ) [%unknown | fuel ~]
5783+ =/ item=igate-free $(typ i.args.typ, path [[%item ~] path])
5784+ item(inhabited &)
5785+ %union
5786+ ?~ cases.typ [%unknown | fuel ~]
5787+ (gate-free-types cases.typ fuel path 0)
5788+ %noun [%unknown & fuel ~]
5789+ %empty [%yes | fuel ~]
5790+ %var [%unknown | fuel ~]
5791+ %avar [%yes & fuel ~]
5792+ %rvar [%yes & fuel ~]
5793+ %nvar [%yes & fuel ~]
5794+ %rnvar [%yes & fuel ~]
5795+ %tag [%unknown | fuel ~]
5796+ %recursive [%unknown | fuel ~]
5797+ %jrec [%yes & fuel ~]
5798+ %grec [%unknown | fuel ~]
5799+ ==
5800+::
5801++$ igate-prelude-evidence [iface=ifile gates=(map term def)]
5802++$ dgo [left=itype right=itype at=span context=span]
5803++$ istate [next=@ud sub=isub caps=icaps binders=(list @ud) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) params=iparams active=(list term) tags=(list ipending) in-mold=? at=path top-molds=(list term) prelude=(unit ifile) holes=(list ihole) jrec-fuel=@ud projections=(list iwprojection) gate-defs=(map term def) head-evidence=(unit igate-prelude-evidence) grec-index=(unit [at=path source=@t prelude=ifile shapes=(map term shape)]) defer=(unit ~) obligations=(list dgo)]
5804++$ idiag [msg=tape sites=(list [at=span note=tape])]
5805++$ iresult (each [typ=itype state=istate] idiag)
5806++$ isample-result (each [typ=itype env=ienv state=istate] tape)
5807+::
5808+++ ienv-lookup
5809+ |= [name=term env=ienv]
5810+ ^- (unit ischeme)
5811+ ?~ env ~
5812+ ?: =(name name.i.env) `scheme.i.env
5813+ $(env t.env)
5814+::
5815+:: Generalized variables are renamed freshly on each use. The renaming
5816+:: substitutes only once, so an old variable and its fresh number may
5817+:: coincide without forming a substitution cycle.
5818+::
5819+++ itype-normalize
5820+ |= [t=itype sub=isub]
5821+ ^- itype
5822+ =. t (itype-walk t sub)
5823+ ?: ?=(%grec -.t) t(args (turn args.t |=(c=itype (itype-normalize c sub))))
5824+ ?: ?=(%collection -.t) [%collection name.t (turn args.t |=(c=itype (itype-normalize c sub)))]
5825+ ?: ?=(%union -.t)
5826+ [%union (turn cases.t |=(c=itype (itype-normalize c sub))) origin.t label.t (turn args.t |=(c=itype (itype-normalize c sub)))]
5827+ ?: ?=(%face -.t)
5828+ [%face name.t $(t body.t)]
5829+ ?: ?=(%fn -.t)
5830+ [%fn $(t sample.t) $(t product.t)]
5831+ ?: ?=(%cell -.t)
5832+ [%cell $(t hed.t) $(t tal.t)]
5833+ t
5834+::
5835+::
5836+:: Default decimal variables only in types with no gates. A gate can
5837+:: generalize an aura from its sample, which requires constraint analysis
5838+:: beyond this fragment; leave those cases unresolved.
5839+::
5840+:: This helper only controls decimal defaulting in visible types. A noun
5841+:: may contain gates and is not proof of a gate-free value.
5842+++ itype-has-gate
5843+ |= t=itype
5844+ ^- ?
5845+ ?- -.t
5846+ %fn &
5847+ %cell |($(t hed.t) $(t tal.t))
5848+ %recursive |
5849+ %jrec |
5850+ %grec &
5851+ %collection (lien args.t |=(c=itype (itype-has-gate c)))
5852+ %face $(t body.t)
5853+ %union (lien cases.t |=(c=itype (itype-has-gate c)))
5854+ %tag |
5855+ %const |
5856+ %var |
5857+ %avar |
5858+ %rvar |
5859+ %nvar |
5860+ %rnvar |
5861+ %atom |
5862+ %any-atom |
5863+ %flag |
5864+ %noun |
5865+ %empty |
5866+ ==
5867+::
5868+++ default-decimals
5869+ |= t=itype
5870+ ^- itype
5871+ ?: (itype-has-gate t) t
5872+ ?- -.t
5873+ %nvar [%atom %ud]
5874+ %rnvar [%atom %ud]
5875+ %grec t(args (turn args.t |=(c=itype (default-decimals c))))
5876+ %collection [%collection name.t (turn args.t |=(c=itype (default-decimals c)))]
5877+ %face [%face name.t $(t body.t)]
5878+ %cell [%cell $(t hed.t) $(t tal.t)]
5879+ * t
5880+ ==
5881+::
5882+:: A hole is solved only by a fully determined type or a written
5883+:: in-scope type variable. Ordinary fresh variables are not evidence.
5884+:: Compare representatives after substitution, since unification can
5885+:: orient a written capital toward the hole rather than the reverse.
5886+++ hole-variable-id
5887+ |= t=itype
5888+ ^- (unit @ud)
5889+ ?- -.t
5890+ %var `id.t
5891+ %avar `id.t
5892+ %rvar `id.t
5893+ %nvar `id.t
5894+ %rnvar `id.t
5895+ %tag `id.t
5896+ * ~
5897+ ==
5898+++ hole-same-variable
5899+ |= [a=itype b=itype]
5900+ ^- ?
5901+ =/ x=(unit @ud) (hole-variable-id a)
5902+ ?~ x |
5903+ =/ y=(unit @ud) (hole-variable-id b)
5904+ ?~ y |
5905+ =(u.x u.y)
5906+++ hole-known
5907+ |= [t=itype state=istate]
5908+ ^- ?
5909+ =. t (itype-walk t sub.state)
5910+ ?- -.t
5911+ ?(%var %avar %rvar %nvar %rnvar)
5912+ ?: (lien caps.state |=(c=icap (hole-same-variable t (itype-walk [%var id.c] sub.state)))) &
5913+ (lien params.state |=(p=[name=@t typ=itype] (hole-same-variable t (itype-walk typ.p sub.state))))
5914+ %tag |
5915+ %any-atom &
5916+ %union &((levy cases.t |=(c=itype (hole-known c state))) (levy args.t |=(c=itype (hole-known c state))))
5917+ %grec (levy args.t |=(c=itype (hole-known c state)))
5918+ %collection (levy args.t |=(c=itype (hole-known c state)))
5919+ %face $(t body.t)
5920+ %fn &($(t sample.t) $(t product.t))
5921+ %cell &($(t hed.t) $(t tal.t))
5922+ * &
5923+ ==
5924+++ promote-restricted-numbers
5925+ |= [state=istate env=ienv]
5926+ ^- istate
5927+ :: With no written capitals, there is nothing to promote.
5928+ ?~ caps.state state
5929+ =/ ids=(list @ud) (turn caps.state |=(c=icap id.c))
5930+ =/ free=(list @ud) (free-env-vars env sub.state)
5931+ |-
5932+ ?~ ids state
5933+ =/ t=itype (itype-walk [%var i.ids] sub.state)
5934+ ?: &(?=(%rnvar -.t) !(lien free |=(n=@ud =(n +.t))))
5935+ $(ids t.ids, state state(sub [[+.t [%rvar +.t]] sub.state]))
5936+ $(ids t.ids)
5937+::
5938+++ default-hole-numbers
5939+ |= [all=(list ihole) prior=(list ihole) state=istate env=ienv permit=?]
5940+ ^- istate
5941+ :: Do not default a named capital or a variable captured from env.
5942+ ?. permit state
5943+ ?: =(all prior) state
5944+ ?~ all state
5945+ =/ t=itype (itype-walk [%var id.i.all] sub.state)
5946+ =/ free=(list @ud) (free-env-vars env sub.state)
5947+ =? state &(?=(?(%nvar %rnvar) -.t) !(hole-known t state) !(lien free |=(id=@ud =(id id.t))))
5948+ state(sub [[id.t [%atom %ud]] sub.state])
5949+ $(all t.all)
5950+::
5951+:: Only obligations created inside this definition belong to it.
5952+++ holes-created
5953+ |= [all=(list ihole) prior=(list ihole)]
5954+ ^- (list ihole)
5955+ ?: =(all prior) ~
5956+ ?~ all ~
5957+ [i.all $(all t.all)]
5958+++ hole-uncertain
5959+ |= [t=itype state=istate]
5960+ ^- ?
5961+ =. t (itype-walk t sub.state)
5962+ ?- -.t
5963+ ?(%tag %nvar %rnvar %avar %rvar) !(hole-known t state)
5964+ %union |((lien cases.t |=(c=itype (hole-uncertain c state))) (lien args.t |=(c=itype (hole-uncertain c state))))
5965+ %grec (lien args.t |=(c=itype (hole-uncertain c state)))
5966+ %collection (lien args.t |=(c=itype (hole-uncertain c state)))
5967+ %face $(t body.t)
5968+ %fn |($(t sample.t) $(t product.t))
5969+ %cell |($(t hed.t) $(t tal.t))
5970+ * |
5971+ ==
5972+::
5973+++ unresolved-hole
5974+ |= [all=(list ihole) prior=(list ihole) state=istate]
5975+ ^- (unit idiag)
5976+ =/ work=(list ihole) (flop (holes-created all prior))
5977+ |-
5978+ ?~ work ~
5979+ ?: (hole-known [%var id.i.work] state) $(work t.work)
5980+ ?: (hole-uncertain [%var id.i.work] state)
5981+ `["type hole needs unsupported inference" ~[[at.i.work "type hole"]]]
5982+ `["type hole needs a determined type" ~[[at.i.work "unresolved type hole"]]]
5983+::
5984+++ itype-vars
5985+ |= t=itype
5986+ ^- (list @ud)
5987+ ?- -.t
5988+ %var ~[id.t]
5989+ %avar ~[id.t]
5990+ %rvar ~[id.t]
5991+ %nvar ~[id.t]
5992+ %rnvar ~[id.t]
5993+ %atom ~
5994+ %any-atom ~
5995+ %flag ~
5996+ %noun ~
5997+ %empty ~
5998+ %tag ~
5999+ %const ~
6000+ %union (zing (turn (weld args.t cases.t) |=(c=itype (itype-vars c))))
6001+ %recursive ~
6002+ %jrec ~
6003+ %grec (zing (turn args.t |=(c=itype (itype-vars c))))
6004+ %collection (zing (turn args.t |=(c=itype (itype-vars c))))
6005+ %face $(t body.t)
6006+ %fn (weld $(t sample.t) $(t product.t))
6007+ %cell (weld $(t hed.t) $(t tal.t))
6008+ ==
6009+::
6010+++ unique-type-vars
6011+ |= ns=(list @ud)
6012+ ^- (list @ud)
6013+ =/ out=(list @ud) ~
6014+ |-
6015+ ?~ ns (flop out)
6016+ ?: (lien out |=(x=@ud =(x i.ns))) $(ns t.ns)
6017+ $(ns t.ns, out [i.ns out])
6018+::
6019+++ itype-rename
6020+ |= [t=itype ren=isub]
6021+ ^- itype
6022+ ?- -.t
6023+ %var
6024+ =/ found=(unit itype) (itype-lookup id.t ren)
6025+ ?~ found t
6026+ u.found
6027+ %avar
6028+ =/ found=(unit itype) (itype-lookup id.t ren)
6029+ ?~ found t
6030+ u.found
6031+ %rvar
6032+ =/ found=(unit itype) (itype-lookup id.t ren)
6033+ ?~ found t
6034+ u.found
6035+ %nvar
6036+ =/ found=(unit itype) (itype-lookup id.t ren)
6037+ ?~ found t
6038+ u.found
6039+ %rnvar
6040+ =/ found=(unit itype) (itype-lookup id.t ren)
6041+ ?~ found t
6042+ u.found
6043+ %atom t
6044+ %any-atom t
6045+ %flag t
6046+ %noun t
6047+ %empty t
6048+ %tag t
6049+ %const t
6050+ %union [%union (turn cases.t |=(c=itype (itype-rename c ren))) origin.t label.t (turn args.t |=(c=itype (itype-rename c ren)))]
6051+ %recursive t
6052+ %jrec t
6053+ %grec t(args (turn args.t |=(c=itype (itype-rename c ren))))
6054+ %collection [%collection name.t (turn args.t |=(c=itype (itype-rename c ren)))]
6055+ %face [%face name.t $(t body.t)]
6056+ %fn [%fn $(t sample.t) $(t product.t)]
6057+ %cell [%cell $(t hed.t) $(t tal.t)]
6058+ ==
6059+::
6060+:: Variable IDs are unique across the two kinds. Inspecting the
6061+:: normalized type preserves the atom constraint when renaming.
6062+::
6063+++ itype-var-is-atom
6064+ |= [n=@ud t=itype]
6065+ ^- ?
6066+ ?- -.t
6067+ %var |
6068+ %avar =(n id.t)
6069+ %rvar =(n id.t)
6070+ %nvar =(n id.t)
6071+ %rnvar =(n id.t)
6072+ %atom |
6073+ %any-atom |
6074+ %flag |
6075+ %noun |
6076+ %empty |
6077+ %tag |
6078+ %const |
6079+ %union |((lien cases.t |=(c=itype (itype-var-is-atom n c))) (lien args.t |=(c=itype (itype-var-is-atom n c))))
6080+ %recursive |
6081+ %jrec |
6082+ %grec (lien args.t |=(c=itype (itype-var-is-atom n c)))
6083+ %collection (lien args.t |=(c=itype (itype-var-is-atom n c)))
6084+ %face $(t body.t)
6085+ %fn |($(t sample.t) $(t product.t))
6086+ %cell |($(t hed.t) $(t tal.t))
6087+ ==
6088+++ itype-var-is-restricted
6089+ |= [n=@ud t=itype]
6090+ ^- ?
6091+ ?- -.t
6092+ %var |
6093+ %avar |
6094+ %rvar =(n id.t)
6095+ %nvar |
6096+ %rnvar |
6097+ %atom |
6098+ %any-atom |
6099+ %flag |
6100+ %noun |
6101+ %empty |
6102+ %tag |
6103+ %const |
6104+ %union |((lien cases.t |=(c=itype (itype-var-is-restricted n c))) (lien args.t |=(c=itype (itype-var-is-restricted n c))))
6105+ %recursive |
6106+ %jrec |
6107+ %grec (lien args.t |=(c=itype (itype-var-is-restricted n c)))
6108+ %collection (lien args.t |=(c=itype (itype-var-is-restricted n c)))
6109+ %face $(t body.t)
6110+ %fn |($(t sample.t) $(t product.t))
6111+ %cell |($(t hed.t) $(t tal.t))
6112+ ==
6113+::
6114+:: Canonical numbering makes printed variables independent of the order
6115+:: the unifier happened to allocate intermediates.
6116+::
6117+++ canonical-itype
6118+ |= [t=itype vars=(list @ud)]
6119+ ^- itype
6120+ =/ ren=isub ~
6121+ =/ n=@ud 0
6122+ |-
6123+ ?~ vars (itype-rename t ren)
6124+ =/ replacement=itype ?:((itype-var-is-restricted i.vars t) [%rvar n] ?:((itype-var-is-atom i.vars t) [%avar n] [%var n]))
6125+ $(vars t.vars, ren [[i.vars replacement] ren], n +(n))
6126+::
6127+++ instantiate-scheme
6128+ |= [scheme=ischeme state=istate]
6129+ ^- [typ=itype state=istate]
6130+ =/ ren=isub ~
6131+ =/ vars=(list @ud) vars.scheme
6132+ |-
6133+ ?~ vars [(itype-rename typ.scheme ren) state]
6134+ =/ replacement=itype
6135+ ?:((itype-var-is-restricted i.vars typ.scheme) [%rvar next.state] ?:((itype-var-is-atom i.vars typ.scheme) [%avar next.state] [%var next.state]))
6136+ :: A generalized atom variable is a valid origin for re-generalizing
6137+ :: an alias, just as a sample binder is.
6138+ =/ st=istate state(next +(next.state))
6139+ =? binders.st |(?=(%avar -.replacement) ?=(%rvar -.replacement)) [next.state binders.state]
6140+ $(vars t.vars, ren [[i.vars replacement] ren], state st)
6141+::
6142+++ icap-lookup
6143+ |= [n=@t caps=icaps]
6144+ ^- (unit @ud)
6145+ ?~ caps ~
6146+ ?: =(n name.i.caps) `id.i.caps
6147+ $(caps t.caps)
6148+::
6149+::
6150+:: Only an unambiguous local name can be expanded. Import faces and
6151+:: recursive mold identity need the full module interface.
6152+::
6153+++ find-simple-mold
6154+ |= [n=term molds=imolds]
6155+ ^- (unit shape)
6156+ =/ matches=imolds (skim molds |=(m=[name=term body=shape] =(n name.m)))
6157+ ?~ matches ~
6158+ ?^ t.matches ~
6159+ `body.i.matches
6160+::
6161+++ collect-simple-molds
6162+ |= ds=(list def)
6163+ ^- imolds
6164+ ?~ ds ~
6165+ ?: ?=(%mold -.i.ds)
6166+ [[name.i.ds shape.i.ds] $(ds t.ds)]
6167+ $(ds t.ds)
6168+::
6169+::
6170+:: The caller supplies unchanged results from the source-aware importer.
6171+:: That boundary is trusted for source provenance: a fork alone cannot
6172+:: reveal cases Hoon collapsed before it was constructed. Validate the
6173+:: supplied graph independently, including pairwise disjointness. Fixed
6174+:: atoms, term singletons, cells, faces and proven forks are decoded;
6175+:: unsupported singletons, collections and recursive references fail.
6176+::
6177+++ jibb-face-name
6178+ |= name=@
6179+ ^- ?
6180+ =/ chars=tape (trip (@t name))
6181+ ?~ chars |
6182+ ?. (is-lower i.chars) |
6183+ (levy t.chars |=(c=@tD (in c name-mask)))
6184+::
6185+:: A source-aware reader result is trusted for origin. Validate every
6186+:: supplied branch and keep the recursive mold opaque: unfolding its
6187+:: root while naming only its tail would change its type identity.
6188++$ irec-pattern [pat=upat has=?]
6189+++ rec-pattern
6190+ |= [node=* module=term name=term]
6191+ ^- (unit irec-pattern)
6192+ ?@ node ~
6193+ ?+ -.node ~
6194+ %atom
6195+ ?: ?=([%atom %n [~ @]] node)
6196+ ?. =(0 +>+.node) ~
6197+ `[[%atom `0] |]
6198+ ?: ?=([%atom %tas [~ @]] node)
6199+ =/ value=@ +>+.node
6200+ ?. |(=(value 0) (jibb-face-name value)) ~
6201+ `[[%atom `value] |]
6202+ ?. ?=([%atom @ ~] node) ~
6203+ =/ aura=@ta (@ta +<.node)
6204+ ?. |(?=(?(%u %ud %ux %uv %t %ta %tas %p %da %dr) aura) =('tD' aura)) ~
6205+ `[[%atom ~] |]
6206+ %ref
6207+ ?. ?=([%ref @ @] node) ~
6208+ ?. &(=(module +<.node) =(name +>.node)) ~
6209+ `[[%unknown ~] &]
6210+ %apply
6211+ ?. ?=([%apply %list [* ~]] node) ~
6212+ =/ item $(node -.+>.node)
6213+ ?~ item ~
6214+ `[[%or ~[[%atom `0] [%cell pat.u.item [%unknown ~]]]] has.u.item]
6215+ %face
6216+ ?. ?=([%face @ *] node) ~
6217+ ?. (jibb-face-name +<.node) ~
6218+ $(node +>.node)
6219+ %cell
6220+ ?. ?=([%cell * *] node) ~
6221+ =/ left $(node +<.node)
6222+ ?~ left ~
6223+ =/ right $(node +>.node)
6224+ ?~ right ~
6225+ `[[%cell pat.u.left pat.u.right] |(has.u.left has.u.right)]
6226+ %fork
6227+ =/ cases (rec-patterns +.node module name)
6228+ ?~ cases ~
6229+ ?~ pats.u.cases ~
6230+ ?~ t.pats.u.cases ~
6231+ ?. (rec-patterns-disjoint pats.u.cases) ~
6232+ `[[%or pats.u.cases] has.u.cases]
6233+ ==
6234+::
6235+++ rec-patterns
6236+ |= [nodes=* module=term name=term]
6237+ ^- (unit [pats=(list upat) has=?])
6238+ ?@ nodes ?:(=(nodes 0) `[~ |] ~)
6239+ =/ first (rec-pattern -.nodes module name)
6240+ ?~ first ~
6241+ =/ rest $(nodes +.nodes)
6242+ ?~ rest ~
6243+ `[[pat.u.first pats.u.rest] |(has.u.first has.u.rest)]
6244+::
6245+++ rec-patterns-disjoint
6246+ |= pats=(list upat)
6247+ ^- ?
6248+ ?~ pats &
6249+ ?. (levy t.pats |=(p=upat =(%disjoint (union-relate i.pats p)))) |
6250+ $(pats t.pats)
6251+::
6252+::
6253+::
6254+:: Repeated faces along an imported record spine fail closed. Hoon's type
6255+:: graph can erase unfaced nested-cell boundaries, so that alone does not
6256+:: prove the original source repeated a name within one record. A faced
6257+:: body and each union alternative have separate scopes. Check recursive
6258+:: roots before making them opaque; unused molds are never inspected.
6259+::
6260+++ imported-faces-valid
6261+ |= node=*
6262+ ^- ?
6263+ ?@ node &
6264+ ?+ -.node &
6265+ %face ?:(?=([%face @ *] node) $(node +>.node) |)
6266+ %cell ?:(?=([%cell * *] node) (imported-record-faces-valid node ~) |)
6267+ %fork (imported-faces-valid-list +.node)
6268+ %apply ?:(?=([%apply @ *] node) (imported-faces-valid-list +>.node) |)
6269+ %named
6270+ ?. ?=([%named @ @ *] node) |
6271+ =/ n=[%named module=@ name=@ body=*] ;;([%named module=@ name=@ body=*] node)
6272+ (imported-faces-valid body.n)
6273+ ==
6274+::
6275+++ imported-faces-valid-list
6276+ |= nodes=*
6277+ ^- ?
6278+ ?@ nodes =(nodes 0)
6279+ ?. (imported-faces-valid -.nodes) |
6280+ $(nodes +.nodes)
6281+::
6282+++ imported-record-faces-valid
6283+ |= [node=* names=(list @)]
6284+ ^- ?
6285+ ?: ?=([%cell * *] node)
6286+ =/ head=* +<.node
6287+ =/ rest=* +>.node
6288+ ?: ?=([%face @ *] head)
6289+ ?: (lien names |=(n=@ =(n +<.head))) |
6290+ ?. (imported-faces-valid +>.head) |
6291+ $(node rest, names [+<.head names])
6292+ ?. (imported-faces-valid head) |
6293+ $(node rest)
6294+ ?: ?=([%face @ *] node)
6295+ ?: (lien names |=(n=@ =(n +<.node))) |
6296+ (imported-faces-valid +>.node)
6297+ (imported-faces-valid node)
6298+::
6299+++ import-to-itype
6300+ |= node=*
6301+ ^- (unit itype)
6302+ ?@ node ~
6303+ ?+ -.node ~
6304+ %noun ?:(=(node [%noun ~]) `[%noun ~] ~)
6305+ %atom
6306+ :: A Hoon loobean singleton is one of the two Jibb loobeans.
6307+ ?: ?=([%atom %f [~ @]] node)
6308+ =/ value=@ +>+.node
6309+ ?. |(=(value 0) =(value 1)) ~
6310+ =/ printed=@t ?:(=(value 0) '%.y' '%.n')
6311+ `[%const [%loobean %f value printed]]
6312+ :: Hoon's null singleton is the same noun as Jibb's `~` mold.
6313+ :: Other non-term singleton atoms remain unsupported here.
6314+ ?: ?=([%atom %n [~ @]] node)
6315+ ?. =(0 +>+.node) ~
6316+ `[%const [%null %n 0 '~']]
6317+ ?: ?=([%atom %tas [~ @]] node)
6318+ =/ value=@ +>+.node
6319+ ?. |(=(value 0) (jibb-face-name value)) ~
6320+ =/ printed=@t ?:(=(value 0) '%$' (cat 3 '%' value))
6321+ `[%const [%term %tas value printed]]
6322+ ?. ?=([%atom @ ~] node) ~
6323+ =/ aura=@ta (@ta +<.node)
6324+ ?. |(?=(?(%u %ud %ux %uv %t %ta %tas %p %da %dr) aura) =('tD' aura)) ~
6325+ `[%atom aura]
6326+ %named
6327+ ?. ?=([%named @ @ *] node) ~
6328+ =/ n=[%named module=@ name=@ body=*] ;;([%named module=@ name=@ body=*] node)
6329+ ?. &((jibb-face-name module.n) (jibb-face-name name.n)) ~
6330+ ?. ?=([%fork *] body.n) ~
6331+ =/ proof=(unit irec-pattern) (rec-pattern body.n (@tas module.n) (@tas name.n))
6332+ ?~ proof ~
6333+ ?. has.u.proof ~
6334+ `[%recursive (@tas module.n) (@tas name.n) `(crip "{(trip name.n)}.{(trip module.n)}")]
6335+ %apply
6336+ ?. ?=([%apply @ *] node) ~
6337+ =/ name=term (@tas +<.node)
6338+ =/ arity=@ud
6339+ ?: |(=(%list name) =(%unit name) =(%set name) =(%qeu name)) 1
6340+ ?: |(=(%map name) =(%mop name) =(%jar name) =(%jug name)) 2
6341+ 0
6342+ ?: =(arity 0) ~
6343+ =/ args=(unit (list itype)) (import-to-itypes +>.node)
6344+ ?~ args ~
6345+ ?. =(arity (lent u.args)) ~
6346+ `[%collection name u.args]
6347+ %fork
6348+ :: Hoon's ordinary ? mold is the fork of its two %f singletons.
6349+ =/ raw=* +.node
6350+ ?: |(=(raw ~[[%atom %f `0] [%atom %f `1]]) =(raw ~[[%atom %f `1] [%atom %f `0]]))
6351+ `[%flag ~]
6352+ =/ cases=(unit (list itype)) (import-to-itypes raw)
6353+ ?~ cases ~
6354+ ?~ u.cases ~
6355+ ?~ t.u.cases ~
6356+ ?: (import-has-loobean-singleton u.cases) ~
6357+ ?. (import-cases-disjoint u.cases) ~
6358+ `[%union u.cases ~ ~ ~]
6359+ %face
6360+ ?. ?=([%face @ *] node) ~
6361+ =/ name=@ +<.node
6362+ ?. (jibb-face-name name) ~
6363+ =/ body=(unit itype) $(node +>.node)
6364+ ?~ body ~
6365+ `[%face (@tas name) u.body]
6366+ %cell
6367+ ?. ?=([%cell * *] node) ~
6368+ =/ left=(unit itype) $(node +<.node)
6369+ ?~ left ~
6370+ =/ right=(unit itype) $(node +>.node)
6371+ ?~ right ~
6372+ `[%cell u.left u.right]
6373+ ==
6374+::
6375+++ import-direct-loobean
6376+ |= t=itype
6377+ ^- ?
6378+ ?: ?=(%face -.t) $(t body.t)
6379+ ?: ?=(%union -.t) (import-has-loobean-singleton cases.t)
6380+ ?=([%const [%loobean *]] t)
6381+::
6382+++ import-has-loobean-singleton
6383+ |= cases=(list itype)
6384+ ^- ?
6385+ ?~ cases |
6386+ ?: (import-direct-loobean i.cases) &
6387+ $(cases t.cases)
6388+::
6389+++ import-to-itypes
6390+ |= nodes=*
6391+ ^- (unit (list itype))
6392+ ?@ nodes ?:(=(nodes 0) `~ ~)
6393+ =/ first (import-to-itype -.nodes)
6394+ ?~ first ~
6395+ =/ rest $(nodes +.nodes)
6396+ ?~ rest ~
6397+ `[u.first u.rest]
6398+::
6399+++ import-type-pattern
6400+ |= typ=itype
6401+ ^- upat
6402+ ?- -.typ
6403+ %noun [%all ~]
6404+ %empty [%empty ~]
6405+ %atom [%atom ~]
6406+ %flag [%or ~[[%atom `0] [%atom `1]]]
6407+ %const [%atom `val.literal.typ]
6408+ %face $(typ body.typ)
6409+ %cell [%cell $(typ hed.typ) $(typ tal.typ)]
6410+ %union [%or (turn cases.typ |=(t=itype (import-type-pattern t)))]
6411+ * [%unknown ~]
6412+ ==
6413+::
6414+++ import-cases-disjoint
6415+ |= cases=(list itype)
6416+ ^- ?
6417+ ?~ cases &
6418+ =/ first=upat (import-type-pattern i.cases)
6419+ ?. (levy t.cases |=(t=itype =(%disjoint (union-relate first (import-type-pattern t))))) |
6420+ $(cases t.cases)
6421+::
6422+++ find-imported-mold
6423+ |= [module=term name=term externals=iexternals surs=(list term)]
6424+ ^- (unit itype)
6425+ ?. (lien surs |=(n=term =(n module))) ~
6426+ =/ found=iexternals
6427+ (skim externals |=(e=[module=term name=term result=*] &(=(module module.e) =(name name.e))))
6428+ ?~ found ~
6429+ ?^ t.found ~
6430+ =/ result=* result.i.found
6431+ ?@ result ~
6432+ ?. ?=(%& -.result) ~
6433+ =/ node=* +.result
6434+ ?. (imported-faces-valid node) ~
6435+ ?@ node (import-to-itype node)
6436+ ?: ?=(%ref -.node) (import-to-itype node)
6437+ =/ pattern=(unit irec-pattern) (rec-pattern node module name)
6438+ ?~ pattern (import-to-itype node)
6439+ ?. has.u.pattern (import-to-itype node)
6440+ `[%recursive module name `(crip "{(trip name)}.{(trip module)}")]
6441+
6442+::
6443+++ collect-sur-imports
6444+ |= imports=(list import)
6445+ ^- (list term)
6446+ ?~ imports ~
6447+ ?: ?=(%sur -.i.imports)
6448+ [name.i.imports $(imports t.imports)]
6449+ $(imports t.imports)
6450+::
6451+++ collect-mark-imports
6452+ |= imports=(list import)
6453+ ^- (list term)
6454+ ?~ imports ~
6455+ ?: ?=(%mark -.i.imports)
6456+ [mark.i.imports $(imports t.imports)]
6457+ $(imports t.imports)
6458+::
6459+++ find-imported-mark
6460+ |= [name=term externals=imark-externals marks=(list term)]
6461+ ^- (unit itype)
6462+ ?. (unique-value-name name marks) ~
6463+ =/ found=imark-externals
6464+ (skim externals |=(e=[mark=term result=*] =(name mark.e)))
6465+ ?~ found ~
6466+ ?^ t.found ~
6467+ =/ result=* result.i.found
6468+ ?@ result ~
6469+ ?. ?=(%& -.result) ~
6470+ ?. (imported-faces-valid +.result) ~
6471+ (import-to-itype +.result)
6472+::
6473+++ find-jibb-interface
6474+ |= [face=term imports=ijimports]
6475+ ^- (unit ifile)
6476+ ?~ imports ~
6477+ ?: =(face face.i.imports) `interface.i.imports
6478+ $(imports t.imports)
6479+::
6480+++ find-jibb-mold
6481+ |= [name=term iface=ifile]
6482+ ^- (unit ischeme)
6483+ =/ ms=imold-types molds.iface
6484+ |-
6485+ ?~ ms ~
6486+ ?: =(name name.i.ms) `template.i.ms
6487+ $(ms t.ms)
6488+::
6489+:: An exported alias may name a union from another module. Only a
6490+:: nongeneric alias of the same origin is usable through this import face.
6491+::
6492+++ imported-union-alias
6493+ |= [origin=[at=path name=term] molds=imold-types]
6494+ ^- (unit term)
6495+ ?~ molds ~
6496+ =/ template=ischeme template.i.molds
6497+ ?: &(?=(~ vars.template) ?=(%union -.typ.template))
6498+ ?:(=(`origin origin.typ.template) `name.i.molds $(molds t.molds))
6499+ $(molds t.molds)
6500+::
6501+:: A prelude union alias is a display name, not a new union identity. An
6502+:: identity-generic alias can carry the origin's arguments only when the
6503+:: origin, arity and ordered parameters match. Swapped, repeated, fixed
6504+:: or phantom parameters cannot be printed that way and remain unsupported
6505+:: when their only available name is private. A nongeneric alias of a
6506+:: generic instantiation cannot be printed with the origin's arguments.
6507+++ identity-union-parameters
6508+ |= [vars=(list @ud) args=(list itype)]
6509+ ^- ?
6510+ ?~ vars ?=(~ args)
6511+ ?~ args |
6512+ ?. =([%var i.vars] i.args) |
6513+ $(vars t.vars, args t.args)
6514+++ prelude-union-alias
6515+ |= [origin=[at=path name=term] args=(list itype) molds=imold-types]
6516+ ^- (unit term)
6517+ ?~ molds ~
6518+ =/ template=ischeme template.i.molds
6519+ ?. ?=(%union -.typ.template) $(molds t.molds)
6520+ ?. =(`origin origin.typ.template) $(molds t.molds)
6521+ ?~ vars.template
6522+ ?^ args $(molds t.molds)
6523+ ?:(=(args args.typ.template) `name.i.molds $(molds t.molds))
6524+ ?: &((identity-union-parameters vars.template args.typ.template) =((lent vars.template) (lent args)))
6525+ `name.i.molds
6526+ $(molds t.molds)
6527+::
6528+:: Names exported by the directly imported module are visible through its
6529+:: face; a matching prelude alias is also visible without a qualifier.
6530+::
6531+++ jrec-alias
6532+ |= [origin=path name=term molds=imold-types]
6533+ ^- (unit term)
6534+ ?~ molds ~
6535+ =/ template=ischeme template.i.molds
6536+ ?: &(?=(~ vars.template) ?=(%jrec -.typ.template) =(at.typ.template origin) =(name.typ.template name)) `name.i.molds
6537+ $(molds t.molds)
6538+::
6539+++ grec-visible-alias
6540+ |= [origin=path name=term proof=shape args=(list itype) molds=imold-types]
6541+ ^- (unit term)
6542+ ?~ molds ~
6543+ =/ template=ischeme template.i.molds
6544+ ?. ?=(%grec -.typ.template) $(molds t.molds)
6545+ ?. &(=(at.typ.template origin) =(name.typ.template name) =(proof.typ.template proof)) $(molds t.molds)
6546+ ?. &((identity-union-parameters vars.template args.typ.template) =((lent vars.template) (lent args))) $(molds t.molds)
6547+ `name.i.molds
6548+::
6549+++ itype-in-import
6550+ |= [t=itype iface=ifile face=term prelude=(unit ifile)]
6551+ ^- itype
6552+ ?- -.t
6553+ %union
6554+ =/ label=(unit @t)
6555+ ?~ origin.t ~
6556+ ?: =(at.u.origin.t /lib/jibb/prelude/jibb) `name.u.origin.t
6557+ =/ public=(unit term)
6558+ ?~ prelude ~
6559+ (prelude-union-alias u.origin.t args.t molds.u.prelude)
6560+ ?^ public `u.public
6561+ =/ alias=(unit term) ~
6562+ =? alias &(=(at.u.origin.t at.iface) ?=(^ (find-jibb-mold name.u.origin.t iface))) `name.u.origin.t
6563+ =? alias ?=(~ alias) (imported-union-alias u.origin.t molds.iface)
6564+ ?~ alias ~
6565+ `(crip "{(trip u.alias)}.{(trip face)}")
6566+ [%union (turn cases.t |=(c=itype (itype-in-import c iface face prelude))) origin.t label (turn args.t |=(c=itype (itype-in-import c iface face prelude)))]
6567+ %recursive [%recursive module.t name.t ~]
6568+ %grec
6569+ =/ public=(unit term) ?~(prelude ~ (grec-visible-alias at.t name.t proof.t args.t molds.u.prelude))
6570+ =/ alias=(unit term) ?~(public (grec-visible-alias at.t name.t proof.t args.t molds.iface) public)
6571+ =/ label=(unit @t) ?~(alias ~ ?~(public `(crip "{(trip u.alias)}.{(trip face)}") `u.alias))
6572+ t(label label, args (turn args.t |=(c=itype (itype-in-import c iface face prelude))))
6573+ %jrec
6574+ =/ public=(unit term) ?~(prelude ~ (jrec-alias at.t name.t molds.u.prelude))
6575+ ?^ public t(label `u.public)
6576+ =/ alias=(unit term) (jrec-alias at.t name.t molds.iface)
6577+ ?~ alias t(label ~)
6578+ t(label `(crip "{(trip u.alias)}.{(trip face)}"))
6579+ %collection [%collection name.t (turn args.t |=(c=itype (itype-in-import c iface face prelude)))]
6580+ %face [%face name.t $(t body.t)]
6581+ %fn [%fn $(t sample.t) $(t product.t)]
6582+ %cell [%cell $(t hed.t) $(t tal.t)]
6583+ * t
6584+ ==
6585+::
6586+++ label-direct-union
6587+ |= [typ=itype body=shape name=term state=istate]
6588+ ^- itype
6589+ ?. ?=(%union -.typ) typ
6590+ =/ direct=? ?=(%union -.body)
6591+ =? direct ?=(%generic -.body) ?=(%union -.body.body)
6592+ ?. direct typ
6593+ ?. (lien top-molds.state |=(n=term =(n name))) typ
6594+ [%union cases.typ `[at.state name] `name args.typ]
6595+::
6596+:: Generic mold parameters are lexical and distinct from the enclosing
6597+:: value's capital variables. Arguments are substituted only once, so
6598+:: an argument's variable ID cannot be captured by a template ID.
6599+:: A generic alias of a named union keeps the underlying union's origin
6600+:: and substituted argument order; an originless union stays unsupported.
6601+::
6602+++ iparam-lookup
6603+ |= [name=@t params=iparams]
6604+ ^- (unit itype)
6605+ ?~ params ~
6606+ ?: =(name name.i.params) `typ.i.params
6607+ $(params t.params)
6608+::
6609+++ distinct-params
6610+ |= names=(list @t)
6611+ ^- ?
6612+ ?~ names &
6613+ ?: (lien t.names |=(n=@t =(n i.names))) |
6614+ $(names t.names)
6615+::
6616+++ bind-params
6617+ |= [names=(list @t) args=(list itype)]
6618+ ^- (unit iparams)
6619+ ?~ names ?~(args `~ ~)
6620+ ?~ args ~
6621+ =/ rest=(unit iparams) $(names t.names, args t.args)
6622+ ?~ rest ~
6623+ `[[i.names i.args] u.rest]
6624+::
6625+++ template-apply
6626+ |= [template=ischeme args=(list itype)]
6627+ ^- (unit itype)
6628+ =/ vars=(list @ud) vars.template
6629+ =/ ren=isub ~
6630+ |-
6631+ ?~ vars ?~(args `(itype-rename typ.template ren) ~)
6632+ ?~ args ~
6633+ $(vars t.vars, args t.args, ren [[i.vars i.args] ren])
6634+::
6635+++ infer-shape-args
6636+ |= [args=(list shape) state=istate]
6637+ ^- (unit [types=(list itype) state=istate])
6638+ ?~ args `[~ state]
6639+ =/ head=(unit [typ=itype state=istate]) (infer-simple-shape i.args state)
6640+ ?~ head ~
6641+ =/ tail=(unit [types=(list itype) state=istate]) $(args t.args, state state.u.head)
6642+ ?~ tail ~
6643+ `[[typ.u.head types.u.tail] state.u.tail]
6644+::
6645+++ fresh-mold-params
6646+ |= [names=(list @t) next=@ud]
6647+ ^- [params=iparams vars=(list @ud) next=@ud]
6648+ ?~ names [~ ~ next]
6649+ =/ rest=[params=iparams vars=(list @ud) next=@ud] $(names t.names, next +(next))
6650+ [[[i.names [%var next]] params.rest] [next vars.rest] next.rest]
6651+::
6652+:: Recognize a unique top-level source mold with exactly a null case and a
6653+:: faced atom-headed cell whose faced tail names that same mold. Its Jibb
6654+:: path and name provide nominal identity. Other recursive shapes fail closed;
6655+:: construction and matching expose the proven shape one layer at a time.
6656+++ simple-source-recursive
6657+ |= [name=term sh=shape state=istate]
6658+ ^- (unit itype)
6659+ ?. (lien top-molds.state |=(n=term =(n name))) ~
6660+ =/ original=(unit shape) (find-simple-mold name molds.state)
6661+ ?~ original ~
6662+ ?. =(u.original sh) ~
6663+ ?. ?=(%union -.sh) ~
6664+ =/ cs=(list shape) cases.sh
6665+ ?~ cs ~
6666+ ?~ t.cs ~
6667+ ?^ t.t.cs ~
6668+ ?. ?=(%const -.i.cs) ~
6669+ ?. =(%null form.lit.i.cs) ~
6670+ ?. ?=(%cell -.i.t.cs) ~
6671+ =/ fs=(list field) fields.i.t.cs
6672+ ?~ fs ~
6673+ ?~ t.fs ~
6674+ ?^ t.t.fs ~
6675+ ?. ?=(%face -.i.fs) ~
6676+ ?. ?=(%aura -.shape.i.fs) ~
6677+ ?. !=(0 aura.shape.i.fs) ~
6678+ ?. ?=(%face -.i.t.fs) ~
6679+ ?. !=(name.i.fs name.i.t.fs) ~
6680+ =/ tail=shape shape.i.t.fs
6681+ ?. ?=(%ref -.tail) ~
6682+ ?. =(names.tail ~[name]) ~
6683+ `[%jrec at.state name `name name.i.fs aura.shape.i.fs name.i.t.fs]
6684+::
6685+++ simple-source-generic-recursive
6686+ |= [name=term sh=shape args=(list itype) state=istate]
6687+ ^- (unit itype)
6688+ ?. ?=(%generic -.sh) ~
6689+ ?. ?=([@ ~] vars.sh) ~
6690+ ?. ?=([* ~] args) ~
6691+ ?~ grec-index.state ~
6692+ ?. =(at.u.grec-index.state at.state) ~
6693+ ?~ prelude.state ~
6694+ ?. =(prelude.u.grec-index.state u.prelude.state) ~
6695+ =/ proof=(unit shape) (~(get by shapes.u.grec-index.state) name)
6696+ ?~ proof ~
6697+ ?. =(u.proof sh) ~
6698+ `[%grec at.state name `name sh args]
6699+::
6700+
6701+++ infer-mold-template
6702+ |= [sh=shape state=istate]
6703+ ^- (unit [template=ischeme state=istate])
6704+ =/ generic=(unit itype)
6705+ ?. ?=([@ ~] active.state) ~
6706+ (simple-source-generic-recursive i.active.state sh ~[[%var next.state]] state)
6707+ ?^ generic `[[u.generic ~[next.state]] state(next +(next.state))]
6708+ =/ direct=(unit itype)
6709+ ?. ?=([@ ~] active.state) ~
6710+ (simple-source-recursive i.active.state sh state)
6711+ ?^ direct `[[u.direct ~] state]
6712+ ?: ?=(%generic -.sh)
6713+ ?~ vars.sh ~
6714+ ?. (distinct-params vars.sh) ~
6715+ =/ fresh=[params=iparams vars=(list @ud) next=@ud] (fresh-mold-params vars.sh next.state)
6716+ =/ out=(unit [typ=itype state=istate])
6717+ (infer-simple-shape body.sh state(next next.fresh, params params.fresh, in-mold &))
6718+ ?~ out ~
6719+ ?^ (unresolved-hole holes.state.u.out holes.state state.u.out) ~
6720+ ?: &(?=(%union -.typ.u.out) !?=(%union -.body.sh) ?=(~ origin.typ.u.out)) ~
6721+ =? typ.u.out &(?=(%union -.typ.u.out) ?=(%union -.body.sh))
6722+ typ.u.out(args (turn vars.fresh |=(n=@ud `itype`[%var n])))
6723+ =/ used=(list @ud) (itype-vars typ.u.out)
6724+ ?. (levy used |=(n=@ud (lien vars.fresh |=(p=@ud =(p n))))) ~
6725+ `[[typ.u.out vars.fresh] state.u.out(params params.state, in-mold in-mold.state, holes holes.state)]
6726+ =/ out=(unit [typ=itype state=istate])
6727+ (infer-simple-shape sh state(params ~, in-mold &))
6728+ ?~ out ~
6729+ ?^ (unresolved-hole holes.state.u.out holes.state state.u.out) ~
6730+ ?: ?=(^ (itype-vars typ.u.out)) ~
6731+ `[[typ.u.out ~] state.u.out(params params.state, in-mold in-mold.state, holes holes.state)]
6732+::
6733+:: A direct imported reference may carry definite reader evidence. Only
6734+:: uniquely supplied, declared inputs are used; unsupported data stay generic.
6735+++ direct-import-invalid
6736+ |= [sh=shape state=istate]
6737+ ^- (unit idiag)
6738+ ?. ?=(%ref -.sh) ~
6739+ ?~ names.sh ~
6740+ =/ n=term i.names.sh
6741+ =/ raw=*
6742+ ?~ t.names.sh
6743+ ?. (unique-value-name n marks.state) ~
6744+ ?: (lien surs.state |=(x=term =(x n))) ~
6745+ ?: ?=(^ (find-jibb-interface n jimports.state)) ~
6746+ ?: (lien globals.state |=(x=term =(x n))) ~
6747+ ?: (lien reserved-molds.state |=(x=term =(x n))) ~
6748+ ?: (lien molds.state |=(m=[name=term body=shape] =(n name.m))) ~
6749+ =/ found=imark-externals (skim mark-externals.state |=(e=[mark=term result=*] =(mark.e n)))
6750+ ?~ found ~
6751+ ?^ t.found ~
6752+ result.i.found
6753+ ?^ t.t.names.sh ~
6754+ =/ mod=term i.t.names.sh
6755+ ?: ?=(^ (find-jibb-interface mod jimports.state)) ~
6756+ ?. (unique-value-name mod surs.state) ~
6757+ ?: (lien marks.state |=(x=term =(x mod))) ~
6758+ ?: (lien globals.state |=(x=term =(x mod))) ~
6759+ ?: (lien reserved-molds.state |=(x=term =(x mod))) ~
6760+ ?: (lien molds.state |=(m=[name=term body=shape] =(mod name.m))) ~
6761+ =/ found=iexternals (skim externals.state |=(e=[module=term name=term result=*] &(=(module.e mod) =(name.e n))))
6762+ ?~ found ~
6763+ ?^ t.found ~
6764+ result.i.found
6765+ ?. ?=([%invalid ?(%aura %core %overlap) @] raw) ~
6766+ `["{(trip +>.raw)}" ~[[at.sh "invalid imported mold"]]]
6767+::
6768+:: Replay only the shape branches whose evaluation order we can prove.
6769+:: Successful prefixes must be checked before descending to a failure.
6770+++ nested-import-invalid
6771+ |= [sh=shape state=istate]
6772+ ^- (unit idiag)
6773+ ?: ?=(^ (infer-simple-shape sh state)) ~
6774+ ?- -.sh
6775+ %ref
6776+ =/ direct=(unit idiag) (direct-import-invalid sh state)
6777+ ?^ direct direct
6778+ ?~ names.sh ~
6779+ ?^ t.names.sh ~
6780+ =/ n=term i.names.sh
6781+ ?: (lien marks.state |=(x=term =(x n))) ~
6782+ ?: (lien active.state |=(x=term =(x n))) ~
6783+ =/ found=(unit shape) (find-simple-mold n molds.state)
6784+ ?~ found ~
6785+ $(sh u.found, state state(active [n active.state], in-mold &, params ~))
6786+ %fn
6787+ =/ first=(unit [typ=itype state=istate]) (infer-simple-shape sample.sh state)
6788+ ?~ first $(sh sample.sh)
6789+ $(sh product.sh, state state.u.first)
6790+ %cell (nested-field-invalid fields.sh state)
6791+ * ~
6792+ ==
6793+::
6794+++ nested-field-invalid
6795+ |= [fields=(list field) state=istate]
6796+ ^- (unit idiag)
6797+ ?~ fields ~
6798+ =/ sh=shape
6799+ ?- -.i.fields
6800+ %bare shape.i.fields
6801+ %face shape.i.fields
6802+ %pun [%ref at.i.fields ~[name.i.fields]]
6803+ ==
6804+ =/ out=(unit [typ=itype state=istate]) (infer-simple-shape sh state)
6805+ ?~ out (nested-import-invalid sh state)
6806+ $(fields t.fields, state state.u.out)
6807+::
6808+++ sample-import-invalid
6809+ |= [s=sample env=ienv state=istate]
6810+ ^- (unit idiag)
6811+ =/ result=isample-result (infer-sample s env state)
6812+ ?: ?=(%& -.result) ~
6813+ ?. =(p.result "sample mold is not supported by partial inference") ~
6814+ ?- s
6815+ [%face *] (nested-import-invalid shape.s state)
6816+ [%bare *] (nested-import-invalid shape.s state)
6817+ [%pun *] (nested-import-invalid [%ref at.s ~[name.s]] state)
6818+ [%cell *] (nested-samples-invalid items.s env state)
6819+ * ~
6820+ ==
6821+::
6822+++ nested-samples-invalid
6823+ |= [items=(list sample) env=ienv state=istate]
6824+ ^- (unit idiag)
6825+ ?~ items ~
6826+ =/ head=isample-result (infer-sample i.items env state)
6827+ ?: ?=(%| -.head) (sample-import-invalid i.items env state)
6828+ $(items t.items, env env.p.head, state state.p.head)
6829+::
6830+++ infer-simple-shape
6831+ |= [sh=shape state=istate]
6832+ ^- (unit [typ=itype state=istate])
6833+ ?- -.sh
6834+ %hole `[[%var next.state] state(next +(next.state), holes [[next.state at.sh] holes.state])]
6835+ %aura
6836+ ?: =(0 aura.sh) `[[%any-atom ~] state]
6837+ `[[%atom aura.sh] state]
6838+ %flag `[[%flag ~] state]
6839+ %noun `[[%noun ~] state]
6840+ %void `[[%empty ~] state]
6841+ %const
6842+ ?. |(=(%term form.lit.sh) =(%null form.lit.sh) =(%loobean form.lit.sh)) ~
6843+ ?: &(=(%loobean form.lit.sh) !|(=(0 val.lit.sh) =(1 val.lit.sh))) ~
6844+ `[[%const lit.sh] state]
6845+ %union
6846+ =/ pairs=(list upair) (union-pairs cases.sh molds.state)
6847+ ?: (lien pairs |=(p=upair =(%overlap relation.p))) ~
6848+ =/ source-proof=?
6849+ ?: (levy pairs |=(p=upair =(%disjoint relation.p))) &
6850+ &((union-source-state-safe state 256) (union-source-distinct-tags cases.sh molds.state 256))
6851+ ?. source-proof ~
6852+ =/ cs=(unit [types=(list itype) state=istate]) (infer-shape-args cases.sh state)
6853+ ?~ cs ~
6854+ `[[%union types.u.cs ~ ~ ~] state.u.cs]
6855+ %cell (infer-simple-fields fields.sh state)
6856+ %fn
6857+ =/ arg=(unit [typ=itype state=istate]) $(sh sample.sh)
6858+ ?~ arg ~
6859+ =/ out=(unit [typ=itype state=istate]) $(sh product.sh, state state.u.arg)
6860+ ?~ out ~
6861+ `[[%fn typ.u.arg typ.u.out] state.u.out]
6862+ %ref
6863+ ?~ names.sh ~
6864+ =/ n=term i.names.sh
6865+ ?^ t.names.sh
6866+ ?^ t.t.names.sh ~
6867+ =/ iface=(unit ifile) (find-jibb-interface i.t.names.sh jimports.state)
6868+ ?^ iface
6869+ =/ found=(unit ischeme) (find-jibb-mold n u.iface)
6870+ ?~ found ~
6871+ ?^ vars.u.found ~
6872+ `[(itype-in-import typ.u.found u.iface i.t.names.sh prelude.state) state]
6873+ =/ found=(unit itype)
6874+ (find-imported-mold i.t.names.sh n externals.state surs.state)
6875+ ?~ found ~
6876+ `[u.found state]
6877+ ?: (lien marks.state |=(x=term =(x n)))
6878+ ?^ (find-simple-mold n molds.state) ~
6879+ =/ imported=(unit itype) (find-imported-mark n mark-externals.state marks.state)
6880+ ?~ imported ~
6881+ `[u.imported state]
6882+ ?: (lien active.state |=(x=term =(x n))) ~
6883+ =/ found=(unit shape) (find-simple-mold n molds.state)
6884+ ?~ found
6885+ ?: (lien molds.state |=(m=[name=term body=shape] =(name.m n))) ~
6886+ ?~ prelude.state ~
6887+ =/ prelude-entry=(unit ischeme) (find-jibb-mold n u.prelude.state)
6888+ ?~ prelude-entry ~
6889+ ?^ vars.u.prelude-entry ~
6890+ `[typ.u.prelude-entry state]
6891+ =/ direct=(unit itype) (simple-source-recursive n u.found state)
6892+ ?^ direct `[u.direct state]
6893+ =/ out=(unit [typ=itype state=istate])
6894+ $(sh u.found, state state(active [n active.state], in-mold &, params ~))
6895+ ?~ out ~
6896+ ?^ (unresolved-hole holes.state.u.out holes.state state.u.out) ~
6897+ `[(label-direct-union typ.u.out u.found n state) state.u.out(active active.state, in-mold in-mold.state, params params.state, holes holes.state)]
6898+ %apply
6899+ ?~ ref.sh ~
6900+ =/ args=(unit [types=(list itype) state=istate]) (infer-shape-args args.sh state)
6901+ ?~ args ~
6902+ =/ n=term i.ref.sh
6903+ ?^ t.ref.sh
6904+ ?^ t.t.ref.sh ~
6905+ =/ iface=(unit ifile) (find-jibb-interface i.t.ref.sh jimports.state.u.args)
6906+ ?~ iface ~
6907+ =/ template=(unit ischeme) (find-jibb-mold n u.iface)
6908+ ?~ template ~
6909+ ?~ vars.u.template ~
6910+ =/ applied=(unit itype) (template-apply u.template types.u.args)
6911+ ?~ applied ~
6912+ `[(itype-in-import u.applied u.iface i.t.ref.sh prelude.state.u.args) state.u.args]
6913+ ?: (lien active.state.u.args |=(x=term =(x n))) ~
6914+ =/ found=(unit shape) (find-simple-mold n molds.state.u.args)
6915+ ?~ found
6916+ ?: (lien molds.state.u.args |=(m=[name=term body=shape] =(name.m n))) ~
6917+ ?~ prelude.state.u.args ~
6918+ =/ prelude-entry=(unit ischeme) (find-jibb-mold n u.prelude.state.u.args)
6919+ ?~ prelude-entry ~
6920+ ?~ vars.u.prelude-entry ~
6921+ =/ applied=(unit itype) (template-apply u.prelude-entry types.u.args)
6922+ ?~ applied ~
6923+ `[u.applied state.u.args]
6924+ ?. ?=(%generic -.u.found) ~
6925+ =/ grec=(unit itype) (simple-source-generic-recursive n u.found types.u.args state.u.args)
6926+ ?^ grec `[u.grec state.u.args]
6927+ ?. (distinct-params vars.u.found) ~
6928+ =/ params=(unit iparams) (bind-params vars.u.found types.u.args)
6929+ ?~ params ~
6930+ =/ out=(unit [typ=itype state=istate])
6931+ $(sh body.u.found, state state.u.args(active [n active.state.u.args], in-mold &, params u.params))
6932+ ?~ out ~
6933+ ?^ (unresolved-hole holes.state.u.out holes.state.u.args state.u.out) ~
6934+ ?: &(?=(%union -.typ.u.out) !?=(%union -.body.u.found) ?=(~ origin.typ.u.out)) ~
6935+ ?: &(?=(%union -.typ.u.out) ?=(%union -.body.u.found) !(lien top-molds.state.u.args |=(x=term =(x n)))) ~
6936+ =? typ.u.out &(?=(%union -.typ.u.out) ?=(%union -.body.u.found))
6937+ (label-direct-union typ.u.out(args types.u.args) u.found n state.u.args)
6938+ `[typ.u.out state.u.out(active active.state.u.args, in-mold in-mold.state.u.args, params params.state.u.args, holes holes.state.u.args)]
6939+ %tvar
6940+ =/ param=(unit itype) (iparam-lookup name.sh params.state)
6941+ ?^ param `[u.param state]
6942+ ?: in-mold.state ~
6943+ =/ n=(unit @ud) (icap-lookup name.sh caps.state)
6944+ ?^ n `[[%var u.n] state]
6945+ `[[%var next.state] state(next +(next.state), caps [[name.sh next.state at.sh] caps.state])]
6946+ * ~
6947+ ==
6948+::
6949+++ infer-simple-fields
6950+ |= [fields=(list field) state=istate]
6951+ ^- (unit [typ=itype state=istate])
6952+ ?~ fields ~
6953+ =/ field-shape=shape
6954+ ?- -.i.fields
6955+ %bare shape.i.fields
6956+ %face shape.i.fields
6957+ %pun [%ref at.i.fields ~[name.i.fields]]
6958+ ==
6959+ =/ head=(unit [typ=itype state=istate]) (infer-simple-shape field-shape state)
6960+ ?~ head ~
6961+ =/ t=itype typ.u.head
6962+ =. t
6963+ ?- -.i.fields
6964+ %bare t
6965+ %face [%face name.i.fields t]
6966+ %pun [%face name.i.fields t]
6967+ ==
6968+ ?~ t.fields `[t state.u.head]
6969+ =/ tail=(unit [typ=itype state=istate]) $(fields t.fields, state state.u.head)
6970+ ?~ tail ~
6971+ `[[%cell t typ.u.tail] state.u.tail]
6972+::
6973+++ infer-sample
6974+ |= [s=sample env=ienv state=istate]
6975+ ^- isample-result
6976+ ?- -.s
6977+ %bind
6978+ ?: |(=(name.s %proj) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
6979+ [%| "sample shadows a name"]
6980+ =/ t=itype [%var next.state]
6981+ [%& t [[name.s [t ~]] env] state(next +(next.state), binders [next.state binders.state])]
6982+ %face
6983+ ?: |(=(name.s %proj) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
6984+ [%| "sample shadows a name"]
6985+ =/ t=(unit [typ=itype state=istate]) (infer-simple-shape shape.s state)
6986+ ?~ t [%| "sample mold is not supported by partial inference"]
6987+ [%& typ.u.t [[name.s [typ.u.t ~]] env] state.u.t]
6988+ %bare
6989+ =/ t=(unit [typ=itype state=istate]) (infer-simple-shape shape.s state)
6990+ ?~ t [%| "sample mold is not supported by partial inference"]
6991+ [%& typ.u.t env state.u.t]
6992+ %pun
6993+ $(s [%face at.s name.s [%ref at.s ~[name.s]]])
6994+ %cell
6995+ (infer-sample-items items.s env state)
6996+ ==
6997+::
6998+:: Cell-sample binders are faces on their positions; at the top of a
6999+:: sample a binder only supplies a name for the whole sample.
7000+::
7001+++ infer-sample-items
7002+ |= [items=(list sample) env=ienv state=istate]
7003+ ^- isample-result
7004+ ?~ items [%| "empty sample is not supported by partial inference"]
7005+ =/ head=isample-result (infer-sample i.items env state)
7006+ ?: ?=(%| -.head) head
7007+ =/ ht=itype typ.p.head
7008+ =. ht
7009+ ?- -.i.items
7010+ %bind [%face name.i.items ht]
7011+ %face [%face name.i.items ht]
7012+ %pun [%face name.i.items ht]
7013+ * ht
7014+ ==
7015+ ?~ t.items [%& ht env.p.head state.p.head]
7016+ =/ tail=isample-result $(items t.items, env env.p.head, state state.p.head)
7017+ ?: ?=(%| -.tail) tail
7018+ [%& [%cell ht typ.p.tail] env.p.tail state.p.tail]
7019+::
7020+:: Local definitions generalize only variables outside their enclosing
7021+:: environment and explicit-capital scope. Recursive gate groups use
7022+:: monomorphic placeholders while their bodies are checked.
7023+::
7024++$ ilocal-result (each [env=ienv state=istate] idiag)
7025+++ free-env-vars
7026+ |= [env=ienv sub=isub]
7027+ ^- (list @ud)
7028+ ?~ env ~
7029+ =/ sc=ischeme scheme.i.env
7030+ =/ ids=(list @ud) (unique-type-vars (itype-vars typ.sc))
7031+ =/ free=(list @ud) ~
7032+ |-
7033+ ?~ ids (weld free (free-env-vars t.env sub))
7034+ ?: (lien vars.sc |=(n=@ud =(n i.ids))) $(ids t.ids)
7035+ =/ resolved=itype (itype-normalize [%var i.ids] sub)
7036+ $(ids t.ids, free (weld (itype-vars resolved) free))
7037+::
7038+++ free-cap-vars
7039+ |= [caps=icaps sub=isub]
7040+ ^- (list @ud)
7041+ ?~ caps ~
7042+ (weld (itype-vars (itype-normalize [%var id.i.caps] sub)) $(caps t.caps))
7043+::
7044+++ local-names-valid
7045+ |= [ds=(list def) env=ienv state=istate]
7046+ ^- ?
7047+ =/ names=(list term) (global-value-names ds)
7048+ |-
7049+ ?~ ds &
7050+ ?: ?=(%mold -.i.ds) $(ds t.ds)
7051+ ?: =(name.i.ds %proj) |
7052+ ?. (unique-value-name name.i.ds names) |
7053+ ?: ?=(^ (ienv-lookup name.i.ds env)) |
7054+ ?: (lien globals.state |=(n=term =(n name.i.ds))) |
7055+ $(ds t.ds)
7056+::
7057+:: The supported local molds are nonrecursive simple aliases. Validate
7058+:: all of them, including unused ones, before checking any local values.
7059+:: The enclosing gate sample was checked before this scope was entered.
7060+::
7061+++ local-value-defs
7062+ |= ds=(list def)
7063+ ^- (list def)
7064+ ?~ ds ~
7065+ ?: ?=(%mold -.i.ds) $(ds t.ds)
7066+ [i.ds $(ds t.ds)]
7067+::
7068+++ local-mold-names-valid
7069+ |= [locals=imolds state=istate]
7070+ ^- ?
7071+ =/ names=(list term) (turn locals |=(m=[name=term body=shape] name.m))
7072+ |-
7073+ ?~ locals &
7074+ =/ n=term name.i.locals
7075+ ?: =(n %proj) |
7076+ ?. (unique-value-name n names) |
7077+ ?: (lien molds.state |=(m=[name=term body=shape] =(n name.m))) |
7078+ ?: (lien marks.state |=(m=term =(n m))) |
7079+ ?: (lien reserved-molds.state |=(m=term =(n m))) |
7080+ ?: (lien surs.state |=(m=term =(n m))) |
7081+ $(locals t.locals)
7082+::
7083+++ local-molds-supported
7084+ |= [locals=imolds state=istate]
7085+ ^- ?
7086+ ?~ locals &
7087+ =/ m=[name=term body=shape] i.locals
7088+ =/ inferred=(unit [template=ischeme state=istate])
7089+ (infer-mold-template body.m state(active [name.m active.state], in-mold &))
7090+ ?~ inferred |
7091+ $(locals t.locals)
7092+::
7093+:: Gather written capitals belonging to one ++. Nested local definitions
7094+:: establish their own scopes; inline gates remain in the enclosing scope.
7095++$ icap-site [name=@t at=span]
7096+++ scope-shape
7097+ |= s=shape
7098+ ^- (list icap-site)
7099+ ?- -.s
7100+ %tvar ~[[name.s at.s]]
7101+ %apply (zing (turn args.s scope-shape))
7102+ %cell (zing (turn fields.s scope-field))
7103+ %union (zing (turn cases.s scope-shape))
7104+ %fn (weld (scope-shape sample.s) (scope-shape product.s))
7105+ %generic
7106+ =/ inside=(list icap-site) (scope-shape body.s)
7107+ (skim inside |=(site=icap-site !(lien vars.s |=(v=@t =(v name.site)))))
7108+ * ~
7109+ ==
7110+::
7111+++ scope-field
7112+ |= f=field
7113+ ^- (list icap-site)
7114+ ?- -.f
7115+ %face (scope-shape shape.f)
7116+ %bare (scope-shape shape.f)
7117+ %pun ~
7118+ ==
7119+::
7120+++ scope-sample
7121+ |= s=sample
7122+ ^- (list icap-site)
7123+ ?- -.s
7124+ %face (scope-shape shape.s)
7125+ %bare (scope-shape shape.s)
7126+ %cell (zing (turn items.s scope-sample))
7127+ * ~
7128+ ==
7129+::
7130+++ scope-pieces
7131+ |= ps=(list piece)
7132+ ^- (list icap-site)
7133+ ?~ ps ~
7134+ =/ first=(list icap-site)
7135+ ?- -.i.ps
7136+ %expr (scope-expr p.i.ps)
7137+ %text ~
7138+ ==
7139+ (weld first $(ps t.ps))
7140+::
7141+++ scope-qsegs
7142+ |= ps=(list qseg)
7143+ ^- (list icap-site)
7144+ ?~ ps ~
7145+ =/ first=(list icap-site)
7146+ ?- -.i.ps
7147+ %expr (scope-expr p.i.ps)
7148+ %knot ~
7149+ ==
7150+ (weld first $(ps t.ps))
7151+::
7152+++ scope-edits
7153+ |= xs=(list edit)
7154+ ^- (list icap-site)
7155+ ?~ xs ~
7156+ =/ first=(list icap-site) (scope-expr val.i.xs)
7157+ (weld first $(xs t.xs))
7158+::
7159+++ scope-items
7160+ |= xs=(list item)
7161+ ^- (list icap-site)
7162+ ?~ xs ~
7163+ =/ first=(list icap-site) (scope-expr val.i.xs)
7164+ (weld first $(xs t.xs))
7165+::
7166+++ scope-arms
7167+ |= xs=(list arm)
7168+ ^- (list icap-site)
7169+ ?~ xs ~
7170+ =/ first=(list icap-site) (scope-expr val.i.xs)
7171+ (weld first $(xs t.xs))
7172+::
7173+++ scope-exprs
7174+ |= xs=(list expr)
7175+ ^- (list icap-site)
7176+ ?~ xs ~
7177+ =/ first=(list icap-site) (scope-expr i.xs)
7178+ (weld first $(xs t.xs))
7179+::
7180+++ scope-expr
7181+ |= e=expr
7182+ ^- (list icap-site)
7183+ ?- -.e
7184+ %str (scope-pieces pieces.e)
7185+ %qath (scope-qsegs segs.e)
7186+ %change (scope-edits edits.e)
7187+ %pair (scope-expr val.e)
7188+ %unit (scope-expr val.e)
7189+ %group (scope-expr inner.e)
7190+ %list (scope-exprs items.e)
7191+ %tuple (scope-items items.e)
7192+ %gate
7193+ =/ first=(list icap-site) (scope-sample sample.e)
7194+ =/ last=(list icap-site) (scope-expr body.e)
7195+ (weld first last)
7196+ %gate-wide
7197+ =/ first=(list icap-site) (scope-sample sample.e)
7198+ =/ last=(list icap-site) (scope-expr body.e)
7199+ (weld first last)
7200+ %call
7201+ =/ first=(list icap-site) (scope-expr head.e)
7202+ =/ last=(list icap-site) (scope-exprs args.e)
7203+ (weld first last)
7204+ %cast
7205+ =/ first=(list icap-site) (scope-shape shape.e)
7206+ =/ last=(list icap-site) (scope-expr val.e)
7207+ (weld first last)
7208+ %trace
7209+ =/ first=(list icap-site) (scope-expr val.e)
7210+ =/ last=(list icap-site) (scope-expr then.e)
7211+ (weld first last)
7212+ %branch
7213+ =/ first=(list icap-site) (scope-expr subject.e)
7214+ =/ last=(list icap-site) (scope-arms arms.e)
7215+ (weld first last)
7216+ %body (scope-expr final.e)
7217+ * ~
7218+ ==
7219+::
7220+++ reserve-cap-sites
7221+ |= [sites=(list icap-site) state=istate]
7222+ ^- istate
7223+ ?~ sites state
7224+ ?: ?=(^ (icap-lookup name.i.sites caps.state)) $(sites t.sites)
7225+ $(sites t.sites, state state(next +(next.state), caps [[name.i.sites next.state at.i.sites] caps.state]))
7226+::
7227+++ reserve-def-caps
7228+ |= [e=expr state=istate]
7229+ ^- istate
7230+ (reserve-cap-sites (scope-expr e) state)
7231+::
7232+++ infer-local-defs
7233+ |= [ds=(list def) env=ienv state=istate]
7234+ ^- ilocal-result
7235+ =/ remaining=(list def) ~
7236+ =/ progressed=? |
7237+ |-
7238+ ?~ ds
7239+ ?~ remaining [%& env state]
7240+ ?. progressed
7241+ =/ pending=(list def) (flop remaining)
7242+ =/ groups=icomponents (graph-components pending (global-value-names pending))
7243+ =/ grouped=(unit [rest=(list def) env=ienv state=istate])
7244+ (try-local-group pending groups env state)
7245+ ?~ grouped [%| ["local definitions need unsupported inference" ~]]
7246+ $(ds rest.u.grouped, remaining ~, env env.u.grouped, state state.u.grouped, progressed |)
7247+ $(ds (flop remaining), remaining ~, progressed |)
7248+ =/ d=def i.ds
7249+ ?> ?=(%value -.d)
7250+ =/ local-state=istate (reserve-def-caps val.d state)
7251+ =/ inferred=iresult (infer-fragment val.d env local-state)
7252+ =/ retried=? ?=(%| -.inferred)
7253+ =? inferred retried (infer-recursive-gate d env local-state)
7254+ ?: ?=(%| -.inferred) $(ds t.ds, remaining [d remaining])
7255+ ?: !=(obligations.state.p.inferred obligations.state) [%| ["deferred local definition needs unsupported inference" ~]]
7256+ =. state.p.inferred (promote-restricted-numbers state.p.inferred env)
7257+ =. state.p.inferred (default-hole-numbers holes.state.p.inferred holes.state state.p.inferred env !(itype-has-gate (itype-normalize typ.p.inferred sub.state.p.inferred)))
7258+ =/ hole=(unit idiag) (unresolved-hole holes.state.p.inferred holes.state state.p.inferred)
7259+ ?^ hole [%| u.hole]
7260+ =/ merged=(unit [first=icap second=icap])
7261+ (merged-capitals caps.state.p.inferred sub.state.p.inferred)
7262+ ?^ merged
7263+ [%| ["distinct type variables `{(trip name.first.u.merged)}` and `{(trip name.second.u.merged)}` must not be forced equal; use the same capital for a shared type" ~[[at.first.u.merged "first type variable"] [at.second.u.merged "second type variable"]]]]
7264+ ?: (constrained-capitals caps.state.p.inferred sub.state.p.inferred)
7265+ [%| ["explicit capital constraints are not supported by partial inference" ~]]
7266+ =/ typ=itype (itype-normalize typ.p.inferred sub.state.p.inferred)
7267+ ?: |((pending-tags tags.state.p.inferred sub.state.p.inferred) (itype-has-tag typ))
7268+ $(ds t.ds, remaining [d remaining])
7269+ ?: (unsupported-atom-vars typ caps.state.p.inferred binders.state.p.inferred sub.state.p.inferred)
7270+ $(ds t.ds, remaining [d remaining])
7271+ =/ free=(list @ud)
7272+ (weld (free-env-vars env sub.state.p.inferred) (free-cap-vars caps.state sub.state.p.inferred))
7273+ =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
7274+ =. vars (skim vars |=(n=@ud !(lien free |=(f=@ud =(f n)))))
7275+ $(ds t.ds, env [[name.d [typ vars]] env], state state.p.inferred(caps caps.state, holes holes.state), progressed &)
7276+::
7277+:: Try complete cyclic local groups after individual definitions stall.
7278+:: Components with non-gates or unresolved constraints stay unavailable.
7279+::
7280+++ try-local-group
7281+ |= [ds=(list def) groups=icomponents env=ienv state=istate]
7282+ ^- (unit [rest=(list def) env=ienv state=istate])
7283+ ?~ groups ~
7284+ =/ names=(list term) i.groups
7285+ ?. (gth (lent names) 1) $(groups t.groups)
7286+ =/ members=(list def)
7287+ (skim ds |=(d=def &(?=(%value -.d) (lien names |=(n=term =(n name.d))))))
7288+ ?. =((lent members) (lent names)) $(groups t.groups)
7289+ =/ result=ilocal-result (infer-gate-group members env state)
7290+ ?: ?=(%| -.result) $(groups t.groups)
7291+ =/ rest=(list def)
7292+ (skim ds |=(d=def !(lien names |=(n=term =(n name.d)))))
7293+ =/ more=(unit [rest=(list def) env=ienv state=istate])
7294+ $(ds rest, groups t.groups, env env.p.result, state state.p.result)
7295+ ?^ more more
7296+ `[rest env.p.result state.p.result]
7297+::
7298+:: Read only fields of a known record. Unresolved field constraints and
7299+:: ambiguous repeated faces are outside this fragment. Imported record
7300+:: spines with repeated names are unavailable when used.
7301+::
7302+++ record-fields-named
7303+ |= [name=term t=itype sub=isub]
7304+ ^- (list itype)
7305+ =. t (itype-walk t sub)
7306+ ?: ?=(%face -.t)
7307+ ?:(=(name name.t) ~[body.t] ~)
7308+ ?. ?=(%cell -.t) ~
7309+ =/ first=(list itype) ~
7310+ =/ head=itype (itype-walk hed.t sub)
7311+ =? first ?=(%face -.head) ?:(=(name name.head) ~[body.head] ~)
7312+ (weld first $(t tal.t))
7313+::
7314+++ infer-field-wing
7315+ |= [names=(list term) env=ienv state=istate]
7316+ ^- iresult
7317+ =/ reverse=(list term) (flop names)
7318+ ?~ reverse [%| ["empty wing" ~]]
7319+ =/ iface=(unit ifile) (find-jibb-interface i.reverse jimports.state)
7320+ =/ fields=(list term) t.reverse
7321+ ?~ fields [%| ["field access is not supported by partial inference" ~]]
7322+ =/ scheme=(unit ischeme)
7323+ ?~ iface
7324+ (ienv-lookup i.reverse env)
7325+ (ienv-lookup i.fields values.u.iface)
7326+ ?~ scheme
7327+ ?^ iface [%| ["module member is not available to partial inference" ~]]
7328+ [%| ["field access is not supported by partial inference" ~]]
7329+ =/ inst=[typ=itype state=istate]
7330+ ?~ iface (instantiate-scheme u.scheme state)
7331+ =/ imported=ischeme u.scheme
7332+ =. typ.imported (itype-in-import typ.imported u.iface i.reverse prelude.state)
7333+ (instantiate-scheme imported state)
7334+ =/ remaining=(list term) ?~(iface fields t.fields)
7335+ =/ typ=itype typ.inst
7336+ |-
7337+ ?~ remaining [%& typ state.inst]
7338+ =/ found=(list itype) (record-fields-named i.remaining typ sub.state.inst)
7339+ ?~ found [%| ["field is not available to partial inference" ~]]
7340+ ?^ t.found [%| ["field name is ambiguous in partial inference" ~]]
7341+ $(remaining t.remaining, typ i.found)
7342+::
7343+:: Propagate a known union or list through supported loobean, unit and list
7344+:: branches. Empty bodies and groups are transparent; bodies with definitions
7345+:: keep their normal scoping and wait for general bidirectional inference.
7346+::
7347+++ context-union-branch
7348+ |= e=expr
7349+ ^- ?
7350+ ?- -.e
7351+ %branch &
7352+ %group $(e inner.e)
7353+ %body ?~(defs.e $(e final.e) |)
7354+ * |
7355+ ==
7356+::
7357+++ infer-union-context
7358+ |= [e=expr expected=itype env=ienv state=istate context=span]
7359+ ^- iresult
7360+ ?: ?=(%group -.e) $(e inner.e)
7361+ ?: &(?=(%body -.e) ?=(~ defs.e)) $(e final.e)
7362+ ?: &(?=(%collection -.expected) =(%list name.expected) (context-list-expression e))
7363+ (infer-list-context e expected env state context)
7364+ ?: ?=(%branch -.e)
7365+ =/ empty-list=(unit iresult) (empty-list-null-branch e env state `[expected context])
7366+ ?^ empty-list u.empty-list
7367+ ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
7368+ ?~ t.arms.e [%| ["branch pattern is not supported by partial inference" ~]]
7369+ ?^ t.t.arms.e [%| ["branch is not supported by partial inference" ~]]
7370+ =/ x=arm i.arms.e
7371+ =/ y=arm i.t.arms.e
7372+ ?: |((unit-empty-pattern pat.x) (unit-empty-pattern pat.y))
7373+ (infer-unit-branch e env state `[expected context])
7374+ ?. &(?=(%lit -.pat.x) ?=(%lit -.pat.y))
7375+ [%| ["branch pattern is not supported by partial inference" ~]]
7376+ ?. &(=(%loobean form.lit.pat.x) =(%loobean form.lit.pat.y))
7377+ [%| ["branch pattern is not supported by partial inference" ~]]
7378+ ?: =(val.lit.pat.x val.lit.pat.y)
7379+ [%| ["branch does not cover both loobeans" ~]]
7380+ =/ subject=iresult (infer-fragment subject.e env state)
7381+ ?: ?=(%| -.subject) subject
7382+ =/ subject-type=itype (itype-normalize typ.p.subject sub.state.p.subject)
7383+ ?: ?=(%union -.subject-type)
7384+ [%| ["contextual union-pattern branch is not supported by partial inference" ~]]
7385+ =/ su=(unit isub) (itype-unify typ.p.subject [%flag ~] sub.state.p.subject)
7386+ ?~ su [%| ["loobean branch subject does not unify with ?" ~]]
7387+ =/ left=iresult $(e val.x, state state.p.subject(sub u.su))
7388+ ?: ?=(%| -.left) left
7389+ =/ right=iresult $(e val.y, state state.p.left)
7390+ ?: ?=(%| -.right) right
7391+ [%& expected state.p.right]
7392+ =/ value=iresult (infer-fragment e env state)
7393+ ?: ?=(%| -.value) value
7394+ =/ fit=ifit (itype-fit typ.p.value expected sub.state.p.value next.state.p.value)
7395+ ?: ?=(%unknown -.fit)
7396+ ?: &(?=(%collection -.expected) =(%list name.expected))
7397+ [%| ["branch list constraint is not supported by partial inference" ~]]
7398+ ?: ?=(%flag -.expected) [%| ["branch loobean constraint is not supported by partial inference" ~]]
7399+ [%| ["branch union constraint is not supported by partial inference" ~]]
7400+ ?: ?=(%bad -.fit)
7401+ =/ missing=(unit idiag) (missing-union-tag e expected sub.state.p.value context)
7402+ ?^ missing [%| u.missing]
7403+ =/ nested=(unit idiag) (nested-missing-tag e typ.p.value expected sub.state.p.value next.state.p.value context)
7404+ ?^ nested [%| u.nested]
7405+ ?: &(?=(%collection -.expected) =(%list name.expected))
7406+ [%| ["branch arm does not fit its expected list" ~[[context "expected list"] [(span-of e) "branch arm"]]]]
7407+ ?: ?=(%flag -.expected)
7408+ [%| ["branch arm does not fit its expected loobean" ~[[context "expected loobean"] [(span-of e) "branch arm"]]]]
7409+ [%| ["branch arm does not fit its expected union" ~[[context "expected union"] [(span-of e) "branch arm"]]]]
7410+ [%& expected state.p.value(sub sub.fit, next next.fit)]
7411+::
7412+:: A list expression needs a known list target and the validated prelude list.
7413+:: Literal items and unfaced two-item cons cells receive that target one by
7414+:: one; pending constraints elsewhere stay in the threaded state.
7415+::
7416+++ context-list-expression
7417+ |= e=expr
7418+ ^- ?
7419+ ?- -.e
7420+ %list &
7421+ %tuple &
7422+ %lit |(=(%null form.lit.e) &(=(%term form.lit.e) =(0 val.lit.e)))
7423+ %group $(e inner.e)
7424+ %body ?~(defs.e $(e final.e) |)
7425+ * |
7426+ ==
7427+::
7428+++ infer-list-context
7429+ |= [e=expr expected=itype env=ienv state=istate context=span]
7430+ ^- iresult
7431+ ?: ?=(%group -.e) $(e inner.e)
7432+ ?: &(?=(%body -.e) ?=(~ defs.e)) $(e final.e)
7433+ ?~ prelude.state [%| ["list literal needs the standard prelude in partial inference" ~]]
7434+ ?. =(at.u.prelude.state /lib/jibb/prelude/jibb)
7435+ [%| ["list literal needs the standard prelude in partial inference" ~]]
7436+ =/ standard=(unit ischeme) (find-jibb-mold %list u.prelude.state)
7437+ ?~ standard [%| ["list literal needs the standard prelude in partial inference" ~]]
7438+ ?. =(u.standard [[%collection %list ~[[%var 0]]] ~[0]])
7439+ [%| ["list literal needs the standard prelude in partial inference" ~]]
7440+ =/ target=itype (itype-walk expected sub.state)
7441+ ?. ?=(%collection -.target) [%| ["list context is not supported by partial inference" ~]]
7442+ ?. =(%list name.target) [%| ["list context is not supported by partial inference" ~]]
7443+ ?~ args.target [%| ["list context is not supported by partial inference" ~]]
7444+ ?^ t.args.target [%| ["list context is not supported by partial inference" ~]]
7445+ ?: ?=(%lit -.e)
7446+ ?. |(=(%null form.lit.e) &(=(%term form.lit.e) =(0 val.lit.e)))
7447+ [%| ["list expression is not supported by partial inference" ~]]
7448+ [%& target state]
7449+ ?: ?=(%list -.e)
7450+ =/ result=iresult (infer-list-items items.e i.args.target env state context)
7451+ ?: ?=(%| -.result) result
7452+ [%& target state.p.result]
7453+ ?. ?=(%tuple -.e) [%| ["list expression is not supported by partial inference" ~]]
7454+ ?~ items.e [%| ["cons shape is not supported by partial inference" ~]]
7455+ ?~ t.items.e [%| ["cons shape is not supported by partial inference" ~]]
7456+ ?^ t.t.items.e [%| ["cons shape is not supported by partial inference" ~]]
7457+ ?^ face.i.items.e [%| ["faced cons is not supported by partial inference" ~]]
7458+ ?^ face.i.t.items.e [%| ["faced cons is not supported by partial inference" ~]]
7459+ =/ head=iresult (infer-list-items ~[val.i.items.e] i.args.target env state context)
7460+ ?: ?=(%| -.head) head
7461+ =/ target=itype (itype-walk target sub.state.p.head)
7462+ =/ tail=iresult
7463+ ?: (context-list-expression val.i.t.items.e)
7464+ (infer-list-context val.i.t.items.e target env state.p.head context)
7465+ (infer-fragment val.i.t.items.e env state.p.head)
7466+ ?: ?=(%| -.tail) tail
7467+ =/ fit=ifit (itype-fit typ.p.tail target sub.state.p.tail next.state.p.tail)
7468+ ?: ?=(%unknown -.fit) [%| ["list tail constraint is not supported by partial inference" ~]]
7469+ ?: ?=(%bad -.fit)
7470+ [%| ["list tail does not fit its expected type" ~[[context (site-type-note "expected list" target sub.state.p.tail)] [(span-of val.i.t.items.e) (site-type-note "list tail" typ.p.tail sub.state.p.tail)]]]]
7471+ [%& target state.p.tail(sub sub.fit, next next.fit)]
7472+::
7473+++ infer-open-list-items
7474+ |= [items=(list expr) expected=itype env=ienv state=istate context=span]
7475+ ^- iresult
7476+ ?~ items [%& expected state]
7477+ =/ target=itype (itype-walk expected sub.state)
7478+ =/ value=iresult (infer-call-context-arg i.items target env state context)
7479+ ?: ?=(%| -.value) value
7480+ =/ fit=ifit (itype-fit typ.p.value target sub.state.p.value next.state.p.value)
7481+ ?: ?=(%unknown -.fit) [%| ["list item constraint is not supported by partial inference" ~]]
7482+ ?: ?=(%bad -.fit)
7483+ ?: |((itype-family-related typ.p.value target sub.state.p.value) (itype-has-any-atom typ.p.value sub.state.p.value) (itype-has-any-atom target sub.state.p.value))
7484+ [%| ["list item widening is not supported by partial inference" ~]]
7485+ [%| ["list items do not have compatible types" ~[[context (site-type-note "expected item" target sub.state.p.value)] [(span-of i.items) (site-type-note "list item" typ.p.value sub.state.p.value)]]]]
7486+ ?: (itype-has-tag (itype-normalize expected sub.fit))
7487+ [%| ["list item needs context in partial inference" ~]]
7488+ $(items t.items, state state.p.value(sub sub.fit, next next.fit))
7489+::
7490+++ infer-list-items
7491+ |= [items=(list expr) expected=itype env=ienv state=istate context=span]
7492+ ^- iresult
7493+ ?~ items [%& expected state]
7494+ =/ target=itype (itype-walk expected sub.state)
7495+ =/ value=iresult (infer-call-context-arg i.items target env state context)
7496+ ?: ?=(%| -.value) value
7497+ =/ fit=ifit (itype-fit typ.p.value target sub.state.p.value next.state.p.value)
7498+ ?: ?=(%unknown -.fit) [%| ["list item constraint is not supported by partial inference" ~]]
7499+ ?: ?=(%bad -.fit)
7500+ =/ missing=(unit idiag) (missing-union-tag i.items target sub.state.p.value context)
7501+ ?^ missing [%| u.missing]
7502+ =/ nested=(unit idiag) (nested-missing-tag i.items typ.p.value target sub.state.p.value next.state.p.value context)
7503+ ?^ nested [%| u.nested]
7504+ [%| ["list item does not fit its expected type" ~[[context (site-type-note "expected item" target sub.state.p.value)] [(span-of i.items) (site-type-note "list item" typ.p.value sub.state.p.value)]]]]
7505+ $(items t.items, state state.p.value(sub sub.fit, next next.fit))
7506+::
7507+:: The supported unit pattern covers exactly an atom zero and a cell
7508+:: headed by zero, with a single binder for its payload. Unresolved
7509+:: subjects and all other pattern matrices stay outside this fragment.
7510+::
7511+++ unit-empty-pattern
7512+ |= p=pattern
7513+ ^- ?
7514+ ?. ?=(%lit -.p) |
7515+ =(%null form.lit.p)
7516+::
7517+++ unit-payload-pattern
7518+ |= p=pattern
7519+ ^- (unit term)
7520+ ?. ?=(%cell -.p) ~
7521+ ?~ items.p ~
7522+ ?~ t.items.p ~
7523+ ?^ t.t.items.p ~
7524+ ?. (unit-empty-pattern i.items.p) ~
7525+ ?. ?=(%bind -.i.t.items.p) ~
7526+ `name.i.t.items.p
7527+::
7528+++ unit-empty-case
7529+ |= t=itype
7530+ ^- ?
7531+ ?. ?=(%const -.t) |
7532+ =(0 val.literal.t)
7533+::
7534+++ unit-payload-case
7535+ |= t=itype
7536+ ^- (unit itype)
7537+ ?. ?=(%cell -.t) ~
7538+ ?. (unit-empty-case hed.t) ~
7539+ =/ payload=itype tal.t
7540+ =? payload ?=(%face -.payload) body.payload
7541+ `payload
7542+::
7543+++ unit-union-payload
7544+ |= t=itype
7545+ ^- (unit itype)
7546+ ?. ?=(%union -.t) ~
7547+ ?~ cases.t ~
7548+ ?~ t.cases.t ~
7549+ ?^ t.t.cases.t ~
7550+ ?: (unit-empty-case i.cases.t) (unit-payload-case i.t.cases.t)
7551+ ?: (unit-empty-case i.t.cases.t) (unit-payload-case i.cases.t)
7552+ ~
7553+::
7554+:: List matching currently covers exactly null and a cell of two binders.
7555+:: The head has the element type and the tail has the whole list type.
7556+:: Other patterns and lists whose element mold is empty remain unsupported.
7557+::
7558+++ list-payload-pattern
7559+ |= p=pattern
7560+ ^- (unit [head=term tail=term])
7561+ ?. ?=(%cell -.p) ~
7562+ ?~ items.p ~
7563+ ?~ t.items.p ~
7564+ ?^ t.t.items.p ~
7565+ ?. ?=(%bind -.i.items.p) ~
7566+ ?. ?=(%bind -.i.t.items.p) ~
7567+ `[name.i.items.p name.i.t.items.p]
7568+::
7569+++ infer-list-branch
7570+ |= [e=expr env=ienv state=istate expected=(unit [typ=itype context=span]) typ=itype]
7571+ ^- iresult
7572+ ?> ?=(%branch -.e)
7573+ ?> ?=(%collection -.typ)
7574+ ?. =(%list name.typ) [%| ["list pattern is not supported by partial inference" ~]]
7575+ ?~ prelude.state [%| ["list pattern needs the standard prelude in partial inference" ~]]
7576+ ?. =(at.u.prelude.state /lib/jibb/prelude/jibb)
7577+ [%| ["list pattern needs the standard prelude in partial inference" ~]]
7578+ =/ standard=(unit ischeme) (find-jibb-mold %list u.prelude.state)
7579+ ?~ standard [%| ["list pattern needs the standard prelude in partial inference" ~]]
7580+ ?. =(u.standard [[%collection %list ~[[%var 0]]] ~[0]])
7581+ [%| ["list pattern needs the standard prelude in partial inference" ~]]
7582+ ?~ args.typ [%| ["list pattern is not supported by partial inference" ~]]
7583+ ?^ t.args.typ [%| ["list pattern is not supported by partial inference" ~]]
7584+ =/ item-live=(unit [result=?(%yes %no %unknown) left=@ud])
7585+ (itype-inhabited-proof i.args.typ sub.state caps.state 256)
7586+ ?~ item-live [%| ["list element reachability needs unsupported inference" ~]]
7587+ ?: =(%unknown result.u.item-live) [%| ["list element reachability needs unsupported inference" ~]]
7588+ ?: =(%no result.u.item-live) [%| ["list nonempty pattern is unreachable" ~]]
7589+ ?~ arms.e [%| ["list branch is not supported by partial inference" ~]]
7590+ ?~ t.arms.e [%| ["list branch is not supported by partial inference" ~]]
7591+ ?^ t.t.arms.e [%| ["list branch is not supported by partial inference" ~]]
7592+ =/ x=arm i.arms.e
7593+ =/ y=arm i.t.arms.e
7594+ =/ first-empty=? (unit-empty-pattern pat.x)
7595+ =/ first-name=(unit [head=term tail=term]) (list-payload-pattern pat.x)
7596+ =/ second-name=(unit [head=term tail=term]) (list-payload-pattern pat.y)
7597+ ?. |(&(first-empty ?=(^ second-name)) &((unit-empty-pattern pat.y) ?=(^ first-name)))
7598+ [%| ["list branch pattern is not supported by partial inference" ~]]
7599+ =/ binder=(unit [head=term tail=term]) ?:(first-empty second-name first-name)
7600+ ?~ binder [%| ["list branch pattern is not supported by partial inference" ~]]
7601+ ?: |(=(head.u.binder %proj) =(tail.u.binder %proj) =(head.u.binder tail.u.binder) ?=(^ (ienv-lookup head.u.binder env)) ?=(^ (ienv-lookup tail.u.binder env)) (lien globals.state |=(n=term |(=(n head.u.binder) =(n tail.u.binder)))))
7602+ [%| ["pattern binder shadows a name" ~]]
7603+ =/ extended=ienv [[head.u.binder [i.args.typ ~]] [tail.u.binder [typ ~]] env]
7604+ =/ left=iresult
7605+ ?~ expected (infer-fragment val.x ?:(first-empty env extended) state)
7606+ (infer-union-context val.x typ.u.expected ?:(first-empty env extended) state context.u.expected)
7607+ ?: ?=(%| -.left) left
7608+ =/ right=iresult
7609+ ?~ expected (infer-fragment val.y ?:(first-empty extended env) state.p.left)
7610+ (infer-union-context val.y typ.u.expected ?:(first-empty extended env) state.p.left context.u.expected)
7611+ ?: ?=(%| -.right) right
7612+ ?^ expected [%& typ.u.expected state.p.right]
7613+ =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
7614+ ?~ joined [%| ["list branch results need unsupported inference" ~]]
7615+ [%& typ.p.left state.p.right(sub u.joined)]
7616+::
7617+++ infer-unit-branch
7618+ |= [e=expr env=ienv state=istate expected=(unit [typ=itype context=span])]
7619+ ^- iresult
7620+ ?> ?=(%branch -.e)
7621+ ?~ arms.e [%| ["unit branch is not supported by partial inference" ~]]
7622+ ?~ t.arms.e [%| ["unit branch is not supported by partial inference" ~]]
7623+ ?^ t.t.arms.e [%| ["unit branch is not supported by partial inference" ~]]
7624+ =/ subject=iresult (infer-fragment subject.e env state)
7625+ ?: ?=(%| -.subject) subject
7626+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
7627+ ?: &(?=(%collection -.typ) =(%list name.typ))
7628+ (infer-list-branch e env state.p.subject expected typ)
7629+ =/ x=arm i.arms.e
7630+ =/ y=arm i.t.arms.e
7631+ =/ first-empty=? (unit-empty-pattern pat.x)
7632+ =/ first-name=(unit term) (unit-payload-pattern pat.x)
7633+ =/ second-name=(unit term) (unit-payload-pattern pat.y)
7634+ ?. |(&(first-empty ?=(^ second-name)) &((unit-empty-pattern pat.y) ?=(^ first-name)))
7635+ [%| ["unit branch pattern is not supported by partial inference" ~]]
7636+ =/ binder=(unit term) ?:(first-empty second-name first-name)
7637+ ?~ binder [%| ["unit branch pattern is not supported by partial inference" ~]]
7638+ ?: |(=(u.binder %proj) ?=(^ (ienv-lookup u.binder env)) (lien globals.state |=(n=term =(n u.binder))))
7639+ [%| ["pattern binder shadows a name" ~]]
7640+ =/ payload=(unit itype) (unit-union-payload typ)
7641+ ?~ payload [%| ["unit branch subject is not supported by partial inference" ~]]
7642+ =/ payload-live=(unit [result=?(%yes %no %unknown) left=@ud])
7643+ (itype-inhabited-proof u.payload sub.state.p.subject caps.state.p.subject 256)
7644+ ?~ payload-live [%| ["unit payload reachability needs unsupported inference" ~]]
7645+ ?: =(%unknown result.u.payload-live) [%| ["unit payload reachability needs unsupported inference" ~]]
7646+ ?: =(%no result.u.payload-live) [%| ["unit present pattern is unreachable" ~]]
7647+ =/ extended=ienv [[u.binder [u.payload ~]] env]
7648+ =/ left=iresult
7649+ ?~ expected (infer-fragment val.x ?:(first-empty env extended) state.p.subject)
7650+ (infer-union-context val.x typ.u.expected ?:(first-empty env extended) state.p.subject context.u.expected)
7651+ ?: ?=(%| -.left) left
7652+ =/ right=iresult
7653+ ?~ expected (infer-fragment val.y ?:(first-empty extended env) state.p.left)
7654+ (infer-union-context val.y typ.u.expected ?:(first-empty extended env) state.p.left context.u.expected)
7655+ ?: ?=(%| -.right) right
7656+ ?^ expected [%& typ.u.expected state.p.right]
7657+ =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
7658+ ?~ joined [%| ["unit branch results need unsupported inference" ~]]
7659+ [%& typ.p.left state.p.right(sub u.joined)]
7660+::
7661+:: Infer pieces in order, retaining their substitutions and pending tags.
7662+:: A bare decimal literal has no outside type constraint, so it takes its
7663+:: normal @ud default here. Other open numeric and aura variables wait for
7664+:: deferred constraints, which this fragment does not implement yet.
7665+++ infer-string-pieces
7666+ |= [ps=(list piece) env=ienv state=istate]
7667+ ^- iresult
7668+ ?~ ps [%& [%atom %t] state]
7669+ ?: ?=(%text -.i.ps) $(ps t.ps)
7670+ =/ item=iresult (infer-fragment p.i.ps env state)
7671+ ?: ?=(%| -.item) item
7672+ =/ t=itype (itype-normalize typ.p.item sub.state.p.item)
7673+ ?: |(?=(%atom -.t) ?=(%any-atom -.t))
7674+ $(ps t.ps, state state.p.item)
7675+ ?: &(|(?=(%nvar -.t) ?=(%rnvar -.t)) ?=(%lit -.p.i.ps) =(%number form.lit.p.i.ps))
7676+ $(ps t.ps, state state.p.item)
7677+ ?: &(?=(%collection -.t) =(%list name.t) =(~[[%atom 'tD']] args.t))
7678+ $(ps t.ps, state state.p.item)
7679+ ?: &(?=(%avar -.t) (atom-var-from-cap id.t caps.state.p.item sub.state.p.item))
7680+ [%| ["a generic atom in interpolation needs an aura" ~[[(span-of p.i.ps) "atom with a generic aura"]]]]
7681+ ?: &(?=(%rvar -.t) (atom-var-from-cap id.t caps.state.p.item sub.state.p.item))
7682+ [%| ["a generic atom in interpolation needs an aura" ~[[(span-of p.i.ps) "atom with a generic aura"]]]]
7683+ ?: ?=(%cell -.t)
7684+ [%| ["a cell in interpolation needs a printer" ~[[(span-of p.i.ps) "cell without a printer"]]]]
7685+ [%| ["interpolation type needs unsupported inference" ~]]
7686+::
7687+:: Whole-case coverage for a known union. When a pattern may cover only
7688+:: part of a case, finite loobean refinements are tried below; other
7689+:: partial coverage stays unsupported until the general pattern matrix.
7690++$ imatch ?(%full %none %unknown)
7691+++ union-pattern-items
7692+ |= [ps=(list pattern) t=itype]
7693+ ^- imatch
7694+ ?~ ps %unknown
7695+ ?~ t.ps (union-pattern i.ps t)
7696+ =. t ?:(?=(%face -.t) body.t t)
7697+ ?. ?=(%cell -.t)
7698+ ?: |(?=(%atom -.t) ?=(%any-atom -.t) ?=(%flag -.t) ?=(%const -.t)) %none
7699+ %unknown
7700+ =/ a=imatch (union-pattern i.ps hed.t)
7701+ =/ b=imatch $(ps t.ps, t tal.t)
7702+ ?: |(=(%none a) =(%none b)) %none
7703+ ?:(&(=(%full a) =(%full b)) %full %unknown)
7704+::
7705+++ union-pattern
7706+ |= [p=pattern t=itype]
7707+ ^- imatch
7708+ =. t ?:(?=(%face -.t) body.t t)
7709+ ?- -.p
7710+ %any %full
7711+ %bind %full
7712+ %lit
7713+ ?: ?=(%const -.t) ?:(=(val.literal.t val.lit.p) %full %none)
7714+ ?: ?=(%cell -.t) %none
7715+ ?: ?=(%flag -.t)
7716+ ?:(|(=(0 val.lit.p) =(1 val.lit.p)) %unknown %none)
7717+ %unknown
7718+ %str ?:(?=(%cell -.t) %none %unknown)
7719+ %cell (union-pattern-items items.p t)
7720+ ==
7721+::
7722+++ union-pattern-has-bind
7723+ |= p=pattern
7724+ ^- ?
7725+ ?: ?=(%bind -.p) &
7726+ ?. ?=(%cell -.p) |
7727+ (lien items.p union-pattern-has-bind)
7728+::
7729+++ union-pattern-bind-items
7730+ |= [ps=(list pattern) t=itype env=ienv globals=(list term)]
7731+ ^- (unit ienv)
7732+ ?~ ps ~
7733+ ?~ t.ps (union-pattern-bind i.ps t env globals)
7734+ =. t ?:(?=(%face -.t) body.t t)
7735+ ?. ?=(%cell -.t) ~
7736+ =/ first=(unit ienv) (union-pattern-bind i.ps hed.t env globals)
7737+ ?~ first ~
7738+ $(ps t.ps, t tal.t, env u.first)
7739+::
7740+++ union-pattern-bind
7741+ |= [p=pattern t=itype env=ienv globals=(list term)]
7742+ ^- (unit ienv)
7743+ =. t ?:(?=(%face -.t) body.t t)
7744+ ?: ?=(%bind -.p)
7745+ ?: |(=(name.p %proj) ?=(^ (ienv-lookup name.p env)) (lien globals |=(n=term =(n name.p)))) ~
7746+ `[[name.p [t ~]] env]
7747+ ?: ?=(%cell -.p) (union-pattern-bind-items items.p t env globals)
7748+ `env
7749+::
7750+:: Split loobean fields into finite refinements for partial patterns.
7751+:: Keep original cases for binder types and preserve whole-case matching
7752+:: before trying refinements. Cap products at 64; unknown, empty or opaque
7753+:: shapes stay unsupported rather than implying complete pattern checking.
7754++$ ifinite [origin=@ud base=itype part=itype]
7755+++ finite-product
7756+ |= [hs=(list itype) ts=(list itype) out=(list itype)]
7757+ ^- (list itype)
7758+ ?~ hs out
7759+ =/ rows=(list itype) (turn ts |=(t=itype [%cell i.hs t]))
7760+ $(hs t.hs, out (weld rows out))
7761+::
7762+++ finite-type
7763+ |= t=itype
7764+ ^- (unit (list itype))
7765+ ?- -.t
7766+ %flag
7767+ `~[[%const [%loobean %f 0 '%.y']] [%const [%loobean %f 1 '%.n']]]
7768+ %face
7769+ =/ body=(unit (list itype)) $(t body.t)
7770+ ?~ body ~
7771+ `(turn u.body |=(x=itype [%face name.t x]))
7772+ %cell
7773+ =/ hed=(unit (list itype)) $(t hed.t)
7774+ ?~ hed ~
7775+ =/ tal=(unit (list itype)) $(t tal.t)
7776+ ?~ tal ~
7777+ ?: (gth (mul (lent u.hed) (lent u.tal)) 64) ~
7778+ `(finite-product u.hed u.tal ~)
7779+ * `~[t]
7780+ ==
7781+::
7782+++ finite-cases
7783+ |= [xs=(list itype) out=(list ifinite) origin=@ud]
7784+ ^- (unit (list ifinite))
7785+ ?~ xs `out
7786+ =/ parts=(unit (list itype)) (finite-type i.xs)
7787+ ?~ parts ~
7788+ ?: (gth (add (lent out) (lent u.parts)) 64) ~
7789+ =/ rows=(list ifinite) (turn u.parts |=(t=itype [origin i.xs t]))
7790+ $(xs t.xs, out (weld out rows), origin +(origin))
7791+::
7792+++ infer-known-union-whole
7793+ |= [e=expr env=ienv subject=iresult]
7794+ ^- (unit iresult)
7795+ ?> ?=(%branch -.e)
7796+ ?: ?=(%| -.subject) `subject
7797+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
7798+ ?. ?=(%union -.typ) `[%| ["branch is not supported by partial inference" ~]]
7799+ =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
7800+ ?~ live ~
7801+ =/ cases=(list itype) u.live
7802+ =/ remaining=(list itype) cases
7803+ =/ arms=(list arm) arms.e
7804+ =/ st=istate state.p.subject
7805+ =/ answer=(unit itype) ~
7806+ |-
7807+ ?~ arms
7808+ ?^ remaining
7809+ `[%| ["missing union case {(show-itype i.remaining sub.st)}" ~]]
7810+ ?~ answer `[%| ["empty union branch is not supported by partial inference" ~]]
7811+ `[%& u.answer st]
7812+ =/ a=arm i.arms
7813+ ?: (lien remaining |=(c=itype =(%unknown (union-pattern pat.a c))))
7814+ ~
7815+ =/ matching=(list itype) (skim remaining |=(c=itype =(%full (union-pattern pat.a c))))
7816+ ?~ matching
7817+ ?: (lien cases |=(c=itype =(%full (union-pattern pat.a c))))
7818+ `[%| ["branch arm is covered by earlier arms" ~[[at.pat.a "covered arm"]]]]
7819+ `[%| ["union pattern is not supported by partial inference" ~]]
7820+ ?: &(?=(^ t.matching) (union-pattern-has-bind pat.a))
7821+ `[%| ["a union pattern binding several cases is not supported by partial inference" ~]]
7822+ =/ bound=(unit ienv) (union-pattern-bind pat.a i.matching env globals.st)
7823+ ?~ bound `[%| ["pattern binder shadows a name" ~]]
7824+ =/ body=iresult (infer-fragment val.a u.bound st)
7825+ ?: ?=(%| -.body) `body
7826+ =/ result=itype (itype-normalize typ.p.body sub.state.p.body)
7827+ =/ mismatch=? ?~(answer | !=((itype-normalize u.answer sub.state.p.body) result))
7828+ ?: mismatch `[%| ["union branch result matching needs unsupported inference" ~]]
7829+ $(arms t.arms, remaining (skim remaining |=(c=itype !=(%full (union-pattern pat.a c)))), st state.p.body, answer `result)
7830+::
7831+++ infer-known-union-context-whole
7832+ |= [e=expr expected=itype env=ienv subject=iresult context=span]
7833+ ^- (unit iresult)
7834+ ?> ?=(%branch -.e)
7835+ ?: ?=(%| -.subject) `subject
7836+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
7837+ ?. ?=(%union -.typ) `[%| ["branch is not supported by partial inference" ~]]
7838+ =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
7839+ ?~ live ~
7840+ =/ cases=(list itype) u.live
7841+ =/ remaining=(list itype) cases
7842+ =/ arms=(list arm) arms.e
7843+ =/ st=istate state.p.subject
7844+ =/ answer=(unit itype) ~
7845+ |-
7846+ ?~ arms
7847+ ?^ remaining
7848+ `[%| ["missing union case {(show-itype i.remaining sub.st)}" ~]]
7849+ ?~ answer `[%| ["empty union branch is not supported by partial inference" ~]]
7850+ `[%& expected st]
7851+ =/ a=arm i.arms
7852+ ?: (lien remaining |=(c=itype =(%unknown (union-pattern pat.a c))))
7853+ ~
7854+ =/ matching=(list itype) (skim remaining |=(c=itype =(%full (union-pattern pat.a c))))
7855+ ?~ matching
7856+ ?: (lien cases |=(c=itype =(%full (union-pattern pat.a c))))
7857+ `[%| ["branch arm is covered by earlier arms" ~[[at.pat.a "covered arm"]]]]
7858+ `[%| ["union pattern is not supported by partial inference" ~]]
7859+ ?: &(?=(^ t.matching) (union-pattern-has-bind pat.a))
7860+ `[%| ["a union pattern binding several cases is not supported by partial inference" ~]]
7861+ =/ bound=(unit ienv) (union-pattern-bind pat.a i.matching env globals.st)
7862+ ?~ bound `[%| ["pattern binder shadows a name" ~]]
7863+ =/ body=iresult (infer-call-context-arg val.a expected u.bound st context)
7864+ ?: ?=(%| -.body) `body
7865+ =/ fit=ifit (itype-fit typ.p.body expected sub.state.p.body next.state.p.body)
7866+ ?: ?=(%unknown -.fit) `[%| ["union branch result constraint is not supported by partial inference" ~]]
7867+ ?: ?=(%bad -.fit)
7868+ =/ missing=(unit idiag) (missing-union-tag val.a expected sub.state.p.body context)
7869+ ?^ missing `[%| u.missing]
7870+ =/ nested=(unit idiag) (nested-missing-tag val.a typ.p.body expected sub.state.p.body next.state.p.body context)
7871+ ?^ nested `[%| u.nested]
7872+ `[%| ["union branch arm does not fit its expected type" ~[[context "expected type"] [(span-of val.a) "branch arm"]]]]
7873+ ?: (itype-has-tag (itype-normalize expected sub.fit))
7874+ `[%| ["union branch result needs context in partial inference" ~]]
7875+ $(arms t.arms, remaining (skim remaining |=(c=itype !=(%full (union-pattern pat.a c)))), st state.p.body(sub sub.fit, next next.fit), answer `expected)
7876+::
7877+++ infer-known-union-finite
7878+ |= [e=expr env=ienv subject=iresult expected=(unit [typ=itype context=span])]
7879+ ^- iresult
7880+ ?> ?=(%branch -.e)
7881+ ?: ?=(%| -.subject) subject
7882+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
7883+ ?. ?=(%union -.typ) [%| ["branch is not supported by partial inference" ~]]
7884+ =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
7885+ ?~ live [%| ["union emptiness needs unsupported inference" ~]]
7886+ =/ expanded=(unit (list ifinite)) (finite-cases u.live ~ 0)
7887+ ?~ expanded [%| ["union pattern expansion needs unsupported inference" ~]]
7888+ =/ cases=(list ifinite) u.expanded
7889+ =/ remaining=(list ifinite) cases
7890+ =/ arms=(list arm) arms.e
7891+ =/ st=istate state.p.subject
7892+ =/ answer=(unit itype) ~
7893+ |-
7894+ ?~ arms
7895+ ?^ remaining
7896+ [%| ["missing union case {(show-itype part.i.remaining sub.st)}" ~]]
7897+ ?~ answer [%| ["empty union branch is not supported by partial inference" ~]]
7898+ ?~ expected [%& u.answer st]
7899+ [%& typ.u.expected st]
7900+ =/ a=arm i.arms
7901+ ?: (lien remaining |=(c=ifinite =(%unknown (union-pattern pat.a part.c))))
7902+ [%| ["partial union pattern is not supported by partial inference" ~]]
7903+ =/ matching=(list ifinite) (skim remaining |=(c=ifinite =(%full (union-pattern pat.a part.c))))
7904+ ?~ matching
7905+ ?: (lien cases |=(c=ifinite =(%full (union-pattern pat.a part.c))))
7906+ [%| ["branch arm is covered by earlier arms" ~[[at.pat.a "covered arm"]]]]
7907+ [%| ["union pattern is not supported by partial inference" ~]]
7908+ ?: &((union-pattern-has-bind pat.a) (lien t.matching |=(c=ifinite !=(origin.c origin.i.matching))))
7909+ [%| ["a union pattern binding several cases is not supported by partial inference" ~]]
7910+ =/ bound=(unit ienv) (union-pattern-bind pat.a base.i.matching env globals.st)
7911+ ?~ bound [%| ["pattern binder shadows a name" ~]]
7912+ =/ body=iresult
7913+ ?~ expected (infer-fragment val.a u.bound st)
7914+ (infer-call-context-arg val.a typ.u.expected u.bound st context.u.expected)
7915+ ?: ?=(%| -.body) body
7916+ ?^ expected
7917+ =/ fit=ifit (itype-fit typ.p.body typ.u.expected sub.state.p.body next.state.p.body)
7918+ ?: ?=(%unknown -.fit) [%| ["union branch result constraint is not supported by partial inference" ~]]
7919+ ?: ?=(%bad -.fit)
7920+ =/ missing=(unit idiag) (missing-union-tag val.a typ.u.expected sub.state.p.body context.u.expected)
7921+ ?^ missing [%| u.missing]
7922+ =/ nested=(unit idiag) (nested-missing-tag val.a typ.p.body typ.u.expected sub.state.p.body next.state.p.body context.u.expected)
7923+ ?^ nested [%| u.nested]
7924+ [%| ["union branch arm does not fit its expected type" ~[[context.u.expected "expected type"] [(span-of val.a) "branch arm"]]]]
7925+ ?: (itype-has-tag (itype-normalize typ.u.expected sub.fit))
7926+ [%| ["union branch result needs context in partial inference" ~]]
7927+ $(arms t.arms, remaining (skim remaining |=(c=ifinite !=(%full (union-pattern pat.a part.c)))), st state.p.body(sub sub.fit, next next.fit), answer `typ.u.expected)
7928+ =/ result=itype (itype-normalize typ.p.body sub.state.p.body)
7929+ =/ mismatch=? ?~(answer | !=((itype-normalize u.answer sub.state.p.body) result))
7930+ ?: mismatch [%| ["union branch result matching needs unsupported inference" ~]]
7931+ $(arms t.arms, remaining (skim remaining |=(c=ifinite !=(%full (union-pattern pat.a part.c)))), st state.p.body, answer `result)
7932+::
7933+:: Prove a one-arm record pattern covers a known, non-union subject.
7934+:: Variable or partial matches stay unsupported; binding uses the same
7935+:: scope and original payload types as the existing union matcher.
7936+++ single-structured-pattern
7937+ |= e=expr
7938+ ^- ?
7939+ ?. ?=(%branch -.e) |
7940+ ?~ arms.e |
7941+ ?^ t.arms.e |
7942+ =/ p=pattern pat.i.arms.e
7943+ ?. ?=(%cell -.p) |
7944+ !(levy items.p |=(x=pattern ?=(%bind -.x)))
7945+::
7946+++ infer-single-case-branch
7947+ |= [e=expr env=ienv state=istate expected=(unit [typ=itype context=span])]
7948+ ^- iresult
7949+ ?> (single-structured-pattern e)
7950+ ?> ?=(%branch -.e)
7951+ ?> ?=(^ arms.e)
7952+ =/ a=arm i.arms.e
7953+ =/ subject=iresult (infer-fragment subject.e env state)
7954+ ?: ?=(%| -.subject) subject
7955+ =/ st=istate state.p.subject
7956+ =/ typ=itype (itype-normalize typ.p.subject sub.st)
7957+ ?: ?=(%union -.typ) [%| ["single-case pattern needs unsupported inference" ~]]
7958+ ?. =(%full (union-pattern pat.a typ))
7959+ [%| ["single-case pattern needs unsupported inference" ~]]
7960+ =/ bound=(unit ienv) (union-pattern-bind pat.a typ env globals.st)
7961+ ?~ bound [%| ["pattern binder shadows a name" ~]]
7962+ ?~ expected (infer-fragment val.a u.bound st)
7963+ =/ body=iresult (infer-call-context-arg val.a typ.u.expected u.bound st context.u.expected)
7964+ ?: ?=(%| -.body) body
7965+ =/ fit=ifit (itype-fit typ.p.body typ.u.expected sub.state.p.body next.state.p.body)
7966+ ?: ?=(%unknown -.fit) [%| ["single-case branch result constraint is not supported by partial inference" ~]]
7967+ ?: ?=(%bad -.fit)
7968+ =/ missing=(unit idiag) (missing-union-tag val.a typ.u.expected sub.state.p.body context.u.expected)
7969+ ?^ missing [%| u.missing]
7970+ =/ nested=(unit idiag) (nested-missing-tag val.a typ.p.body typ.u.expected sub.state.p.body next.state.p.body context.u.expected)
7971+ ?^ nested [%| u.nested]
7972+ [%| ["single-case branch arm does not fit its expected type" ~[[context.u.expected "expected type"] [(span-of val.a) "branch arm"]]]]
7973+ ?: (itype-has-tag (itype-normalize typ.u.expected sub.fit))
7974+ [%| ["single-case branch result needs context in partial inference" ~]]
7975+ [%& typ.u.expected state.p.body(sub sub.fit, next next.fit)]
7976+::
7977+:: This view is used only by pattern analysis, never exported or bound as
7978+:: the subject. Only null plus a two-binder/wildcard cell is supported; its
7979+:: tail keeps the original recursive type. Other patterns fail closed.
7980+++ jrec-match-view
7981+ |= [e=expr subject=iresult]
7982+ ^- iresult
7983+ ?: ?=(%| -.subject) subject
7984+ ?. ?=(%branch -.e) subject
7985+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
7986+ ?. ?=(%jrec -.typ) subject
7987+ ?~ arms.e subject
7988+ ?~ t.arms.e subject
7989+ ?^ t.t.arms.e subject
7990+ =/ x=pattern pat.i.arms.e
7991+ =/ y=pattern pat.i.t.arms.e
7992+ =/ empty=? &(?=(%lit -.x) =(%null form.lit.x))
7993+ =/ full=pattern ?:(empty y x)
7994+ ?. |(empty &(?=(%lit -.y) =(%null form.lit.y))) subject
7995+ ?. ?=(%cell -.full) subject
7996+ ?~ items.full subject
7997+ ?~ t.items.full subject
7998+ ?^ t.t.items.full subject
7999+ ?. |(?=(%bind -.i.items.full) ?=(%any -.i.items.full)) subject
8000+ ?. |(?=(%bind -.i.t.items.full) ?=(%any -.i.t.items.full)) subject
8001+ ?: =(0 jrec-fuel.state.p.subject)
8002+ [%| ["recursive mold unfolding needs unsupported inference" ~]]
8003+ =/ nil=itype [%const [%null %n 0 '~']]
8004+ =/ cell=itype [%cell [%face head.typ [%atom aura.typ]] [%face tail.typ typ]]
8005+ [%& [%union ~[nil cell] ~ ~ ~] state.p.subject(jrec-fuel (dec jrec-fuel.state.p.subject))]
8006+::
8007+:: A bounded source-proven tree match permits flat tag patterns and
8008+:: nonbinding catch-alls. Whole-case binders cannot consume the temporary
8009+:: structural view. Pattern count and field arity are checked first.
8010+++ grec-simple-pattern
8011+ |= [pat=pattern view=itype]
8012+ ^- ?
8013+ ?. ?=(%cell -.pat) |
8014+ ?~ items.pat |
8015+ =/ first=pattern i.items.pat
8016+ ?. ?=(%lit -.first) |
8017+ ?. =(%term form.lit.first) |
8018+ =/ chosen=(unit itype) (contextual-tagged-case view val.lit.first ~)
8019+ ?~ chosen |
8020+ ?> ?=(%cell -.u.chosen)
8021+ =/ rest=(list pattern) t.items.pat
8022+ =/ arity=? ?:(?=(%cell -.tal.u.chosen) ?=([* [* ~]] rest) ?=([* ~] rest))
8023+ ?. arity |
8024+ (levy rest |=(p=pattern |(?=(%bind -.p) ?=(%any -.p))))
8025+::
8026+:: A catch-all with no binder is safe even when it covers both cases.
8027+:: A bound whole case still declines to avoid exporting the analysis view.
8028+++ grec-patterns-eligible
8029+ |= [arms=(list arm) view=itype left=@ud]
8030+ ^- ?
8031+ ?~ arms &
8032+ ?: =(0 left) |
8033+ =/ pat=pattern pat.i.arms
8034+ ?. |(?=(%any -.pat) (grec-simple-pattern pat view)) |
8035+ $(arms t.arms, left (dec left))
8036+++ grec-match-view
8037+ |= [e=expr subject=iresult]
8038+ ^- iresult
8039+ ?: ?=(%| -.subject) subject
8040+ ?. ?=(%branch -.e) subject
8041+ ?. (grec-direct-context typ.p.subject sub.state.p.subject) subject
8042+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8043+ ?. ?=(%grec -.typ) subject
8044+ ?~ arms.e subject
8045+ =/ view=(unit [view=itype left=@ud]) (grec-unfold-view typ jrec-fuel.state.p.subject)
8046+ ?~ view [%| ["recursive mold unfolding needs unsupported inference" ~]]
8047+ ?. (grec-patterns-eligible arms.e view.u.view 128) subject
8048+ [%& view.u.view state.p.subject(jrec-fuel left.u.view)]
8049+::
8050+:: A single-arm diagnostic only probes a direct, source-typed in-scope wing;
8051+:: other subjects retain the prior single-pattern inference path.
8052+++ grec-single-wing-subject
8053+ |= [e=expr env=ienv state=istate]
8054+ ^- (unit iresult)
8055+ ?. ?=(%wing -.e) ~
8056+ ?. ?=([@ ~] names.e) ~
8057+ =/ scheme=(unit ischeme) (ienv-lookup i.names.e env)
8058+ ?~ scheme ~
8059+ ?. (grec-direct-context typ.u.scheme sub.state) ~
8060+ `(infer-fragment e env state)
8061+::
8062+++ infer-known-union-branch-subject
8063+ |= [e=expr env=ienv subject=iresult]
8064+ ^- iresult
8065+ =. subject (grec-match-view e subject)
8066+ =. subject (jrec-match-view e subject)
8067+ =/ whole=(unit iresult) (infer-known-union-whole e env subject)
8068+ ?~ whole (infer-known-union-finite e env subject ~)
8069+ u.whole
8070+::
8071+++ infer-known-union-branch
8072+ |= [e=expr env=ienv state=istate]
8073+ ^- iresult
8074+ ?> ?=(%branch -.e)
8075+ (infer-known-union-branch-subject e env (infer-fragment subject.e env state))
8076+::
8077+++ infer-known-union-context-subject
8078+ |= [e=expr expected=itype env=ienv subject=iresult context=span]
8079+ ^- iresult
8080+ =. subject (grec-match-view e subject)
8081+ =. subject (jrec-match-view e subject)
8082+ =/ whole=(unit iresult) (infer-known-union-context-whole e expected env subject context)
8083+ ?~ whole (infer-known-union-finite e env subject `[expected context])
8084+ u.whole
8085+::
8086+:: Limit speculative subject inference to wings and shallow calls;
8087+:: grouping is peeled linearly and cannot introduce a nested branch.
8088+++ simple-union-subject-arg
8089+ |= e=expr
8090+ ^- ?
8091+ ?- -.e
8092+ %wing &
8093+ %lit &
8094+ %str !(lien pieces.e |=(p=piece ?=(%expr -.p)))
8095+ * |
8096+ ==
8097+::
8098+++ safe-union-subject
8099+ |= e=expr
8100+ ^- ?
8101+ ?: ?=(%group -.e) $(e inner.e)
8102+ ?: ?=(%wing -.e) &
8103+ ?. ?=(%call -.e) |
8104+ ?. ?=(%wing -.head.e) |
8105+ (levy args.e simple-union-subject-arg)
8106+::
8107+++ duplicate-loobean-arms
8108+ |= e=expr
8109+ ^- ?
8110+ ?. ?=(%branch -.e) |
8111+ ?~ arms.e |
8112+ ?~ t.arms.e |
8113+ ?^ t.t.arms.e |
8114+ =/ x=pattern pat.i.arms.e
8115+ =/ y=pattern pat.i.t.arms.e
8116+ ?. &(?=(%lit -.x) ?=(%lit -.y)) |
8117+ ?. &(=(%loobean form.lit.x) =(%loobean form.lit.y)) |
8118+ =(val.lit.x val.lit.y)
8119+::
8120+++ union-subject-call
8121+ |= e=expr
8122+ ^- ?
8123+ ?: ?=(%group -.e) $(e inner.e)
8124+ ?=(%call -.e)
8125+::
8126+++ known-union-subject
8127+ |= [e=expr env=ienv state=istate]
8128+ ^- (unit iresult)
8129+ ?. (safe-union-subject e) ~
8130+ =/ subject=iresult (infer-fragment e env state)
8131+ ?: ?=(%| -.subject) ?:((union-subject-call e) `subject ~)
8132+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8133+ ?. |(?=(%union -.typ) ?=(%jrec -.typ) &(?=(%grec -.typ) (grec-direct-context typ.p.subject sub.state.p.subject))) ~
8134+ `subject
8135+::
8136+:: A direct wing with an already-known union may skip genuinely empty cases
8137+:: when checking a one-arm match. Other subjects keep their existing path.
8138+:: A directly known canonical list of an empty element contains only null.
8139+:: This helper never refines an opaque or variable-bound subject.
8140+++ empty-list-null-branch
8141+ |= [e=expr env=ienv state=istate expected=(unit [typ=itype context=span])]
8142+ ^- (unit iresult)
8143+ ?. ?=(%branch -.e) ~
8144+ ?~ arms.e ~
8145+ ?^ t.arms.e ~
8146+ ?. (unit-empty-pattern pat.i.arms.e) ~
8147+ ?. ?=(%wing -.subject.e) ~
8148+ ?. ?=([@ ~] names.subject.e) ~
8149+ =/ scheme=(unit ischeme) (ienv-lookup i.names.subject.e env)
8150+ ?~ scheme ~
8151+ ?. ?=(%collection -.typ.u.scheme) ~
8152+ ?. =(%list name.typ.u.scheme) ~
8153+ ?~ prelude.state ~
8154+ ?. =(at.u.prelude.state /lib/jibb/prelude/jibb) ~
8155+ =/ standard=(unit ischeme) (find-jibb-mold %list u.prelude.state)
8156+ ?~ standard ~
8157+ ?. =(u.standard [[%collection %list ~[[%var 0]]] ~[0]]) ~
8158+ =/ subject=iresult (infer-fragment subject.e env state)
8159+ ?: ?=(%| -.subject) ~
8160+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8161+ ?. ?=(%collection -.typ) ~
8162+ ?. =(%list name.typ) ~
8163+ ?~ args.typ ~
8164+ ?^ t.args.typ ~
8165+ =/ proof=(unit [empty=? left=@ud]) (itype-empty-proof i.args.typ sub.state.p.subject 256)
8166+ ?~ proof ~
8167+ ?. empty.u.proof ~
8168+ ?~ expected `(infer-fragment val.i.arms.e env state.p.subject)
8169+ =/ body=iresult (infer-call-context-arg val.i.arms.e typ.u.expected env state.p.subject context.u.expected)
8170+ ?: ?=(%| -.body) `body
8171+ =/ fit=ifit (itype-fit typ.p.body typ.u.expected sub.state.p.body next.state.p.body)
8172+ ?: ?=(%unknown -.fit) `[%| ["single-case branch result constraint is not supported by partial inference" ~]]
8173+ ?: ?=(%bad -.fit) `[%| ["single-case branch arm does not fit its expected type" ~[[context.u.expected "expected type"] [(span-of val.i.arms.e) "branch arm"]]]]
8174+ ?: (itype-has-tag (itype-normalize typ.u.expected sub.fit))
8175+ `[%| ["single-case branch result needs context in partial inference" ~]]
8176+ `[%& typ.p.body state.p.body(sub sub.fit, next next.fit)]
8177+::
8178+++ known-empty-union-wing
8179+ |= [e=expr env=ienv state=istate]
8180+ ^- (unit iresult)
8181+ ?. ?=(%wing -.e) ~
8182+ ?. ?=([@ ~] names.e) ~
8183+ =/ scheme=(unit ischeme) (ienv-lookup i.names.e env)
8184+ ?~ scheme ~
8185+ ?. (contextual-direct-union typ.u.scheme) ~
8186+ =/ subject=iresult (infer-fragment e env state)
8187+ ?: ?=(%| -.subject) ~
8188+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8189+ ?. ?=(%union -.typ) ~
8190+ =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
8191+ ?~ live ~
8192+ ?: =(u.live cases.typ) ~
8193+ `subject
8194+::
8195+:: Infer changes only against a fully known record spine. Retain the
8196+:: target type; unknown spines and repeated edits remain unsupported.
8197+++ change-spine-known
8198+ |= [t=itype sub=isub]
8199+ ^- ?
8200+ =. t (itype-walk t sub)
8201+ ?: ?=(%face -.t) &
8202+ ?. ?=(%cell -.t) |
8203+ =/ first=itype (itype-walk hed.t sub)
8204+ ?. ?=(%face -.first) |
8205+ $(t tal.t)
8206+::
8207+++ infer-change-edits
8208+ |= [edits=(list edit) target=itype env=ienv state=istate seen=(list term)]
8209+ ^- iresult
8210+ ?~ edits [%& target state]
8211+ =/ entry=edit i.edits
8212+ ?: (lien seen |=(name=term =(name name.entry)))
8213+ [%| ["repeated change fields are not supported by partial inference" ~]]
8214+ ?. (change-spine-known target sub.state)
8215+ [%| ["change target needs a known record in partial inference" ~]]
8216+ =/ found=(list itype) (record-fields-named name.entry target sub.state)
8217+ ?~ found
8218+ [%| ["record has no field `{(trip name.entry)}`" ~[[at.entry "unknown field"]]]]
8219+ ?^ t.found [%| ["change field is ambiguous in partial inference" ~]]
8220+ =/ expected=itype i.found
8221+ =/ value=iresult (infer-call-context-arg val.entry expected env state at.entry)
8222+ ?: ?=(%| -.value) value
8223+ =/ fit=ifit (itype-fit typ.p.value expected sub.state.p.value next.state.p.value)
8224+ ?: ?=(%unknown -.fit) [%| ["change field constraint is not supported by partial inference" ~]]
8225+ ?: ?=(%bad -.fit)
8226+ [%| ["change field and replacement do not unify" ~[[at.entry (site-type-note "expected replacement" expected sub.state.p.value)] [(span-of val.entry) (site-type-note "replacement" typ.p.value sub.state.p.value)]]]]
8227+ $(edits t.edits, state state.p.value(sub sub.fit, next next.fit), seen [name.entry seen])
8228+::
8229+:: Backtick constructs the canonical prelude unit, after checking its
8230+:: prepared template has the standard null and [~ u=A] cases.
8231+++ standard-unit-template
8232+ |= [template=ischeme at=path]
8233+ ^- ?
8234+ ?. =(at /lib/jibb/prelude/jibb) |
8235+ ?~ vars.template |
8236+ ?^ t.vars.template |
8237+ =/ v=@ud i.vars.template
8238+ =/ nil=itype [%const [%null %n 0 '~']]
8239+ =/ expected=itype
8240+ [%union ~[nil [%cell nil [%face %u [%var v]]]] `[at %unit] `%unit ~[[%var v]]]
8241+ =(typ.template expected)
8242+::
8243+:: A named missing-case diagnostic needs more than a failed fit: a case
8244+:: with that tag but the wrong payload is not a missing case. Unknown
8245+:: shapes and atom types that accept terms keep the proof conservative.
8246++$ itag-presence ?(%yes %no %maybe)
8247+++ tag-presence-cases
8248+ |= [cases=(list itype) value=@ sub=isub]
8249+ ^- itag-presence
8250+ ?~ cases %no
8251+ =/ first=itag-presence (tag-presence i.cases value sub)
8252+ ?: =(%yes first) %yes
8253+ =/ rest=itag-presence $(cases t.cases)
8254+ ?: =(%yes rest) %yes
8255+ ?: |(=(%maybe first) =(%maybe rest)) %maybe
8256+ %no
8257+::
8258+++ tag-presence
8259+ |= [t=itype value=@ sub=isub]
8260+ ^- itag-presence
8261+ =. t (itype-walk t sub)
8262+ ?- -.t
8263+ %const ?:(=(value val.literal.t) %yes %no)
8264+ %flag ?:(|(=(value 0) =(value 1)) %yes %no)
8265+ %atom ?:(|(=(%tas aura.t) =(%ta aura.t)) %maybe %no)
8266+ %face $(t body.t)
8267+ %cell
8268+ =/ first=itag-presence $(t hed.t)
8269+ ?: =(%yes first) %yes
8270+ =/ rest=itag-presence $(t tal.t)
8271+ ?: =(%yes rest) %yes
8272+ ?: |(=(%maybe first) =(%maybe rest)) %maybe
8273+ %no
8274+ %union (tag-presence-cases cases.t value sub)
8275+ * %maybe
8276+ ==
8277+::
8278+++ missing-union-tag
8279+ |= [e=expr expected=itype sub=isub context=span]
8280+ ^- (unit idiag)
8281+ ?. ?=(%lit -.e) ~
8282+ ?. =(%term form.lit.e) ~
8283+ =. expected (itype-walk expected sub)
8284+ |-
8285+ ?: ?=(%face -.expected) $(expected (itype-walk body.expected sub))
8286+ ?. ?=(%union -.expected) ~
8287+ ?. =(%no (tag-presence-cases cases.expected val.lit.e sub)) ~
8288+ =/ label=tape
8289+ ?~ label.expected "union {(show-itype expected sub)}"
8290+ (show-itype expected sub)
8291+ `["{label} has no case `{(trip txt.lit.e)}`" ~[[context "expected union"] [(span-of e) "tag"]]]
8292+::
8293+:: Locate a missing tag inside a syntactic tuple only by replaying the
8294+:: directional fit in source order. Uncertain or earlier failures stop
8295+:: the walk, preserving the generic diagnostic rather than guessing.
8296+++ nested-missing-tag
8297+ |= [e=expr actual=itype expected=itype sub=isub next=@ud context=span]
8298+ ^- (unit idiag)
8299+ =/ original=[left=itype right=itype] [actual expected]
8300+ ?: |(?=(%var -.left.original) ?=(%avar -.left.original) ?=(%rvar -.left.original) |(?=(%nvar -.left.original) ?=(%rnvar -.left.original)) ?=(%var -.right.original) ?=(%avar -.right.original) ?=(%rvar -.right.original) |(?=(%nvar -.right.original) ?=(%rnvar -.right.original))) ~
8301+ =/ fit=ifit (itype-fit actual expected sub next)
8302+ ?. ?=(%bad -.fit) ~
8303+ =. actual (itype-walk actual sub)
8304+ =. expected (itype-walk expected sub)
8305+ ?: &(?=(%face -.actual) ?=(%face -.expected))
8306+ ?. =(name.actual name.expected) ~
8307+ $(actual body.actual, expected body.expected)
8308+ ?: ?=(%face -.actual) $(actual body.actual)
8309+ ?: ?=(%face -.expected) $(expected body.expected)
8310+ =/ direct=(unit idiag) (missing-union-tag e expected sub context)
8311+ ?^ direct direct
8312+ ?. ?=(%tuple -.e) ~
8313+ (nested-missing-items items.e actual expected sub next context)
8314+::
8315+++ nested-missing-items
8316+ |= [items=(list item) actual=itype expected=itype sub=isub next=@ud context=span]
8317+ ^- (unit idiag)
8318+ ?~ items ~
8319+ ?~ t.items (nested-missing-tag val.i.items actual expected sub next context)
8320+ =/ original=[left=itype right=itype] [actual expected]
8321+ ?: |(?=(%var -.left.original) ?=(%avar -.left.original) ?=(%rvar -.left.original) |(?=(%nvar -.left.original) ?=(%rnvar -.left.original)) ?=(%var -.right.original) ?=(%avar -.right.original) ?=(%rvar -.right.original) |(?=(%nvar -.right.original) ?=(%rnvar -.right.original))) ~
8322+ =. actual (itype-walk actual sub)
8323+ =. expected (itype-walk expected sub)
8324+ ?. &(?=(%cell -.actual) ?=(%cell -.expected)) ~
8325+ =/ first=ifit (itype-fit hed.actual hed.expected sub next)
8326+ ?: ?=(%bad -.first)
8327+ (nested-missing-tag val.i.items hed.actual hed.expected sub next context)
8328+ ?. ?=(%ok -.first) ~
8329+ $(items t.items, actual tal.actual, expected tal.expected, sub sub.first, next next.first)
8330+::
8331+:: A term-headed pair is the same noun as a two-item cell. Preserve the
8332+:: whole pair span for the synthetic head and the value's own span for
8333+:: the payload; unresolved term constraints follow ordinary cell inference.
8334+++ pair-as-cell
8335+ |= e=expr
8336+ ^- expr
8337+ ?> ?=(%pair -.e)
8338+ =/ head=expr [%lit at.e [%term %tas tag.e (crip ['%' (trip tag.e)])]]
8339+ [%tuple at.e ~[[at.e ~ head] [(span-of val.e) ~ val.e]]]
8340+::
8341+:: A segment costs one shared step; dynamic segments are not handled yet.
8342+++ qath-static-fuel
8343+ |= [segs=(list qseg) fuel=@ud]
8344+ ^- (unit @ud)
8345+ ?~ segs `fuel
8346+ ?: =(0 fuel) ~
8347+ ?. ?=(%knot -.i.segs) ~
8348+ $(segs t.segs, fuel (dec fuel))
8349+::
8350+++ infer-fragment
8351+ |= [e=expr env=ienv state=istate]
8352+ ^- iresult
8353+ ?- -.e
8354+ %pair $(e (pair-as-cell e))
8355+ %lit
8356+ ?- form.lit.e
8357+ %number ?: =(%ud aura.lit.e)
8358+ [%& [%nvar next.state] state(next +(next.state))]
8359+ [%& [%atom aura.lit.e] state]
8360+ %ship [%& [%atom %p] state]
8361+ %date [%& [%atom %da] state]
8362+ %duration [%& [%atom %dr] state]
8363+ %knot [%& [%atom %ta] state]
8364+ %loobean [%& [%flag ~] state]
8365+ %term [%& [%tag next.state lit.e |] state(next +(next.state), tags [[next.state lit.e] tags.state])]
8366+ %null [%& [%tag next.state lit.e |] state(next +(next.state), tags [[next.state lit.e] tags.state])]
8367+ ==
8368+ %unit
8369+ ?~ prelude.state [%| ["unit construction needs the standard prelude in partial inference" ~]]
8370+ =/ standard=(unit ischeme) (find-jibb-mold %unit u.prelude.state)
8371+ ?~ standard [%| ["unit construction needs the standard prelude in partial inference" ~]]
8372+ ?. (standard-unit-template u.standard at.u.prelude.state)
8373+ [%| ["unit construction needs the standard prelude in partial inference" ~]]
8374+ =/ value=iresult $(e val.e)
8375+ ?: ?=(%| -.value) value
8376+ =/ result=(unit itype) (template-apply u.standard ~[typ.p.value])
8377+ ?~ result [%| ["unit construction is not supported by partial inference" ~]]
8378+ [%& u.result state.p.value]
8379+ %list
8380+ ?~ prelude.state [%| ["list literal needs the standard prelude in partial inference" ~]]
8381+ ?. =(at.u.prelude.state /lib/jibb/prelude/jibb)
8382+ [%| ["list literal needs the standard prelude in partial inference" ~]]
8383+ =/ standard=(unit ischeme) (find-jibb-mold %list u.prelude.state)
8384+ ?~ standard [%| ["list literal needs the standard prelude in partial inference" ~]]
8385+ ?. =(u.standard [[%collection %list ~[[%var 0]]] ~[0]])
8386+ [%| ["list literal needs the standard prelude in partial inference" ~]]
8387+ =/ element=itype [%var next.state]
8388+ =/ result=iresult (infer-open-list-items items.e element env state(next +(next.state)) at.e)
8389+ ?: ?=(%| -.result) result
8390+ [%& [%collection %list ~[element]] state.p.result]
8391+ %str (infer-string-pieces pieces.e env state)
8392+ %qath
8393+ ?~ prelude.state [%| ["application path needs the standard prelude in partial inference" ~]]
8394+ ?. =(at.u.prelude.state /lib/jibb/prelude/jibb)
8395+ [%| ["application path needs the standard prelude in partial inference" ~]]
8396+ =/ standard=(unit ischeme) (find-jibb-mold %qath u.prelude.state)
8397+ ?~ standard [%| ["application path needs the standard prelude in partial inference" ~]]
8398+ ?. ?=(~ vars.u.standard) [%| ["application path mold needs unsupported inference" ~]]
8399+ =/ typ=itype typ.u.standard
8400+ ?. ?=(%jrec -.typ) [%| ["application path mold needs unsupported inference" ~]]
8401+ ?. &(=(at.typ /lib/jibb/internal/jibb) =(%qath name.typ) =(%i head.typ) =(%ta aura.typ) =(%t tail.typ))
8402+ [%| ["application path mold needs unsupported inference" ~]]
8403+ ?: =(0 jrec-fuel.state) [%| ["recursive mold unfolding needs unsupported inference" ~]]
8404+ =/ remain=(unit @ud) (qath-static-fuel segs.e (dec jrec-fuel.state))
8405+ ?~ remain [%| ["application path segments need unsupported inference" ~]]
8406+ [%& typ state(jrec-fuel u.remain)]
8407+ %wing
8408+ ?~ names.e [%| ["empty wing" ~]]
8409+ ?^ t.names.e
8410+ ?^ t.t.names.e (infer-field-wing names.e env state)
8411+ =/ iface=(unit ifile) (find-jibb-interface i.t.names.e jimports.state)
8412+ ?~ iface (infer-field-wing names.e env state)
8413+ =/ member=(unit ischeme) (ienv-lookup i.names.e values.u.iface)
8414+ ?~ member [%| ["module member is not available to partial inference" ~]]
8415+ =. typ.u.member (itype-in-import typ.u.member u.iface i.t.names.e prelude.state)
8416+ =/ instance=[typ=itype state=istate] (instantiate-scheme u.member state)
8417+ [%& typ.instance state.instance]
8418+ =/ scheme=(unit ischeme) (ienv-lookup i.names.e env)
8419+ ?~ scheme
8420+ ?~ prelude.state [%| ["name is not available to partial inference" ~]]
8421+ =/ prelude-entry=(unit ischeme) (ienv-lookup i.names.e values.u.prelude.state)
8422+ ?~ prelude-entry [%| ["name is not available to partial inference" ~]]
8423+ =/ inst=[typ=itype state=istate] (instantiate-scheme u.prelude-entry state)
8424+ [%& typ.inst state.inst]
8425+ =/ instance=[typ=itype state=istate] (instantiate-scheme u.scheme state)
8426+ [%& typ.instance state.instance]
8427+ %group $(e inner.e)
8428+ %change
8429+ ?~ edits.e [%| ["a change takes at least one field" ~[[at.e "empty change"]]]]
8430+ =/ target=iresult $(e [%wing at.e target.e])
8431+ ?: ?=(%| -.target) target
8432+ (infer-change-edits edits.e typ.p.target env state.p.target ~)
8433+ %ctor [%& [%tag next.state tag.e &] state(next +(next.state), tags [[next.state tag.e] tags.state])]
8434+ %trace
8435+ =/ traced=iresult $(e val.e)
8436+ ?: ?=(%| -.traced) traced
8437+ $(e then.e, state state.p.traced)
8438+ %tuple
8439+ ?: &(?=(^ defer.state) ?=(^ prelude.state))
8440+ (dg-infer-tuple-items items.e env state)
8441+ (infer-simple-items items.e env state)
8442+ %body
8443+ ?~ defs.e $(e final.e)
8444+ =/ local-names=(list term) (global-value-names defs.e)
8445+ ?. (local-names-valid defs.e env state)
8446+ [%| ["local definitions shadow a name" ~]]
8447+ =/ local-molds=imolds (collect-simple-molds defs.e)
8448+ ?. (local-mold-names-valid local-molds state)
8449+ [%| ["local molds shadow a name" ~]]
8450+ =/ local-state=istate
8451+ state(globals (weld local-names globals.state), molds (weld local-molds molds.state))
8452+ =/ mold-hole=(unit span) (simple-local-mold-hole defs.e)
8453+ ?^ mold-hole
8454+ [%| ["type hole needs a determined type" ~[[u.mold-hole "unresolved type hole"]]]]
8455+ ?. (local-molds-supported local-molds local-state)
8456+ [%| ["local molds need unsupported inference" ~]]
8457+ =/ values=(list def) (local-value-defs defs.e)
8458+ =/ locals=ilocal-result (infer-local-defs values env local-state)
8459+ ?: ?=(%| -.locals) locals
8460+ =/ result=iresult $(e final.e, env env.p.locals, state state.p.locals)
8461+ ?: ?=(%| -.result) result
8462+ [%& typ.p.result state.p.result(globals globals.state, molds molds.state)]
8463+ %branch
8464+ ?^ defer.state (dg-boolean-branch e env state)
8465+ ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
8466+ ?~ t.arms.e
8467+ =/ empty-list=(unit iresult) (empty-list-null-branch e env state ~)
8468+ ?^ empty-list u.empty-list
8469+ =/ empty-union=(unit iresult) (known-empty-union-wing subject.e env state)
8470+ ?^ empty-union (infer-known-union-branch-subject e env u.empty-union)
8471+ =/ single=(unit iresult) (grec-single-wing-subject subject.e env state)
8472+ ?^ single (infer-known-union-branch-subject e env u.single)
8473+ ?: (single-structured-pattern e) (infer-single-case-branch e env state ~)
8474+ (infer-cell-branch e env state ~)
8475+ ?^ t.t.arms.e (infer-known-union-branch e env state)
8476+ =/ known=(unit iresult) (known-union-subject subject.e env state)
8477+ ?: &(?=(^ known) ?=(%| -.u.known) !(duplicate-loobean-arms e)) u.known
8478+ ?: &(?=(^ known) ?=(%& -.u.known) ?=(~ (unit-union-payload (itype-normalize typ.p.u.known sub.state.p.u.known))))
8479+ (infer-known-union-branch-subject e env u.known)
8480+ =/ x=arm i.arms.e
8481+ =/ y=arm i.t.arms.e
8482+ ?: |((unit-empty-pattern pat.x) (unit-empty-pattern pat.y))
8483+ (infer-unit-branch e env state ~)
8484+ ?. ?=(%lit -.pat.x) (infer-known-union-branch e env state)
8485+ ?. ?=(%lit -.pat.y) (infer-known-union-branch e env state)
8486+ ?. &(=(%loobean form.lit.pat.x) =(%loobean form.lit.pat.y))
8487+ (infer-known-union-branch e env state)
8488+ ?: &(?=(^ known) ?=(%& -.u.known)) (infer-known-union-branch-subject e env u.known)
8489+ ?: =(val.lit.pat.x val.lit.pat.y)
8490+ [%| ["branch does not cover both loobeans" ~]]
8491+ =/ subject=iresult $(e subject.e)
8492+ ?: ?=(%| -.subject) subject
8493+ =/ subject-type=itype (itype-normalize typ.p.subject sub.state.p.subject)
8494+ ?: ?=(%union -.subject-type)
8495+ [%| ["union-pattern branch subject is not supported by partial inference" ~]]
8496+ =/ su=(unit isub) (itype-unify typ.p.subject [%flag ~] sub.state.p.subject)
8497+ ?~ su [%| ["loobean branch subject does not unify with ?" ~]]
8498+ =/ left=iresult $(e val.x, state state.p.subject(sub u.su))
8499+ ?: ?=(%| -.left) left
8500+ =/ right=iresult $(e val.y, state state.p.left)
8501+ ?: ?=(%| -.right) right
8502+ =/ ltype=itype (itype-normalize typ.p.left sub.state.p.right)
8503+ =/ rtype=itype (itype-normalize typ.p.right sub.state.p.right)
8504+ ?: &(!=(ltype rtype) |(?=(^ (itype-vars ltype)) ?=(^ (itype-vars rtype))) |((itype-has-fixed-atom ltype) (itype-has-fixed-atom rtype)))
8505+ [%| ["branch widening is not supported by partial inference" ~]]
8506+ =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
8507+ ?~ joined
8508+ ?: |((itype-has-recursive ltype) (itype-has-recursive rtype))
8509+ [%| ["recursive branch matching is not supported by partial inference" ~]]
8510+ ?: |((itype-has-tag ltype) (itype-has-tag rtype) (itype-has-union ltype) (itype-has-union rtype))
8511+ [%| ["branch tag or union context is not supported by partial inference" ~]]
8512+ =/ common=(unit itype) (itype-concrete-join typ.p.left typ.p.right sub.state.p.right)
8513+ ?^ common [%& u.common state.p.right]
8514+ ?: |((itype-has-face typ.p.left sub.state.p.right) (itype-has-face typ.p.right sub.state.p.right))
8515+ [%| ["record branch matching is not supported by partial inference" ~]]
8516+ ?: |((itype-has-any-atom typ.p.left sub.state.p.right) (itype-has-any-atom typ.p.right sub.state.p.right) (itype-family-related typ.p.left typ.p.right sub.state.p.right))
8517+ [%| ["branch widening is not supported by partial inference" ~]]
8518+ [%| ["branch arms have incompatible types" ~[[(span-of val.x) (site-type-note "first arm" typ.p.left sub.state.p.right)] [(span-of val.y) (site-type-note "second arm" typ.p.right sub.state.p.right)]]]]
8519+ [%& typ.p.left state.p.right(sub u.joined)]
8520+ %cast
8521+ =/ target=(unit [typ=itype state=istate]) (infer-simple-shape shape.e state)
8522+ ?~ target
8523+ =/ diag=(unit idiag) (nested-import-invalid shape.e state)
8524+ ?^ diag [%| u.diag]
8525+ [%| ["cast mold is not supported by partial inference" ~]]
8526+ =/ value=iresult
8527+ (infer-call-context-arg val.e typ.u.target env state.u.target at.shape.e)
8528+ ?: ?=(%| -.value) value
8529+ =/ shape=(unit [source=iwfields target=iwfields])
8530+ (width-shape typ.p.value typ.u.target sub.state.p.value)
8531+ ?^ shape [%| ["record width constraint needs unsupported inference" ~]]
8532+ =/ fit=ifit (itype-fit typ.p.value typ.u.target sub.state.p.value next.state.p.value)
8533+ ?: ?=(%unknown -.fit) [%| ["cast constraint is not supported by partial inference" ~]]
8534+ ?: ?=(%bad -.fit)
8535+ =/ missing=(unit idiag) (missing-union-tag val.e typ.u.target sub.state.p.value at.shape.e)
8536+ ?^ missing [%| u.missing]
8537+ =/ nested=(unit idiag) (nested-missing-tag val.e typ.p.value typ.u.target sub.state.p.value next.state.p.value at.shape.e)
8538+ ?^ nested [%| u.nested]
8539+ [%| ["cast mold and expression type do not unify" ~[[at.shape.e (site-type-note "cast mold" typ.u.target sub.state.p.value)] [(span-of val.e) (site-type-note "expression" typ.p.value sub.state.p.value)]]]]
8540+ ?: &(?=(^ defer.state.p.value) !(dg-stable-fit typ.p.value typ.u.target sub.fit))
8541+ [%| ["deferred cast fit needs stable inference" ~]]
8542+ =/ merged=itype (itype-merge-faces typ.p.value typ.u.target sub.fit)
8543+ [%& merged state.p.value(sub sub.fit, next next.fit)]
8544+ %crash [%& [%var next.state] state(next +(next.state))]
8545+ %gate
8546+ =/ sam=isample-result (infer-sample sample.e env state)
8547+ ?: ?=(%| -.sam)
8548+ =/ diag=(unit idiag) (sample-import-invalid sample.e env state)
8549+ ?: &(=(p.sam "sample mold is not supported by partial inference") ?=(^ diag)) [%| u.diag]
8550+ [%| [p.sam ~]]
8551+ =/ body=iresult $(e body.e, env env.p.sam, state state.p.sam)
8552+ ?: ?=(%| -.body) body
8553+ [%& [%fn typ.p.sam typ.p.body] state.p.body]
8554+ %gate-wide
8555+ =/ sam=isample-result (infer-sample sample.e env state)
8556+ ?: ?=(%| -.sam)
8557+ =/ diag=(unit idiag) (sample-import-invalid sample.e env state)
8558+ ?: &(=(p.sam "sample mold is not supported by partial inference") ?=(^ diag)) [%| u.diag]
8559+ [%| [p.sam ~]]
8560+ =/ body=iresult $(e body.e, env env.p.sam, state state.p.sam)
8561+ ?: ?=(%| -.body) body
8562+ [%& [%fn typ.p.sam typ.p.body] state.p.body]
8563+ %call
8564+ ?~ args.e [%| ["call has no argument" ~]]
8565+ ?: (explicit-proj-call e env state)
8566+ [%| ["proj needs an expected record type" ~]]
8567+ (infer-call-with-head e env state (infer-fragment head.e env state))
8568+ * [%| ["expression is not supported by partial inference" ~]]
8569+ ==
8570+::
8571+:: Locate a definite failing argument after the complete sample fit has
8572+:: failed. If an intermediate fit is uncertain, retain the whole argument
8573+:: span rather than assigning blame to a particular argument.
8574+::
8575+:: Check a call using the head already inferred in this state. Keeping
8576+:: this shared avoids evaluating or instantiating a contextual head twice.
8577+++ width-has-projections
8578+ |= ps=(list iwprojection)
8579+ ^- ?
8580+ ?~ ps |
8581+ &
8582+::
8583++$ iwidth-elaboration [original=expr typ=itype sub=isub projections=(list iwprojection)]
8584+++ infer-width-elaboration
8585+ |= [e=expr env=ienv state=istate]
8586+ ^- (each iwidth-elaboration idiag)
8587+ =/ out=iresult (infer-fragment e env state)
8588+ ?: ?=(%| -.out) [%| p.out]
8589+ [%& [e typ.p.out sub.state.p.out (flop projections.state.p.out)]]
8590+::
8591+:: Source-bound gate-layout evidence, confined to checked root gate
8592+:: definitions and direct unshadowed prelude calls. The prepared prelude
8593+:: interface and its retained source are trusted as a matching artifact.
8594+:: Layouts identify sample binder faces; they do not change call arity or
8595+:: authorize stripping nested value faces. Unknown origins use ordinary fit.
8596+++ direct-written-gates
8597+ |= [ds=(list def) out=ivisited]
8598+ ^- ivisited
8599+ ?~ ds out
8600+ ?: ?=(%mold -.i.ds) $(ds t.ds)
8601+ ?. |(?=(%gate -.val.i.ds) ?=(%gate-wide -.val.i.ds)) $(ds t.ds)
8602+ $(ds t.ds, out (~(put by out) name.i.ds &))
8603+++ direct-may-use-prelude
8604+ |= [ds=(list def) root=ivisited heads=ivisited]
8605+ ^- ?
8606+ ?~ ds |
8607+ ?: ?=(%mold -.i.ds) $(ds t.ds)
8608+ =/ refs=(list term) (dependency-expr val.i.ds)
8609+ =/ has-root=? (lien refs |=(n=term ?=(^ (~(get by root) n))))
8610+ =/ has-head=? (lien refs |=(n=term ?=(^ (~(get by heads) n))))
8611+ ?: &(has-root has-head) &
8612+ $(ds t.ds)
8613+++ direct-unique-names
8614+ |= [names=(list term) seen=ivisited]
8615+ ^- ?
8616+ ?~ names &
8617+ ?: ?=(^ (~(get by seen) i.names)) |
8618+ $(names t.names, seen (~(put by seen) i.names &))
8619+++ direct-prelude-evidence
8620+ |= [ds=(list def) prelude=(unit ifile)]
8621+ ^- (unit igate-prelude-evidence)
8622+ ?~ prelude ~
8623+ ?~ source.u.prelude ~
8624+ =/ root=ivisited (direct-written-gates ds ~)
8625+ =/ names=(list term) (turn values.u.prelude |=(e=[name=term scheme=ischeme] name.e))
8626+ =/ heads=ivisited (graph-nameset names ~)
8627+ ?. (direct-may-use-prelude ds root heads) ~
8628+ =/ parsed (parse at.u.prelude u.source.u.prelude)
8629+ ?: ?=(%| -.parsed) ~
8630+ ?^ (duplicate-defs defs.p.parsed) ~
8631+ ?. (direct-unique-names (global-value-names defs.p.parsed) ~) ~
8632+ =/ gates=(map term def) (direct-checked-gates defs.p.parsed values.u.prelude)
8633+ `[u.prelude gates]
8634+++ direct-checked-gates
8635+ |= [ds=(list def) env=ienv]
8636+ ^- (map term def)
8637+ =/ names=(list term) (turn env |=(e=[name=term scheme=ischeme] name.e))
8638+ =/ known=ivisited (graph-nameset names ~)
8639+ =/ out=(map term def) ~
8640+ |-
8641+ ?~ ds out
8642+ =/ d=def i.ds
8643+ ?: ?=(%mold -.d) $(ds t.ds)
8644+ ?. ?=(^ (~(get by known) name.d)) $(ds t.ds)
8645+ ?. |(?=(%gate -.val.d) ?=(%gate-wide -.val.d)) $(ds t.ds)
8646+ $(ds t.ds, out (~(put by out) name.d d))
8647+++ direct-find-gate
8648+ |= [n=term ds=(list def)]
8649+ ^- (unit def)
8650+ ?~ ds ~
8651+ ?: &(?=(%value -.i.ds) =(n name.i.ds)) `i.ds
8652+ $(ds t.ds)
8653+++ direct-gate-sample
8654+ |= d=def
8655+ ^- (unit sample)
8656+ ?. ?=(%value -.d) ~
8657+ ?- -.val.d
8658+ %gate `sample.val.d
8659+ %gate-wide `sample.val.d
8660+ * ~
8661+ ==
8662+++ direct-sample-name
8663+ |= sam=sample
8664+ ^- (unit term)
8665+ ?- -.sam
8666+ %bind `name.sam
8667+ %face `name.sam
8668+ %pun `name.sam
8669+ * ~
8670+ ==
8671+++ direct-field-name
8672+ |= f=field
8673+ ^- (unit term)
8674+ ?- -.f
8675+ %face `name.f
8676+ %pun `name.f
8677+ * ~
8678+ ==
8679+++ direct-slot-body
8680+ |= [typ=itype name=(unit term)]
8681+ ^- (unit itype)
8682+ ?~ name `typ
8683+ ?. ?=(%face -.typ) ~
8684+ ?. =(name.typ u.name) ~
8685+ `body.typ
8686+++ direct-invariant
8687+ |= [a=itype b=itype sub=isub next=@ud]
8688+ ^- ifit
8689+ ?: (itype-face-asym a b sub) [%unknown ~]
8690+ =/ forward=ifit (itype-fit a b sub next)
8691+ ?. ?=(%ok -.forward) [%unknown ~]
8692+ ?: (itype-face-asym a b sub.forward) [%unknown ~]
8693+ =/ reverse=ifit (itype-fit b a sub.forward next.forward)
8694+ ?. ?=(%ok -.reverse) [%unknown ~]
8695+ reverse
8696+++ direct-function-fit
8697+ |= [a=itype b=itype sam=sample sh=shape sub=isub next=@ud]
8698+ ^- ifit
8699+ ?. &(?=(%fn -.a) ?=(%fn -.b) ?=(%cell -.sam) ?=(%fn -.sh)) [%unknown ~]
8700+ ?. ?=(%cell -.sample.sh) [%unknown ~]
8701+ =/ as=(list sample) items.sam
8702+ =/ bs=(list field) fields.sample.sh
8703+ ?~ as [%unknown ~]
8704+ ?~ t.as [%unknown ~]
8705+ ?^ t.t.as [%unknown ~]
8706+ ?~ bs [%unknown ~]
8707+ ?~ t.bs [%unknown ~]
8708+ ?^ t.t.bs [%unknown ~]
8709+ ?. &(?=(%cell -.sample.a) ?=(%cell -.sample.b)) [%unknown ~]
8710+ =/ an=(unit term) (direct-sample-name i.as)
8711+ =/ bn=(unit term) (direct-field-name i.bs)
8712+ ?: &(?=(^ an) ?=(^ bn) !=(u.an u.bn)) [%unknown ~]
8713+ =/ x=(unit itype) (direct-slot-body hed.sample.a an)
8714+ =/ y=(unit itype) (direct-slot-body hed.sample.b bn)
8715+ ?~ x [%unknown ~]
8716+ ?~ y [%unknown ~]
8717+ =/ first=ifit (direct-invariant u.x u.y sub next)
8718+ ?. ?=(%ok -.first) [%unknown ~]
8719+ =. an (direct-sample-name i.t.as)
8720+ =. bn (direct-field-name i.t.bs)
8721+ ?: &(?=(^ an) ?=(^ bn) !=(u.an u.bn)) [%unknown ~]
8722+ =/ x2=(unit itype) (direct-slot-body tal.sample.a an)
8723+ =/ y2=(unit itype) (direct-slot-body tal.sample.b bn)
8724+ ?~ x2 [%unknown ~]
8725+ ?~ y2 [%unknown ~]
8726+ =/ second=ifit (direct-invariant u.x2 u.y2 sub.first next.first)
8727+ ?. ?=(%ok -.second) [%unknown ~]
8728+ (direct-invariant product.a product.b sub.second next.second)
8729+:: This is a tentative proof: its caller must require closed call samples
8730+:: and repeat every positional check under the stable final substitution.
8731+++ direct-positional-fit
8732+ |= [args=(list expr) slots=(list sample) actual=itype expected=itype env=ienv state=istate sub=isub next=@ud]
8733+ ^- ifit
8734+ ?~ args [%unknown ~]
8735+ ?~ slots [%unknown ~]
8736+ =/ last=? ?=(~ t.args)
8737+ ?: !=(last ?=(~ t.slots)) [%unknown ~]
8738+ =/ split=(unit [left=itype right=itype])
8739+ ?: last `[actual expected]
8740+ ?. &(?=(%cell -.actual) ?=(%cell -.expected)) ~
8741+ `[hed.actual hed.expected]
8742+ ?~ split [%unknown ~]
8743+ =/ x=itype left.u.split
8744+ =/ y=itype right.u.split
8745+ =/ expected-name=(unit term) (direct-sample-name i.slots)
8746+ =/ expected-body=(unit itype) (direct-slot-body y expected-name)
8747+ ?~ expected-body [%unknown ~]
8748+ =. y u.expected-body
8749+ =/ fit=ifit (itype-fit x y sub next)
8750+ =/ accepted=? &(?=(%ok -.fit) !(itype-positional-slot-face-asym x y sub.fit))
8751+ =/ result=(unit ifit)
8752+ ?: accepted `fit
8753+ ?. &(?=(%face -.i.slots) ?=(%fn -.shape.i.slots)) ~
8754+ ?. ?=(%wing -.i.args) ~
8755+ ?. ?=([@ ~] names.i.args) ~
8756+ ?. (unique-value-name i.names.i.args globals.state) ~
8757+ =/ source=(unit def) (~(get by gate-defs.state) i.names.i.args)
8758+ ?~ source ~
8759+ =/ sample=(unit sample) (direct-gate-sample u.source)
8760+ ?~ sample ~
8761+ =/ trial=ifit (direct-function-fit x y u.sample shape.i.slots sub next)
8762+ ?. ?=(%ok -.trial) ~
8763+ `trial
8764+ ?~ result [%unknown ~]
8765+ =. fit u.result
8766+ ?: last fit
8767+ ?. &(?=(%cell -.actual) ?=(%cell -.expected)) [%unknown ~]
8768+ ?. ?=(%ok -.fit) [%unknown ~]
8769+ $(args t.args, slots t.slots, actual tal.actual, expected tal.expected, sub sub.fit, next next.fit)
8770+++ direct-any-gate-arg
8771+ |= [args=(list expr) defs=(map term def)]
8772+ ^- ?
8773+ ?~ args |
8774+ =/ found=?
8775+ ?. ?=(%wing -.i.args) |
8776+ ?. ?=([@ ~] names.i.args) |
8777+ ?=(^ (~(get by defs) i.names.i.args))
8778+ ?: found &
8779+ $(args t.args)
8780+++ direct-gate-call-fit
8781+ |= [e=expr actual=itype expected=itype env=ienv state=istate]
8782+ ^- (unit ifit)
8783+ ?. ?=(%call -.e) ~
8784+ ?~ args.e ~
8785+ ?~ t.args.e ~
8786+ ?. &(?=(%cell -.actual) ?=(%cell -.expected)) ~
8787+ ?. ?=(%wing -.head.e) ~
8788+ ?. ?=([@ ~] names.head.e) ~
8789+ ?. ?=(~ (ienv-lookup i.names.head.e env)) ~
8790+ ?. (unique-value-name i.names.head.e globals.state) ~
8791+ ?. (direct-any-gate-arg args.e gate-defs.state) ~
8792+ ?~ prelude.state ~
8793+ ?~ source.u.prelude.state ~
8794+ ?~ head-evidence.state ~
8795+ ?. =(u.prelude.state iface.u.head-evidence.state) ~
8796+ ?. ?=(^ (ienv-lookup i.names.head.e values.u.prelude.state)) ~
8797+ =/ head=(unit def) (~(get by gates.u.head-evidence.state) i.names.head.e)
8798+ ?~ head ~
8799+ =/ sam=(unit sample) (direct-gate-sample u.head)
8800+ ?~ sam ~
8801+ ?. ?=(%cell -.u.sam) ~
8802+ =/ fit=ifit (direct-positional-fit args.e items.u.sam actual expected env state sub.state next.state)
8803+ ?. ?=(%ok -.fit) ~
8804+ :: Enclosing inference may add constraints after this call. Only a
8805+ :: closed call-sample proof can remain stable under those later bindings.
8806+ =/ actual-final=itype (itype-normalize actual sub.fit)
8807+ =/ expected-final=itype (itype-normalize expected sub.fit)
8808+ ?^ (itype-vars actual-final) ~
8809+ ?^ (itype-vars expected-final) ~
8810+ ?: |((itype-has-tag actual-final) (itype-has-tag expected-final)) ~
8811+ :: A later argument may resolve a variable used by an earlier slot.
8812+ :: Recheck every fit and face against the completed substitution; no
8813+ :: additional binding or fresh variable is permitted in the second pass.
8814+ =/ verified=ifit (direct-positional-fit args.e items.u.sam actual expected env state sub.fit next.fit)
8815+ ?. ?=(%ok -.verified) ~
8816+ ?. &(=(sub.fit sub.verified) =(next.fit next.verified)) ~
8817+ `fit
8818+::
8819+++ infer-call-with-head
8820+ |= [e=expr env=ienv state=istate head=iresult]
8821+ ^- iresult
8822+ ?> ?=(%call -.e)
8823+ ?~ args.e [%| ["call has no argument" ~]]
8824+ ?: ?=(%| -.head) head
8825+ =/ head-type=itype (itype-walk typ.p.head sub.state.p.head)
8826+ =/ arg=iresult
8827+ ?^ t.args.e
8828+ ?: ?=(%fn -.head-type)
8829+ (infer-call-context-args args.e sample.head-type env state.p.head (span-of head.e))
8830+ (infer-simple-items (turn args.e |=(a=expr [(span-of a) ~ a])) env state.p.head)
8831+ ?: ?=(%fn -.head-type)
8832+ (infer-call-context-arg i.args.e sample.head-type env state.p.head (span-of head.e))
8833+ (infer-fragment i.args.e env state.p.head)
8834+ ?: ?=(%| -.arg) arg
8835+ =/ st=istate state.p.arg
8836+ =/ ht=itype (itype-walk typ.p.head sub.st)
8837+ ?: ?=(%fn -.ht)
8838+ =/ shape=(unit [source=iwfields target=iwfields])
8839+ ?^ t.args.e ~
8840+ (width-shape typ.p.arg sample.ht sub.st)
8841+ ?^ shape [%| ["record width constraint needs unsupported inference" ~]]
8842+ =/ fit=ifit
8843+ ?^ t.args.e (itype-fit-inner typ.p.arg sample.ht sub.st next.st & |)
8844+ (itype-fit typ.p.arg sample.ht sub.st next.st)
8845+ =/ direct=(unit ifit)
8846+ ?: ?=(%ok -.fit) ~
8847+ (direct-gate-call-fit e typ.p.arg sample.ht env st)
8848+ =. fit ?~(direct fit u.direct)
8849+ ?: ?=(%unknown -.fit)
8850+ ?~ defer.st [%| ["call constraint is not supported by partial inference" ~]]
8851+ =/ edge=(unit dgo) (dg-eligible-ctor e typ.p.head typ.p.arg sample.ht st)
8852+ ?~ edge [%| ["call constraint is not supported by partial inference" ~]]
8853+ ?: (gth (lent obligations.st) 63) [%| ["call constraint is not supported by partial inference" ~]]
8854+ [%& product.ht st(obligations [u.edge obligations.st])]
8855+
8856+ ?: ?=(%bad -.fit)
8857+ ?~ t.args.e
8858+ =/ missing=(unit idiag) (missing-union-tag i.args.e sample.ht sub.st (span-of head.e))
8859+ ?^ missing [%| u.missing]
8860+ =/ nested=(unit idiag) (nested-missing-tag i.args.e typ.p.arg sample.ht sub.st next.st (span-of head.e))
8861+ ?^ nested [%| u.nested]
8862+ [%| ["call's sample and argument types do not unify" ~[[(span-of head.e) (site-type-note "called gate" ht sub.st)] [(span-of i.args.e) (site-type-note "argument" typ.p.arg sub.st)]]]]
8863+ =/ bad=(unit [at=span typ=itype])
8864+ (call-error-site args.e typ.p.arg sample.ht sub.st next.st)
8865+ =/ whole-args=span
8866+ [beg:(span-of i.args.e) end:(span-of (rear args.e))]
8867+ =/ arg-at=span ?~(bad whole-args at.u.bad)
8868+ =/ arg-type=itype ?~(bad typ.p.arg typ.u.bad)
8869+ [%| ["call's sample and argument types do not unify" ~[[(span-of head.e) (site-type-note "called gate" ht sub.st)] [arg-at (site-type-note "argument" arg-type sub.st)]]]]
8870+ ?: &(?=(^ defer.st) !(dg-stable-call-fit typ.p.arg sample.ht product.ht sub.fit ?=(^ t.args.e)))
8871+ [%| ["deferred call fit needs stable inference" ~]]
8872+ =/ face-asym=?
8873+ ?^ direct |
8874+ ?^ t.args.e (itype-positional-face-asym args.e typ.p.arg sample.ht sub.fit)
8875+ (itype-face-asym typ.p.arg sample.ht sub.fit)
8876+ ?: &((itype-has-face typ.p.arg sub.fit) face-asym (itype-output-may-be-cell product.ht sub.fit))
8877+ [%| ["call result face propagation is not supported by partial inference" ~]]
8878+ [%& product.ht st(sub sub.fit, next next.fit)]
8879+ =/ result=itype [%var next.st]
8880+ =/ uni=(unit isub) (itype-unify ht [%fn typ.p.arg result] sub.st)
8881+ ?~ uni
8882+ [%| ["call's sample and argument types do not unify" ~[[(span-of head.e) (site-type-note "called gate" ht sub.st)] [(span-of i.args.e) (site-type-note "argument" typ.p.arg sub.st)]]]]
8883+ [%& result st(next +(next.st), sub u.uni)]
8884+::
8885+++ call-error-site
8886+ |= [args=(list expr) actual=itype expected=itype sub=isub next=@ud]
8887+ ^- (unit [at=span typ=itype])
8888+ ?~ args ~
8889+ =/ original=[left=itype right=itype] [actual expected]
8890+ ?: |(?=(%var -.left.original) ?=(%avar -.left.original) ?=(%rvar -.left.original) |(?=(%nvar -.left.original) ?=(%rnvar -.left.original)) ?=(%var -.right.original) ?=(%avar -.right.original) ?=(%rvar -.right.original) |(?=(%nvar -.right.original) ?=(%rnvar -.right.original))) ~
8891+ =. actual (itype-walk actual sub)
8892+ =. expected (itype-walk expected sub)
8893+ ?: &(?=(%face -.expected) !?=(%face -.actual))
8894+ $(expected body.expected)
8895+ ?~ t.args
8896+ =/ fit=ifit (itype-fit actual expected sub next)
8897+ ?. ?=(%bad -.fit) ~
8898+ `[(span-of i.args) (itype-normalize actual sub)]
8899+ ?. &(?=(%cell -.actual) ?=(%cell -.expected)) ~
8900+ =/ first=ifit (itype-fit hed.actual hed.expected sub next)
8901+ ?: ?=(%bad -.first) `[(span-of i.args) (itype-normalize hed.actual sub)]
8902+ ?: ?=(%unknown -.first) ~
8903+ $(args t.args, actual tal.actual, expected tal.expected, sub sub.first, next next.first)
8904+::
8905+:: Context can help a call argument or cast value while the final fit
8906+:: checks the complete right-nested type, including any written faces.
8907+::
8908+:: Context can resolve the payload of a canonical prelude unit, but an
8909+:: unrelated union with a similar noun shape is not the same mold.
8910+++ infer-unit-context
8911+ |= [e=expr expected=itype env=ienv state=istate context=span]
8912+ ^- iresult
8913+ ?> ?=(%unit -.e)
8914+ ?> ?=(%union -.expected)
8915+ ?~ prelude.state (infer-fragment e env state)
8916+ =/ standard=(unit ischeme) (find-jibb-mold %unit u.prelude.state)
8917+ ?~ standard (infer-fragment e env state)
8918+ ?. (standard-unit-template u.standard at.u.prelude.state) (infer-fragment e env state)
8919+ ?. =(origin.expected `[at.u.prelude.state %unit]) (infer-fragment e env state)
8920+ ?~ args.expected (infer-fragment e env state)
8921+ ?^ t.args.expected (infer-fragment e env state)
8922+ =/ payload=itype i.args.expected
8923+ =/ canonical=(unit itype) (template-apply u.standard ~[payload])
8924+ ?~ canonical (infer-fragment e env state)
8925+ ?> ?=(%union -.u.canonical)
8926+ ?. =((itype-normalize expected(label ~) sub.state) (itype-normalize u.canonical(label ~) sub.state))
8927+ (infer-fragment e env state)
8928+ =/ value=iresult (infer-call-context-arg val.e payload env state context)
8929+ ?: ?=(%| -.value) value
8930+ =/ fit=ifit (itype-fit typ.p.value payload sub.state.p.value next.state.p.value)
8931+ ?: ?=(%unknown -.fit) [%| ["unit payload constraint is not supported by partial inference" ~]]
8932+ ?: ?=(%bad -.fit)
8933+ =/ missing=(unit idiag) (missing-union-tag val.e payload sub.state.p.value context)
8934+ ?^ missing [%| u.missing]
8935+ =/ nested=(unit idiag) (nested-missing-tag val.e typ.p.value payload sub.state.p.value next.state.p.value context)
8936+ ?^ nested [%| u.nested]
8937+ [%| ["unit payload does not fit its expected type" ~[[context (site-type-note "expected unit payload" payload sub.state.p.value)] [(span-of val.e) (site-type-note "payload" typ.p.value sub.state.p.value)]]]]
8938+ [%& expected state.p.value(sub sub.fit, next next.fit)]
8939+::
8940+:: A known gate may receive an enclosing target before its argument is
8941+:: inferred when its result is open or a direct, matching named generic
8942+:: union. Opaque, recursive, tag-constrained and variable-bound union
8943+:: results keep the existing directional path.
8944+++ infer-contextual-call
8945+ |= [e=expr expected=itype env=ienv state=istate]
8946+ ^- iresult
8947+ ?> ?=(%call -.e)
8948+ ?~ args.e [%| ["call has no argument" ~]]
8949+ =/ head=iresult (infer-fragment head.e env state)
8950+ ?: ?=(%| -.head) head
8951+ =/ ht=itype (itype-walk typ.p.head sub.state.p.head)
8952+ ?. ?=(%fn -.ht) (infer-call-with-head e env state head)
8953+ =/ result=itype (itype-walk product.ht sub.state.p.head)
8954+ =/ eligible=?
8955+ ?: ?=(%var -.result) &
8956+ :: A direct known generic union may receive the same nominal result
8957+ :: context before its arguments are checked. Variable-bound origins,
8958+ :: pending tags, recursive identities and unknown atoms stay open.
8959+ ?. &(?=(%union -.product.ht) ?=(%union -.result) ?=(%union -.expected)) |
8960+ ?~ origin.result |
8961+ ?. =(origin.result origin.expected) |
8962+ ?~ args.result |
8963+ ?. =((lent args.result) (lent args.expected)) |
8964+ ?: |((itype-has-tag (itype-normalize result sub.state.p.head)) (itype-has-tag (itype-normalize expected sub.state.p.head))) |
8965+ ?: |((itype-has-recursive (itype-normalize result sub.state.p.head)) (itype-has-recursive (itype-normalize expected sub.state.p.head))) |
8966+ ?: |((itype-has-any-atom result sub.state.p.head) (itype-has-any-atom expected sub.state.p.head)) |
8967+ &
8968+ ?. eligible (infer-call-with-head e env state head)
8969+ ?: |(?=(%var -.expected) ?=(%avar -.expected) ?=(%rvar -.expected) |(?=(%nvar -.expected) ?=(%rnvar -.expected)) (itype-has-tag (itype-normalize expected sub.state.p.head)))
8970+ (infer-call-with-head e env state head)
8971+ =/ sub=(unit isub) (itype-unify result expected sub.state.p.head)
8972+ ?~ sub (infer-call-with-head e env state head)
8973+ (infer-call-with-head e env state [%& typ.p.head state.p.head(sub u.sub)])
8974+::
8975+:: An eligible fully faced literal receives context by name, in source order.
8976+++ width-literal-fields
8977+ |= [items=(list item) axis=@ud fuel=@ud]
8978+ ^- (unit iwfields)
8979+ =/ order=(list iwfield) ~
8980+ =/ index=(map term iwfield) *(map term iwfield)
8981+ |-
8982+ ?~ items ~
8983+ ?: =(0 fuel) ~
8984+ ?~ face.i.items ~
8985+ =/ at-axis=@ud ?~(t.items axis (mul 2 axis))
8986+ =/ entry=iwfield [u.face.i.items at-axis [%noun ~]]
8987+ ?: ?=(^ (~(get by index) name.entry)) ~
8988+ =. index (~(put by index) name.entry entry)
8989+ =. order [entry order]
8990+ ?~ t.items `[(flop order) index]
8991+ $(items t.items, axis +((mul 2 axis)), fuel (dec fuel))
8992+++ width-infer-items
8993+ |= [items=(list item) expected=(map term iwfield) env=ienv state=istate context=span]
8994+ ^- iresult
8995+ ?~ items [%| ["empty record is not supported" ~]]
8996+ ?~ face.i.items [%| ["record face needs unsupported inference" ~]]
8997+ =/ field=(unit iwfield) (~(get by expected) u.face.i.items)
8998+ =/ head=iresult
8999+ ?~ field (infer-fragment val.i.items env state)
9000+ (infer-call-context-arg val.i.items typ.u.field env state context)
9001+ ?: ?=(%| -.head) head
9002+ =/ typ=itype [%face u.face.i.items typ.p.head]
9003+ ?~ t.items [%& typ state.p.head]
9004+ =/ tail=iresult $(items t.items, state state.p.head)
9005+ ?: ?=(%| -.tail) tail
9006+ [%& [%cell typ typ.p.tail] state.p.tail]
9007+++ width-infer-literal
9008+ |= [e=expr expected=itype env=ienv state=istate context=span]
9009+ ^- (unit iresult)
9010+ ?. ?=(%tuple -.e) ~
9011+ ?. |(?=(%cell -.expected) ?=(%face -.expected)) ~
9012+ =/ source=(unit iwfields) (width-literal-fields items.e 1 4.096)
9013+ =/ target=(unit iwfields) (width-scan expected sub.state 1 4.096)
9014+ ?~ source ~
9015+ ?~ target ~
9016+ ?: (lth (lent order.u.source) (lent order.u.target)) ~
9017+ ?. (width-in-order order.u.source order.u.target)
9018+ `(infer-simple-items items.e env state)
9019+ `(width-infer-items items.e index.u.target env state context)
9020+::
9021+:: Experimental intrinsic recognition; real bindings retain normal calls.
9022+++ explicit-proj-call
9023+ |= [e=expr env=ienv state=istate]
9024+ ^- ?
9025+ ?. ?=(%call -.e) |
9026+ ?. ?=([* ~] args.e) |
9027+ ?. ?=(%wing -.head.e) |
9028+ ?. =(names.head.e ~[%proj]) |
9029+ ?: ?=(^ (ienv-lookup %proj env)) |
9030+ ?: (lien globals.state |=(n=term =(n %proj))) |
9031+ ?~ prelude.state &
9032+ ?:(?=(^ (ienv-lookup %proj values.u.prelude.state)) | &)
9033+++ infer-proj-source
9034+ |= [e=expr expected=itype env=ienv state=istate context=span]
9035+ ^- iresult
9036+ ?: ?=(%group -.e) $(e inner.e)
9037+ =/ literal=(unit iresult) (width-infer-literal e expected env state context)
9038+ ?^ literal u.literal
9039+ (infer-fragment e env state)
9040+++ infer-proj-context
9041+ |= [e=expr expected=itype env=ienv state=istate context=span]
9042+ ^- iresult
9043+ ?> ?=(%call -.e)
9044+ ?~ args.e [%| ["proj needs one record" ~]]
9045+ ?. |(?=(%cell -.expected) ?=(%face -.expected)) [%| ["proj needs an expected record type" ~]]
9046+ =/ value=iresult (infer-proj-source i.args.e expected env state context)
9047+ ?: ?=(%| -.value) value
9048+ =/ shape=(unit [source=iwfields target=iwfields])
9049+ (width-proj-shape typ.p.value expected sub.state.p.value)
9050+ ?~ shape [%| ["proj needs a known record containing its expected fields" ~]]
9051+ =/ project=(unit iwidth-result) (width-project u.shape sub.state.p.value next.state.p.value)
9052+ ?~ project [%| ["proj constraint needs unsupported inference" ~]]
9053+ =/ st=istate state.p.value(sub sub.u.project, next next.u.project)
9054+ [%& expected st(projections [[at.e e typ.p.value expected steps.u.project] projections.st])]
9055+::
9056+:: A known literal singleton in a direct union can contextualize a
9057+:: loobean literal of the same noun. Only explicit singleton and cell
9058+:: competitors are considered; opaque or variable cases stay unknown.
9059+++ explicit-singleton-in-union
9060+ |= [t=itype noun=@]
9061+ ^- ?
9062+ ?. ?=(%union -.t) |
9063+ =/ cases=(list itype) cases.t
9064+ =/ found=? |
9065+ |-
9066+ ?~ cases found
9067+ =/ c=itype i.cases
9068+ ?: ?=(%cell -.c) $(cases t.cases)
9069+ ?. ?=(%const -.c) |
9070+ ?: =(noun val.literal.c)
9071+ ?: found |
9072+ $(cases t.cases, found &)
9073+ $(cases t.cases)
9074+::
9075+:: Select a written literal-headed case only when every competing case is
9076+:: also an explicit singleton-headed cell and exactly one matches. Opaque,
9077+:: variable-bound and differently shaped cases keep inference unchanged.
9078+:: This first slice supplies context to a directly called payload. Plain
9079+:: literal data and other expressions retain their existing inference path.
9080+++ contextual-atomic-arguments
9081+ |= args=(list expr)
9082+ ^- ?
9083+ ?~ args &
9084+ ?. ?=(?(%lit %wing %ctor) -.i.args) |
9085+ $(args t.args)
9086+++ contextual-direct-payload-call
9087+ |= e=expr
9088+ ^- ?
9089+ ?: ?=(%group -.e) $(e inner.e)
9090+ ?. ?=(%call -.e) |
9091+ ?. ?=(%wing -.head.e) |
9092+ ?~ args.e |
9093+ (contextual-atomic-arguments args.e)
9094+::
9095+:: A walked variable may have concealed a union inside a substituted
9096+:: structure before this arm was called. Decline in that case rather than
9097+:: deriving provenance from the already-walked type.
9098+++ contextual-simple-sub
9099+ |= sub=isub
9100+ ^- ?
9101+ ?~ sub &
9102+ ?: ?=(?(%cell %face %fn %union %collection) -.val.i.sub) |
9103+ $(sub t.sub)
9104+::
9105+:: Check the syntactic root before scanning; scan substitutions once.
9106+++ grec-direct-context
9107+ |= [expected=itype sub=isub]
9108+ ^- ?
9109+ =/ left=@ud 4.096
9110+ |-
9111+ ?: ?=(%face -.expected)
9112+ ?: =(0 left) |
9113+ $(expected body.expected, left (dec left))
9114+ ?. ?=(%grec -.expected) |
9115+ ?~ sub &
9116+ ?: =(0 left) |
9117+ ?: ?=(?(%cell %face %fn %union %collection %grec) -.val.i.sub) |
9118+ $(sub t.sub, left (dec left))
9119+++ contextual-direct-union
9120+ |= target=itype
9121+ ^- ?
9122+ ?: ?=(%face -.target) $(target body.target)
9123+ ?=(%union -.target)
9124+++ contextual-tagged-case
9125+ |= [target=itype tag=@ sub=isub]
9126+ ^- (unit itype)
9127+ ?. ?=(%union -.target) ~
9128+ =/ remaining=(list itype) cases.target
9129+ =/ found=(unit itype) ~
9130+ =/ seen=(set @) *(set @)
9131+ |-
9132+ ?~ remaining found
9133+ =/ c=itype i.remaining
9134+ ?. ?=(%cell -.c) ~
9135+ =/ head=itype hed.c
9136+ ?. ?=(%const -.head) ~
9137+ ?: (~(has in:..zuse seen) val.literal.head) ~
9138+ =. seen (~(put in:..zuse seen) val.literal.head)
9139+ ?: =(tag val.literal.head)
9140+ $(remaining t.remaining, found `c)
9141+ $(remaining t.remaining)
9142+::
9143+:: A bounded syntactic screen: no nested branch, cast, gate or local body
9144+:: can re-enter cell-branch retry during either inference attempt.
9145+++ closed-cell-retry-safe
9146+ |= [todo=(list expr) fuel=@ud]
9147+ ^- ?
9148+ ?~ todo &
9149+ ?: =(0 fuel) |
9150+ =/ e=expr i.todo
9151+ =. fuel (dec fuel)
9152+ ?+ -.e |
9153+ %lit $(todo t.todo)
9154+ %wing $(todo t.todo)
9155+ %ctor $(todo t.todo)
9156+ %path $(todo t.todo)
9157+ %crash $(todo t.todo)
9158+ %str
9159+ ?. (levy pieces.e |=(p=piece ?=(%text -.p))) |
9160+ $(todo t.todo)
9161+ %group $(todo [inner.e t.todo])
9162+ %pair $(todo [val.e t.todo])
9163+ %unit $(todo [val.e t.todo])
9164+ %list $(todo (weld items.e t.todo))
9165+ %tuple $(todo (weld (turn items.e |=(i=item val.i)) t.todo))
9166+ %change $(todo (weld (turn edits.e |=(ed=edit val.ed)) t.todo))
9167+ %call $(todo [head.e (weld args.e t.todo)])
9168+ %trace $(todo [val.e then.e t.todo])
9169+ ==
9170+::
9171+++ closed-cell-sub-safe
9172+ |= [sub=isub fuel=@ud]
9173+ ^- ?
9174+ ?~ sub &
9175+ ?: =(0 fuel) |
9176+ ?: ?=(?(%cell %face %fn %union %collection %grec %jrec %recursive) -.val.i.sub) |
9177+ $(sub t.sub, fuel (dec fuel))
9178+::
9179+++ closed-cell-branch-eligible
9180+ |= [e=expr expected=itype sub=isub]
9181+ ^- ?
9182+ ?. &(?=(%branch -.e) ?=(%cell -.expected) (closed-cell-sub-safe sub 512)) |
9183+ ?~ arms.e |
9184+ ?~ t.arms.e |
9185+ ?^ t.t.arms.e |
9186+ =/ x=arm i.arms.e
9187+ =/ y=arm i.t.arms.e
9188+ ?. &(?=(%lit -.pat.x) ?=(%lit -.pat.y)) |
9189+ ?. &(=(%loobean form.lit.pat.x) =(%loobean form.lit.pat.y)) |
9190+ ?: =(val.lit.pat.x val.lit.pat.y) |
9191+ (closed-cell-retry-safe ~[subject.e val.x val.y] 512)
9192+::
9193+:: Attempt ordinary inference first; retry from the same state only for
9194+:: the bounded non-reentrant syntax above. Preserve original value faces.
9195+++ infer-closed-cell-branch
9196+ |= [e=expr expected=itype env=ienv state=istate context=span]
9197+ ^- iresult
9198+ ?> (closed-cell-branch-eligible e expected sub.state)
9199+ ?> ?=(%branch -.e)
9200+ ?> ?=(^ arms.e)
9201+ ?> ?=(^ t.arms.e)
9202+ =/ ordinary=iresult (infer-fragment e env state)
9203+ =/ ordinary-good=?
9204+ ?: ?=(%| -.ordinary) |
9205+ =/ fit=ifit (itype-fit typ.p.ordinary expected sub.state.p.ordinary next.state.p.ordinary)
9206+ ?=(%ok -.fit)
9207+ ?: ordinary-good ordinary
9208+ =/ attempt=(unit iresult)
9209+ =/ x=arm i.arms.e
9210+ =/ y=arm i.t.arms.e
9211+ =/ subject=iresult (infer-fragment subject.e env state)
9212+ ?: ?=(%| -.subject) ~
9213+ =/ subject-type=itype (itype-normalize typ.p.subject sub.state.p.subject)
9214+ ?: ?=(%union -.subject-type) ~
9215+ =/ su=(unit isub) (itype-unify typ.p.subject [%flag ~] sub.state.p.subject)
9216+ ?~ su ~
9217+ =/ left=iresult (infer-call-context-arg val.x expected env state.p.subject(sub u.su) context)
9218+ ?: ?=(%| -.left) ~
9219+ =/ lf=ifit (itype-fit typ.p.left expected sub.state.p.left next.state.p.left)
9220+ ?. ?=(%ok -.lf) ~
9221+ =/ right=iresult (infer-call-context-arg val.y expected env state.p.left(sub sub.lf, next next.lf) context)
9222+ ?: ?=(%| -.right) ~
9223+ =/ rf=ifit (itype-fit typ.p.right expected sub.state.p.right next.state.p.right)
9224+ ?. ?=(%ok -.rf) ~
9225+ =/ sub=isub sub.rf
9226+ =/ next=@ud next.rf
9227+ =/ lt=itype (itype-normalize typ.p.left sub)
9228+ =/ rt=itype (itype-normalize typ.p.right sub)
9229+ =/ et=itype (itype-normalize expected sub)
9230+ ?. =(lt rt) ~
9231+ ?: |(?=(^ (itype-vars lt)) ?=(^ (itype-vars rt)) ?=(^ (itype-vars et))) ~
9232+ ?: |((itype-has-tag lt) (itype-has-tag rt) (itype-has-tag et)) ~
9233+ =/ lcheck=ifit (itype-fit typ.p.left expected sub next)
9234+ ?. ?=(%ok -.lcheck) ~
9235+ ?. &(=(sub.lcheck sub) =(next.lcheck next)) ~
9236+ =/ rcheck=ifit (itype-fit typ.p.right expected sub next)
9237+ ?. ?=(%ok -.rcheck) ~
9238+ ?. &(=(sub.rcheck sub) =(next.rcheck next)) ~
9239+ `[%& typ.p.left state.p.right(sub sub, next next)]
9240+ ?~ attempt ordinary
9241+ u.attempt
9242+::
9243+++ infer-call-context-arg
9244+ |= [e=expr expected=itype env=ienv state=istate context=span]
9245+ ^- iresult
9246+ ?: &(?=(^ defer.state) ?=(%branch -.e)) (infer-fragment e env state)
9247+ ?: &(?=(^ defer.state) ?=(^ prelude.state) ?=(%tuple -.e))
9248+ (infer-fragment e env state)
9249+ ?: ?=(%pair -.e) $(e (pair-as-cell e))
9250+ ?: ?=(%group -.e) $(e inner.e)
9251+ ?: &(?=(%body -.e) ?=(~ defs.e)) $(e final.e)
9252+ ?: ?=(%trace -.e)
9253+ =/ traced=iresult (infer-fragment val.e env state)
9254+ ?: ?=(%| -.traced) traced
9255+ $(e then.e, state state.p.traced)
9256+ =/ target=itype (itype-walk expected sub.state)
9257+ |-
9258+ ?: ?=(%face -.target) $(target (itype-walk body.target sub.state))
9259+ ?: (explicit-proj-call e env state)
9260+ (infer-proj-context e expected env state context)
9261+ :: Experimental construction only for a source-proven direct target.
9262+ :: Decline any walked structural binding to retain raw-variable provenance.
9263+ ?: &(?=(%grec -.target) ?=(%tuple -.e) (grec-direct-context expected sub.state))
9264+ =/ unfolded=(unit [view=itype left=@ud]) (grec-unfold-view target jrec-fuel.state)
9265+ ?~ unfolded [%| ["recursive mold unfolding needs unsupported inference" ~]]
9266+ ?~ items.e [%| ["recursive mold constructor needs unsupported inference" ~]]
9267+ =/ first=item i.items.e
9268+ ?. &(?=(~ face.first) ?=(%lit -.val.first) =(%term form.lit.val.first))
9269+ [%| ["recursive mold constructor needs unsupported inference" ~]]
9270+ =/ chosen=(unit itype) (contextual-tagged-case view.u.unfolded val.lit.val.first sub.state)
9271+ ?~ chosen [%| ["recursive mold constructor has no matching case" ~]]
9272+ =/ value=iresult (infer-call-context-items items.e u.chosen env state(jrec-fuel left.u.unfolded) context)
9273+ ?: ?=(%| -.value) value
9274+ =/ fit=ifit (itype-fit typ.p.value u.chosen sub.state.p.value next.state.p.value)
9275+ ?: ?=(%unknown -.fit) [%| ["recursive mold case needs unsupported inference" ~]]
9276+ ?: ?=(%bad -.fit) [%| ["recursive mold case does not fit its source shape" ~]]
9277+ [%& target state.p.value(sub sub.fit, next next.fit)]
9278+ :: Only the source-proven one-layer cell is exposed. Each recursive
9279+ :: descent consumes one written tuple; named values use ordinary fit.
9280+ ?: &(?=(%jrec -.target) ?=(%lit -.e) =(%null form.lit.e))
9281+ ?: =(0 jrec-fuel.state) [%| ["recursive mold unfolding needs unsupported inference" ~]]
9282+ [%& target state(jrec-fuel (dec jrec-fuel.state))]
9283+ ?: &(?=(%jrec -.target) ?=(%tuple -.e))
9284+ ?: =(0 jrec-fuel.state) [%| ["recursive mold unfolding needs unsupported inference" ~]]
9285+ =. state state(jrec-fuel (dec jrec-fuel.state))
9286+ =/ shape=itype
9287+ [%cell [%face head.target [%atom aura.target]] [%face tail.target target]]
9288+ =/ value=iresult (infer-call-context-items items.e shape env state context)
9289+ ?: ?=(%| -.value) value
9290+ =/ fit=ifit (itype-fit typ.p.value shape sub.state.p.value next.state.p.value)
9291+ ?: ?=(%unknown -.fit) [%| ["recursive mold cell constraint needs unsupported inference" ~]]
9292+ ?: ?=(%bad -.fit) [%| ["recursive mold cell does not fit its source shape" ~]]
9293+ [%& target state.p.value(sub sub.fit, next next.fit)]
9294+ ?: ?=(%call -.e) (infer-contextual-call e target env state)
9295+ =/ empty-list=(unit iresult) (empty-list-null-branch e env state `[target context])
9296+ ?^ empty-list u.empty-list
9297+ ?: (single-structured-pattern e)
9298+ ?> ?=(%branch -.e)
9299+ =/ empty-union=(unit iresult) (known-empty-union-wing subject.e env state)
9300+ ?^ empty-union (infer-known-union-context-subject e target env u.empty-union context)
9301+ =/ single=(unit iresult) (grec-single-wing-subject subject.e env state)
9302+ ?^ single (infer-known-union-context-subject e target env u.single context)
9303+ (infer-single-case-branch e env state `[target context])
9304+ ?: (cell-binder-pattern e)
9305+ (infer-cell-branch e env state `[target context])
9306+ :: In an explicit singleton context retain the written loobean noun;
9307+ :: the ordinary singleton fit compares its noun, not its spelling.
9308+ =/ singleton=(unit itype)
9309+ ?. ?=(%lit -.e) ~
9310+ ?. =(%loobean form.lit.e) ~
9311+ ?. |(?=(%const -.target) &(?=(%union -.expected) (explicit-singleton-in-union expected val.lit.e))) ~
9312+ `[%const lit.e]
9313+ ?^ singleton [%& u.singleton state]
9314+ =/ known=(unit iresult)
9315+ ?: ?=(%branch -.e) (known-union-subject subject.e env state)
9316+ ~
9317+ ?: &(?=(^ known) ?=(%| -.u.known) !(duplicate-loobean-arms e)) u.known
9318+ ?: &(?=(^ known) ?=(%& -.u.known) ?=(~ (unit-union-payload (itype-normalize typ.p.u.known sub.state.p.u.known))))
9319+ (infer-known-union-context-subject e target env u.known context)
9320+ ?: &(?=(%union -.target) ?=(%unit -.e))
9321+ (infer-unit-context e target env state context)
9322+ ?: (closed-cell-branch-eligible e expected sub.state)
9323+ (infer-closed-cell-branch e expected env state context)
9324+ ?: &(?=(%flag -.target) (context-union-branch e))
9325+ (infer-union-context e target env state context)
9326+ ?: &(?=(%union -.target) (context-union-branch e))
9327+ (infer-union-context e target env state context)
9328+ ?: &(?=(%collection -.target) =(%list name.target) (context-union-branch e))
9329+ (infer-union-context e target env state context)
9330+ ?: &(?=(%collection -.target) =(%list name.target) (context-list-expression e))
9331+ (infer-list-context e target env state context)
9332+ :: A literal-headed tuple can receive the unique case's payload
9333+ :: context. The ordinary final fit still checks the complete union.
9334+ =/ selected=(unit itype)
9335+ ?. &((contextual-simple-sub sub.state) (contextual-direct-union expected) ?=(%union -.target) ?=(%tuple -.e) ?=(^ items.e)) ~
9336+ ?~ t.items.e ~
9337+ ?^ t.t.items.e ~
9338+ ?. (contextual-direct-payload-call val.i.t.items.e) ~
9339+ =/ first=item i.items.e
9340+ ?. &(?=(~ face.first) ?=(%lit -.val.first) |(=(%term form.lit.val.first) =(%null form.lit.val.first) =(%loobean form.lit.val.first))) ~
9341+ (contextual-tagged-case target val.lit.val.first sub.state)
9342+ ?^ selected
9343+ ?> ?=(%tuple -.e)
9344+ :: On this bounded shallow-call shape, preserve any inference that
9345+ :: already fits before trying the new contextual path. Neither pass
9346+ :: can recursively select a nested tuple from the atomic arguments.
9347+ =/ ordinary=(unit iresult)
9348+ =/ initial=iresult (infer-fragment e env state)
9349+ ?: ?=(%| -.initial) ~
9350+ =/ fit=ifit (itype-fit typ.p.initial target sub.state.p.initial next.state.p.initial)
9351+ ?. ?=(%ok -.fit) ~
9352+ `initial
9353+ ?^ ordinary u.ordinary
9354+ =/ value=iresult (infer-call-context-items items.e u.selected env state context)
9355+ ?: ?=(%| -.value) value
9356+ =/ fit=ifit (itype-fit typ.p.value u.selected sub.state.p.value next.state.p.value)
9357+ ?: ?=(%unknown -.fit) [%| ["tagged case needs unsupported inference" ~]]
9358+ ?: ?=(%bad -.fit) [%| ["tagged case does not fit its expected type" ~[[context "expected union case"] [(span-of e) "value"]]]]
9359+ [%& typ.p.value state.p.value(sub sub.fit, next next.fit)]
9360+ ?: &(?=(%cell -.target) ?=(%tuple -.e))
9361+ (infer-call-context-items items.e target env state context)
9362+ (infer-fragment e env state)
9363+::
9364+:: Preserve each written face; the final complete sample fit checks faces.
9365+:: A tuple or positional field face belongs to the enclosing sample,
9366+:: not to the expression at that position. A second face, if present,
9367+:: is part of the value's own expected type.
9368+++ projection-field-target
9369+ |= expected=itype
9370+ ^- itype
9371+ ?:(?=(%face -.expected) body.expected expected)
9372+::
9373+++ infer-call-context-items
9374+ |= [items=(list item) expected=itype env=ienv state=istate context=span]
9375+ ^- iresult
9376+ ?~ items [%| ["empty cell is not supported by partial inference" ~]]
9377+ ?~ t.items
9378+ =/ last=iresult (infer-call-context-arg val.i.items (projection-field-target expected) env state context)
9379+ ?: ?=(%| -.last) last
9380+ =/ typ=itype typ.p.last
9381+ =. typ ?~(face.i.items typ [%face u.face.i.items typ])
9382+ [%& typ state.p.last]
9383+ =/ target=itype (itype-walk expected sub.state)
9384+ |-
9385+ ?: ?=(%face -.target) $(target (itype-walk body.target sub.state))
9386+ ?. ?=(%cell -.target) (infer-simple-items items env state)
9387+ =/ head=iresult (infer-call-context-arg val.i.items (projection-field-target hed.target) env state context)
9388+ ?: ?=(%| -.head) head
9389+ =/ typ=itype typ.p.head
9390+ =. typ ?~(face.i.items typ [%face u.face.i.items typ])
9391+ =/ tail=iresult (infer-call-context-items t.items tal.target env state.p.head context)
9392+ ?: ?=(%| -.tail) tail
9393+ [%& [%cell typ typ.p.tail] state.p.tail]
9394+::
9395+++ infer-call-context-args
9396+ |= [args=(list expr) expected=itype env=ienv state=istate context=span]
9397+ ^- iresult
9398+ ?~ args [%| ["call has no argument" ~]]
9399+ ?~ t.args (infer-call-context-arg i.args (projection-field-target expected) env state context)
9400+ =/ target=itype (itype-walk expected sub.state)
9401+ |-
9402+ ?: ?=(%face -.target) $(target (itype-walk body.target sub.state))
9403+ ?. ?=(%cell -.target)
9404+ (infer-simple-items (turn args |=(a=expr [(span-of a) ~ a])) env state)
9405+ =/ head=iresult (infer-call-context-arg i.args (projection-field-target hed.target) env state context)
9406+ ?: ?=(%| -.head) head
9407+ =/ tail=iresult (infer-call-context-args t.args tal.target env state.p.head context)
9408+ ?: ?=(%| -.tail) tail
9409+ [%& [%cell typ.p.head typ.p.tail] state.p.tail]
9410+::
9411+:: Tuple and record expressions preserve their explicitly written faces.
9412+::
9413+++ infer-simple-items
9414+ |= [items=(list item) env=ienv state=istate]
9415+ ^- iresult
9416+ ?~ items [%| ["empty cell is not supported by partial inference" ~]]
9417+ =/ head=iresult (infer-fragment val.i.items env state)
9418+ ?: ?=(%| -.head) head
9419+ =/ ht=itype typ.p.head
9420+ =. ht ?~(face.i.items ht [%face u.face.i.items ht])
9421+ ?~ t.items [%& ht state.p.head]
9422+ =/ tail=iresult $(items t.items, state state.p.head)
9423+ ?: ?=(%| -.tail) tail
9424+ [%& [%cell ht typ.p.tail] state.p.tail]
9425+::
9426+:: A single all-binder cell pattern covers a known cell spine; the final
9427+:: binder captures the remaining noun. Other pattern matrices stay partial.
9428+::
9429+:: Validate binders before reading the subject, preserving shadow-error
9430+:: precedence. The last binder receives the entire remaining tail.
9431+++ cell-pattern-names
9432+ |= [pats=(list pattern) env=ienv globals=(list term) seen=(list term)]
9433+ ^- (each (list term) @t)
9434+ ?~ pats [%& ~]
9435+ ?. ?=(%bind -.i.pats) [%| 'branch pattern is not supported by partial inference']
9436+ =/ name=term name.i.pats
9437+ ?: |(=(name %proj) ?=(^ (ienv-lookup name env)) (lien globals |=(n=term =(n name))) (lien seen |=(n=term =(n name))))
9438+ [%| 'pattern shadows a name']
9439+ =/ rest=(each (list term) @t) $(pats t.pats, seen [name seen])
9440+ ?: ?=(%| -.rest) rest
9441+ [%& [name p.rest]]
9442+::
9443+++ cell-pattern-types
9444+ |= [names=(list term) env=ienv next=@ud]
9445+ ^- [typ=itype env=ienv next=@ud]
9446+ ?~ names !!
9447+ =/ head=itype [%var next]
9448+ =/ scope=ienv [[i.names [head ~]] env]
9449+ ?~ t.names [head scope +(next)]
9450+ =/ tail=[typ=itype env=ienv next=@ud] $(names t.names, env scope, next +(next))
9451+ [[%cell head typ.tail] env.tail next.tail]
9452+::
9453+:: At every position that must be a cell, opaque or sum types may still
9454+:: contain cells. Do not report a definite mismatch without unfolding them.
9455+++ cell-pattern-spine-unknown
9456+ |= [typ=itype names=(list term) sub=isub]
9457+ ^- ?
9458+ ?~ names |
9459+ ?~ t.names |
9460+ =. typ (itype-walk typ sub)
9461+ ?: ?=(%cell -.typ) $(typ tal.typ, names t.names)
9462+ |(?=(%union -.typ) ?=(%collection -.typ) ?=(%recursive -.typ) ?=(%jrec -.typ) ?=(%grec -.typ) ?=(%noun -.typ) ?=(%fn -.typ) ?=(%tag -.typ))
9463+::
9464+++ cell-binder-pattern
9465+ |= e=expr
9466+ ^- ?
9467+ ?. ?=(%branch -.e) |
9468+ ?~ arms.e |
9469+ ?^ t.arms.e |
9470+ ?. ?=(%cell -.pat.i.arms.e) |
9471+ !(single-structured-pattern e)
9472+::
9473+++ infer-cell-branch
9474+ |= [e=expr env=ienv state=istate expected=(unit [typ=itype context=span])]
9475+ ^- iresult
9476+ ?> ?=(%branch -.e)
9477+ ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
9478+ =/ arm=arm i.arms.e
9479+ ?. ?=(%cell -.pat.arm) [%| ["branch pattern is not supported by partial inference" ~]]
9480+ =/ pats=(list pattern) items.pat.arm
9481+ ?~ pats [%| ["branch pattern is not supported by partial inference" ~]]
9482+ ?~ t.pats [%| ["branch pattern is not supported by partial inference" ~]]
9483+ =/ names=(each (list term) @t) (cell-pattern-names pats env globals.state ~)
9484+ ?: ?=(%| -.names) [%| [(trip p.names) ~]]
9485+ =/ subject=iresult (infer-fragment subject.e env state)
9486+ ?: ?=(%| -.subject) subject
9487+ =/ st=istate state.p.subject
9488+ =/ subject-type=itype (itype-normalize typ.p.subject sub.st)
9489+ ?: (itype-has-recursive subject-type)
9490+ [%| ["recursive pattern is not supported by partial inference" ~]]
9491+ ?: (itype-has-face typ.p.subject sub.st)
9492+ [%| ["record patterns are not supported by partial inference" ~]]
9493+ ?: (cell-pattern-spine-unknown subject-type p.names sub.st)
9494+ [%| ["cell pattern subject is not supported by partial inference" ~]]
9495+ =/ binders=[typ=itype env=ienv next=@ud] (cell-pattern-types p.names env next.st)
9496+ =/ sub=(unit isub) (itype-unify typ.p.subject typ.binders sub.st)
9497+ ?~ sub [%| ["cell pattern does not match the subject type" ~]]
9498+ =. st st(next next.binders, sub u.sub)
9499+ ?~ expected (infer-fragment val.arm env.binders st)
9500+ =/ body=iresult (infer-call-context-arg val.arm typ.u.expected env.binders st context.u.expected)
9501+ ?: ?=(%| -.body) body
9502+ =/ fit=ifit (itype-fit typ.p.body typ.u.expected sub.state.p.body next.state.p.body)
9503+ ?: ?=(%unknown -.fit) [%| ["cell branch result constraint is not supported by partial inference" ~]]
9504+ ?: ?=(%bad -.fit) [%| ["cell branch arm does not fit its expected type" ~[[context.u.expected "expected type"] [(span-of val.arm) "branch arm"]]]]
9505+ ?: (itype-has-tag (itype-normalize typ.u.expected sub.fit))
9506+ [%| ["cell branch result needs context in partial inference" ~]]
9507+ [%& typ.u.expected state.p.body(sub sub.fit, next next.fit)]
9508+::
9509+++ show-itype
9510+ |= [t=itype sub=isub]
9511+ ^- tape
9512+ =. t (itype-walk t sub)
9513+ ?- -.t
9514+ %var
9515+ ?: (lth id.t 26) [(add 65 id.t) ~]
9516+ "T{<id.t>}"
9517+ %avar
9518+ ?: (lth id.t 26) [(add 65 id.t) ~]
9519+ "T{<id.t>}"
9520+ %rvar
9521+ ?: (lth id.t 26) [(add 65 id.t) ~]
9522+ "T{<id.t>}"
9523+ %nvar
9524+ ?: (lth id.t 26) [(add 65 id.t) ~]
9525+ "T{<id.t>}"
9526+ %rnvar
9527+ ?: (lth id.t 26) [(add 65 id.t) ~]
9528+ "T{<id.t>}"
9529+ %atom "@{(trip aura.t)}"
9530+ %any-atom "@"
9531+ %flag "?"
9532+ %noun "*"
9533+ %empty "!!"
9534+ %tag (trip txt.literal.t)
9535+ %const (trip txt.literal.t)
9536+ %union
9537+ ?~ label.t (show-itype-cases cases.t sub)
9538+ ?~ args.t (trip u.label.t)
9539+ "({(trip u.label.t)} {(show-itype-cases args.t sub)})"
9540+ %recursive ?~(label.t "recursive mold" (trip u.label.t))
9541+ %jrec ?~(label.t "recursive mold" (trip u.label.t))
9542+ %grec ?~(label.t "recursive mold" "({(trip u.label.t)} {(show-itype-cases args.t sub)})")
9543+ %collection "({(trip name.t)} {(show-itype-cases args.t sub)})"
9544+ %face "[{(trip name.t)}={(show-itype-context body.t sub)}]"
9545+ %fn "$-({(show-itype-context sample.t sub)} {(show-itype-context product.t sub)})"
9546+ %cell "[{(show-itype-item hed.t sub)} {(show-itype-item tal.t sub)}]"
9547+ ==
9548+::
9549+++ show-itype-item
9550+ |= [t=itype sub=isub]
9551+ ^- tape
9552+ =. t (itype-walk t sub)
9553+ ?: ?=(%face -.t) "{(trip name.t)}={(show-itype-context body.t sub)}"
9554+ (show-itype-context t sub)
9555+::
9556+++ show-itype-context
9557+ |= [t=itype sub=isub]
9558+ ^- tape
9559+ =. t (itype-walk t sub)
9560+ ?: &(?=(%union -.t) ?=(~ label.t)) "({(show-itype t sub)})"
9561+ (show-itype t sub)
9562+::
9563+++ show-itype-cases
9564+ |= [cases=(list itype) sub=isub]
9565+ ^- tape
9566+ ?~ cases ""
9567+ ?~ t.cases (show-itype-context i.cases sub)
9568+ "{(show-itype-context i.cases sub)} {$(cases t.cases)}"
9569+::
9570+:: Include the type at a conflicting site where it can be printed.
9571+:: A lone unresolved variable or decimal variable keeps the neutral label.
9572+::
9573+++ itype-has-nvar
9574+ |= typ=itype
9575+ ^- ?
9576+ ?- -.typ
9577+ %nvar &
9578+ %rnvar &
9579+ %var |
9580+ %avar |
9581+ %rvar |
9582+ %atom |
9583+ %any-atom |
9584+ %flag |
9585+ %noun |
9586+ %empty |
9587+ %tag |
9588+ %const |
9589+ %union |((lien cases.typ |=(c=itype (itype-has-nvar c))) (lien args.typ |=(c=itype (itype-has-nvar c))))
9590+ %recursive |
9591+ %jrec |
9592+ %grec (lien args.typ |=(c=itype (itype-has-nvar c)))
9593+ %collection (lien args.typ |=(c=itype (itype-has-nvar c)))
9594+ %face $(typ body.typ)
9595+ %fn |($(typ sample.typ) $(typ product.typ))
9596+ %cell |($(typ hed.typ) $(typ tal.typ))
9597+ ==
9598+::
9599+++ site-type-note
9600+ |= [label=tape typ=itype sub=isub]
9601+ ^- tape
9602+ =/ normalized=itype (itype-normalize typ sub)
9603+ ?: |(?=(%var -.normalized) ?=(%avar -.normalized) ?=(%rvar -.normalized) (itype-has-nvar normalized) (itype-has-tag normalized) (itype-has-union normalized)) label
9604+ ?: (itype-has-hidden-recursive normalized) label
9605+ =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
9606+ ?: (gth (lent vars) 26) label
9607+ =/ printable=itype (canonical-itype normalized vars)
9608+ "{label} has type {(show-itype printable ~)}{(show-atom-constraint printable)}"
9609+::
9610+:: A capital in a written mold is generalized with its enclosing ++.
9611+:: Atom constraints may remain generic; until full rigidity checking
9612+:: is implemented, do not report a type if one became more specific.
9613+:: Distinct written capitals cannot be forced equal; use the same
9614+:: capital where a type must be shared (Decisions 2026-10-30).
9615+::
9616+++ cap-id-in
9617+ |= [n=@ud caps=icaps sub=isub]
9618+ ^- ?
9619+ ?~ caps |
9620+ =/ resolved=itype (itype-walk [%var id.i.caps] sub)
9621+ =/ ident=(unit @ud)
9622+ ?+ -.resolved ~
9623+ %var `id.resolved
9624+ %avar `id.resolved
9625+ %rvar `id.resolved
9626+ ==
9627+ ?~ ident $(caps t.caps)
9628+ ?: =(n u.ident) &
9629+ $(caps t.caps)
9630+::
9631+++ cap-with-id
9632+ |= [n=@ud caps=icaps sub=isub]
9633+ ^- (unit icap)
9634+ ?~ caps ~
9635+ =/ resolved=itype (itype-walk [%var id.i.caps] sub)
9636+ =/ ident=(unit @ud)
9637+ ?+ -.resolved ~
9638+ %var `id.resolved
9639+ %avar `id.resolved
9640+ %rvar `id.resolved
9641+ ==
9642+ ?~ ident $(caps t.caps)
9643+ ?: =(n u.ident) `i.caps
9644+ $(caps t.caps)
9645+::
9646+++ merged-capitals
9647+ |= [caps=icaps sub=isub]
9648+ ^- (unit [first=icap second=icap])
9649+ ?~ caps ~
9650+ =/ resolved=itype (itype-walk [%var id.i.caps] sub)
9651+ =/ ident=(unit @ud)
9652+ ?+ -.resolved ~
9653+ %var `id.resolved
9654+ %avar `id.resolved
9655+ %rvar `id.resolved
9656+ ==
9657+ ?~ ident $(caps t.caps)
9658+ =/ found=(unit icap) (cap-with-id u.ident t.caps sub)
9659+ ?^ found `[u.found i.caps]
9660+ $(caps t.caps)
9661+::
9662+++ constrained-capitals
9663+ |= [caps=icaps sub=isub]
9664+ ^- ?
9665+ ?~ caps |
9666+ =/ resolved=itype (itype-walk [%var id.i.caps] sub)
9667+ =/ ident=(unit @ud)
9668+ ?+ -.resolved ~
9669+ %var `id.resolved
9670+ %avar `id.resolved
9671+ %rvar `id.resolved
9672+ ==
9673+ ?~ ident &
9674+ ?: (cap-id-in u.ident t.caps sub) &
9675+ $(caps t.caps)
9676+::
9677+:: An atom variable may be generalized when an explicit capital, sample
9678+:: binder or instantiated constraint resolves to it. Decimal variables need
9679+:: defaulting and must not be generalized as arbitrary atom types.
9680+::
9681+++ atom-var-from-cap
9682+ |= [n=@ud caps=icaps sub=isub]
9683+ ^- ?
9684+ ?~ caps |
9685+ =/ resolved=itype (itype-walk [%var id.i.caps] sub)
9686+ ?: |(?=(%avar -.resolved) ?=(%rvar -.resolved))
9687+ ?: =(n +.resolved) &
9688+ $(caps t.caps)
9689+ $(caps t.caps)
9690+::
9691+++ has-atom-var
9692+ |= [n=@ud t=itype]
9693+ ^- ?
9694+ ?- -.t
9695+ %var |
9696+ %avar =(n id.t)
9697+ %rvar =(n id.t)
9698+ %nvar |
9699+ %rnvar |
9700+ %atom |
9701+ %any-atom |
9702+ %flag |
9703+ %noun |
9704+ %empty |
9705+ %tag |
9706+ %const |
9707+ %union |((lien cases.t |=(c=itype (has-atom-var n c))) (lien args.t |=(c=itype (has-atom-var n c))))
9708+ %recursive |
9709+ %jrec |
9710+ %grec (lien args.t |=(c=itype (has-atom-var n c)))
9711+ %collection (lien args.t |=(c=itype (has-atom-var n c)))
9712+ %face $(t body.t)
9713+ %fn |($(t sample.t) $(t product.t))
9714+ %cell |($(t hed.t) $(t tal.t))
9715+ ==
9716+::
9717+++ atom-var-from-binder
9718+ |= [n=@ud binders=(list @ud) sub=isub]
9719+ ^- ?
9720+ ?~ binders |
9721+ =/ resolved=itype (itype-normalize [%var i.binders] sub)
9722+ :: An instantiated atom variable is not itself a substitution, so
9723+ :: its origin still walks as an unbound variable of the same ID.
9724+ ?: ?=(%var -.resolved)
9725+ ?: =(n id.resolved) &
9726+ $(binders t.binders)
9727+ ?: (has-atom-var n resolved) &
9728+ $(binders t.binders)
9729+::
9730+++ unsupported-atom-vars
9731+ |= [t=itype caps=icaps binders=(list @ud) sub=isub]
9732+ ^- ?
9733+ =/ vars=(list @ud) (unique-type-vars (itype-vars t))
9734+ |-
9735+ ?~ vars |
9736+ ?: (itype-var-is-atom i.vars t)
9737+ ?. (has-atom-var i.vars t) &
9738+ ?. |((atom-var-from-cap i.vars caps sub) (atom-var-from-binder i.vars binders sub)) &
9739+ $(vars t.vars)
9740+ $(vars t.vars)
9741+::
9742+++ show-atom-constraint
9743+ |= t=itype
9744+ ^- tape
9745+ =/ vars=(list @ud) (unique-type-vars (itype-vars t))
9746+ =/ printed=? |
9747+ =/ out=tape ""
9748+ |-
9749+ ?~ vars out
9750+ ?: (itype-var-is-restricted i.vars t)
9751+ =/ sep=tape ?:(printed ", " " where ")
9752+ =/ clause=tape "{sep}{(show-itype [%rvar i.vars] ~)} is an atom other than ?"
9753+ $(vars t.vars, printed &, out (weld out clause))
9754+ ?: (itype-var-is-atom i.vars t)
9755+ =/ sep=tape ?:(printed ", " " where ")
9756+ =/ clause=tape "{sep}{(show-itype [%avar i.vars] ~)} is an atom"
9757+ $(vars t.vars, printed &, out (weld out clause))
9758+ $(vars t.vars)
9759+::
9760+:: Build the supported part of the value environment in dependency order.
9761+:: Each pass adds successful definitions. Forward references become
9762+:: available on a later pass; unsupported syntax does not enter the
9763+:: environment. Generalized definitions are closed, so a use instantiates
9764+:: its variables afresh.
9765+::
9766+++ global-value-names
9767+ |= ds=(list def)
9768+ ^- (list term)
9769+ ?~ ds ~
9770+ ?: ?=(%value -.i.ds)
9771+ [name.i.ds $(ds t.ds)]
9772+ $(ds t.ds)
9773+::
9774+++ unique-value-name
9775+ |= [n=term names=(list term)]
9776+ ^- ?
9777+ =/ hits=(list term) (skim names |=(x=term =(x n)))
9778+ ?~ hits |
9779+ ?~ t.hits &
9780+ |
9781+::
9782+:: A top-level gate may refer to itself through one monomorphic placeholder.
9783+:: Its declared sample is inferred first and preserves its field faces.
9784+:: Unify the completed body with that placeholder before generalization;
9785+:: reporting repeats the same check instead of instantiating the gate's
9786+:: generalized interface inside its own body. Mutual groups stay unsupported.
9787+::
9788+++ direct-self-call
9789+ |= [e=expr name=term]
9790+ ^- ?
9791+ ?: ?=(%group -.e) $(e inner.e)
9792+ ?: &(?=(%body -.e) ?=(~ defs.e)) $(e final.e)
9793+ ?. ?=(%call -.e) |
9794+ ?. ?=(%wing -.head.e) |
9795+ =(names.head.e ~[name])
9796+::
9797+++ branch-base-arm
9798+ |= [e=expr name=term]
9799+ ^- (unit expr)
9800+ ?: ?=(%group -.e) $(e inner.e)
9801+ ?: &(?=(%body -.e) ?=(~ defs.e)) $(e final.e)
9802+ ?. ?=(%branch -.e) ~
9803+ ?~ arms.e ~
9804+ ?~ t.arms.e ~
9805+ ?^ t.t.arms.e ~
9806+ =/ x=arm i.arms.e
9807+ =/ y=arm i.t.arms.e
9808+ ?. &(?=(%lit -.pat.x) ?=(%lit -.pat.y)) ~
9809+ ?. &(=(%loobean form.lit.pat.x) =(%loobean form.lit.pat.y)) ~
9810+ ?: =(val.lit.pat.x val.lit.pat.y) ~
9811+ =/ first=? (direct-self-call val.x name)
9812+ =/ second=? (direct-self-call val.y name)
9813+ ?: =(first second) ~
9814+ `?:(first val.y val.x)
9815+::
9816+:: Infer the base arm independently, with the self binding removed. Only
9817+:: a closed type whose constraints resolved can seed the recursive result.
9818+:: The regular body inference then checks both arms with shared state.
9819+::
9820+++ recursive-branch-seed
9821+ |= [d=def env=ienv state=istate]
9822+ ^- (unit itype)
9823+ ?. ?=(%value -.d) ~
9824+ ?. |(?=(%gate -.val.d) ?=(%gate-wide -.val.d)) ~
9825+ =/ gate=expr val.d
9826+ =/ body=expr
9827+ ?- -.gate
9828+ %gate body.gate
9829+ %gate-wide body.gate
9830+ * !!
9831+ ==
9832+ =/ base=(unit expr) (branch-base-arm body name.d)
9833+ ?~ base ~
9834+ =/ outer=ienv (skim env |=(entry=[name=term scheme=ischeme] !=(name.entry name.d)))
9835+ =/ sam=isample-result
9836+ ?- -.gate
9837+ %gate (infer-sample sample.gate outer state)
9838+ %gate-wide (infer-sample sample.gate outer state)
9839+ * !!
9840+ ==
9841+ ?: ?=(%| -.sam) ~
9842+ =/ inferred=iresult (infer-fragment u.base env.p.sam state.p.sam)
9843+ ?: ?=(%| -.inferred) ~
9844+ ?: (pending-tags tags.state.p.inferred sub.state.p.inferred) ~
9845+ ?: (constrained-capitals caps.state.p.inferred sub.state.p.inferred) ~
9846+ =/ typ=itype (itype-normalize typ.p.inferred sub.state.p.inferred)
9847+ ?: ?=(^ (itype-vars typ)) ~
9848+ ?: (itype-has-tag typ) ~
9849+ `typ
9850+::
9851+++ infer-recursive-gate
9852+ |= [d=def env=ienv state=istate]
9853+ ^- iresult
9854+ ?^ defer.state [%| ["deferred recursive inference is unsupported" ~]]
9855+ =. gate-defs.state ~
9856+ ?. ?=(%value -.d) [%| ["recursive definition is not a gate" ~]]
9857+ ?. |(?=(%gate -.val.d) ?=(%gate-wide -.val.d))
9858+ [%| ["recursive definition is not a gate" ~]]
9859+ =/ result=(unit itype) (recursive-branch-seed d env state)
9860+ =/ gate=expr val.d
9861+ =/ sam=isample-result
9862+ ?- -.gate
9863+ %gate (infer-sample sample.gate env state)
9864+ %gate-wide (infer-sample sample.gate env state)
9865+ * !!
9866+ ==
9867+ ?: ?=(%| -.sam)
9868+ =/ diag=(unit idiag)
9869+ ?- -.gate
9870+ %gate (sample-import-invalid sample.gate env state)
9871+ %gate-wide (sample-import-invalid sample.gate env state)
9872+ * ~
9873+ ==
9874+ ?: &(=(p.sam "sample mold is not supported by partial inference") ?=(^ diag)) [%| u.diag]
9875+ [%| [p.sam ~]]
9876+ =/ id=@ud next.state.p.sam
9877+ =/ product=itype ?~(result [%var id] u.result)
9878+ =/ st=istate state.p.sam(next +(id))
9879+ =/ seed=itype [%fn typ.p.sam product]
9880+ =/ seeded=ienv [[name.d [seed ~]] env.p.sam]
9881+ =/ body=expr
9882+ ?- -.gate
9883+ %gate body.gate
9884+ %gate-wide body.gate
9885+ * !!
9886+ ==
9887+ =/ out=iresult (infer-fragment body seeded st)
9888+ ?: ?=(%| -.out) out
9889+ =/ uni=(unit isub) (itype-unify product typ.p.out sub.state.p.out)
9890+ ?~ uni [%| ["recursive gate constraint is not supported by partial inference" ~]]
9891+ [%& [%fn typ.p.sam typ.p.out] state.p.out(sub u.uni)]
9892+::
9893+++ dependency-root
9894+ |= names=(list term)
9895+ ^- (list term)
9896+ ?~ names ~
9897+ ~[(rear names)]
9898+::
9899+++ dependency-exprs
9900+ |= xs=(list expr)
9901+ ^- (list term)
9902+ ?~ xs ~
9903+ =/ first=(list term) (dependency-expr i.xs)
9904+ (weld first $(xs t.xs))
9905+::
9906+++ dependency-pieces
9907+ |= xs=(list piece)
9908+ ^- (list term)
9909+ ?~ xs ~
9910+ =/ first=(list term)
9911+ ?- -.i.xs
9912+ %expr (dependency-expr p.i.xs)
9913+ %text ~
9914+ ==
9915+ (weld first $(xs t.xs))
9916+::
9917+++ dependency-qsegs
9918+ |= xs=(list qseg)
9919+ ^- (list term)
9920+ ?~ xs ~
9921+ =/ first=(list term)
9922+ ?- -.i.xs
9923+ %expr (dependency-expr p.i.xs)
9924+ %knot ~
9925+ ==
9926+ (weld first $(xs t.xs))
9927+::
9928+++ dependency-items
9929+ |= xs=(list item)
9930+ ^- (list term)
9931+ ?~ xs ~
9932+ =/ first=(list term) (dependency-expr val.i.xs)
9933+ (weld first $(xs t.xs))
9934+::
9935+++ dependency-edits
9936+ |= xs=(list edit)
9937+ ^- (list term)
9938+ ?~ xs ~
9939+ =/ first=(list term) (dependency-expr val.i.xs)
9940+ (weld first $(xs t.xs))
9941+::
9942+++ dependency-arms
9943+ |= xs=(list arm)
9944+ ^- (list term)
9945+ ?~ xs ~
9946+ =/ first=(list term) (dependency-expr val.i.xs)
9947+ (weld first $(xs t.xs))
9948+::
9949+++ dependency-defs
9950+ |= xs=(list def)
9951+ ^- (list term)
9952+ ?~ xs ~
9953+ =/ first=(list term)
9954+ ?: ?=(%value -.i.xs) (dependency-expr val.i.xs)
9955+ ~
9956+ (weld first $(xs t.xs))
9957+::
9958+++ dependency-expr
9959+ |= e=expr
9960+ ^- (list term)
9961+ ?- -.e
9962+ %str (dependency-pieces pieces.e)
9963+ %qath (dependency-qsegs segs.e)
9964+ %wing (dependency-root names.e)
9965+ %change
9966+ =/ first=(list term) (dependency-root target.e)
9967+ =/ last=(list term) (dependency-edits edits.e)
9968+ (weld first last)
9969+ %pair (dependency-expr val.e)
9970+ %unit (dependency-expr val.e)
9971+ %group (dependency-expr inner.e)
9972+ %list (dependency-exprs items.e)
9973+ %tuple (dependency-items items.e)
9974+ %gate (dependency-expr body.e)
9975+ %gate-wide (dependency-expr body.e)
9976+ %call
9977+ =/ first=(list term) (dependency-expr head.e)
9978+ =/ last=(list term) (dependency-exprs args.e)
9979+ (weld first last)
9980+ %cast (dependency-expr val.e)
9981+ %trace
9982+ =/ first=(list term) (dependency-expr val.e)
9983+ =/ last=(list term) (dependency-expr then.e)
9984+ (weld first last)
9985+ %branch
9986+ =/ first=(list term) (dependency-expr subject.e)
9987+ =/ last=(list term) (dependency-arms arms.e)
9988+ (weld first last)
9989+ %body
9990+ =/ first=(list term) (dependency-defs defs.e)
9991+ =/ last=(list term) (dependency-expr final.e)
9992+ (weld first last)
9993+ * ~
9994+ ==
9995+::
9996+:: Infer a cyclic component with one monomorphic seed per gate. All members
9997+:: must succeed before any scheme is available; pending constraints and
9998+:: unresolved branch joins remain partial.
9999++$ igate-entry [name=term typ=itype body=expr env=ienv caps=icaps]
10000++$ igate-seeds (each [entries=(list igate-entry) state=istate] idiag)
10001+++ seed-gate-group
10002+ |= [ds=(list def) env=ienv state=istate]
10003+ ^- igate-seeds
10004+ ?~ ds [%& [~ state]]
10005+ =/ d=def i.ds
10006+ ?. ?=(%value -.d) [%| ["recursive group contains a non-gate" ~]]
10007+ =/ gate=expr val.d
10008+ ?. |(?=(%gate -.gate) ?=(%gate-wide -.gate))
10009+ [%| ["recursive group contains a non-gate" ~]]
10010+ =/ initial=istate (reserve-def-caps gate state)
10011+ =/ sam=isample-result
10012+ ?- -.gate
10013+ %gate (infer-sample sample.gate env initial)
10014+ %gate-wide (infer-sample sample.gate env initial)
10015+ * !!
10016+ ==
10017+ ?: ?=(%| -.sam) [%| [p.sam ~]]
10018+ =/ body=expr
10019+ ?- -.gate
10020+ %gate body.gate
10021+ %gate-wide body.gate
10022+ * !!
10023+ ==
10024+ =/ seed=itype [%fn typ.p.sam [%var next.state.p.sam]]
10025+ =/ entry=igate-entry [name.d seed body env.p.sam caps.state.p.sam]
10026+ =/ after=istate state.p.sam(next +(next.state.p.sam), caps caps.state)
10027+ =/ rest=igate-seeds $(ds t.ds, state after)
10028+ ?: ?=(%| -.rest) rest
10029+ [%& [[entry entries.p.rest] state.p.rest]]
10030+::
10031+++ group-seed-env
10032+ |= [entries=(list igate-entry) env=ienv]
10033+ ^- ienv
10034+ ?~ entries env
10035+ [[name.i.entries [typ.i.entries ~]] $(entries t.entries)]
10036+::
10037+++ infer-gate-group-bodies
10038+ |= [entries=(list igate-entry) seeds=ienv state=istate]
10039+ ^- igate-seeds
10040+ ?~ entries [%& [~ state]]
10041+ =/ entry=igate-entry i.entries
10042+ ?> ?=(%fn -.typ.entry)
10043+ =/ scope=ienv (weld seeds env.entry)
10044+ =/ out=iresult (infer-fragment body.entry scope state(caps caps.entry))
10045+ ?: ?=(%| -.out) out
10046+ =/ uni=(unit isub) (itype-unify product.typ.entry typ.p.out sub.state.p.out)
10047+ ?~ uni [%| ["recursive group constraint is not supported by partial inference" ~]]
10048+ =. caps.entry caps.state.p.out
10049+ =/ after=istate state.p.out(sub u.uni, caps caps.state)
10050+ =/ rest=igate-seeds $(entries t.entries, state after)
10051+ ?: ?=(%| -.rest) rest
10052+ [%& [[entry entries.p.rest] state.p.rest]]
10053+::
10054+++ group-schemes
10055+ |= [entries=(list igate-entry) env=ienv outer=istate state=istate]
10056+ ^- (each ienv idiag)
10057+ ?~ entries [%& ~]
10058+ =/ entry=igate-entry i.entries
10059+ =/ merged=(unit [first=icap second=icap]) (merged-capitals caps.entry sub.state)
10060+ ?^ merged
10061+ [%| ["distinct type variables must not be forced equal" ~[[at.first.u.merged "first type variable"] [at.second.u.merged "second type variable"]]]]
10062+ ?: (constrained-capitals caps.entry sub.state)
10063+ [%| ["explicit capital constraints are not supported by partial inference" ~]]
10064+ =/ typ=itype (itype-normalize typ.entry sub.state)
10065+ ?: (itype-has-nvar typ) [%| ["recursive group needs unsupported inference" ~]]
10066+ ?: |((itype-has-tag typ) (itype-has-hidden-generic typ) (itype-has-hidden-recursive typ) (unsupported-atom-vars typ caps.entry binders.state sub.state))
10067+ [%| ["recursive group needs unsupported inference" ~]]
10068+ =/ free=(list @ud) (weld (free-env-vars env sub.state) (free-cap-vars caps.outer sub.state))
10069+ =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
10070+ =. vars (skim vars |=(n=@ud !(lien free |=(f=@ud =(f n)))))
10071+ ?: (gth (lent vars) 26) [%| ["recursive group needs too many type variables" ~]]
10072+ =/ rest=(each ienv idiag) $(entries t.entries)
10073+ ?: ?=(%| -.rest) rest
10074+ [%& [[name.entry [typ vars]] p.rest]]
10075+::
10076+++ infer-gate-group
10077+ |= [ds=(list def) env=ienv state=istate]
10078+ ^- ilocal-result
10079+ ?^ defer.state [%| ["deferred recursive inference is unsupported" ~]]
10080+ =/ names=(list term) (global-value-names ds)
10081+ ?. (levy names |=(n=term (unique-value-name n names)))
10082+ [%| ["recursive group contains duplicate names" ~]]
10083+ ?: (lien names |=(n=term ?=(^ (ienv-lookup n env))))
10084+ [%| ["recursive group shadows a name" ~]]
10085+ =/ scoped=istate state(globals (weld names globals.state), gate-defs ~)
10086+ =/ seeded=igate-seeds (seed-gate-group ds env scoped)
10087+ ?: ?=(%| -.seeded) seeded
10088+ =/ seeds=ienv (group-seed-env entries.p.seeded ~)
10089+ =/ body=igate-seeds (infer-gate-group-bodies entries.p.seeded seeds state.p.seeded)
10090+ ?: ?=(%| -.body) body
10091+ :: Per-member ownership through mutual recursion is not implemented.
10092+ ?: !=(projections.state.p.body projections.state)
10093+ [%| ["record projection in recursive groups needs unsupported inference" ~]]
10094+ ?: !=(holes.state.p.body holes.state)
10095+ [%| ["holes in recursive groups need unsupported inference" ~]]
10096+ ?: (pending-tags tags.state.p.body sub.state.p.body)
10097+ [%| ["recursive group has unresolved literal constraints" ~]]
10098+ =/ schemes=(each ienv idiag) (group-schemes entries.p.body env state state.p.body)
10099+ ?: ?=(%| -.schemes) schemes
10100+ [%& [(weld p.schemes env) state.p.body(globals globals.state)]]
10101+::
10102+++ width-finalize
10103+ |= [ps=(list iwprojection) sub=isub visible=(list @ud)]
10104+ ^- (unit (list iwprojection))
10105+ ?~ ps `~
10106+ ?: (lien t.ps |=(p=iwprojection =(at.p at.i.ps))) ~
10107+ =/ src=itype (default-decimals (itype-normalize source.i.ps sub))
10108+ =/ dst=itype (default-decimals (itype-normalize target.i.ps sub))
10109+ ?: |((itype-has-nvar src) (itype-has-nvar dst) (itype-has-tag src) (itype-has-tag dst)) ~
10110+ =/ vars=(list @ud) (weld (itype-vars src) (itype-vars dst))
10111+ ?. (levy vars |=(n=@ud (lien visible |=(v=@ud =(n v))))) ~
10112+ =/ rest=(unit (list iwprojection)) $(ps t.ps)
10113+ ?~ rest ~
10114+ =/ entry=iwprojection i.ps
10115+ =. entry entry(source src, target dst)
10116+ `[entry u.rest]
10117+::
10118+++ add-supported-defs
10119+ |= [ds=(list def) all-defs=(list def) checked=(map term def) heads=(unit igate-prelude-evidence) env=ienv molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) at=path prelude=(unit ifile) artifacts=(list iwidth-definition)]
10120+ ^- [env=ienv artifacts=(list iwidth-definition)]
10121+ (add-supported-defs-core ds all-defs checked heads env molds globals externals surs mark-externals marks jimports reserved-molds at prelude artifacts ~)
10122+::
10123+
10124++$ iresolved [env=ienv grouped=(list term) artifacts=(list iwidth-definition)]
10125++$ iadj (map term (list term))
10126++$ ivisited (map term ?)
10127++$ iwork (list [name=term done=?])
10128++$ iwresult [seen=ivisited order=(list term)]
10129++$ icresult [seen=ivisited component=(list term)]
10130++$ icomponents (list (list term))
10131+++ graph-nameset
10132+ |= [names=(list term) seen=ivisited]
10133+ ^- ivisited
10134+ ?~ names seen
10135+ $(names t.names, seen (~(put by seen) i.names &))
10136+::
10137+++ graph-edges
10138+ |= [name=term graph=iadj]
10139+ ^- (list term)
10140+ =/ found=(unit (list term)) (~(get by graph) name)
10141+ ?~ found ~
10142+ u.found
10143+::
10144+++ graph-make-forward
10145+ |= [ds=(list def) names=ivisited graph=iadj]
10146+ ^- iadj
10147+ ?~ ds graph
10148+ ?. ?=(%value -.i.ds) $(ds t.ds)
10149+ =/ deps=(list term) (dependency-expr val.i.ds)
10150+ =. deps (skim deps |=(n=term ?=(^ (~(get by names) n))))
10151+ $(ds t.ds, graph (~(put by graph) name.i.ds deps))
10152+::
10153+++ graph-add-reverse
10154+ |= [name=term edges=(list term) reverse=iadj]
10155+ ^- iadj
10156+ ?~ edges reverse
10157+ =/ prior=(list term) (graph-edges i.edges reverse)
10158+ $(edges t.edges, reverse (~(put by reverse) i.edges [name prior]))
10159+::
10160+++ graph-reverse
10161+ |= [names=(list term) graph=iadj reverse=iadj]
10162+ ^- iadj
10163+ ?~ names reverse
10164+ =. reverse (graph-add-reverse i.names (graph-edges i.names graph) reverse)
10165+ $(names t.names)
10166+::
10167+++ graph-order
10168+ |= [todo=iwork seen=ivisited order=(list term) graph=iadj]
10169+ ^- iwresult
10170+ ?~ todo [seen order]
10171+ =/ event=[name=term done=?] i.todo
10172+ ?: done.event $(todo t.todo, order [name.event order])
10173+ ?: ?=(^ (~(get by seen) name.event)) $(todo t.todo)
10174+ =. seen (~(put by seen) name.event &)
10175+ =/ children=iwork (turn (graph-edges name.event graph) |=(n=term [n |]))
10176+ $(todo (weld children [[name.event &] t.todo]))
10177+::
10178+++ graph-collect
10179+ |= [todo=(list term) seen=ivisited component=(list term) graph=iadj]
10180+ ^- icresult
10181+ ?~ todo [seen component]
10182+ ?: ?=(^ (~(get by seen) i.todo)) $(todo t.todo)
10183+ =. seen (~(put by seen) i.todo &)
10184+ $(todo (weld (graph-edges i.todo graph) t.todo), component [i.todo component])
10185+::
10186+++ graph-collect-all
10187+ |= [order=(list term) seen=ivisited graph=iadj comps=icomponents]
10188+ ^- icomponents
10189+ ?~ order comps
10190+ ?: ?=(^ (~(get by seen) i.order)) $(order t.order)
10191+ =/ found=icresult (graph-collect ~[i.order] seen ~ graph)
10192+ $(order t.order, seen seen.found, comps [component.found comps])
10193+::
10194+:: Two depth-first passes find components before group inference. Maps
10195+:: preserve the graph identity; duplicate global names fail closed.
10196+++ graph-components
10197+ |= [ds=(list def) names=(list term)]
10198+ ^- icomponents
10199+ =/ nameset=ivisited ~
10200+ =/ pending=(list term) names
10201+ |-
10202+ ?^ pending
10203+ ?: ?=(^ (~(get by nameset) i.pending)) ~
10204+ $(pending t.pending, nameset (~(put by nameset) i.pending &))
10205+ =/ graph=iadj (graph-make-forward ds nameset ~)
10206+ =/ reverse=iadj (graph-reverse names graph ~)
10207+ =/ order=iwresult (graph-order (turn names |=(n=term [n |])) ~ ~ graph)
10208+ (graph-collect-all order.order ~ reverse ~)
10209+::
10210+++ graph-cycle
10211+ |= [component=(list term) graph=iadj]
10212+ ^- ?
10213+ ?~ component |
10214+ ?^ t.component &
10215+ (lien (graph-edges i.component graph) |=(x=term =(x i.component)))
10216+::
10217+++ add-groups
10218+ |= [ds=(list def) components=icomponents graph=iadj env=ienv grouped=(list term) artifacts=(list iwidth-definition) state=istate]
10219+ ^- iresolved
10220+ ?~ components [env grouped artifacts]
10221+ =/ component=(list term) i.components
10222+ ?. (graph-cycle component graph) $(components t.components)
10223+ ?: (lien component |=(n=term ?=(^ (ienv-lookup n env)))) $(components t.components)
10224+ =/ members=(list def)
10225+ %+ skim ds
10226+ |= d=def
10227+ &(?=(%value -.d) (lien component |=(n=term =(n name.d))))
10228+ ?. =((lent members) (lent component)) $(components t.components)
10229+ ?. (levy component |=(n=term (unique-value-name n globals.state))) $(components t.components)
10230+ =/ result=ilocal-result (infer-gate-group members env state)
10231+ ?: ?=(%| -.result) $(components t.components)
10232+ $(components t.components, env env.p.result, grouped (weld component grouped))
10233+::
10234+++ resolve-groups
10235+ |= [ds=(list def) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) at=path prelude=(unit ifile)]
10236+ ^- iresolved
10237+ (resolve-groups-core ds molds globals externals surs mark-externals marks jimports reserved-molds at prelude ~)
10238+::
10239+
10240++$ iadded-definition
10241+ [env=ienv checked=(map term def) artifacts=(list iwidth-definition)]
10242+++ add-supported-result
10243+ |= [d=def result=iresult initial=istate env=ienv checked=(map term def) artifacts=(list iwidth-definition)]
10244+ ^- (unit iadded-definition)
10245+ ?> ?=(%value -.d)
10246+ ?: ?=(%| -.result) ~
10247+ =. state.p.result (promote-restricted-numbers state.p.result env)
10248+ =. state.p.result (default-hole-numbers holes.state.p.result holes.initial state.p.result env !(itype-has-gate (itype-normalize typ.p.result sub.state.p.result)))
10249+ ?^ (unresolved-hole holes.state.p.result holes.initial state.p.result) ~
10250+ ?: (constrained-capitals caps.state.p.result sub.state.p.result) ~
10251+ =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
10252+ ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ)) ~
10253+ ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result) ~
10254+ =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
10255+ ?: (gth (lent vars) 26) ~
10256+ =/ finalized=(unit (list iwprojection))
10257+ (width-finalize projections.state.p.result sub.state.p.result vars)
10258+ ?~ finalized ~
10259+ =? artifacts ?=(^ u.finalized)
10260+ [[name.d val.d typ sub.state.p.result (flop u.finalized)] artifacts]
10261+ =? checked |(?=(%gate -.val.d) ?=(%gate-wide -.val.d)) (~(put by checked) name.d d)
10262+ `[[[name.d [typ vars]] env] checked artifacts]
10263+++ add-supported-defs-core
10264+ |= [ds=(list def) all-defs=(list def) checked=(map term def) heads=(unit igate-prelude-evidence) env=ienv molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) at=path prelude=(unit ifile) artifacts=(list iwidth-definition) index=(unit [at=path source=@t prelude=ifile shapes=(map term shape)])]
10265+ ^- [env=ienv artifacts=(list iwidth-definition)]
10266+ ?~ ds [env artifacts]
10267+ =/ d=def i.ds
10268+ ?: ?=(%mold -.d) $(ds t.ds)
10269+ ?. (unique-value-name name.d globals) $(ds t.ds)
10270+ ?^ (ienv-lookup name.d env) $(ds t.ds)
10271+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
10272+ =/ initial=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ | at top prelude ~ 256 ~ ~ ~ ~ ~ ~]
10273+ =. grec-index.initial index
10274+ =. gate-defs.initial checked
10275+ =. head-evidence.initial heads
10276+ =. initial (reserve-def-caps val.d initial)
10277+ =/ result=iresult (infer-fragment val.d env initial)
10278+ =? result ?=(%| -.result) (infer-recursive-gate d env initial)
10279+ =/ added=(unit iadded-definition)
10280+ (add-supported-result d result initial env checked artifacts)
10281+ ?~ added $(ds t.ds)
10282+ $(ds t.ds, env env.u.added, checked checked.u.added, artifacts artifacts.u.added)
10283+::
10284+++ resolve-groups-core
10285+ |= [ds=(list def) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) at=path prelude=(unit ifile) index=(unit [at=path source=@t prelude=ifile shapes=(map term shape)])]
10286+ ^- iresolved
10287+ =/ env=ienv ~
10288+ =/ grouped=(list term) ~
10289+ =/ artifacts=(list iwidth-definition) ~
10290+ =/ names=(list term) (global-value-names ds)
10291+ =/ nameset=ivisited (graph-nameset names ~)
10292+ =/ graph=iadj (graph-make-forward ds nameset ~)
10293+ =/ components=icomponents (graph-components ds names)
10294+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
10295+ =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude)
10296+ |-
10297+ =/ next=[env=ienv artifacts=(list iwidth-definition)]
10298+ (add-supported-defs-core ds ds (direct-checked-gates ds env) heads env molds globals externals surs mark-externals marks jimports reserved-molds at prelude artifacts index)
10299+ =/ initial=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ | at top prelude ~ 256 ~ ~ ~ ~ ~ ~]
10300+ =. grec-index.initial index
10301+ =/ out=iresolved (add-groups ds components graph env.next grouped artifacts.next initial)
10302+ ?: =(env env.out) out
10303+ $(env env.out, grouped grouped.out, artifacts artifacts.out)
10304+::
10305+++ resolve-supported-defs
10306+ |= [ds=(list def) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) at=path prelude=(unit ifile)]
10307+ ^- ienv
10308+ env:(resolve-groups ds molds globals externals surs mark-externals marks jimports reserved-molds at prelude)
10309+::
10310+:: A diagnostic-only proof for a narrow syntactic value cycle. Every
10311+:: edge is an unqualified wing in a supported expression, and samples
10312+:: may not shadow global bindings. Unknown forms yield no conclusion.
10313++$ icyclesite [name=term at=span]
10314++$ icycle [name=term first=span next=span]
10315+++ cycle-sites-list
10316+ |= [xs=(list expr) globals=(list term) locals=(list term)]
10317+ ^- (unit (list icyclesite))
10318+ ?~ xs `~
10319+ =/ first=(unit (list icyclesite)) (cycle-sites i.xs globals locals)
10320+ ?~ first ~
10321+ =/ tail=(unit (list icyclesite)) $(xs t.xs)
10322+ ?~ tail ~
10323+ `(weld u.first u.tail)
10324+::
10325+++ cycle-sample-name
10326+ |= [sam=sample globals=(list term) locals=(list term)]
10327+ ^- (unit (unit term))
10328+ ?- -.sam
10329+ %bind
10330+ ?: (lien (weld globals locals) |=(n=term =(n name.sam))) ~
10331+ ``name.sam
10332+ %face
10333+ ?: (lien (weld globals locals) |=(n=term =(n name.sam))) ~
10334+ ``name.sam
10335+ %bare `~
10336+ * ~
10337+ ==
10338+::
10339+++ cycle-sites
10340+ |= [e=expr globals=(list term) locals=(list term)]
10341+ ^- (unit (list icyclesite))
10342+ ?- -.e
10343+ %wing
10344+ ?. ?=([@ ~] names.e) ~
10345+ `~[[i.names.e at.e]]
10346+ %lit `~
10347+ %str
10348+ ?: (lien pieces.e |=(p=piece ?=(%expr -.p))) ~
10349+ `~
10350+ %group $(e inner.e)
10351+ %body ?~(defs.e $(e final.e) ~)
10352+ %cast $(e val.e)
10353+ %gate
10354+ =/ binder=(unit (unit term)) (cycle-sample-name sample.e globals locals)
10355+ ?~ binder ~
10356+ =/ nested=(list term) ?~(u.binder locals [u.u.binder locals])
10357+ $(e body.e, locals nested)
10358+ %gate-wide
10359+ =/ binder=(unit (unit term)) (cycle-sample-name sample.e globals locals)
10360+ ?~ binder ~
10361+ =/ nested=(list term) ?~(u.binder locals [u.u.binder locals])
10362+ $(e body.e, locals nested)
10363+ %call
10364+ =/ first=(unit (list icyclesite)) $(e head.e)
10365+ ?~ first ~
10366+ =/ tail=(unit (list icyclesite)) (cycle-sites-list args.e globals locals)
10367+ ?~ tail ~
10368+ `(weld u.first u.tail)
10369+ * ~
10370+ ==
10371+::
10372+++ cycle-definitely-atom
10373+ |= e=expr
10374+ ^- ?
10375+ ?: ?=(%group -.e) $(e inner.e)
10376+ ?: &(?=(%body -.e) ?=(~ defs.e)) $(e final.e)
10377+ ?. ?=(%cast -.e) |
10378+ |(?=(%aura -.shape.e) ?=(%flag -.shape.e))
10379+::
10380+++ cycle-proof-group
10381+ |= [members=(list def) globals=(list term)]
10382+ ^- ?
10383+ ?~ members &
10384+ ?. ?=(%value -.i.members) |
10385+ ?. (unique-value-name name.i.members globals) |
10386+ ?. ?=(^ (cycle-sites val.i.members globals ~)) |
10387+ $(members t.members)
10388+::
10389+++ cycle-find-site
10390+ |= [sites=(list icyclesite) component=(list term)]
10391+ ^- (unit span)
10392+ ?~ sites ~
10393+ ?: (lien component |=(n=term =(n name.i.sites))) `at.i.sites
10394+ $(sites t.sites)
10395+::
10396+++ cycle-group-errors
10397+ |= [members=(list def) component=(list term) globals=(list term)]
10398+ ^- (list icycle)
10399+ ?~ members ~
10400+ =/ d=def i.members
10401+ ?> ?=(%value -.d)
10402+ =/ tail=(list icycle) $(members t.members)
10403+ ?. (cycle-definitely-atom val.d) tail
10404+ =/ sites=(unit (list icyclesite)) (cycle-sites val.d globals ~)
10405+ ?~ sites tail
10406+ =/ found=(unit span) (cycle-find-site u.sites component)
10407+ ?~ found tail
10408+ [[name.d at.d u.found] tail]
10409+::
10410+++ definite-value-cycles
10411+ |= [ds=(list def) globals=(list term)]
10412+ ^- (list icycle)
10413+ =/ names=(list term) (global-value-names ds)
10414+ =/ graph=iadj (graph-make-forward ds (graph-nameset names ~) ~)
10415+ =/ components=icomponents (graph-components ds names)
10416+ =/ out=(list icycle) ~
10417+ |-
10418+ ?~ components out
10419+ =/ component=(list term) i.components
10420+ ?. (graph-cycle component graph) $(components t.components)
10421+ =/ members=(list def)
10422+ (skim ds |=(d=def &(?=(%value -.d) (lien component |=(n=term =(n name.d))))))
10423+ ?. =((lent members) (lent component)) $(components t.components)
10424+ ?. (cycle-proof-group members globals) $(components t.components)
10425+ $(components t.components, out (weld (cycle-group-errors members component globals) out))
10426+::
10427++| %union-analysis
10428+::
10429+:: A conservative projection of written molds onto noun shapes. The
10430+:: result %unknown never establishes either overlap or disjointness.
10431+:: Gates, applications, imports and recursive references stay unknown;
10432+:: another position in a cell may nevertheless prove two cases apart.
10433+::
10434++$ upat
10435+ $~ [%unknown ~]
10436+ $% [%unknown ~]
10437+ [%all ~]
10438+ [%empty ~]
10439+ [%atom val=(unit @)]
10440+ [%flag ~]
10441+ [%cell hed=upat tal=upat]
10442+ [%or alts=(list upat)]
10443+ ==
10444++$ urelation ?(%disjoint %overlap %unknown)
10445++$ upair [first=span second=span relation=urelation]
10446+::
10447+++ project-union-mold
10448+ |= [sh=shape molds=imolds seen=(list term)]
10449+ ^- upat
10450+ ?- -.sh
10451+ %aura [%atom ~]
10452+ %noun [%all ~]
10453+ %tvar [%all ~]
10454+ %void [%empty ~]
10455+ :: ? is its two atoms, 0 and 1 (Decisions 2026-10-30).
10456+ %flag [%flag ~]
10457+ %const [%atom `val.lit.sh]
10458+ %cell (project-union-fields fields.sh molds seen)
10459+ %union [%or (turn cases.sh |=(x=shape (project-union-mold x molds seen)))]
10460+ %ref
10461+ ?~ names.sh [%unknown ~]
10462+ ?^ t.names.sh [%unknown ~]
10463+ =/ n=term i.names.sh
10464+ ?: (lien seen |=(x=term =(x n))) [%unknown ~]
10465+ =/ found=(unit shape) (find-simple-mold n molds)
10466+ ?~ found [%unknown ~]
10467+ $(sh u.found, seen [n seen])
10468+ * [%unknown ~]
10469+ ==
10470+::
10471+++ project-union-fields
10472+ |= [fields=(list field) molds=imolds seen=(list term)]
10473+ ^- upat
10474+ ?~ fields [%unknown ~]
10475+ =/ head=upat
10476+ ?- -.i.fields
10477+ %bare (project-union-mold shape.i.fields molds seen)
10478+ %face (project-union-mold shape.i.fields molds seen)
10479+ %pun (project-union-mold [%ref at.i.fields ~[name.i.fields]] molds seen)
10480+ ==
10481+ ?~ t.fields head
10482+ [%cell head $(fields t.fields)]
10483+::
10484+++ union-inhabited
10485+ |= p=upat
10486+ ^- urelation
10487+ ?- -.p
10488+ %unknown %unknown
10489+ %empty %disjoint
10490+ %all %overlap
10491+ %atom %overlap
10492+ %flag %overlap
10493+ %cell
10494+ =/ a=urelation $(p hed.p)
10495+ =/ b=urelation $(p tal.p)
10496+ ?: |(=(%disjoint a) =(%disjoint b)) %disjoint
10497+ ?: |(=(%unknown a) =(%unknown b)) %unknown
10498+ %overlap
10499+ %or
10500+ =/ alts=(list upat) alts.p
10501+ =/ result=urelation %disjoint
10502+ |-
10503+ ?~ alts result
10504+ =/ r=urelation (union-inhabited i.alts)
10505+ ?: =(%overlap r) %overlap
10506+ $(alts t.alts, result ?:(=(%unknown r) %unknown result))
10507+ ==
10508+::
10509+++ union-relate-alts
10510+ |= [alts=(list upat) b=upat]
10511+ ^- urelation
10512+ =/ result=urelation %disjoint
10513+ |-
10514+ ?~ alts result
10515+ =/ r=urelation (union-relate i.alts b)
10516+ ?: =(%overlap r) %overlap
10517+ $(alts t.alts, result ?:(=(%unknown r) %unknown result))
10518+::
10519+++ union-relate
10520+ |= [a=upat b=upat]
10521+ ^- urelation
10522+ ?: |(?=(%empty -.a) ?=(%empty -.b)) %disjoint
10523+ ?: ?=(%or -.a) (union-relate-alts alts.a b)
10524+ ?: ?=(%or -.b) (union-relate-alts alts.b a)
10525+ ?: ?=(%all -.a) (union-inhabited b)
10526+ ?: ?=(%all -.b) (union-inhabited a)
10527+ ?: |(?=(%unknown -.a) ?=(%unknown -.b)) %unknown
10528+ ?: |(&(?=(%cell -.a) |(?=(%atom -.b) ?=(%flag -.b))) &(?=(%cell -.b) |(?=(%atom -.a) ?=(%flag -.a))))
10529+ %disjoint
10530+ ?: &(?=(%flag -.a) ?=(%flag -.b)) %overlap
10531+ ?: &(?=(%flag -.a) ?=(%atom -.b))
10532+ ?~ val.b %overlap
10533+ ?:(|(=(0 u.val.b) =(1 u.val.b)) %overlap %disjoint)
10534+ ?: &(?=(%atom -.a) ?=(%flag -.b))
10535+ ?~ val.a %overlap
10536+ ?:(|(=(0 u.val.a) =(1 u.val.a)) %overlap %disjoint)
10537+ ?: &(?=(%atom -.a) ?=(%atom -.b))
10538+ ?~ val.a %overlap
10539+ ?~ val.b %overlap
10540+ ?:(=(u.val.a u.val.b) %overlap %disjoint)
10541+ ?: &(?=(%cell -.a) ?=(%cell -.b))
10542+ =/ x=urelation $(a hed.a, b hed.b)
10543+ =/ y=urelation $(a tal.a, b tal.b)
10544+ ?: |(=(%disjoint x) =(%disjoint y)) %disjoint
10545+ ?: |(=(%unknown x) =(%unknown y)) %unknown
10546+ %overlap
10547+ %unknown
10548+::
10549+:: A source-only fallback for literal-tagged cells and one-hop local
10550+:: generic applications. It screens all work before ordinary inference.
10551+++ union-simple-shape-budget
10552+ |= [s=shape fuel=@ud vars=(unit (list @t))]
10553+ ^- (unit @ud)
10554+ ?: =(0 fuel) ~
10555+ =. fuel (dec fuel)
10556+ ?- -.s
10557+ ?(%aura %noun %void %flag) `fuel
10558+ %tvar
10559+ ?~ vars `fuel
10560+ ?:((lien u.vars |=(n=@t =(n name.s))) `fuel ~)
10561+ %const
10562+ ?. |(=(%term form.lit.s) =(%null form.lit.s) =(%loobean form.lit.s)) ~
10563+ ?: &(=(%loobean form.lit.s) !|(=(0 val.lit.s) =(1 val.lit.s))) ~
10564+ `fuel
10565+ %cell (union-simple-fields-budget fields.s fuel vars)
10566+ %fn
10567+ =/ left=(unit @ud) $(s sample.s, fuel fuel)
10568+ ?~ left ~
10569+ $(s product.s, fuel u.left)
10570+ * ~
10571+ ==
10572+++ union-simple-fields-budget
10573+ |= [fields=(list field) fuel=@ud vars=(unit (list @t))]
10574+ ^- (unit @ud)
10575+ ?~ fields `fuel
10576+ ?: =(0 fuel) ~
10577+ =/ field-shape=shape
10578+ ?- -.i.fields
10579+ %bare shape.i.fields
10580+ %face shape.i.fields
10581+ %pun [%ref at.i.fields ~[name.i.fields]]
10582+ ==
10583+ =/ head=(unit @ud) (union-simple-shape-budget field-shape (dec fuel) vars)
10584+ ?~ head ~
10585+ $(fields t.fields, fuel u.head)
10586+++ union-source-find
10587+ |= [n=term molds=imolds fuel=@ud]
10588+ ^- (unit [body=shape left=@ud])
10589+ =/ found=(unit shape) ~
10590+ |-
10591+ ?~ molds
10592+ ?~ found ~
10593+ `[u.found fuel]
10594+ ?: =(0 fuel) ~
10595+ ?: =(n name.i.molds)
10596+ ?^ found ~
10597+ $(molds t.molds, fuel (dec fuel), found `body.i.molds)
10598+ $(molds t.molds, fuel (dec fuel))
10599+++ union-source-args-budget
10600+ |= [vars=(list @t) args=(list shape) fuel=@ud]
10601+ ^- (unit @ud)
10602+ =/ seen=(set @t) *(set @t)
10603+ |-
10604+ ?~ vars ?~(args `fuel ~)
10605+ ?~ args ~
10606+ ?: =(0 fuel) ~
10607+ ?: (~(has in:..zuse seen) i.vars) ~
10608+ =/ arg=(unit @ud) (union-simple-shape-budget i.args (dec fuel) ~)
10609+ ?~ arg ~
10610+ $(vars t.vars, args t.args, fuel u.arg, seen (~(put in:..zuse seen) i.vars))
10611+++ union-source-cell-tag
10612+ |= s=shape
10613+ ^- (unit @)
10614+ ?. ?=(%cell -.s) ~
10615+ ?~ fields.s ~
10616+ ?~ t.fields.s ~
10617+ ?. ?=(%bare -.i.fields.s) ~
10618+ =/ head=shape shape.i.fields.s
10619+ ?. ?=(%const -.head) ~
10620+ ?. |(=(%term form.lit.head) =(%null form.lit.head) =(%loobean form.lit.head)) ~
10621+ ?: &(=(%loobean form.lit.head) !|(=(0 val.lit.head) =(1 val.lit.head))) ~
10622+ `val.lit.head
10623+++ union-source-case-tag
10624+ |= [s=shape molds=imolds fuel=@ud]
10625+ ^- (unit [tag=@ left=@ud])
10626+ ?: ?=(%cell -.s)
10627+ =/ tag=(unit @) (union-source-cell-tag s)
10628+ ?~ tag ~
10629+ =/ left=(unit @ud) (union-simple-shape-budget s fuel ~)
10630+ ?~ left ~
10631+ `[u.tag u.left]
10632+ ?. ?=(%apply -.s) ~
10633+ ?. ?=([@ ~] ref.s) ~
10634+ ?: =(0 fuel) ~
10635+ =/ found=(unit [body=shape left=@ud]) (union-source-find i.ref.s molds (dec fuel))
10636+ ?~ found ~
10637+ ?. ?=(%generic -.body.u.found) ~
10638+ ?~ vars.body.u.found ~
10639+ =/ tag=(unit @) (union-source-cell-tag body.body.u.found)
10640+ ?~ tag ~
10641+ =/ args=(unit @ud) (union-source-args-budget vars.body.u.found args.s left.u.found)
10642+ ?~ args ~
10643+ =/ left=(unit @ud) (union-simple-shape-budget body.body.u.found u.args `vars.body.u.found)
10644+ ?~ left ~
10645+ `[u.tag u.left]
10646+++ union-source-distinct-tags
10647+ |= [cases=(list shape) molds=imolds fuel=@ud]
10648+ ^- ?
10649+ =/ seen=(set @) *(set @)
10650+ =/ has-application=? |
10651+ |-
10652+ ?~ cases has-application
10653+ ?: =(0 fuel) |
10654+ =/ item=(unit [tag=@ left=@ud]) (union-source-case-tag i.cases molds (dec fuel))
10655+ ?~ item |
10656+ ?: (~(has in:..zuse seen) tag.u.item) |
10657+ $(cases t.cases, fuel left.u.item, seen (~(put in:..zuse seen) tag.u.item), has-application |(has-application ?=(%apply -.i.cases)))
10658+::
10659+:: This inference-only screen bounds inherited work that the small source
10660+:: slice may consult. It does not authenticate a caller-created state.
10661+++ union-state-leaf
10662+ |= t=itype
10663+ ^- ?
10664+ ?=(?(%var %avar %rvar %nvar %rnvar %atom %any-atom %flag %noun %empty %const) -.t)
10665+++ union-state-params-budget
10666+ |= [params=iparams fuel=@ud]
10667+ ^- (unit @ud)
10668+ ?~ params `fuel
10669+ ?: =(0 fuel) ~
10670+ ?. (union-state-leaf typ.i.params) ~
10671+ $(params t.params, fuel (dec fuel))
10672+++ union-state-sub-budget
10673+ |= [sub=isub fuel=@ud]
10674+ ^- (unit @ud)
10675+ ?~ sub `fuel
10676+ ?: =(0 fuel) ~
10677+ ?. (union-state-leaf val.i.sub) ~
10678+ $(sub t.sub, fuel (dec fuel))
10679+++ union-state-caps-budget
10680+ |= [caps=icaps fuel=@ud]
10681+ ^- (unit @ud)
10682+ ?~ caps `fuel
10683+ ?: =(0 fuel) ~
10684+ $(caps t.caps, fuel (dec fuel))
10685+++ union-state-active-budget
10686+ |= [active=(list term) fuel=@ud]
10687+ ^- (unit @ud)
10688+ ?~ active `fuel
10689+ ?: =(0 fuel) ~
10690+ $(active t.active, fuel (dec fuel))
10691+++ union-state-tags-budget
10692+ |= [tags=(list ipending) fuel=@ud]
10693+ ^- (unit @ud)
10694+ ?~ tags `fuel
10695+ ?: =(0 fuel) ~
10696+ $(tags t.tags, fuel (dec fuel))
10697+++ union-source-state-safe
10698+ |= [state=istate fuel=@ud]
10699+ ^- ?
10700+ ?^ grec-index.state |
10701+ ?^ holes.state |
10702+ ?^ defer.state |
10703+ ?^ obligations.state |
10704+ =/ params=(unit @ud) (union-state-params-budget params.state fuel)
10705+ ?~ params |
10706+ =/ sub=(unit @ud) (union-state-sub-budget sub.state u.params)
10707+ ?~ sub |
10708+ =/ caps=(unit @ud) (union-state-caps-budget caps.state u.sub)
10709+ ?~ caps |
10710+ =/ active=(unit @ud) (union-state-active-budget active.state u.caps)
10711+ ?~ active |
10712+ ?=(^ (union-state-tags-budget tags.state u.active))
10713+::
10714+:: Positive overlap witnesses from parsed, one-hop local source only.
10715+:: Unknown or exhausted work returns no witness, never disjointness.
10716++$ uow-case [at=span head=@ payload=upat]
10717+++ union-overlap-primitive
10718+ |= s=shape
10719+ ^- (unit upat)
10720+ ?- -.s
10721+ %aura `[%atom ~]
10722+ %noun `[%all ~]
10723+ %void `[%empty ~]
10724+ %flag `[%flag ~]
10725+ %const
10726+ ?. |(=(%term form.lit.s) =(%null form.lit.s) =(%loobean form.lit.s)) ~
10727+ ?: &(=(%loobean form.lit.s) !|(=(0 val.lit.s) =(1 val.lit.s))) ~
10728+ `[%atom `val.lit.s]
10729+ * ~
10730+ ==
10731+++ union-overlap-case
10732+ |= [s=shape molds=imolds fuel=@ud]
10733+ ^- (unit [item=uow-case left=@ud])
10734+ ?: =(0 fuel) ~
10735+ =. fuel (dec fuel)
10736+ :: Each body has exactly two fields; an application has exactly one
10737+ :: parameter and one concrete primitive argument. The full mold table
10738+ :: is scanned to establish unique ownership.
10739+ =/ expanded=(unit [body=shape param=(unit [name=@t pat=upat]) left=@ud])
10740+ ?: ?=(%cell -.s) `[s ~ fuel]
10741+ ?. ?=(%apply -.s) ~
10742+ ?. ?=([@ ~] ref.s) ~
10743+ ?. ?=([* ~] args.s) ~
10744+ ?: =(0 fuel) ~
10745+ =/ found=(unit [body=shape left=@ud]) (union-source-find i.ref.s molds (dec fuel))
10746+ ?~ found ~
10747+ ?. ?=(%generic -.body.u.found) ~
10748+ ?. ?=([@ ~] vars.body.u.found) ~
10749+ ?: =(0 left.u.found) ~
10750+ =/ argument=(unit upat) (union-overlap-primitive i.args.s)
10751+ ?~ argument ~
10752+ `[body.body.u.found `[i.vars.body.u.found u.argument] (dec left.u.found)]
10753+ ?~ expanded ~
10754+ =/ body=shape body.u.expanded
10755+ ?. ?=(%cell -.body) ~
10756+ ?. ?=([* * ~] fields.body) ~
10757+ :: Charge the cell, two fields, and the head and payload nodes.
10758+ ?: (lth left.u.expanded 5) ~
10759+ =/ head=(unit @) (union-source-cell-tag body)
10760+ ?~ head ~
10761+ =/ field=field i.t.fields.body
10762+ =/ payload=shape
10763+ ?- -.field
10764+ %bare shape.field
10765+ %face shape.field
10766+ %pun [%ref at.field ~[name.field]]
10767+ ==
10768+ =/ pattern=(unit upat)
10769+ ?: ?=(%tvar -.payload)
10770+ ?~ param.u.expanded ~
10771+ ?. =(name.payload name.u.param.u.expanded) ~
10772+ `pat.u.param.u.expanded
10773+ (union-overlap-primitive payload)
10774+ ?~ pattern ~
10775+ `[[at.s u.head u.pattern] (sub left.u.expanded 5)]
10776+++ union-overlap-against
10777+ |= [first=uow-case rest=(list shape) molds=imolds fuel=@ud]
10778+ ^- (unit [witness=(unit upair) left=@ud])
10779+ ?~ rest `[~ fuel]
10780+ ?: =(0 fuel) ~
10781+ =/ other=(unit [item=uow-case left=@ud]) (union-overlap-case i.rest molds (dec fuel))
10782+ ?~ other ~
10783+ ?: &(=(head.first head.item.u.other) =(%overlap (union-relate payload.first payload.item.u.other)))
10784+ `[`[at.first at.item.u.other %overlap] left.u.other]
10785+ $(rest t.rest, fuel left.u.other)
10786+++ union-source-overlap
10787+ |= [cases=(list shape) molds=imolds fuel=@ud]
10788+ ^- (unit upair)
10789+ ?~ cases ~
10790+ ?~ t.cases ~
10791+ ?: =(0 fuel) ~
10792+ =/ first=(unit [item=uow-case left=@ud]) (union-overlap-case i.cases molds (dec fuel))
10793+ ?~ first ~
10794+ =/ found=(unit [witness=(unit upair) left=@ud])
10795+ (union-overlap-against item.u.first t.cases molds left.u.first)
10796+ ?~ found ~
10797+ ?^ witness.u.found witness.u.found
10798+ $(cases t.cases, fuel left.u.found)
10799+::
10800+++ union-pairs
10801+ |= [cases=(list shape) molds=imolds]
10802+ ^- (list upair)
10803+ ?~ cases ~
10804+ =/ first=shape i.cases
10805+ =/ a=upat (project-union-mold first molds ~)
10806+ =/ pairs=(list upair)
10807+ %+ turn t.cases
10808+ |= second=shape
10809+ ^- upair
10810+ [at.first at.second (union-relate a (project-union-mold second molds ~))]
10811+ (weld pairs $(cases t.cases))
10812+::
10813+:: A closed structural mold supplies no equation to determine a hole.
10814+:: Applications, references, unbound capitals and unions are unproved.
10815+++ simple-mold-hole
10816+ |= sh=shape
10817+ ^- (unit (unit span))
10818+ ?: ?=(%generic -.sh)
10819+ ?~ vars.sh ~
10820+ ?. (distinct-params vars.sh) ~
10821+ (simple-mold-hole-in body.sh vars.sh)
10822+ (simple-mold-hole-in sh ~)
10823+++ simple-mold-hole-in
10824+ |= [sh=shape vars=(list @t)]
10825+ ^- (unit (unit span))
10826+ ?- -.sh
10827+ %hole ``at.sh
10828+ ?(%aura %noun %void %flag %const) `~
10829+ %tvar ?:((lien vars |=(v=@t =(v name.sh))) `~ ~)
10830+ %cell (simple-mold-field-holes fields.sh vars)
10831+ %fn
10832+ =/ a=(unit (unit span)) $(sh sample.sh)
10833+ ?~ a ~
10834+ =/ b=(unit (unit span)) $(sh product.sh)
10835+ ?~ b ~
10836+ `?~(u.a u.b u.a)
10837+ %generic ~
10838+ * ~
10839+ ==
10840+++ simple-mold-field-holes
10841+ |= [fields=(list field) vars=(list @t)]
10842+ ^- (unit (unit span))
10843+ ?~ fields `~
10844+ =/ f=field i.fields
10845+ =/ first=(unit (unit span))
10846+ ?- -.f
10847+ %face (simple-mold-hole-in shape.f vars)
10848+ %bare (simple-mold-hole-in shape.f vars)
10849+ %pun ~
10850+ ==
10851+ ?~ first ~
10852+ =/ rest=(unit (unit span)) $(fields t.fields)
10853+ ?~ rest ~
10854+ `?~(u.first u.rest u.first)
10855+++ simple-local-mold-hole
10856+ |= defs=(list def)
10857+ ^- (unit span)
10858+ ?~ defs ~
10859+ ?. ?=(%mold -.i.defs) $(defs t.defs)
10860+ =/ found=(unit (unit span)) (simple-mold-hole shape.i.defs)
10861+ ?~ found $(defs t.defs)
10862+ ?^ u.found u.found
10863+ $(defs t.defs)
10864+::
10865+:: A partial prelude may omit unsupported declarations, but may not
10866+:: publish an interface while a named mold's hole remains unchecked.
10867+++ shape-has-hole
10868+ |= sh=shape
10869+ ^- ?
10870+ ?- -.sh
10871+ %hole &
10872+ %path (lien segs.sh |=(s=pseg ?=(%inferred -.s)))
10873+ %apply (lien args.sh shape-has-hole)
10874+ %union (lien cases.sh shape-has-hole)
10875+ %cell (lien fields.sh field-has-hole)
10876+ %fn |($(sh sample.sh) $(sh product.sh))
10877+ %generic $(sh body.sh)
10878+ * |
10879+ ==
10880+++ field-has-hole
10881+ |= f=field
10882+ ^- ?
10883+ ?- -.f
10884+ %face (shape-has-hole shape.f)
10885+ %bare (shape-has-hole shape.f)
10886+ %pun |
10887+ ==
10888+++ named-mold-has-hole
10889+ |= ds=(list def)
10890+ ^- ?
10891+ ?~ ds |
10892+ ?: &(?=(%mold -.i.ds) (shape-has-hole shape.i.ds)) &
10893+ $(ds t.ds)
10894+::
10895+++ sample-has-hole
10896+ |= sam=sample
10897+ ^- ?
10898+ ?- -.sam
10899+ %face (shape-has-hole shape.sam)
10900+ %bare (shape-has-hole shape.sam)
10901+ %cell (lien items.sam sample-has-hole)
10902+ * |
10903+ ==
10904+++ def-has-hole
10905+ |= d=def
10906+ ^- ?
10907+ ?- -.d
10908+ %mold (shape-has-hole shape.d)
10909+ %value (expr-has-hole val.d)
10910+ ==
10911+++ expr-has-hole
10912+ |= e=expr
10913+ ^- ?
10914+ ?- -.e
10915+ %str (lien pieces.e |=(p=piece ?:(?=(%expr -.p) (expr-has-hole p.p) |)))
10916+ %qath (lien segs.e |=(p=qseg ?:(?=(%expr -.p) (expr-has-hole p.p) |)))
10917+ %change (lien edits.e |=(p=edit (expr-has-hole val.p)))
10918+ %pair $(e val.e)
10919+ %unit $(e val.e)
10920+ %group $(e inner.e)
10921+ %list (lien items.e expr-has-hole)
10922+ %tuple (lien items.e |=(i=item (expr-has-hole val.i)))
10923+ ?(%gate %gate-wide) |((sample-has-hole sample.e) $(e body.e))
10924+ %cast |((shape-has-hole shape.e) $(e val.e))
10925+ %call |($(e head.e) (lien args.e expr-has-hole))
10926+ %trace |($(e val.e) $(e then.e))
10927+ %branch |($(e subject.e) (lien arms.e |=(a=arm (expr-has-hole val.a))))
10928+ %body |((lien defs.e def-has-hole) $(e final.e))
10929+ * |
10930+ ==
10931+++ hole-values-present
10932+ |= [ds=(list def) env=ienv]
10933+ ^- ?
10934+ ?~ ds &
10935+ ?. ?=(%value -.i.ds) $(ds t.ds)
10936+ ?: (expr-has-hole val.i.ds)
10937+ ?. ?=(^ (ienv-lookup name.i.ds env)) |
10938+ $(ds t.ds)
10939+ $(ds t.ds)
10940+++ show-partial-mold
10941+ |= [file=path src=@t d=def molds=imolds]
10942+ ^- @t
10943+ ?> ?=(%mold -.d)
10944+ =/ sh=shape shape.d
10945+ =/ hole=(unit (unit span)) (simple-mold-hole sh)
10946+ ?: &(?=(^ hole) ?=(^ u.hole))
10947+ =/ text=@t (show-error src [file line.beg.u.u.hole col.beg.u.u.hole "unresolved type hole"])
10948+ (of-wain:format ~[(crip "+$ {(trip name.d)}: type hole needs a determined type") text])
10949+ =? sh ?=(%generic -.sh) body.sh
10950+ ?. ?=(%union -.sh) (crip "+$ {(trip name.d)}: not checked")
10951+ =/ pairs=(list upair) (union-pairs cases.sh molds)
10952+ =/ overlapping=(list upair) (skim pairs |=(p=upair =(%overlap relation.p)))
10953+ =. overlapping
10954+ ?^ overlapping overlapping
10955+ ?. (lien pairs |=(p=upair =(%unknown relation.p))) ~
10956+ =/ witness=(unit upair) (union-source-overlap cases.sh molds 256)
10957+ ?~(witness ~ ~[u.witness])
10958+ ?^ overlapping
10959+ =/ p=upair i.overlapping
10960+ =/ summary=@t (crip "+$ {(trip name.d)}: overlapping cases; mold not checked")
10961+ =/ first=@t (show-error src [file line.beg.first.p col.beg.first.p "first union case"])
10962+ =/ second=@t (show-error src [file line.beg.second.p col.beg.second.p "overlapping case"])
10963+ (of-wain:format ~[summary first second])
10964+ ?: (lien pairs |=(p=upair =(%unknown relation.p)))
10965+ ?. (union-source-distinct-tags cases.sh molds 256)
10966+ (crip "+$ {(trip name.d)}: case disjointness unresolved; mold not checked")
10967+ (crip "+$ {(trip name.d)}: cases proven disjoint; mold not checked")
10968+ (crip "+$ {(trip name.d)}: cases proven disjoint; mold not checked")
10969+::
10970+:: +show-inference-diagnostic: a partial report with both source sites
10971+::
10972+++ show-inference-diagnostic
10973+ |= [file=path src=@t name=term diagnostic=idiag]
10974+ ^- @t
10975+ =/ summary=@t (crip "++ {(trip name)}: {msg.diagnostic}")
10976+ =/ excerpts=(list @t)
10977+ %+ turn sites.diagnostic
10978+ |= site=[at=span note=tape]
10979+ (show-error src [file line.beg.at.site col.beg.at.site note.site])
10980+ (of-wain:format [summary excerpts])
10981+::
10982+:: Both written field sites are shown in the source that declares them.
10983+++ show-duplicate-fields
10984+ |= [file=path src=@t diagnostic=idiag]
10985+ ^- @t
10986+ =/ excerpts=(list @t)
10987+ %+ turn sites.diagnostic
10988+ |= site=[at=span note=tape]
10989+ (show-error src [file line.beg.at.site col.beg.at.site note.site])
10990+ (of-wain:format [(crip msg.diagnostic) excerpts])
10991+::
10992+++ duplicate-fields-report
10993+ |= [file=path src=@t diagnostic=idiag]
10994+ ^- @t
10995+ (of-wain:format ~['partial inference; module not checked' (show-duplicate-fields file src diagnostic)])
10996+::
10997+:: +golden-types: a partial report; it does not claim the module checks
10998+::
10999+++ golden-types
11000+ |= [file=path src=@t]
11001+ ^- @t
11002+ (golden-types-imports file src ~)
11003+::
11004+:: +golden-types-imports: partial inference with caller-supplied /sur types
11005+::
11006+:: Each entry is [module mold result], where result is exactly the
11007+:: noun returned by +read-mold:jibb-import. Only imports declared with
11008+:: /- are visible. Unrecognized or failed results are unsupported.
11009+::
11010+++ golden-types-imports
11011+ |= [file=path src=@t externals=iexternals]
11012+ ^- @t
11013+ (golden-types-with-marks file src externals ~)
11014+::
11015+:: A supplied module is addressed by its logical /ui/.../name/jibb path.
11016+:: Interfaces are closed inference schemes, never raw source shapes.
11017+:: Recursive modules, APIs, derived gates and unsupported definitions do
11018+:: not yield an interface. The reachable graph is checked before the root.
11019+::
11020++$ jsource [at=path source=@t]
11021++$ jbundle (list jsource)
11022++$ jcache (list [at=path iface=ifile])
11023++$ jfile-result (each [iface=ifile cache=jcache] @t)
11024+:: Overlap evidence retains the exact source that supplied its spans.
11025+:: Ordinary Jibb imports preserve this evidence through the resolver.
11026++$ jfile-overlap [file=path source=@t name=term cases=upair]
11027++$ jfile-failure [message=@t overlap=(unit jfile-overlap)]
11028++$ jfile-detailed-result (each [iface=ifile cache=jcache] jfile-failure)
11029++$ jimports-result (each [resolved=ijimports cache=jcache] @t)
11030+:: Preserve an imported overlap's original file and source across the graph.
11031++$ jimports-detailed-result (each [resolved=ijimports cache=jcache] jfile-failure)
11032+::
11033+:: Written record fields each have their own lexical record scope.
11034++$ written-fields (map term span)
11035+++ duplicate-written-field
11036+ |= [name=term at=span seen=written-fields]
11037+ ^- (unit idiag)
11038+ =/ prior=(unit span) (~(get by seen) name)
11039+ ?~ prior ~
11040+ `["record field `{(trip name)}` is repeated" ~[[u.prior "first field"] [at "repeated field"]]]
11041+++ duplicate-shapes
11042+ |= xs=(list shape)
11043+ ^- (unit idiag)
11044+ ?~ xs ~
11045+ =/ first (duplicate-shape i.xs)
11046+ ?^ first first
11047+ $(xs t.xs)
11048+++ duplicate-fields
11049+ |= [fields=(list field) seen=written-fields]
11050+ ^- (unit idiag)
11051+ ?~ fields ~
11052+ =/ f=field i.fields
11053+ =/ n=(unit term)
11054+ ?- -.f
11055+ %face `name.f
11056+ %pun `name.f
11057+ %bare ~
11058+ ==
11059+ =/ dup=(unit idiag) ?~(n ~ (duplicate-written-field u.n at.f seen))
11060+ ?^ dup dup
11061+ =/ inner=(unit idiag)
11062+ ?- -.f
11063+ %face (duplicate-shape shape.f)
11064+ %pun ~
11065+ %bare (duplicate-shape shape.f)
11066+ ==
11067+ ?^ inner inner
11068+ $(fields t.fields, seen ?~(n seen (~(put by seen) u.n at.f)))
11069+++ duplicate-shape
11070+ |= s=shape
11071+ ^- (unit idiag)
11072+ ?- -.s
11073+ %cell (duplicate-fields fields.s ~)
11074+ %apply (duplicate-shapes args.s)
11075+ %union (duplicate-shapes cases.s)
11076+ %fn
11077+ =/ left (duplicate-shape sample.s)
11078+ ?^ left left
11079+ (duplicate-shape product.s)
11080+ %generic (duplicate-shape body.s)
11081+ * ~
11082+ ==
11083+++ duplicate-samples
11084+ |= [items=(list sample) seen=written-fields]
11085+ ^- (unit idiag)
11086+ ?~ items ~
11087+ =/ a=sample i.items
11088+ =/ n=(unit term)
11089+ ?- -.a
11090+ %bind `name.a
11091+ %face `name.a
11092+ %pun `name.a
11093+ * ~
11094+ ==
11095+ =/ dup=(unit idiag) ?~(n ~ (duplicate-written-field u.n at.a seen))
11096+ ?^ dup dup
11097+ =/ inner (duplicate-sample a)
11098+ ?^ inner inner
11099+ $(items t.items, seen ?~(n seen (~(put by seen) u.n at.a)))
11100+++ duplicate-sample
11101+ |= s=sample
11102+ ^- (unit idiag)
11103+ ?- -.s
11104+ %cell (duplicate-samples items.s ~)
11105+ %face (duplicate-shape shape.s)
11106+ %bare (duplicate-shape shape.s)
11107+ * ~
11108+ ==
11109+++ duplicate-exprs
11110+ |= xs=(list expr)
11111+ ^- (unit idiag)
11112+ ?~ xs ~
11113+ =/ first (duplicate-expr i.xs)
11114+ ?^ first first
11115+ $(xs t.xs)
11116+++ duplicate-items
11117+ |= [items=(list item) seen=written-fields]
11118+ ^- (unit idiag)
11119+ ?~ items ~
11120+ =/ a=item i.items
11121+ =/ dup=(unit idiag) ?~(face.a ~ (duplicate-written-field u.face.a at.a seen))
11122+ ?^ dup dup
11123+ =/ inner (duplicate-expr val.a)
11124+ ?^ inner inner
11125+ $(items t.items, seen ?~(face.a seen (~(put by seen) u.face.a at.a)))
11126+++ duplicate-pieces
11127+ |= pieces=(list piece)
11128+ ^- (unit idiag)
11129+ ?~ pieces ~
11130+ =/ first=(unit idiag) ?:(?=(%expr -.i.pieces) (duplicate-expr p.i.pieces) ~)
11131+ ?^ first first
11132+ $(pieces t.pieces)
11133+++ duplicate-qsegs
11134+ |= segs=(list qseg)
11135+ ^- (unit idiag)
11136+ ?~ segs ~
11137+ =/ first=(unit idiag) ?:(?=(%expr -.i.segs) (duplicate-expr p.i.segs) ~)
11138+ ?^ first first
11139+ $(segs t.segs)
11140+++ duplicate-edits
11141+ |= edits=(list edit)
11142+ ^- (unit idiag)
11143+ ?~ edits ~
11144+ =/ first (duplicate-expr val.i.edits)
11145+ ?^ first first
11146+ $(edits t.edits)
11147+++ duplicate-arms
11148+ |= arms=(list arm)
11149+ ^- (unit idiag)
11150+ ?~ arms ~
11151+ =/ first (duplicate-expr val.i.arms)
11152+ ?^ first first
11153+ $(arms t.arms)
11154+++ duplicate-defs
11155+ |= defs=(list def)
11156+ ^- (unit idiag)
11157+ ?~ defs ~
11158+ =/ first=(unit idiag)
11159+ ?- -.i.defs
11160+ %mold (duplicate-shape shape.i.defs)
11161+ %value (duplicate-expr val.i.defs)
11162+ ==
11163+ ?^ first first
11164+ $(defs t.defs)
11165+++ duplicate-expr
11166+ |= e=expr
11167+ ^- (unit idiag)
11168+ ?- -.e
11169+ %str (duplicate-pieces pieces.e)
11170+ %qath (duplicate-qsegs segs.e)
11171+ %change (duplicate-edits edits.e)
11172+ %pair (duplicate-expr val.e)
11173+ %unit (duplicate-expr val.e)
11174+ %group (duplicate-expr inner.e)
11175+ %list (duplicate-exprs items.e)
11176+ %tuple (duplicate-items items.e ~)
11177+ %gate-wide
11178+ =/ first (duplicate-sample sample.e)
11179+ ?^ first first
11180+ (duplicate-expr body.e)
11181+ %gate
11182+ =/ first (duplicate-sample sample.e)
11183+ ?^ first first
11184+ (duplicate-expr body.e)
11185+ %cast
11186+ =/ first (duplicate-shape shape.e)
11187+ ?^ first first
11188+ (duplicate-expr val.e)
11189+ %call
11190+ =/ first (duplicate-expr head.e)
11191+ ?^ first first
11192+ (duplicate-exprs args.e)
11193+ %trace
11194+ =/ first (duplicate-expr val.e)
11195+ ?^ first first
11196+ (duplicate-expr then.e)
11197+ %branch
11198+ =/ first (duplicate-expr subject.e)
11199+ ?^ first first
11200+ (duplicate-arms arms.e)
11201+ %body
11202+ =/ first (duplicate-defs defs.e)
11203+ ?^ first first
11204+ (duplicate-expr final.e)
11205+ * ~
11206+ ==
11207+++ import-binding-names
11208+ |= imports=(list import)
11209+ ^- (list term)
11210+ ?~ imports ~
11211+ =/ n=term
11212+ ?- -.i.imports
11213+ %jibb face.i.imports
11214+ %sur name.i.imports
11215+ %mark mark.i.imports
11216+ ==
11217+ [n $(imports t.imports)]
11218+::
11219+++ reserved-proj-sample
11220+ |= sam=sample
11221+ ^- ?
11222+ ?- -.sam
11223+ %bind =(name.sam %proj)
11224+ %face =(name.sam %proj)
11225+ %pun =(name.sam %proj)
11226+ %cell (lien items.sam reserved-proj-sample)
11227+ * |
11228+ ==
11229+++ reserved-proj-pattern
11230+ |= p=pattern
11231+ ^- ?
11232+ ?- -.p
11233+ %bind =(name.p %proj)
11234+ %cell (lien items.p reserved-proj-pattern)
11235+ * |
11236+ ==
11237+++ reserved-proj-def
11238+ |= d=def
11239+ ^- ?
11240+ ?: =(name.d %proj) &
11241+ ?: ?=(%value -.d) (reserved-proj-expr val.d)
11242+ |
11243+++ reserved-proj-expr
11244+ |= e=expr
11245+ ^- ?
11246+ ?- -.e
11247+ %str (lien pieces.e |=(p=piece ?:(?=(%expr -.p) (reserved-proj-expr p.p) |)))
11248+ %qath (lien segs.e |=(p=qseg ?:(?=(%expr -.p) (reserved-proj-expr p.p) |)))
11249+ %change (lien edits.e |=(p=edit (reserved-proj-expr val.p)))
11250+ %pair $(e val.e)
11251+ %unit $(e val.e)
11252+ %group $(e inner.e)
11253+ %list (lien items.e reserved-proj-expr)
11254+ %tuple (lien items.e |=(i=item (reserved-proj-expr val.i)))
11255+ ?(%gate %gate-wide) |((reserved-proj-sample sample.e) $(e body.e))
11256+ %cast $(e val.e)
11257+ %call |($(e head.e) (lien args.e reserved-proj-expr))
11258+ %trace |($(e val.e) $(e then.e))
11259+ %branch |($(e subject.e) (lien arms.e |=(a=arm |((reserved-proj-pattern pat.a) (reserved-proj-expr val.a)))))
11260+ %body |((lien defs.e reserved-proj-def) $(e final.e))
11261+ * |
11262+ ==
11263+::
11264+++ module-has-reserved-proj
11265+ |= mod=module
11266+ ^- ?
11267+ =/ imported=(list term) (import-binding-names imports.mod)
11268+ =/ vals=(list term) (global-value-names defs.mod)
11269+ =/ molds=imolds (collect-simple-molds defs.mod)
11270+ =/ mold-names=(list term) (turn molds |=(m=[name=term body=shape] name.m))
11271+ |((lien (weld imported (weld vals mold-names)) |=(n=term =(n %proj))) (lien defs.mod reserved-proj-def))
11272+::
11273+++ module-scope-valid
11274+ |= [mod=module prelude-values=(list term) prelude-molds=(list term)]
11275+ ^- ?
11276+ =/ imported=(list term) (import-binding-names imports.mod)
11277+ =/ vals=(list term) (global-value-names defs.mod)
11278+ =/ molds=imolds (collect-simple-molds defs.mod)
11279+ =/ mold-names=(list term) (turn molds |=(m=[name=term body=shape] name.m))
11280+ ?: (module-has-reserved-proj mod) |
11281+ ?. %+ levy imported
11282+ |= n=term
11283+ &((unique-value-name n imported) !(lien vals |=(v=term =(n v))) !(lien mold-names |=(m=term =(n m))) !(lien prelude-values |=(v=term =(n v))) !(lien prelude-molds |=(m=term =(n m))))
11284+ |
11285+ ?. (levy vals |=(n=term &((unique-value-name n vals) !(lien prelude-values |=(v=term =(n v)))))) |
11286+ (levy mold-names |=(n=term &((unique-value-name n mold-names) !(lien prelude-molds |=(m=term =(n m))))))
11287+::
11288+:: In an API file or before main's kind is known, a lone `+$ poke`
11289+:: may be a declaration rather than a mold that shadows the prelude. Do not call
11290+:: that one collision definite, and do not hide unrelated scope errors.
11291+++ pending-declared-poke
11292+ |= [at=path mod=module prelude-values=(list term) prelude-molds=(list term)]
11293+ ^- ?
11294+ ?. (lien prelude-molds |=(n=term =(%poke n))) |
11295+ ?. |(?=([%ui %api @ %jibb ~] at) (lien defs.mod |=(d=def &(?=(%value -.d) =(%main name.d))))) |
11296+ =/ pokes=(list def)
11297+ (skim defs.mod |=(d=def &(?=(%mold -.d) =(%poke name.d))))
11298+ ?~ pokes |
11299+ ?^ t.pokes |
11300+ =/ remaining=(list def)
11301+ (skim defs.mod |=(d=def !&(?=(%mold -.d) =(%poke name.d))))
11302+ (module-scope-valid mod(defs remaining) prelude-values prelude-molds)
11303+::
11304+:: A detailed failure is attached only to the first mold that actually
11305+:: failed in this check, using that module's checked source mold table.
11306++$ imold-failure [message=@t overlap=(unit [name=term cases=upair])]
11307+:: Validate a generic wrapper without an unbounded duplicate-name pass.
11308+++ module-mold-params-valid
11309+ |= [vars=(list @t) seen=(set @t) fuel=@ud]
11310+ ^- ?
11311+ ?~ vars &
11312+ ?: =(0 fuel) |
11313+ ?: (~(has in:..zuse seen) i.vars) |
11314+ $(vars t.vars, seen (~(put in:..zuse seen) i.vars), fuel (dec fuel))
11315+++ module-mold-overlap
11316+ |= [m=[name=term body=shape] molds=imolds]
11317+ ^- (unit upair)
11318+ =/ sh=shape body.m
11319+ =/ valid=?
11320+ ?. ?=(%generic -.sh) &
11321+ ?~ vars.sh |
11322+ (module-mold-params-valid vars.sh *(set @t) 256)
11323+ ?. valid ~
11324+ =? sh ?=(%generic -.sh) body.sh
11325+ ?. ?=(%union -.sh) ~
11326+ (union-source-overlap cases.sh molds 256)
11327+++ module-mold-types-detail
11328+ |= [molds=imolds state=istate]
11329+ ^- (each imold-types imold-failure)
11330+ ?~ molds [%& ~]
11331+ =/ m=[name=term body=shape] i.molds
11332+ =/ t=(unit [template=ischeme state=istate])
11333+ (infer-mold-template body.m state(active [name.m active.state], in-mold &))
11334+ ?~ t
11335+ =/ overlap=(unit upair) (module-mold-overlap m molds.state)
11336+ [%| ['module mold needs unsupported inference' ?~(overlap ~ `[name.m u.overlap])]]
11337+ =. typ.template.u.t (label-direct-union typ.template.u.t body.m name.m state)
11338+ =/ rest=(each imold-types imold-failure) $(molds t.molds)
11339+ ?: ?=(%| -.rest) rest
11340+ [%& [[name.m template.u.t] p.rest]]
11341+++ module-mold-types
11342+ |= [molds=imolds state=istate]
11343+ ^- (each imold-types @t)
11344+ ?~ molds [%& ~]
11345+ =/ m=[name=term body=shape] i.molds
11346+ =/ t=(unit [template=ischeme state=istate])
11347+ (infer-mold-template body.m state(active [name.m active.state], in-mold &))
11348+ ?~ t [%| 'module mold needs unsupported inference']
11349+ =. typ.template.u.t (label-direct-union typ.template.u.t body.m name.m state)
11350+ =/ rest=(each imold-types @t) $(molds t.molds)
11351+ ?: ?=(%| -.rest) rest
11352+ [%& [[name.m template.u.t] p.rest]]
11353+::
11354+:: Prepare a provisional interface from the trusted vendored source.
11355+:: Every declared name remains reserved, but only molds and values this
11356+:: fragment can infer are usable. Unsupported bodies are not validated.
11357+:: An optional internal source supplies the prelude's one supported import;
11358+:: clients cannot import that path directly. Named unions retain their origin.
11359+::
11360+:: Recognize only the complete standard prelude list shape. Its recursive
11361+:: tail uses the same parameter and the unqualified list name. The reader
11362+:: verifies Hoon's list provenance before producing the same collection type.
11363+:: The prelude source and reader output are trusted caller inputs.
11364+::
11365+++ standard-prelude-list
11366+ |= sh=shape
11367+ ^- ?
11368+ ?. ?=(%generic -.sh) |
11369+ ?~ vars.sh |
11370+ ?^ t.vars.sh |
11371+ =/ var=@t i.vars.sh
11372+ ?. ?=(%union -.body.sh) |
11373+ =/ cs=(list shape) cases.body.sh
11374+ ?~ cs |
11375+ ?~ t.cs |
11376+ ?^ t.t.cs |
11377+ ?. ?=(%const -.i.cs) |
11378+ ?. =(%null form.lit.i.cs) |
11379+ ?. ?=(%cell -.i.t.cs) |
11380+ =/ fs=(list field) fields.i.t.cs
11381+ ?~ fs |
11382+ ?~ t.fs |
11383+ ?^ t.t.fs |
11384+ ?. ?=(%face -.i.fs) |
11385+ ?. =(%i name.i.fs) |
11386+ ?. ?=(%tvar -.shape.i.fs) |
11387+ ?. =(var name.shape.i.fs) |
11388+ ?. ?=(%face -.i.t.fs) |
11389+ ?. =(%t name.i.t.fs) |
11390+ =/ tail=shape shape.i.t.fs
11391+ ?. ?=(%apply -.tail) |
11392+ ?. =(~[%list] ref.tail) |
11393+ ?~ args.tail |
11394+ ?^ t.args.tail |
11395+ ?. ?=(%tvar -.i.args.tail) |
11396+ =(var name.i.args.tail)
11397+::
11398+++ prelude-label
11399+ |= [typ=itype name=term vars=(list @ud)]
11400+ ^- itype
11401+ ?: ?=(%jrec -.typ) typ(label `name)
11402+ ?: ?=(%grec -.typ)
11403+ ?. (identity-union-parameters vars args.typ) typ(label ~)
11404+ typ(label `name)
11405+ ?. ?=(%union -.typ) typ
11406+ ?. (identity-union-parameters vars args.typ)
11407+ ?~ origin.typ typ
11408+ ?: =(at.u.origin.typ /lib/jibb/internal/jibb) typ(label ~)
11409+ typ
11410+ typ(label `name)
11411+::
11412+++ partial-prelude-molds
11413+ |= [molds=imolds state=istate]
11414+ ^- imold-types
11415+ ?~ molds ~
11416+ =/ m=[name=term body=shape] i.molds
11417+ ?: &(=(at.state /lib/jibb/prelude/jibb) =(%list name.m))
11418+ ?. (standard-prelude-list body.m) $(molds t.molds)
11419+ [[%list [[%collection %list ~[[%var 0]]] ~[0]]] $(molds t.molds)]
11420+ =/ out=(unit [template=ischeme state=istate])
11421+ (infer-mold-template body.m state(active [name.m active.state], in-mold &))
11422+ ?~ out $(molds t.molds)
11423+ =. typ.template.u.out (label-direct-union typ.template.u.out body.m name.m state)
11424+ =. typ.template.u.out (prelude-label typ.template.u.out name.m vars.template.u.out)
11425+ [[name.m template.u.out] $(molds t.molds)]
11426+::
11427+:: A compiler-owned interface available only to the dedicated
11428+:: internal-prelude preparation path, never the ordinary module resolver.
11429+++ private-primitive-interface
11430+ ^- ifile
11431+ =/ a=itype [%avar 0]
11432+ =/ pair=itype [%cell a a]
11433+ =/ b=itype [%rvar 0]
11434+ =/ plus=ischeme [[%fn [%cell b b] b] ~[0]]
11435+ =/ minus=ischeme [[%fn b b] ~[0]]
11436+ =/ greater=ischeme [[%fn pair [%flag ~]] ~[0]]
11437+ =/ utf8=itype [%atom 'tD']
11438+ =/ tape=itype [%collection %list ~[utf8]]
11439+ =/ codepoints=itype [%collection %list ~[[%atom %c]]]
11440+ =/ text-trip=ischeme [[%fn [%atom %t] tape] ~]
11441+ =/ text-tuba=ischeme [[%fn tape codepoints] ~]
11442+ [~[[%raw-add plus] [%raw-dec minus] [%raw-gth greater] [%raw-trip text-trip] [%raw-tuba text-tuba]] ~ /lib/jibb/primitives/jibb ~ ~ ~ ~ ~]
11443+::
11444+++ infer-private-internal
11445+ |= [src=@t public-source=@t]
11446+ ^- (unit ifile)
11447+ =/ at=path /lib/jibb/internal/jibb
11448+ =/ parsed (parse at src)
11449+ ?: ?=(%| -.parsed) ~
11450+ =/ mod=module p.parsed
11451+ ?^ (duplicate-defs defs.mod) ~
11452+ ?~ imports.mod
11453+ =/ built=jfile-result (infer-jibb-file at src ~ ~ ~ ~[at] ~ ~ ~ ~)
11454+ ?: ?=(%| -.built) ~
11455+ `iface.p.built
11456+ ?. ?=([[%jibb *] ~] imports.mod) ~
11457+ ?. =(path.i.imports.mod /lib/jibb/primitives) ~
11458+ ?. (module-scope-valid mod ~ ~) ~
11459+ =/ vals=(list term) (global-value-names defs.mod)
11460+ ?: (lien vals |=(n=term =(n %main))) ~
11461+ =/ molds=imolds (collect-simple-molds defs.mod)
11462+ =/ globals=(list term) (weld (import-binding-names imports.mod) vals)
11463+ :: The private source can use the public list and unit molds before the
11464+ :: prelude is otherwise prepared. Re-read the trusted public source here
11465+ :: and admit only its validated canonical templates; do not accept schemes
11466+ :: supplied independently by the caller.
11467+ =/ public=(each module error) (parse /lib/jibb/prelude/jibb public-source)
11468+ ?: ?=(%| -.public) ~
11469+ ?^ (duplicate-defs defs.p.public) ~
11470+ ?. (module-scope-valid p.public ~ ~) ~
11471+ =/ source-molds=imolds (collect-simple-molds defs.p.public)
11472+ =/ written-list=(unit shape) (find-simple-mold %list source-molds)
11473+ =/ source-list=(unit ischeme)
11474+ ?~ written-list ~
11475+ ?. (standard-prelude-list u.written-list) ~
11476+ `[[%collection %list ~[[%var 0]]] ~[0]]
11477+ :: Derive the public unit template from its actual source, then compare
11478+ :: the complete nominal template before making it available privately.
11479+ =/ unit-decl=(unit shape) (find-simple-mold %unit source-molds)
11480+ =/ source-unit=(unit ischeme)
11481+ ?~ unit-decl ~
11482+ =/ unit-molds=imolds ~[[%unit u.unit-decl]]
11483+ =/ unit-state=istate [0 ~ ~ ~ unit-molds ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | /lib/jibb/prelude/jibb ~[%unit] ~ ~ 256 ~ ~ ~ ~ ~ ~]
11484+ =/ unit-types=imold-types (partial-prelude-molds unit-molds unit-state)
11485+ =/ unit-iface=ifile [~ unit-types /lib/jibb/prelude/jibb ~ ~ ~ ~ ~]
11486+ =/ found=(unit ischeme) (find-jibb-mold %unit unit-iface)
11487+ ?~ found ~
11488+ ?. (standard-unit-template u.found /lib/jibb/prelude/jibb) ~
11489+ found
11490+ =/ primitive=ifile private-primitive-interface
11491+ =? primitive ?=(^ source-list)
11492+ primitive(molds [[%list u.source-list] molds.primitive])
11493+ =? primitive ?=(^ source-unit)
11494+ primitive(molds [[%unit u.source-unit] molds.primitive])
11495+ =/ js=ijimports ~[[face.i.imports.mod primitive]]
11496+ =/ reserved=(list term) ~[face.i.imports.mod]
11497+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
11498+ =/ state=istate [0 ~ ~ ~ molds globals ~ ~ ~ ~ js reserved ~ ~ ~ | at top ~ ~ 256 ~ ~ ~ ~ ~ ~]
11499+ =/ mts=(each imold-types @t) (module-mold-types molds state)
11500+ =/ usable=(unit imold-types)
11501+ ?: ?=(%& -.mts) `p.mts
11502+ :: Missing public templates may make an unrelated internal mold
11503+ :: unavailable. Validate all molds once with isolated canonical
11504+ :: templates before admitting only those inferred using the actual
11505+ :: source-backed templates. The proof interface is never exported.
11506+ ?. |(?=(~ source-list) ?=(~ source-unit)) ~
11507+ =/ nil=itype [%const [%null %n 0 '~']]
11508+ =/ canonical-unit=ischeme
11509+ [[%union ~[nil [%cell nil [%face %u [%var 0]]]] `[/lib/jibb/prelude/jibb %unit] `%unit ~[[%var 0]]] ~[0]]
11510+ =/ canonical-list=ischeme [[%collection %list ~[[%var 0]]] ~[0]]
11511+ =/ proof-primitive=ifile private-primitive-interface
11512+ =. molds.proof-primitive ~[[%list canonical-list] [%unit canonical-unit]]
11513+ =/ proof-imports=ijimports ~[[face.i.imports.mod proof-primitive]]
11514+ =/ proof=(each imold-types @t) (module-mold-types molds state(jimports proof-imports))
11515+ ?: ?=(%| -.proof) ~
11516+ `(partial-prelude-molds molds state)
11517+ ?~ usable ~
11518+ =/ resolution=iresolved (resolve-groups defs.mod molds globals ~ ~ ~ ~ js reserved at ~)
11519+ =/ env=ienv env.resolution
11520+ ?. (module-values-complete defs.mod env) ~
11521+ `[env u.usable at ~ artifacts.resolution ~ `src ~]
11522+::
11523+++ partial-prelude-interface-with-internal
11524+ |= [src=@t internal-source=(unit @t)]
11525+ ^- (unit ifile)
11526+ ?: =(0 src) ~
11527+ =/ at=path /lib/jibb/prelude/jibb
11528+ =/ parsed (parse at src)
11529+ ?: ?=(%| -.parsed) ~
11530+ ?: (named-mold-has-hole defs.p.parsed) ~
11531+ ?^ (duplicate-defs defs.p.parsed) ~
11532+ =/ private=(unit ijimports)
11533+ ?~ imports.p.parsed `~
11534+ ?. ?=([[%jibb *] ~] imports.p.parsed) ~
11535+ ?. =(path.i.imports.p.parsed /lib/jibb/internal) ~
11536+ ?~ internal-source ~
11537+ =/ built=(unit ifile) (infer-private-internal u.internal-source src)
11538+ ?~ built ~
11539+ `~[[face.i.imports.p.parsed u.built]]
11540+ ?~ private ~
11541+ ?~ defs.p.parsed ~
11542+ ?. (module-scope-valid p.parsed ~ ~) ~
11543+ =/ ds=(list def) defs.p.parsed
11544+ =/ molds=imolds (collect-simple-molds ds)
11545+ =/ names=(list term) (turn molds |=(m=[name=term body=shape] name.m))
11546+ =/ globals=(list term) (weld (import-binding-names imports.p.parsed) (global-value-names ds))
11547+ :: Remove raw list before inferring any template, so an altered list
11548+ :: cannot leak through an alias. Its name remains reserved either way.
11549+ =/ declared=? (lien names |=(name=term =(%list name)))
11550+ =/ env-molds=imolds molds
11551+ =? env-molds declared
11552+ (skim molds |=(m=[name=term body=shape] !=(%list name.m)))
11553+ =/ reserved=(list term) ?:(declared ~[%list] ~)
11554+ =/ state=istate [0 ~ ~ ~ env-molds globals ~ ~ ~ ~ u.private reserved ~ ~ ~ | at names ~ ~ 256 ~ ~ ~ ~ ~ ~]
11555+ :: Other prelude molds may use list only after its source has passed
11556+ :: the standard-list check. The raw declaration remains removed.
11557+ =/ declared-list=(unit shape) (find-simple-mold %list molds)
11558+ =/ mold-prelude=(unit ifile)
11559+ ?~ declared-list ~
11560+ ?. (standard-prelude-list u.declared-list) ~
11561+ `[~ ~[[%list [[%collection %list ~[[%var 0]]] ~[0]]]] at ~ ~ ~ ~ ~]
11562+ =/ mt=imold-types (partial-prelude-molds molds state(prelude mold-prelude))
11563+ =/ partial=ifile [~ mt at ~ ~ ~ ~ ~]
11564+ :: An explicitly qualified re-export must resolve. Other unsupported
11565+ :: prelude declarations remain reserved but absent from the interface.
11566+ =/ required=imolds
11567+ %+ skim molds
11568+ |= m=[name=term body=shape]
11569+ =/ sh=shape body.m
11570+ ?. ?=(%ref -.sh) |
11571+ ?~ names.sh |
11572+ ?=(^ t.names.sh)
11573+ ?. (levy required |=(m=[name=term body=shape] ?=(^ (find-jibb-mold name.m partial)))) ~
11574+ =/ resolution=iresolved (resolve-groups ds env-molds globals ~ ~ ~ ~ u.private reserved at `partial)
11575+ =/ env=ienv env.resolution
11576+ ?. (hole-values-present ds env) ~
11577+ =/ deps=(list iwidth-dependency)
11578+ ?~ u.private ~
11579+ ~[[at.interface.i.u.private source.interface.i.u.private elaborations.interface.i.u.private]]
11580+ `[env mt at ~ artifacts.resolution deps `src ~]
11581+::
11582+++ partial-prelude-interface
11583+ |= src=@t
11584+ ^- (unit ifile)
11585+ (partial-prelude-interface-with-internal src ~)
11586+::
11587++$ iprelude [iface=ifile values=(list term) molds=(list term)]
11588+::
11589+++ prepare-prelude
11590+ |= src=@t
11591+ ^- (unit iprelude)
11592+ =/ iface=(unit ifile) (partial-prelude-interface src)
11593+ ?~ iface ~
11594+ =/ parsed (parse /lib/jibb/prelude/jibb src)
11595+ ?: ?=(%| -.parsed) ~
11596+ =/ vals=(list term) (global-value-names defs.p.parsed)
11597+ =/ ms=(list term) (turn (collect-simple-molds defs.p.parsed) |=(m=[name=term body=shape] name.m))
11598+ `[u.iface vals ms]
11599+::
11600+++ prepare-prelude-with-internal
11601+ |= [src=@t internal-source=@t]
11602+ ^- (unit iprelude)
11603+ =/ iface=(unit ifile) (partial-prelude-interface-with-internal src `internal-source)
11604+ ?~ iface ~
11605+ =/ parsed (parse /lib/jibb/prelude/jibb src)
11606+ ?: ?=(%| -.parsed) ~
11607+ =/ vals=(list term) (global-value-names defs.p.parsed)
11608+ =/ ms=(list term) (turn (collect-simple-molds defs.p.parsed) |=(m=[name=term body=shape] name.m))
11609+ `[u.iface vals ms]
11610+::
11611+++ module-values-complete
11612+ |= [ds=(list def) env=ienv]
11613+ ^- ?
11614+ ?~ ds &
11615+ ?: ?=(%mold -.i.ds) $(ds t.ds)
11616+ ?~ (ienv-lookup name.i.ds env) |
11617+ $(ds t.ds)
11618+::
11619+:: Cache only completed interfaces for this invocation. The source bundle,
11620+:: imported Hoon types and prelude are fixed for the whole graph. Check the
11621+:: active path and duplicate sources before consulting it, so a cache hit
11622+:: cannot hide a cycle or ambiguous source.
11623+::
11624+++ find-jibb-cache
11625+ |= [at=path cache=jcache]
11626+ ^- (unit ifile)
11627+ ?~ cache ~
11628+ ?: =(at at.i.cache) `iface.i.cache
11629+ $(cache t.cache)
11630+::
11631+:: These certificates retain the complete checked source closure. The
11632+:: trusted host must supply the identical prepared prelude and reader nouns.
11633+:: Exact bundle equality binds all source paths and versions; the set
11634+:: retains transitive paths for active-cycle checks. Request-bearing graphs
11635+:: alone have a size limit; incompatible diamond evidence fails closed.
11636+++ request-graph-requests-add
11637+ |= [pending=(list irequest-evidence) acc=(list irequest-evidence) fuel=@ud]
11638+ ^- (unit (list irequest-evidence))
11639+ ?~ pending `acc
11640+ ?: =(0 fuel) ~
11641+ =/ hit=(list irequest-evidence)
11642+ (skim acc |=(x=irequest-evidence &(=(api-at.x api-at.i.pending) =(name.x name.i.pending))))
11643+ ?^ hit
11644+ ?. ?=([* ~] hit) ~
11645+ ?. =(i.hit i.pending) ~
11646+ $(pending t.pending, fuel (dec fuel))
11647+ $(pending t.pending, acc [i.pending acc], fuel (dec fuel))
11648+++ request-graph-inputs-match
11649+ |= [g=irequest-graph externals=iexternals marks=imark-externals modules=jbundle values=(list term) molds=(list term) prelude=(unit ifile)]
11650+ ^- ?
11651+ ?& =(bundle-input.g modules)
11652+ =(prelude-input.g prelude)
11653+ =(prelude-values.g values)
11654+ =(prelude-molds.g molds)
11655+ =(externals.g externals)
11656+ =(marks.g marks)
11657+ ==
11658+++ request-graph-merge
11659+ |= [imports=ijimports g=irequest-graph fuel=@ud]
11660+ ^- (unit irequest-graph)
11661+ ?~ imports `g
11662+ ?: =(0 fuel) ~
11663+ =/ child=ifile interface.i.imports
11664+ ?~ graph.child ~
11665+ =/ cg=irequest-graph u.graph.child
11666+ ?. ?& =(bundle-input.g bundle-input.cg)
11667+ =(prelude-input.g prelude-input.cg)
11668+ =(prelude-values.g prelude-values.cg)
11669+ =(prelude-molds.g prelude-molds.cg)
11670+ =(externals.g externals.cg)
11671+ =(marks.g marks.cg)
11672+ ==
11673+ ~
11674+ =/ merged=(set path) (~(uni in:..zuse paths.g) paths.cg)
11675+ =/ rs=(unit (list irequest-evidence))
11676+ (request-graph-requests-add requests.cg requests.g (add 1 (lent requests.cg)))
11677+ ?~ rs ~
11678+ ?: &(?=(^ u.rs) |((gth (lent ~(tap in:..zuse merged)) 256) (gth (lent u.rs) 256))) ~
11679+ $(imports t.imports, g g(paths merged, requests u.rs), fuel (dec fuel))
11680+++ request-graph-reusable
11681+ |= [f=ifile src=@t externals=iexternals marks=imark-externals modules=jbundle active=(list path) values=(list term) molds=(list term) prelude=(unit ifile)]
11682+ ^- ?
11683+ ?~ source.f |
11684+ ?. =(u.source.f src) |
11685+ ?~ graph.f |
11686+ =/ g=irequest-graph u.graph.f
11687+ ?. (request-graph-inputs-match g externals marks modules values molds prelude) |
11688+ ?. (~(has in:..zuse paths.g) at.f) |
11689+ !(lien active |=(p=path (~(has in:..zuse paths.g) p)))
11690+::
11691+++ resolve-jibb-imports
11692+ |= [imports=(list import) externals=iexternals mark-externals=imark-externals modules=jbundle active=(list path) prelude-values=(list term) prelude-molds=(list term) cache=jcache prelude=(unit ifile)]
11693+ ^- jimports-result
11694+ =/ result=jimports-detailed-result
11695+ (resolve-jibb-imports-detailed imports externals mark-externals modules active prelude-values prelude-molds cache prelude)
11696+ ?: ?=(%| -.result) [%| message.p.result]
11697+ [%& p.result]
11698+++ resolve-jibb-imports-detailed
11699+ |= [imports=(list import) externals=iexternals mark-externals=imark-externals modules=jbundle active=(list path) prelude-values=(list term) prelude-molds=(list term) cache=jcache prelude=(unit ifile)]
11700+ ^- jimports-detailed-result
11701+ ?~ imports [%& [~ cache]]
11702+ ?. ?=(%jibb -.i.imports) $(imports t.imports)
11703+ =/ at=path (weld path.i.imports `path`~[%jibb])
11704+ ?: =(at /lib/jibb/internal/jibb)
11705+ [%| ['the prelude internal module is private' ~]]
11706+ ?: =(at /lib/jibb/primitives/jibb)
11707+ [%| ['the prelude primitive interface is private' ~]]
11708+ ?: (lien active |=(p=path =(p at)))
11709+ [%| [(crip "import cycle at {(spud at)}") ~]]
11710+ =/ found=jbundle (skim modules |=(m=jsource =(at at.m)))
11711+ ?~ found [%| [(crip "module source missing: {(spud at)}") ~]]
11712+ ?^ t.found [%| [(crip "duplicate module sources: {(spud at)}") ~]]
11713+ =/ cached=(unit ifile) (find-jibb-cache at cache)
11714+ =/ iface=jfile-detailed-result
11715+ ?^ cached
11716+ ?. =(at.u.cached at) [%| ['cached module identity needs unsupported inference' ~]]
11717+ ?~ graph.u.cached
11718+ :: A detached legacy interface has unknown evidence. Rebuild it
11719+ :: against the current graph, without retaining any stale entry.
11720+ =/ clean=jcache (skim cache |=(x=[at=path iface=ifile] !=(at.x at)))
11721+ (infer-jibb-file-detailed at source.i.found externals mark-externals modules [at active] prelude-values prelude-molds clean prelude)
11722+ ?. (request-graph-reusable u.cached source.i.found externals mark-externals modules active prelude-values prelude-molds prelude)
11723+ [%| ['cached module evidence needs unsupported inference' ~]]
11724+ [%& [u.cached cache]]
11725+ (infer-jibb-file-detailed at source.i.found externals mark-externals modules [at active] prelude-values prelude-molds cache prelude)
11726+ ?: ?=(%| -.iface) [%| p.iface]
11727+ =/ rest=jimports-detailed-result $(imports t.imports, cache cache.p.iface)
11728+ ?: ?=(%| -.rest) rest
11729+ [%& [[[face.i.imports iface.p.iface] resolved.p.rest] cache.p.rest]]
11730+::
11731+:: Provisional declaration extraction only; this does not derive asks,
11732+:: validate imported types, or claim that an API module has checked.
11733++$ iapi-path [at=span name=term segments=(list pseg) full=term diffs=(list term) scry=(unit (list pseg))]
11734+++ api-path-mark
11735+ |= [sh=shape marks=(list term)]
11736+ ^- (unit term)
11737+ ?. ?=(%ref -.sh) ~
11738+ ?. ?=([@ ~] names.sh) ~
11739+ ?. (unique-value-name i.names.sh marks) ~
11740+ `i.names.sh
11741+::
11742+++ api-path-diffs
11743+ |= [shapes=(list shape) marks=(list term) used=(list term)]
11744+ ^- (unit (list term))
11745+ ?~ shapes `~
11746+ =/ n=(unit term) (api-path-mark i.shapes marks)
11747+ ?~ n ~
11748+ ?: (lien used |=(x=term =(x u.n))) ~
11749+ =/ rest=(unit (list term)) $(shapes t.shapes, used [u.n used])
11750+ ?~ rest ~
11751+ `[u.n u.rest]
11752+::
11753+++ api-path-payload
11754+ |= [sh=shape marks=(list term)]
11755+ ^- (unit [full=term diffs=(list term)])
11756+ =/ direct=(unit term) (api-path-mark sh marks)
11757+ ?^ direct `[u.direct ~]
11758+ ?. ?=(%apply -.sh) ~
11759+ ?. =(~[%facts] ref.sh) ~
11760+ ?~ args.sh ~
11761+ ?~ t.args.sh ~
11762+ =/ full=(unit term) (api-path-mark i.args.sh marks)
11763+ ?~ full ~
11764+ =/ diffs=(unit (list term)) (api-path-diffs t.args.sh marks ~[u.full])
11765+ ?~ diffs ~
11766+ `[u.full u.diffs]
11767+::
11768++$ iapi-parameter [name=term aura=@ta at=span]
11769+++ api-path-parameters
11770+ |= [segments=(list pseg) seen=(list term)]
11771+ ^- (unit (list iapi-parameter))
11772+ ?~ segments `~
11773+ ?: ?=(%knot -.i.segments) $(segments t.segments)
11774+ =/ seg=pseg i.segments
11775+ ?. ?=(%typed -.seg) ~
11776+ ?: =(0 aura.seg) ~
11777+ ?: (lien seen |=(n=term =(n name.seg))) ~
11778+ =/ rest=(unit (list iapi-parameter)) $(segments t.segments, seen [name.seg seen])
11779+ ?~ rest ~
11780+ `[[name.seg aura.seg at.seg] u.rest]
11781+::
11782+++ api-scry-parameters-compatible
11783+ |= [scry=(list iapi-parameter) watch=(list iapi-parameter)]
11784+ ^- ?
11785+ ?~ scry &
11786+ ?. (lien watch |=(p=iapi-parameter &(=(name.p name.i.scry) =(aura.p aura.i.scry)))) |
11787+ $(scry t.scry)
11788+::
11789+++ api-path-one
11790+ |= [sh=shape marks=(list term)]
11791+ ^- (unit iapi-path)
11792+ ?. ?=(%cell -.sh) ~
11793+ =/ fs=(list field) fields.sh
11794+ ?~ fs ~
11795+ ?~ t.fs ~
11796+ ?~ t.t.fs ~
11797+ ?: (gth (lent fs) 4) ~
11798+ ?. ?=(%bare -.i.fs) ~
11799+ =/ tag=shape shape.i.fs
11800+ ?. ?=(%const -.tag) ~
11801+ ?. =(%term form.lit.tag) ~
11802+ =/ name=term val.lit.tag
11803+ ?. (jibb-face-name name) ~
11804+ ?. ?=(%bare -.i.t.fs) ~
11805+ =/ path-shape=shape shape.i.t.fs
11806+ ?. ?=(%path -.path-shape) ~
11807+ ?. ?=(%bare -.i.t.t.fs) ~
11808+ =/ payload=(unit [full=term diffs=(list term)]) (api-path-payload shape.i.t.t.fs marks)
11809+ ?~ payload ~
11810+ =/ scry=(unit (unit (list pseg)))
11811+ ?~ t.t.t.fs `~
11812+ =/ entry=field i.t.t.t.fs
11813+ ?. ?=(%face -.entry) ~
11814+ ?. =(%scry name.entry) ~
11815+ ?. ?=(%path -.shape.entry) ~
11816+ ``segs.shape.entry
11817+ ?~ scry ~
11818+ =/ params=(unit (list iapi-parameter)) (api-path-parameters segs.path-shape ~)
11819+ ?~ params ~
11820+ ?^ u.scry
11821+ =/ scry-params=(unit (list iapi-parameter)) (api-path-parameters u.u.scry ~)
11822+ ?~ scry-params ~
11823+ ?. (api-scry-parameters-compatible u.scry-params u.params) ~
11824+ `[at.sh name segs.path-shape full.u.payload diffs.u.payload u.scry]
11825+ `[at.sh name segs.path-shape full.u.payload diffs.u.payload u.scry]
11826+::
11827+++ api-path-many
11828+ |= [shapes=(list shape) marks=(list term) seen=(list term)]
11829+ ^- (unit (list iapi-path))
11830+ ?~ shapes `~
11831+ =/ one=(unit iapi-path) (api-path-one i.shapes marks)
11832+ ?~ one ~
11833+ ?: (lien seen |=(n=term =(n name.u.one))) ~
11834+ =/ rest=(unit (list iapi-path)) $(shapes t.shapes, seen [name.u.one seen])
11835+ ?~ rest ~
11836+ `[u.one u.rest]
11837+::
11838+++ api-path-declaration
11839+ |= [sh=shape marks=(list term)]
11840+ ^- (unit (list iapi-path))
11841+ ?: ?=(%union -.sh) (api-path-many cases.sh marks ~)
11842+ (api-path-many ~[sh] marks ~)
11843+::
11844+:: Derived gates share the value namespace. /% marks name molds; /- and
11845+:: /= also introduce faces that cannot be shadowed by a derived value.
11846+++ api-import-faces
11847+ |= imports=(list import)
11848+ ^- (list term)
11849+ ?~ imports ~
11850+ ?- -.i.imports
11851+ %mark $(imports t.imports)
11852+ %sur [name.i.imports $(imports t.imports)]
11853+ %jibb [face.i.imports $(imports t.imports)]
11854+ ==
11855+::
11856+++ api-derived-names-valid
11857+ |= [paths=(list iapi-path) poke-names=(list term) mod=module prelude-values=(list term)]
11858+ ^- ?
11859+ =/ path-names=(list term) (turn paths |=(p=iapi-path name.p))
11860+ =/ derived=(list term) (weld path-names poke-names)
11861+ ?: (lien derived |=(n=term =(n %proj))) |
11862+ =/ outer=(list term) (weld prelude-values (weld (global-value-names defs.mod) (api-import-faces imports.mod)))
11863+ (levy derived |=(n=term &((unique-value-name n derived) !(lien outer |=(x=term =(n x))))))
11864+::
11865+:: Analysis only. Successful external entries must be unchanged results
11866+:: produced for the declared marks; no request interface is produced.
11867++$ iapi-mark-type [name=term typ=itype]
11868++$ iapi-path-typed [path=iapi-path full=itype diffs=(list iapi-mark-type)]
11869+++ api-diff-types
11870+ |= [names=(list term) externals=imark-externals declared=(list term)]
11871+ ^- (unit (list iapi-mark-type))
11872+ ?~ names `~
11873+ =/ typ=(unit itype) (find-imported-mark i.names externals declared)
11874+ ?~ typ ~
11875+ =/ tail=(unit (list iapi-mark-type)) $(names t.names)
11876+ ?~ tail ~
11877+ `[[i.names u.typ] u.tail]
11878+::
11879+++ api-path-types
11880+ |= [paths=(list iapi-path) externals=imark-externals declared=(list term)]
11881+ ^- (unit (list iapi-path-typed))
11882+ ?~ paths `~
11883+ =/ full=(unit itype) (find-imported-mark full.i.paths externals declared)
11884+ ?~ full ~
11885+ =/ diffs=(unit (list iapi-mark-type)) (api-diff-types diffs.i.paths externals declared)
11886+ ?~ diffs ~
11887+ =/ tail=(unit (list iapi-path-typed)) $(paths t.paths)
11888+ ?~ tail ~
11889+ `[[i.paths u.full u.diffs] u.tail]
11890+::
11891+++ api-poke-mark-names
11892+ |= [pokes=(list def) declared=(list term)]
11893+ ^- (unit (list term))
11894+ ?~ pokes `~
11895+ ?^ t.pokes ~
11896+ =/ d=def i.pokes
11897+ ?. ?=(%mold -.d) ~
11898+ =/ sh=shape shape.d
11899+ ?: ?=(%union -.sh) (api-path-diffs cases.sh declared ~)
11900+ =/ name=(unit term) (api-path-mark sh declared)
11901+ ?~ name ~
11902+ `~[u.name]
11903+::
11904+++ api-path-analysis
11905+ |= [mod=module externals=imark-externals prelude-values=(list term) prelude-molds=(list term)]
11906+ ^- (unit (list iapi-path-typed))
11907+ ?: (lien defs.mod def-has-hole) ~
11908+ ?^ (duplicate-defs defs.mod) ~
11909+ =/ ds=(list def) defs.mod
11910+ =/ declarations=(list def)
11911+ (skim ds |=(d=def &(?=(%mold -.d) =(%paths name.d))))
11912+ ?. ?=([* ~] declarations) ~
11913+ =/ pokes=(list def)
11914+ (skim ds |=(d=def &(?=(%mold -.d) =(%poke name.d))))
11915+ ?: (gth (lent pokes) 1) ~
11916+ =/ ordinary=(list def)
11917+ (skim ds |=(d=def !&(?=(%mold -.d) |(=(%paths name.d) =(%poke name.d)))))
11918+ ?. (module-scope-valid mod(defs ordinary) prelude-values prelude-molds) ~
11919+ =/ declared=(list term) (collect-mark-imports imports.mod)
11920+ =/ poke-names=(unit (list term)) (api-poke-mark-names pokes declared)
11921+ ?~ poke-names ~
11922+ =/ decl=def i.declarations
11923+ ?> ?=(%mold -.decl)
11924+ =/ paths=(unit (list iapi-path)) (api-path-declaration shape.decl declared)
11925+ ?~ paths ~
11926+ ?. (api-derived-names-valid u.paths u.poke-names mod prelude-values) ~
11927+ (api-path-types u.paths externals declared)
11928+::
11929+:: Source/graph entry for path analysis only. The returned paths retain
11930+:: reader-derived mark types and import resolution has checked reachable
11931+:: Jibb dependencies. This is not an API interface or a module check.
11932+++ api-path-analysis-source
11933+ |= [file=path src=@t externals=iexternals marks=imark-externals modules=jbundle prepared=(unit iprelude)]
11934+ ^- (each (list iapi-path-typed) @t)
11935+ ?. ?=([%ui %api @ %jibb ~] file) [%| 'API path analysis requires /ui/api/<agent>.jibb']
11936+ =/ parsed (parse file src)
11937+ ?: ?=(%| -.parsed) [%| 'API path source does not parse']
11938+ =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
11939+ ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
11940+ ?~ prepared [%| 'API path analysis needs the prepared prelude']
11941+ =/ prelude=(unit ifile) `iface.u.prepared
11942+ =/ deps=jimports-result
11943+ (resolve-jibb-imports imports.p.parsed externals marks modules ~[file] values.u.prepared molds.u.prepared ~ prelude)
11944+ ?: ?=(%| -.deps) [%| p.deps]
11945+ =/ paths=(unit (list iapi-path-typed))
11946+ (api-path-analysis p.parsed marks values.u.prepared molds.u.prepared)
11947+ ?~ paths [%| 'API path declaration needs unsupported analysis']
11948+ [%& u.paths]
11949+::
11950+:: Analysis evidence retains the API source, the prepared interface, the
11951+:: caller's reader results and the resolved Jibb dependency cache alongside
11952+:: the typed path declarations. Reader results and prepared interfaces are
11953+:: trusted inputs: this does not verify their underlying Hoon source/version,
11954+:: create requests or check the provenance of arbitrary values.
11955++$ iapi-path-evidence
11956+ [at=path source=@t prepared=iprelude externals=iexternals marks=imark-externals dependencies=jcache paths=(list iapi-path-typed)]
11957+++ api-path-evidence-source
11958+ |= [file=path src=@t externals=iexternals marks=imark-externals modules=jbundle prepared=(unit iprelude)]
11959+ ^- (each iapi-path-evidence @t)
11960+ ?. ?=([%ui %api @ %jibb ~] file) [%| 'API path evidence requires /ui/api/<agent>.jibb']
11961+ =/ parsed (parse file src)
11962+ ?: ?=(%| -.parsed) [%| 'API path evidence source does not parse']
11963+ =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
11964+ ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
11965+ ?~ prepared [%| 'API path evidence needs the prepared prelude']
11966+ =/ public=ifile iface.u.prepared
11967+ =/ deps=jimports-result
11968+ (resolve-jibb-imports imports.p.parsed externals marks modules ~[file] values.u.prepared molds.u.prepared ~ `public)
11969+ ?: ?=(%| -.deps) [%| p.deps]
11970+ =/ paths=(unit (list iapi-path-typed))
11971+ (api-path-analysis p.parsed marks values.u.prepared molds.u.prepared)
11972+ ?~ paths [%| 'API path declaration needs unsupported analysis']
11973+ [%& [file src u.prepared externals marks cache.p.deps u.paths]]
11974+:: Graph-aware variant preserves the caller active stack and cache.
11975+++ api-path-evidence-graph
11976+ |= [file=path src=@t externals=iexternals marks=imark-externals modules=jbundle active=(list path) cache=jcache prepared=(unit iprelude)]
11977+ ^- (each iapi-path-evidence @t)
11978+ ?~ active [%| 'API analysis needs an active graph']
11979+ ?. =(i.active file) [%| 'API analysis active graph does not start at the source']
11980+ ?: (lien t.active |=(p=path =(p file))) [%| 'API analysis active graph contains a cycle']
11981+ ?. ?=([%ui %api @ %jibb ~] file) [%| 'API path evidence requires /ui/api/<agent>.jibb']
11982+ =/ parsed (parse file src)
11983+ ?: ?=(%| -.parsed) [%| 'API path evidence source does not parse']
11984+ =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
11985+ ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
11986+ ?~ prepared [%| 'API path evidence needs the prepared prelude']
11987+ =/ public=ifile iface.u.prepared
11988+ =/ deps=jimports-result
11989+ (resolve-jibb-imports imports.p.parsed externals marks modules active values.u.prepared molds.u.prepared cache `public)
11990+ ?: ?=(%| -.deps) [%| p.deps]
11991+ =/ paths=(unit (list iapi-path-typed))
11992+ (api-path-analysis p.parsed marks values.u.prepared molds.u.prepared)
11993+ ?~ paths [%| 'API path declaration needs unsupported analysis']
11994+ [%& [file src u.prepared externals marks cache.p.deps u.paths]]
11995+::
11996+:: This query classifies a unique path declaration only. Missing evidence
11997+:: or a nonunique name is unknown; it proves nothing about an ask value.
11998+:: Like prepared interfaces, the supplied evidence is a trusted host input.
11999+++ api-path-watchability
12000+ |= [evidence=(unit iapi-path-evidence) case-name=term]
12001+ ^- ?(%watchable %not-watchable %unknown)
12002+ ?~ evidence %unknown
12003+ =/ found=(list iapi-path-typed)
12004+ (skim paths.u.evidence |=(p=iapi-path-typed =(name.path.p case-name)))
12005+ ?. ?=([* ~] found) %unknown
12006+ ?~ scry.path.i.found %watchable
12007+ %not-watchable
12008+::
12009+:: These are declaration-derived request components, not a callable gate,
12010+:: an ask value, or proof of a value's provenance. Keep the exact trusted
12011+:: source/reader evidence until a later checked interface and lowerer can
12012+:: attach it to a generated request. No argument ordering is claimed here.
12013++$ iapi-request-parameter [name=term typ=itype at=span]
12014++$ iapi-request-parts
12015+ [evidence=iapi-path-evidence path=iapi-path-typed parameters=(list iapi-request-parameter) reply-sample=itype fold=(unit itype) watchability=?(%watchable %not-watchable)]
12016+++ api-request-parameter-types
12017+ |= params=(list iapi-parameter)
12018+ ^- (unit (list iapi-request-parameter))
12019+ ?~ params `~
12020+ =/ aura=@ta aura.i.params
12021+ ?. |(?=(?(%u %ud %ux %uv %t %ta %tas %p %da %dr) aura) =('tD' aura)) ~
12022+ =/ rest=(unit (list iapi-request-parameter)) $(params t.params)
12023+ ?~ rest ~
12024+ `[[name.i.params [%atom aura] at.i.params] u.rest]
12025+::
12026+:: A single diff's fold consumes the tagged diff and the previous full value.
12027+:: Multiple-diff unions need a checked union representation and remain open.
12028+++ api-request-fold-type
12029+ |= p=iapi-path-typed
12030+ ^- (unit (unit itype))
12031+ ?~ diffs.p `~
12032+ ?^ t.diffs.p ~
12033+ =/ d=iapi-mark-type i.diffs.p
12034+ =/ literal=lit [%term %tas name.d (crip ['%' (trip name.d)])]
12035+ =/ sample=itype [%cell [%cell [%const literal] typ.d] full.p]
12036+ ``[%fn sample full.p]
12037+::
12038+++ api-request-parts
12039+ |= [evidence=(unit iapi-path-evidence) case-name=term]
12040+ ^- (unit iapi-request-parts)
12041+ ?~ evidence ~
12042+ =/ found=(list iapi-path-typed)
12043+ (skim paths.u.evidence |=(p=iapi-path-typed =(name.path.p case-name)))
12044+ ?. ?=([* ~] found) ~
12045+ =/ p=iapi-path-typed i.found
12046+ =/ raw=(unit (list iapi-parameter)) (api-path-parameters segments.path.p ~)
12047+ ?~ raw ~
12048+ =/ params=(unit (list iapi-request-parameter)) (api-request-parameter-types u.raw)
12049+ ?~ params ~
12050+ =/ fold=(unit (unit itype)) (api-request-fold-type p)
12051+ ?~ fold ~
12052+ =/ watch=?(%watchable %not-watchable) ?~(scry.path.p %watchable %not-watchable)
12053+ `[u.evidence p u.params full.p u.fold watch]
12054+::
12055+:: Check ordinary API molds and values plus every declared mark type using
12056+:: the same trusted source, prepared prelude and reader inputs as path
12057+:: evidence. Keep elaborations with those inputs for a later interface.
12058+:: This is partial analysis: an unused /- core is not independently checked,
12059+:: definitions needing derived values remain unsupported, and no complete
12060+:: API, request or constructor is exported or given runtime behavior.
12061++$ iapi-support-evidence
12062+ [paths=iapi-path-evidence values=ienv molds=imold-types marks=(list iapi-mark-type) elaborations=(list iwidth-definition)]
12063+++ api-support-analysis-source
12064+ |= [file=path src=@t externals=iexternals marks=imark-externals modules=jbundle prepared=(unit iprelude)]
12065+ ^- (each iapi-support-evidence @t)
12066+ =/ path-result (api-path-evidence-source file src externals marks modules prepared)
12067+ ?: ?=(%| -.path-result) [%| p.path-result]
12068+ =/ evidence=iapi-path-evidence p.path-result
12069+ =/ parsed (parse file src)
12070+ ?: ?=(%| -.parsed) [%| 'API source does not parse']
12071+ =/ mod=module p.parsed
12072+ =/ ordinary=(list def)
12073+ (skim defs.mod |=(d=def !&(?=(%mold -.d) |(=(%paths name.d) =(%poke name.d)))))
12074+ =/ prep=iprelude prepared.evidence
12075+ ?. (module-scope-valid mod(defs ordinary) values.prep molds.prep) [%| 'API ordinary scope needs unsupported inference']
12076+ =/ vals=(list term) (global-value-names ordinary)
12077+ ?: (lien vals |=(n=term =(n %main))) [%| 'API module kind needs unsupported inference']
12078+ =/ declared=(list term) (collect-mark-imports imports.mod)
12079+ =/ mark-types=(unit (list iapi-mark-type)) (api-diff-types declared marks declared)
12080+ ?~ mark-types [%| 'API declared marks need unsupported inference']
12081+ =/ prelude=(unit ifile) `iface.prep
12082+ =/ deps=jimports-result
12083+ (resolve-jibb-imports imports.mod externals marks modules ~[file] values.prep molds.prep dependencies.evidence prelude)
12084+ ?: ?=(%| -.deps) [%| p.deps]
12085+ =/ molds=imolds (collect-simple-molds ordinary)
12086+ =/ globals=(list term) (weld values.prep (weld (import-binding-names imports.mod) vals))
12087+ =/ surs=(list term) (collect-sur-imports imports.mod)
12088+ =/ reserved=(list term) (weld molds.prep (turn resolved.p.deps |=(j=[face=term interface=ifile] face.j)))
12089+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
12090+ =/ state=istate [0 ~ ~ ~ molds globals externals surs marks declared resolved.p.deps reserved ~ ~ ~ | file top prelude ~ 256 ~ ~ ~ ~ ~ ~]
12091+ =/ mts=(each imold-types @t) (module-mold-types molds state)
12092+ ?: ?=(%| -.mts) [%| p.mts]
12093+ =/ resolution=iresolved (resolve-groups ordinary molds globals externals surs marks declared resolved.p.deps reserved file prelude)
12094+ ?. (module-values-complete ordinary env.resolution) [%| 'API ordinary definitions need unsupported inference']
12095+ [%& [evidence env.resolution p.mts u.mark-types artifacts.resolution]]
12096+:: Preserve the same graph context through supporting definitions.
12097+++ api-support-analysis-graph
12098+ |= [file=path src=@t externals=iexternals marks=imark-externals modules=jbundle active=(list path) cache=jcache prepared=(unit iprelude)]
12099+ ^- (each iapi-support-evidence @t)
12100+ =/ path-result (api-path-evidence-graph file src externals marks modules active cache prepared)
12101+ ?: ?=(%| -.path-result) [%| p.path-result]
12102+ =/ evidence=iapi-path-evidence p.path-result
12103+ =/ parsed (parse file src)
12104+ ?: ?=(%| -.parsed) [%| 'API source does not parse']
12105+ =/ mod=module p.parsed
12106+ =/ ordinary=(list def)
12107+ (skim defs.mod |=(d=def !&(?=(%mold -.d) |(=(%paths name.d) =(%poke name.d)))))
12108+ =/ prep=iprelude prepared.evidence
12109+ ?. (module-scope-valid mod(defs ordinary) values.prep molds.prep) [%| 'API ordinary scope needs unsupported inference']
12110+ =/ vals=(list term) (global-value-names ordinary)
12111+ ?: (lien vals |=(n=term =(n %main))) [%| 'API module kind needs unsupported inference']
12112+ =/ declared=(list term) (collect-mark-imports imports.mod)
12113+ =/ mark-types=(unit (list iapi-mark-type)) (api-diff-types declared marks declared)
12114+ ?~ mark-types [%| 'API declared marks need unsupported inference']
12115+ =/ prelude=(unit ifile) `iface.prep
12116+ =/ deps=jimports-result
12117+ (resolve-jibb-imports imports.mod externals marks modules active values.prep molds.prep dependencies.evidence prelude)
12118+ ?: ?=(%| -.deps) [%| p.deps]
12119+ =/ molds=imolds (collect-simple-molds ordinary)
12120+ =/ globals=(list term) (weld values.prep (weld (import-binding-names imports.mod) vals))
12121+ =/ surs=(list term) (collect-sur-imports imports.mod)
12122+ =/ reserved=(list term) (weld molds.prep (turn resolved.p.deps |=(j=[face=term interface=ifile] face.j)))
12123+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
12124+ =/ state=istate [0 ~ ~ ~ molds globals externals surs marks declared resolved.p.deps reserved ~ ~ ~ | file top prelude ~ 256 ~ ~ ~ ~ ~ ~]
12125+ =/ mts=(each imold-types @t) (module-mold-types molds state)
12126+ ?: ?=(%| -.mts) [%| p.mts]
12127+ =/ resolution=iresolved (resolve-groups ordinary molds globals externals surs marks declared resolved.p.deps reserved file prelude)
12128+ ?. (module-values-complete ordinary env.resolution) [%| 'API ordinary definitions need unsupported inference']
12129+ [%& [evidence env.resolution p.mts u.mark-types artifacts.resolution]]
12130+::
12131+:: Type-analysis artifact for one plain request. The resolver may publish
12132+:: its interface only together with trusted source and reader evidence.
12133+:: No lowering or runtime validator exists.
12134+:: Value watchability remains unproved even for a watchable declaration.
12135++$ ione-request-interface
12136+ [support=iapi-support-evidence parts=iapi-request-parts iface=ifile]
12137+++ request-compatible-ask
12138+ |= prelude=iprelude
12139+ ^- (unit ischeme)
12140+ =/ public=ifile iface.prelude
12141+ ?. =(at.public /lib/jibb/prelude/jibb) ~
12142+ =/ ask=(unit ischeme) (find-jibb-mold %ask public)
12143+ ?~ ask ~
12144+ ?. ?=([@ ~] vars.u.ask) ~
12145+ ?. ?=(%union -.typ.u.ask) ~
12146+ ?. =(origin.typ.u.ask `[/lib/jibb/internal/jibb %ask]) ~
12147+ ?. (identity-union-parameters vars.u.ask args.typ.u.ask) ~
12148+ =/ m=@ud i.vars.u.ask
12149+ ?: (itype-var-is-atom m typ.u.ask) ~
12150+ ?. (levy (itype-vars typ.u.ask) |=(n=@ud =(n m))) ~
12151+ ?: (itype-has-tag typ.u.ask) ~
12152+ =/ private=(list iwidth-dependency)
12153+ (skim dependencies.public |=(d=iwidth-dependency =(at.d /lib/jibb/internal/jibb)))
12154+ ?. ?=([* ~] private) ~
12155+ ?~ source.i.private ~
12156+ =/ path=(unit ischeme) (find-jibb-mold %path public)
12157+ ?~ path ~
12158+ ?^ vars.u.path ~
12159+ =/ path-type=itype [%collection %list ~[[%atom %ta]]]
12160+ ?. =(typ.u.path path-type) ~
12161+ =/ unit-template=(unit ischeme) (find-jibb-mold %unit public)
12162+ ?~ unit-template ~
12163+ ?. (standard-unit-template u.unit-template /lib/jibb/prelude/jibb) ~
12164+ =/ state-unit=(unit itype) (template-apply u.unit-template ~[[%noun ~]])
12165+ ?~ state-unit ~
12166+ =/ path-unit=(unit itype) (template-apply u.unit-template ~[path-type])
12167+ ?~ path-unit ~
12168+ =/ output=itype [%cell [%face %state [%noun ~]] [%face %message [%var m]]]
12169+ =/ agent-input=itype [%cell [%face %mark [%atom %tas]] [%cell [%face %state u.state-unit] [%face %fact [%noun ~]]]]
12170+ =/ store-input=itype [%cell [%face %state u.state-unit] [%face %fact [%noun ~]]]
12171+ =/ pure-case=itype [%cell [%const [%term %tas %pure '%pure']] [%face %value [%var m]]]
12172+ =/ agent-case=itype
12173+ [%cell [%const [%term %tas %agent '%agent']] [%cell [%face %api [%atom %t]] [%cell [%face %case [%atom %tas]] [%cell [%face %agent [%atom %tas]] [%cell [%face %path path-type] [%cell [%face %scry u.path-unit] [%face %receive [%fn agent-input output]]]]]]]]
12174+ =/ store-case=itype
12175+ [%cell [%const [%term %tas %store '%store']] [%cell [%face %module [%atom %t]] [%cell [%face %name [%atom %tas]] [%face %receive [%fn store-input output]]]]]
12176+ ?. =(cases.typ.u.ask ~[pure-case agent-case store-case]) ~
12177+ ask
12178+::
12179+:: The first supported standalone API has exactly one mark import and one
12180+:: plain path declaration, with no other definitions or imports. No partial
12181+:: success is published when source, schema, or a required mold is unknown.
12182+++ one-request-interface-source
12183+ |= [file=path src=@t externals=iexternals marks=imark-externals modules=jbundle prepared=(unit iprelude)]
12184+ ^- (each ione-request-interface @t)
12185+ =/ out (api-support-analysis-source file src externals marks modules prepared)
12186+ ?: ?=(%| -.out) [%| p.out]
12187+ =/ support=iapi-support-evidence p.out
12188+ =/ ev=iapi-path-evidence paths.support
12189+ =/ parsed (parse file src)
12190+ ?: ?=(%| -.parsed) [%| 'request source does not parse']
12191+ =/ mod=module p.parsed
12192+ ?. ?=(?([[%mark *] ~] [[%mark *] [%mark *] ~]) imports.mod) [%| 'request imports need unsupported inference']
12193+ ?. ?=([[%mold *] ~] defs.mod) [%| 'request definitions need unsupported inference']
12194+ ?. =(%paths name.i.defs.mod) [%| 'request declaration needs unsupported inference']
12195+ ?. ?=([* ~] paths.ev) [%| 'request count needs unsupported inference']
12196+ =/ p=iapi-path-typed i.paths.ev
12197+ =/ parts=(unit iapi-request-parts) (api-request-parts `ev name.path.p)
12198+ ?~ parts [%| 'request components need unsupported inference']
12199+ ?. ?=(?(~ [* ~]) parameters.u.parts) [%| 'request parameters need unsupported inference']
12200+ ?: &(?=(^ fold.u.parts) ?=(^ parameters.u.parts)) [%| 'request parameter and fold need unsupported inference']
12201+ ?^ scry.path.p [%| 'request scry needs unsupported inference']
12202+ =/ valid-marks=?
12203+ ?~ fold.u.parts ?=([* ~] marks.support)
12204+ ?=([* [* ~]] marks.support)
12205+ ?. valid-marks [%| 'request marks need unsupported inference']
12206+ =/ fold-open=?
12207+ ?~ fold.u.parts |
12208+ |(?=(^ (itype-vars u.fold.u.parts)) (itype-has-tag u.fold.u.parts))
12209+ ?: fold-open [%| 'request fold needs unsupported inference']
12210+ ?^ (itype-vars reply-sample.u.parts) [%| 'request payload needs unsupported inference']
12211+ ?: (itype-has-tag reply-sample.u.parts) [%| 'request payload needs unsupported inference']
12212+ =/ ask=(unit ischeme) (request-compatible-ask prepared.ev)
12213+ ?~ ask [%| 'request ask needs unsupported inference']
12214+ =/ result=(unit itype) (template-apply u.ask ~[[%var 0]])
12215+ ?~ result [%| 'request ask needs unsupported inference']
12216+ =/ callback=itype [%fn reply-sample.u.parts [%var 0]]
12217+ =/ sample=itype
12218+ ?^ fold.u.parts [%cell callback u.fold.u.parts]
12219+ ?~ parameters.u.parts callback
12220+ [%cell typ.i.parameters.u.parts callback]
12221+ =/ scheme=ischeme [[%fn sample u.result] ~[0]]
12222+ =/ exports=imold-types
12223+ (turn marks.support |=(m=iapi-mark-type [name.m [typ.m ~]]))
12224+ =/ prelude=iprelude prepared.ev
12225+ =/ public=ifile iface.prelude
12226+ ?~ source.public [%| 'request prelude source needs unsupported inference']
12227+ =/ private=(list iwidth-dependency)
12228+ (skim dependencies.public |=(d=iwidth-dependency =(at.d /lib/jibb/internal/jibb)))
12229+ ?. ?=([* ~] private) [%| 'request internal source needs unsupported inference']
12230+ ?~ source.i.private [%| 'request internal source needs unsupported inference']
12231+ =/ req=irequest-evidence
12232+ [file name.path.p p src u.source.public u.source.i.private values.prelude molds.prelude externals marks]
12233+ =/ interface=ifile [~[[name.path.p scheme]] exports file ~ ~ ~ `src `[(silt `(list path)`~[file]) ~[req] modules `public values.prelude molds.prelude externals marks]]
12234+ [%& [support u.parts interface]]
12235+:: Graph-aware request artifact; resolver use remains type-only.
12236+++ one-request-interface-graph
12237+ |= [file=path src=@t externals=iexternals marks=imark-externals modules=jbundle active=(list path) cache=jcache prepared=(unit iprelude)]
12238+ ^- (each ione-request-interface @t)
12239+ =/ out (api-support-analysis-graph file src externals marks modules active cache prepared)
12240+ ?: ?=(%| -.out) [%| p.out]
12241+ =/ support=iapi-support-evidence p.out
12242+ =/ ev=iapi-path-evidence paths.support
12243+ =/ parsed (parse file src)
12244+ ?: ?=(%| -.parsed) [%| 'request source does not parse']
12245+ =/ mod=module p.parsed
12246+ ?. ?=(?([[%mark *] ~] [[%mark *] [%mark *] ~]) imports.mod) [%| 'request imports need unsupported inference']
12247+ ?. ?=([[%mold *] ~] defs.mod) [%| 'request definitions need unsupported inference']
12248+ ?. =(%paths name.i.defs.mod) [%| 'request declaration needs unsupported inference']
12249+ ?. ?=([* ~] paths.ev) [%| 'request count needs unsupported inference']
12250+ =/ p=iapi-path-typed i.paths.ev
12251+ =/ parts=(unit iapi-request-parts) (api-request-parts `ev name.path.p)
12252+ ?~ parts [%| 'request components need unsupported inference']
12253+ ?. ?=(?(~ [* ~]) parameters.u.parts) [%| 'request parameters need unsupported inference']
12254+ ?: &(?=(^ fold.u.parts) ?=(^ parameters.u.parts)) [%| 'request parameter and fold need unsupported inference']
12255+ ?^ scry.path.p [%| 'request scry needs unsupported inference']
12256+ =/ valid-marks=?
12257+ ?~ fold.u.parts ?=([* ~] marks.support)
12258+ ?=([* [* ~]] marks.support)
12259+ ?. valid-marks [%| 'request marks need unsupported inference']
12260+ =/ fold-open=?
12261+ ?~ fold.u.parts |
12262+ |(?=(^ (itype-vars u.fold.u.parts)) (itype-has-tag u.fold.u.parts))
12263+ ?: fold-open [%| 'request fold needs unsupported inference']
12264+ ?^ (itype-vars reply-sample.u.parts) [%| 'request payload needs unsupported inference']
12265+ ?: (itype-has-tag reply-sample.u.parts) [%| 'request payload needs unsupported inference']
12266+ =/ ask=(unit ischeme) (request-compatible-ask prepared.ev)
12267+ ?~ ask [%| 'request ask needs unsupported inference']
12268+ =/ result=(unit itype) (template-apply u.ask ~[[%var 0]])
12269+ ?~ result [%| 'request ask needs unsupported inference']
12270+ =/ callback=itype [%fn reply-sample.u.parts [%var 0]]
12271+ =/ sample=itype
12272+ ?^ fold.u.parts [%cell callback u.fold.u.parts]
12273+ ?~ parameters.u.parts callback
12274+ [%cell typ.i.parameters.u.parts callback]
12275+ =/ scheme=ischeme [[%fn sample u.result] ~[0]]
12276+ =/ exports=imold-types
12277+ (turn marks.support |=(m=iapi-mark-type [name.m [typ.m ~]]))
12278+ =/ prelude=iprelude prepared.ev
12279+ =/ public=ifile iface.prelude
12280+ ?~ source.public [%| 'request prelude source needs unsupported inference']
12281+ =/ private=(list iwidth-dependency)
12282+ (skim dependencies.public |=(d=iwidth-dependency =(at.d /lib/jibb/internal/jibb)))
12283+ ?. ?=([* ~] private) [%| 'request internal source needs unsupported inference']
12284+ ?~ source.i.private [%| 'request internal source needs unsupported inference']
12285+ =/ req=irequest-evidence
12286+ [file name.path.p p src u.source.public u.source.i.private values.prelude molds.prelude externals marks]
12287+ =/ interface=ifile [~[[name.path.p scheme]] exports file ~ ~ ~ `src `[(silt `(list path)`~[file]) ~[req] modules `public values.prelude molds.prelude externals marks]]
12288+ [%& [support u.parts interface]]
12289+::
12290+++ api-mark-exports
12291+ |= [marks=(list term) all=(list term) externals=imark-externals]
12292+ ^- imold-types
12293+ ?~ marks ~
12294+ =/ t=(unit itype) (find-imported-mark i.marks externals all)
12295+ ?~ t $(marks t.marks)
12296+ [[i.marks [u.t ~]] $(marks t.marks)]
12297+::
12298+:: Experimental direct poke-only API. Unsupported API declarations fail
12299+:: as a whole; supplied mark reader results retain their existing boundary.
12300+++ api-poke-interface
12301+ |= [at=path mod=module mark-externals=imark-externals prelude-values=(list term) prelude-molds=(list term) prelude=(unit ifile)]
12302+ ^- (unit ifile)
12303+ ?: (lien defs.mod def-has-hole) ~
12304+ ?. ?=([%ui %api @ %jibb ~] at) ~
12305+ ?^ (duplicate-defs defs.mod) ~
12306+ ?~ prelude ~
12307+ ?. =(at.u.prelude /lib/jibb/prelude/jibb) ~
12308+ =/ poke=(unit ischeme) (find-jibb-mold %poke u.prelude)
12309+ ?~ poke ~
12310+ ?. ?=(%union -.typ.u.poke) ~
12311+ ?^ vars.u.poke ~
12312+ =/ compatible=?
12313+ %+ lien cases.typ.u.poke
12314+ |= c=itype
12315+ ?=([%cell [%const [%term %tas %agent *]] [%cell [%face %agent [%atom %tas]] [%cell [%face %mark [%atom %tas]] [%face %payload [%noun ~]]]]] c)
12316+ ?. compatible ~
12317+ ?. (module-scope-valid mod(defs ~) prelude-values prelude-molds) ~
12318+ ?. (levy imports.mod |=(i=import ?=(%mark -.i))) ~
12319+ =/ marks=(list term) (collect-mark-imports imports.mod)
12320+ ?. ?=([@ ~] marks) ~
12321+ =/ ds=(list def) defs.mod
12322+ ?. ?=([[%mold *] ~] ds) ~
12323+ ?. =(%poke name.i.ds) ~
12324+ =/ sh=shape shape.i.ds
12325+ ?. ?=([%ref *] sh) ~
12326+ ?. ?=([@ ~] names.sh) ~
12327+ =/ n=term i.names.sh
12328+ ?. (unique-value-name n marks) ~
12329+ ?: |((lien prelude-values |=(x=term =(n x))) (lien prelude-molds |=(x=term =(n x)))) ~
12330+ =/ mark=(unit itype) (find-imported-mark n mark-externals marks)
12331+ ?~ mark ~
12332+ =/ sc=ischeme [[%fn u.mark typ.u.poke] ~]
12333+ `[~[[n sc]] (api-mark-exports marks marks mark-externals) at ~[[n i.t.t.at n]] ~ ~ ~ ~]
12334+::
12335+:: Source-proven ordinary helpers validate each selected /sur dependency.
12336+:: Unused or less direct cores remain unsupported by this first interface.
12337+++ api-sur-covered
12338+ |= [surs=(list term) defs=(list def) externals=iexternals all=(list term)]
12339+ ^- ?
12340+ ?~ surs &
12341+ =/ found=(list def)
12342+ %+ skim defs
12343+ |= d=def
12344+ ?. ?=(%mold -.d) |
12345+ ?. ?=(%ref -.shape.d) |
12346+ ?. ?=([@ [@ ~]] names.shape.d) |
12347+ =(i.t.names.shape.d i.surs)
12348+ ?~ found |
12349+ =/ selected=def i.found
12350+ ?. ?=(%mold -.selected) |
12351+ =/ sh=shape shape.selected
12352+ ?. ?=(%ref -.sh) |
12353+ ?. ?=([@ [@ ~]] names.sh) |
12354+ =/ checked=(unit itype) (find-imported-mold i.surs i.names.sh externals all)
12355+ ?~ checked |
12356+ $(surs t.surs)
12357+::
12358++$ imulti-request-gates [values=ienv requests=(list irequest-evidence)]
12359+++ api-request-gates
12360+ |= [paths=(list iapi-path-typed) ev=iapi-path-evidence ask=ischeme file=path src=@t public=@t internal=@t externals=iexternals marks=imark-externals fuel=@ud]
12361+ ^- (unit imulti-request-gates)
12362+ ?~ paths `[~ ~]
12363+ ?: =(0 fuel) ~
12364+ =/ p=iapi-path-typed i.paths
12365+ =/ parts=(unit iapi-request-parts) (api-request-parts `ev name.path.p)
12366+ ?~ parts ~
12367+ ?. ?=(?(~ [* ~]) parameters.u.parts) ~
12368+ ?: &(?=(^ fold.u.parts) ?=(^ parameters.u.parts)) ~
12369+ ?^ scry.path.p ~
12370+ ?^ (itype-vars reply-sample.u.parts) ~
12371+ ?: (itype-has-tag reply-sample.u.parts) ~
12372+ =/ open-fold=?
12373+ ?~ fold.u.parts |
12374+ |(?=(^ (itype-vars u.fold.u.parts)) (itype-has-tag u.fold.u.parts))
12375+ ?: open-fold ~
12376+ =/ result=(unit itype) (template-apply ask ~[[%var 0]])
12377+ ?~ result ~
12378+ =/ callback=itype [%fn reply-sample.u.parts [%var 0]]
12379+ =/ sample=itype
12380+ ?^ fold.u.parts [%cell callback u.fold.u.parts]
12381+ ?~ parameters.u.parts callback
12382+ [%cell typ.i.parameters.u.parts callback]
12383+ =/ scheme=ischeme [[%fn sample u.result] ~[0]]
12384+ =/ prep=iprelude prepared.ev
12385+ =/ req=irequest-evidence
12386+ [file name.path.p p src public internal values.prep molds.prep externals marks]
12387+ =/ rest=(unit imulti-request-gates)
12388+ $(paths t.paths, fuel (dec fuel))
12389+ ?~ rest ~
12390+ `[[[name.path.p scheme] values.u.rest] [req requests.u.rest]]
12391+::
12392+++ api-poke-from-checked
12393+ |= [file=path mod=module marks=imark-externals values=(list term) molds=(list term) prelude=(unit ifile)]
12394+ ^- (unit [values=ienv derived=(list iderived)])
12395+ =/ pokes=(list def)
12396+ (skim defs.mod |=(d=def &(?=(%mold -.d) =(%poke name.d))))
12397+ ?~ pokes `[~ ~]
12398+ ?. ?=([* ~] pokes) ~
12399+ =/ declared=(list term) (collect-mark-imports imports.mod)
12400+ =/ ns=(unit (list term)) (api-poke-mark-names pokes declared)
12401+ ?~ ns ~
12402+ ?. ?=([@ ~] u.ns) ~
12403+ =/ matching=(list import)
12404+ %+ skim imports.mod
12405+ |= i=import
12406+ ?. ?=(%mark -.i) |
12407+ =(mark.i i.u.ns)
12408+ ?. ?=([* ~] matching) ~
12409+ =/ checked=(unit ifile)
12410+ (api-poke-interface file mod(defs pokes, imports matching) marks values molds prelude)
12411+ ?~ checked ~
12412+ `[values.u.checked derived.u.checked]
12413+::
12414+:: The partial interface is published atomically: all paths, ordinary
12415+:: source definitions, declared marks and the poke must check. Unselected
12416+:: /sur bindings, runtime validation and value watchability remain unproved.
12417+++ multi-request-interface-graph
12418+ |= [file=path src=@t externals=iexternals marks=imark-externals modules=jbundle active=(list path) cache=jcache prepared=(unit iprelude)]
12419+ ^- (each [iface=ifile cache=jcache] @t)
12420+ =/ out (api-support-analysis-graph file src externals marks modules active cache prepared)
12421+ ?: ?=(%| -.out) [%| p.out]
12422+ =/ support=iapi-support-evidence p.out
12423+ =/ ev=iapi-path-evidence paths.support
12424+ =/ parsed (parse file src)
12425+ ?: ?=(%| -.parsed) [%| 'request source does not parse']
12426+ =/ mod=module p.parsed
12427+ ?. (levy imports.mod |=(i=import ?=(?(%mark %sur) -.i)))
12428+ [%| 'request imports need unsupported inference']
12429+ =/ surs=(list term) (collect-sur-imports imports.mod)
12430+ ?. (api-sur-covered surs defs.mod externals surs)
12431+ [%| 'API source dependency needs unsupported inference']
12432+ ?~ paths.ev [%| 'request count needs unsupported inference']
12433+ =/ ask=(unit ischeme) (request-compatible-ask prepared.ev)
12434+ ?~ ask [%| 'request ask needs unsupported inference']
12435+ =/ prep=iprelude prepared.ev
12436+ =/ public=ifile iface.prep
12437+ ?~ source.public [%| 'request prelude source needs unsupported inference']
12438+ =/ private=(list iwidth-dependency)
12439+ (skim dependencies.public |=(d=iwidth-dependency =(at.d /lib/jibb/internal/jibb)))
12440+ ?. ?=([* ~] private) [%| 'request internal source needs unsupported inference']
12441+ ?~ source.i.private [%| 'request internal source needs unsupported inference']
12442+ =/ gates=(unit imulti-request-gates)
12443+ (api-request-gates paths.ev ev u.ask file src u.source.public u.source.i.private externals marks 256)
12444+ ?~ gates [%| 'request paths need unsupported inference']
12445+ =/ poke=(unit [values=ienv derived=(list iderived)])
12446+ (api-poke-from-checked file mod marks values.prep molds.prep `public)
12447+ ?~ poke [%| 'API poke needs unsupported inference']
12448+ =/ mark-molds=imold-types
12449+ (turn marks.support |=(m=iapi-mark-type [name.m [typ.m ~]]))
12450+ =/ exports=imold-types (weld mark-molds molds.support)
12451+ =/ names=(list term) (turn exports |=(m=[name=term template=ischeme] name.m))
12452+ ?. (levy names |=(n=term (unique-value-name n names)))
12453+ [%| 'API exported molds need unsupported inference']
12454+ =/ env=ienv (weld values.u.gates (weld values.u.poke values.support))
12455+ =/ graph=irequest-graph
12456+ [(silt `(list path)`~[file]) requests.u.gates modules `public values.prep molds.prep externals marks]
12457+ =/ iface=ifile
12458+ [env exports file derived.u.poke elaborations.support ~ `src `graph]
12459+ [%& [iface dependencies.ev]]
12460+::
12461+:: A checked program main is only the direct four-component source call.
12462+:: Grouping is transparent, but aliases, qualified wings and other module
12463+:: kinds remain outside this slice.
12464+++ program-main-def
12465+ |= ds=(list def)
12466+ ^- (unit def)
12467+ ?~ ds ~
12468+ ?: &(?=(%value -.i.ds) =(%main name.i.ds)) `i.ds
12469+ $(ds t.ds)
12470+::
12471+++ program-main-wing
12472+ |= e=expr
12473+ ^- (unit term)
12474+ ?: ?=(%group -.e) $(e inner.e)
12475+ ?. ?=(%wing -.e) ~
12476+ ?. ?=([@ ~] names.e) ~
12477+ `i.names.e
12478+::
12479+++ program-main-args
12480+ |= d=def
12481+ ^- (unit (list expr))
12482+ ?. ?=(%value -.d) ~
12483+ |-
12484+ ?: ?=(%group -.val.d) $(val.d inner.val.d)
12485+ ?. ?=(%call -.val.d) ~
12486+ =/ head=(unit term) (program-main-wing head.val.d)
12487+ ?~ head ~
12488+ ?. =(%program u.head) ~
12489+ ?. ?=([* * * * ~] args.val.d) ~
12490+ `args.val.d
12491+::
12492+++ program-main-parts
12493+ |= d=def
12494+ ^- (unit [init=term update=term view=term subs=term])
12495+ ?. ?=(%value -.d) ~
12496+ |-
12497+ ?: ?=(%group -.val.d) $(val.d inner.val.d)
12498+ ?. ?=(%call -.val.d) ~
12499+ =/ head=(unit term) (program-main-wing head.val.d)
12500+ ?~ head ~
12501+ ?. =(%program u.head) ~
12502+ ?. ?=([* * * * ~] args.val.d) ~
12503+ =/ args=(list expr) args.val.d
12504+ ?> ?=([* * * * ~] args)
12505+ =/ init=(unit term) (program-main-wing i.args)
12506+ =/ update=(unit term) (program-main-wing i.t.args)
12507+ =/ view=(unit term) (program-main-wing i.t.t.args)
12508+ =/ subs=(unit term) (program-main-wing i.t.t.t.args)
12509+ ?~ init ~
12510+ ?~ update ~
12511+ ?~ view ~
12512+ ?~ subs ~
12513+ `[u.init u.update u.view u.subs]
12514+::
12515+++ program-empty-null
12516+ |= e=expr
12517+ ^- ?
12518+ ?- -.e
12519+ %lit =(%null form.lit.e)
12520+ %cast $(e val.e)
12521+ %group $(e inner.e)
12522+ %body ?~(defs.e $(e final.e) |)
12523+ * |
12524+ ==
12525+::
12526+++ program-subs-empty
12527+ |= d=def
12528+ ^- ?
12529+ ?. ?=(%value -.d) |
12530+ ?- -.val.d
12531+ %gate (program-empty-null body.val.d)
12532+ %gate-wide (program-empty-null body.val.d)
12533+ * |
12534+ ==
12535+::
12536+++ program-transparent
12537+ |= e=expr
12538+ ^- expr
12539+ ?- -.e
12540+ %group $(e inner.e)
12541+ %cast $(e val.e)
12542+ %body ?~(defs.e $(e final.e) e)
12543+ * e
12544+ ==
12545+++ program-init-tuple-null
12546+ |= d=def
12547+ ^- ?
12548+ ?. ?=(%value -.d) |
12549+ ?. |(?=(%gate -.val.d) ?=(%gate-wide -.val.d)) |
12550+ =/ body=expr
12551+ ?- -.val.d
12552+ %gate body.val.d
12553+ %gate-wide body.val.d
12554+ * !!
12555+ ==
12556+ =. body (program-transparent body)
12557+ ?. ?=(%tuple -.body) |
12558+ ?~ items.body |
12559+ (program-empty-null val:(rear items.body))
12560+::
12561+:: Recover only the update of an already recognized direct program main.
12562+:: Its written sample determines the message/model relationship; the canonical
12563+:: cmd and list molds determine the result context. Every candidate is checked
12564+:: against the complete program call before an ordinary update/main retry.
12565+++ program-update-context
12566+ |= [main=def parts=[init=term update=term view=term subs=term] ds=(list def) resolution=iresolved initial=istate]
12567+ ^- (unit iresolved)
12568+ =/ env=ienv env.resolution
12569+ ?^ (ienv-lookup %main env) ~
12570+ ?^ (ienv-lookup update.parts env) ~
12571+ =/ init=(unit ischeme) (ienv-lookup init.parts env)
12572+ =/ view=(unit ischeme) (ienv-lookup view.parts env)
12573+ =/ subs=(unit ischeme) (ienv-lookup subs.parts env)
12574+ ?~ init ~
12575+ ?~ view ~
12576+ ?~ subs ~
12577+ =/ updates=(list def)
12578+ (skim ds |=(d=def &(?=(%value -.d) =(update.parts name.d))))
12579+ ?. ?=([* ~] updates) ~
12580+ =/ update-def=def i.updates
12581+ ?> ?=(%value -.update-def)
12582+ =/ written-update=(unit sample) (direct-gate-sample update-def)
12583+ ?~ written-update ~
12584+ ?. ?=(%cell -.u.written-update) ~
12585+ ?. ?=([* * ~] items.u.written-update) ~
12586+ =/ args=(unit (list expr)) (program-main-args main)
12587+ ?~ args ~
12588+ ?~ prelude.initial ~
12589+ =/ program=(unit ischeme) (ienv-lookup %program values.u.prelude.initial)
12590+ ?~ program ~
12591+ =/ command=(unit ischeme) (find-jibb-mold %cmd u.prelude.initial)
12592+ =/ list-template=(unit ischeme) (find-jibb-mold %list u.prelude.initial)
12593+ ?~ command ~
12594+ ?~ list-template ~
12595+ =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude.initial)
12596+ ?~ heads ~
12597+ =/ written=(unit def) (~(get by gates.u.heads) %program)
12598+ ?~ written ~
12599+ =/ written-sample=(unit sample) (direct-gate-sample u.written)
12600+ ?~ written-sample ~
12601+ ?. ?=(%cell -.u.written-sample) ~
12602+ ?. ?=([* * * * ~] items.u.written-sample) ~
12603+ =/ checked=(map term def)
12604+ (~(put by (direct-checked-gates ds env)) update.parts update-def)
12605+ =/ templates=ienv
12606+ (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
12607+ =/ scanned=(unit dgscan)
12608+ (dg-all-env-ids (weld env (weld values.u.prelude.initial templates)) 32.768 ~)
12609+ ?~ scanned ~
12610+ =. next.initial (dg-next-id ids.u.scanned 0)
12611+ =/ update-state=istate (reserve-def-caps val.update-def initial)
12612+ =/ sam=isample-result (infer-sample u.written-update env update-state)
12613+ ?: ?=(%| -.sam) ~
12614+ =/ actual-sample=itype (itype-normalize typ.p.sam sub.state.p.sam)
12615+ ?. ?=(%cell -.actual-sample) ~
12616+ =/ message=(unit itype)
12617+ (direct-slot-body hed.actual-sample (direct-sample-name i.items.u.written-update))
12618+ =/ model=(unit itype)
12619+ (direct-slot-body tal.actual-sample (direct-sample-name i.t.items.u.written-update))
12620+ ?~ message ~
12621+ ?~ model ~
12622+ =/ cmd=(unit itype) (template-apply u.command ~[u.message])
12623+ ?~ cmd ~
12624+ =/ cmds=(unit itype) (template-apply u.list-template ~[u.cmd])
12625+ ?~ cmds ~
12626+ =/ product=itype [%cell u.model u.cmds]
12627+ =/ instance=[typ=itype state=istate] (instantiate-scheme u.program state.p.sam)
12628+ ?. ?=(%fn -.typ.instance) ~
12629+ ?. ?=(%cell -.sample.typ.instance) ~
12630+ ?. ?=(%cell -.tal.sample.typ.instance) ~
12631+ =/ expected-update=(unit itype)
12632+ (direct-slot-body hed.tal.sample.typ.instance (direct-sample-name i.t.items.u.written-sample))
12633+ ?~ expected-update ~
12634+ ?. ?=(%fn -.u.expected-update) ~
12635+ :: Sample binders are not value faces. Strip only those two slot faces
12636+ :: for the invariant canonical-gate proof; the source-faced gate is still
12637+ :: used by the complete positional call and final ordinary result cast.
12638+ =/ canonical-candidate=itype [%fn [%cell u.message u.model] product]
12639+ =/ gate-fit=ifit
12640+ (direct-invariant canonical-candidate u.expected-update sub.state.instance next.state.instance)
12641+ ?. ?=(%ok -.gate-fit) ~
12642+ =/ st=istate state.instance(sub sub.gate-fit, next next.gate-fit)
12643+ =/ ini=[typ=itype state=istate] (instantiate-scheme u.init st)
12644+ =/ vw=[typ=itype state=istate] (instantiate-scheme u.view state.ini)
12645+ =/ sb=[typ=itype state=istate] (instantiate-scheme u.subs state.vw)
12646+ =. st state.sb(gate-defs checked, head-evidence heads)
12647+ =/ expected=itype [%fn typ.p.sam product]
12648+ =/ actual=itype [%cell typ.ini [%cell expected [%cell typ.vw typ.sb]]]
12649+ =/ fit=ifit
12650+ (direct-positional-fit u.args items.u.written-sample actual sample.typ.instance env st sub.st next.st)
12651+ ?. ?=(%ok -.fit) ~
12652+ =/ actual-final=itype (itype-normalize actual sub.fit)
12653+ =/ expected-final=itype (itype-normalize sample.typ.instance sub.fit)
12654+ ?^ (itype-vars actual-final) ~
12655+ ?^ (itype-vars expected-final) ~
12656+ ?: |((itype-has-tag actual-final) (itype-has-tag expected-final)) ~
12657+ =/ replay=ifit
12658+ (direct-positional-fit u.args items.u.written-sample actual sample.typ.instance env st sub.fit next.fit)
12659+ ?. ?=(%ok -.replay) ~
12660+ ?. &(=(sub.fit sub.replay) =(next.fit next.replay)) ~
12661+ =/ closed=itype (itype-normalize expected sub.fit)
12662+ ?. ?=(%fn -.closed) ~
12663+ :: The closed product no longer needs the canonical call substitutions.
12664+ :: Start the body at its ordinary sample state so existing branch retries
12665+ :: keep their substitution guards, but retain the shared fresh-ID high water.
12666+ =. st state.p.sam(next next.fit)
12667+ =/ body=expr
12668+ ?- -.val.update-def
12669+ %gate body.val.update-def
12670+ %gate-wide body.val.update-def
12671+ * !!
12672+ ==
12673+ =/ inferred=iresult
12674+ (infer-call-context-arg body product.closed env.p.sam st (span-of body))
12675+ ?: ?=(%| -.inferred) ~
12676+ =/ product-fit=ifit
12677+ (itype-fit typ.p.inferred product.closed sub.state.p.inferred next.state.p.inferred)
12678+ ?. ?=(%ok -.product-fit) ~
12679+ =/ merged-product=itype
12680+ (itype-merge-faces typ.p.inferred product.closed sub.product-fit)
12681+ =/ actual-cast=itype [%fn typ.p.sam merged-product]
12682+ =/ cast=ifit
12683+ (itype-fit actual-cast closed sub.product-fit next.product-fit)
12684+ ?. ?=(%ok -.cast) ~
12685+ =/ merged=itype (itype-merge-faces actual-cast closed sub.cast)
12686+ =/ adjusted=iresult
12687+ [%& merged state.p.inferred(sub sub.cast, next next.cast)]
12688+ =/ added=(unit iadded-definition)
12689+ (add-supported-result update-def adjusted update-state env checked artifacts.resolution)
12690+ ?~ added ~
12691+ =/ recovered=(unit ischeme) (ienv-lookup update.parts env.u.added)
12692+ ?~ recovered ~
12693+ ?. ?=(~ vars.u.recovered) ~
12694+ ?. ?=(~ (itype-vars typ.u.recovered)) ~
12695+ =/ completed=[env=ienv artifacts=(list iwidth-definition)]
12696+ (add-supported-defs-core ~[main] ds checked.u.added heads env.u.added molds.initial globals.initial externals.initial surs.initial mark-externals.initial marks.initial jimports.initial reserved-molds.initial at.initial prelude.initial artifacts.u.added grec-index.initial)
12697+ ?~ (ienv-lookup %main env.completed) ~
12698+ `[env.completed grouped.resolution artifacts.completed]
12699+::
12700+:: Recover only the initializer of an already recognized direct program main.
12701+:: The derived call is evidence for an ordinary init/main retry, never an
12702+:: interface to publish on its own. Any failure returns the original resolution.
12703+++ program-init-context
12704+ |= [main=def parts=[init=term update=term view=term subs=term] ds=(list def) resolution=iresolved initial=istate]
12705+ ^- (unit iresolved)
12706+ =/ env=ienv env.resolution
12707+ ?^ (ienv-lookup %main env) ~
12708+ ?^ (ienv-lookup init.parts env) ~
12709+ =/ update=(unit ischeme) (ienv-lookup update.parts env)
12710+ =/ view=(unit ischeme) (ienv-lookup view.parts env)
12711+ =/ subs=(unit ischeme) (ienv-lookup subs.parts env)
12712+ ?~ update ~
12713+ ?~ view ~
12714+ ?~ subs ~
12715+ =/ inits=(list def)
12716+ (skim ds |=(d=def &(?=(%value -.d) =(init.parts name.d))))
12717+ ?. ?=([* ~] inits) ~
12718+ =/ init-def=def i.inits
12719+ ?> ?=(%value -.init-def)
12720+ ?. (program-init-tuple-null init-def) ~
12721+ =/ args=(unit (list expr)) (program-main-args main)
12722+ ?~ args ~
12723+ ?~ prelude.initial ~
12724+ =/ program=(unit ischeme) (ienv-lookup %program values.u.prelude.initial)
12725+ ?~ program ~
12726+ =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude.initial)
12727+ ?~ heads ~
12728+ =/ written=(unit def) (~(get by gates.u.heads) %program)
12729+ ?~ written ~
12730+ =/ written-sample=(unit sample) (direct-gate-sample u.written)
12731+ ?~ written-sample ~
12732+ ?. ?=(%cell -.u.written-sample) ~
12733+ ?~ items.u.written-sample ~
12734+ =/ checked=(map term def) (direct-checked-gates ds env)
12735+ =/ templates=ienv
12736+ (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
12737+ =/ scanned=(unit dgscan)
12738+ (dg-all-env-ids (weld env (weld values.u.prelude.initial templates)) 32.768 ~)
12739+ ?~ scanned ~
12740+ =. next.initial (dg-next-id ids.u.scanned 0)
12741+ =/ instance=[typ=itype state=istate] (instantiate-scheme u.program initial)
12742+ ?. ?=(%fn -.typ.instance) ~
12743+ ?. ?=(%cell -.sample.typ.instance) ~
12744+ =/ expected-init=(unit itype)
12745+ (direct-slot-body hed.sample.typ.instance (direct-sample-name i.items.u.written-sample))
12746+ ?~ expected-init ~
12747+ ?. ?=(%fn -.u.expected-init) ~
12748+ ?. ?=(%var -.sample.u.expected-init) ~
12749+ =/ data=@ud id.sample.u.expected-init
12750+ =/ init-var=itype [%var next.state.instance]
12751+ =/ st=istate state.instance(next +(next.state.instance))
12752+ =/ up=[typ=itype state=istate] (instantiate-scheme u.update st)
12753+ =/ vw=[typ=itype state=istate] (instantiate-scheme u.view state.up)
12754+ =/ sb=[typ=itype state=istate] (instantiate-scheme u.subs state.vw)
12755+ =. st state.sb(gate-defs checked, head-evidence heads)
12756+ =/ actual=itype [%cell init-var [%cell typ.up [%cell typ.vw typ.sb]]]
12757+ =/ fit=ifit
12758+ (direct-positional-fit u.args items.u.written-sample actual sample.typ.instance env st sub.st next.st)
12759+ ?. ?=(%ok -.fit) ~
12760+ =/ actual-final=itype (itype-normalize actual sub.fit)
12761+ =/ expected-final=itype (itype-normalize sample.typ.instance sub.fit)
12762+ =/ open=(list @ud)
12763+ (unique-type-vars (weld (itype-vars actual-final) (itype-vars expected-final)))
12764+ ?. (levy open |=(n=@ud =(data n))) ~
12765+ ?: |((itype-has-tag actual-final) (itype-has-tag expected-final)) ~
12766+ =/ replay=ifit
12767+ (direct-positional-fit u.args items.u.written-sample actual sample.typ.instance env st sub.fit next.fit)
12768+ ?. ?=(%ok -.replay) ~
12769+ ?. &(=(sub.fit sub.replay) =(next.fit next.replay)) ~
12770+ =/ expected=itype (itype-normalize u.expected-init sub.fit)
12771+ ?. ?=(%fn -.expected) ~
12772+ =. st st(sub sub.fit, next next.fit)
12773+ =/ init-state=istate (reserve-def-caps val.init-def st)
12774+ =/ inferred=iresult (infer-fragment val.init-def env init-state)
12775+ =? inferred ?=(%| -.inferred) (infer-recursive-gate init-def env init-state)
12776+ ?: ?=(%| -.inferred) ~
12777+ ?. ?=(%fn -.typ.p.inferred) ~
12778+ =/ data-fit=ifit
12779+ (itype-fit sample.typ.p.inferred sample.expected sub.state.p.inferred next.state.p.inferred)
12780+ ?. ?=(%ok -.data-fit) ~
12781+ =/ closed=itype (itype-normalize expected sub.data-fit)
12782+ ?. ?=(%fn -.closed) ~
12783+ :: Resolve the ordinary tuple cast first, then check the complete gate.
12784+ :: General function fit remains unchanged; only this recovered candidate
12785+ :: receives the derived result context before its whole-type cast fit.
12786+ =/ product-fit=ifit
12787+ (itype-fit product.typ.p.inferred product.closed sub.data-fit next.data-fit)
12788+ ?. ?=(%ok -.product-fit) ~
12789+ =/ product=itype
12790+ (itype-merge-faces product.typ.p.inferred product.closed sub.product-fit)
12791+ =/ actual-cast=itype [%fn sample.typ.p.inferred product]
12792+ =/ cast=ifit
12793+ (itype-fit actual-cast closed sub.product-fit next.product-fit)
12794+ ?. ?=(%ok -.cast) ~
12795+ =/ merged=itype (itype-merge-faces actual-cast closed sub.cast)
12796+ =/ adjusted=iresult
12797+ [%& merged state.p.inferred(sub sub.cast, next next.cast)]
12798+ =/ added=(unit iadded-definition)
12799+ (add-supported-result init-def adjusted init-state env checked artifacts.resolution)
12800+ ?~ added ~
12801+ =/ recovered=(unit ischeme) (ienv-lookup init.parts env.u.added)
12802+ ?~ recovered ~
12803+ ?. ?=(~ vars.u.recovered) ~
12804+ ?. ?=(~ (itype-vars typ.u.recovered)) ~
12805+ =/ completed=[env=ienv artifacts=(list iwidth-definition)]
12806+ (add-supported-defs-core ~[main] ds checked.u.added heads env.u.added molds.initial globals.initial externals.initial surs.initial mark-externals.initial marks.initial jimports.initial reserved-molds.initial at.initial prelude.initial artifacts.u.added grec-index.initial)
12807+ ?~ (ienv-lookup %main env.completed) ~
12808+ `[env.completed grouped.resolution artifacts.completed]
12809+::
12810+++ program-subs-watch
12811+ |= [d=def imports=ijimports graph=irequest-graph prelude=ifile]
12812+ ^- ?
12813+ ?. ?=(%value -.d) |
12814+ ?. |(?=(%gate -.val.d) ?=(%gate-wide -.val.d)) |
12815+ =/ body=expr
12816+ ?- -.val.d
12817+ %gate body.val.d
12818+ %gate-wide body.val.d
12819+ * val.d
12820+ ==
12821+ =. body (program-transparent body)
12822+ ?. ?=(%list -.body) |
12823+ ?. ?=([* ~] items.body) |
12824+ =/ watch=expr (program-transparent i.items.body)
12825+ ?. ?=(%tuple -.watch) |
12826+ ?. ?=([* * ~] items.watch) |
12827+ =/ tag=item i.items.watch
12828+ =/ payload=item i.t.items.watch
12829+ ?. &(?=(~ face.tag) ?=(~ face.payload)) |
12830+ =/ tag-expr=expr (program-transparent val.tag)
12831+ ?. ?=(%lit -.tag-expr) |
12832+ ?. &(?=(%term form.lit.tag-expr) =(%watch val.lit.tag-expr)) |
12833+ =/ request=expr (program-transparent val.payload)
12834+ ?. ?=(%call -.request) |
12835+ ?. ?=([* ~] args.request) |
12836+ =/ head=expr (program-transparent head.request)
12837+ ?. ?=(%wing -.head) |
12838+ ?. ?=([@ @ ~] names.head) |
12839+ =/ case=term i.names.head
12840+ =/ face=term i.t.names.head
12841+ =/ callback=expr (program-transparent i.args.request)
12842+ ?. ?=(%ctor -.callback) |
12843+ ?. ?=(%term form.tag.callback) |
12844+ =/ selected=(list [face=term interface=ifile])
12845+ (skim imports |=(j=[face=term interface=ifile] =(face face.j)))
12846+ ?. ?=([* ~] selected) |
12847+ =/ iface=ifile interface.i.selected
12848+ =/ member=(unit ischeme) (ienv-lookup case values.iface)
12849+ ?~ member |
12850+ ?~ source.iface |
12851+ =/ evidence=(list irequest-evidence)
12852+ (skim requests.graph |=(r=irequest-evidence &(=(api-at.r at.iface) =(name.r case))))
12853+ ?. ?=([* ~] evidence) |
12854+ =/ request-evidence=irequest-evidence i.evidence
12855+ ?. =(u.source.iface api-source.request-evidence) |
12856+ ?. =(name.path.path.request-evidence case) |
12857+ ?~ graph.iface |
12858+ ?. (lien requests.u.graph.iface |=(r=irequest-evidence =(r request-evidence))) |
12859+ ?. ?=(~ scry.path.path.request-evidence) |
12860+ ?. &(?=(~ diffs.path.request-evidence) ?=(~ diffs.path.path.request-evidence)) |
12861+ ?: (lien segments.path.path.request-evidence |=(p=pseg !?=(%knot -.p))) |
12862+ ?. ?=([@ ~] vars.u.member) |
12863+ =/ message=@ud i.vars.u.member
12864+ ?. ?=(%fn -.typ.u.member) |
12865+ ?. ?=(%fn -.sample.typ.u.member) |
12866+ ?. =(sample.sample.typ.u.member full.path.request-evidence) |
12867+ ?. =(product.sample.typ.u.member [%var message]) |
12868+ =/ prep=iprelude [prelude prelude-values.graph prelude-molds.graph]
12869+ =/ ask=(unit ischeme) (request-compatible-ask prep)
12870+ ?~ ask |
12871+ =/ result=(unit itype) (template-apply u.ask ~[[%var message]])
12872+ ?~ result |
12873+ =(product.typ.u.member u.result)
12874+::
12875+++ program-main-closed
12876+ |= [parts=[init=term update=term view=term subs=term] ds=(list def) env=ienv prelude=(unit ifile) imports=ijimports graph=irequest-graph]
12877+ ^- ?
12878+ ?~ prelude |
12879+ ?~ (ienv-lookup %program values.u.prelude) |
12880+ =/ program=(unit ischeme) (find-jibb-mold %program u.prelude)
12881+ ?~ program |
12882+ =/ main=(unit ischeme) (ienv-lookup %main env)
12883+ ?~ main |
12884+ ?. ?=(~ vars.u.main) |
12885+ ?. ?=(~ (itype-vars typ.u.main)) |
12886+ =/ instance=[typ=itype state=istate] (instantiate-scheme u.program *istate)
12887+ =/ main-fit=ifit (direct-invariant typ.u.main typ.instance ~ next.state.instance)
12888+ ?. ?=(%ok -.main-fit) |
12889+ =/ init=(unit ischeme) (ienv-lookup init.parts env)
12890+ ?~ init |
12891+ ?. ?=(~ vars.u.init) |
12892+ ?. ?=(%fn -.typ.u.init) |
12893+ ?. ?=(~ (itype-vars sample.typ.u.init)) |
12894+ ?. ?=(~ (itype-vars product.typ.u.init)) |
12895+ =/ data=igate-free (gate-free-type sample.typ.u.init 256 ~)
12896+ ?. =(%yes verdict.data) |
12897+ =/ model=igate-free (gate-free-type product.typ.u.init left.data ~)
12898+ ?. =(%yes verdict.model) |
12899+ =/ subs=(list def)
12900+ (skim ds |=(d=def &(?=(%value -.d) =(subs.parts name.d))))
12901+ ?. ?=([* ~] subs) |
12902+ |((program-subs-empty i.subs) (program-subs-watch i.subs imports graph u.prelude))
12903+::
12904+++ infer-jibb-file
12905+ |= [at=path src=@t externals=iexternals mark-externals=imark-externals modules=jbundle active=(list path) prelude-values=(list term) prelude-molds=(list term) cache=jcache prelude=(unit ifile)]
12906+ ^- jfile-result
12907+ =/ out=jfile-detailed-result
12908+ (infer-jibb-file-detailed at src externals mark-externals modules active prelude-values prelude-molds cache prelude)
12909+ ?: ?=(%| -.out) [%| message.p.out]
12910+ [%& p.out]
12911+:: Returns structured root-source overlap evidence after the same full check.
12912+++ infer-jibb-file-detailed
12913+ |= [at=path src=@t externals=iexternals mark-externals=imark-externals modules=jbundle active=(list path) prelude-values=(list term) prelude-molds=(list term) cache=jcache prelude=(unit ifile)]
12914+ ^- jfile-detailed-result
12915+ =/ parsed (parse at src)
12916+ ?: ?=(%| -.parsed) [%| [(crip "module source does not parse: {(spud at)}") ~]]
12917+ =/ mod=module p.parsed
12918+ =/ duplicate=(unit idiag) (duplicate-defs defs.mod)
12919+ ?^ duplicate [%| [(show-duplicate-fields at src u.duplicate) ~]]
12920+ ?: &(?=([%ui %api *] at) ?=(^ (program-main-def defs.mod)))
12921+ [%| [(crip "module kind needs unsupported inference: {(spud at)}") ~]]
12922+ ?: ?=([%ui %api *] at)
12923+ =/ iface=(unit ifile) (api-poke-interface at mod mark-externals prelude-values prelude-molds prelude)
12924+ ?^ iface
12925+ =/ checked=ifile u.iface(source `src, graph `[(silt `(list path)`~[at]) ~ modules prelude prelude-values prelude-molds externals mark-externals])
12926+ [%& [checked [[at checked] cache]]]
12927+ ?~ prelude [%| [(crip "API module needs unsupported inference: {(spud at)}") ~]]
12928+ =/ prepared=iprelude [u.prelude prelude-values prelude-molds]
12929+ =/ narrow=?
12930+ ?. ?=([[%mark *] ~] imports.mod) |
12931+ ?. ?=([[%mold *] ~] defs.mod) |
12932+ ?. =(%paths name.i.defs.mod) |
12933+ !?=(%union -.shape.i.defs.mod)
12934+ ?: narrow
12935+ =/ request=(each ione-request-interface @t)
12936+ (one-request-interface-graph at src externals mark-externals modules active cache `prepared)
12937+ ?: ?=(%| -.request) [%| [(crip "API module needs unsupported inference: {(spud at)}") ~]]
12938+ =/ checked=ifile iface.p.request
12939+ [%& [checked [[at checked] dependencies.paths.support.p.request]]]
12940+ =/ multi=(each [iface=ifile cache=jcache] @t)
12941+ (multi-request-interface-graph at src externals mark-externals modules active cache `prepared)
12942+ ?: ?=(%| -.multi) [%| [(crip "API module needs unsupported inference: {(spud at)}") ~]]
12943+ [%& [iface.p.multi [[at iface.p.multi] cache.p.multi]]]
12944+ ?. (module-scope-valid mod prelude-values prelude-molds)
12945+ ?: (pending-declared-poke at mod prelude-values prelude-molds)
12946+ [%| [(crip "module kind or scope needs unsupported inference: {(spud at)}") ~]]
12947+ [%| [(crip "module has conflicting names: {(spud at)}") ~]]
12948+ =/ vals=(list term) (global-value-names defs.mod)
12949+ =/ main=(unit def) (program-main-def defs.mod)
12950+ =/ main-parts=(unit [init=term update=term view=term subs=term])
12951+ ?~(main ~ (program-main-parts u.main))
12952+ ?. ?~(main & &(!?=([%ui %stores *] at) ?=(^ main-parts)))
12953+ [%| [(crip "module kind needs unsupported inference: {(spud at)}") ~]]
12954+ =/ js=jimports-detailed-result (resolve-jibb-imports-detailed imports.mod externals mark-externals modules active prelude-values prelude-molds cache prelude)
12955+ ?: ?=(%| -.js) [%| p.js]
12956+ =/ collected=grec-collected
12957+ ?^ imports.mod [(collect-simple-molds defs.mod) *(map term shape)]
12958+ (grec-collect-molds defs.mod)
12959+ =/ molds=imolds molds.collected
12960+ =/ globals=(list term) (weld prelude-values (weld (import-binding-names imports.mod) vals))
12961+ =/ surs=(list term) (collect-sur-imports imports.mod)
12962+ =/ marks=(list term) (collect-mark-imports imports.mod)
12963+ =/ reserved=(list term) (weld prelude-molds (turn resolved.p.js |=(j=[face=term interface=ifile] face.j)))
12964+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
12965+ =/ state=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks resolved.p.js reserved ~ ~ ~ | at top prelude ~ 256 ~ ~ ~ ~ ~ ~]
12966+ :: Source and scope were checked above; preserve that exact root and prelude.
12967+ :: This first integration only indexes import-free library sources.
12968+ =/ index=(unit [at=path source=@t prelude=ifile shapes=(map term shape)])
12969+ ?^ imports.mod ~
12970+ ?~ prelude ~
12971+ =/ standard=(unit ischeme) (find-jibb-mold %list u.prelude)
12972+ ?~ standard ~
12973+ ?. =(u.standard [[%collection %list ~[[%var 0]]] ~[0]]) ~
12974+ =/ index=(map term shape) proofs.collected
12975+ ?. !=(index *(map term shape)) ~
12976+ ?: (lien molds |=(m=[name=term body=shape] =(%list name.m))) ~
12977+ `[at src u.prelude index]
12978+ =. grec-index.state index
12979+ =/ mts=(each imold-types imold-failure) (module-mold-types-detail molds state)
12980+ ?: ?=(%| -.mts)
12981+ ?~ overlap.p.mts [%| [(crip "{(trip message.p.mts)}: {(spud at)}") ~]]
12982+ =/ witness=[name=term cases=upair] u.overlap.p.mts
12983+ =/ first=@t (show-error src [at line.beg.first.cases.witness col.beg.first.cases.witness "first union case"])
12984+ =/ second=@t (show-error src [at line.beg.second.cases.witness col.beg.second.cases.witness "overlapping case"])
12985+ =/ msg=@t (of-wain:format ~[(crip "module mold {(trip name.witness)} has overlapping cases") first second])
12986+ [%| [msg `[at src name.witness cases.witness]]]
12987+ =/ resolution=iresolved
12988+ ?~ index
12989+ (resolve-groups defs.mod molds globals externals surs mark-externals marks resolved.p.js reserved at prelude)
12990+ (resolve-groups-core defs.mod molds globals externals surs mark-externals marks resolved.p.js reserved at prelude index)
12991+ =/ env=ienv env.resolution
12992+ =/ recovered=(unit iresolved)
12993+ ?~ main ~
12994+ ?~ main-parts ~
12995+ =/ updated=(unit iresolved)
12996+ (program-update-context u.main u.main-parts defs.mod resolution state)
12997+ ?^ updated updated
12998+ (program-init-context u.main u.main-parts defs.mod resolution state)
12999+ =. env ?~(recovered env env.u.recovered)
13000+ =. artifacts.resolution
13001+ ?~(recovered artifacts.resolution artifacts.u.recovered)
13002+ =. env
13003+ ?: (module-values-complete defs.mod env) env
13004+ ?: |(?=([%ui %stores *] at) ?=(^ imports.mod) ?=(^ prelude) ?=(^ prelude-values) ?=(^ prelude-molds)) env
13005+ ?: (gth (met 3 src) 65.536) env
13006+ ?: (gth (lent defs.mod) 64) env
13007+ ?. (dg-source-candidate defs.mod 64) env
13008+ =/ transaction=(unit dgcommit) (dg-root-source at src)
13009+ ?~ transaction env
13010+ ?: (dg-interface-safe env.u.transaction) env.u.transaction
13011+ env
13012+ ?. (module-values-complete defs.mod env)
13013+ [%| [(crip "module definitions need unsupported inference: {(spud at)}") ~]]
13014+ =/ initial=irequest-graph [(silt `(list path)`~[at]) ~ modules prelude prelude-values prelude-molds externals mark-externals]
13015+ =/ graph=(unit irequest-graph) (request-graph-merge resolved.p.js initial (add 1 (lent resolved.p.js)))
13016+ ?~ graph [%| ['module request evidence needs unsupported inference' ~]]
13017+ ?. ?~(main & ?~(main-parts | (program-main-closed u.main-parts defs.mod env prelude resolved.p.js u.graph)))
13018+ [%| [(crip "module kind needs unsupported inference: {(spud at)}") ~]]
13019+ =/ iface=ifile [env p.mts at ~ artifacts.resolution ~ `src graph]
13020+ [%& [iface [[at iface] cache.p.js]]]
13021+::
13022+:: A source-bound analysis of one named mold, not a module, island,
13023+:: request, watchability or runtime check. The host owns the trusted
13024+:: prepared prelude, canonical paths and reader/source version identities.
13025+:: The 256-node cap covers only classification, not source/graph work.
13026++$ igate-free-mold
13027+ [at=path source=@t name=term prepared=iprelude externals=iexternals marks=imark-externals modules=jbundle dependencies=jcache mold=ischeme requested=@ud budget=@ud result=igate-free]
13028+++ gate-free-mold-source
13029+ |= [file=path src=@t name=term externals=iexternals marks=imark-externals modules=jbundle prepared=(unit iprelude) fuel=@ud]
13030+ ^- (each igate-free-mold @t)
13031+ ?~ file [%| 'mold analysis needs a path ending in jibb']
13032+ ?. =(%jibb (rear file)) [%| 'mold analysis needs a path ending in jibb']
13033+ ?: |(=(file /lib/jibb/internal/jibb) =(file /lib/jibb/primitives/jibb))
13034+ [%| 'the prelude internal modules are private']
13035+ ?: ?=([%ui %api *] file) [%| 'API declarations need unsupported mold analysis']
13036+ ?: ?=([%ui %stores *] file) [%| 'store declarations need unsupported mold analysis']
13037+ =/ entries=jbundle (skim modules |=(m=jsource =(file at.m)))
13038+ ?: (gth (lent entries) 1) [%| 'duplicate root module sources']
13039+ =/ wrong-root=? ?~(entries | !=(source.i.entries src))
13040+ ?: wrong-root [%| 'root module source does not match bundle']
13041+ =/ parsed (parse file src)
13042+ ?: ?=(%| -.parsed) [%| 'mold source does not parse']
13043+ =/ mod=module p.parsed
13044+ =/ duplicate=(unit idiag) (duplicate-defs defs.mod)
13045+ ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
13046+ ?~ prepared [%| 'mold analysis needs the prepared prelude']
13047+ ?. (module-scope-valid mod values.u.prepared molds.u.prepared)
13048+ [%| 'mold source has conflicting or unsupported scope']
13049+ =/ selected=(list def)
13050+ (skim defs.mod |=(d=def &(?=(%mold -.d) =(name.d name))))
13051+ ?~ selected [%| 'selected mold is not declared']
13052+ ?^ t.selected [%| 'selected mold is not unique']
13053+ ?> ?=(%mold -.i.selected)
13054+ =/ public=ifile iface.u.prepared
13055+ =/ js=jimports-result
13056+ (resolve-jibb-imports imports.mod externals marks modules ~[file] values.u.prepared molds.u.prepared ~ `public)
13057+ ?: ?=(%| -.js) [%| p.js]
13058+ =/ ms=imolds (collect-simple-molds defs.mod)
13059+ =/ vals=(list term) (global-value-names defs.mod)
13060+ =/ globals=(list term) (weld values.u.prepared (weld (import-binding-names imports.mod) vals))
13061+ =/ surs=(list term) (collect-sur-imports imports.mod)
13062+ =/ declared=(list term) (collect-mark-imports imports.mod)
13063+ =/ reserved=(list term) (weld molds.u.prepared (turn resolved.p.js |=(j=[face=term interface=ifile] face.j)))
13064+ =/ top=(list term) (turn ms |=(m=[name=term body=shape] name.m))
13065+ =/ state=istate [0 ~ ~ ~ ms globals externals surs marks declared resolved.p.js reserved ~ ~ ~ | file top `public ~ 256 ~ ~ ~ ~ ~ ~]
13066+ =/ inferred=(unit [template=ischeme state=istate])
13067+ (infer-mold-template shape.i.selected state(active ~[name], in-mold &))
13068+ ?~ inferred [%| 'selected mold needs unsupported inference']
13069+ =/ template=ischeme template.u.inferred
13070+ =. typ.template (label-direct-union typ.template shape.i.selected name state)
13071+ =. typ.template (itype-normalize typ.template sub.state.u.inferred)
13072+ =/ cap=@ud (min fuel 256)
13073+ =/ analysis=igate-free (gate-free-type typ.template cap ~)
13074+ [%& [file src name u.prepared externals marks modules cache.p.js template fuel cap analysis]]
13075+::
13076+:: +golden-types-with-modules fails closed for imports without prelude
13077+:: scope. +golden-types-with-prelude resolves supported library graphs;
13078+:: its report remains partial and unreachable sources are not examined.
13079+::
13080+++ golden-types-with-modules
13081+ |= [file=path src=@t externals=iexternals mark-externals=imark-externals modules=jbundle]
13082+ ^- @t
13083+ =/ parsed (parse file src)
13084+ ?: ?=(%| -.parsed) (show-error src p.parsed)
13085+ =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
13086+ ?^ duplicate (duplicate-fields-report file src u.duplicate)
13087+ ?: (lien imports.p.parsed |=(i=import ?=(%jibb -.i)))
13088+ 'partial inference; module not checked\0aprelude source missing; module import inference unsupported'
13089+ (golden-types-with-marks file src externals mark-externals)
13090+::
13091+:: The caller supplies the actual prelude source. Its declared names are
13092+:: reserved, and supported inferred types are made available. The inventory
13093+:: and the checker are incomplete, so this never claims a checked module.
13094+:: Hosts may prepare the same trusted source once and reuse its interface.
13095+::
13096+++ golden-types-with-prelude
13097+ |= [file=path src=@t externals=iexternals mark-externals=imark-externals modules=jbundle prelude-source=@t]
13098+ ^- @t
13099+ =/ parsed (parse file src)
13100+ ?: ?=(%| -.parsed) (show-error src p.parsed)
13101+ =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
13102+ ?^ duplicate (duplicate-fields-report file src u.duplicate)
13103+ ?: =(0 prelude-source) 'partial inference; module not checked\0aprelude source missing; module import inference unsupported'
13104+ =/ prelude (parse /lib/jibb/prelude/jibb prelude-source)
13105+ ?: ?=(%| -.prelude) 'partial inference; module not checked\0aprelude source does not parse; module import inference unsupported'
13106+ =/ prepared=(unit iprelude) (prepare-prelude prelude-source)
13107+ ?~ prepared 'partial inference; module not checked\0aprelude interface is not supported'
13108+ (golden-types-with-prepared-prelude file src externals mark-externals modules prepared)
13109+::
13110+++ golden-types-with-prelude-and-internal
13111+ |= [file=path src=@t externals=iexternals mark-externals=imark-externals modules=jbundle prelude-source=@t internal-source=@t]
13112+ ^- @t
13113+ =/ prepared=(unit iprelude) (prepare-prelude-with-internal prelude-source internal-source)
13114+ (golden-types-with-prepared-prelude file src externals mark-externals modules prepared)
13115+::
13116+++ golden-types-with-prepared-prelude
13117+ |= [file=path src=@t externals=iexternals mark-externals=imark-externals modules=jbundle prepared=(unit iprelude)]
13118+ ^- @t
13119+ =/ parsed (parse file src)
13120+ ?: ?=(%| -.parsed) (show-error src p.parsed)
13121+ =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
13122+ ?^ duplicate (duplicate-fields-report file src u.duplicate)
13123+ ?~ prepared 'partial inference; module not checked\0aprelude interface is not supported'
13124+ =/ prelude-values=(list term) values.u.prepared
13125+ =/ prelude-molds=(list term) molds.u.prepared
13126+ =/ iface=(unit ifile) `iface.u.prepared
13127+ ?. (module-scope-valid p.parsed prelude-values prelude-molds)
13128+ ?: (pending-declared-poke file p.parsed prelude-values prelude-molds)
13129+ 'partial inference; module not checked\0amodule kind or scope needs unsupported inference'
13130+ 'partial inference; module not checked\0amodule has conflicting names'
13131+ =/ js=jimports-result
13132+ (resolve-jibb-imports imports.p.parsed externals mark-externals modules ~[file] prelude-values prelude-molds ~ iface)
13133+ ?: ?=(%| -.js) (of-wain:format ~['partial inference; module not checked' p.js])
13134+ =/ scope-values=(list term)
13135+ (weld prelude-values (weld (collect-sur-imports imports.p.parsed) (collect-mark-imports imports.p.parsed)))
13136+ (golden-types-in-context-core file src externals mark-externals resolved.p.js scope-values prelude-molds iface prepared)
13137+::
13138+:: +golden-types-with-marks: supply declared mark types separately from /sur
13139+:: entries, as [mark result] with the result from +read-mark:jibb-import.
13140+:: Unknown, duplicated, failed and undeclared entries never resolve a mold.
13141+::
13142+:: Callers pass unchanged structured reader results; graph validation
13143+:: remains in the existing bridge, and failures stay available lazily.
13144+++ reader-result-for-checker
13145+ |= result=*
13146+ ^- *
13147+ ?: ?=([%ok *] result) [%& +.result]
13148+ result
13149+::
13150+++ golden-types-with-reader-diagnostics
13151+ |= [file=path src=@t externals=iexternals mark-externals=imark-externals]
13152+ ^- @t
13153+ =/ ex=iexternals
13154+ (turn externals |=(e=[module=term name=term result=*] [module.e name.e (reader-result-for-checker result.e)]))
13155+ =/ mx=imark-externals
13156+ (turn mark-externals |=(e=[mark=term result=*] [mark.e (reader-result-for-checker result.e)]))
13157+ (golden-types-with-marks file src ex mx)
13158+::
13159+++ golden-types-with-marks
13160+ |= [file=path src=@t externals=iexternals mark-externals=imark-externals]
13161+ ^- @t
13162+ (golden-types-in-context file src externals mark-externals ~ ~ ~ ~)
13163+::
13164+++ golden-types-in-context
13165+ |= [file=path src=@t externals=iexternals mark-externals=imark-externals jimports=ijimports prelude-values=(list term) reserved-molds=(list term) prelude=(unit ifile)]
13166+ ^- @t
13167+ (golden-types-in-context-core file src externals mark-externals jimports prelude-values reserved-molds prelude ~)
13168+++ golden-types-in-context-core
13169+ |= [file=path src=@t externals=iexternals mark-externals=imark-externals jimports=ijimports prelude-values=(list term) reserved-molds=(list term) prelude=(unit ifile) prepared=(unit iprelude)]
13170+ ^- @t
13171+ =. reserved-molds (weld reserved-molds (turn jimports |=(j=[face=term interface=ifile] face.j)))
13172+ =/ parsed (parse file src)
13173+ ?: ?=(%| -.parsed) (show-error src p.parsed)
13174+ =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
13175+ ?^ duplicate (duplicate-fields-report file src u.duplicate)
13176+ ?: (module-has-reserved-proj p.parsed)
13177+ 'module has reserved proj name'
13178+ =/ ds=(list def) defs.p.parsed
13179+ =/ molds=imolds (collect-simple-molds ds)
13180+ =/ globals=(list term) (weld prelude-values (weld (turn jimports |=(j=[face=term interface=ifile] face.j)) (global-value-names ds)))
13181+ =/ surs=(list term) (collect-sur-imports imports.p.parsed)
13182+ =/ marks=(list term) (collect-mark-imports imports.p.parsed)
13183+ =/ resolution=iresolved (resolve-groups ds molds globals externals surs mark-externals marks jimports reserved-molds file prelude)
13184+ =/ cycles=(list icycle) (definite-value-cycles ds globals)
13185+ =/ env=ienv env.resolution
13186+ =/ recovered=(list term) ~
13187+ =/ eligible=?
13188+ ?& ?=(~ imports.p.parsed)
13189+ ?=(~ jimports)
13190+ !?=([%ui %api *] file)
13191+ !?=([%ui %stores *] file)
13192+ !(lien (global-value-names ds) |=(n=term =(n %main)))
13193+ !(module-values-complete ds env)
13194+ (lte (met 3 src) 65.536)
13195+ (lte (lent ds) 64)
13196+ ?| &(?=(~ prepared) ?=(~ prelude) ?=(~ prelude-values) ?=(~ reserved-molds) (module-scope-valid p.parsed ~ ~) (dg-source-candidate ds 64))
13197+ ?& ?=(^ prepared)
13198+ ?=(^ prelude)
13199+ =(u.prelude iface.u.prepared)
13200+ =(prelude-values values.u.prepared)
13201+ =(reserved-molds molds.u.prepared)
13202+ (module-scope-valid p.parsed values.u.prepared molds.u.prepared)
13203+ (dg-prepared-candidate ds 64)
13204+ ==
13205+ ==
13206+ ==
13207+ =/ transaction=(unit dgcommit)
13208+ ?. eligible ~
13209+ ?~ prepared (dg-root-source file src)
13210+ (dg-root-prepared file src u.prepared)
13211+ =. recovered
13212+ ?~ transaction ~
13213+ ?. &((module-values-complete ds env.u.transaction) (dg-interface-safe env.u.transaction)) ~
13214+ (turn (skim env.u.transaction |=(entry=[name=term scheme=ischeme] ?=(~ (ienv-lookup name.entry env)))) |=(entry=[name=term scheme=ischeme] name.entry))
13215+ =. env
13216+ ?~ transaction env
13217+ ?: &((module-values-complete ds env.u.transaction) (dg-interface-safe env.u.transaction)) env.u.transaction
13218+ env
13219+ =/ source-defs=(map term def) (direct-checked-gates ds env)
13220+ =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude)
13221+ =/ lines=(list @t) ~
13222+ |-
13223+ ?~ ds (of-wain:format ['partial inference; module not checked' (flop lines)])
13224+ =/ d=def i.ds
13225+ ?: ?=(%mold -.d)
13226+ $(ds t.ds, lines [(show-partial-mold file src d molds) lines])
13227+ ?. (unique-value-name name.d globals)
13228+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: name already in scope") lines])
13229+ =/ cycle=(list icycle) (skim cycles |=(c=icycle =(name.c name.d)))
13230+ ?^ cycle
13231+ =/ diag=idiag ["non-gate value depends on itself through a cycle" ~[[first.i.cycle "value in cycle"] [next.i.cycle "dependency in cycle"]]]
13232+ $(ds t.ds, lines [(show-inference-diagnostic file src name.d diag) lines])
13233+ ?: (lien recovered |=(n=term =(n name.d)))
13234+ =/ found=(unit ischeme) (ienv-lookup name.d env)
13235+ ?~ found $(ds t.ds, lines [(crip "++ {(trip name.d)}: committed definition unavailable") lines])
13236+ ?: (itype-has-hidden-recursive typ.u.found)
13237+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: recursive mold name is not available in this scope") lines])
13238+ ?: (itype-has-hidden-generic typ.u.found)
13239+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: generic union name is not available in this scope") lines])
13240+ =/ typ=itype (canonical-itype typ.u.found vars.u.found)
13241+ =/ line=@t (crip "++ {(trip name.d)}: {(show-itype typ ~)}{(show-atom-constraint typ)}")
13242+ $(ds t.ds, lines [line lines])
13243+ ?: (lien grouped.resolution |=(n=term =(n name.d)))
13244+ =/ found=(unit ischeme) (ienv-lookup name.d env)
13245+ ?~ found $(ds t.ds, lines [(crip "++ {(trip name.d)}: recursive group unavailable") lines])
13246+ =/ typ=itype (canonical-itype typ.u.found vars.u.found)
13247+ =/ line=@t (crip "++ {(trip name.d)}: {(show-itype typ ~)}{(show-atom-constraint typ)}")
13248+ $(ds t.ds, lines [line lines])
13249+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
13250+ =/ initial=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ | file top prelude ~ 256 ~ ~ ~ ~ ~ ~]
13251+ =. gate-defs.initial source-defs
13252+ =. head-evidence.initial heads
13253+ =. initial (reserve-def-caps val.d initial)
13254+ =/ result=iresult
13255+ ?: |(?=(%gate -.val.d) ?=(%gate-wide -.val.d))
13256+ (infer-recursive-gate d env initial)
13257+ (infer-fragment val.d env initial)
13258+ ?: ?=(%| -.result)
13259+ $(ds t.ds, lines [(show-inference-diagnostic file src name.d p.result) lines])
13260+ =. state.p.result (promote-restricted-numbers state.p.result env)
13261+ =. state.p.result (default-hole-numbers holes.state.p.result holes.initial state.p.result env !(itype-has-gate (itype-normalize typ.p.result sub.state.p.result)))
13262+ =/ hole=(unit idiag) (unresolved-hole holes.state.p.result holes.initial state.p.result)
13263+ ?^ hole
13264+ $(ds t.ds, lines [(show-inference-diagnostic file src name.d u.hole) lines])
13265+ =/ merged=(unit [first=icap second=icap])
13266+ (merged-capitals caps.state.p.result sub.state.p.result)
13267+ ?^ merged
13268+ =/ diag=idiag
13269+ ["distinct type variables `{(trip name.first.u.merged)}` and `{(trip name.second.u.merged)}` must not be forced equal; use the same capital for a shared type" ~[[at.first.u.merged "first type variable"] [at.second.u.merged "second type variable"]]]
13270+ $(ds t.ds, lines [(show-inference-diagnostic file src name.d diag) lines])
13271+ ?: (constrained-capitals caps.state.p.result sub.state.p.result)
13272+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: explicit capital constraints are not supported by partial inference") lines])
13273+ =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
13274+ ?: (pending-null tags.state.p.result sub.state.p.result)
13275+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: `~` needs context in partial inference") lines])
13276+ ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ))
13277+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: tag needs context in partial inference") lines])
13278+ ?: (itype-has-hidden-recursive typ)
13279+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: recursive mold name is not available in this scope") lines])
13280+ ?: (itype-has-hidden-generic typ)
13281+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: generic union name is not available in this scope") lines])
13282+ ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result)
13283+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: unresolved aura-variable inference") lines])
13284+ =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
13285+ ?: (gth (lent vars) 26)
13286+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: too many variables for partial printer") lines])
13287+ ?~ (width-finalize projections.state.p.result sub.state.p.result vars)
13288+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: record projection elaboration needs unsupported inference") lines])
13289+ =/ printable=itype (canonical-itype typ vars)
13290+ =/ line=@t (crip "++ {(trip name.d)}: {(show-itype printable ~)}{(show-atom-constraint printable)}")
13291+ $(ds t.ds, lines [line lines])
13292+:: Experimental module-owned pending-constraint generalization only.
13293+:: Inputs, IDs and substitution come from one checker-owned transaction.
13294++$ dgscan [ids=(list @ud) fuel=@ud]
13295+++ dg-scan
13296+ |= [todo=(list itype) sub=isub fuel=@ud ids=(list @ud)]
13297+ ^- (unit dgscan)
13298+ ?~ todo `[ids fuel]
13299+ ?: =(0 fuel) ~
13300+ =. fuel (dec fuel)
13301+ =/ t=itype i.todo
13302+ ?: ?=(?(%var %avar %rvar %nvar %rnvar %tag) -.t)
13303+ =/ node-id=@ud ?:(?=(%tag -.t) id.t +.t)
13304+ =/ found=(unit itype) (itype-lookup node-id sub)
13305+ ?~ found $(todo t.todo, ids [node-id ids])
13306+ ?: &(?=(?(%rvar %rnvar) -.u.found) =(node-id +.u.found))
13307+ $(todo t.todo, ids [node-id ids])
13308+ $(todo [u.found t.todo])
13309+ ?: ?=(%jrec -.t) $(todo t.todo)
13310+ ?+ -.t ~
13311+ %collection $(todo (weld args.t t.todo))
13312+ %union $(todo (weld args.t (weld cases.t t.todo)))
13313+ %face $(todo [body.t t.todo])
13314+ %fn $(todo [sample.t product.t t.todo])
13315+ %cell $(todo [hed.t tal.t t.todo])
13316+ %atom $(todo t.todo)
13317+ %any-atom $(todo t.todo)
13318+ %flag $(todo t.todo)
13319+ %noun $(todo t.todo)
13320+ %empty $(todo t.todo)
13321+ %const $(todo t.todo)
13322+ ==
13323+::
13324+++ dg-scan-ids
13325+ |= [ids=(list @ud) sub=isub fuel=@ud blocked=(list @ud)]
13326+ ^- (unit dgscan)
13327+ ?~ ids `[blocked fuel]
13328+ =/ one=(unit dgscan) (dg-scan ~[[%var i.ids]] sub fuel blocked)
13329+ ?~ one ~
13330+ $(ids t.ids, fuel fuel.u.one, blocked ids.u.one)
13331+::
13332+++ dg-env
13333+ |= [env=ienv sub=isub fuel=@ud blocked=(list @ud)]
13334+ ^- (unit dgscan)
13335+ ?~ env `[blocked fuel]
13336+ =/ sc=ischeme scheme.i.env
13337+ :: Quantifiers are local to the scheme: first find raw free IDs, then
13338+ :: follow those IDs in the module substitution without capturing them.
13339+ =/ raw=(unit dgscan) (dg-scan ~[typ.sc] ~ fuel ~)
13340+ ?~ raw ~
13341+ =/ free=(list @ud) (skim ids.u.raw |=(n=@ud !(lien vars.sc |=(q=@ud =(q n)))))
13342+ =/ resolved=(unit dgscan) (dg-scan-ids free sub fuel.u.raw blocked)
13343+ ?~ resolved ~
13344+ $(env t.env, fuel fuel.u.resolved, blocked ids.u.resolved)
13345+::
13346+++ dg-obligations
13347+ |= [pending=(list dgo) sub=isub fuel=@ud blocked=(list @ud)]
13348+ ^- (unit dgscan)
13349+ ?~ pending `[blocked fuel]
13350+ =/ found=(unit dgscan) (dg-scan ~[left.i.pending right.i.pending] sub fuel blocked)
13351+ ?~ found ~
13352+ $(pending t.pending, fuel fuel.u.found, blocked ids.u.found)
13353+::
13354+++ dg-tags
13355+ |= [tags=(list ipending) sub=isub fuel=@ud blocked=(list @ud)]
13356+ ^- (unit dgscan)
13357+ ?~ tags `[blocked fuel]
13358+ ?: =(0 fuel) ~
13359+ =/ found=(unit itype) (itype-lookup id.i.tags sub)
13360+ ?~ found $(tags t.tags, fuel (dec fuel), blocked [id.i.tags blocked])
13361+ :: Until this entry is explicitly discharged, retain variables reachable
13362+ :: through its binding; mere existence of a substitution is not proof.
13363+ =/ reached=(unit dgscan) (dg-scan ~[u.found] sub (dec fuel) blocked)
13364+ ?~ reached ~
13365+ $(tags t.tags, fuel fuel.u.reached, blocked ids.u.reached)
13366+::
13367+++ dg-generalize
13368+ |= [typ=itype env=ienv pending=(list dgo) tags=(list ipending) captured=(list @ud) state=istate fuel=@ud]
13369+ ^- (unit ischeme)
13370+ :: Bound the obligation list and all graph/substitution walks. The
13371+ :: substitution is assumed checker-owned and occurs-checked.
13372+ ?: (gth (lent pending) 64) ~
13373+ =/ capt=(unit dgscan) (dg-scan-ids captured sub.state fuel ~)
13374+ ?~ capt ~
13375+ =/ env-free=(unit dgscan) (dg-env env sub.state fuel.u.capt ids.u.capt)
13376+ ?~ env-free ~
13377+ =/ obligations=(unit dgscan) (dg-obligations pending sub.state fuel.u.env-free ids.u.env-free)
13378+ ?~ obligations ~
13379+ =/ tagged=(unit dgscan) (dg-tags tags sub.state fuel.u.obligations ids.u.obligations)
13380+ ?~ tagged ~
13381+ =/ bounded=(unit dgscan) (dg-scan ~[typ] sub.state fuel.u.tagged ~)
13382+ ?~ bounded ~
13383+ =/ normalized=itype (itype-normalize typ sub.state)
13384+ =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
13385+ =/ quantified=(list @ud) (skim vars |=(n=@ud !(lien ids.u.tagged |=(b=@ud =(b n)))))
13386+ `[[normalized quantified]]
13387+::
13388++$ dgcommit [env=ienv state=istate]
13389+:: A branch literal must not acquire a value face through replay.
13390+++ dg-literal-target-safe
13391+ |= target=itype
13392+ ^- ?
13393+ ?: ?=(%union -.target)
13394+ (levy cases.target |=(c=itype ?=(?(%const %cell) -.c)))
13395+ ?=(?(%const %atom %any-atom %flag %noun) -.target)
13396+::
13397+++ dg-replay-edges
13398+ |= [edges=(list dgo) state=istate fuel=@ud]
13399+ ^- (unit istate)
13400+ ?~ edges `state
13401+ ?: =(0 fuel) ~
13402+ =/ trial=ifit (itype-fit left.i.edges right.i.edges sub.state next.state)
13403+ ?. ?=(%ok -.trial) ~
13404+ =/ valid=?
13405+ ?: ?=(%tag -.left.i.edges)
13406+ ?. constructor.left.i.edges
13407+ =/ closed=(unit dgscan) (dg-scan ~[right.i.edges] sub.trial 512 ~)
13408+ ?~ closed |
13409+ ?^ ids.u.closed |
13410+ (dg-literal-target-safe (itype-normalize right.i.edges sub.trial))
13411+ =((itype-walk left.i.edges sub.trial) (itype-walk right.i.edges sub.trial))
13412+ =((itype-walk left.i.edges sub.trial) (itype-walk right.i.edges sub.trial))
13413+ ?. valid ~
13414+ $(edges t.edges, state state(sub sub.trial, next next.trial), fuel (dec fuel))
13415+::
13416+++ dg-close-env
13417+ |= [env=ienv sub=isub fuel=@ud]
13418+ ^- (unit ienv)
13419+ ?~ env `~
13420+ ?: =(0 fuel) ~
13421+ =/ s=ischeme scheme.i.env
13422+ :: Quantified IDs are scheme-local and cannot be rewritten on publication.
13423+ ?. (levy vars.s |=(n=@ud ?=(~ (itype-lookup n sub)))) ~
13424+ =/ bounded=(unit dgscan) (dg-scan ~[typ.s] sub (dec fuel) ~)
13425+ ?~ bounded ~
13426+ =/ normalized=itype (itype-normalize typ.s sub)
13427+ ?: (itype-has-tag normalized) ~
13428+ =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
13429+ ?. (levy vars |=(n=@ud (lien vars.s |=(v=@ud =(v n))))) ~
13430+ =/ rest=(unit ienv) (dg-close-env t.env sub fuel.u.bounded)
13431+ ?~ rest ~
13432+ `[[name.i.env [normalized vars.s]] u.rest]
13433+::
13434+:: A deferred boolean branch has exactly the two literal flag patterns.
13435+:: Arms are inferred in order. Equal types are retained; two direct pending
13436+:: literals may instead retain source-owned obligations for later context.
13437+++ dg-boolean-patterns
13438+ |= e=expr
13439+ ^- ?
13440+ ?. ?=(%branch -.e) |
13441+ ?~ arms.e |
13442+ ?~ t.arms.e |
13443+ ?^ t.t.arms.e |
13444+ =/ x=arm i.arms.e
13445+ =/ y=arm i.t.arms.e
13446+ ?. &(?=(%lit -.pat.x) ?=(%lit -.pat.y)) |
13447+ ?. &(=(%loobean form.lit.pat.x) =(%loobean form.lit.pat.y)) |
13448+ !=(val.lit.pat.x val.lit.pat.y)
13449+:: Only a direct source literal which created its own unbound pending tag
13450+:: may create a branch edge. The caller must retain the exact source and state.
13451+++ dg-owned-arm-literal
13452+ |= [e=expr t=itype tags=(list ipending) sub=isub initial=@ud]
13453+ ^- ?
13454+ ?. ?=(%lit -.e) |
13455+ ?. ?=(%tag -.t) |
13456+ ?: constructor.t |
13457+ ?. =(lit.e literal.t) |
13458+ ?: (lth id.t initial) |
13459+ ?^ (itype-lookup id.t sub) |
13460+ (lien tags |=(x=ipending &(=(id.x id.t) =(literal.x literal.t))))
13461+++ dg-boolean-branch
13462+ |= [e=expr env=ienv state=istate]
13463+ ^- iresult
13464+ ?. (dg-boolean-patterns e) [%| ["deferred branch patterns need unsupported inference" ~]]
13465+ ?> ?=(%branch -.e)
13466+ ?> ?=(^ arms.e)
13467+ ?> ?=(^ t.arms.e)
13468+ =/ x=arm i.arms.e
13469+ =/ y=arm i.t.arms.e
13470+ =/ subject=iresult (infer-fragment subject.e env state)
13471+ ?: ?=(%| -.subject) subject
13472+ =/ su=(unit isub) (itype-unify typ.p.subject [%flag ~] sub.state.p.subject)
13473+ ?~ su [%| ["deferred branch subject does not unify with ?" ~]]
13474+ =/ left=iresult (infer-fragment val.x env state.p.subject(sub u.su))
13475+ ?: ?=(%| -.left) left
13476+ =/ right=iresult (infer-fragment val.y env state.p.left)
13477+ ?: ?=(%| -.right) right
13478+ ?. (dg-stable-fit typ.p.left typ.p.right sub.state.p.right)
13479+ =/ st=istate state.p.right
13480+ ?. (dg-owned-arm-literal val.x typ.p.left tags.st sub.st next.state)
13481+ [%| ["deferred branch arm context needs unsupported inference" ~]]
13482+ ?. (dg-owned-arm-literal val.y typ.p.right tags.st sub.st next.state)
13483+ [%| ["deferred branch arm context needs unsupported inference" ~]]
13484+ ?> ?=(%tag -.typ.p.left)
13485+ ?> ?=(%tag -.typ.p.right)
13486+ ?: =(id.typ.p.left id.typ.p.right)
13487+ [%| ["deferred branch arm context needs unsupported inference" ~]]
13488+ ?: (gth (lent obligations.st) 62)
13489+ [%| ["deferred branch arm context needs unsupported inference" ~]]
13490+ =/ result=itype [%var next.st]
13491+ =/ ex=dgo [typ.p.left result (span-of val.x) (span-of e)]
13492+ =/ ey=dgo [typ.p.right result (span-of val.y) (span-of e)]
13493+ [%& result st(next +(next.st), obligations [ex ey obligations.st])]
13494+ [%& typ.p.left state.p.right]
13495+::
13496+:: A direct tuple literal may wait for a later exact result context.
13497+:: Each pending literal retains its source tag and its own fit obligation.
13498+++ dg-infer-tuple-items
13499+ |= [items=(list item) env=ienv state=istate]
13500+ ^- iresult
13501+ ?~ items [%| ["empty cell is not supported by partial inference" ~]]
13502+ =/ head=iresult (infer-fragment val.i.items env state)
13503+ ?: ?=(%| -.head) head
13504+ =/ typ=itype typ.p.head
13505+ =/ st=istate state.p.head
13506+ =/ adjusted=(unit [typ=itype state=istate])
13507+ ?. (dg-owned-arm-literal val.i.items typ tags.st sub.st next.state) `[typ st]
13508+ ?: (gth (lent obligations.st) 63) ~
13509+ =/ pending=itype [%var next.st]
13510+ =/ edge=dgo [typ pending (span-of val.i.items) at.i.items]
13511+ `[pending st(next +(next.st), obligations [edge obligations.st])]
13512+ ?~ adjusted [%| ["deferred tuple context needs unsupported inference" ~]]
13513+ =. typ typ.u.adjusted
13514+ =. st state.u.adjusted
13515+ =. typ ?~(face.i.items typ [%face u.face.i.items typ])
13516+ ?~ t.items [%& typ st]
13517+ =/ tail=iresult $(items t.items, state st)
13518+ ?: ?=(%| -.tail) tail
13519+ [%& [%cell typ typ.p.tail] state.p.tail]
13520+::
13521+:: Deferred inference uses only source forms whose successful fit sites are
13522+:: guarded below; a shared source-node budget bounds this screen.
13523+++ dg-safe-expressions
13524+ |= [todo=(list expr) fuel=@ud]
13525+ ^- (unit @ud)
13526+ ?~ todo `fuel
13527+ =/ first=(unit @ud) (dg-safe-expression i.todo fuel)
13528+ ?~ first ~
13529+ $(todo t.todo, fuel u.first)
13530+++ dg-safe-items
13531+ |= [items=(list item) fuel=@ud]
13532+ ^- (unit @ud)
13533+ ?~ items `fuel
13534+ =/ first=(unit @ud) (dg-safe-expression val.i.items fuel)
13535+ ?~ first ~
13536+ $(items t.items, fuel u.first)
13537+++ dg-safe-expression
13538+ |= [e=expr fuel=@ud]
13539+ ^- (unit @ud)
13540+ ?: =(0 fuel) ~
13541+ =. fuel (dec fuel)
13542+ ?+ -.e ~
13543+ ?(%lit %ctor) `fuel
13544+ %wing ?:(?=([@ ~] names.e) `fuel ~)
13545+ %str
13546+ ?. (levy pieces.e |=(p=piece ?=(%text -.p))) ~
13547+ `fuel
13548+ %group $(e inner.e, fuel fuel)
13549+ %body
13550+ ?^ defs.e ~
13551+ $(e final.e, fuel fuel)
13552+ %gate $(e body.e, fuel fuel)
13553+ %gate-wide $(e body.e, fuel fuel)
13554+ %tuple (dg-safe-items items.e fuel)
13555+ %branch
13556+ ?. (dg-boolean-patterns e) ~
13557+ ?> ?=(^ arms.e)
13558+ ?> ?=(^ t.arms.e)
13559+ =/ subject=(unit @ud) $(e subject.e, fuel fuel)
13560+ ?~ subject ~
13561+ (dg-safe-expressions ~[val.i.arms.e val.i.t.arms.e] u.subject)
13562+ %cast $(e val.e, fuel fuel)
13563+ %call
13564+ =/ head=(unit @ud) $(e head.e, fuel fuel)
13565+ ?~ head ~
13566+ (dg-safe-expressions args.e u.head)
13567+ ==
13568+:: Exact normalized equality is preserved by all later substitutions.
13569+:: The bounded scan declines opaque types and oversized inputs.
13570+++ dg-stable-fit
13571+ |= [actual=itype expected=itype sub=isub]
13572+ ^- ?
13573+ ?~ (dg-scan ~[actual expected] sub 512 ~) |
13574+ =((itype-normalize actual sub) (itype-normalize expected sub))
13575+::
13576+:: A positional call peels sample-slot faces during its separate face check.
13577+:: Require its argument, sample and result closed so that check stays valid.
13578+++ dg-stable-call-fit
13579+ |= [actual=itype expected=itype product=itype sub=isub positional=?]
13580+ ^- ?
13581+ =/ checked=(unit dgscan) (dg-scan ~[actual expected product] sub 512 ~)
13582+ ?~ checked |
13583+ ?: &(positional ?=(^ ids.u.checked)) |
13584+ =((itype-normalize actual sub) (itype-normalize expected sub))
13585+::
13586+:: One definition attempt retains state only when inference succeeds.
13587++$ dg-step [env=ienv state=istate pending=(list dgo)]
13588+++ dg-stage-one
13589+ |= [d=def env=ienv state=istate]
13590+ ^- (unit dg-step)
13591+ ?> ?=(%value -.d)
13592+ ?~ (dg-safe-expression val.d 512) ~
13593+ =/ local=istate (reserve-def-caps val.d state)
13594+ :: This first slice declines all written capitals and holes/projections.
13595+ ?^ caps.local ~
13596+ =/ ordinary=iresult (infer-fragment val.d env local)
13597+ ?: ?=(%| -.ordinary) ~
13598+ =/ typ=itype typ.p.ordinary
13599+ =/ after=istate state.p.ordinary
13600+ =/ edges=(list dgo) obligations.after
13601+ ?. =(binders.after binders.state) ~
13602+ ?. =(molds.after molds.state) ~
13603+ ?. =(globals.after globals.state) ~
13604+ ?. =(externals.after externals.state) ~
13605+ ?. =(surs.after surs.state) ~
13606+ ?. =(mark-externals.after mark-externals.state) ~
13607+ ?. =(marks.after marks.state) ~
13608+ ?. =(jimports.after jimports.state) ~
13609+ ?. =(reserved-molds.after reserved-molds.state) ~
13610+ ?. =(params.after params.state) ~
13611+ ?. =(active.after active.state) ~
13612+ ?. =(in-mold.after in-mold.state) ~
13613+ ?. =(at.after at.state) ~
13614+ ?. =(top-molds.after top-molds.state) ~
13615+ ?. =(prelude.after prelude.state) ~
13616+ ?. =(gate-defs.after gate-defs.state) ~
13617+ ?. =(head-evidence.after head-evidence.state) ~
13618+ ?. =(grec-index.after grec-index.state) ~
13619+ ?. =(defer.after defer.state) ~
13620+ ?. =(holes.after holes.state) ~
13621+ ?. =(caps.after caps.state) ~
13622+ ?. =(projections.after projections.state) ~
13623+ ?: (unsupported-atom-vars (itype-normalize typ sub.after) caps.after binders.after sub.after) ~
13624+ ?: (itype-has-nvar (itype-normalize typ sub.after)) ~
13625+ =/ scheme=(unit ischeme) (dg-generalize typ env edges tags.after ~ after 32.768)
13626+ ?~ scheme ~
13627+ `[[[name.d u.scheme] env] after edges]
13628+:: Retry only definitions that did not infer. Successful definitions are
13629+:: committed into the local transaction, never published until all close.
13630+++ dg-stage
13631+ |= [ds=(list def) base=ienv env=ienv state=istate pending=(list dgo) fuel=@ud]
13632+ ^- (unit dgcommit)
13633+ ?: (gth fuel 64) ~
13634+ ?: (gth (lent ds) fuel) ~
13635+ =/ remaining=(list def) ds
13636+ =/ waiting=(list def) ~
13637+ =/ progress=? |
13638+ =/ attempts=@ud (mul fuel fuel)
13639+ |-
13640+ ?~ remaining
13641+ ?^ waiting
13642+ ?. progress ~
13643+ $(remaining (flop waiting), waiting ~, progress |)
13644+ =/ replayed=(unit istate) (dg-replay-edges pending state 64)
13645+ ?~ replayed ~
13646+ ?: (pending-tags tags.u.replayed sub.u.replayed) ~
13647+ =/ closed-edges=(unit dgscan) (dg-obligations pending sub.u.replayed 32.768 ~)
13648+ ?~ closed-edges ~
13649+ ?^ ids.u.closed-edges ~
13650+ =/ rechecked=(unit istate) (dg-replay-edges pending u.replayed 64)
13651+ ?~ rechecked ~
13652+ ?. =(sub.u.rechecked sub.u.replayed) ~
13653+ ?. =(next.u.rechecked next.u.replayed) ~
13654+ =/ closed=(unit ienv) (dg-close-env env sub.u.replayed 32.768)
13655+ ?~ closed ~
13656+ `[[u.closed u.replayed(defer ~, obligations ~)]]
13657+ ?: =(0 attempts) ~
13658+ =. attempts (dec attempts)
13659+ =/ d=def i.remaining
13660+ ?: ?=(%mold -.d) $(remaining t.remaining)
13661+ ?^ (ienv-lookup name.d base) $(remaining t.remaining)
13662+ ?^ (ienv-lookup name.d env) ~
13663+ =/ done=(unit dg-step) (dg-stage-one d env state)
13664+ ?~ done $(remaining t.remaining, waiting [d waiting])
13665+ $(remaining t.remaining, env env.u.done, state state.u.done, pending pending.u.done, progress &)
13666+::
13667+:: Cheap bounded eligibility check on the already parsed source. This
13668+:: deliberately covers only direct constructor calls beneath transparent
13669+:: groups, gates, casts and definition-free bodies. Other shapes decline
13670+:: this fallback without a second parse or resolution pass.
13671+++ dg-direct-source
13672+ |= [e=expr fuel=@ud]
13673+ ^- ?
13674+ ?: =(0 fuel) |
13675+ ?+ -.e |
13676+ %group $(e inner.e, fuel (dec fuel))
13677+ %gate $(e body.e, fuel (dec fuel))
13678+ %gate-wide $(e body.e, fuel (dec fuel))
13679+ %cast $(e val.e, fuel (dec fuel))
13680+ %body ?~(defs.e $(e final.e, fuel (dec fuel)) |)
13681+ %call
13682+ ?. ?=([* ~] args.e) |
13683+ ?=(%ctor -.i.args.e)
13684+ ==
13685+++ dg-source-candidate
13686+ |= [ds=(list def) fuel=@ud]
13687+ ^- ?
13688+ ?~ ds |
13689+ ?: =(0 fuel) |
13690+ ?. ?=(%value -.i.ds) $(ds t.ds, fuel (dec fuel))
13691+ ?: (dg-direct-source val.i.ds 64) &
13692+ $(ds t.ds, fuel (dec fuel))
13693+::
13694+++ dg-prepared-source
13695+ |= [e=expr fuel=@ud]
13696+ ^- ?
13697+ ?: (dg-direct-source e fuel) &
13698+ ?: =(0 fuel) |
13699+ ?+ -.e |
13700+ %group $(e inner.e, fuel (dec fuel))
13701+ %gate $(e body.e, fuel (dec fuel))
13702+ %gate-wide $(e body.e, fuel (dec fuel))
13703+ %cast $(e val.e, fuel (dec fuel))
13704+ %body ?~(defs.e $(e final.e, fuel (dec fuel)) |)
13705+ %tuple &
13706+ ==
13707+++ dg-prepared-candidate
13708+ |= [ds=(list def) fuel=@ud]
13709+ ^- ?
13710+ ?~ ds |
13711+ ?: =(0 fuel) |
13712+ ?. ?=(%value -.i.ds) $(ds t.ds, fuel (dec fuel))
13713+ ?: (dg-prepared-source val.i.ds 64) &
13714+ $(ds t.ds, fuel (dec fuel))
13715+::
13716+++ dg-interface-safe
13717+ |= [env=ienv]
13718+ ^- ?
13719+ ?~ env &
13720+ =/ sc=ischeme scheme.i.env
13721+ ?: |((itype-has-hidden-recursive typ.sc) (itype-has-hidden-generic typ.sc)) |
13722+ ?: (gth (lent vars.sc) 26) |
13723+ $(env t.env)
13724+:: Parse status and the transaction result come from the same source parse.
13725++$ dgparse [parsed=? result=(unit dgcommit)]
13726+++ dg-root-source
13727+ |= [at=path src=@t]
13728+ ^- (unit dgcommit)
13729+ result:(dg-root-detail at src)
13730+++ dg-root-detail
13731+ |= [at=path src=@t]
13732+ ^- dgparse
13733+ =/ parsed (parse at src)
13734+ ?: ?=(%| -.parsed) [| ~]
13735+ =/ transact
13736+ |.
13737+ ?^ imports.p.parsed ~
13738+ ?. (module-scope-valid p.parsed ~ ~) ~
13739+ ?^ (duplicate-defs defs.p.parsed) ~
13740+ =/ defs=(list def) defs.p.parsed
13741+ ?: (gth (lent defs) 64) ~
13742+ =/ molds=imolds (collect-simple-molds defs)
13743+ =/ globals=(list term) (global-value-names defs)
13744+ =/ resolution=iresolved (resolve-groups defs molds globals ~ ~ ~ ~ ~ ~ at ~)
13745+ ?^ grouped.resolution ~
13746+ ?^ artifacts.resolution ~
13747+ =/ base=ienv env.resolution
13748+ =/ free=(unit dgscan) (dg-env base ~ 32.768 ~)
13749+ ?~ free ~
13750+ ?^ ids.u.free ~
13751+ =/ all=(unit dgscan) (dg-all-env-ids base 32.768 ~)
13752+ ?~ all ~
13753+ =/ fresh=@ud (dg-next-id ids.u.all 0)
13754+ =/ st=istate *istate
13755+ =. st st(next fresh, defer `~, molds molds, globals globals, at at, top-molds (turn molds |=(m=[name=term body=shape] name.m)), in-mold |, jrec-fuel 256)
13756+ =/ checked-molds=(each imold-types @t) (module-mold-types molds st)
13757+ ?: ?=(%| -.checked-molds) ~
13758+ (dg-stage defs base base st ~ 64)
13759+ ::
13760+ [& (transact)]
13761+:: The caller supplies the trusted prepared prelude. This transaction is
13762+:: only report evidence; the ordinary module resolver does not publish it.
13763+++ dg-root-prepared
13764+ |= [at=path src=@t prepared=iprelude]
13765+ ^- (unit dgcommit)
13766+ ?: ?=([%ui %api *] at) ~
13767+ ?: ?=([%ui %stores *] at) ~
13768+ ?: (gth (met 3 src) 65.536) ~
13769+ =/ parsed (parse at src)
13770+ ?: ?=(%| -.parsed) ~
13771+ ?^ imports.p.parsed ~
13772+ ?. (module-scope-valid p.parsed values.prepared molds.prepared) ~
13773+ ?^ (duplicate-defs defs.p.parsed) ~
13774+ =/ defs=(list def) defs.p.parsed
13775+ ?: (gth (lent defs) 64) ~
13776+ ?: (lien (global-value-names defs) |=(n=term =(n %main))) ~
13777+ ?. (dg-prepared-candidate defs 64) ~
13778+ =/ local-molds=imolds (collect-simple-molds defs)
13779+ =/ globals=(list term) (weld values.prepared (global-value-names defs))
13780+ =/ iface=ifile iface.prepared
13781+ =/ prelude=(unit ifile) `iface
13782+ =/ resolution=iresolved
13783+ (resolve-groups defs local-molds globals ~ ~ ~ ~ ~ molds.prepared at prelude)
13784+ ?^ grouped.resolution ~
13785+ ?^ artifacts.resolution ~
13786+ =/ base=ienv env.resolution
13787+ =/ templates=ienv
13788+ (turn molds.iface |=(x=[name=term template=ischeme] [name.x template.x]))
13789+ =/ all-env=ienv (weld base (weld values.iface templates))
13790+ =/ free=(unit dgscan) (dg-env all-env ~ 32.768 ~)
13791+ ?~ free ~
13792+ ?^ ids.u.free ~
13793+ =/ all=(unit dgscan) (dg-all-env-ids all-env 32.768 ~)
13794+ ?~ all ~
13795+ =/ fresh=@ud (dg-next-id ids.u.all 0)
13796+ =/ st=istate *istate
13797+ =. st st(next fresh, defer `~, molds local-molds, globals globals, at at, reserved-molds molds.prepared, prelude prelude, top-molds (turn local-molds |=(m=[name=term body=shape] name.m)), in-mold |, jrec-fuel 256)
13798+ =/ checked-molds=(each imold-types @t) (module-mold-types local-molds st)
13799+ ?: ?=(%| -.checked-molds) ~
13800+ (dg-stage defs base base st ~ 64)
13801+::
13802+++ dg-all-env-ids
13803+ |= [env=ienv fuel=@ud ids=(list @ud)]
13804+ ^- (unit dgscan)
13805+ ?~ env `[ids fuel]
13806+ ?: =(0 fuel) ~
13807+ =/ sc=ischeme scheme.i.env
13808+ ?: (itype-has-tag typ.sc) ~
13809+ =/ raw=(unit dgscan) (dg-scan ~[typ.sc] ~ (dec fuel) ids)
13810+ ?~ raw ~
13811+ =/ quant=(unit dgscan) (dg-scan-ids vars.sc ~ fuel.u.raw ids.u.raw)
13812+ ?~ quant ~
13813+ $(env t.env, fuel fuel.u.quant, ids ids.u.quant)
13814+::
13815+++ dg-next-id
13816+ |= [ids=(list @ud) largest=@ud]
13817+ ^- @ud
13818+ ?~ ids +(largest)
13819+ $(ids t.ids, largest (max largest i.ids))
13820+::
13821+++ dg-eligible-ctor
13822+ |= [e=expr head=itype actual=itype expected=itype state=istate]
13823+ ^- (unit dgo)
13824+ ?. ?=(%call -.e) ~
13825+ ?. ?=([* ~] args.e) ~
13826+ ?. ?=(%ctor -.i.args.e) ~
13827+ ?. ?=(%fn -.head) ~
13828+ ?. ?=(%fn -.expected) ~
13829+ ?. ?=(%tag -.actual) ~
13830+ ?. constructor.actual ~
13831+ ?. ?=(%var -.product.expected) ~
13832+ ?^ (itype-lookup id.product.expected sub.state) ~
13833+ =/ bounded=(unit dgscan) (dg-scan ~[sample.expected] sub.state 256 ~)
13834+ ?~ bounded ~
13835+ ?^ ids.u.bounded ~
13836+ `[[actual expected (span-of i.args.e) (span-of head.e)]]
13837+::
13838+:: Experimental per-module, source-derived recursive tree index.
13839+:: The two tags and the exact children/list/self layout are fixed-shape
13840+:: checks, so ordinary definitions incur no type-tree or source scans.
13841+++ grec-tagged-fields
13842+ |= sh=shape
13843+ ^- (unit [tag=@ fields=(list field)])
13844+ ?. ?=(%cell -.sh) ~
13845+ ?~ fields.sh ~
13846+ =/ head=field i.fields.sh
13847+ ?. ?=(%bare -.head) ~
13848+ ?. ?=(%const -.shape.head) ~
13849+ ?. &(?=(%term form.lit.shape.head) =(%tas aura.lit.shape.head)) ~
13850+ `[val.lit.shape.head t.fields.sh]
13851+++ grec-tree-children
13852+ |= [fs=(list field) param=@t]
13853+ ^- (unit field)
13854+ ?~ fs ~
13855+ ?~ t.fs `i.fs
13856+ ?^ t.t.fs ~
13857+ =/ event=field i.fs
13858+ =/ kids=field i.t.fs
13859+ ?. &(?=(%face -.event) ?=(%face -.kids)) ~
13860+ ?. !=(name.event name.kids) ~
13861+ ?. ?=(%fn -.shape.event) ~
13862+ ?. ?=(%aura -.sample.shape.event) ~
13863+ ?. =(%t aura.sample.shape.event) ~
13864+ ?. ?=(%tvar -.product.shape.event) ~
13865+ ?. =(param name.product.shape.event) ~
13866+ `kids
13867+::
13868+++ grec-tree-proof
13869+ |= [name=term sh=shape]
13870+ ^- ?
13871+ ?. ?=(%generic -.sh) |
13872+ ?. ?=([@ ~] vars.sh) |
13873+ =/ param=@t i.vars.sh
13874+ ?. ?=(%union -.body.sh) |
13875+ ?. ?=([* [* ~]] cases.body.sh) |
13876+ =/ a=(unit [tag=@ fields=(list field)]) (grec-tagged-fields i.cases.body.sh)
13877+ =/ b=(unit [tag=@ fields=(list field)]) (grec-tagged-fields i.t.cases.body.sh)
13878+ ?~ a |
13879+ ?~ b |
13880+ ?. !=(tag.u.a tag.u.b) |
13881+ ?. ?=([* ~] fields.u.a) |
13882+ =/ value=field i.fields.u.a
13883+ ?. ?=(%face -.value) |
13884+ ?. ?=(%aura -.shape.value) |
13885+ ?. =(%t aura.shape.value) |
13886+ =/ selected=(unit field) (grec-tree-children fields.u.b param)
13887+ ?~ selected |
13888+ =/ kids=field u.selected
13889+ ?. ?=(%face -.kids) |
13890+ ?. ?=(%apply -.shape.kids) |
13891+ ?. =(ref.shape.kids ~[%list]) |
13892+ ?. ?=([* ~] args.shape.kids) |
13893+ =/ self=shape i.args.shape.kids
13894+ ?. ?=(%apply -.self) |
13895+ ?. =(ref.self ~[name]) |
13896+ ?. ?=([* ~] args.self) |
13897+ ?. ?=(%tvar -.i.args.self) |
13898+ =(name.i.args.self param)
13899++$ grec-collected [molds=imolds proofs=(map term shape)]
13900+:: Experimental one-layer analysis view, never an exported mold identity.
13901+++ grec-unfold-view
13902+ |= [typ=itype fuel=@ud]
13903+ ^- (unit [view=itype left=@ud])
13904+ ?. ?=(%grec -.typ) ~
13905+ ?: =(fuel 0) ~
13906+ ?. ?=([* ~] args.typ) ~
13907+ =/ sh=shape proof.typ
13908+ ?. (grec-tree-proof name.typ sh) ~
13909+ ?> ?=(%generic -.sh)
13910+ ?> ?=([@ ~] vars.sh)
13911+ ?> ?=(%union -.body.sh)
13912+ ?> ?=([* [* ~]] cases.body.sh)
13913+ =/ ca=shape i.cases.body.sh
13914+ =/ cb=shape i.t.cases.body.sh
13915+ ?> ?=(%cell -.ca)
13916+ ?> ?=(%cell -.cb)
13917+ ?> ?=([* [* ~]] fields.ca)
13918+ ?> ?=([* *] fields.cb)
13919+ =/ tag-a=field i.fields.ca
13920+ =/ tag-b=field i.fields.cb
13921+ ?> ?=(%bare -.tag-a)
13922+ ?> ?=(%bare -.tag-b)
13923+ ?> ?=(%const -.shape.tag-a)
13924+ ?> ?=(%const -.shape.tag-b)
13925+ =/ text-field=field i.t.fields.ca
13926+ ?> ?=(%face -.text-field)
13927+ =/ branch=(list field) t.fields.cb
13928+ =/ kids=(unit field) (grec-tree-children branch i.vars.sh)
13929+ ?~ kids ~
13930+ ?> ?=(%face -.u.kids)
13931+ =/ children=itype [%face name.u.kids [%collection %list ~[typ]]]
13932+ ?> ?=(^ branch)
13933+ =/ payload=itype
13934+ ?~ t.branch children
13935+ =/ event=field i.branch
13936+ ?> ?=(%face -.event)
13937+ [%cell [%face name.event [%fn [%atom %t] i.args.typ]] children]
13938+ =/ leaf=itype [%cell [%const lit.shape.tag-a] [%face name.text-field [%atom %t]]]
13939+ =/ node=itype [%cell [%const lit.shape.tag-b] payload]
13940+ `[[%union ~[leaf node] ~ ~ ~] (dec fuel)]
13941+::
13942+++ grec-collect-molds
13943+ |= ds=(list def)
13944+ ^- grec-collected
13945+ ?~ ds [~ *(map term shape)]
13946+ =/ rest=grec-collected $(ds t.ds)
13947+ ?. ?=(%mold -.i.ds) rest
13948+ =/ name=term name.i.ds
13949+ =/ body=shape shape.i.ds
13950+ =/ proofs=(map term shape) proofs.rest
13951+ =? proofs (grec-tree-proof name body) (~(put by proofs) name body)
13952+ [[[name body] molds.rest] proofs]
13953+::
13954+
195013955--