@@ -26,7 +26,9 @@
26:: likely reading and are listed, with the doc's words, for the doc's
26:: 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
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
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).
29+:: the parser finds an earlier error first, as in `++ 2nd 5`, or moves
30+:: one back to the start of its text, as in `++ x @sd` (2.0, 2.8, and
31+:: section 3, Errors).
31:: ===================================================================
33:: ===================================================================
32:: 1. Positions
34:: 1. Positions
@@ -52,7 +54,12 @@
52:: only, and milestone 1's errors use starts only, so ends are first
54:: only, and milestone 1's errors use starts only, so ends are first
53:: used by milestone 2's excerpts. Until then +check-spans tests the two
55:: used by milestone 2's excerpts. Until then +check-spans tests the two
54:: rules above on every tree +golden prints, and a tree that breaks one
56:: rules above on every tree +golden prints, and a tree that breaks one
55−:: ends with a line "SPAN ERROR: (<kind> <start> to <end>) <why>".
57+:: ends with a line "SPAN ERROR: (<kind> <start> to <end>) <why>". It
58+:: finds each node's end from the tokens alone, matching each opener
59+:: with its closer on the line, so a node that stops at a child where
60+:: its closer follows fails it, and +check-spans-test plants such
61+:: wrong ends to show that it does (tools/hoon check-spans-test prints
62+:: the empty list, <<>>, when it passes).
57:: ===================================================================
64:: ===================================================================
58:: 2. The layout pass (+layout)
65:: 2. The layout pass (+layout)
@@ -62,17 +69,22 @@
62:: crosses a line break, and only layout tokens join lines.
69:: crosses a line break, and only layout tokens join lines.
64:: 2.0 Errors. +layout never fails. Where the text breaks a rule of this
71:: 2.0 Errors. +layout never fails. Where the text breaks a rule of this
65−:: section, it emits one error token, [%error msg], at the first
72+:: section, it emits one error token, [%error msg from c], at the first
66−:: character that breaks it, and stops reading. The parser accepts no
73+:: character that breaks it, and stops reading. from is where the text
74+:: it was reading began, c is that text's first character, and the
75+:: token is tight when that text follows the previous token with no
67−:: error token, so it reports whichever comes first, its own error or
76+:: space. The parser accepts no error token, so it reports whichever
68−:: this one (section 3, Errors). Every error, from either stage, points
77+:: comes first, its own error or this one (section 3, Errors). Every
69−:: at the first character where the text stops being the start of any
78+:: error, from either stage, points at the first character where the
70−:: valid module: everything before it could still be right. Hoon's
79+:: text stops being the start of any valid module: everything before
71−:: parser reports errors the same way, and the golden corpus's expect
80+:: it could still be right. Hoon's parser reports errors the same way,
72−:: lines assume it. It also puts `++ x ]` on line 1 before a bad string
81+:: and the golden corpus's expect lines assume it. It also puts `++ x
82+:: ]` on line 1 before a bad string on line 9, which a lexer that
73−:: on line 9, which a lexer that failed first would report instead. The
83+:: failed first would report instead. The positions below follow from
84+:: it, for text that could begin a token where it stands; where the
85+:: parser's place can't begin with c at all, the parser moves the
86+:: error back to from, as `++ x @sd` at the @ (section 3, Errors).
74−:: positions below follow from it. Messages quote code in backticks, as
87+:: Messages quote code in backticks, as the parser's do.
75−:: the parser's do (section 3, Errors).
77:: 2.1 Lines. The text is split at every \0a. A final \0a ends the last
89:: 2.1 Lines. The text is split at every \0a. A final \0a ends the last
78:: line rather than starting an empty one. Lines are numbered from 1.
90:: line rather than starting an empty one. Lines are numbered from 1.
@@ -164,7 +176,8 @@
164:: $?( $? $-( glyphs; $- followed by anything but ( is an error
176:: $?( $? $-( glyphs; $- followed by anything but ( is an error
165:: at 3rd, "`$-` has only the wide form `$-(sample
177:: at 3rd, "`$-` has only the wide form `$-(sample
166:: product)`"
178:: product)`"
167−:: ^- ?- !! ? glyphs (? alone is the loobean mold)
179+:: ^- ?- !! ? glyphs (? alone is the loobean mold; ? then a
180+:: character of Hoon's other ? runes is left out, below)
168:: @ aura: @, then [a-z]*, then at most one [A-Z]; the
181:: @ aura: @, then [a-z]*, then at most one [A-Z]; the
169:: token holds the text after @. An aura starting @s or
182:: token holds the text after @. An aura starting @s or
170:: @r is an error at 2nd: "signed and floating-point
183:: @r is an error at 2nd: "signed and floating-point
@@ -186,8 +199,8 @@
186:: an error at 2nd, "`|` begins `|=`, `|=(` or `|$`",
199:: an error at 2nd, "`|` begins `|=`, `|=(` or `|$`",
187:: "`$` begins `$?`, `$?(` or `$-(`", "`^` begins `^-`"
200:: "`$` begins `$?`, `$?(` or `$-(`", "`^` begins `^-`"
188:: : followed by anything but :, an error at 2nd: the
201:: : followed by anything but :, an error at 2nd: the
189−:: table's :~ :* and a:b, else "a comment starts with
202+:: table's :~ :* :- :+ :^ :_ and a:b, else "a comment
190−:: `::`"
203+:: starts with `::`"
191:: anything else an error at it, naming it: "unexpected `,`", with a
204:: anything else an error at it, naming it: "unexpected `,`", with a
192:: hint where one helps (+unexpected): for , . - and <,
205:: hint where one helps (+unexpected): for , . - and <,
193:: what Jibb writes instead
206:: what Jibb writes instead
@@ -195,32 +208,46 @@
195:: Hoon forms the doc leaves out are errors with the doc's reason, as
208:: Hoon forms the doc leaves out are errors with the doc's reason, as
196:: "`|%` is left out: modules are records". Each points where the text
209:: "`|%` is left out: modules are records". Each points where the text
197:: stops being Jibb: at its second character when its first can begin
210:: stops being Jibb: at its second character when its first can begin
198−:: Jibb there, else at its first.
211+:: some Jibb token, else at its first. Where the parser's place can't
212+:: begin with that first character, the parser moves the error to it
213+:: (2.0): `|%` at the top of a file fails at the |, `++ x |%` at the %.
214+:: The doc's list says "such as" of the tall forms and the wide ones,
215+:: so Hoon's runes of the same kinds get the same reason (doc
200:: |% |_ |* 2nd modules are records
218:: |% |_ |* 2nd modules are records
201:: |- 2nd gates recurse by name
219:: |- 2nd gates recurse by name
202−:: $( 1st gates recurse by name; no expression starts $
220+:: $( 2nd gates recurse by name (at the $ where an
221+:: expression goes, as no expression starts $)
203:: $% 2nd $? covers unions
222:: $% 2nd $? covers unions
223+:: ?: ?+ 2nd ?- is the branch, and so for Hoon's other ?
224+:: runes, ?~ ?= ?. ?@ ?^ ?& ?| ?< ?> (?:: is ?
204−:: ?+ ?: 2nd ?- is the branch (?:: is ? and a comment)
225+:: and a comment)
205:: ?! 2nd eq and not are gates
226:: ?! 2nd eq and not are gates
206:: .= 1st eq and not are gates
227:: .= 1st eq and not are gates
207:: !x 2nd not is a gate: ! then anything but ! or >
228:: !x 2nd not is a gate: ! then anything but ! or >
208:: !> /+ 2nd code also runs in the browser
229:: !> /+ 2nd code also runs in the browser
209−:: =< => .* 1st names never shadow, and . reads imports too
230+:: =< => 2nd names never shadow, and . reads imports too
210:: a:b 2nd of the :, right after a name: names never
232:: a:b 2nd of the :, right after a name: names never
211:: shadow, and . reads imports too; write a.b
233:: shadow, and . reads imports too; write a.b
212:: :~ :* 2nd indentation covers them; write ~[…] or […]
234:: :~ :* 2nd indentation covers them; write ~[…] or […]
235+:: :- :+ :^ :_ 2nd indentation covers them; write a cell as [a b]
236+:: %: %- %+ 2nd indentation covers them; a call is (f a b)
213−:: %: %= 2nd indentation covers them
238+:: %= 2nd indentation covers it; write a change, m(a=b)
214−:: == -- 1st the closers are left out: indentation covers
239+:: == 2nd the closers are left out: indentation covers
215−:: them
240+:: -- 1st them
216:: ~| 2nd ~& covers debugging
241:: ~| 2nd ~& covers debugging
242+:: ;: 1st nest the calls, as (add a (add b c))
217:: ; 1st Sail's ; runes are left out: layout is Jibb's
243:: ; 1st Sail's ; runes are left out: layout is Jibb's
218:: elements
244:: elements
219:: ' 1st there is no '…' form: strings are "…"
245:: ' 1st there is no '…' form: strings are "…"
221:: The parser finds the doc's other left-out forms (section 3, Errors):
247:: The parser finds the doc's other left-out forms (section 3, Errors):
248+:: =(a b), =/, *mold, ^-(…), ?-(…) and ~&(…), and Hoon's =+ =? and =.
222−:: =(a b), =/, *mold, ^-(…) and ?-(…). The lexer can't, since =( =/ and *
249+:: The lexer can't, since = and * begin valid Jibb too: open=(not
223−:: begin valid Jibb too: open=(not open.s), scry=/todos, a * mold.
250+:: open.s), scry=/todos, a * mold.
225:: 2.7 Paths. Right after a / or %/ glyph, a run of knot characters
252:: 2.7 Paths. Right after a / or %/ glyph, a run of knot characters
226:: [a-z0-9._~-] is one knot token, tight. So /posts/~zod is / knot / knot;
253:: [a-z0-9._~-] is one knot token, tight. So /posts/~zod is / knot / knot;
@@ -241,17 +268,38 @@
242:: 2.8 Literals. The lexer takes a literal's run (2.6), then reads it
269:: 2.8 Literals. The lexer takes a literal's run (2.6), then reads it
243:: with Hoon's own parser, (nuck:so [[line col] run]), whose edge says
270:: with Hoon's own parser, (nuck:so [[line col] run]), whose edge says
244−:: how much it read and how far it looked (p.edge):
271+:: how much it read and how far it looked (p.edge). Some runs never
272+:: reach it, since they begin an aura Jibb doesn't write, whatever
273+:: follows, or text Hoon's parser crashes on:
274+:: - 0b, 0c, 0i and 0w: an error at 2nd, "Jibb writes no @uw
275+:: literals" and so on. Hoon's parser would read 0b, or a 0c1 whose
276+:: checksum fails, as the number 0 and an error past the run.
277+:: - ~- (a @c), "Jibb writes no @c literals", and ~~ (a cord), "Jibb
278+:: writes no @t literals; strings are "…"", at 2nd. Hoon's reader of
279+:: @c crashes on a control character, as in ~-~1.
280+:: - ~0 and a base-32 digit, at 3rd: Hoon's parser reads a blob there
281+:: and cues it, which can run out of memory, past what mule catches.
282+:: No Jibb literal goes on so, since a year has no leading 0: after
283+:: a letter it is "Jibb writes no blob literals", after a digit the
284+:: date's message (+literal-msg). ~0.1.1 is a date (below).
285+:: - A year BC of 0 or past 292.277.024.401, as in ~0-.1.1, at the -
286+:: that makes it BC: Hoon's +year crashes on it (+year-bc).
287+:: - A fifth sub-second group, after a duration's .. or a date's
288+:: second .., at the dot that begins it: "a date or duration takes
289+:: at most four sub-second groups", as Hoon's do, since its +yule
290+:: crashes on a fifth (+fifth-group).
291+:: A date or duration is also read under mule, so that any other crash
292+:: is an error at the run's start, "Jibb can't read this literal"; other
293+:: runs aren't, since mule costs about a millisecond a call. Then:
245:: - It read the whole run, as an aura Jibb takes: the token. Numbers
294:: - It read the whole run, as an aura Jibb takes: the token. Numbers
246:: take %ud, %ux and %uv: 1.000, 0x1f, 0v5.fdf99 (Hoon reads 0x1F
295:: take %ud, %ux and %uv: 1.000, 0x1f, 0v5.fdf99 (Hoon reads 0x1F
247:: too). ~ runs take %p, %da, %dr and %ta: ~zod, ~sampel-palnet,
296:: too). ~ runs take %p, %da, %dr and %ta: ~zod, ~sampel-palnet,
248−:: ~2026.10.23..14.30.00, ~h1.m30, ~.my-post.
297+:: ~2026.10.23..14.30.00, ~h1.m30, ~.my-post. Its value is Hoon's:
298+:: ~0.1.1 is 1 BC and prints as ~1-.1.1, and ~2026.2.31 is
299+:: ~2026.3.3 (doc question).
249−:: - It read the run or part of it as an aura Jibb doesn't take: 0w1,
300+:: - It read the run or part of it as another aura Jibb doesn't take:
250−:: 0i1, ~~a (a cord), ~-a (a @c). An error at 2nd, "Jibb writes no
301+:: an error at 2nd that names the aura, as "Jibb writes no @if
251−:: @uw literals". A run starting 0b, 0c, 0i or 0w gets that error
302+:: literals".
252−:: before nuck:so reads it, since no Jibb literal goes on that way:
253−:: Hoon's parser would read 0b, or a 0c1 whose checksum fails, as
254−:: the number 0 and an error past the run.
255:: - It read only part of the run, as an aura Jibb takes: that part is
303:: - It read only part of the run, as an aura Jibb takes: that part is
256:: a token, then an error token at p.edge, the furthest character
304:: a token, then an error token at p.edge, the furthest character
257:: Hoon's parser looked at, where Hoon reports it too. 1000 is the
305:: Hoon's parser looked at, where Hoon reports it too. 1000 is the
@@ -267,13 +315,12 @@
267:: d h m or s, if that is later: Hoon's parser reads a syllable's
315:: d h m or s, if that is later: Hoon's parser reads a syllable's
268:: three letters before it looks them up, so it looks past that
316:: three letters before it looks them up, so it looks past that
269:: letter. `++ x ~x` fails at the x, 1:7, as no syllable starts with
317:: letter. `++ x ~x` fails at the x, 1:7, as no syllable starts with
270−:: x, and ~sampel-palnez at the z.
318+:: x, and ~sampel-palnez at the z. The error token's from is the
271−:: A run that starts as a date BC does, ~ and a year then -, fails at the
319+:: run's start, since the whole run is what fails (2.0).
272−:: - if the year is 0 or past 292.277.024.401, before nuck:so sees it:
273−:: Hoon's +year crashes on those years, as in ~0-.1.1 (+year-bc).
274−:: The token is [%lit [form aura val]]: form names the literal rule that
320+:: The token is [%lit [form aura val txt]]: form names the literal rule
275−:: matched, aura and val are the dime Hoon's parser gives. Terms,
321+:: that matched, aura and val are the dime Hoon's parser gives, and txt
276−:: loobeans and the bare ~ are read by hand (2.6).
322+:: is the literal as written. Terms, loobeans and the bare ~ are read by
278:: 2.9 Strings. A " starts a string, which ends on the same line. Up to
325:: 2.9 Strings. A " starts a string, which ends on the same line. Up to
279:: the closing ":
326:: the closing ":
@@ -342,14 +389,15 @@
342:: descent is shorter, and each error names what its construct expected.
389:: descent is shorter, and each error names what its construct expected.
343:: An operand that isn't where an expression starts (a call's argument,
390:: An operand that isn't where an expression starts (a call's argument,
344:: an item, a pair's or unit's operand, the wide gate's body) can't be a
391:: an item, a pair's or unit's operand, the wide gate's body) can't be a
345−:: rune, so there |= is a constructor and needs its term at once:
392+:: rune, so there |= is a constructor and needs its term at once, or
346−:: (state.cart |= %got) is an error at the space after |=, 1:20. A loop
393+:: the ( of the wide gate: in ++ x (state.cart |= %got) the space after
347−:: over many items (definitions, arms, lines, items) is a trap whose
394+:: |= is an error, 1:20. A loop over many items (definitions, arms,
348−:: every step, through +then, is a tail call, so a long module grows no
395+:: lines, items) is a trap whose every step, through +then, is a tail
349−:: stack. Nesting does, by a few frames a level: 100.000 nested
396+:: call, so a long module grows no stack. Nesting does, by a few frames
350−:: parentheses parse, and so does a 20.000-line module. +golden's tree
397+:: a level: 100.000 nested parentheses parse, and so does a 20.000-line
351−:: is another matter: its indent grows with depth, so 7.000 nested
398+:: module. +golden's tree stops indenting past 64 levels (4.2), so its
352−:: parentheses print as 49 MB and 10.000 run out of memory.
399+:: size grows with the text's, not with its square: tools/golden takes
400+:: 8 s on 10.000 nested parentheses, 5.5 s of it building the library.
354:: The EBNF and its nodes (see the types below):
402:: The EBNF and its nodes (see the types below):
355:: module { import NEWLINE } { definition NEWLINE }, then the end
403:: module { import NEWLINE } { definition NEWLINE }, then the end
@@ -357,7 +405,9 @@
357:: "expected a definition, found `/-`; imports come first"
405:: "expected a definition, found `/-`; imports come first"
358:: import /- name -> %sur; /% term -> %mark; /= name pathlit ->
406:: import /- name -> %sur; /% term -> %mark; /= name pathlit ->
359:: %jibb. /% takes % and a name only: no mark is called %0,
407:: %jibb. /% takes % and a name only: no mark is called %0,
360−:: %& or %| (doc question)
408+:: %& or %| (doc question). /='s path has a segment, as it
409+:: names a module's file: /= card / is an error just past
410+:: the / (doc question)
361:: definition +$ name mold, or the mold alone on a deeper line ->
411:: definition +$ name mold, or the mold alone on a deeper line ->
362:: %mold (both layouts give one node); ++ name expr or body
412:: %mold (both layouts give one node); ++ name expr or body
363:: -> %value (a body becomes a %body expr)
413:: -> %value (a body becomes a %body expr)
@@ -404,13 +454,15 @@
404:: - Spaces, comments and blank lines: the layout pass, and Spacing
454:: - Spaces, comments and blank lines: the layout pass, and Spacing
406:: - pathlit as an operand (above), with / alone the empty path.
456:: - pathlit as an operand (above), with / alone the empty path.
407−:: - knot may be empty: only / alone uses that, as the empty path; //
457+:: - knot may be empty: only / alone uses that, as the empty path in
458+:: an expression or a mold, not in an import; // and a trailing /
408−:: and a trailing / are errors (doc question).
459+:: are errors (doc question).
409:: - Open brackets in molds: mold has no open form, so a mold's [ or (
460:: - Open brackets in molds: mold has no open form, so a mold's [ or (
410:: closes on its line, and only $? takes lines below (doc question).
461:: closes on its line, and only $? takes lines below (doc question).
411:: - Two brackets left open on one line, as (column ~[: the last one
462:: - Two brackets left open on one line, as (column ~[: the last one
412:: takes the deeper lines, and the other is then unclosed, an error
463:: takes the deeper lines, and the other is then unclosed, an error
464+:: at the end of that line, where nothing can close it any more
413−:: (doc question).
465+:: (doc question; Errors below).
414:: - Local definitions: the EBNF takes them in every body (of ++, |=,
466:: - Local definitions: the EBNF takes them in every body (of ++, |=,
415:: ^-, ~& and arms), the Runes prose says "inside a gate"; the parser
467:: ^-, ~& and arms), the Runes prose says "inside a gate"; the parser
416:: takes them in every body and leaves the rest to the checker (doc
468:: takes them in every body and leaves the rest to the checker (doc
@@ -428,12 +480,13 @@
428:: right before a closer ) ] or } (the theme example writes `[ space=`),
480:: right before a closer ) ] or } (the theme example writes `[ space=`),
429:: the ( and ) of an application path's segment included; inside
481:: the ( and ) of an application path's segment included; inside
430:: them the expression is spaced as anywhere else, as %/x/(f a)
482:: them the expression is spaced as anywhere else, as %/x/(f a)
431−:: A missing space is an error at the tight token, and so is a space
483+:: A missing space is an error at the tight token, and a space inside
484+:: a tight form, or the end of the line there, is one where it starts
432−:: inside a tight form, at the space (Errors). A rune with children, and
485+:: (Errors). A rune with children, and an import glyph, is followed by
433−:: an import glyph, is followed by a space (or, for $? with its cases
486+:: a space (or, for $? with its cases below, the end of the line).
434−:: below, the end of the line). Items are separated by one or more
487+:: Items are separated by one or more spaces; how many isn't checked.
435−:: spaces; how many isn't checked. This is how the parser makes "one
488+:: This is how the parser makes "one space between items; more for
436−:: space between items; more for alignment" precise (doc question).
489+:: alignment" precise (doc question).
438:: Errors. The parser stops at the first token it can't accept and
491:: Errors. The parser stops at the first token it can't accept and
439:: reports "expected <what>, found <token>", with an optional "; <hint>",
492:: reports "expected <what>, found <token>", with an optional "; <hint>",
@@ -444,30 +497,78 @@
444:: the same depth" (NEWLINE), "a shallower line" (DEDENT), or "the end of
497:: the same depth" (NEWLINE), "a shallower line" (DEDENT), or "the end of
445:: the file" (an empty span, 2.5). Each error points at the first
498:: the file" (an empty span, 2.5). Each error points at the first
446:: character that can't begin a valid module (2.0):
499:: character that can't begin a valid module (2.0):
447−:: - At the token's start; for a layout token, at the start of the
500+:: - At a token the place can't take: just past the part of it that
501+:: could still begin what the place takes (+fail-in, +prefix). That
502+:: is none when the place can't begin with its first character, so
503+:: `++ 2nd 5` fails at the 2, 1:4; a wing's first name where a name
504+:: goes, so `++ a.b 1` fails at the dot, 1:5; else one character,
505+:: as the % of %.y where a term goes, the ~ of ~zod where a mold
506+:: goes (~ alone is one), or a + or ? alone. A layout token is at
448−:: line it begins, or just past the last token at the end of the
507+:: the start of the line it begins, or just past the last token at
449−:: file (+where). So `++ view` above `++ main view` is an error at
508+:: the end of the file (+where). So `++ view` above `++ main view`
450−:: 2:1, the line that isn't deeper.
509+:: is an error at 2:1, the line that isn't deeper.
451:: - Where a tight form needs its next token at once (after name+, `,
510:: - Where a tight form needs its next token at once (after name+, `,
452−:: |= in an operand, name=, the = of a pun, a path's / and %/, a
511+:: |= in an operand, name=, the = of a pun, a / after a path
453−:: typed segment's parts) and finds a space: at the end of the
512+:: segment, a typed segment's parts) and finds a space or the end
454−:: previous token, where the space starts, "expected a term right
513+:: of the line: at the end of the previous token, where the space or
455−:: after `|=`, found a space" (+fail-space). A wing and a ( after a
514+:: the line's end starts, as "expected an operand right after `+`,
515+:: found the end of the line" (+fail-space). No later line can give
516+:: a tight form its next token. A wing and a ( after a space are no
456−:: space are no error: that is a call.
517+:: error: that is a call; nor is / or %/ alone, a whole path.
457−:: - At an error token: the lexer's position and message, unchanged.
518+:: - At an error token: the lexer's position and message, unless the
519+:: text it was reading begins with a character the place can't
520+:: begin with. Then at that character, the lexer's message after
521+:: the parser's (+moved): `++ x @sd` is "expected an expression,
522+:: found `@`; signed and floating-point auras are left out of Jibb"
523+:: at the @, while `+$ x @sd` fails at the s. The place includes
524+:: what could still go on before it: after a call's operand and a
525+:: space, another operand, so `++ x a ?:` fails at the ? and `++ x
526+:: a |%` at the % (+read-operands); after a mold, an import or !!
527+:: that ends a line, nothing, so `+$ x @ |%` fails at the |
528+:: (+bad-end-in); tight after an item, a closer, or after a name
529+:: the ( . + or = of a change, wing, pair or face (+tight-error,
530+:: which doesn't look at what the item was, though it takes no =
531+:: after a call's operand). A : stays where the lexer put it, since
532+:: it could begin a comment. An error token after a space or on a
533+:: later line, where a tight form needed its next token, comes after
534+:: the tight form's error (+fail-space).
535+:: - At layout tokens followed by an error token whose text begins
536+:: the line, both errors are at the line's start, and the lexer's
537+:: message, about that text, says more: a line `==` that closes a
538+:: ?- is "the closer `==` is left out: indentation covers it", not
539+:: "expected the end of the body" (+lexer-error).
540+:: - Where a line's last open bracket or rune took the deeper lines
541+:: while something opened before it on the line still needs a
542+:: closer there or deeper lines of its own: at the end of that
543+:: line, since no later line can supply them (+doomed). `++ x
544+:: (column ~[` above deeper lines is "expected `)` to close the `(`
545+:: at 1:6, found the end of the line; the deeper lines go to the
546+:: last bracket or rune left open on this line", at 1:16.
458−:: - Three pattern errors point inside their token, where it stops
547+:: - Pattern errors point inside their token, where it stops being a
459−:: being a pattern: a date, duration or knot at its second character
548+:: pattern: a date or knot at its second character (~ alone is
460−:: (~ alone is null, and no ship goes on so), ~[ at its [, and a
549+:: null, and no ship goes on so), a duration just past its unit
550+:: letter (~d begins ships, as ~dur), ~[ at its [, and a string
461−:: string with {…} at its {.
551+:: with {…} at its {.
462:: In a bracket, a closer that doesn't match is "expected `]` to close
552:: In a bracket, a closer that doesn't match is "expected `]` to close
463:: the `~[` at 1:6, found `)`", checked before spacing; after an item, a
553:: the `~[` at 1:6, found `)`", checked before spacing; after an item, a
464:: tight token that isn't a closer is "expected a space between items,
554:: tight token that isn't a closer is "expected a space between items,
555+:: found `M`". A ) or ] that closes no bracket opened before it on its
556+:: line adds "this `)` closes no bracket" (+stray), and a closer on a
557+:: line of an open bracket "a bracket open at the end of its line takes
558+:: no closer: its items end at the first line that isn't deeper". Hints
465−:: found `M`". Hints name the left-out forms the lexer can't see (2.6):
559+:: name the left-out forms the lexer can't see (2.6): where an
466−:: where an expression starts, = followed tight by ( is "=(a b) is left
560+:: expression starts, = followed tight by ( is "=(a b) is left out: eq
467−:: out: eq is a gate", = followed tight by / is "=/ is left out: ++
561+:: is a gate"; = followed tight by / is "=/ is left out: ++ defines
468−:: defines values", and * is "*mold is left out: no defaults"; ^- or ?-
562+:: values", and so for Hoon's =+ =? and =.; * is "*mold is left out: no
469−:: followed tight by ( is "the wide form ^-(…) is left out: indentation
563+:: defaults"; ^-, ?- or ~& followed tight by ( is "the wide form ^-(…)
564+:: is left out: indentation covers it". Others name likely slips: |=
565+:: and a space where an operand goes, "a gate in an operand is |=(a
566+:: body)", or before a term "a case's constructor takes its term with
567+:: no space, as |=%got"; name= in a pattern, "patterns take no
568+:: `name=`: a bare name binds, as [a b]"; a capital or a wing where a
569+:: name goes, "a name starts with a lowercase letter" and "a name has
570+:: no `.`"; a lone + where a definition goes, "`+` begins `++` or
470−:: covers it". The messages quote that code in backticks (2.0), as in
571+:: `+$`". The messages quote that code in backticks (2.0), as in
471:: "`=(a b)` is left out: eq is a gate". Examples:
572:: "`=(a b)` is left out: eq is a gate". Examples:
472:: expected `]` or an item on a deeper line, found a line at the same
573:: expected `]` or an item on a deeper line, found a line at the same
@@ -524,7 +625,10 @@
524:: (a string's quoted text, an application path's knots). A node whose
625:: (a string's quoted text, an application path's knots). A node whose
525:: kids are all leaves prints on one line; otherwise each kid goes on its
626:: kids are all leaves prints on one line; otherwise each kid goes on its
526:: own line, indented two more spaces, and the closing parens end the
627:: own line, indented two more spaces, and the closing parens end the
527−:: last kid's line. (module …) always breaks. Bare fields and samples
628+:: last kid's line. (module …) always breaks. Past 64 levels the indent
629+:: stops growing: a deeper line starts with 128 spaces and its depth
630+:: between bars, as `|65| (group 1:69`, so the printed tree's size is
631+:: linear in the text's however deep it nests. Bare fields and samples
528:: print as their mold, and a cell sample as (cell …) of its samples, a
632:: print as their mold, and a cell sample as (cell …) of its samples, a
529:: bare name there as (bind …); unnamed items print as their expr;
633:: bare name there as (bind …); unnamed items print as their expr;
530:: strings print text pieces quoted, between their interpolated exprs;
634:: strings print text pieces quoted, between their interpolated exprs;
@@ -627,7 +731,7 @@
627 [%knot p=@ta] :: path segment
731 [%knot p=@ta] :: path segment
628 [%aura p=@ta] :: @ud as 'ud', @ as ''
732 [%aura p=@ta] :: @ud as 'ud', @ as ''
629 [%tvar p=@t] :: M
733 [%tvar p=@t] :: M
630− [%error p=tape] :: 2.0: what broke
734+ [%error p=tape from=loc c=@] :: 2.0: what broke
633:: +glyph: a token that is its text, and the layout tokens
737:: +glyph: a token that is its text, and the layout tokens
@@ -646,8 +750,10 @@
647:: +lit: a literal other than a string, as Hoon's parsers read it
751:: +lit: a literal other than a string, as Hoon's parsers read it
649−:: form is the literal rule that matched; aura and val are the dime
753+:: form is the literal rule that matched; txt is the literal as
754+:: written, which the printers show, since Hoon's own printing of
755+:: some auras (@da) differs between Hoon versions; aura and val are
650−:: nuck:so gives, or for terms and loobeans:
756+:: the dime nuck:so gives, or for terms and loobeans:
651:: %number 1.000 0x1f 0v5.fdf99 %ud %ux %uv
757:: %number 1.000 0x1f 0v5.fdf99 %ud %ux %uv
652:: %ship ~zod %p
758:: %ship ~zod %p
653:: %date ~2026.10.23 %da
759:: %date ~2026.10.23 %da
@@ -657,7 +763,7 @@
657:: %loobean %.y %.n %f 0, %f 1
763:: %loobean %.y %.n %f 0, %f 1
658:: %null ~ %n 0
764:: %null ~ %n 0
660−+$ lit [form=lit-form aura=@ta val=@]
766++$ lit [form=lit-form aura=@ta val=@ txt=@t]
661+$ lit-form
767+$ lit-form
662 ?(%number %ship %date %duration %knot %term %loobean %null)
768 ?(%number %ship %date %duration %knot %term %loobean %null)
@@ -794,8 +900,8 @@
795:: +layout: source to tokens (design: section 2)
901:: +layout: source to tokens (design: section 2)
797−:: Never fails: an error it finds is its last token, [%error msg], at
903+:: Never fails: an error it finds is its last token, [%error msg from
798−:: the error's position (2.0). +lexer does the work.
904+:: c], at the error's position (2.0). +lexer does the work.
801 |= [file=path src=@t]
907 |= [file=path src=@t]
@@ -827,7 +933,7 @@
827++ parse-tokens
933++ parse-tokens
828 |= [file=path toks=(list token)]
934 |= [file=path toks=(list token)]
829 ^- (each module error)
935 ^- (each module error)
830− (~(read-module parser file) toks)
936+ (~(read-module parser file toks) toks)
832:: +golden: both stages printed, or the rendered error
938:: +golden: both stages printed, or the rendered error
@@ -962,10 +1068,23 @@
963 :: +err: the error token, at column c of this line (2.0)
1069 :: +err: the error token, at column c of this line (2.0)
1071+ :: It also records where the text it was reading began, from, and
1072+ :: that text's first character: the parser moves the error there
1073+ :: when the place it is in can't begin with that character (section
1074+ :: 3, Errors). Like any token, it is tight when that text follows the
1075+ :: last token with no space.
966 |= [c=@ud msg=tape]
1078 |= [c=@ud msg=tape]
1080+ (err-from c msg [lin col] ?~(cs 0 i.cs))
1082+ :: +err-from: +err, where the text began at from with first
1085+ |= [c=@ud msg=tape from=loc first=@]
968− cor(out [[[[lin c] [lin c]] | [%error msg]] out])
1087+ cor(out [[[[lin c] [lin c]] =(from pend) [%error msg from first]] out])
970 :: +put: a token from beg to end on this line, with rest the text
1089 :: +put: a token from beg to end on this line, with rest the text
971 :: after it, which starts at end
1090 :: after it, which starts at end
@@ -1023,10 +1142,10 @@
1023 ?: =('%' a) (percent b c)
1142 ?: =('%' a) (percent b c)
1024 ?: =('=' a)
1143 ?: =('=' a)
1025 ?: |(=('<' b) =('>' b))
1144 ?: |(=('<' b) =('>' b))
1026− %+ err col
1145+ %+ err +(col)
1027 "`={[b ~]}` is left out: names never shadow, and `.` reads imports too"
1146 "`={[b ~]}` is left out: names never shadow, and `.` reads imports too"
1028 ?: =('=' b)
1147 ?: =('=' b)
1029− (err col "the closer `==` is left out: indentation covers it")
1148+ (err +(col) "the closer `==` is left out: indentation covers it")
1030 (emit 1 %'=')
1149 (emit 1 %'=')
1031 ?: =('`' a) (emit 1 %'`')
1150 ?: =('`' a) (emit 1 %'`')
1032 ?: =('*' a) (emit 1 %'*')
1151 ?: =('*' a) (emit 1 %'*')
@@ -1035,7 +1154,7 @@
1035 ?: =('&' b) (emit 2 %'~&')
1154 ?: =('&' b) (emit 2 %'~&')
1036 ?: =('|' b) (err +(col) "`~|` is left out: `~&` covers debugging")
1155 ?: =('|' b) (err +(col) "`~|` is left out: `~&` covers debugging")
1037 =/ n=@ud (run-len t.cs knot-mask)
1156 =/ n=@ud (run-len t.cs knot-mask)
1038− ?: =(0 n) (emit 1 [%lit %null %n 0])
1157+ ?: =(0 n) (emit 1 [%lit %null %n 0 '~'])
1039 (literal +(n))
1158 (literal +(n))
1040 ?: =('/' a)
1159 ?: =('/' a)
1041 ?: &(=(1 col) |(=('-' b) =('%' b) =('=' b)))
1160 ?: &(=(1 col) |(=('-' b) =('%' b) =('=' b)))
@@ -1061,7 +1180,7 @@
1061 ?: &(=('-' b) =('(' c)) (emit 3 %'$-(')
1180 ?: &(=('-' b) =('(' c)) (emit 3 %'$-(')
1062 ?: =('-' b)
1181 ?: =('-' b)
1063 (err (add 2 col) "`$-` has only the wide form `$-(sample product)`")
1182 (err (add 2 col) "`$-` has only the wide form `$-(sample product)`")
1064− ?: =('(' b) (err col "`$(…)` is left out: gates recurse by name")
1183+ ?: =('(' b) (err +(col) "`$(…)` is left out: gates recurse by name")
1065 ?: =('%' b) (err +(col) "`$%` is left out: `$?` covers unions")
1184 ?: =('%' b) (err +(col) "`$%` is left out: `$?` covers unions")
1066 (err +(col) "`$` begins `$?`, `$?(` or `$-(`")
1185 (err +(col) "`$` begins `$?`, `$?(` or `$-(`")
1067 ?: =('^' a)
1186 ?: =('^' a)
@@ -1069,10 +1188,12 @@
1069 (err +(col) "`^` begins `^-`")
1188 (err +(col) "`^` begins `^-`")
1070 ?: =('?' a)
1189 ?: =('?' a)
1071 ?: =('-' b) (emit 2 %'?-')
1190 ?: =('-' b) (emit 2 %'?-')
1072− ?: =('+' b) (err +(col) "`?+` is left out: `?-` is the branch")
1073 ?: &(=(':' b) !=(':' c))
1191 ?: &(=(':' b) !=(':' c))
1074 (err +(col) "`?:` is left out: `?-` is the branch")
1192 (err +(col) "`?:` is left out: `?-` is the branch")
1075 ?: =('!' b) (err +(col) "`?!` is left out: eq and not are gates")
1193 ?: =('!' b) (err +(col) "`?!` is left out: eq and not are gates")
1194+ :: Hoon's other ? runes; nothing in Jibb goes tight after a ? mold
1196+ (err +(col) "`?{[b ~]}` is left out: `?-` is the branch")
1076 (emit 1 %'?')
1197 (emit 1 %'?')
1077 ?: =('!' a)
1198 ?: =('!' a)
1078 ?: =('!' b) (emit 2 %'!!')
1199 ?: =('!' b) (emit 2 %'!!')
@@ -1098,6 +1219,9 @@
1098 (err +(col) "`:~` is left out: indentation covers it; write ~[…]")
1219 (err +(col) "`:~` is left out: indentation covers it; write ~[…]")
1099 ?: =('*' b)
1220 ?: =('*' b)
1100 (err +(col) "`:*` is left out: indentation covers it; write […]")
1221 (err +(col) "`:*` is left out: indentation covers it; write […]")
1222+ ?: |(=('-' b) =('+' b) =('^' b) =('_' b))
1224+ "`:{[b ~]}` is left out: indentation covers it; write a cell as [a b]"
1101 ?: &(=(pend [lin col]) ?=([[* * ?([%name *] [%wing *])] *] out))
1225 ?: &(=(pend [lin col]) ?=([[* * ?([%name *] [%wing *])] *] out))
1102 %+ err +(col)
1226 %+ err +(col)
1103 %+ weld "`a:b` is left out: names never shadow, "
1227 %+ weld "`a:b` is left out: names never shadow, "
@@ -1114,6 +1238,8 @@
1114 (err col "the closer `--` is left out: indentation covers it")
1238 (err col "the closer `--` is left out: indentation covers it")
1115 (err col (unexpected a))
1239 (err col (unexpected a))
1116 ?: =(';' a)
1240 ?: =(';' a)
1242+ (err col "`;:` is left out: nest the calls, as (add a (add b c))")
1117 (err col "Sail's `;` runes are left out: layout is Jibb's elements")
1243 (err col "Sail's `;` runes are left out: layout is Jibb's elements")
1118 ?: =('\'' a) (err col "there is no '…' form: strings are \"…\"")
1244 ?: =('\'' a) (err col "there is no '…' form: strings are \"…\"")
1119 ?: =('{' a)
1245 ?: =('{' a)
@@ -1146,24 +1272,28 @@
1147 ?: =('/' b) segment:(emit 2 %'%/')
1273 ?: =('/' b) segment:(emit 2 %'%/')
1148 ?: =('.' b)
1274 ?: =('.' b)
1149− ?: =('y' c) (emit 3 [%lit %loobean %f 0])
1275+ ?: =('y' c) (emit 3 [%lit %loobean %f 0 '%.y'])
1150− ?: =('n' c) (emit 3 [%lit %loobean %f 1])
1276+ ?: =('n' c) (emit 3 [%lit %loobean %f 1 '%.n'])
1151 (err (add 2 col) "the loobeans are `%.y` and `%.n`")
1277 (err (add 2 col) "the loobeans are `%.y` and `%.n`")
1152− ?: =('&' b) (emit 2 [%lit %term %f 0])
1278+ ?: =('&' b) (emit 2 [%lit %term %f 0 '%&'])
1153− ?: =('|' b) (emit 2 [%lit %term %f 1])
1279+ ?: =('|' b) (emit 2 [%lit %term %f 1 '%|'])
1280+ ?: |(=(':' b) =('-' b) =('+' b) =('^' b) =('~' b))
1154− ?: =(':' b) (err +(col) "`%:` is left out: indentation covers it")
1282+ "`%{[b ~]}` is left out: indentation covers it; a call is (f a b)"
1155 ?: =('=' b)
1283 ?: =('=' b)
1156 %+ err +(col)
1284 %+ err +(col)
1157 "`%=` is left out: indentation covers it; write a change, as m(a=b)"
1285 "`%=` is left out: indentation covers it; write a change, as m(a=b)"
1158 =/ rest=tape ?~(cs ~ t.cs)
1286 =/ rest=tape ?~(cs ~ t.cs)
1159 ?: (is-lower b)
1287 ?: (is-lower b)
1160 =/ n=@ud (run-len rest name-mask)
1288 =/ n=@ud (run-len rest name-mask)
1289+ =/ nam=tape (scag n rest)
1161− => (emit +(n) [%lit %term %tas (crip (scag n rest))])
1290+ => (emit +(n) [%lit %term %tas (crip nam) (crip ['%' nam])])
1162 ?. &(?=(^ cs) |((is-upper i.cs) =('_' i.cs))) cor
1291 ?. &(?=(^ cs) |((is-upper i.cs) =('_' i.cs))) cor
1163 (err col "names are lowercase letters, digits and -")
1292 (err col "names are lowercase letters, digits and -")
1164 ?: (is-digit b)
1293 ?: (is-digit b)
1165 =/ n=@ud (run-len rest digit-mask)
1294 =/ n=@ud (run-len rest digit-mask)
1295+ =/ dig=tape (scag n rest)
1166− => (emit +(n) [%lit %term %ud (decimal (scag n rest))])
1296+ => (emit +(n) [%lit %term %ud (decimal dig) (crip ['%' dig])])
1167 ?. &(?=(^ cs) (in i.cs term-tail-mask)) cor
1297 ?. &(?=(^ cs) (in i.cs term-tail-mask)) cor
1168 %+ err col
1298 %+ err col
1169 "unexpected `{[i.cs ~]}`: a numeric term is `%` and digits only, as %1000"
1299 "unexpected `{[i.cs ~]}`: a numeric term is `%` and digits only, as %1000"
@@ -1217,9 +1347,20 @@
1217 =/ run=tape (scag n cs)
1347 =/ run=tape (scag n cs)
1218 =/ a=@ ?~(run 0 i.run)
1348 =/ a=@ ?~(run 0 i.run)
1219 =/ b=@ ?~(run 0 ?~(t.run 0 i.t.run))
1349 =/ b=@ ?~(run 0 ?~(t.run 0 i.t.run))
1220− :: 0b 0c 0i 0w begin auras Jibb doesn't write, whatever follows
1350+ :: 0b 0c 0i 0w, ~- and ~~ begin auras Jibb doesn't write, whatever
1351+ :: follows; Hoon's reader of ~- (@c) crashes on a control character
1221 ?: &(=('0' a) |(=('b' b) =('c' b) =('i' b) =('w' b)))
1352 ?: &(=('0' a) |(=('b' b) =('c' b) =('i' b) =('w' b)))
1222 (err +(col) "Jibb writes no @u{[b ~]} literals")
1353 (err +(col) "Jibb writes no @u{[b ~]} literals")
1354+ ?: &(=('~' a) =('-' b)) (err +(col) "Jibb writes no @c literals")
1355+ ?: &(=('~' a) =('~' b))
1356+ (err +(col) "Jibb writes no @t literals; strings are \"…\"")
1357+ :: ~0 and a base-32 digit begin a blob, which Hoon's reader cues, and
1358+ :: cue can run out of memory, which nothing catches; no Jibb literal
1359+ :: goes on so (a date's year has no leading 0)
1360+ =/ c=@ ?~(run 0 ?~(t.run 0 ?~(t.t.run 0 i.t.t.run)))
1361+ ?: &(=('~' a) =('0' b) (in c b32-mask))
1362+ ?: (is-digit c) (err (add 2 col) (literal-msg run %da))
1363+ (err (add 2 col) "Jibb writes no blob literals")
1223 :: a year BC that Hoon's dates can't hold, which its date code
1364 :: a year BC that Hoon's dates can't hold, which its date code
1224 :: crashes on: an error at the - that makes it BC
1365 :: crashes on: an error at the - that makes it BC
1225 =/ bc=(unit [at=@ud y=@ud]) (year-bc col run)
1366 =/ bc=(unit [at=@ud y=@ud]) (year-bc col run)
@@ -1227,7 +1368,18 @@
1227 (err at.u.bc "there is no year 0 BC: 1 BC is ~1-, as ~1-.1.1")
1368 (err at.u.bc "there is no year 0 BC: 1 BC is ~1-, as ~1-.1.1")
1228 ?: &(?=(^ bc) (gth y.u.bc 292.277.024.401))
1369 ?: &(?=(^ bc) (gth y.u.bc 292.277.024.401))
1229 (err at.u.bc "Hoon's dates begin in 292.277.024.401 BC")
1370 (err at.u.bc "Hoon's dates begin in 292.277.024.401 BC")
1230− =/ ed (nuck:so [[lin col] run])
1371+ :: a fifth sub-second group, which Hoon's +yule crashes on
1372+ =/ five=(unit @ud) (fifth-group run)
1374+ %+ err (add col u.five)
1375+ "a date or duration takes at most four sub-second groups"
1376+ :: Hoon's date code reads dates and durations, and has crashed on
1377+ :: forms the checks above now stop; it runs under mule, in case
1378+ =/ try=(each (like coin) tang)
1379+ ?. (is-time run) [%& (nuck:so [[lin col] run])]
1380+ (mule |.((nuck:so [[lin col] run])))
1381+ ?: ?=(%| -.try) (err col "Jibb can't read this literal")
1382+ =/ ed=(like coin) p.try
1231 ?~ q.ed (err q.p.ed (literal-msg run %$))
1383 ?~ q.ed (err q.p.ed (literal-msg run %$))
1232 =/ used=@ud (sub n (lent q.q.u.q.ed))
1384 =/ used=@ud (sub n (lent q.q.u.q.ed))
1233 =/ con=coin p.u.q.ed
1385 =/ con=coin p.u.q.ed
@@ -1238,7 +1390,7 @@
1238 %+ err +(col)
1390 %+ err +(col)
1239 %+ weld "Jibb writes no @{(trip p.p.con)} literals"
1391 %+ weld "Jibb writes no @{(trip p.p.con)} literals"
1240 ?:(=(%t p.p.con) "; strings are \"…\"" "")
1392 ?:(=(%t p.p.con) "; strings are \"…\"" "")
1241− =/ lex=lexeme [%lit u.form p.p.con q.p.con]
1393+ =/ lex=lexeme [%lit u.form p.p.con q.p.con (crip (scag used run))]
1242 ?: =(used n)
1394 ?: =(used n)
1243 ?. =(%ta p.p.con) (emit n lex)
1395 ?. =(%ta p.p.con) (emit n lex)
1244 :: a ~. knot is followed as a path segment is (2.7)
1396 :: a ~. knot is followed as a path segment is (2.7)
@@ -1255,7 +1407,9 @@
1255 =? at &(=('~' a) (is-lower b) ?=(?(%n %p) p.p.con))
1407 =? at &(=('~' a) (is-lower b) ?=(?(%n %p) p.p.con))
1256 =/ dur=@ud ?:(|(=('d' b) =('h' b) =('m' b) =('s' b)) 2 1)
1408 =/ dur=@ud ?:(|(=('d' b) =('h' b) =('m' b) =('s' b)) 2 1)
1257 (min at (add col (max dur (ship-stop run))))
1409 (min at (add col (max dur (ship-stop run))))
1410+ :: the text that fails is the whole run, from its start, though its
1411+ :: first part is a token
1258− (err:(emit used lex) at (literal-msg run p.p.con))
1412+ (err-from:(emit used lex) at (literal-msg run p.p.con) [lin col] a)
1260 :: +text: a string's text, from its opening " or the } that closes
1414 :: +text: a string's text, from its opening " or the } that closes
1261 :: an interpolation, through the " or { that ends it (2.9). mid: it
1415 :: an interpolation, through the " or { that ends it (2.9). mid: it
@@ -1336,6 +1490,31 @@
1336++ seg-bad-mask 0x1800.0001.57ff.ffff.f800.1cfe.0000.0000
1490++ seg-bad-mask 0x1800.0001.57ff.ffff.f800.1cfe.0000.0000
1337:: after a numeric term: a-z A-Z _ - .
1491:: after a numeric term: a-z A-Z _ - .
1338++ term-tail-mask 0x7ff.fffe.87ff.fffe.0000.6000.0000.0000
1492++ term-tail-mask 0x7ff.fffe.87ff.fffe.0000.6000.0000.0000
1493+:: after a ? glyph, Hoon's ? runes but ?- ?: and ?! (2.6): + ~ = . @ ^ & | < >
1494+++ wut-mask 0x5000.0000.4000.0001.7000.4840.0000.0000
1495+:: base-32 digits: 0-9 a-v
1496+++ b32-mask 0x7f.fffe.0000.0000.03ff.0000.0000.0000
1498+:: What may begin each place the parser reads (section 3, Errors):
1499+:: an expression a-z 0-9 " ( [ ~ % / ` | ^ ? !
1500+:: an operand a-z 0-9 " ( [ ~ % / ` |
1501+:: a mold a-z A-Z @ * ! ? ~ % / ( [ $ |
1502+:: a pattern a-z 0-9 " ~ % * [
1503+:: and what may go tight after an operand: . ( + = after a name, a
1504+:: closer ) ] }, or the : of a comment
1506+++ expr-mask 0x57ff.ffff.4800.0000.83ff.8126.0000.0000
1507+++ operand-mask 0x57ff.ffff.0800.0000.03ff.8124.0000.0000
1508+++ mold-mask 0x57ff.fffe.0fff.ffff.8000.8532.0000.0000
1509+++ pattern-mask 0x47ff.fffe.0800.0000.03ff.0424.0000.0000
1510+++ after-mask 0x2000.0000.2000.0000.2400.4b00.0000.0000
1511+++ plus-mask 0x800.0000.0000 :: +
1512+++ cen-mask 0x20.0000.0000 :: %
1513+++ fas-mask 0x8000.0000.0000 :: /
1514+++ tis-mask 0x2000.0000.0000.0000 :: =
1515+++ pat-mask 0x1.0000.0000.0000.0000 :: @
1516+++ sel-mask 0x800.0000.0000.0000.0000.0000 :: [
1517+++ ser-mask 0x2000.0000.0000.0000.0000.0000 :: ]
1340:: +cont-mask: UTF-8 continuation bytes, 10xx.xxxx, which start no
1519:: +cont-mask: UTF-8 continuation bytes, 10xx.xxxx, which start no
1341:: column (1)
1520:: column (1)
@@ -1437,6 +1616,62 @@
1437 ?. ?=([%'-' *] rest) ~
1616 ?. ?=([%'-' *] rest) ~
1438 `[(add col +((lent ds))) (decimal ds)]
1617 `[(add col +((lent ds))) (decimal ds)]
1619+:: +fifth-group: where in a ~ literal's run, counting from its ~, the
1620+:: dot that begins a fifth sub-second group is, if the first four are
1623+:: Sub-seconds follow a duration's first .. or a date's second, as in
1624+:: ~s1..0000 and ~2026.10.23..14.30.00..0000: groups of four
1625+:: lowercase hex digits joined by dots. Hoon's reader takes any
1626+:: number, and its +yule crashes on a fifth (2.8).
1631+ =/ b=@ ?.(?=([%'~' @ *] run) 0 i.t.run)
1634+ ?:(|(=('d' b) =('h' b) =('m' b) =('s' b)) 1 0)
1636+ =/ past=(unit [i=@ud cs=tape]) (past-dots k 0 run)
1639+ =/ cs=tape cs.u.past
1642+ =/ quad=tape (scag 4 cs)
1643+ ?. &(=(4 (lent quad)) (levy quad is-hex)) ~
1646+ ?. ?=([%'.' *] cs) ~
1648+ $(g +(g), i +(i), cs t.cs)
1650+:: +past-dots: where the text past the k-th .. of cs starts, counting
1651+:: from i, and that text
1654+ |= [k=@ud i=@ud cs=tape]
1655+ ^- (unit [i=@ud cs=tape])
1657+ ?. &(=('.' i.cs) ?=(^ t.cs) =('.' i.t.cs))
1659+ ?: =(1 k) `[(add 2 i) t.t.cs]
1660+ $(k (dec k), i (add 2 i), cs t.t.cs)
1662+:: +is-time: whether a ~ literal's run starts as a date or a duration
1663+:: does, which Hoon's date code reads (2.8)
1668+ ?. ?=([%'~' @ *] run) |
1669+ ?: (is-digit i.t.run) &
1670+ ?& |(=('d' i.t.run) =('h' i.t.run) =('m' i.t.run) =('s' i.t.run))
1672+ (is-digit i.t.t.run)
1440:: +ship-stop: how many characters of a ~ literal's run, from its ~,
1675:: +ship-stop: how many characters of a ~ literal's run, from its ~,
1441:: could still begin a ship (2.8)
1676:: could still begin a ship (2.8)
@@ -1554,11 +1789,8 @@
1555 =/ kids=(list sexp)
1790 =/ kids=(list sexp)
1556 (weld (turn imports.mod sexp-import) (turn defs.mod sexp-def))
1791 (weld (turn imports.mod sexp-import) (turn defs.mod sexp-def))
1558− ?~ kids ~["(module)"]
1792+ ?~ kids '(module)'
1560− (close (zing (turn kids |=(k=sexp (render 2 k)))))
1561− (of-wain:format (turn lines crip))
1793+ (of-wain:format (turn (render kids) crip))
1563:: +show-error: "<file>:<line>:<col>: <message>", the line, a caret
1795:: +show-error: "<file>:<line>:<col>: <message>", the line, a caret
@@ -1654,17 +1886,15 @@
1654 ?~ t.ns (trip i.ns)
1886 ?~ t.ns (trip i.ns)
1655 "{(trip i.ns)}.{$(ns t.ns)}"
1887 "{(trip i.ns)}.{$(ns t.ns)}"
1657−:: +show-lit: a literal as Hoon prints it
1889+:: +show-lit: a literal as written for atoms read by nuck:so, whose
1890+:: printing differs between Hoon versions (@da); terms, loobeans and ~
1891+:: in their one form
1659++ show-lit
1893++ show-lit
1660 |= l=lit
1894 |= l=lit
1662 ?- form.l
1896 ?- form.l
1663− %number (scow aura.l val.l)
1897+ ?(%number %ship %date %duration %knot) (trip txt.l)
1664− %ship (scow %p val.l)
1665− %date (scow %da val.l)
1666− %duration (scow %dr val.l)
1667− %knot (scow %ta val.l)
1668 %loobean ?:(=(0 val.l) "%.y" "%.n")
1898 %loobean ?:(=(0 val.l) "%.y" "%.n")
1669 %null "~"
1899 %null "~"
@@ -1726,20 +1956,57 @@
1726 [%node head=tape kids=(list sexp)]
1956 [%node head=tape kids=(list sexp)]
1729−:: +render: a node as lines, at an indent
1959+:: +render: a module's kids as the tree's lines (4.2)
1731−:: On one line when every kid is a leaf: an atom, or a node whose kids
1961+:: A node whose kids are all leaves goes on one line; else its head,
1732−:: are all atoms (a string's text, a path's knots). Else each kid on
1962+:: then each kid a level deeper, and its ) at the end of its last
1733−:: its own lines, two spaces deeper.
1963+:: kid's last line; (module …) always breaks. Each line is built once,
1964+:: from its depth: a line deeper than 64 levels keeps 64 levels'
1965+:: indent and says its depth, as |65| (group 3:1 …), so printing is
1966+:: linear in the tree's size however deep it nests.
1735++ render
1968++ render
1736− |= [ind=@ud s=sexp]
1969+ |= kids=(list sexp)
1738− =/ pad=tape (reap ind ' ')
1971+ =/ acc=(list pline) ~[[0 "(module" 0]]
1975+ $(kids t.kids, acc (put-sexp 1 i.kids acc))
1976+ (flop (turn (shut-last acc) show-pline))
1978+:: +pline: a printed line: its depth, its text, and how many )s end it
1980++$ pline [dep=@ud txt=tape shut=@ud]
1982+:: +put-sexp: a node's lines at depth dep, last first, onto acc
1985+ |= [dep=@ud s=sexp acc=(list pline)]
1739− ?: ?=(%atom -.s) ~[(weld pad p.s)]
1987+ ?: ?=(%atom -.s) [[dep p.s 0] acc]
1740− ?: (levy kids.s is-leaf) ~[(weld pad (flat s))]
1988+ ?: (levy kids.s is-leaf) [[dep (flat s) 0] acc]
1989+ =/ ks=(list sexp) kids.s
1741− :- "{pad}({head.s}"
1990+ =. acc [[dep "({head.s}" 0] acc]
1742− (close (zing (turn kids.s |=(k=sexp (render (add ind 2) k)))))
1991+ |- ^- (list pline)
1992+ ?~ ks (shut-last acc)
1993+ $(ks t.ks, acc (put-sexp +(dep) i.ks acc))
1995+:: +shut-last: one more ) at the end of the last line
1998+ |= acc=(list pline)
2001+ [i.acc(shut +(shut.i.acc)) t.acc]
2007+ ?: (lte dep.l 64) (reap (mul 2 dep.l) ' ')
2008+ "{(reap 128 ' ')}|{(a-co:co dep.l)}| "
2009+ :(weld pad txt.l (reap shut.l ')'))
1744++ is-leaf
2011++ is-leaf
1745 |= s=sexp
2012 |= s=sexp
@@ -1753,15 +2020,6 @@
1753 ?: ?=(%atom -.s) p.s
2020 ?: ?=(%atom -.s) p.s
1754 "({head.s}{(zing (turn kids.s |=(k=sexp (weld " " (flat k)))))})"
2021 "({head.s}{(zing (turn kids.s |=(k=sexp (weld " " (flat k)))))})"
1756−:: +close: end the last line with )
1762− ?~ t.w ~[(weld i.w ")")]
1765:: +nod: a node's sexp: "kind line:col extra" and its kids
2023:: +nod: a node's sexp: "kind line:col extra" and its kids
@@ -1927,49 +2185,195 @@
1928:: +fail: the error "expected <want>, found <the next token>"
2186:: +fail: the error "expected <want>, found <the next token>"
1930−:: At an error token, the layout pass's error instead (2.0). The token
2188+:: At the layout pass's error instead (+lexer-error). The token list
1931−:: list always ends with NEWLINE or an error token (2.5), and the
2189+:: always ends with NEWLINE or an error token (2.5), and the parser
1932−:: parser stops at either, so it never runs out; if it did, the error
2190+:: stops at either, so it never runs out; if it did, the error would
1933−:: would sit at 1:1.
2191+:: sit at 1:1.
1936 |= [file=path toks=(list token) want=tape]
2194 |= [file=path toks=(list token) want=tape]
1937 ^- [%| p=error]
2195 ^- [%| p=error]
1938 ?~ toks [%| file 1 1 "expected {want}, found the end of the tokens"]
2196 ?~ toks [%| file 1 1 "expected {want}, found the end of the tokens"]
1939− ?: ?=([%error *] lex.i.toks)
2197+ =/ lex=(unit error) (lexer-error file toks)
1940− [%| file line.beg.at.i.toks col.beg.at.i.toks p.lex.i.toks]
2198+ ?^ lex [%| u.lex]
1941 =/ l=loc (where i.toks)
2199 =/ l=loc (where i.toks)
1942 [%| file line.l col.l "expected {want}, found {(show-found i.toks)}"]
2200 [%| file line.l col.l "expected {want}, found {(show-found i.toks)}"]
1944−:: +fail-space: a tight form found a space before its next token
2202+:: +lexer-error: the layout pass's error, where the parser fails at it
2204+:: At an error token, its error. At layout tokens followed by an error
2205+:: token whose text begins the line, both errors point at the line's
2206+:: start (+where), and the layout pass's message, about that text,
2207+:: says more: a line `==` closing a ?- is "the closer `==` is left
2208+:: out", not "expected the end of the body".
2211+ |= [file=path toks=(list token)]
2214+ ?: ?=([%error *] lex.i.toks)
2215+ `[file line.beg.at.i.toks col.beg.at.i.toks p.lex.i.toks]
2216+ ?. (is-layout i.toks) ~
2217+ =/ l=loc (where i.toks)
2218+ =/ rest=(list token) t.toks
2221+ ?: (is-layout i.rest) $(rest t.rest)
2222+ ?. ?=([%error *] lex.i.rest) ~
2223+ ?. =(l from.lex.i.rest) ~
2224+ `[file line.l col.l p.lex.i.rest]
2226+:: +fail-in: +fail where the next token begins a place, such as an
2227+:: expression or a mold, whose first character is one of the mask can
2229+:: The error points at the first character where the text stops being
2230+:: the start of any valid module (2.0), so at a token the place can't
2231+:: take, just past the part of it the place could: none if the place
2232+:: can't begin with its first character; a wing's first name, as in
2233+:: `++ a.b`, where a name goes; else that first character, as the ~ of
2234+:: ~zod where a mold goes (~ alone is one). At an error token whose
2235+:: text begins with a character the place can't, the error moves to
2236+:: that character, with the layout pass's message: `++ x @sd` fails
2237+:: at the @, since no expression begins with @, while `+$ x @sd`
2241+ |= [file=path toks=(list token) want=tape can=@]
2243+ ?~ toks (fail file toks want)
2245+ ?: ?=([%error *] lex.t)
2246+ :: a : could begin a comment anywhere, which this leaves out
2247+ ?: |(=(':' c.lex.t) (in c.lex.t can)) (fail file toks want)
2248+ [%| (moved file want t)]
2249+ ?: (is-layout t) (fail file toks want)
2250+ =/ n=@ud (prefix t can)
2251+ =/ e=[%| p=error] (fail file toks want)
2252+ e(col.p (add n col.p.e))
2254+:: +prefix: how many of the first characters of a token that a place
2255+:: can't take could still begin it, the place beginning with a
2256+:: character of the mask can (+fail-in)
2261+ ?. (in (first-char t) can) 0
2262+ ?. ?=([%wing *] lex.t) 1
2263+ ?~(p.lex.t 1 (met 3 i.p.lex.t))
2265+:: +first-char: a token's first character, or one like it: a number
2266+:: begins with a digit, ~zod with ~ and %add with %
2272+ ?@ x ?:(?=(?(%indent %dedent %newline) x) 0 (end 3 x))
2275+ %wing ?~(p.x 0 (end 3 i.p.x))
2288+ ?(%term %loobean) '%'
2289+ ?(%ship %date %duration %knot %null) '~'
2293+:: +fail-space: a tight form found no next token right after prev
1946−:: The error sits where the space starts, just past prev, the token
2295+:: The error sits just past prev, the token that needs its next one
1947−:: that needs its next one at once (section 3, Errors). If the next
2296+:: at once, where the space or the end of the line starts (section 3,
1948−:: token is a layout or error token, it is +fail's error instead.
2297+:: Errors): no deeper line can supply a tight form's next token. So
2298+:: does an error token past a space or on a later line, whose error
2299+:: comes after. A tight error token's text begins right after prev,
2300+:: and its error is +fail's. why is a hint, if not empty.
1950++ fail-space
2302++ fail-space
1951− |= [file=path prev=token toks=(list token) want=tape]
2303+ |= [file=path prev=token toks=(list token) want=tape why=tape]
1952 ^- [%| p=error]
2304 ^- [%| p=error]
1953− ?: ?| ?=(~ toks)
2305+ =/ at=loc end.at.prev
1954− ?=(?(%indent %dedent %newline) lex.i.toks)
1955− ?=([%error *] lex.i.toks)
2306+ ?: &(?=(^ toks) ?=([%error *] lex.i.toks) =(at from.lex.i.toks))
1957 (fail file toks want)
2307 (fail file toks want)
1958− :+ %| file
2308+ =/ found=tape
1959− :+ line.end.at.prev col.end.at.prev
2309+ ?~ toks "the end of the file"
2312+ ?:(=(beg.at.t end.at.t) "the end of the file" "the end of the line")
2313+ ?: &(?=([%error *] lex.t) !=(line.at line.from.lex.t))
2314+ "the end of the line"
1960− "expected {want} right after {(show-found prev)}, found a space"
2317+ "expected {want} right after {(show-found prev)}, found {found}"
2318+ [%| file line.at col.at ?~(why msg "{msg}; {why}")]
1962:: +fail-why: +fail with a hint after its message, "; <why>"
2320:: +fail-why: +fail with a hint after its message, "; <why>"
1964−:: The layout pass's error, at an error token, stays as it is (2.0).
2322+:: The layout pass's error (+lexer-error) stays as it is (2.0).
1966++ fail-why
2324++ fail-why
1967 |= [file=path toks=(list token) want=tape why=tape]
2325 |= [file=path toks=(list token) want=tape why=tape]
1968 ^- [%| p=error]
2326 ^- [%| p=error]
1969 =/ e=[%| p=error] (fail file toks want)
2327 =/ e=[%| p=error] (fail file toks want)
2328+ ?^ (lexer-error file toks) e
2329+ e(msg.p (weld msg.p.e "; {why}"))
2331+:: +fail-in-why: +fail-in with a hint, as +fail-why
2334+ |= [file=path toks=(list token) want=tape can=@ why=tape]
2336+ =/ e=[%| p=error] (fail-in file toks want can)
1970 ?: &(?=(^ toks) ?=([%error *] lex.i.toks)) e
2337 ?: &(?=(^ toks) ?=([%error *] lex.i.toks)) e
2338+ ?^ (lexer-error file toks) e
1971 e(msg.p (weld msg.p.e "; {why}"))
2339 e(msg.p (weld msg.p.e "; {why}"))
2341+:: +tight-error: the error at an error token tight after an operand or
2342+:: an item, if its text's first character can't go there: the layout
2343+:: pass's message, at that character (+fail-in)
2345+:: What may go tight after an item is a closer, a comment's :, or,
2346+:: after a name, the ( . + or = of a change, a wing, a pair or a face
2347+:: (after-mask, which doesn't look at what the item was).
2350+ |= [file=path toks=(list token)]
2352+ (tight-error-in file toks after-mask)
2354+:: +tight-error-in: +tight-error where what may go tight is can, as no
2355+:: = goes tight after a call's operand, which takes no face
2358+ |= [file=path toks=(list token) can=@]
2360+ ?. ?=([[* %& [%error *]] *] toks) ~
2361+ ?: (in c.lex.i.toks can) ~
2362+ `(moved file "a space between items" i.toks)
2364+:: +moved: an error token's error, moved to the first character of the
2365+:: text it was reading, which can't go where it is (+fail-in): "expected
2366+:: <want>, found <that character>; <the layout pass's message>"
2369+ |= [file=path want=tape t=token]
2371+ ?. ?=([%error *] lex.t) [file line.beg.at.t col.beg.at.t "expected {want}"]
2373+ ?: =(from.x beg.at.t) [file line.from.x col.from.x p.x]
2374+ =/ what=tape ?:(=('"' c.x) "a string" "`{[c.x ~]}`")
2375+ [file line.from.x col.from.x "expected {want}, found {what}; {p.x}"]
1973:: Token tests for the parser
2377:: Token tests for the parser
1975:: +is-layout: INDENT, DEDENT or NEWLINE
2379:: +is-layout: INDENT, DEDENT or NEWLINE
@@ -2001,6 +2405,28 @@
2001 ?=([%error *] lex.t)
2405 ?=([%error *] lex.t)
2408+:: +tail-can: what may begin text that goes on, on its line, after an
2409+:: expression: more operands after a call, nothing after !! (+bad-end-in)
2414+ ?+ -.e operand-mask
2420+:: +def-can: +tail-can after a definition: nothing after a mold
2427+ %value (tail-can val.d)
2004:: +is-operand-start: a token an operand starts with; where an operand
2430:: +is-operand-start: a token an operand starts with; where an operand
2005:: goes, |= is the constructor's (section 3)
2431:: goes, |= is the constructor's (section 3)
@@ -2093,10 +2519,11 @@
2093:: (section 3), so it never backtracks. A loop over items is a trap
2519:: (section 3), so it never backtracks. A loop over items is a trap
2094:: whose every step, through +then, is a tail call, so a long module
2520:: whose every step, through +then, is a tail call, so a long module
2095:: grows no stack; only nesting does, and a line's nesting is bounded
2521:: grows no stack; only nesting does, and a line's nesting is bounded
2096−:: by its length.
2522+:: by its length. all is the whole token list, which only errors
2098++ parser
2525++ parser
2099− |_ file=path
2526+ |_ [file=path all=(list token)]
2101 :: +bad: "expected <want>, found <the next token>" (+fail)
2528 :: +bad: "expected <want>, found <the next token>" (+fail)
@@ -2112,82 +2539,161 @@
2112 ^- [%| p=error]
2539 ^- [%| p=error]
2113 (fail-why file ts want why)
2540 (fail-why file ts want why)
2542+ :: +bad-in: +bad where a place begins whose first characters are the
2543+ :: mask can (+fail-in)
2546+ |= [ts=(list token) want=tape can=@]
2548+ (fail-in file ts want can)
2550+ :: +bad-in-why: +bad-in with a hint (+fail-in-why)
2553+ |= [ts=(list token) want=tape can=@ why=tape]
2555+ (fail-in-why file ts want can why)
2115− :: +bad-space: a tight form that found a space after prev
2557+ :: +bad-space: a tight form that found no next token right after prev
2116 :: (+fail-space)
2558 :: (+fail-space)
2118 ++ bad-space
2560 ++ bad-space
2119 |= [prev=token ts=(list token) want=tape]
2561 |= [prev=token ts=(list token) want=tape]
2120 ^- [%| p=error]
2562 ^- [%| p=error]
2121− (fail-space file prev ts want)
2563+ (fail-space file prev ts want "")
2123− :: +bad-at: an error inside a token (section 3, Errors)
2565+ :: +bad-at: an error inside a token, or at the end of a line
2125 ++ bad-at
2567 ++ bad-at
2126 |= [at=loc msg=tape]
2568 |= [at=loc msg=tape]
2127 ^- [%| p=error]
2569 ^- [%| p=error]
2128 [%| file line.at col.at msg]
2570 [%| file line.at col.at msg]
2572+ :: +closing: what a bracket op still needs, its closer close
2575+ |= [op=token close=tape]
2577+ "`{close}` to close the {(show-found op)} at {(show-loc beg.at.op)}"
2130− :: +bad-end: a line that should end and goes on
2579+ :: +bad-end: a line that should end and goes on, after a call
2132 ++ bad-end
2581 ++ bad-end
2133 |= ts=(list token)
2582 |= ts=(list token)
2134 ^- [%| p=error]
2583 ^- [%| p=error]
2584+ (bad-end-in ts operand-mask)
2586+ :: +bad-end-in: +bad-end after a construct that text beginning with
2587+ :: a character of the mask can could still go on, as more operands go
2588+ :: on a call; at an error token whose text can't, at that text's
2589+ :: start (+fail-in): +$ x @ ?: fails at the ?
2592+ |= [ts=(list token) can=@]
2594+ =/ want=tape "the end of the line"
2135− ?. ?=([[* * %indent] *] ts) (bad ts "the end of the line")
2595+ ?: ?=([[* * %indent] *] ts)
2136− %^ bad-why ts "the end of the line"
2596+ %^ bad-why ts want
2137− %+ weld "only a bracket open at the end of a line, "
2597+ %+ weld "only a bracket open at the end of a line, "
2138− "or a rune's body, takes deeper lines"
2598+ "or a rune's body, takes deeper lines"
2599+ ?: &(?=(^ ts) (stray i.ts))
2600+ (bad-why ts want "this {(show-found i.ts)} closes no bracket")
2601+ ?. ?=([[* * [%error *]] *] ts) (bad ts want)
2602+ =/ ok=@ ?:(tight.i.ts after-mask can)
2603+ ?: |(=(':' c.lex.i.ts) (in c.lex.i.ts ok)) (bad ts want)
2604+ [%| (moved file want i.ts)]
2606+ :: +no-gap: a token tight where a space goes, after a rune, a name, a
2607+ :: sample or a pattern; at an error token, whose text can't go tight
2608+ :: there unless it is a comment's :, at that text's start (+fail-in)
2611+ |= [ts=(list token) want=tape]
2613+ ?. &(?=([[* * [%error *]] *] ts) !=(':' c.lex.i.ts)) (bad ts want)
2614+ [%| (moved file want i.ts)]
2140 :: +no-space: a token tight after an item, where a space goes
2616 :: +no-space: a token tight after an item, where a space goes
2142 ++ no-space
2618 ++ no-space
2143 |= ts=(list token)
2619 |= ts=(list token)
2144 ^- [%| p=error]
2620 ^- [%| p=error]
2621+ =/ te=(unit error) (tight-error file ts)
2145 ?. ?=([[* * %'='] *] ts) (bad ts "a space between items")
2623 ?. ?=([[* * %'='] *] ts) (bad ts "a space between items")
2146 %^ bad-why ts "a space between items"
2624 %^ bad-why ts "a space between items"
2147 "`name=value` goes in a cell, as [a=1], or a change, as m(a=1)"
2625 "`name=value` goes in a cell, as [a=1], or a change, as m(a=1)"
2149− :: +no-operand: a token where an operand goes that starts none, with
2627+ :: +no-space-pattern: +no-space in a cell pattern
2150− :: a hint for the left-out forms the lexer can't see (2.6)
2152− ++ no-operand
2629+ ++ no-space-pattern
2153 |= ts=(list token)
2630 |= ts=(list token)
2154 ^- [%| p=error]
2631 ^- [%| p=error]
2632+ ?. ?=([[* * %'='] *] ts) (no-space ts)
2633+ %^ bad-why ts "a space between items"
2634+ "patterns take no `name=`: a bare name binds, as [a b]"
2636+ :: +no-operand: a token where an expression or an operand goes that
2637+ :: starts none (can: what may start one), with a hint for the left-out
2638+ :: forms the lexer can't see (2.6) and other likely slips
2641+ |= [ts=(list token) can=@]
2155 =/ want=tape "an expression"
2643 =/ want=tape "an expression"
2156 ?: ?=([[* * %'='] [* %& %'('] *] ts)
2644 ?: ?=([[* * %'='] [* %& %'('] *] ts)
2157 (bad-why ts want "`=(a b)` is left out: eq is a gate")
2645 (bad-why ts want "`=(a b)` is left out: eq is a gate")
2158 ?: ?=([[* * %'='] [* %& %'/'] *] ts)
2646 ?: ?=([[* * %'='] [* %& %'/'] *] ts)
2159 (bad-why ts want "`=/` is left out: `++` defines values")
2647 (bad-why ts want "`=/` is left out: `++` defines values")
2648+ ?: ?=([[* * %'='] [* %& %'+'] *] ts)
2649+ (bad-why ts want "`=+` is left out: `++` defines values")
2650+ ?: ?=([[* * %'='] [* %& %'?'] *] ts)
2651+ (bad-why ts want "`=?` is left out: `++` defines values")
2652+ ?: ?& ?=([[* * %'='] [* %& [%error *]] *] ts)
2653+ =('.' c.lex.i.t.ts)
2655+ (bad-why ts want "`=.` is left out: `++` defines values")
2160 ?: ?=([[* * %'*'] *] ts)
2656 ?: ?=([[* * %'*'] *] ts)
2161 (bad-why ts want "`*mold` is left out: no defaults")
2657 (bad-why ts want "`*mold` is left out: no defaults")
2162 ?: ?=([[* * %'+'] *] ts)
2658 ?: ?=([[* * %'+'] *] ts)
2163 (bad-why ts want "a pair takes no spaces, as gap+%s2")
2659 (bad-why ts want "a pair takes no spaces, as gap+%s2")
2660+ ?: ?=([[* * %'?'] *] ts)
2661+ %: bad-in-why ts want can
2662+ "`?` alone is the loobean mold, and `?-` the branch"
2164 ?: &(?=(^ ts) (is-rune i.ts))
2664 ?: &(?=(^ ts) (is-rune i.ts))
2165− (bad-why ts want "a rune here goes in parentheses")
2665+ (bad-in-why ts want can "a rune here goes in parentheses")
2166− (bad ts want)
2666+ ?: &(?=(^ ts) (stray i.ts))
2667+ (bad-why ts want "this {(show-found i.ts)} closes no bracket")
2668+ (bad-in ts want can)
2670+ :: +no-name: a token where a name goes that isn't one
2675+ ?: ?=([[* * [%tvar *]] *] ts)
2676+ (bad-why ts "a name" "a name starts with a lowercase letter")
2677+ ?: ?=([[* * [%wing *]] *] ts)
2678+ (bad-in-why ts "a name" lower-mask "a name has no `.`")
2679+ (bad-in ts "a name" lower-mask)
2168 :: +unclosed: where the closer of the bracket op opened should be
2681 :: +unclosed: where the closer of the bracket op opened should be
2170 ++ unclosed
2683 ++ unclosed
2171 |= [op=token close=tape ts=(list token)]
2684 |= [op=token close=tape ts=(list token)]
2172 ^- [%| p=error]
2685 ^- [%| p=error]
2173− =/ want=tape
2686+ =/ want=tape (closing op close)
2174− "`{close}` to close the {(show-found op)} at {(show-loc beg.at.op)}"
2175 ?. ?=([[* * %indent] *] ts) (bad ts want)
2687 ?. ?=([[* * %indent] *] ts) (bad ts want)
2176 (bad-why ts want "this bracket closes on its line")
2688 (bad-why ts want "this bracket closes on its line")
2178 :: +unclosed-open: a bracket that may be left open, whose line ends
2690 :: +unclosed-open: a bracket that may be left open, whose line ends
2179− :: with neither its closer nor deeper lines; last is its last item's
2691+ :: with neither its closer nor deeper lines; noun names its items
2180− :: span, and noun names its items
2182 ++ unclosed-open
2693 ++ unclosed-open
2183− |= [op=token close=tape noun=tape last=(unit span) ts=(list token)]
2694+ |= [op=token close=tape noun=tape ts=(list token)]
2184 ^- [%| p=error]
2695 ^- [%| p=error]
2185 ?. ?=([[* * ?(%newline %dedent)] *] ts) (unclosed op close ts)
2696 ?. ?=([[* * ?(%newline %dedent)] *] ts) (unclosed op close ts)
2186− :: its last item ends on a later line: an item left open took them
2187− ?: &(?=(^ last) (gth line.end.u.last line.beg.at.op))
2189− "`{close}` to close the {(show-found op)} at {(show-loc beg.at.op)}"
2190− "only the last bracket open at the end of a line takes the deeper lines"
2191 (bad ts "`{close}` or {noun} on a deeper line")
2697 (bad ts "`{close}` or {noun} on a deeper line")
2193 :: +wide-rune: a rune followed tight; txt( is a left-out wide form
2699 :: +wide-rune: a rune followed tight; txt( is a left-out wide form
@@ -2196,7 +2702,7 @@
2196 |= [txt=tape ts=(list token)]
2702 |= [txt=tape ts=(list token)]
2197 ^- [%| p=error]
2703 ^- [%| p=error]
2198 =/ want=tape "a space after `{txt}`"
2704 =/ want=tape "a space after `{txt}`"
2199− ?. ?=([[* * %'('] *] ts) (bad ts want)
2705+ ?. ?=([[* * %'('] *] ts) (no-gap ts want)
2200 %^ bad-why ts want
2706 %^ bad-why ts want
2201 "the wide form `{txt}(…)` is left out: indentation covers it"
2707 "the wide form `{txt}(…)` is left out: indentation covers it"
@@ -2208,6 +2714,62 @@
2208 %^ bad-why ts "a named item"
2714 %^ bad-why ts "a named item"
2209 "a change's items are named, as in m(done=%.y)"
2715 "a change's items are named, as in m(done=%.y)"
2717+ :: +doomed: where a part of a line, read from ts up to after, took
2718+ :: the deeper lines while what holds it needs more: a closer on the
2719+ :: line, or deeper lines of its own. No later line can give it that,
2720+ :: so the error is at the end of the line that took them (section 3,
2721+ :: Errors). want is what it needs. Only an error path calls this, and
2722+ :: it looks only when after begins with NEWLINE or DEDENT, so it
2723+ :: costs nothing on the way to a tree.
2726+ |= [ts=(list token) after=(list token) want=tape]
2727+ ^- (unit [%| p=error])
2728+ ?. ?=([[* * ?(%newline %dedent)] *] after) ~
2729+ =/ ind=(unit token) (took ts after)
2732+ %+ bad-at beg.at.u.ind
2734+ "expected {want}, found the end of the line; the deeper lines "
2735+ "go to the last bracket or rune left open on this line"
2738+ :: +took: the INDENT among the tokens from ts up to after, if any
2741+ |= [ts=(list token) after=(list token)]
2744+ =/ stop=loc beg.at.i.after
2747+ ?. (loc-lth beg.at.i.ts stop) ~
2748+ ?: ?=(%indent lex.i.ts) `i.ts
2751+ :: +stray: whether a ) or ] closes no bracket opened before it on its
2752+ :: line, or none inside the interpolation it is in
2757+ ?. ?=(?(%')' %']') lex.t) |
2759+ =/ ts=(list token) all
2763+ ?: =(at.u at.t) |(?=(~ open) !i.open)
2764+ ?: (is-layout u) $(ts t.ts, open ~)
2765+ ?: ?=(?(%'(' %'[' %'~[' %'|=(' %'$?(' %'$-(') lex.u)
2766+ $(ts t.ts, open [& open])
2767+ ?: ?=([%str-head *] lex.u) $(ts t.ts, open [| open])
2768+ ?: ?=([%str-mid *] lex.u) $(ts t.ts, open [| ?~(open ~ t.open)])
2769+ ?: |(?=(?(%')' %']') lex.u) ?=([%str-tail *] lex.u))
2770+ $(ts t.ts, open ?~(open ~ t.open))
2211 :: +read-module: { import NEWLINE } { definition NEWLINE }, then the
2773 :: +read-module: { import NEWLINE } { definition NEWLINE }, then the
2212 :: end of the tokens
2774 :: end of the tokens
@@ -2218,15 +2780,17 @@
2218 |- ^- (each module error)
2780 |- ^- (each module error)
2219 ?: ?=([[* * ?(%'/-' %'/%' %'/=')] *] ts)
2781 ?: ?=([[* * ?(%'/-' %'/%' %'/=')] *] ts)
2220 ;< [im=import after=(list token)] then (read-import ts)
2782 ;< [im=import after=(list token)] then (read-import ts)
2221− ?. ?=([[* * %newline] *] after) (bad-end after)
2783+ ?. ?=([[* * %newline] *] after) (bad-end-in after 0)
2222 $(ims [im ims], ts t.after)
2784 $(ims [im ims], ts t.after)
2223 =| defs=(list def)
2785 =| defs=(list def)
2224 |- ^- (each module error)
2786 |- ^- (each module error)
2225 ?~ ts [%& (flop ims) (flop defs)]
2787 ?~ ts [%& (flop ims) (flop defs)]
2226 ?: ?=([[* * ?(%'/-' %'/%' %'/=')] *] ts)
2788 ?: ?=([[* * ?(%'/-' %'/%' %'/=')] *] ts)
2227 (bad-why ts "a definition" "imports come first")
2789 (bad-why ts "a definition" "imports come first")
2790+ :: what may begin the line: a definition, or before any, an import
2791+ =/ can=@ ?~(defs (con plus-mask fas-mask) plus-mask)
2228− ;< [d=def after=(list token)] then (read-def ts)
2792+ ;< [d=def after=(list token)] then (read-def ts can)
2229− ?. ?=([[* * %newline] *] after) (bad-end after)
2793+ ?. ?=([[* * %newline] *] after) (bad-end-in after (def-can d))
2230 $(defs [d defs], ts t.after)
2794 $(defs [d defs], ts t.after)
2232 :: +read-import: /- name, /% term, or /= name pathlit
2796 :: +read-import: /- name, /% term, or /= name pathlit
@@ -2238,34 +2802,36 @@
2238 =* g i.ts
2802 =* g i.ts
2239 =/ rest=(list token) t.ts
2803 =/ rest=(list token) t.ts
2240 ?: &(?=(^ rest) tight.i.rest)
2804 ?: &(?=(^ rest) tight.i.rest)
2241− (bad rest "a space after {(show-found g)}")
2805+ (no-gap rest "a space after {(show-found g)}")
2242 ?: =(%'/%' lex.g)
2806 ?: =(%'/%' lex.g)
2243 ?: ?=([[* * [%lit %term %tas *]] *] rest)
2807 ?: ?=([[* * [%lit %term %tas *]] *] rest)
2244 [%& [%mark [beg.at.g end.at.i.rest] val.p.lex.i.rest] t.rest]
2808 [%& [%mark [beg.at.g end.at.i.rest] val.p.lex.i.rest] t.rest]
2245 =/ want=tape "a mark's term, as `%todo-action`"
2809 =/ want=tape "a mark's term, as `%todo-action`"
2246− ?. ?=([[* * [%name *]] *] rest) (bad rest want)
2810+ ?. ?=([[* * [%name *]] *] rest) (bad-in rest want cen-mask)
2247 (bad-why rest want "`/%` takes no face: it names the type after its mark")
2811 (bad-why rest want "`/%` takes no face: it names the type after its mark")
2248− ?. ?=([[* * [%name *]] *] rest) (bad rest "a name")
2812+ ?. ?=([[* * [%name *]] *] rest) (no-name rest)
2249 =* nam i.rest
2813 =* nam i.rest
2250 ?. =(%'/=' lex.g)
2814 ?. =(%'/=' lex.g)
2251 [%& [%sur [beg.at.g end.at.nam] p.lex.nam] t.rest]
2815 [%& [%sur [beg.at.g end.at.nam] p.lex.nam] t.rest]
2252 =/ more=(list token) t.rest
2816 =/ more=(list token) t.rest
2253− ?: &(?=(^ more) tight.i.more) (bad more "a space after the name")
2817+ ?: &(?=(^ more) tight.i.more) (no-gap more "a space after the name")
2254 ?. ?=([[* * %'/'] *] more)
2818 ?. ?=([[* * %'/'] *] more)
2255− (bad more "a module's path, as /ui/components/card")
2819+ (bad-in more "a module's path, as /ui/components/card" fas-mask)
2256 ;< [[sp=span segs=(list @ta)] after=(list token)] then
2820 ;< [[sp=span segs=(list @ta)] after=(list token)] then
2257− (read-pathlit i.more t.more)
2821+ (read-pathlit i.more t.more |)
2258 [%& [%jibb [beg.at.g end.sp] p.lex.nam segs] after]
2822 [%& [%jibb [beg.at.g end.sp] p.lex.nam segs] after]
2260 :: +read-pathlit: after a path's /, its knots, each after a tight /
2824 :: +read-pathlit: after a path's /, its knots, each after a tight /
2261− :: and tight itself; / alone is the empty path
2825+ :: and tight itself; / alone is the empty path where empty allows it,
2826+ :: in an expression but not an import (doc question)
2263 ++ read-pathlit
2828 ++ read-pathlit
2264− |= [sl=token ts=(list token)]
2829+ |= [sl=token ts=(list token) empty=?]
2265 ^- (pare [span (list @ta)])
2830 ^- (pare [span (list @ta)])
2266 ?. ?=([[* %& [%knot *]] *] ts)
2831 ?. ?=([[* %& [%knot *]] *] ts)
2267 ?: &(?=(^ ts) tight.i.ts !(is-closer i.ts))
2832 ?: &(?=(^ ts) tight.i.ts !(is-closer i.ts))
2268 (bad ts "a path segment")
2833 (bad ts "a path segment")
2834+ ?. empty (bad-space sl ts "a path segment")
2269 [%& [at.sl ~] ts]
2835 [%& [at.sl ~] ts]
2270 =/ segs=(list @ta) ~[p.lex.i.ts]
2836 =/ segs=(list @ta) ~[p.lex.i.ts]
2271 =/ fin=loc end.at.i.ts
2837 =/ fin=loc end.at.i.ts
@@ -2280,10 +2846,11 @@
2280 (bad-space i.rest nex "a path segment")
2846 (bad-space i.rest nex "a path segment")
2282 :: +read-def: ++ name, then an expression or a body; +$ name, then a
2848 :: +read-def: ++ name, then an expression or a body; +$ name, then a
2283− :: mold on its line or alone on a deeper one
2849+ :: mold on its line or alone on a deeper one. can is what may begin
2850+ :: a line where a definition goes (+fail-in).
2285 ++ read-def
2852 ++ read-def
2286− |= ts=(list token)
2853+ |= [ts=(list token) can=@]
2287 ^- (pare def)
2854 ^- (pare def)
2288 ?~ ts (bad ts "a definition")
2855 ?~ ts (bad ts "a definition")
2289 =* rune i.ts
2856 =* rune i.ts
@@ -2295,18 +2862,23 @@
2295 ?: (is-closer rune)
2862 ?: (is-closer rune)
2296 %^ bad-why ts "a definition"
2863 %^ bad-why ts "a definition"
2297 "this closes no bracket, as one open at the end of its line needs none"
2864 "this closes no bracket, as one open at the end of its line needs none"
2866+ ?.((in '/' can) "a definition" "an import or a definition")
2298− ?. =(%'+$' lex.rune) (bad ts "a definition")
2867+ ?: =(%'+' lex.rune)
2868+ (bad-in-why ts want can "`+` begins `++` or `+$`")
2869+ ?. =(%'+$' lex.rune) (bad-in ts want can)
2299 ;< [nam=term after=(list token)] then (read-def-name rune t.ts)
2870 ;< [nam=term after=(list token)] then (read-def-name rune t.ts)
2300 ?: ?=([[* * %indent] *] after)
2871 ?: ?=([[* * %indent] *] after)
2301 ;< [s=shape more=(list token)] then (read-mold t.after)
2872 ;< [s=shape more=(list token)] then (read-mold t.after)
2302 ?: ?=([[* * %dedent] *] more)
2873 ?: ?=([[* * %dedent] *] more)
2303 [%& [%mold [beg.at.rune end:(span-of s)] nam s] t.more]
2874 [%& [%mold [beg.at.rune end:(span-of s)] nam s] t.more]
2304− ?. ?=([[* * %newline] *] more) (bad-end more)
2875+ ?. ?=([[* * %newline] *] more) (bad-end-in more 0)
2305 %^ bad-why more "the end of the mold"
2876 %^ bad-why more "the end of the mold"
2306 "a `+$` takes one mold; a union is `$?` with its cases below"
2877 "a `+$` takes one mold; a union is `$?` with its cases below"
2307 ?: ?=([[* * ?(%newline %dedent)] *] after)
2878 ?: ?=([[* * ?(%newline %dedent)] *] after)
2308 (bad after "a mold, on its line or a deeper one")
2879 (bad after "a mold, on its line or a deeper one")
2880+ ?: &(?=(^ after) tight.i.after)
2309− ?: &(?=(^ after) tight.i.after) (bad after "a space after the name")
2881+ (no-gap after "a space after the name")
2310 ;< [s=shape more=(list token)] then (read-mold after)
2882 ;< [s=shape more=(list token)] then (read-mold after)
2311 [%& [%mold [beg.at.rune end:(span-of s)] nam s] more]
2883 [%& [%mold [beg.at.rune end:(span-of s)] nam s] more]
@@ -2316,8 +2888,8 @@
2316 |= [rune=token ts=(list token)]
2888 |= [rune=token ts=(list token)]
2317 ^- (pare term)
2889 ^- (pare term)
2318 ?: &(?=(^ ts) tight.i.ts)
2890 ?: &(?=(^ ts) tight.i.ts)
2319− (bad ts "a space after {(show-found rune)}")
2891+ (no-gap ts "a space after {(show-found rune)}")
2320− ?. ?=([[* * [%name *]] *] ts) (bad ts "a name")
2892+ ?. ?=([[* * [%name *]] *] ts) (no-name ts)
2321 [%& p.lex.i.ts t.ts]
2893 [%& p.lex.i.ts t.ts]
2323 :: +read-expr-or-body: a space and an expression on the line, or a
2895 :: +read-expr-or-body: a space and an expression on the line, or a
@@ -2329,7 +2901,7 @@
2329 ?: ?=([[* * %indent] *] ts) (read-body t.ts)
2901 ?: ?=([[* * %indent] *] ts) (read-body t.ts)
2330 ?: ?=([[* * ?(%newline %dedent)] *] ts)
2902 ?: ?=([[* * ?(%newline %dedent)] *] ts)
2331 (bad ts "an expression, or a body on deeper lines")
2903 (bad ts "an expression, or a body on deeper lines")
2332− ?: &(?=(^ ts) tight.i.ts) (bad ts "a space after {what}")
2904+ ?: &(?=(^ ts) tight.i.ts) (no-gap ts "a space after {what}")
2333 (read-expr ts)
2905 (read-expr ts)
2335 :: +read-body: after its INDENT, { definition NEWLINE } expr DEDENT
2907 :: +read-body: after its INDENT, { definition NEWLINE } expr DEDENT
@@ -2340,16 +2912,20 @@
2340 =| defs=(list def)
2912 =| defs=(list def)
2341 |- ^- (pare expr)
2913 |- ^- (pare expr)
2342 ?: ?=([[* * ?(%'++' %'+$')] *] ts)
2914 ?: ?=([[* * ?(%'++' %'+$')] *] ts)
2343− ;< [d=def after=(list token)] then (read-def ts)
2915+ ;< [d=def after=(list token)] then (read-def ts plus-mask)
2344 ?: ?=([[* * %newline] *] after) $(defs [d defs], ts t.after)
2916 ?: ?=([[* * %newline] *] after) $(defs [d defs], ts t.after)
2345− ?. ?=([[* * %dedent] *] after) (bad-end after)
2917+ ?. ?=([[* * %dedent] *] after) (bad-end-in after (def-can d))
2346 (bad after "the body's final expression, after its definitions")
2918 (bad after "the body's final expression, after its definitions")
2919+ ?: ?=([[* * %'+'] *] ts)
2920+ %: bad-in-why ts "a definition or an expression" plus-mask
2921+ "`+` begins `++` or `+$`"
2347 ;< [e=expr after=(list token)] then (read-expr ts)
2923 ;< [e=expr after=(list token)] then (read-expr ts)
2348 ?: ?=([[* * %dedent] *] after)
2924 ?: ?=([[* * %dedent] *] after)
2349 =/ ds=(list def) (flop defs)
2925 =/ ds=(list def) (flop defs)
2350 =/ beg=loc ?~(ds beg:(span-of e) beg:(span-of i.ds))
2926 =/ beg=loc ?~(ds beg:(span-of e) beg:(span-of i.ds))
2351 [%& [%body [beg end:(span-of e)] ds e] t.after]
2927 [%& [%body [beg end:(span-of e)] ds e] t.after]
2352− ?. ?=([[* * %newline] *] after) (bad-end after)
2928+ ?. ?=([[* * %newline] *] after) (bad-end-in after (tail-can e))
2353 %^ bad-why after "the end of the body"
2929 %^ bad-why after "the end of the body"
2354 "a body's final expression is its last line"
2930 "a body's final expression is its last line"
@@ -2374,7 +2950,7 @@
2374 |= ts=(list token)
2950 |= ts=(list token)
2375 ^- (pare expr)
2951 ^- (pare expr)
2376 ;< [els=(list expr) after=(list token)] then (read-operands ts)
2952 ;< [els=(list expr) after=(list token)] then (read-operands ts)
2377− ?~ els (no-operand ts)
2953+ ?~ els (no-operand ts expr-mask)
2378 [%& (call-of els) after]
2954 [%& (call-of els) after]
2380 :: +read-operands: a call's operands, or those on a group's first
2956 :: +read-operands: a call's operands, or those on a group's first
@@ -2387,15 +2963,27 @@
2387 |- ^- (pare (list expr))
2963 |- ^- (pare (list expr))
2388 ?~ ts [%& (flop els) ts]
2964 ?~ ts [%& (flop els) ts]
2389 =* t i.ts
2965 =* t i.ts
2390− ?: (ends-call t) [%& (flop els) ts]
2966+ ?: (ends-call t)
2967+ :: an error token whose text can't go tight after an operand
2969+ :: after-mask without its =
2970+ ?~(els ~ (tight-error-in file ts (mix after-mask tis-mask)))
2972+ :: or, past a space, can't begin one (+fail-in)
2973+ ?: ?& ?=(^ els) ?=([%error *] lex.t) !tight.t
2974+ !=(':' c.lex.t) !(in c.lex.t operand-mask)
2976+ [%| (moved file "an expression" t)]
2391 ?: &(tight.t ?=(^ els)) (no-space ts)
2978 ?: &(tight.t ?=(^ els)) (no-space ts)
2392 ?: (is-operand-start t)
2979 ?: (is-operand-start t)
2393 ;< [e=expr more=(list token)] then (read-operand ts)
2980 ;< [e=expr more=(list token)] then (read-operand ts)
2394 $(els [e els], ts more)
2981 $(els [e els], ts more)
2395 ?: &(?=(^ els) (is-rune t))
2982 ?: &(?=(^ els) (is-rune t))
2396− %^ bad-why ts "an expression"
2983+ %: bad-in-why ts "an expression" operand-mask
2397− "inside a call, a rune goes in parentheses"
2984+ "inside a call, a rune goes in parentheses"
2398− (no-operand ts)
2986+ (no-operand ts ?~(els expr-mask operand-mask))
2400 :: +read-operand: one operand, told by its first token and, after a
2988 :: +read-operand: one operand, told by its first token and, after a
2401 :: name or a wing, by a tight ( or +
2989 :: name or a wing, by a tight ( or +
@@ -2405,7 +2993,7 @@
2405 ^- (pare expr)
2993 ^- (pare expr)
2406 ?~ ts (bad ts "an expression")
2994 ?~ ts (bad ts "an expression")
2407 =* t i.ts
2995 =* t i.ts
2408− ?+ lex.t (no-operand ts)
2996+ ?+ lex.t (no-operand ts operand-mask)
2409 [%lit *] [%& [%lit at.t p.lex.t] t.ts]
2997 [%lit *] [%& [%lit at.t p.lex.t] t.ts]
2410 [%str *] [%& [%str at.t (text-piece p.lex.t)] t.ts]
2998 [%str *] [%& [%str at.t (text-piece p.lex.t)] t.ts]
2411 [%str-head *] (read-string t t.ts)
2999 [%str-head *] (read-string t t.ts)
@@ -2454,11 +3042,19 @@
2455 :: +read-ctor: |= and a term, with no space: a case's constructor
3043 :: +read-ctor: |= and a term, with no space: a case's constructor
3045+ :: Where an operand goes, |= can only be a constructor or begin |=(,
3046+ :: so a tall gate there fails at the space after |=.
2457 ++ read-ctor
3048 ++ read-ctor
2458 |= [bar=token ts=(list token)]
3049 |= [bar=token ts=(list token)]
2459 ^- (pare expr)
3050 ^- (pare expr)
2460− ?: |(?=(~ ts) !tight.i.ts) (bad-space bar ts "a term")
3051+ ?: |(?=(~ ts) !tight.i.ts)
3052+ %: fail-space file bar ts "`(` or a term"
3053+ ?: ?=([[* * [%lit %term *]] *] ts)
3054+ "a case's constructor takes its term with no space, as |=%got"
3055+ "a gate in an operand is |=(a body)"
2461− ?. ?=([[* * [%lit %term *]] *] ts) (bad ts "a term")
3057+ ?. ?=([[* * [%lit %term *]] *] ts) (bad-in ts "a term" cen-mask)
2462 [%& [%ctor [beg.at.bar end.at.i.ts] p.lex.i.ts] t.ts]
3058 [%& [%ctor [beg.at.bar end.at.i.ts] p.lex.i.ts] t.ts]
2464 :: +read-path: a path literal, as /posts/~zod (doc question)
3060 :: +read-path: a path literal, as /posts/~zod (doc question)
@@ -2467,7 +3063,7 @@
2467 |= [sl=token ts=(list token)]
3063 |= [sl=token ts=(list token)]
2468 ^- (pare expr)
3064 ^- (pare expr)
2469 ;< [[sp=span segs=(list @ta)] after=(list token)] then
3065 ;< [[sp=span segs=(list @ta)] after=(list token)] then
2470− (read-pathlit sl ts)
3066+ (read-pathlit sl ts &)
2471 [%& [%path sp segs] after]
3067 [%& [%path sp segs] after]
2473 :: +read-qath: %/, then its segments, knots or (expr), each after a
3069 :: +read-qath: %/, then its segments, knots or (expr), each after a
@@ -2502,7 +3098,10 @@
2502 ?. ?=([[* * %'('] *] ts) (bad ts "a path segment")
3098 ?. ?=([[* * %'('] *] ts) (bad ts "a path segment")
2503 =* par i.ts
3099 =* par i.ts
2504 ;< [e=expr after=(list token)] then (read-expr t.ts)
3100 ;< [e=expr after=(list token)] then (read-expr t.ts)
3101+ ?. ?=([[* * %')'] *] after)
3102+ =/ dm (doomed t.ts after (closing par ")"))
2505− ?. ?=([[* * %')'] *] after) (unclosed par ")" after)
3104+ (unclosed par ")" after)
2506 [%& [[%expr e] end.at.i.after] t.after]
3105 [%& [[%expr e] end.at.i.after] t.after]
2508 :: +read-string: after its str-head, a string's interpolations and
3107 :: +read-string: after its str-head, a string's interpolations and
@@ -2521,7 +3120,10 @@
2521 $(ps (weld (text-piece p.lex.i.after) ps), op i.after, ts t.after)
3120 $(ps (weld (text-piece p.lex.i.after) ps), op i.after, ts t.after)
2522 ?. ?=([[* * [%str-tail *]] *] after)
3121 ?. ?=([[* * [%str-tail *]] *] after)
2523 =/ brace=loc [line.end.at.op (dec (max 2 col.end.at.op))]
3122 =/ brace=loc [line.end.at.op (dec (max 2 col.end.at.op))]
2524− (bad after "`}` to close the `\{` at {(show-loc brace)}")
3123+ =/ want=tape "`}` to close the `\{` at {(show-loc brace)}"
3124+ =/ dm (doomed ts after want)
2525 =. ps (weld (text-piece p.lex.i.after) ps)
3127 =. ps (weld (text-piece p.lex.i.after) ps)
2526 [%& [%str [beg.at.head end.at.i.after] (flop ps)] t.after]
3128 [%& [%str [beg.at.head end.at.i.after] (flop ps)] t.after]
@@ -2537,15 +3139,19 @@
2537 ^- (pare expr)
3139 ^- (pare expr)
2538 ?: (is-rune-start ts)
3140 ?: (is-rune-start ts)
2539 ;< [e=expr after=(list token)] then (read-expr ts)
3141 ;< [e=expr after=(list token)] then (read-expr ts)
3142+ ?. ?=([[* * %')'] *] after)
3143+ =/ dm (doomed ts after (closing par ")"))
2540− ?. ?=([[* * %')'] *] after) (unclosed par ")" after)
3145+ (unclosed par ")" after)
2541 [%& [%group [beg.at.par end.at.i.after] e] t.after]
3146 [%& [%group [beg.at.par end.at.i.after] e] t.after]
2542 ;< [els=(list expr) after=(list token)] then (read-operands ts)
3147 ;< [els=(list expr) after=(list token)] then (read-operands ts)
2543 ?: ?=([[* * %')'] *] after)
3148 ?: ?=([[* * %')'] *] after)
2544 ?~ els (bad after "an expression")
3149 ?~ els (bad after "an expression")
2545 [%& [%group [beg.at.par end.at.i.after] (call-of els)] t.after]
3150 [%& [%group [beg.at.par end.at.i.after] (call-of els)] t.after]
2546 ?. ?=([[* * %indent] *] after)
3151 ?. ?=([[* * %indent] *] after)
2547− =/ last=(unit span) ?~(els ~ `(span-of (rear els)))
3152+ =/ dm (doomed ts after (closing par ")"))
2548− (unclosed-open par ")" "an argument" last after)
3154+ (unclosed-open par ")" "an argument" after)
2549 ;< [ls=(list item) more=(list token)] then
3155 ;< [ls=(list item) more=(list token)] then
2550 (read-lines %group t.after)
3156 (read-lines %group t.after)
2551 =/ inner=expr (call-of (weld els (turn ls |=(i=item val.i))))
3157 =/ inner=expr (call-of (weld els (turn ls |=(i=item val.i))))
@@ -2554,6 +3160,8 @@
2554 :: +read-bracket: a tuple's, list's or change's items, to its closer
3160 :: +read-bracket: a tuple's, list's or change's items, to its closer
2555 :: on the line, or to the end of its lines below when left open
3161 :: on the line, or to the end of its lines below when left open
3163+ :: pre is the tokens from the last item on, for +doomed.
2557 ++ read-bracket
3165 ++ read-bracket
2558 |= $: kind=?(%tuple %list %change)
3166 |= $: kind=?(%tuple %list %change)
2559 op=token
3167 op=token
@@ -2563,6 +3171,7 @@
2563 ^- (pare expr)
3171 ^- (pare expr)
2564 =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
3172 =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
2565 =| its=(list item)
3173 =| its=(list item)
3174+ =| pre=(list token)
2566 |- ^- (pare expr)
3175 |- ^- (pare expr)
2567 ?~ ts (bad ts "an item")
3176 ?~ ts (bad ts "an item")
2568 =* t i.ts
3177 =* t i.ts
@@ -2571,15 +3180,16 @@
2571 ?: (is-closer t) (unclosed op (trip close) ts)
3180 ?: (is-closer t) (unclosed op (trip close) ts)
2572 ?: ?=(%indent lex.t)
3181 ?: ?=(%indent lex.t)
2573 ;< [ls=(list item) more=(list token)] then (read-lines kind t.ts)
3182 ;< [ls=(list item) more=(list token)] then (read-lines kind t.ts)
2574− =/ all=(list item) (weld (flop its) ls)
3183+ =/ every=(list item) (weld (flop its) ls)
2575− =/ fin=loc ?~(all end.at.op end.at:(rear all))
3184+ =/ fin=loc ?~(every end.at.op end.at:(rear every))
2576− [%& (bracket-node kind op target all fin) more]
3185+ [%& (bracket-node kind op target every fin) more]
2577 ?: ?=(?(%newline %dedent) lex.t)
3186 ?: ?=(?(%newline %dedent) lex.t)
2578− =/ last=(unit span) ?~(its ~ `at.i.its)
3187+ =/ dm (doomed pre ts (closing op (trip close)))
2579− (unclosed-open op (trip close) "an item" last ts)
3189+ (unclosed-open op (trip close) "an item" ts)
2580 ?: &(tight.t ?=(^ its)) (no-space ts)
3190 ?: &(tight.t ?=(^ its)) (no-space ts)
2581 ;< [i=item more=(list token)] then (read-item kind ts)
3191 ;< [i=item more=(list token)] then (read-item kind ts)
2582− $(its [i its], ts more)
3192+ $(its [i its], ts more, pre ts)
2584 :: +read-item: [ name= ] operand; a tuple's item may be named, a
3194 :: +read-item: [ name= ] operand; a tuple's item may be named, a
2585 :: change's must be, a list's is not
3195 :: change's must be, a list's is not
@@ -2595,8 +3205,9 @@
2595 [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
3205 [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
2596 ?: ?=(%change kind) (unnamed ts)
3206 ?: ?=(%change kind) (unnamed ts)
2597 ?: &(?=(^ ts) (is-rune i.ts))
3207 ?: &(?=(^ ts) (is-rune i.ts))
2598− %^ bad-why ts "an expression"
3208+ %: bad-in-why ts "an expression" operand-mask
2599− "inside brackets, a rune goes in parentheses"
3209+ "inside brackets, a rune goes in parentheses"
2600 ;< [v=expr after=(list token)] then (read-operand ts)
3211 ;< [v=expr after=(list token)] then (read-operand ts)
2601 [%& [(span-of v) ~ v] after]
3212 [%& [(span-of v) ~ v] after]
@@ -2611,7 +3222,7 @@
2611 ;< [l=item after=(list token)] then (read-line kind ts)
3222 ;< [l=item after=(list token)] then (read-line kind ts)
2612 ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
3223 ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
2613 ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
3224 ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
2614− ?. ?=([[* * ?(%')' %']')] *] after) (bad-end after)
3225+ ?. ?=([[* * ?(%')' %']')] *] after) (bad-end-in after (tail-can val.l))
2615 %^ bad-why after "the end of the line"
3226 %^ bad-why after "the end of the line"
2616 "a bracket open at the end of its line takes no closer"
3227 "a bracket open at the end of its line takes no closer"
@@ -2622,6 +3233,10 @@
2622 ++ read-line
3233 ++ read-line
2623 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3234 |= [kind=?(%tuple %list %change %group) ts=(list token)]
2624 ^- (pare item)
3235 ^- (pare item)
3236+ ?: ?=([[* * ?(%')' %']')] *] ts)
3237+ %^ bad-why ts "an item"
3238+ %+ weld "a bracket open at the end of its line takes no closer: "
3239+ "its items end at the first line that isn't deeper"
2625 ?: ?& ?=(?(%tuple %change) kind)
3240 ?: ?& ?=(?(%tuple %change) kind)
2626 ?=([[* * [%name *]] [* %& %'='] *] ts)
3241 ?=([[* * [%name *]] [* %& %'='] *] ts)
@@ -2641,17 +3256,22 @@
2641 ^- (pare expr)
3256 ^- (pare expr)
2642 ;< [s=sample after=(list token)] then (read-sample ts)
3257 ;< [s=sample after=(list token)] then (read-sample ts)
2643 ?: ?=([[* * %')'] *] after) (bad after "the gate's body")
3258 ?: ?=([[* * %')'] *] after) (bad after "the gate's body")
3259+ ?: &(?=(^ after) tight.i.after)
2644− ?: &(?=(^ after) tight.i.after) (bad after "a space after the sample")
3260+ (no-gap after "a space after the sample")
3261+ =/ dm (doomed ts after "the gate's body")
2645 ?: &(?=(^ after) (is-rune i.after))
3263 ?: &(?=(^ after) (is-rune i.after))
2646− %^ bad-why after "an expression"
3264+ %: bad-in-why after "an expression" operand-mask
2647− "the wide gate's body is an operand, so a rune goes in parentheses"
3265+ "the wide gate's body is an operand, so a rune goes in parentheses"
2648 ;< [b=expr more=(list token)] then (read-operand after)
3267 ;< [b=expr more=(list token)] then (read-operand after)
2649 ?: ?=([[* * %')'] *] more)
3268 ?: ?=([[* * %')'] *] more)
2650 [%& [%gate-wide [beg.at.op end.at.i.more] s b] t.more]
3269 [%& [%gate-wide [beg.at.op end.at.i.more] s b] t.more]
3270+ =/ dn (doomed after more (closing op ")"))
2651 ?. &(?=(^ more) !tight.i.more (is-operand-start i.more))
3272 ?. &(?=(^ more) !tight.i.more (is-operand-start i.more))
2652 (unclosed op ")" more)
3273 (unclosed op ")" more)
2653− %^ bad-why more
3274+ %^ bad-why more (closing op ")")
2654− "`)` to close the `|=(` at {(show-loc beg.at.op)}"
2655 "the wide gate's body is one operand, so a call goes in parentheses"
3275 "the wide gate's body is one operand, so a call goes in parentheses"
2657 :: +read-gate: |= sample, then an expression or a body
3277 :: +read-gate: |= sample, then an expression or a body
@@ -2659,8 +3279,13 @@
2659 ++ read-gate
3279 ++ read-gate
2660 |= [bar=token ts=(list token)]
3280 |= [bar=token ts=(list token)]
2661 ^- (pare expr)
3281 ^- (pare expr)
3282+ ?: &(?=(^ ts) tight.i.ts)
3283+ :: a % could begin a constructor's term, as |=%got
3284+ ?: =('%' (first-char i.ts)) (bad-in ts "a term" cen-mask)
2662− ?: &(?=(^ ts) tight.i.ts) (bad ts "a space after `|=`")
3285+ (no-gap ts "a space after `|=`")
2663 ;< [s=sample after=(list token)] then (read-sample ts)
3286 ;< [s=sample after=(list token)] then (read-sample ts)
3287+ =/ dm (doomed ts after "an expression, or a body on deeper lines")
2664 ;< [e=expr more=(list token)] then
3289 ;< [e=expr more=(list token)] then
2665 (read-expr-or-body "the sample" after)
3290 (read-expr-or-body "the sample" after)
2666 [%& [%gate [beg.at.bar end:(span-of e)] s e] more]
3291 [%& [%gate [beg.at.bar end:(span-of e)] s e] more]
@@ -2672,6 +3297,8 @@
2672 ^- (pare expr)
3297 ^- (pare expr)
2673 ?: &(?=(^ ts) tight.i.ts) (wide-rune "^-" ts)
3298 ?: &(?=(^ ts) tight.i.ts) (wide-rune "^-" ts)
2674 ;< [s=shape after=(list token)] then (read-mold ts)
3299 ;< [s=shape after=(list token)] then (read-mold ts)
3300+ =/ dm (doomed ts after "an expression, or a body on deeper lines")
2675 ;< [e=expr more=(list token)] then
3302 ;< [e=expr more=(list token)] then
2676 (read-expr-or-body "the mold" after)
3303 (read-expr-or-body "the mold" after)
2677 [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
3304 [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
@@ -2681,9 +3308,11 @@
2681 ++ read-trace
3308 ++ read-trace
2682 |= [sig=token ts=(list token)]
3309 |= [sig=token ts=(list token)]
2683 ^- (pare expr)
3310 ^- (pare expr)
2684− ?: &(?=(^ ts) tight.i.ts) (bad ts "a space after `~&`")
3311+ ?: &(?=(^ ts) tight.i.ts) (wide-rune "~&" ts)
2685 ;< [v=expr after=(list token)] then (read-expr ts)
3312 ;< [v=expr after=(list token)] then (read-expr ts)
2686 ?. ?=([[* * %indent] *] after)
3313 ?. ?=([[* * %indent] *] after)
3314+ =/ dm (doomed ts after "`~&`'s body on deeper lines")
2687 (bad after "`~&`'s body on deeper lines")
3316 (bad after "`~&`'s body on deeper lines")
2688 ;< [b=expr more=(list token)] then (read-body t.after)
3317 ;< [b=expr more=(list token)] then (read-body t.after)
2689 [%& [%trace [beg.at.sig end:(span-of b)] v b] more]
3318 [%& [%trace [beg.at.sig end:(span-of b)] v b] more]
@@ -2696,13 +3325,15 @@
2696 ?: &(?=(^ ts) tight.i.ts) (wide-rune "?-" ts)
3325 ?: &(?=(^ ts) tight.i.ts) (wide-rune "?-" ts)
2697 ;< [s=expr after=(list token)] then (read-expr ts)
3326 ;< [s=expr after=(list token)] then (read-expr ts)
2698 ?. ?=([[* * %indent] *] after)
3327 ?. ?=([[* * %indent] *] after)
3328+ =/ dm (doomed ts after "`?-`'s arms on deeper lines")
2699 (bad after "`?-`'s arms on deeper lines")
3330 (bad after "`?-`'s arms on deeper lines")
2700 =| arms=(list arm)
3331 =| arms=(list arm)
2701 =/ rest=(list token) t.after
3332 =/ rest=(list token) t.after
2702 |- ^- (pare expr)
3333 |- ^- (pare expr)
2703 ;< [a=arm more=(list token)] then (read-arm rest)
3334 ;< [a=arm more=(list token)] then (read-arm rest)
2704 ?: ?=([[* * %newline] *] more) $(arms [a arms], rest t.more)
3335 ?: ?=([[* * %newline] *] more) $(arms [a arms], rest t.more)
2705− ?. ?=([[* * %dedent] *] more) (bad-end more)
3336+ ?. ?=([[* * %dedent] *] more) (bad-end-in more (tail-can val.a))
2706 [%& [%branch [beg.at.wut end.at.a] s (flop [a arms])] t.more]
3337 [%& [%branch [beg.at.wut end.at.a] s (flop [a arms])] t.more]
2708 :: +read-arm: a pattern, then an expression or a body
3339 :: +read-arm: a pattern, then an expression or a body
@@ -2714,6 +3345,9 @@
2714 ?: ?=([[* %& %'+'] *] after)
3345 ?: ?=([[* %& %'+'] *] after)
2715 %^ bad-why after "a space after the pattern"
3346 %^ bad-why after "a space after the pattern"
2716 "patterns take no pairs: write a cell, as [%gap %s2]"
3347 "patterns take no pairs: write a cell, as [%gap %s2]"
3348+ ?: ?=([[* %& %'='] *] after)
3349+ %^ bad-why after "a space after the pattern"
3350+ "patterns take no `name=`: a bare name binds, as [a b]"
2717 ;< [e=expr more=(list token)] then
3351 ;< [e=expr more=(list token)] then
2718 (read-expr-or-body "the pattern" after)
3352 (read-expr-or-body "the pattern" after)
2719 [%& [[beg:(span-of p) end:(span-of e)] p e] more]
3353 [%& [[beg:(span-of p) end:(span-of e)] p e] more]
@@ -2721,17 +3355,18 @@
2721 :: +read-pattern: a term, number, string, ship, loobean, ~, * or name,
3355 :: +read-pattern: a term, number, string, ship, loobean, ~, * or name,
2722 :: or a cell of patterns
3356 :: or a cell of patterns
3358+ :: Where a pattern can't take a token, the error points where the
3359+ :: token stops being a pattern's start (+fail-in): a date or knot
2724− :: A date, duration or knot fails at its second character, since ~
3360+ :: at its second character, since ~ alone is null; a duration at its
2725− :: alone is null and no ship goes on so; ~[ at its [; and a string
3361+ :: third, as ~s could begin the ship ~sev; ~[ at its [; a string
2726− :: with {…} at its { (section 3, Errors).
3362+ :: with {…} at its {; a wing at its first dot.
2728 ++ read-pattern
3364 ++ read-pattern
2729 |= ts=(list token)
3365 |= ts=(list token)
2730 ^- (pare pattern)
3366 ^- (pare pattern)
2731 ?~ ts (bad ts "a pattern")
3367 ?~ ts (bad ts "a pattern")
2732 =* t i.ts
3368 =* t i.ts
2733− =/ next=loc [line.beg.at.t +(col.beg.at.t)]
2734− ?+ lex.t (bad ts "a pattern")
3369+ ?+ lex.t (bad-in ts "a pattern" pattern-mask)
2735 [%lit *]
3370 [%lit *]
2736 =* l p.lex.t
3371 =* l p.lex.t
2737 ?: ?=(?(%number %ship %term %loobean %null) form.l)
3372 ?: ?=(?(%number %ship %term %loobean %null) form.l)
@@ -2742,7 +3377,8 @@
2742 %duration "durations"
3377 %duration "durations"
2743 %knot "knots"
3378 %knot "knots"
2745− %+ bad-at next
3380+ =/ n=@ud ?:(?=(%duration form.l) 2 1)
3381+ %+ bad-at [line.beg.at.t (add n col.beg.at.t)]
2747 "expected a pattern, found {(show-found t)}; patterns take no "
3383 "expected a pattern, found {(show-found t)}; patterns take no "
@@ -2754,6 +3390,11 @@
2754 [%name *] [%& [%bind at.t p.lex.t] t.ts]
3390 [%name *] [%& [%bind at.t p.lex.t] t.ts]
2755 %'[' (read-cell-pattern t t.ts)
3391 %'[' (read-cell-pattern t t.ts)
2756 %'`' (bad-why ts "a pattern" "patterns take no units: write [~ x]")
3392 %'`' (bad-why ts "a pattern" "patterns take no units: write [~ x]")
3395+ %: bad-in-why ts "a pattern" pattern-mask
3396+ "a name in a pattern binds anew, so it has no `.`"
2758 [%str-head *]
3399 [%str-head *]
2759 %+ bad-at [line.end.at.t (dec (max 2 col.end.at.t))]
3400 %+ bad-at [line.end.at.t (dec (max 2 col.end.at.t))]
@@ -2761,7 +3402,7 @@
2761 "patterns take strings without `\{…}`"
3402 "patterns take strings without `\{…}`"
2764− %+ bad-at next
3405+ %+ bad-at [line.beg.at.t +(col.beg.at.t)]
2765 "expected a pattern, found `~[`; patterns take no lists"
3406 "expected a pattern, found `~[`; patterns take no lists"
@@ -2777,7 +3418,7 @@
2777 [%& [%cell [beg.at.op end.at.i.ts] (flop ps)] t.ts]
3418 [%& [%cell [beg.at.op end.at.i.ts] (flop ps)] t.ts]
2778 ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3419 ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
2779 (unclosed op "]" ts)
3420 (unclosed op "]" ts)
2780− ?: &(?=(^ ps) ?=(^ ts) tight.i.ts) (no-space ts)
3421+ ?: &(?=(^ ps) ?=(^ ts) tight.i.ts) (no-space-pattern ts)
2781 ;< [p=pattern after=(list token)] then (read-pattern ts)
3422 ;< [p=pattern after=(list token)] then (read-pattern ts)
2782 $(ps [p ps], ts after)
3423 $(ps [p ps], ts after)
@@ -2791,21 +3432,26 @@
2791 ?: ?=([[* * [%name *]] *] ts) [%& [%bind at.i.ts p.lex.i.ts] t.ts]
3432 ?: ?=([[* * [%name *]] *] ts) [%& [%bind at.i.ts p.lex.i.ts] t.ts]
2792 ?: ?=([[* * %'='] *] ts) (read-pun i.ts t.ts)
3433 ?: ?=([[* * %'='] *] ts) (read-pun i.ts t.ts)
2793 ?: &(?=(^ ts) (is-layout i.ts)) (bad ts "a sample")
3434 ?: &(?=(^ ts) (is-layout i.ts)) (bad ts "a sample")
3435+ ?: ?=([[* * [%error *]] *] ts)
3436+ (bad-in ts "a mold" (con mold-mask tis-mask))
2794 ?. ?=([[* * %'['] *] ts)
3437 ?. ?=([[* * %'['] *] ts)
2795 ;< [s=shape after=(list token)] then (read-mold ts)
3438 ;< [s=shape after=(list token)] then (read-mold ts)
2796 [%& [%bare (span-of s) s] after]
3439 [%& [%bare (span-of s) s] after]
2797 =* op i.ts
3440 =* op i.ts
2798 =| ss=(list sample)
3441 =| ss=(list sample)
3442+ =| pre=(list token)
2799 =/ rest=(list token) t.ts
3443 =/ rest=(list token) t.ts
2800 |- ^- (pare sample)
3444 |- ^- (pare sample)
2801 ?: ?=([[* * %']'] *] rest)
3445 ?: ?=([[* * %']'] *] rest)
2802 ?~ ss (bad rest "a sample")
3446 ?~ ss (bad rest "a sample")
2803 [%& [%cell [beg.at.op end.at.i.rest] (flop ss)] t.rest]
3447 [%& [%cell [beg.at.op end.at.i.rest] (flop ss)] t.rest]
2804 ?: &(?=(^ rest) |((is-closer i.rest) (is-layout i.rest)))
3448 ?: &(?=(^ rest) |((is-closer i.rest) (is-layout i.rest)))
3449+ =/ dm (doomed pre rest (closing op "]"))
2805 (unclosed op "]" rest)
3451 (unclosed op "]" rest)
2806 ?: &(?=(^ ss) ?=(^ rest) tight.i.rest) (no-space rest)
3452 ?: &(?=(^ ss) ?=(^ rest) tight.i.rest) (no-space rest)
2807 ;< [s=sample after=(list token)] then (read-sample rest)
3453 ;< [s=sample after=(list token)] then (read-sample rest)
2808− $(ss [s ss], rest after)
3454+ $(ss [s ss], rest after, pre rest)
2810 :: +read-field: a cell mold's field: name=mold, =name, or a mold
3456 :: +read-field: a cell mold's field: name=mold, =name, or a mold
@@ -2814,6 +3460,9 @@
2814 ^- (pare field)
3460 ^- (pare field)
2815 ?: ?=([[* * [%name *]] [* %& %'='] *] ts) (read-face ts)
3461 ?: ?=([[* * [%name *]] [* %& %'='] *] ts) (read-face ts)
2816 ?: ?=([[* * %'='] *] ts) (read-pun i.ts t.ts)
3462 ?: ?=([[* * %'='] *] ts) (read-pun i.ts t.ts)
3463+ :: = begins a pun here, as a mold's first characters begin a mold
3464+ ?: ?=([[* * [%error *]] *] ts)
3465+ (bad-in ts "a mold" (con mold-mask tis-mask))
2817 ;< [s=shape after=(list token)] then (read-mold ts)
3466 ;< [s=shape after=(list token)] then (read-mold ts)
2818 [%& [%bare (span-of s) s] after]
3467 [%& [%bare (span-of s) s] after]
@@ -2835,7 +3484,7 @@
2835 |= [tis=token ts=(list token)]
3484 |= [tis=token ts=(list token)]
2836 ^- (pare field)
3485 ^- (pare field)
2837 ?: |(?=(~ ts) !tight.i.ts) (bad-space tis ts "a name")
3486 ?: |(?=(~ ts) !tight.i.ts) (bad-space tis ts "a name")
2838− ?. ?=([[* * [%name *]] *] ts) (bad ts "a name")
3487+ ?. ?=([[* * [%name *]] *] ts) (no-name ts)
2839 [%& [%pun [beg.at.tis end.at.i.ts] p.lex.i.ts] t.ts]
3488 [%& [%pun [beg.at.tis end.at.i.ts] p.lex.i.ts] t.ts]
2841 :: +read-mold: one mold
3490 :: +read-mold: one mold
@@ -2845,7 +3494,7 @@
2845 ^- (pare shape)
3494 ^- (pare shape)
2846 ?~ ts (bad ts "a mold")
3495 ?~ ts (bad ts "a mold")
2847 =* t i.ts
3496 =* t i.ts
2848− ?+ lex.t (bad ts "a mold")
3497+ ?+ lex.t (bad-in ts "a mold" mold-mask)
2849 [%aura *] [%& [%aura at.t p.lex.t] t.ts]
3498 [%aura *] [%& [%aura at.t p.lex.t] t.ts]
2850 %'*' [%& [%noun at.t ~] t.ts]
3499 %'*' [%& [%noun at.t ~] t.ts]
2851 %'!!' [%& [%void at.t ~] t.ts]
3500 %'!!' [%& [%void at.t ~] t.ts]
@@ -2860,9 +3509,15 @@
2860 %'$?(' (read-union-wide t t.ts)
3509 %'$?(' (read-union-wide t t.ts)
2861 %'$-(' (read-fn t t.ts)
3510 %'$-(' (read-fn t t.ts)
2862 %'|$' (read-generic t t.ts)
3511 %'|$' (read-generic t t.ts)
3514+ %: bad-in-why ts "a mold" mold-mask
3515+ "a gate's mold is $-(sample product)"
2864 [%lit *]
3518 [%lit *]
2865− ?. ?=(?(%null %term %loobean) form.p.lex.t) (bad ts "a mold")
3519+ ?. ?=(?(%null %term %loobean) form.p.lex.t)
3520+ (bad-in ts "a mold" mold-mask)
2866 [%& [%const at.t p.lex.t] t.ts]
3521 [%& [%const at.t p.lex.t] t.ts]
@@ -2873,15 +3528,18 @@
2873 |= [op=token spaced=? ts=(list token)]
3528 |= [op=token spaced=? ts=(list token)]
2874 ^- (pare [(list shape) loc])
3529 ^- (pare [(list shape) loc])
2875 =| ms=(list shape)
3530 =| ms=(list shape)
3531+ =| pre=(list token)
2876 |- ^- (pare [(list shape) loc])
3532 |- ^- (pare [(list shape) loc])
2877 ?: ?=([[* * %')'] *] ts)
3533 ?: ?=([[* * %')'] *] ts)
2878 ?~ ms (bad ts "a mold")
3534 ?~ ms (bad ts "a mold")
2879 [%& [(flop ms) end.at.i.ts] t.ts]
3535 [%& [(flop ms) end.at.i.ts] t.ts]
2880 ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3536 ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3537+ =/ dm (doomed pre ts (closing op ")"))
2881 (unclosed op ")" ts)
3539 (unclosed op ")" ts)
2882 ?: &(?=(^ ts) tight.i.ts |(spaced ?=(^ ms))) (no-space ts)
3540 ?: &(?=(^ ts) tight.i.ts |(spaced ?=(^ ms))) (no-space ts)
2883 ;< [m=shape after=(list token)] then (read-mold ts)
3541 ;< [m=shape after=(list token)] then (read-mold ts)
2884− $(ms [m ms], ts after)
3542+ $(ms [m ms], ts after, pre ts)
2886 :: +read-apply: ( ref mold { mold } )
3544 :: +read-apply: ( ref mold { mold } )
@@ -2889,7 +3547,7 @@
2889 |= [op=token ts=(list token)]
3547 |= [op=token ts=(list token)]
2890 ^- (pare shape)
3548 ^- (pare shape)
2891 ?. ?=([[* * ?([%name *] [%wing *])] *] ts)
3549 ?. ?=([[* * ?([%name *] [%wing *])] *] ts)
2892− (bad ts "a mold's name, as in (list @t)")
3550+ (bad-in ts "a mold's name, as in (list @t)" lower-mask)
2893 ;< [[ms=(list shape) fin=loc] after=(list token)] then
3551 ;< [[ms=(list shape) fin=loc] after=(list token)] then
2894 (read-molds op & t.ts)
3552 (read-molds op & t.ts)
2895 [%& [%apply [beg.at.op fin] (names-of lex.i.ts) ms] after]
3553 [%& [%apply [beg.at.op fin] (names-of lex.i.ts) ms] after]
@@ -2911,10 +3569,15 @@
2911 ;< [a=shape after=(list token)] then (read-mold ts)
3569 ;< [a=shape after=(list token)] then (read-mold ts)
2912 ?: ?=([[* * %')'] *] after) (bad after "a mold, the product")
3570 ?: ?=([[* * %')'] *] after) (bad after "a mold, the product")
2913 ?: &(?=(^ after) |((is-closer i.after) (is-layout i.after)))
3571 ?: &(?=(^ after) |((is-closer i.after) (is-layout i.after)))
3572+ =/ dm (doomed ts after (closing op ")"))
2914 (unclosed op ")" after)
3574 (unclosed op ")" after)
2915 ?: &(?=(^ after) tight.i.after) (no-space after)
3575 ?: &(?=(^ after) tight.i.after) (no-space after)
2916 ;< [b=shape more=(list token)] then (read-mold after)
3576 ;< [b=shape more=(list token)] then (read-mold after)
3577+ ?. ?=([[* * %')'] *] more)
3578+ =/ dn (doomed after more (closing op ")"))
2917− ?. ?=([[* * %')'] *] more) (unclosed op ")" more)
3580+ (unclosed op ")" more)
2918 [%& [%fn [beg.at.op end.at.i.more] a b] t.more]
3581 [%& [%fn [beg.at.op end.at.i.more] a b] t.more]
2920 :: +read-cell-mold: [ field { field } ]
3583 :: +read-cell-mold: [ field { field } ]
@@ -2923,15 +3586,18 @@
2923 |= [op=token ts=(list token)]
3586 |= [op=token ts=(list token)]
2924 ^- (pare shape)
3587 ^- (pare shape)
2925 =| fs=(list field)
3588 =| fs=(list field)
3589+ =| pre=(list token)
2926 |- ^- (pare shape)
3590 |- ^- (pare shape)
2927 ?: ?=([[* * %']'] *] ts)
3591 ?: ?=([[* * %']'] *] ts)
2928 ?~ fs (bad ts "a mold")
3592 ?~ fs (bad ts "a mold")
2929 [%& [%cell [beg.at.op end.at.i.ts] (flop fs)] t.ts]
3593 [%& [%cell [beg.at.op end.at.i.ts] (flop fs)] t.ts]
2930 ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3594 ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
3595+ =/ dm (doomed pre ts (closing op "]"))
2931 (unclosed op "]" ts)
3597 (unclosed op "]" ts)
2932 ?: &(?=(^ fs) ?=(^ ts) tight.i.ts) (no-space ts)
3598 ?: &(?=(^ fs) ?=(^ ts) tight.i.ts) (no-space ts)
2933 ;< [f=field after=(list token)] then (read-field ts)
3599 ;< [f=field after=(list token)] then (read-field ts)
2934− $(fs [f fs], ts after)
3600+ $(fs [f fs], ts after, pre ts)
2936 :: +read-union: $?, then its cases below, one mold per line
3602 :: +read-union: $?, then its cases below, one mold per line
@@ -2951,6 +3617,7 @@
2951 ?: ?=([[* * %dedent] *] after)
3617 ?: ?=([[* * %dedent] *] after)
2952 [%& [%union [beg.at.buc end:(span-of c)] (flop [c cs])] t.after]
3618 [%& [%union [beg.at.buc end:(span-of c)] (flop [c cs])] t.after]
2953 ?: ?=([[* * %indent] *] after) (bad-end after)
3619 ?: ?=([[* * %indent] *] after) (bad-end after)
3620+ ?: &(?=(^ after) (stray i.after)) (bad-end after)
2954 (bad-why after "the end of the line" "a union takes one case per line")
3621 (bad-why after "the end of the line" "a union takes one case per line")
2956 :: +read-generic: |$ [ typevar { typevar } ] mold
3623 :: +read-generic: |$ [ typevar { typevar } ] mold
@@ -2958,9 +3625,9 @@
2958 ++ read-generic
3625 ++ read-generic
2959 |= [bar=token ts=(list token)]
3626 |= [bar=token ts=(list token)]
2960 ^- (pare shape)
3627 ^- (pare shape)
2961− ?: &(?=(^ ts) tight.i.ts) (bad ts "a space after `|$`")
3628+ ?: &(?=(^ ts) tight.i.ts) (wide-rune "|$" ts)
2962 ?. ?=([[* * %'['] *] ts)
3629 ?. ?=([[* * %'['] *] ts)
2963− (bad ts "`[` and its type variables, as in |$ [M]")
3630+ (bad-in ts "`[` and its type variables, as in |$ [M]" sel-mask)
2964 =* op i.ts
3631 =* op i.ts
2965 =| vs=(list @t)
3632 =| vs=(list @t)
2966 =/ rest=(list token) t.ts
3633 =/ rest=(list token) t.ts
@@ -2968,13 +3635,14 @@
2968 ?: ?=([[* * %']'] *] rest)
3635 ?: ?=([[* * %']'] *] rest)
2969 ?~ vs (bad rest "a type variable")
3636 ?~ vs (bad rest "a type variable")
2970 =/ more=(list token) t.rest
3637 =/ more=(list token) t.rest
2971− ?: &(?=(^ more) tight.i.more) (bad more "a space after `]`")
3638+ ?: &(?=(^ more) tight.i.more) (no-gap more "a space after `]`")
2972 ;< [b=shape after=(list token)] then (read-mold more)
3639 ;< [b=shape after=(list token)] then (read-mold more)
2973 [%& [%generic [beg.at.bar end:(span-of b)] (flop vs) b] after]
3640 [%& [%generic [beg.at.bar end:(span-of b)] (flop vs) b] after]
2974 ?: &(?=(^ rest) |((is-closer i.rest) (is-layout i.rest)))
3641 ?: &(?=(^ rest) |((is-closer i.rest) (is-layout i.rest)))
2975 (unclosed op "]" rest)
3642 (unclosed op "]" rest)
2976 ?: &(?=(^ vs) ?=(^ rest) tight.i.rest) (no-space rest)
3643 ?: &(?=(^ vs) ?=(^ rest) tight.i.rest) (no-space rest)
3644+ ?. ?=([[* * [%tvar *]] *] rest)
2977− ?. ?=([[* * [%tvar *]] *] rest) (bad rest "a type variable")
3645+ (bad-in rest "a type variable" upper-mask)
2978 $(vs [p.lex.i.rest vs], rest t.rest)
3646 $(vs [p.lex.i.rest vs], rest t.rest)
2980 :: +read-pathmold: / [ segment { / segment } ], each / and segment
3648 :: +read-pathmold: / [ segment { / segment } ], each / and segment
@@ -3010,16 +3678,16 @@
3010 =* op i.ts
3678 =* op i.ts
3011 =/ r1=(list token) t.ts
3679 =/ r1=(list token) t.ts
3012 ?: |(?=(~ r1) !tight.i.r1) (bad-space op r1 "a name")
3680 ?: |(?=(~ r1) !tight.i.r1) (bad-space op r1 "a name")
3013− ?. ?=([[* * [%name *]] *] r1) (bad r1 "a name")
3681+ ?. ?=([[* * [%name *]] *] r1) (no-name r1)
3014 =/ r2=(list token) t.r1
3682 =/ r2=(list token) t.r1
3015 ?: |(?=(~ r2) !tight.i.r2) (bad-space i.r1 r2 "`=`")
3683 ?: |(?=(~ r2) !tight.i.r2) (bad-space i.r1 r2 "`=`")
3016− ?. ?=([[* * %'='] *] r2) (bad r2 "`=`")
3684+ ?. ?=([[* * %'='] *] r2) (bad-in r2 "`=`" tis-mask)
3017 =/ r3=(list token) t.r2
3685 =/ r3=(list token) t.r2
3018 ?: |(?=(~ r3) !tight.i.r3) (bad-space i.r2 r3 "an aura")
3686 ?: |(?=(~ r3) !tight.i.r3) (bad-space i.r2 r3 "an aura")
3019− ?. ?=([[* * [%aura *]] *] r3) (bad r3 "an aura")
3687+ ?. ?=([[* * [%aura *]] *] r3) (bad-in r3 "an aura" pat-mask)
3020 =/ r4=(list token) t.r3
3688 =/ r4=(list token) t.r3
3021 ?: |(?=(~ r4) !tight.i.r4) (bad-space i.r3 r4 "`]`")
3689 ?: |(?=(~ r4) !tight.i.r4) (bad-space i.r3 r4 "`]`")
3022− ?. ?=([[* * %']'] *] r4) (bad r4 "`]`")
3690+ ?. ?=([[* * %']'] *] r4) (bad-in r4 "`]`" ser-mask)
3023 =/ at=span [beg.at.op end.at.i.r4]
3691 =/ at=span [beg.at.op end.at.i.r4]
3024 [%& [[%typed at p.lex.i.r1 p.lex.i.r3] end.at.i.r4] t.r4]
3692 [%& [[%typed at p.lex.i.r1 p.lex.i.r3] end.at.i.r4] t.r4]
@@ -3029,38 +3697,97 @@
3029:: +outline: a node as +check-spans sees it
3697:: +outline: a node as +check-spans sees it
3031:: lead lists the kinds (+kind-of) of token the node may start with,
3699:: lead lists the kinds (+kind-of) of token the node may start with,
3032−:: or is ~ when it starts with its first child; last likewise for its
3700+:: or is ~ when it starts with its first child; stop says where it
3033−:: end, and open lets a bracket that may be left open end with its
3701+:: ends (+stop).
3034−:: last child instead.
3036+$ outline
3703+$ outline
3037− $~ [%$ *span ~ ~ | ~]
3704+ $~ [%$ *span ~ %kid ~]
3038 $: kind=@tas
3705 $: kind=@tas
3040 lead=(list @)
3707 lead=(list @)
3041− last=(list @)
3708+ =stop
3043 kids=(list outline)
3709 kids=(list outline)
3712+:: +stop: where a node ends, by the tokens of its text alone
3714+:: %kid with its last child
3715+:: %one where its first token ends: a name, a literal
3716+:: %two where the token after its first ends: |=%got, =msg, /- todo
3717+:: %shut at the closer of its first token, an opener closed on its
3718+:: line; or with its last child, if that opener is left open
3719+:: or is a rune, as $? with its cases below
3720+:: %shut2 likewise from the token after its first, a change's (
3721+:: %run at the end of the path it starts: then each tight / and
3722+:: knot, and each tight [ or ( to its closer
3723+:: %run3 likewise from its third token, an import's path
3724+:: %string at the str-tail that ends its string, past each str-mid
3726++$ stop ?(%kid %one %two %shut %shut2 %run %run3 %string)
3728+:: +tinfo: a token as +check-spans sees it: its kind, its end, and the
3729+:: next token's start and whether that is tight, unless it is a layout
3732++$ tinfo [kind=@ end=loc nex=(unit [beg=loc tight=?])]
3046:: +check-spans: whether a module's spans follow section 1's rules
3734:: +check-spans: whether a module's spans follow section 1's rules
3048:: A node starts at its first token and ends where its last token
3736:: A node starts at its first token and ends where its last token
3049:: ends, never at a layout token: at its own token where it has one
3737:: ends, never at a layout token: at its own token where it has one
3050−:: there (a rune, a name, an opener or a closer), else where its
3738+:: there (a rune, a name, an opener), else where its first child does;
3051−:: first or last child does. Its children's spans lie inside its own
3739+:: and at the token +stop names, which it finds from the tokens alone,
3740+:: matching each opener with its closer on the line. Its children's
3052−:: in source order, and so do the module's imports and definitions.
3741+:: spans lie inside its own in source order, and so do the module's
3053−:: Gives the first node that breaks a rule, and how, or ~.
3742+:: imports and definitions. Gives the first node that breaks a rule,
3743+:: and how, or ~. +check-spans-test checks that it catches spans a
3744+:: parser bug could give.
3055++ check-spans
3746++ check-spans
3056 |= [mod=module toks=(list token)]
3747 |= [mod=module toks=(list token)]
3057 ^- (unit tape)
3748 ^- (unit tape)
3058− =/ real=(list token) (skip toks is-layout)
3749+ %+ check-outlines toks
3059− =/ begs=(map loc @) (malt (turn real |=(t=token [beg.at.t (kind-of t)])))
3060− =/ ends=(map loc @) (malt (turn real |=(t=token [end.at.t (kind-of t)])))
3061− %^ check-kids [begs ends] ~
3062 (weld (turn imports.mod outline-import) (turn defs.mod outline-def))
3750 (weld (turn imports.mod outline-import) (turn defs.mod outline-def))
3752+:: +check-outlines: +check-spans over the outlines of a module's nodes
3755+ |= [toks=(list token) os=(list outline)]
3757+ (check-kids (index-tokens toks) ~ os)
3759+:: +index-tokens: each token that isn't a layout token, by its start,
3760+:: and each opener's closer on its line, by their starts
3762+:: A str-head opens an interpolation that a str-mid or str-tail
3763+:: closes, and a str-mid opens the next. Openers still open at the end
3764+:: of a line have no closer.
3767+ |= toks=(list token)
3768+ ^- [info=(map loc tinfo) mat=(map loc loc)]
3769+ =| info=(map loc tinfo)
3770+ =| mat=(map loc loc)
3772+ |- ^- [info=(map loc tinfo) mat=(map loc loc)]
3775+ ?: (is-layout t) $(toks t.toks, open ~)
3777+ =/ nex=(unit [beg=loc tight=?])
3778+ ?: |(?=(~ t.toks) (is-layout i.t.toks)) ~
3779+ `[beg.at.i.t.toks tight.i.t.toks]
3780+ =. info (~(put by info) beg.at.t [k end.at.t nex])
3781+ ?: ?=(?(%'(' %'[' %'~[' %'|=(' %'$?(' %'$-(' %str-head) k)
3782+ $(toks t.toks, open [beg.at.t open])
3783+ ?. ?=(?(%')' %']' %str-mid %str-tail) k) $(toks t.toks)
3784+ ?~ open $(toks t.toks)
3787+ mat (~(put by mat) i.open beg.at.t)
3788+ open ?:(?=(%str-mid k) [beg.at.t t.open] t.open)
3064:: +kind-of: a token's kind: a glyph, or its lexeme's tag
3791:: +kind-of: a token's kind: a glyph, or its lexeme's tag
3066++ kind-of
3793++ kind-of
@@ -3071,7 +3798,10 @@
3071:: +check-kids: nodes in source order, inside the span in, each checked
3798:: +check-kids: nodes in source order, inside the span in, each checked
3073++ check-kids
3800++ check-kids
3801+ |= $: idx=[info=(map loc tinfo) mat=(map loc loc)]
3074− |= [maps=[begs=(map loc @) ends=(map loc @)] in=(unit span) os=(list outline)]
3803+ os=(list outline)
3075 ^- (unit tape)
3805 ^- (unit tape)
3076 =| prev=(unit span)
3806 =| prev=(unit span)
3077 |- ^- (unit tape)
3807 |- ^- (unit tape)
@@ -3083,14 +3813,14 @@
3083 `(span-bad o "ends after its parent")
3813 `(span-bad o "ends after its parent")
3084 ?: &(?=(^ prev) (loc-lth beg.at.o end.u.prev))
3814 ?: &(?=(^ prev) (loc-lth beg.at.o end.u.prev))
3085 `(span-bad o "starts before the node before it ends")
3815 `(span-bad o "starts before the node before it ends")
3086− =/ bad=(unit tape) (check-outline maps o)
3816+ =/ bad=(unit tape) (check-outline idx o)
3087 ?^ bad bad
3817 ?^ bad bad
3088 $(prev `at.o, os t.os)
3818 $(prev `at.o, os t.os)
3090:: +check-outline: one node's start and end, then its children
3820:: +check-outline: one node's start and end, then its children
3092++ check-outline
3822++ check-outline
3093− |= [maps=[begs=(map loc @) ends=(map loc @)] o=outline]
3823+ |= [idx=[info=(map loc tinfo) mat=(map loc loc)] o=outline]
3094 ^- (unit tape)
3824 ^- (unit tape)
3095 =* ks kids.o
3825 =* ks kids.o
3096 =/ head=(unit span) ?~(ks ~ `at.i.ks)
3826 =/ head=(unit span) ?~(ks ~ `at.i.ks)
@@ -3102,29 +3832,95 @@
3102 ?~ head `"has no token or child to start with"
3832 ?~ head `"has no token or child to start with"
3103 ?: =(beg.at.o beg.u.head) ~
3833 ?: =(beg.at.o beg.u.head) ~
3104 `"should start where its first child does, at {(show-loc beg.u.head)}"
3834 `"should start where its first child does, at {(show-loc beg.u.head)}"
3105− =/ k=(unit @) (~(get by begs.maps) beg.at.o)
3835+ =/ t=(unit tinfo) (~(get by info.idx) beg.at.o)
3106− ?~ k `"starts where no token does"
3836+ ?~ t `"starts where no token does"
3107− ?. (lien `(list @)`lead.o |=(a=@ =(a u.k)))
3837+ ?. (lien `(list @)`lead.o |=(a=@ =(a kind.u.t)))
3108 `"starts at a token of a kind it can't start with"
3838 `"starts at a token of a kind it can't start with"
3109 ?: &(?=(^ head) !(loc-lth beg.at.o beg.u.head))
3839 ?: &(?=(^ head) !(loc-lth beg.at.o beg.u.head))
3110 `"should start with its own token, before its first child"
3840 `"should start with its own token, before its first child"
3112 ?^ start `(span-bad o u.start)
3842 ?^ start `(span-bad o u.start)
3113− :: the end: its own token, or its last child's
3843+ :: the end: where +stop says
3114− =/ stop=(unit tape)
3844+ =/ want=(unit loc) (stop-of idx o tail)
3115− ?: &(|(?=(~ last.o) open.o) ?=(^ tail) =(end.at.o end.u.tail)) ~
3845+ ?~ want `(span-bad o "has no end that its tokens give")
3116− ?~ last.o
3846+ ?. =(u.want end.at.o)
3117− ?~ tail `"has no token or child to end with"
3118− `"should end where its last child does, at {(show-loc end.u.tail)}"
3847+ `(span-bad o "should end at {(show-loc u.want)}")
3119− =/ k=(unit @) (~(get by ends.maps) end.at.o)
3120− ?~ k `"ends where no token does"
3121− ?. (lien `(list @)`last.o |=(a=@ =(a u.k)))
3122− `"ends at a token of a kind it can't end with"
3123− ?: &(?=(^ tail) !(loc-lth end.u.tail end.at.o))
3124− `"should end with its own token, after its last child"
3126− ?^ stop `(span-bad o u.stop)
3127− (check-kids maps `at.o ks)
3848+ (check-kids idx `at.o ks)
3850+:: +stop-of: where a node should end, from its stop, the tokens, and
3851+:: its last child's span, tail
3854+ |= $: idx=[info=(map loc tinfo) mat=(map loc loc)]
3860+ =/ first=(unit tinfo) (~(get by info) beg.at.o)
3861+ :: the token after the one at beg, if it is on the same line
3865+ =/ t=(unit tinfo) (~(get by info) beg)
3869+ :: the end of the token at beg
3873+ =/ t=(unit tinfo) (~(get by info) beg)
3875+ :: the closer of the opener at beg, else the last child
3879+ =/ c=(unit loc) (~(get by mat.idx) beg)
3881+ ?~(tail ~ `end.u.tail)
3882+ :: a path from the token at beg: each tight / and knot after it, and
3883+ :: each tight [ or ( to its closer
3888+ =/ t=(unit tinfo) (~(get by info) beg)
3891+ ?. &(?=(^ n) tight.u.n) `end.u.t
3892+ =/ nk=(unit tinfo) (~(get by info) beg.u.n)
3894+ ?: ?=(?(%'/' %knot) kind.u.nk) $(beg beg.u.n)
3895+ ?. ?=(?(%'[' %'(') kind.u.nk) `end.u.t
3896+ =/ c=(unit loc) (~(get by mat.idx) beg.u.n)
3900+ %kid ?~(tail ~ `end.u.tail)
3901+ %one (end-at beg.at.o)
3902+ %shut (shut beg.at.o)
3903+ %run (run beg.at.o)
3904+ %two =/(n (after beg.at.o) ?~(n ~ (end-at u.n)))
3905+ %shut2 =/(n (after beg.at.o) ?~(n ~ (shut u.n)))
3908+ =/ n (after beg.at.o)
3915+ =/ beg=loc beg.at.o
3917+ =/ c=(unit loc) (~(get by mat.idx) beg)
3919+ =/ t=(unit tinfo) (~(get by info) u.c)
3921+ ?: ?=(%str-tail kind.u.t) `end.u.t
3129:: +span-bad: a span check's error, naming the node by kind and span
3925:: +span-bad: a span check's error, naming the node by kind and span
@@ -3146,75 +3942,75 @@
3146 |= i=import
3942 |= i=import
3147 ^- outline
3943 ^- outline
3149− %sur [%sur at.i ~[%'/-'] ~[%name] | ~]
3945+ %sur [%sur at.i ~[%'/-'] %two ~]
3150− %mark [%mark at.i ~[%'/%'] ~[%lit] | ~]
3946+ %mark [%mark at.i ~[%'/%'] %two ~]
3151− %jibb [%jibb at.i ~[%'/='] ~[%'/' %knot] | ~]
3947+ %jibb [%jibb at.i ~[%'/='] %run3 ~]
3154++ outline-def
3950++ outline-def
3155 |= d=def
3951 |= d=def
3156 ^- outline
3952 ^- outline
3158− %mold [%mold at.d ~[%'+$'] ~ | ~[(outline-shape shape.d)]]
3954+ %mold [%mold at.d ~[%'+$'] %kid ~[(outline-shape shape.d)]]
3159− %value [%value at.d ~[%'++'] ~ | ~[(outline-expr val.d)]]
3955+ %value [%value at.d ~[%'++'] %kid ~[(outline-expr val.d)]]
3162++ outline-expr
3958++ outline-expr
3163 |= e=expr
3959 |= e=expr
3164 ^- outline
3960 ^- outline
3166− %lit [%lit at.e ~[%lit] ~[%lit] | ~]
3962+ %lit [%lit at.e ~[%lit] %one ~]
3167 %str (outline-str at.e pieces.e)
3963 %str (outline-str at.e pieces.e)
3168− %path [%path at.e ~[%'/'] ~[%'/' %knot] | ~]
3964+ %path [%path at.e ~[%'/'] %run ~]
3169− %wing [%wing at.e ~[%name %wing] ~[%name %wing] | ~]
3965+ %wing [%wing at.e ~[%name %wing] %one ~]
3170− %pair [%pair at.e ~[%name] ~ | ~[(outline-expr val.e)]]
3966+ %pair [%pair at.e ~[%name] %kid ~[(outline-expr val.e)]]
3171− %unit [%unit at.e ~[%'`'] ~ | ~[(outline-expr val.e)]]
3967+ %unit [%unit at.e ~[%'`'] %kid ~[(outline-expr val.e)]]
3172− %group [%group at.e ~[%'('] ~[%')'] & ~[(outline-expr inner.e)]]
3968+ %group [%group at.e ~[%'('] %shut ~[(outline-expr inner.e)]]
3173− %list [%list at.e ~[%'~['] ~[%']'] & (turn items.e outline-expr)]
3969+ %list [%list at.e ~[%'~['] %shut (turn items.e outline-expr)]
3174− %tuple [%tuple at.e ~[%'['] ~[%']'] & (turn items.e outline-item)]
3970+ %tuple [%tuple at.e ~[%'['] %shut (turn items.e outline-item)]
3175− %ctor [%ctor at.e ~[%'|='] ~[%lit] | ~]
3971+ %ctor [%ctor at.e ~[%'|='] %two ~]
3176− %crash [%crash at.e ~[%'!!'] ~[%'!!'] | ~]
3972+ %crash [%crash at.e ~[%'!!'] %one ~]
3179 =/ ks=(list outline)
3975 =/ ks=(list outline)
3180 %+ murn segs.e
3976 %+ murn segs.e
3181 |=(s=qseg ?.(?=(%expr -.s) ~ `(outline-expr p.s)))
3977 |=(s=qseg ?.(?=(%expr -.s) ~ `(outline-expr p.s)))
3182− [%qath at.e ~[%'%/'] ~[%'%/' %knot %')'] | ks]
3978+ [%qath at.e ~[%'%/'] %run ks]
3185 =/ ks=(list outline) (turn edits.e outline-edit)
3981 =/ ks=(list outline) (turn edits.e outline-edit)
3186− [%change at.e ~[%name %wing] ~[%')'] & ks]
3982+ [%change at.e ~[%name %wing] %shut2 ks]
3188 %gate-wide
3984 %gate-wide
3189 =/ ks=(list outline)
3985 =/ ks=(list outline)
3190 ~[(outline-sample sample.e) (outline-expr body.e)]
3986 ~[(outline-sample sample.e) (outline-expr body.e)]
3191− [%gate-wide at.e ~[%'|=('] ~[%')'] | ks]
3987+ [%gate-wide at.e ~[%'|=('] %shut ks]
3194− [%call at.e ~ ~ | [(outline-expr head.e) (turn args.e outline-expr)]]
3990+ [%call at.e ~ %kid [(outline-expr head.e) (turn args.e outline-expr)]]
3197 =/ ks=(list outline)
3993 =/ ks=(list outline)
3198 ~[(outline-sample sample.e) (outline-expr body.e)]
3994 ~[(outline-sample sample.e) (outline-expr body.e)]
3199− [%gate at.e ~[%'|='] ~ | ks]
3995+ [%gate at.e ~[%'|='] %kid ks]
3202 =/ ks=(list outline) ~[(outline-shape shape.e) (outline-expr val.e)]
3998 =/ ks=(list outline) ~[(outline-shape shape.e) (outline-expr val.e)]
3203− [%cast at.e ~[%'^-'] ~ | ks]
3999+ [%cast at.e ~[%'^-'] %kid ks]
3206 =/ ks=(list outline) ~[(outline-expr val.e) (outline-expr then.e)]
4002 =/ ks=(list outline) ~[(outline-expr val.e) (outline-expr then.e)]
3207− [%trace at.e ~[%'~&'] ~ | ks]
4003+ [%trace at.e ~[%'~&'] %kid ks]
3210 =/ ks=(list outline)
4006 =/ ks=(list outline)
3211 [(outline-expr subject.e) (turn arms.e outline-arm)]
4007 [(outline-expr subject.e) (turn arms.e outline-arm)]
3212− [%branch at.e ~[%'?-'] ~ | ks]
4008+ [%branch at.e ~[%'?-'] %kid ks]
3215 =/ ks=(list outline)
4011 =/ ks=(list outline)
3216 (snoc (turn defs.e outline-def) (outline-expr final.e))
4012 (snoc (turn defs.e outline-def) (outline-expr final.e))
3217− [%body at.e ~ ~ | ks]
4013+ [%body at.e ~ %kid ks]
3220++ outline-str
4016++ outline-str
@@ -3222,60 +4018,60 @@
3222 ^- outline
4018 ^- outline
3223 =/ ks=(list outline)
4019 =/ ks=(list outline)
3224 (murn ps |=(p=piece ?.(?=(%expr -.p) ~ `(outline-expr p.p))))
4020 (murn ps |=(p=piece ?.(?=(%expr -.p) ~ `(outline-expr p.p))))
3225− ?~ ks [%str at ~[%str] ~[%str] | ~]
4021+ ?~ ks [%str at ~[%str] %one ~]
3226− [%str at ~[%str-head] ~[%str-tail] | ks]
4022+ [%str at ~[%str-head] %string ks]
3228++ outline-item
4024++ outline-item
3229 |= i=item
4025 |= i=item
3230 ^- outline
4026 ^- outline
3231− ?~ face.i [%item at.i ~ ~ | ~[(outline-expr val.i)]]
4027+ ?~ face.i [%item at.i ~ %kid ~[(outline-expr val.i)]]
3232− [%face at.i ~[%name] ~ | ~[(outline-expr val.i)]]
4028+ [%face at.i ~[%name] %kid ~[(outline-expr val.i)]]
3234++ outline-edit
4030++ outline-edit
3235 |= e=edit
4031 |= e=edit
3236 ^- outline
4032 ^- outline
3237− [%edit at.e ~[%name] ~ | ~[(outline-expr val.e)]]
4033+ [%edit at.e ~[%name] %kid ~[(outline-expr val.e)]]
3239++ outline-arm
4035++ outline-arm
3240 |= a=arm
4036 |= a=arm
3241 ^- outline
4037 ^- outline
3242− [%arm at.a ~ ~ | ~[(outline-pattern pat.a) (outline-expr val.a)]]
4038+ [%arm at.a ~ %kid ~[(outline-pattern pat.a) (outline-expr val.a)]]
3244++ outline-sample
4040++ outline-sample
3245 |= s=sample
4041 |= s=sample
3246 ^- outline
4042 ^- outline
3248− %bind [%bind at.s ~[%name] ~[%name] | ~]
4044+ %bind [%bind at.s ~[%name] %one ~]
3249− %face [%face at.s ~[%name] ~ | ~[(outline-shape shape.s)]]
4045+ %face [%face at.s ~[%name] %kid ~[(outline-shape shape.s)]]
3250− %pun [%pun at.s ~[%'='] ~[%name] | ~]
4046+ %pun [%pun at.s ~[%'='] %two ~]
3251− %cell [%cell at.s ~[%'['] ~[%']'] | (turn items.s outline-sample)]
4047+ %cell [%cell at.s ~[%'['] %shut (turn items.s outline-sample)]
3252− %bare [%bare at.s ~ ~ | ~[(outline-shape shape.s)]]
4048+ %bare [%bare at.s ~ %kid ~[(outline-shape shape.s)]]
3255++ outline-pattern
4051++ outline-pattern
3256 |= p=pattern
4052 |= p=pattern
3257 ^- outline
4053 ^- outline
3259− %lit [%lit at.p ~[%lit] ~[%lit] | ~]
4055+ %lit [%lit at.p ~[%lit] %one ~]
3260− %str [%str at.p ~[%str] ~[%str] | ~]
4056+ %str [%str at.p ~[%str] %one ~]
3261− %any [%any at.p ~[%'*'] ~[%'*'] | ~]
4057+ %any [%any at.p ~[%'*'] %one ~]
3262− %bind [%bind at.p ~[%name] ~[%name] | ~]
4058+ %bind [%bind at.p ~[%name] %one ~]
3263− %cell [%cell at.p ~[%'['] ~[%']'] | (turn items.p outline-pattern)]
4059+ %cell [%cell at.p ~[%'['] %shut (turn items.p outline-pattern)]
3266++ outline-shape
4062++ outline-shape
3267 |= s=shape
4063 |= s=shape
3268 ^- outline
4064 ^- outline
3270− %aura [%aura at.s ~[%aura] ~[%aura] | ~]
4066+ %aura [%aura at.s ~[%aura] %one ~]
3271− %noun [%noun at.s ~[%'*'] ~[%'*'] | ~]
4067+ %noun [%noun at.s ~[%'*'] %one ~]
3272− %void [%void at.s ~[%'!!'] ~[%'!!'] | ~]
4068+ %void [%void at.s ~[%'!!'] %one ~]
3273− %flag [%flag at.s ~[%'?'] ~[%'?'] | ~]
4069+ %flag [%flag at.s ~[%'?'] %one ~]
3274− %const [%const at.s ~[%lit] ~[%lit] | ~]
4070+ %const [%const at.s ~[%lit] %one ~]
3275− %ref [%ref at.s ~[%name %wing] ~[%name %wing] | ~]
4071+ %ref [%ref at.s ~[%name %wing] %one ~]
3276− %tvar [%tvar at.s ~[%tvar] ~[%tvar] | ~]
4072+ %tvar [%tvar at.s ~[%tvar] %one ~]
3277− %apply [%apply at.s ~[%'('] ~[%')'] | (turn args.s outline-shape)]
4073+ %apply [%apply at.s ~[%'('] %shut (turn args.s outline-shape)]
3278− %cell [%cell at.s ~[%'['] ~[%']'] | (turn fields.s outline-sample)]
4074+ %cell [%cell at.s ~[%'['] %shut (turn fields.s outline-sample)]
3281 =/ ks=(list outline)
4077 =/ ks=(list outline)
@@ -3283,19 +4079,100 @@
3283 |= g=pseg
4079 |= g=pseg
3284 ^- (unit outline)
4080 ^- (unit outline)
3285 ?. ?=(%typed -.g) ~
4081 ?. ?=(%typed -.g) ~
3286− `[%typed at.g ~[%'['] ~[%']'] | ~]
4082+ `[%typed at.g ~[%'['] %shut ~]
3287− [%path at.s ~[%'/'] ~[%'/' %knot %']'] & ks]
4083+ [%path at.s ~[%'/'] %run ks]
3290 =/ ks=(list outline) (turn cases.s outline-shape)
4086 =/ ks=(list outline) (turn cases.s outline-shape)
3291− [%union at.s ~[%'$?' %'$?('] ~[%')'] & ks]
4087+ [%union at.s ~[%'$?' %'$?('] %shut ks]
3294 =/ ks=(list outline)
4090 =/ ks=(list outline)
3295 ~[(outline-shape sample.s) (outline-shape product.s)]
4091 ~[(outline-shape sample.s) (outline-shape product.s)]
3296− [%fn at.s ~[%'$-('] ~[%')'] | ks]
4092+ [%fn at.s ~[%'$-('] %shut ks]
3298 %generic
4094 %generic
3299− [%generic at.s ~[%'|$'] ~ | ~[(outline-shape body.s)]]
4095+ [%generic at.s ~[%'|$'] %kid ~[(outline-shape body.s)]]
4098+:: +check-spans-test: +check-spans's own test: ~, or what went wrong
4100+:: Each case parses a source, checks that its spans pass, then moves
4101+:: the span of every node of a kind that starts at a place, as a
4102+:: parser bug would, and checks that +check-spans says so. Run it as
4103+:: tools/hoon check-spans-test, which prints <<>> when every case
4108+ =/ cases=(list [src=@t bends=(list [kind=@tas beg=loc at=span])])
4109+ :~ :: a closed bracket ending before its closer, or at its parent's
4110+ :- '++ x [a [b c]]'
4111+ ~[[%tuple [1 9] [1 9] [1 13]] [%item [1 9] [1 9] [1 13]]]
4112+ :- '++ x [a [b c]]'
4113+ ~[[%tuple [1 9] [1 9] [1 15]] [%item [1 9] [1 9] [1 15]]]
4114+ :: a bracket starting at its parent's opener
4115+ :- '++ x [[b c] a]'
4116+ ~[[%tuple [1 7] [1 6] [1 12]] [%item [1 7] [1 6] [1 12]]]
4117+ :: a group without its ), a list at the next line, a call with )
4118+ :- '++ x ~[\0a (f a)\0a++ y 1'
4119+ :~ [%group [2 3] [2 3] [2 7]]
4120+ [%list [1 6] [1 6] [2 7]]
4121+ [%value [1 1] [1 1] [2 7]]
4123+ :- '++ x ~[\0a (f a)\0a++ y 1'
4124+ ~[[%list [1 6] [1 6] [3 1]] [%value [1 1] [1 1] [3 1]]]
4125+ ['++ x ~[\0a (f a)\0a++ y 1' ~[[%call [2 4] [2 4] [2 8]]]]
4126+ :: a literal running on to the next one's end
4127+ ['++ x f 1 2' ~[[%lit [1 8] [1 8] [1 11]]]]
4128+ :: a path, a string, a change and a wide union cut short
4129+ ['++ x f /a/b c' ~[[%path [1 8] [1 8] [1 10]]]]
4130+ ['++ x f "a{b}c" d' ~[[%str [1 8] [1 8] [1 13]]]]
4131+ ['++ x m(a=1) b' ~[[%change [1 6] [1 6] [1 11]]]]
4132+ :- '+$ x $?(%a %b)'
4133+ ~[[%union [1 6] [1 6] [1 14]] [%mold [1 1] [1 1] [1 14]]]
4134+ :: a mold's cell before its closer, a typed segment past its own
4135+ :- '+$ x [a=[@ @] b=@]'
4136+ ~[[%cell [1 9] [1 9] [1 13]] [%face [1 7] [1 7] [1 13]]]
4137+ :- '+$ x [p=/a/[id=@ud]]'
4138+ :~ [%typed [1 12] [1 12] [1 21]]
4139+ [%path [1 9] [1 9] [1 21]]
4140+ [%face [1 7] [1 7] [1 21]]
4142+ :: an import's path cut short
4143+ ['/= c /ui/c' ~[[%jibb [1 1] [1 1] [1 11]]]]
4147+ |= [src=@t bends=(list [kind=@tas beg=loc at=span])]
4149+ =/ name=tape "`{(trip src)}`, {<bends>}"
4150+ =/ toks=(list token) (layout /test/jibb src)
4151+ =/ res (parse-tokens /test/jibb toks)
4152+ ?: ?=(%| -.res) ~["{name}: doesn't parse: {msg.p.res}"]
4153+ =/ os=(list outline)
4154+ %+ weld (turn imports.p.res outline-import)
4155+ (turn defs.p.res outline-def)
4156+ =/ true=(unit tape) (check-outlines toks os)
4157+ ?^ true ~["{name}: its true spans fail: {u.true}"]
4158+ =/ bent=(list outline)
4159+ =/ o=(list outline) os
4160+ |- ^- (list outline)
4162+ $(bends t.bends, o (bend-outlines o kind.i.bends beg.i.bends at.i.bends))
4163+ ?: =(bent os) ~["{name}: no such node"]
4164+ ?^ (check-outlines toks bent) ~
4165+ ~["{name}: not caught"]
4167+:: +bend-outlines: os, with the span of each node of kind kind that
4168+:: starts at beg set to at, as a parser bug could set it
4171+ |= [os=(list outline) kind=@tas beg=loc at=span]
4175+ =? at.o &(=(kind kind.o) =(beg beg.at.o)) at
4176+ :- o(kids $(os kids.o))