on master help sign in
Implement the layout pass
15a5545Claude
jibb-dev/lib/jibb.hoon+1064−174
@@ -7,7 +7,7 @@
7:: ship builds it as /lib/jibb.hoon.
7:: ship builds it as /lib/jibb.hoon.
8::
8::
9:: API
9:: API
10−:: +layout [file=path src=@t] (each (list token) error)
10+:: +layout [file=path src=@t] (list token)
11:: +parse [file=path src=@t] (each module error)
11:: +parse [file=path src=@t] (each module error)
12:: +parse-tokens [file=path toks=(list token)] (each module error)
12:: +parse-tokens [file=path toks=(list token)] (each module error)
13:: +golden [file=path src=@t] [tokens=@t tree=@t]
13:: +golden [file=path src=@t] [tokens=@t tree=@t]
@@ -15,13 +15,18 @@
15:: +show-module module @t
15:: +show-module module @t
16:: +show-error [src=@t error] @t
16:: +show-error [src=@t error] @t
17:: A file is a Clay path whose last segment is the extension, as the
17:: A file is a Clay path whose last segment is the extension, as the
18−:: golden runners pass /tests/golden/<case>/source/jibb.
18+:: golden runners pass /tests/golden/<case>/source/jibb. +layout never
19+:: fails: an error it finds is its last token (2.0), and +layout-error
20+:: takes it out.
19−::
21+::
20−:: Status: the types, the printers and +golden work. +layout and
22+:: Status: the types, the printers, +golden and the layout pass
21−:: +parse-tokens are stubs that return an error; they are implemented
23+:: (+layout, +lexer) work. +parse-tokens is a stub that returns an
22−:: next, against the design below. Choices the doc leaves open are marked
24+:: error; it is implemented next, against the design below. Choices the
23−:: "(doc question)": they follow the most likely reading and are listed,
25+:: doc leaves open are marked "(doc question)": they follow the most
24−:: with the doc's words, for the doc's author to settle.
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
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).
25::
30::
26:: ===================================================================
31:: ===================================================================
27:: 1. Positions
32:: 1. Positions
@@ -38,9 +43,15 @@
38:: has beg = end). Nodes keep their ends because the checker's errors in
43:: has beg = end). Nodes keep their ends because the checker's errors in
39:: milestone 2 name both conflicting sites with excerpts, and an excerpt
44:: milestone 2 name both conflicting sites with excerpts, and an excerpt
40:: that underlines a whole expression, as Elm and Rust do, needs its end;
45:: that underlines a whole expression, as Elm and Rust do, needs its end;
41−:: so does editor tooling later. Ends cost the parser nothing: a node ends
46+:: so does editor tooling later. A node starts at its first token and
42−:: where its last child or closing token ends. The printed tree shows
47+:: ends where its last token ends: its closing token if it has one, else
48+:: its last child's last token, never a layout token. So an open
49+:: bracket, a body, ?-'s arms and $?'s cases end with their last line's
50+:: code, not at the line that closes them. Every node's span holds its
51+:: children's spans, in source order. The printed tree shows starts
43−:: starts only, and milestone 1's errors use starts only.
52+:: only, and milestone 1's errors use starts only, so ends are first
53+:: tested by milestone 2's excerpts; the parser's own tests should check
54+:: the two rules above on every golden tree.
44::
55::
45:: ===================================================================
56:: ===================================================================
46:: 2. The layout pass (+layout)
57:: 2. The layout pass (+layout)
@@ -49,16 +60,30 @@
49:: +layout turns the text into tokens one line at a time: no token
60:: +layout turns the text into tokens one line at a time: no token
50:: crosses a line break, and only layout tokens join lines.
61:: crosses a line break, and only layout tokens join lines.
51::
62::
63+:: 2.0 Errors. +layout never fails. Where the text breaks a rule of this
64+:: section, it emits one error token, [%error msg], at the first
65+:: character that breaks it, and stops reading. The parser accepts no
66+:: error token, so it reports whichever comes first, its own error or
67+:: this one (section 3, Errors). Every error, from either stage, points
68+:: at the first character where the text stops being the start of any
69+:: valid module: everything before it could still be right. Hoon's
70+:: parser reports errors the same way, and the golden corpus's expect
71+:: lines assume it. It also puts `++ x ]` on line 1 before a bad string
72+:: on line 9, which a lexer that failed first would report instead. The
73+:: positions below follow from it. Messages quote code in backticks, as
74+:: the parser's do (section 3, Errors).
75+::
52:: 2.1 Lines. The text is split at every \0a. A final \0a ends the last
76:: 2.1 Lines. The text is split at every \0a. A final \0a ends the last
53:: line rather than starting an empty one. Lines are numbered from 1.
77:: line rather than starting an empty one. Lines are numbered from 1.
54::
78::
55:: 2.2 Characters. Anywhere in the text, strings and comments included,
79:: 2.2 Characters. Anywhere in the text, strings and comments included,
56−:: these are errors: tab (9), carriage return (13), every other byte
80+:: these are errors at the character: tab (9), "a tab: Jibb uses spaces
81+:: only"; carriage return (13), "a carriage return: Jibb lines end with
57−:: below 32 except \0a, and 127. Jibb, like Hoon, spaces with spaces
82+:: a line feed alone"; every other byte below 32 except \0a, and 127, "a
58−:: only ("tab: Jibb uses spaces only"). Bytes from 128 up (UTF-8) are
83+:: control character". Bytes from 128 up (UTF-8) are allowed only inside
59−:: allowed only inside strings and comments ("non-ASCII text outside a
84+:: strings and comments ("non-ASCII text outside a string or comment").
60−:: string or comment"). Outside strings and comments, see 2.6 for which
85+:: Outside strings and comments, see 2.6 for which printable characters
61−:: printable characters start a token.
86+:: start a token.
62::
87::
63:: 2.3 Blank and comment-only lines. A line of spaces only, or whose first
88:: 2.3 Blank and comment-only lines. A line of spaces only, or whose first
64:: non-space characters are ::, emits nothing and changes no level. Its
89:: non-space characters are ::, emits nothing and changes no level. Its
@@ -66,27 +91,31 @@
66::
91::
67:: 2.4 Levels. The stack holds the columns of the open levels, innermost
92:: 2.4 Levels. The stack holds the columns of the open levels, innermost
68:: first, and starts as ~[1]. For every other line let c be the column of
93:: first, and starts as ~[1]. For every other line let c be the column of
69−:: its first non-space character; then:
94+:: its first non-space character. The first such line emits no layout
70−:: - The first such line needs c = 1, else the error "the first line is
95+:: token and needs c = 1, else the error "the first line is indented:
71−:: indented: top-level lines start at column 1".
96+:: top-level lines start at column 1". Each later one emits:
72:: - c > top: push c, emit INDENT.
97:: - c > top: push c, emit INDENT.
73:: - c = top: emit NEWLINE.
98:: - c = top: emit NEWLINE.
74:: - c < top: while c < top, pop and emit DEDENT. Then c must equal the
99:: - c < top: while c < top, pop and emit DEDENT. Then c must equal the
75:: new top, else the error "this line's indentation matches no
100:: new top, else the error "this line's indentation matches no
76−:: enclosing line: indent it to column 1 or 5" (the stack's columns,
101+:: enclosing line: indent it to column 1, 5 or 7" (the stack's
77−:: outermost first); emit NEWLINE.
102+:: columns before the pops, outermost first); emit NEWLINE.
103+:: Then the line's tokens (2.6). These errors, and a bad character (2.2)
104+:: at column c, sit at column c and come before the line's layout
78−:: Then the line's tokens (2.6). A layout token's span runs from just past
105+:: tokens. A layout token's span runs from just past the previous token,
79−:: the previous token, on an earlier line, to column c of this line:
106+:: on an earlier line, to column c of this line. Errors and the token
80−:: its start is where the previous line's code ended, where "found the
107+:: printer place a layout token at its span's end, the start of the line
81−:: end of the line" errors point, and its end is where the new line
108+:: it begins (+where): the line's column is what made it INDENT, NEWLINE
82−:: starts, where "found a deeper line" errors point (see +where).
109+:: or DEDENT, and until that line, a deeper one could still have come.
83−::
110+::
84−:: 2.5 End of file. If any token was emitted: pop every level above 1,
111+:: 2.5 End of file. If any token was emitted and no error token: pop
85−:: emitting DEDENT for each, then emit one NEWLINE, all with empty spans
112+:: every level above 1, emitting DEDENT for each, then emit one NEWLINE,
113+:: all with empty spans just past the last token. They are the only
114+:: layout tokens with empty spans, which is how errors name "the end of
86−:: just past the last token. So every import and definition, the last
115+:: the file". So every import and definition, the last one included, is
87−:: one included, is followed by NEWLINE, as `module = { import NEWLINE }
116+:: followed by NEWLINE, as `module = { import NEWLINE } { definition
88−:: { definition NEWLINE }` needs. A file without tokens (empty, or only
117+:: NEWLINE }` needs. A file without tokens (empty, or only blank and
89−:: blank and comment lines) gives no tokens: an empty module.
118+:: comment lines) gives no tokens: an empty module.
90::
119::
91:: The layout pass knows nothing of brackets: it emits INDENT, NEWLINE and
120:: The layout pass knows nothing of brackets: it emits INDENT, NEWLINE and
92:: DEDENT by column alone. The parser decides what takes an indented
121:: DEDENT by column alone. The parser decides what takes an indented
@@ -95,60 +124,102 @@
95:: closed on one line is just tokens.
124:: closed on one line is just tokens.
96::
125::
97:: 2.6 Tokens. After the indentation, tokens are read left to right;
126:: 2.6 Tokens. After the indentation, tokens are read left to right;
98−:: spaces separate them and are dropped. A token is tight when it
127+:: spaces separate them and are dropped, spaces at the end of a line too.
99−:: follows the previous token on the same line with no space between;
128+:: A token is tight when it follows the previous token on the same line
100−:: the first token of a line never is. Tightness is how the parser tells
129+:: with no space between; the first token of a line never is. Tightness
101−:: the tight forms apart: m( from m (, a+b from a + b, `x from ` x,
130+:: is how the parser tells the tight forms apart: m( from m (, a+b from
102−:: |=%got from |= %got, name=value from name = value. What a token is
131+:: a + b, `x from ` x, |=%got from |= %got, name=value from name = value.
103−:: depends on its first characters:
132+:: What a token is depends on its first characters. An error "at 2nd" is
133+:: at the token's second character, the first that no Jibb token allows
134+:: after its first:
104::
135::
105:: :: a comment: the rest of the line is skipped
136:: :: a comment: the rest of the line is skipped
106:: ( ) [ ] ` = * glyphs
137:: ( ) [ ] ` = * glyphs
107:: ~[ ~& glyphs
138:: ~[ ~& glyphs
108−:: ~ a ~ literal: ~ and the run of [a-z0-9._~-] after it;
139+:: ~ a ~ literal: ~ and the run of [a-z0-9._~-] after it,
109−:: a bare ~ is null (2.8)
140+:: read as 2.8 says; a bare ~ is null, [%null %n 0]
110:: %/ glyph, then a path segment may follow (2.7)
141:: %/ glyph, then a path segment may follow (2.7)
111−:: %.y %.n loobean literals, [%f 0] and [%f 1]
142+:: %.y %.n loobean literals, [%f 0] and [%f 1]; %. then anything
143+:: else is an error at 3rd, "the loobeans are `%.y` and
144+:: `%.n`"
112:: %& %| term literals, [%f 0] and [%f 1]
145:: %& %| term literals, [%f 0] and [%f 1]
113−:: %a... term literal: % and a name [a-z][a-z0-9-]*, [%tas name]
146+:: %a... term literal: % and a name [a-z][a-z0-9-]*, [%tas name];
147+:: a capital or _ right after it is an error there,
148+:: "names are lowercase letters, digits and -"
114:: %0... term literal: % and digits [0-9]+, [%ud value]
149:: %0... term literal: % and digits [0-9]+, [%ud value]
115:: (doc question: digits only, as the EBNF says, so
150:: (doc question: digits only, as the EBNF says, so
116−:: %1000 is a term and %1.000 an error, unlike Hoon)
151+:: %1000 is a term and %1.000 an error at the dot); a
117−:: /- /% /= import glyphs, when followed by a space or the end
152+:: letter, _, - or . right after it is an error there,
118−:: of the line
153+:: "unexpected `a`: a numeric term is `%` and digits
154+:: only, as %1000"
155+:: % anything else after it: error at 2nd, "`%` begins a
156+:: term, a loobean or `%/`"
157+:: /- /% /= import glyphs at column 1, where imports go; anywhere
158+:: else / is a path's, so ++ x /- is the path whose
159+:: one segment is -, as the EBNF's knot allows
119:: / glyph, then a path segment may follow (2.7)
160:: / glyph, then a path segment may follow (2.7)
120:: ++ +$ + glyphs
161:: ++ +$ + glyphs
121:: |=( |= |$ glyphs
162:: |=( |= |$ glyphs
122−:: $?( $? $-( glyphs; $- without ( is the error "$- has only the
163+:: $?( $? $-( glyphs; $- followed by anything but ( is an error
123−:: wide form $-(sample product)"
164+:: at 3rd, "`$-` has only the wide form `$-(sample
165+:: product)`"
124:: ^- ?- !! ? glyphs (? alone is the loobean mold)
166:: ^- ?- !! ? glyphs (? alone is the loobean mold)
125:: @ aura: @, then [a-z]*, then at most one [A-Z]; the
167:: @ aura: @, then [a-z]*, then at most one [A-Z]; the
126−:: token holds the text after @. Auras starting @s or @r
168+:: token holds the text after @. An aura starting @s or
127−:: are errors: "signed and floating-point auras are left
169+:: @r is an error at 2nd: "signed and floating-point
128−:: out of Jibb"
170+:: auras are left out of Jibb"
129−:: A-Z type variable: one capital; a letter or digit right
171+:: A-Z type variable: one capital. A letter or digit right
130−:: after it is the error "a type variable is one capital
172+:: after it is an error there, "a type variable is one
131−:: letter"
173+:: capital letter", after the type variable's token
132:: a-z name [a-z][a-z0-9-]*, or a wing: two or more names
174:: a-z name [a-z][a-z0-9-]*, or a wing: two or more names
133−:: joined by dots. A . must be followed by [a-z] ("a . in
175+:: joined by dots. Right after the name or wing, which
134−:: a wing is followed by a name"); a capital or _ right
176+:: is emitted first, a capital or _ is an error there,
135−:: after a name is the error "names are lowercase letters,
177+:: "names are lowercase letters, digits and -", and so
136−:: digits and -"
178+:: is a . not followed by [a-z], at the character after
179+:: the dot, "a `.` in a wing is followed by a name"
137:: 0-9 number literal: the run of [0-9a-zA-Z.] (2.8)
180:: 0-9 number literal: the run of [0-9a-zA-Z.] (2.8)
138:: " string (2.9)
181:: " string (2.9)
139:: } ends the innermost interpolation (2.9), else an error
182:: } ends the innermost interpolation (2.9), else an error
183+:: at it, "this `}` closes no `{`"
184+:: | $ ^ followed by nothing above or in the table below:
185+:: an error at 2nd, "`|` begins `|=`, `|=(` or `|$`",
186+:: "`$` begins `$?`, `$?(` or `$-(`", "`^` begins `^-`"
187+:: : followed by anything but :, an error at 2nd: the
188+:: table's :~ :* and a:b, else "a comment starts with
189+:: `::`"
140−:: anything else an error naming the character: "unexpected `,`"
190+:: anything else an error at it, naming it: "unexpected `,`", with a
191+:: hint where one helps (+unexpected): for , . - and <,
192+:: what Jibb writes instead
141−::
193+::
142−:: Hoon runes the doc leaves out are errors with the doc's reason, found
194+:: Hoon forms the doc leaves out are errors with the doc's reason, as
195+:: "`|%` is left out: modules are records". Each points where the text
196+:: stops being Jibb: at its second character when its first can begin
197+:: Jibb there, else at its first.
198+::
143−:: where the token would start: |% |_ |* "modules are records"; $% "$?
199+:: |% |_ |* 2nd modules are records
200+:: |- 2nd gates recurse by name
201+:: $( 1st gates recurse by name; no expression starts $
144−:: covers unions"; ?+ ?: "?- is the branch"; .= ?! and !x "eq and not
202+:: $% 2nd $? covers unions
145−:: are gates"; =/ "++ defines values"; |- $( "gates recurse by name"; ~|
203+:: ?+ ?: 2nd ?- is the branch (?:: is ? and a comment)
146−:: "~& covers debugging"; => =< .* and a:b "names never shadow, and .
204+:: ?! 2nd eq and not are gates
205+:: .= 1st eq and not are gates
206+:: !x 2nd not is a gate: ! then anything but ! or >
147−:: reads imports too"; !> /+ "code also runs in the browser"; ; "layout
207+:: !> /+ 2nd code also runs in the browser
208+:: =< => .* 1st names never shadow, and . reads imports too
209+:: a:b 2nd of the :, right after a name: names never
210+:: shadow, and . reads imports too; write a.b
211+:: :~ :* 2nd indentation covers them; write ~[…] or […]
212+:: %: %= 2nd indentation covers them
148−:: is Jibb's elements"; :~ :* %: %= == -- "indentation covers them"; '
213+:: == -- 1st the closers are left out: indentation covers
214+:: them
215+:: ~| 2nd ~& covers debugging
216+:: ; 1st Sail's ; runes are left out: layout is Jibb's
217+:: elements
149−:: "there is no '...' form: strings are \"...\"". Wide forms the doc
218+:: ' 1st there is no '…' form: strings are "…"
150−:: leaves out, ^-(...) and ?-(...), lex fine and fail in the parser: a
219+::
151−:: rune is followed by a space.
220+:: The parser finds the doc's other left-out forms (section 3, Errors):
221+:: =(a b), =/, *mold, ^-(…) and ?-(…). The lexer can't, since =( =/ and *
222+:: begin valid Jibb too: open=(not open.s), scry=/todos, a * mold.
152::
223::
153:: 2.7 Paths. Right after a / or %/ glyph, a run of knot characters
224:: 2.7 Paths. Right after a / or %/ glyph, a run of knot characters
154:: [a-z0-9._~-] is one knot token, tight. So /posts/~zod is / knot / knot;
225:: [a-z0-9._~-] is one knot token, tight. So /posts/~zod is / knot / knot;
@@ -158,50 +229,85 @@
158:: lexer tracks: segments such as logo.png, 1 or ~zod would otherwise lex
229:: lexer tracks: segments such as logo.png, 1 or ~zod would otherwise lex
159:: as a wing, a number or a ship. A / followed by anything else is just a
230:: as a wing, a number or a ship. A / followed by anything else is just a
160:: glyph: / alone is the empty path, and the parser rejects empty
231:: glyph: / alone is the empty path, and the parser rejects empty
161−:: segments such as //.
232+:: segments such as //. After the glyph and its knot, if any, comes a /,
233+:: ( or [, a closer ) ] or }, a : (of a comment) or a space: any other
234+:: printable character is an error there, "unexpected `P`: a path
235+:: segment holds lowercase letters, digits and - . ~ _", which for ?
236+:: and # also says a path carries no query or fragment. No Jibb token
237+:: goes on a path that way, so /Posts and %/blog?page=2 fail at the P
238+:: and the ?. A ~. knot literal (2.8) gets the same check, "a knot
239+:: holds lowercase letters, digits and - . ~ _".
162−::
240+::
163−:: 2.8 Literals. The lexer takes the literal's characters first, then
241+:: 2.8 Literals. The lexer takes a literal's run (2.6), then reads it
164−:: reads them with Hoon's own parser, which must consume all of them:
242+:: with Hoon's own parser, (nuck:so [[line col] run]), whose edge says
165−:: 0-9 run (rush run nuck:so) must give [%$ %ud|%ux|%uv val]: 1.000,
243+:: how much it read and how far it looked (p.edge):
166−:: 0x1f, 0v5.fdf99. So 1000 is an error, as in Hoon (groups
244+:: - It read the whole run, as an aura Jibb takes: the token. Numbers
167−:: of three), and 0b1, 0w1, 0i1, 0c1 are errors. Hoon reads
245+:: take %ud, %ux and %uv: 1.000, 0x1f, 0v5.fdf99 (Hoon reads 0x1F
168−:: 0x1F too.
169−:: ~ run a bare ~ is null, [%n 0]. Otherwise (rush run nuck:so) must
170−:: give [%$ %p|%da|%dr|%ta val]: ~zod, ~sampel-palnet,
246+:: too). ~ runs take %p, %da, %dr and %ta: ~zod, ~sampel-palnet,
171−:: ~2026.10.23..14.30.00, ~h1.m30, ~.my-post. ~~a, ~-a and
247+:: ~2026.10.23..14.30.00, ~h1.m30, ~.my-post.
172−:: ~0v... are errors.
248+:: - It read the run or part of it as an aura Jibb doesn't take: 0w1,
173−:: terms and loobeans as in 2.6.
249+:: 0i1, ~~a (a cord), ~-a (a @c). An error at 2nd, "Jibb writes no
250+:: @uw literals". A run starting 0b, 0c, 0i or 0w gets that error
251+:: before nuck:so reads it, since no Jibb literal goes on that way:
252+:: Hoon's parser would read 0b, or a 0c1 whose checksum fails, as
253+:: the number 0 and an error past the run.
254+:: - It read only part of the run, as an aura Jibb takes: that part is
255+:: a token, then an error token at p.edge, the furthest character
256+:: Hoon's parser looked at, where Hoon reports it too. 1000 is the
257+:: token 100 and an error at its fourth digit ("a decimal is digits
258+:: in groups of three joined by dots, as 1.000": each kind of literal
259+:: has its message, +literal-msg); 0v5.fdfz9 is 0v5 and an error at the
260+:: z; ~2026.10.29..14.30 is ~2026.10.29 and an error just past the
261+:: run. The token lets the parser report an earlier error first: in
262+:: `++ 2nd 5` it finds the number 2 where a name goes, at 1:4.
263+:: When it read a ship, or only the ~ of a run that goes on with a
264+:: letter, the error goes instead at the first letter that no
265+:: syllable continues (+ship-stop), or just past a duration's unit,
266+:: d h m or s, if that is later: Hoon's parser reads a syllable's
267+:: three letters before it looks them up, so it looks past that
268+:: letter. `++ x ~x` fails at the x, 1:7, as no syllable starts with
269+:: x, and ~sampel-palnez at the z.
270+:: A run that starts as a date BC does, ~ and a year then -, fails at the
271+:: - if the year is 0 or past 292.277.024.401, before nuck:so sees it:
272+:: Hoon's +year crashes on those years, as in ~0-.1.1 (+year-bc).
174:: The token is [%lit [form aura val]]: form names the literal rule that
273:: The token is [%lit [form aura val]]: form names the literal rule that
175−:: matched, aura and val are the dime Hoon's parser gives.
274+:: matched, aura and val are the dime Hoon's parser gives. Terms,
275+:: loobeans and the bare ~ are read by hand (2.6).
176::
276::
177:: 2.9 Strings. A " starts a string, which ends on the same line. Up to
277:: 2.9 Strings. A " starts a string, which ends on the same line. Up to
178:: the closing ":
278:: the closing ":
179:: \\ \" \{ and \ with two lowercase hex digits are escapes, as in
279:: \\ \" \{ and \ with two lowercase hex digits are escapes, as in
180−:: Hoon's tapes (doc question: the doc names only \{ and \"); any
280+:: Hoon's tapes (doc question: the doc names only \{ and \"). Any
181−:: other \ is an error at the \
281+:: other \ is an error at the first character that can't continue
282+:: the escape: the one after the \, or a bad second hex digit (2.2's
283+:: error if it is a tab or another control character)
182−:: { starts an interpolation: the text so far is emitted as str-head
284+:: { starts an interpolation. The text so far is emitted as str-head,
285+:: spanning from the opening " to just past the {, or as str-mid,
183−:: (at the opening ") or str-mid (at the } that ended the previous
286+:: from the } that ended the previous interpolation to just past the
184−:: interpolation); then tokens are lexed as usual, strings included,
287+:: {. Then tokens are lexed as usual, strings included, up to the }
185−:: up to the } that ends this interpolation, where the string resumes
288+:: that ends this interpolation, where the string resumes
186−:: the closing " emits str when there was no interpolation (at the
289+:: the closing " emits str when there was no interpolation, spanning
187−:: opening ") or str-tail (at the last })
290+:: the whole string, or str-tail, from the last } to just past the "
291+:: any other character is text, } included, as in Hoon
188:: So "Since {day}!" is str-head "Since ", name day, str-tail "!", and the
292:: So "Since {day}!" is str-head "Since ", name day, str-tail "!", and the
189:: parser reads head expr { mid expr } tail. The lexer keeps a stack of
293:: parser reads head expr { mid expr } tail. The lexer keeps a stack of
190:: open interpolations, since strings nest inside them. Inside an
294:: open interpolations, since strings nest inside them. Inside an
191−:: interpolation, :: is the error "a comment can't start inside {...}"
295+:: interpolation a : is an error at it, "a comment can't start inside
192−:: and { is an error; inside a string, :: is text. The end of the line
296+:: `{…}`", and so is a {; inside a string, :: is text. A line that ends
193−:: inside a string or an interpolation is an error at its " ("this
297+:: inside a string or an interpolation is an error at its end, "this
194−:: string has no closing \" on its line") or { ("this { has no }").
298+:: string has no closing `\"` on its line" or "this `{` has no `}` on its
195−:: Token texts hold the decoded text. Spaces after { and before } are
299+:: line". Token texts hold the decoded text. Spaces after { and before }
196−:: allowed, as after any opener.
300+:: are allowed, as after any opener.
197::
301::
198:: 2.10 What fails here. Bad characters (2.2), an indented first line and
302:: 2.10 What fails here. Bad characters (2.2), an indented first line and
199:: a dedent to no open level (2.4), characters that start no token or a
303:: a dedent to no open level (2.4), characters that start no token or a
200−:: left-out rune (2.6), malformed literals, auras, type variables and
304+:: left-out form (2.6), malformed literals, auras, type variables and
305+:: wings (2.6, 2.8), a character that no token lets follow a path
306+:: segment, a ~. knot or a numeric term (2.6, 2.7), and unclosed strings
201−:: wings (2.6, 2.8), and unclosed strings and interpolations, bad escapes
307+:: and interpolations, bad escapes and stray { or } (2.9). Everything
202−:: and stray { or } (2.9). Everything else is the parser's: brackets that
308+:: else is the parser's: brackets that don't match or don't close, a
203−:: don't match or don't close, a missing or extra space, a deeper line
309+:: missing or extra space, a deeper line that nothing takes, a token
204−:: that nothing takes, a token where it can't go.
310+:: where it can't go.
205::
311::
206:: ===================================================================
312:: ===================================================================
207:: 3. The parser (+parse-tokens)
313:: 3. The parser (+parse-tokens)
@@ -221,7 +327,8 @@
221:: name, then = tight a face (items, lines, fields, samples)
327:: name, then = tight a face (items, lines, fields, samples)
222:: name, then + tight a pair
328:: name, then + tight a pair
223:: name or wing, then ( tight a change
329:: name or wing, then ( tight a change
224−:: |=, then a term tight a constructor; else the tall gate
330+:: |=, then a term tight a constructor; else, where an
331+:: expression starts, the tall gate
225:: ++ or +$ a definition; else a body's final expr
332:: ++ or +$ a definition; else a body's final expr
226:: INDENT a body, an open bracket's lines, arms
333:: INDENT a body, an open bracket's lines, arms
227:: or cases; else the expression goes on
334:: or cases; else the expression goes on
@@ -231,11 +338,18 @@
231:: their failures carry a position but no expectation; over tokens they
338:: their failures carry a position but no expectation; over tokens they
232:: would need a token "tape" and an expectation set bolted on. Recursive
339:: would need a token "tape" and an expectation set bolted on. Recursive
233:: descent is shorter, and each error names what its construct expected.
340:: descent is shorter, and each error names what its construct expected.
341+:: An operand that isn't where an expression starts (a call's argument,
342+:: an item, a pair's or unit's operand, the wide gate's body) can't be a
343+:: rune, so there |= is a constructor and needs its term at once:
344+:: (state.cart |= %got) is an error at the space after |=, 1:20. Loops
345+:: over many items (definitions, arms, lines, items) may recurse: vere's
346+:: stack takes ten million plain frames, so no Jibb file nests or runs
347+:: long enough to overflow it.
234::
348::
235:: The EBNF and its nodes (see the types below):
349:: The EBNF and its nodes (see the types below):
236:: module { import NEWLINE } { definition NEWLINE }, then the end
350:: module { import NEWLINE } { definition NEWLINE }, then the end
237:: of the tokens; an import after a definition is the error
351:: of the tokens; an import after a definition is the error
238−:: "imports come first"
352+:: "expected a definition, found `/-`; imports come first"
239:: import /- name -> %sur; /% term -> %mark; /= name pathlit ->
353:: import /- name -> %sur; /% term -> %mark; /= name pathlit ->
240:: %jibb. /% takes % and a name only: no mark is called %0,
354:: %jibb. /% takes % and a name only: no mark is called %0,
241:: %& or %| (doc question)
355:: %& or %| (doc question)
@@ -252,15 +366,19 @@
252:: group ( expr ) -> %group of the expr. The open form ( {operand}
366:: group ( expr ) -> %group of the expr. The open form ( {operand}
253:: open -> %group of the call whose elements are the first
367:: open -> %group of the call whose elements are the first
254:: line's operands, then one per line; one element alone is
368:: line's operands, then one per line; one element alone is
369+:: just grouped. A ( followed by a rune is the closed form.
255−:: just grouped. Lines of an open group or list take no
370+:: Lines of an open group or list take no name= (doc
256−:: name= (doc question)
371+:: question)
257:: change every item and line has name= (the EBNF's "items named")
372:: change every item and line has name= (the EBNF's "items named")
258:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch;
373:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch;
259−:: !! -> %crash. A bare name as the whole sample binds, in
260−:: |=(…) and in the tall |= alike; inside a cell sample a
261−:: bare name is a mold, as field says (doc question). !!
262−:: is not an operand, so [a !!] needs [a (!!)] (doc
374+:: !! -> %crash. !! is not an operand, so [a !!] needs
263−:: question)
375+:: [a (!!)] (doc question)
376+:: sample the sample of |= and |=(…): a field, except that a bare
377+:: name binds (%bind) wherever it stands in the sample: the
378+:: whole sample, as |= x and |=(p title.p), or a field of a
379+:: cell sample at any depth, as b in |= [a=@ b], which is
380+:: a %cell of samples (doc question). A name inside a mold,
381+:: as a in (list a), $-(a b) or $?(a b), is a mold
264:: mold aura -> %aura; * -> %noun; !! -> %void; ? -> %flag;
382:: mold aura -> %aura; * -> %noun; !! -> %void; ? -> %flag;
265:: ~ term loobean -> %const; ref -> %ref; typevar -> %tvar;
383:: ~ term loobean -> %const; ref -> %ref; typevar -> %tvar;
266:: pathmold -> %path; ( ref mold … ) -> %apply; [ field … ]
384:: pathmold -> %path; ( ref mold … ) -> %apply; [ field … ]
@@ -280,7 +398,7 @@
280:: expr } str-tail, where each expr is a full expression.
398:: expr } str-tail, where each expr is a full expression.
281:: - Spaces, comments and blank lines: the layout pass, and Spacing
399:: - Spaces, comments and blank lines: the layout pass, and Spacing
282:: below.
400:: below.
283−:: - pathlit as an operand (above).
401+:: - pathlit as an operand (above), with / alone the empty path.
284:: - knot may be empty: only / alone uses that, as the empty path; //
402:: - knot may be empty: only / alone uses that, as the empty path; //
285:: and a trailing / are errors (doc question).
403:: and a trailing / are errors (doc question).
286:: - Open brackets in molds: mold has no open form, so a mold's [ or (
404:: - Open brackets in molds: mold has no open form, so a mold's [ or (
@@ -292,36 +410,67 @@
292:: ^-, ~& and arms), the Runes prose says "inside a gate"; the parser
410:: ^-, ~& and arms), the Runes prose says "inside a gate"; the parser
293:: takes them in every body and leaves the rest to the checker (doc
411:: takes them in every body and leaves the rest to the checker (doc
294:: question).
412:: question).
413+:: - Where errors point: the doc says only "line, column and an
414+:: excerpt"; 2.0 and Errors below say where.
295::
415::
296:: Spacing. Two tokens on one line are separated by spaces, except:
416:: Spacing. Two tokens on one line are separated by spaces, except:
297:: - tight, always: name+operand (pair), `operand (unit), |=term
417:: - tight, always: name+operand (pair), `operand (unit), |=term
298:: (constructor), wing( (change), name= and = value (faces, in items,
418:: (constructor), wing( (change), name= and = value (faces, in items,
299−:: lines, fields and samples), =name (pun), and every token of a path
419+:: lines, fields and samples), =name (pun); in a path or application
300−:: or application path after its first / or %/, typed segments
420+:: path, each / and the segment after it, and all of a typed segment,
301−:: ([id=@ud]) included
421+:: [id=@ud]
302:: - either way: right after an opener ( [ ~[ |=( $?( $-( or {, and
422:: - either way: right after an opener ( [ ~[ |=( $?( $-( or {, and
303−:: right before a closer ) ] or } (the theme example writes `[ space=`)
423+:: right before a closer ) ] or } (the theme example writes `[ space=`),
424+:: the ( and ) of an application path's segment included; inside
425+:: them the expression is spaced as anywhere else, as %/x/(f a)
304−:: A missing space is an error ("expected a space between items, found
426+:: A missing space is an error at the tight token, and so is a space
305−:: `[`"), and so is a space inside a tight form ("a pair has no spaces,
306−:: as in gap+%s2"). A rune with children, and an import glyph, is
427+:: inside a tight form, at the space (Errors). A rune with children, and
307−:: followed by a space (or, for $? with its cases below, the end of the
428+:: an import glyph, is followed by a space (or, for $? with its cases
429+:: below, the end of the line). Items are separated by one or more
308−:: line). This is how the parser makes "one space between items; more for
430+:: spaces; how many isn't checked. This is how the parser makes "one
309−:: alignment" precise (doc question).
431+:: space between items; more for alignment" precise (doc question).
310−::
432+::
433+:: Errors. The parser stops at the first token it can't accept and
311−:: Errors. "expected <what>, found <token>", with an optional "; <hint>",
434+:: reports "expected <what>, found <token>", with an optional "; <hint>",
312:: lowercase, no final period. <what> uses the doc's words: "an
435:: lowercase, no final period. <what> uses the doc's words: "an
313−:: expression", "a mold", "a pattern", "a name", "`]`", "the end of the
436+:: expression", "a mold", "a pattern", "a name", "`]`", "a space between
314−:: line". <token> is +show-found: the token's text in backticks, "a
437+:: items". <token> is +show-found: the token's text in backticks, "a
315−:: string", "a deeper line" for INDENT, "the end of the line" for NEWLINE
438+:: string", and for layout tokens "a deeper line" (INDENT), "a line at
316−:: and DEDENT. The error sits where +where says: at the token's start, but
439+:: the same depth" (NEWLINE), "a shallower line" (DEDENT), or "the end of
317−:: at the end of the previous line's code for NEWLINE and DEDENT, and at
440+:: the file" (an empty span, 2.5). Each error points at the first
318−:: the start of the deeper line for INDENT. Examples:
441+:: character that can't begin a valid module (2.0):
319−:: expected `]` to close the `[` at 3:5, found the end of the line
442+:: - At the token's start; for a layout token, at the start of the
443+:: line it begins, or just past the last token at the end of the
444+:: file (+where). So `++ view` above `++ main view` is an error at
445+:: 2:1, the line that isn't deeper.
446+:: - Where a tight form needs its next token at once (after name+, `,
447+:: |= in an operand, name=, the = of a pun, a path's / and %/, a
448+:: typed segment's parts) and finds a space: at the end of the
449+:: previous token, where the space starts, "expected a term right
450+:: after `|=`, found a space" (+fail-space). A wing and a ( after a
451+:: space are no error: that is a call.
452+:: - At an error token: the lexer's position and message, unchanged.
453+:: - Three pattern errors point inside their token, where it stops
454+:: being a pattern: a date, duration or knot at its second character
455+:: (~ alone is null, and no ship goes on so), ~[ at its [, and a
456+:: string with {…} at its {.
457+:: In a bracket, a closer that doesn't match is "expected `]` to close
458+:: the `~[` at 1:6, found `)`", checked before spacing; after an item, a
459+:: tight token that isn't a closer is "expected a space between items,
460+:: found `M`". Hints name the left-out forms the lexer can't see (2.6):
461+:: where an expression starts, = followed tight by ( is "=(a b) is left
462+:: out: eq is a gate", = followed tight by / is "=/ is left out: ++
463+:: defines values", and * is "*mold is left out: no defaults"; ^- or ?-
464+:: followed tight by ( is "the wide form ^-(…) is left out: indentation
465+:: covers it". Examples:
466+:: expected `]` or an item on a deeper line, found a line at the same
467+:: depth
320:: expected the end of the line, found a deeper line; only a bracket
468:: expected the end of the line, found a deeper line; only a bracket
321:: open at the end of a line, or a rune's body, takes deeper lines
469:: open at the end of a line, or a rune's body, takes deeper lines
322:: expected an expression, found `^-`; inside a call, a rune goes in
470:: expected an expression, found `^-`; inside a call, a rune goes in
323:: parentheses
471:: parentheses
324−:: a change's items are named, as in m(done=%.y)
472+:: expected a named item, found `x`; a change's items are named, as in
473+:: m(done=%.y)
325:: Messages of milestone 1 are golden-tested, so their wording is fixed
474:: Messages of milestone 1 are golden-tested, so their wording is fixed
326:: by the tests once written.
475:: by the tests once written.
327::
476::
@@ -331,30 +480,51 @@
331::
480::
332:: Each printer returns a cord: lines joined by \0a, no final newline.
481:: Each printer returns a cord: lines joined by \0a, no final newline.
333::
482::
334−:: 4.1 Tokens (+show-tokens): one token per line, "<line>:<col>", then
483+:: 4.1 Tokens (+show-tokens): one token per line, "<line>:<col>" at
335−:: "tight " if the token is tight, then the kind and the text. Kinds:
484+:: +where, then "tight " if the token is tight, then the kind and the
336−:: glyph (with its text), INDENT, DEDENT, NEWLINE, name, wing, lit (the
485+:: text. Kinds: glyph (with its text), INDENT, DEDENT, NEWLINE, name, wing,
337−:: literal as Hoon prints its dime: 1.000, 0x1f, ~zod, ~h1.m30, ~.knot;
486+:: lit (the literal as Hoon prints its dime: 1.000, 0x1f, ~zod, ~h1.m30,
338−:: terms as %add, %0, %& and %|; loobeans %.y and %.n; null ~), str,
487+:: ~.knot; terms as %add, %0, %& and %|; loobeans %.y and %.n; null ~),
339−:: str-head, str-mid and str-tail (quoted, with \\ \" \{ and \XX
488+:: str, str-head, str-mid and str-tail (quoted, with \\ \" \{ and \XX
340−:: escapes), knot, aura (@ud), tvar. Layout tokens print their span's
489+:: escapes), knot, aura (@ud), tvar, and ERROR with its message (+golden
490+:: prints the rendered error instead). A layout token prints at the
491+:: start of the line it begins, beside that line's first token; at the
341−:: start: the end of the previous line's code. For `++ main view`:
492+:: end of the file, just past the last token. For `++ main view`:
342::
493::
343:: 1:1 glyph ++
494:: 1:1 glyph ++
344:: 1:4 name main
495:: 1:4 name main
345:: 1:9 name view
496:: 1:9 name view
346:: 1:13 NEWLINE
497:: 1:13 NEWLINE
347::
498::
499+:: and for `++ init |= ~` with ` [[~ %.n] ""]` below it:
500+::
501+:: 1:1 glyph ++
502+:: 1:4 name init
503+:: 1:9 glyph |=
504+:: 1:12 lit ~
505+:: 2:3 INDENT
506+:: 2:3 glyph [
507+:: 2:4 tight glyph [
508+:: 2:5 tight lit ~
509+:: 2:7 lit %.n
510+:: 2:10 tight glyph ]
511+:: 2:12 str ""
512+:: 2:14 tight glyph ]
513+:: 2:15 DEDENT
514+:: 2:15 NEWLINE
515+::
348:: 4.2 Trees (+show-module): S-expressions, (kind line:col fields kids),
516:: 4.2 Trees (+show-module): S-expressions, (kind line:col fields kids),
349:: with the node's start. A leaf is a node whose kids, if any, are atoms
517:: with the node's start. A leaf is a node whose kids, if any, are atoms
350:: (a string's quoted text, an application path's knots). A node whose
518:: (a string's quoted text, an application path's knots). A node whose
351:: kids are all leaves prints on one line; otherwise each kid goes on its
519:: kids are all leaves prints on one line; otherwise each kid goes on its
352:: own line, indented two more spaces, and the closing parens end the
520:: own line, indented two more spaces, and the closing parens end the
353:: last kid's line. (module …) always breaks. Bare fields and samples
521:: last kid's line. (module …) always breaks. Bare fields and samples
522+:: print as their mold, and a cell sample as (cell …) of its samples, a
354−:: print as their mold, unnamed items as their expr; strings print text
523+:: bare name there as (bind …); unnamed items print as their expr;
355−:: pieces quoted, between their interpolated exprs; application paths
524+:: strings print text pieces quoted, between their interpolated exprs;
356−:: print knots bare between their (expr) segments. The cart store from
525+:: application paths print knots bare between their (expr) segments. The
357−:: the Grammar tab, its code block's first line being line 1:
526+:: cart store from the Grammar tab, its code block's first line being
527+:: line 1:
358::
528::
359:: (module
529:: (module
360:: (mold 2:1 state
530:: (mold 2:1 state
@@ -400,7 +570,10 @@
400:: source line, then a caret under the column (col - 1 spaces, then ^).
570:: source line, then a caret under the column (col - 1 spaces, then ^).
401:: The file prints as a Clay path with its last segment as the extension:
571:: The file prints as a Clay path with its last segment as the extension:
402:: /tests/golden/x/source/jibb is /tests/golden/x/source.jibb. A line
572:: /tests/golden/x/source/jibb is /tests/golden/x/source.jibb. A line
403−:: past the end of the text prints as an empty line.
573+:: past the end of the text prints as an empty line. In the excerpt every
574+:: control character, a tab or carriage return being the likely ones,
575+:: prints as a space, so the caret stays under its column and golden
576+:: files hold no raw control bytes.
404::
577::
405:: /ui/basket.jibb:22:5: msg has no case %submitt
578:: /ui/basket.jibb:22:5: msg has no case %submitt
406:: %submitt [m(note="") ~]
579:: %submitt [m(note="") ~]
@@ -430,6 +603,9 @@
430::
603::
431:: tight is %.y when the token follows the previous one on the same
604:: tight is %.y when the token follows the previous one on the same
432:: line with no space between them; layout tokens are never tight.
605:: line with no space between them; layout tokens are never tight.
606+:: A layout token's span runs from just past the previous token to the
607+:: start of the line it begins, or is empty at the end of the file
608+:: (2.4, 2.5). An error token is the last token, if any (2.0).
433::
609::
434+$ token [at=span tight=? lex=lexeme]
610+$ token [at=span tight=? lex=lexeme]
435::
611::
@@ -445,6 +621,7 @@
445 [%knot p=@ta] :: path segment
621 [%knot p=@ta] :: path segment
446 [%aura p=@ta] :: @ud as 'ud', @ as ''
622 [%aura p=@ta] :: @ud as 'ud', @ as ''
447 [%tvar p=@t] :: M
623 [%tvar p=@t] :: M
624+ [%error p=tape] :: 2.0: what broke
448 ==
625 ==
449::
626::
450:: +glyph: a token that is its text, and the layout tokens
627:: +glyph: a token that is its text, and the layout tokens
@@ -481,7 +658,10 @@
481+| %tree
658+| %tree
482::
659::
483:: The syntax tree. Every node is [%tag at=span …] with at least one
660:: The syntax tree. Every node is [%tag at=span …] with at least one
484−:: field after at, so +span-of finds the span of any node at +<.
661+:: field after at, so +span-of finds its span at +<, except +item, +edit
662+:: and +arm, which have no tag and start with at=span; and a path's
663+:: knots (+pseg, +qseg) and a string's text (+piece), which have no
664+:: span: their node's span covers them.
485:: Types avoid the standard library's names (mold, wing, gate, sym…),
665:: Types avoid the standard library's names (mold, wing, gate, sym…),
486:: hence +shape for a mold as written. Every type in a recursive cycle
666:: hence +shape for a mold as written. Every type in a recursive cycle
487:: has a $~ default that is a leaf: Hoon can't build the default of
667:: has a $~ default that is a leaf: Hoon can't build the default of
@@ -549,14 +729,18 @@
549::
729::
550+$ arm $~([*span *pattern *expr] [at=span pat=pattern val=expr])
730+$ arm $~([*span *pattern *expr] [at=span pat=pattern val=expr])
551::
731::
552−:: +sample: a gate's sample; a bare name binds (%bind)
732+:: +sample: a gate's sample, or a field of a cell sample
733+::
734+:: A bare name binds (%bind) wherever it stands in a sample, so a cell
735+:: sample is a %cell of samples, never a %bare cell (section 3).
553::
736::
554+$ sample
737+$ sample
555 $~ [%bind *span %$]
738 $~ [%bind *span %$]
556 $% [%bind at=span name=term] :: p
739 $% [%bind at=span name=term] :: p
557 [%face at=span name=term =shape] :: m=model
740 [%face at=span name=term =shape] :: m=model
558 [%pun at=span name=term] :: =msg, for msg=msg
741 [%pun at=span name=term] :: =msg, for msg=msg
742+ [%cell at=span items=(list sample)] :: [a=@ b] [=msg m=model]
559− [%bare at=span =shape] :: ~ [a=@ b=@]
743+ [%bare at=span =shape] :: ~ @t (list @t) %add
560 ==
744 ==
561::
745::
562:: +field: a field of a cell mold; nests in +sample
746:: +field: a field of a cell mold; nests in +sample
@@ -604,46 +788,713 @@
604::
788::
605:: +layout: source to tokens (design: section 2)
789:: +layout: source to tokens (design: section 2)
606::
790::
791+:: Never fails: an error it finds is its last token, [%error msg], at
792+:: the error's position (2.0). +lexer does the work.
793+::
607++ layout
794++ layout
608 |= [file=path src=@t]
795 |= [file=path src=@t]
609− ^- (each (list token) error)
796+ ^- (list token)
610− [%| file 1 1 "layout pass not implemented"]
797+ ~(run lexer [(trip src) 1 1 ~ ~[1] [0 0] 0 &])
798+::
799+:: +layout-error: the error of a token list's error token, if any
800+::
801+++ layout-error
802+ |= [file=path toks=(list token)]
803+ ^- (unit error)
804+ ?~ toks ~
805+ =/ last=token (rear toks)
806+ ?. ?=([%error *] lex.last) ~
807+ `[file line.beg.at.last col.beg.at.last p.lex.last]
611::
808::
612:: +parse: source to tree
809:: +parse: source to tree
613::
810::
614++ parse
811++ parse
615 |= [file=path src=@t]
812 |= [file=path src=@t]
616 ^- (each module error)
813 ^- (each module error)
617− =/ lay (layout file src)
618− ?: ?=(%| -.lay) lay
619− (parse-tokens file p.lay)
814+ (parse-tokens file (layout file src))
620::
815::
621:: +parse-tokens: tokens to tree (design: section 3)
816:: +parse-tokens: tokens to tree (design: section 3)
622::
817::
818+:: It accepts no error token, so it fails at the first of its own
819+:: error and the layout pass's (2.0). The stub reports an error token
820+:: that comes first, as the parser will, and fails otherwise.
821+::
623++ parse-tokens
822++ parse-tokens
624 |= [file=path toks=(list token)]
823 |= [file=path toks=(list token)]
625 ^- (each module error)
824 ^- (each module error)
825+ ?: ?=([[* * [%error *]] *] toks)
826+ (fail file toks "a module")
626 =/ at=loc ?~(toks [1 1] (where i.toks))
827 =/ at=loc ?~(toks [1 1] (where i.toks))
627 [%| file line.at col.at "parser not implemented"]
828 [%| file line.at col.at "parser not implemented"]
628::
829::
629:: +golden: both stages printed, or the rendered error
830:: +golden: both stages printed, or the rendered error
630::
831::
631−:: tokens: the layout pass's output, or its error
832+:: tokens: the layout pass's tokens, or its error if it found one
632−:: tree: the parser's output, or the layout pass's or parser's error
833+:: tree: the parser's tree, or the first error of either stage, which
834+:: the parser reports since it accepts no error token (2.0)
633::
835::
634++ golden
836++ golden
635 |= [file=path src=@t]
837 |= [file=path src=@t]
636 ^- [tokens=@t tree=@t]
838 ^- [tokens=@t tree=@t]
637− =/ lay (layout file src)
839+ =/ toks=(list token) (layout file src)
638− ?: ?=(%| -.lay)
840+ =/ bad=(unit error) (layout-error file toks)
639− =/ msg=@t (show-error src p.lay)
841+ :- ?^ bad (show-error src u.bad)
640− [msg msg]
842+ (show-tokens toks)
641− :- (show-tokens p.lay)
642− =/ par (parse-tokens file p.lay)
843+ =/ par (parse-tokens file toks)
643− ?: ?=(%| -.par)
644− (show-error src p.par)
844+ ?: ?=(%| -.par) (show-error src p.par)
845+ :: a parser that accepted an error token would be wrong; say so
846+ ?^ bad (show-error src u.bad)
645 (show-module p.par)
847 (show-module p.par)
646::
848::
849++| %lexer
850+::
851+:: +lexer: the layout pass (section 2), a door over its state
852+::
853+:: It reads the text as one tape, a line at a time, keeps its tokens
854+:: last first and flops them at the end, so its time is linear in the
855+:: text. Each +step reads a line's indentation, one token or the end of
856+:: a line, and returns the door; +run steps until the text ends or an
857+:: error token stops it (2.0). Every loop is a trap whose recursive
858+:: call is a tail call, so a long file grows no stack.
859+::
860+++ lexer
861+ |_ $: cs=tape :: the text not yet read
862+ lin=@ud :: the line it starts on
863+ col=@ud :: the column it starts at
864+ out=(list token) :: the tokens so far, last first
865+ lev=(list @ud) :: open levels, innermost first
866+ pend=loc :: just past the last token
867+ dep=@ud :: open interpolations (2.9)
868+ bol=? :: at the start of a line
869+ ==
870+ ++ cor .
871+ ::
872+ :: +run: the tokens, to an error token or the end of the file
873+ ::
874+ ++ run
875+ ^- (list token)
876+ =/ lx cor
877+ |- ^- (list token)
878+ ?: stopped:lx (flop out.lx)
879+ ?: &(bol.lx ?=(~ cs.lx)) (flop out:eof:lx)
880+ $(lx step:lx)
881+ ::
882+ :: +stopped: whether an error token was emitted (2.0)
883+ ::
884+ ++ stopped ?=([[* * [%error *]] *] out)
885+ ::
886+ :: +eof: the end of the file (2.5): a DEDENT for each open level but
887+ :: the first, then NEWLINE, all with empty spans just past the last
888+ :: token; nothing in a file without tokens
889+ ::
890+ ++ eof
891+ ^+ cor
892+ ?~ out cor
893+ =/ at=span [pend pend]
894+ =/ n=@ud (dec (max 1 (lent lev)))
895+ cor(out [[at | %newline] (weld (reap n `token`[at | %dedent]) out)])
896+ ::
897+ :: +step: a line's indentation, or the line's next token or its end
898+ ::
899+ ++ step
900+ ^+ cor
901+ ?: bol indent:spaces
902+ read:spaces
903+ ::
904+ :: +spaces: past the spaces at the head of the text
905+ ::
906+ ++ spaces
907+ ^+ cor
908+ |- ^+ cor
909+ ?. &(?=(^ cs) =(' ' i.cs)) cor
910+ $(cs t.cs, col +(col))
911+ ::
912+ :: +next: past the end of the line, to the start of the next one
913+ ::
914+ ++ next
915+ ^+ cor
916+ ?~ cs cor(bol &)
917+ cor(cs t.cs, lin +(lin), col 1, bol &)
918+ ::
919+ :: +indent: a line, from its first character that isn't a space. A
920+ :: blank or comment-only line gives nothing (2.3); another line gets
921+ :: that character checked (2.2), then its layout tokens (2.4).
922+ ::
923+ ++ indent
924+ ^+ cor
925+ ?: |(?=(~ cs) =('\0a' i.cs)) next
926+ ?: &(=(':' i.cs) ?=(^ t.cs) =(':' i.t.cs)) next:comment
927+ =/ bad=(unit tape) (bad-char i.cs)
928+ ?^ bad (err col u.bad)
929+ ?: (gte i.cs 128) (err col non-ascii)
930+ ?~ out
931+ ?. =(1 col)
932+ %+ err col
933+ "the first line is indented: top-level lines start at column 1"
934+ cor(bol |)
935+ =/ top=@ud ?~(lev 1 i.lev)
936+ ?: (gth col top) (lay(lev [col lev], bol |) 1 %indent)
937+ ?: =(col top) (lay(bol |) 1 %newline)
938+ =/ n=@ud 0
939+ =/ rest=(list @ud) lev
940+ |- ^+ cor
941+ ?: &(?=(^ rest) (lth col i.rest)) $(n +(n), rest t.rest)
942+ ?. &(?=(^ rest) =(col i.rest)) (err col (no-level lev))
943+ (lay:(lay(lev rest, bol |) n %dedent) 1 %newline)
944+ ::
945+ :: +lay: n layout tokens g, spanning from just past the last token to
946+ :: this line's first character (2.4); they leave pend as it is
947+ ::
948+ ++ lay
949+ |= [n=@ud g=?(%indent %dedent %newline)]
950+ ^+ cor
951+ cor(out (weld (reap n `token`[[pend [lin col]] | g]) out))
952+ ::
953+ :: +err: the error token, at column c of this line (2.0)
954+ ::
955+ ++ err
956+ |= [c=@ud msg=tape]
957+ ^+ cor
958+ cor(out [[[[lin c] [lin c]] | [%error msg]] out])
959+ ::
960+ :: +put: a token from beg to end on this line, with rest the text
961+ :: after it, which starts at end
962+ ::
963+ ++ put
964+ |= [beg=loc end=loc lex=lexeme rest=tape]
965+ ^+ cor
966+ %= cor
967+ out [[[beg end] =(beg pend) lex] out]
968+ pend end
969+ cs rest
970+ col col.end
971+ ==
972+ ::
973+ :: +emit: a token of the next n characters, which are ASCII
974+ ::
975+ ++ emit
976+ |= [n=@ud lex=lexeme]
977+ ^+ cor
978+ (put [lin col] [lin (add col n)] lex (slag n cs))
979+ ::
980+ :: +comment: past a comment to the end of its line, checking its
981+ :: characters (2.2)
982+ ::
983+ ++ comment
984+ ^+ cor
985+ |- ^+ cor
986+ ?: |(?=(~ cs) =('\0a' i.cs)) cor
987+ ?: (in i.cs bad-mask) (err col (need (bad-char i.cs)))
988+ $(cs t.cs, col (next-col col i.cs))
989+ ::
990+ :: +read: the line's next token, or its end (2.6)
991+ ::
992+ :: A token is told by its first characters a, b and c, where b and c
993+ :: are 0 past the end of the text. Names, the most common, go first.
994+ ::
995+ ++ read
996+ ^+ cor
997+ ?: |(?=(~ cs) =('\0a' i.cs))
998+ ?. =(0 dep) (err col "this `\{` has no `}` on its line")
999+ next
1000+ =/ a=@ i.cs
1001+ ?: (is-lower a) name
1002+ =/ b=@ ?~(t.cs 0 i.t.cs)
1003+ =/ c=@ ?~(t.cs 0 ?~(t.t.cs 0 i.t.t.cs))
1004+ ?: =('(' a) (emit 1 %'(')
1005+ ?: =(')' a) (emit 1 %')')
1006+ ?: =('[' a) (emit 1 %'[')
1007+ ?: =(']' a) (emit 1 %']')
1008+ ?: =('"' a) (text |)
1009+ ?: =('}' a)
1010+ ?: =(0 dep) (err col "this `}` closes no `\{`")
1011+ (text(dep (dec dep)) &)
1012+ ?: (is-digit a) (literal (run-len cs number-mask))
1013+ ?: =('%' a) (percent b c)
1014+ ?: =('=' a)
1015+ ?: |(=('<' b) =('>' b))
1016+ %+ err col
1017+ "`={[b ~]}` is left out: names never shadow, and `.` reads imports too"
1018+ ?: =('=' b)
1019+ (err col "the closer `==` is left out: indentation covers it")
1020+ (emit 1 %'=')
1021+ ?: =('`' a) (emit 1 %'`')
1022+ ?: =('*' a) (emit 1 %'*')
1023+ ?: =('~' a)
1024+ ?: =('[' b) (emit 2 %'~[')
1025+ ?: =('&' b) (emit 2 %'~&')
1026+ ?: =('|' b) (err +(col) "`~|` is left out: `~&` covers debugging")
1027+ =/ n=@ud (run-len t.cs knot-mask)
1028+ ?: =(0 n) (emit 1 [%lit %null %n 0])
1029+ (literal +(n))
1030+ ?: =('/' a)
1031+ ?: &(=(1 col) |(=('-' b) =('%' b) =('=' b)))
1032+ (emit 2 ?:(=('-' b) %'/-' ?:(=('%' b) %'/%' %'/=')))
1033+ ?: =('+' b)
1034+ (err +(col) "`/+` is left out: code also runs in the browser")
1035+ segment:(emit 1 %'/')
1036+ ?: =('+' a)
1037+ ?: =('+' b) (emit 2 %'++')
1038+ ?: =('$' b) (emit 2 %'+$')
1039+ (emit 1 %'+')
1040+ ?: =('|' a)
1041+ ?: &(=('=' b) =('(' c)) (emit 3 %'|=(')
1042+ ?: =('=' b) (emit 2 %'|=')
1043+ ?: =('$' b) (emit 2 %'|$')
1044+ ?: |(=('%' b) =('_' b) =('*' b))
1045+ (err +(col) "`|{[b ~]}` is left out: modules are records")
1046+ ?: =('-' b) (err +(col) "`|-` is left out: gates recurse by name")
1047+ (err +(col) "`|` begins `|=`, `|=(` or `|$`")
1048+ ?: =('$' a)
1049+ ?: &(=('?' b) =('(' c)) (emit 3 %'$?(')
1050+ ?: =('?' b) (emit 2 %'$?')
1051+ ?: &(=('-' b) =('(' c)) (emit 3 %'$-(')
1052+ ?: =('-' b)
1053+ (err (add 2 col) "`$-` has only the wide form `$-(sample product)`")
1054+ ?: =('(' b) (err col "`$(…)` is left out: gates recurse by name")
1055+ ?: =('%' b) (err +(col) "`$%` is left out: `$?` covers unions")
1056+ (err +(col) "`$` begins `$?`, `$?(` or `$-(`")
1057+ ?: =('^' a)
1058+ ?: =('-' b) (emit 2 %'^-')
1059+ (err +(col) "`^` begins `^-`")
1060+ ?: =('?' a)
1061+ ?: =('-' b) (emit 2 %'?-')
1062+ ?: =('+' b) (err +(col) "`?+` is left out: `?-` is the branch")
1063+ ?: &(=(':' b) !=(':' c))
1064+ (err +(col) "`?:` is left out: `?-` is the branch")
1065+ ?: =('!' b) (err +(col) "`?!` is left out: eq and not are gates")
1066+ (emit 1 %'?')
1067+ ?: =('!' a)
1068+ ?: =('!' b) (emit 2 %'!!')
1069+ ?: =('>' b)
1070+ (err +(col) "`!>` is left out: code also runs in the browser")
1071+ (err +(col) "`!` begins only `!!`: `!x` is left out, as not is a gate")
1072+ ?: =('@' a)
1073+ ?: |(=('s' b) =('r' b))
1074+ (err +(col) "signed and floating-point auras are left out of Jibb")
1075+ =/ n=@ud (run-len t.cs lower-mask)
1076+ =/ rest=tape (slag n t.cs)
1077+ =? n &(?=(^ rest) (is-upper i.rest)) +(n)
1078+ (emit +(n) [%aura (@ta (crip (scag n t.cs)))])
1079+ ?: (is-upper a)
1080+ => (emit 1 [%tvar a])
1081+ ?. &(?=(^ cs) |((is-lower i.cs) (is-upper i.cs) (is-digit i.cs)))
1082+ cor
1083+ (err col "a type variable is one capital letter")
1084+ ?: =(':' a)
1085+ ?. =(0 dep) (err col "a comment can't start inside `\{…}`")
1086+ ?: =(':' b) comment
1087+ ?: =('~' b)
1088+ (err +(col) "`:~` is left out: indentation covers it; write ~[…]")
1089+ ?: =('*' b)
1090+ (err +(col) "`:*` is left out: indentation covers it; write […]")
1091+ ?: &(=(pend [lin col]) ?=([[* * ?([%name *] [%wing *])] *] out))
1092+ %+ err +(col)
1093+ %+ weld "`a:b` is left out: names never shadow, "
1094+ "and `.` reads imports too; write a.b"
1095+ (err +(col) "a comment starts with `::`")
1096+ ?: =('.' a)
1097+ ?: =('=' b) (err col "`.=` is left out: eq and not are gates")
1098+ ?: =('*' b)
1099+ %+ err col
1100+ "`.*` is left out: names never shadow, and `.` reads imports too"
1101+ (err col (unexpected a))
1102+ ?: =('-' a)
1103+ ?: =('-' b)
1104+ (err col "the closer `--` is left out: indentation covers it")
1105+ (err col (unexpected a))
1106+ ?: =(';' a)
1107+ (err col "Sail's `;` runes are left out: layout is Jibb's elements")
1108+ ?: =('\'' a) (err col "there is no '…' form: strings are \"…\"")
1109+ ?: =('{' a)
1110+ (err col "unexpected `\{`: `\{…}` interpolates only inside a string")
1111+ ?: (gte a 128) (err col non-ascii)
1112+ =/ bad=(unit tape) (bad-char a)
1113+ ?^ bad (err col u.bad)
1114+ (err col (unexpected a))
1115+ ::
1116+ :: +unexpected: the error for a character that starts no token (2.6),
1117+ :: with a hint where one helps
1118+ ::
1119+ ++ unexpected
1120+ |= a=@
1121+ ^- tape
1122+ =/ what=tape "unexpected `{[a ~]}`"
1123+ ?: =('.' a) "{what}: a `.` joins the names of a wing, as title.p"
1124+ ?: =(',' a) "{what}: items are separated by spaces"
1125+ ?: =('-' a)
1126+ "{what}: a name starts with a letter, and Jibb has no operators"
1127+ ?: =('<' a)
1128+ "{what}: there is no `<…>`, since `\{…}` prints a value by its aura"
1129+ what
1130+ ::
1131+ :: +percent: a token that starts with %, whose next characters are b
1132+ :: and c: %/, a loobean or a term (2.6)
1133+ ::
1134+ ++ percent
1135+ |= [b=@ c=@]
1136+ ^+ cor
1137+ ?: =('/' b) segment:(emit 2 %'%/')
1138+ ?: =('.' b)
1139+ ?: =('y' c) (emit 3 [%lit %loobean %f 0])
1140+ ?: =('n' c) (emit 3 [%lit %loobean %f 1])
1141+ (err (add 2 col) "the loobeans are `%.y` and `%.n`")
1142+ ?: =('&' b) (emit 2 [%lit %term %f 0])
1143+ ?: =('|' b) (emit 2 [%lit %term %f 1])
1144+ ?: =(':' b) (err +(col) "`%:` is left out: indentation covers it")
1145+ ?: =('=' b)
1146+ %+ err +(col)
1147+ "`%=` is left out: indentation covers it; write a change, as m(a=b)"
1148+ =/ rest=tape ?~(cs ~ t.cs)
1149+ ?: (is-lower b)
1150+ =/ n=@ud (run-len rest name-mask)
1151+ => (emit +(n) [%lit %term %tas (crip (scag n rest))])
1152+ ?. &(?=(^ cs) |((is-upper i.cs) =('_' i.cs))) cor
1153+ (err col "names are lowercase letters, digits and -")
1154+ ?: (is-digit b)
1155+ =/ n=@ud (run-len rest digit-mask)
1156+ => (emit +(n) [%lit %term %ud (decimal (scag n rest))])
1157+ ?. &(?=(^ cs) (in i.cs term-tail-mask)) cor
1158+ %+ err col
1159+ "unexpected `{[i.cs ~]}`: a numeric term is `%` and digits only, as %1000"
1160+ (err +(col) "`%` begins a term, a loobean or `%/`")
1161+ ::
1162+ :: +name: a name, or a wing, names joined by dots (2.6)
1163+ ::
1164+ ++ name
1165+ ^+ cor
1166+ =| ns=(list term)
1167+ =| len=@ud
1168+ =/ rest=tape cs
1169+ |- ^+ cor
1170+ =/ n=@ud (run-len rest name-mask)
1171+ =/ nam=term (@tas (crip (scag n rest)))
1172+ =. rest (slag n rest)
1173+ ?: &(?=([@ @ *] rest) =('.' i.rest) (is-lower i.t.rest))
1174+ $(ns [nam ns], len (add +(len) n), rest t.rest)
1175+ =/ lex=lexeme ?~(ns [%name nam] [%wing (flop [nam ns])])
1176+ => (emit (add len n) lex)
1177+ ?~ cs cor
1178+ ?: |((is-upper i.cs) =('_' i.cs))
1179+ (err col "names are lowercase letters, digits and -")
1180+ ?. =('.' i.cs) cor
1181+ (err +(col) "a `.` in a wing is followed by a name")
1182+ ::
1183+ :: +segment: after / or %/, a run of knot characters as one knot
1184+ :: token, tight (2.7)
1185+ ::
1186+ ++ segment
1187+ ^+ cor
1188+ =/ n=@ud (run-len cs knot-mask)
1189+ => ?:(=(0 n) cor (emit n [%knot (@ta (crip (scag n cs)))]))
1190+ :: what follows a segment: / ( [, a closer, a comment or a space
1191+ ?. &(?=(^ cs) (in i.cs seg-bad-mask)) cor
1192+ %+ err col
1193+ ;: weld
1194+ "unexpected `{[i.cs ~]}`: "
1195+ ?: =('?' i.cs) "a path carries no query, and a "
1196+ ?: =('#' i.cs) "a path carries no fragment, and a "
1197+ "a path "
1198+ "segment holds lowercase letters, digits and - . ~ _"
1199+ ==
1200+ ::
1201+ :: +literal: a number or a ~ literal, the next n characters, read by
1202+ :: Hoon's own parser, nuck:so (2.8)
1203+ ::
1204+ ++ literal
1205+ |= n=@ud
1206+ ^+ cor
1207+ =/ run=tape (scag n cs)
1208+ =/ a=@ ?~(run 0 i.run)
1209+ =/ b=@ ?~(run 0 ?~(t.run 0 i.t.run))
1210+ :: 0b 0c 0i 0w begin auras Jibb doesn't write, whatever follows
1211+ ?: &(=('0' a) |(=('b' b) =('c' b) =('i' b) =('w' b)))
1212+ (err +(col) "Jibb writes no @u{[b ~]} literals")
1213+ :: a year BC that Hoon's dates can't hold, which its date code
1214+ :: crashes on: an error at the - that makes it BC
1215+ =/ bc=(unit [at=@ud y=@ud]) (year-bc col run)
1216+ ?: &(?=(^ bc) =(0 y.u.bc))
1217+ (err at.u.bc "there is no year 0 BC: 1 BC is ~1-, as ~1-.1.1")
1218+ ?: &(?=(^ bc) (gth y.u.bc 292.277.024.401))
1219+ (err at.u.bc "Hoon's dates begin in 292.277.024.401 BC")
1220+ =/ ed (nuck:so [[lin col] run])
1221+ ?~ q.ed (err q.p.ed (literal-msg run %$))
1222+ =/ used=@ud (sub n (lent q.q.u.q.ed))
1223+ =/ con=coin p.u.q.ed
1224+ ?: =(0 used) (err col (literal-msg run %$))
1225+ ?. ?=([%$ *] con) (err +(col) "Jibb writes no such literal")
1226+ =/ form=(unit lit-form) (lit-form-of p.p.con)
1227+ ?~ form
1228+ %+ err +(col)
1229+ %+ weld "Jibb writes no @{(trip p.p.con)} literals"
1230+ ?:(=(%t p.p.con) "; strings are \"…\"" "")
1231+ =/ lex=lexeme [%lit u.form p.p.con q.p.con]
1232+ ?: =(used n)
1233+ ?. =(%ta p.p.con) (emit n lex)
1234+ :: a ~. knot is followed as a path segment is (2.7)
1235+ => (emit n lex)
1236+ ?. &(?=(^ cs) (in i.cs seg-bad-mask)) cor
1237+ %+ err col
1238+ %+ weld "unexpected `{[i.cs ~]}`: "
1239+ "a knot holds lowercase letters, digits and - . ~ _"
1240+ :: the error goes where Hoon's parser stopped looking; after a ship,
1241+ :: or a bare ~ that a letter follows, at the first letter that no
1242+ :: syllable continues (+ship-stop), or past a duration's unit, d h m
1243+ :: or s, if that is later (2.8)
1244+ =/ at=@ud q.p.ed
1245+ =? at &(=('~' a) (is-lower b) ?=(?(%n %p) p.p.con))
1246+ =/ dur=@ud ?:(|(=('d' b) =('h' b) =('m' b) =('s' b)) 2 1)
1247+ (min at (add col (max dur (ship-stop run))))
1248+ (err:(emit used lex) at (literal-msg run p.p.con))
1249+ ::
1250+ :: +text: a string's text, from its opening " or the } that closes
1251+ :: an interpolation, through the " or { that ends it (2.9). mid: it
1252+ :: resumes after a }, so it is str-mid or str-tail, not str-head or str.
1253+ ::
1254+ ++ text
1255+ |= mid=?
1256+ ^+ cor
1257+ =/ beg=loc [lin col]
1258+ =/ rest=tape ?~(cs ~ t.cs)
1259+ =/ at=@ud +(col)
1260+ =| acc=tape
1261+ |- ^+ cor
1262+ ?: |(?=(~ rest) =('\0a' i.rest))
1263+ (err at "this string has no closing `\"` on its line")
1264+ =/ ch=@ i.rest
1265+ ?: =('"' ch)
1266+ =/ txt=@t (crip (flop acc))
1267+ (put beg [lin +(at)] ?:(mid [%str-tail txt] [%str txt]) t.rest)
1268+ ?: =('{' ch)
1269+ =/ txt=@t (crip (flop acc))
1270+ => (put beg [lin +(at)] ?:(mid [%str-mid txt] [%str-head txt]) t.rest)
1271+ cor(dep +(dep))
1272+ ?: =('\\' ch)
1273+ ?~ t.rest (err +(at) bad-escape)
1274+ =/ d=@ i.t.rest
1275+ ?: |(=('\\' d) =('"' d) =('{' d))
1276+ $(rest t.t.rest, at (add 2 at), acc [d acc])
1277+ =/ bd=(unit tape) (bad-char d)
1278+ ?^ bd (err +(at) u.bd)
1279+ ?. (is-hex d) (err +(at) bad-escape)
1280+ ?~ t.t.rest (err (add 2 at) bad-hex)
1281+ =/ e=@ i.t.t.rest
1282+ =/ be=(unit tape) (bad-char e)
1283+ ?^ be (err (add 2 at) u.be)
1284+ ?. (is-hex e) (err (add 2 at) bad-hex)
1285+ %= $
1286+ rest t.t.t.rest
1287+ at (add 3 at)
1288+ acc [(add (mul 16 (hex-val d)) (hex-val e)) acc]
1289+ ==
1290+ ?: =(1 (cut 0 [ch 1] bad-mask)) (err at (need (bad-char ch)))
1291+ %= $
1292+ rest t.rest
1293+ at ?:(=(1 (cut 0 [ch 1] cont-mask)) at +(at))
1294+ acc [ch acc]
1295+ ==
1296+ --
1297+::
1298+:: +bad-char: the error for a character that no text may hold (2.2)
1299+::
1300+++ bad-char
1301+ |= c=@
1302+ ^- (unit tape)
1303+ ?: =(9 c) `"a tab: Jibb uses spaces only"
1304+ ?: =(13 c) `"a carriage return: Jibb lines end with a line feed alone"
1305+ ?: |((lth c 32) =(127 c)) `"a control character"
1306+ ~
1307+::
1308+++ non-ascii "non-ASCII text outside a string or comment"
1309+++ bad-escape "a `\\` begins `\\\\`, `\\\"`, `\\\{` or two hex digits"
1310+++ bad-hex "a `\\` escape takes two lowercase hex digits, as `\\0a`"
1311+::
1312+:: Character classes are masks, bit c set for each character c in the
1313+:: class, so a test is one (cut 0 [c 1] mask) rather than a chain of
1314+:: comparisons.
1315+::
1316+++ lower-mask 0x7ff.fffe.0000.0000.0000.0000.0000.0000 :: a-z
1317+++ upper-mask 0x7ff.fffe.0000.0000.0000.0000 :: A-Z
1318+++ digit-mask 0x3ff.0000.0000.0000 :: 0-9
1319+++ hex-mask 0x7e.0000.0000.03ff.0000.0000.0000 :: 0-9 a-f
1320+++ name-mask 0x7ff.fffe.0000.0000.03ff.2000.0000.0000 :: a-z 0-9 -
1321+++ knot-mask 0x47ff.fffe.8000.0000.03ff.6000.0000.0000 :: and . ~ _
1322+++ number-mask 0x7ff.fffe.07ff.fffe.03ff.4000.0000.0000 :: a-z A-Z 0-9 .
1323+++ bad-mask 0x8000.0000.0000.0000.0000.0000.ffff.fbff :: 2.2
1324+:: after a path segment (2.7): printable, but not a knot character,
1325+:: / ( [ ) ] } or :
1326+++ seg-bad-mask 0x1800.0001.57ff.ffff.f800.1cfe.0000.0000
1327+:: after a numeric term: a-z A-Z _ - .
1328+++ term-tail-mask 0x7ff.fffe.87ff.fffe.0000.6000.0000.0000
1329+::
1330+:: +cont-mask: UTF-8 continuation bytes, 10xx.xxxx, which start no
1331+:: column (1)
1332+::
1333+++ cont-mask
1334+ 0xffff.ffff.ffff.ffff.0000.0000.0000.0000.0000.0000.0000.0000
1335+::
1336+++ in |=([c=@ m=@] =(1 (cut 0 [c 1] m)))
1337+++ is-lower |=(c=@ (in c lower-mask))
1338+++ is-upper |=(c=@ (in c upper-mask))
1339+++ is-digit |=(c=@ (in c digit-mask))
1340+++ is-hex |=(c=@ (in c hex-mask))
1341+++ hex-val |=(c=@ ^-(@ ?:((is-digit c) (sub c '0') (sub c 87))))
1342+::
1343+:: +next-col: the column after character c at column col
1344+::
1345+++ next-col
1346+ |= [col=@ud c=@]
1347+ ^- @ud
1348+ ?:(=(1 (cut 0 [c 1] cont-mask)) col +(col))
1349+::
1350+:: +run-len: how many characters at the head of cs are in class m
1351+::
1352+++ run-len
1353+ |= [cs=tape m=@]
1354+ ^- @ud
1355+ =| n=@ud
1356+ |- ^- @ud
1357+ ?~ cs n
1358+ ?. =(1 (cut 0 [`@`i.cs 1] m)) n
1359+ $(cs t.cs, n +(n))
1360+::
1361+:: +decimal: digits as a number
1362+::
1363+++ decimal
1364+ |= ds=tape
1365+ ^- @ud
1366+ (roll ds |=([d=@ a=@ud] (add (mul 10 a) (sub d '0'))))
1367+::
1368+:: +lit-form-of: the literal rule of a dime's aura, if Jibb takes it (2.8)
1369+::
1370+++ lit-form-of
1371+ |= aura=@ta
1372+ ^- (unit lit-form)
1373+ ?+ aura ~
1374+ %ud `%number
1375+ %ux `%number
1376+ %uv `%number
1377+ %p `%ship
1378+ %da `%date
1379+ %dr `%duration
1380+ %ta `%knot
1381+ %n `%null
1382+ ==
1383+::
1384+:: +literal-msg: why a literal stops where nuck:so stops (2.8), told by
1385+:: its first characters and the aura of what nuck:so read
1386+::
1387+++ literal-msg
1388+ |= [run=tape aura=@ta]
1389+ ^- tape
1390+ =/ a=@ ?~(run 0 i.run)
1391+ =/ b=@ ?~(run 0 ?~(t.run 0 i.t.run))
1392+ ?. =('~' a)
1393+ ?: &(=('0' a) =('x' b))
1394+ %+ weld "a hexadecimal number is 0x and digits 0-9 and a-f, "
1395+ "in groups of four joined by dots, as 0x1.ffff"
1396+ ?: &(=('0' a) =('v' b))
1397+ %+ weld "a base-32 number is 0v and digits 0-9 and a-v, "
1398+ "in groups of five joined by dots, as 0v5.fdf99"
1399+ "a decimal is digits in groups of three joined by dots, as 1.000"
1400+ ?: |(=(%da aura) &(=(%n aura) (is-digit b)))
1401+ %+ weld "a date is ~year.month.day, then optionally "
1402+ "..hours.minutes.seconds, as ~2026.10.23..14.30.00"
1403+ ?: =(%dr aura)
1404+ "a duration is units of d, h, m and s joined by dots, as ~h1.m30"
1405+ ?: =(%p aura)
1406+ %+ weld "a ship is syllables in pairs joined by hyphens, "
1407+ "as ~zod, ~marzod or ~sampel-palnet"
1408+ %+ weld "`~` alone is null, and nothing here reads as a ship, "
1409+ "date, duration or knot"
1410+::
1411+:: +year-bc: a ~ literal run's year and the column of its -, if it
1412+:: starts as a date BC does, ~ then digits Hoon reads as a year, then -
1413+::
1414+:: Hoon's +year crashes on a year BC of 0 or past 292.277.024.401, as
1415+:: in ~0-.1.1, so these never reach nuck:so (2.8).
1416+::
1417+++ year-bc
1418+ |= [col=@ud run=tape]
1419+ ^- (unit [at=@ud y=@ud])
1420+ ?. ?=([%'~' @ *] run) ~
1421+ =/ tr=tape t.run
1422+ =/ ds=tape (scag (run-len tr digit-mask) tr)
1423+ ?~ ds ~
1424+ :: a year is 0 or has no leading 0, as dim:ag reads it
1425+ ?: &(=('0' i.ds) ?=(^ t.ds)) ~
1426+ =/ rest=tape (slag (lent ds) tr)
1427+ ?. ?=([%'-' *] rest) ~
1428+ `[(add col +((lent ds))) (decimal ds)]
1429+::
1430+:: +ship-stop: how many characters of a ~ literal's run, from its ~,
1431+:: could still begin a ship (2.8)
1432+::
1433+:: Hoon's parser reads a syllable's three letters before it looks
1434+:: them up, so it stops past the first letter that no syllable
1435+:: continues; this stops at that letter. It takes a galaxy's suffix,
1436+:: or words of a prefix and a suffix joined by - or --, as many as
1437+:: come. That is a few more texts than Hoon reads, so it never stops
1438+:: before Hoon's parser could have gone on.
1439+::
1440+++ ship-stop
1441+ |= run=tape
1442+ ^- @ud
1443+ =/ cs=tape ?~(run ~ t.run)
1444+ =/ pre=@ud (syllable cs sis:po)
1445+ :: a galaxy's suffix, or a word's prefix
1446+ ?. =(3 pre) +((max pre (syllable cs dex:po)))
1447+ =/ i=@ud 4
1448+ =. cs (slag 3 cs)
1449+ |- ^- @ud
1450+ :: the word's suffix
1451+ =/ suf=@ud (syllable cs dex:po)
1452+ ?. =(3 suf) (add i suf)
1453+ =. i (add i 3)
1454+ =. cs (slag 3 cs)
1455+ :: then - or --, and the next word's prefix
1456+ ?. &(?=(^ cs) =('-' i.cs)) i
1457+ =/ h=@ud ?:(&(?=([@ @ *] cs) =('-' i.t.cs)) 2 1)
1458+ =/ word=tape (slag h `tape`cs)
1459+ =/ nex=@ud (syllable word sis:po)
1460+ ?. =(3 nex) :(add i h nex)
1461+ $(i :(add i h 3), cs (slag 3 word))
1462+::
1463+:: +syllable: how many of cs's first three characters begin one of the
1464+:: 256 syllables in syls, the prefixes or suffixes of +po
1465+::
1466+++ syllable
1467+ |= [cs=tape syls=@t]
1468+ ^- @ud
1469+ =/ l=tape (scag 3 cs)
1470+ =/ k=@ud 0
1471+ |- ^- @ud
1472+ ?: =(k (lent l)) k
1473+ =/ head=@ (crip (scag +(k) l))
1474+ ?. (lien (gulf 0 255) |=(i=@ =(head (cut 3 [(mul 3 i) +(k)] syls))))
1475+ k
1476+ $(k +(k))
1477+::
1478+:: +no-level: the error for a line that returns to no open level (2.4),
1479+:: naming the open levels' columns, outermost first
1480+::
1481+++ no-level
1482+ |= lev=(list @ud)
1483+ ^- tape
1484+ %+ weld
1485+ "this line's indentation matches no enclosing line: indent it to column "
1486+ (join-or (turn (flop lev) |=(c=@ud (a-co:co c))))
1487+::
1488+:: +join-or: words as "a", "a or b", "a, b or c"
1489+::
1490+++ join-or
1491+ |= ws=(list tape)
1492+ ^- tape
1493+ ?~ ws ""
1494+ ?~ t.ws i.ws
1495+ ?~ t.t.ws "{i.ws} or {i.t.ws}"
1496+ "{i.ws}, {$(ws t.ws)}"
1497+::
647+| %printers
1498+| %printers
648::
1499::
649:: +show-tokens: one token per line (format: section 4.1)
1500:: +show-tokens: one token per line (format: section 4.1)
@@ -657,7 +1508,7 @@
657 |= t=token
1508 |= t=token
658 ^- tape
1509 ^- tape
659 ;: weld
1510 ;: weld
660− (show-loc beg.at.t)
1511+ (show-loc (where t))
661 " "
1512 " "
662 ?:(tight.t "tight " "")
1513 ?:(tight.t "tight " "")
663 (show-lexeme lex.t)
1514 (show-lexeme lex.t)
@@ -683,6 +1534,7 @@
683 %knot "knot {(trip p.x)}"
1534 %knot "knot {(trip p.x)}"
684 %aura "aura @{(trip p.x)}"
1535 %aura "aura @{(trip p.x)}"
685 %tvar "tvar {(trip p.x)}"
1536 %tvar "tvar {(trip p.x)}"
1537+ %error "ERROR {p.x}"
686 ==
1538 ==
687::
1539::
688:: +show-module: the tree as S-expressions (format: section 4.2)
1540:: +show-module: the tree as S-expressions (format: section 4.2)
@@ -700,6 +1552,8 @@
700::
1552::
701:: +show-error: "<file>:<line>:<col>: <message>", the line, a caret
1553:: +show-error: "<file>:<line>:<col>: <message>", the line, a caret
702::
1554::
1555+:: In the excerpt a control character prints as a space (4.3).
1556+::
703++ show-error
1557++ show-error
704 |= [src=@t err=error]
1558 |= [src=@t err=error]
705 ^- @t
1559 ^- @t
@@ -707,6 +1561,9 @@
707 =/ text=@t
1561 =/ text=@t
708 ?: |(=(0 line.err) (gth line.err (lent lines))) ''
1562 ?: |(=(0 line.err) (gth line.err (lent lines))) ''
709 (snag (dec line.err) lines)
1563 (snag (dec line.err) lines)
1564+ =/ excerpt=tape
1565+ %+ turn (trip text)
1566+ |=(c=@tD ?:(|((lth c 32) =(127 c)) ' ' c))
710 %- crip
1567 %- crip
711 ;: weld
1568 ;: weld
712 (show-file file.err)
1569 (show-file file.err)
@@ -717,7 +1574,7 @@
717 ": "
1574 ": "
718 msg.err
1575 msg.err
719 "\0a"
1576 "\0a"
720− (trip text)
1577+ excerpt
721 "\0a"
1578 "\0a"
722 (reap (dec (max 1 col.err)) ' ')
1579 (reap (dec (max 1 col.err)) ' ')
723 "^"
1580 "^"
@@ -725,15 +1582,19 @@
725::
1582::
726:: +show-found: a token as error messages name it
1583:: +show-found: a token as error messages name it
727::
1584::
1585+:: A layout token with an empty span is at the end of the file (2.5).
1586+::
728++ show-found
1587++ show-found
729 |= t=token
1588 |= t=token
730 ^- tape
1589 ^- tape
731 =/ x=lexeme lex.t
1590 =/ x=lexeme lex.t
732 ?@ x
1591 ?@ x
1592+ ?: &(?=(?(%indent %dedent %newline) x) =(beg.at.t end.at.t))
1593+ "the end of the file"
733 ?+ x "`{(trip x)}`"
1594 ?+ x "`{(trip x)}`"
734 %indent "a deeper line"
1595 %indent "a deeper line"
735− %dedent "the end of the line"
1596+ %dedent "a shallower line"
736− %newline "the end of the line"
1597+ %newline "a line at the same depth"
737 ==
1598 ==
738 ?- -.x
1599 ?- -.x
739 %name "`{(trip p.x)}`"
1600 %name "`{(trip p.x)}`"
@@ -746,17 +1607,19 @@
746 %knot "`{(trip p.x)}`"
1607 %knot "`{(trip p.x)}`"
747 %aura "`@{(trip p.x)}`"
1608 %aura "`@{(trip p.x)}`"
748 %tvar "`{(trip p.x)}`"
1609 %tvar "`{(trip p.x)}`"
1610+ %error "an error"
749 ==
1611 ==
750::
1612::
751−:: +where: where an error at a token points
1613+:: +where: where a token is, for errors and the token printer
752::
1614::
753−:: At the token's start; for NEWLINE and DEDENT that is the end of the
1615+:: At the token's start; for a layout token, at the end of its span:
754−:: previous line's code. For INDENT, the start of the deeper line.
1616+:: the start of the line it begins, or at the end of the file just
1617+:: past the last token (2.4, 2.5).
755::
1618::
756++ where
1619++ where
757 |= t=token
1620 |= t=token
758 ^- loc
1621 ^- loc
759− ?: ?=(%indent lex.t) end.at.t
1622+ ?: ?=(?(%indent %dedent %newline) lex.t) end.at.t
760 beg.at.t
1623 beg.at.t
761::
1624::
762++ show-loc
1625++ show-loc
@@ -984,6 +1847,7 @@
984 %bind (nod "bind" at.s (trip name.s) ~)
1847 %bind (nod "bind" at.s (trip name.s) ~)
985 %face (nod "face" at.s (trip name.s) ~[(sexp-shape shape.s)])
1848 %face (nod "face" at.s (trip name.s) ~[(sexp-shape shape.s)])
986 %pun (nod "pun" at.s (trip name.s) ~)
1849 %pun (nod "pun" at.s (trip name.s) ~)
1850+ %cell (nod "cell" at.s "" (turn items.s sexp-sample))
987 %bare (sexp-shape shape.s)
1851 %bare (sexp-shape shape.s)
988 ==
1852 ==
989::
1853::
@@ -1042,7 +1906,8 @@
1042 %& (next p.res)
1906 %& (next p.res)
1043 ==
1907 ==
1044::
1908::
1045−:: +span-of: the span of any node: every node is [%tag at=span …]
1909+:: +span-of: the span of a tagged node, [%tag at=span …]; an +item,
1910+:: +edit or +arm has its span at its head, at.node
1046::
1911::
1047++ span-of
1912++ span-of
1048 |* node=[@ span *]
1913 |* node=[@ span *]
@@ -1051,10 +1916,35 @@
1051::
1916::
1052:: +fail: the error "expected <want>, found <the next token>"
1917:: +fail: the error "expected <want>, found <the next token>"
1053::
1918::
1919+:: At an error token, the layout pass's error instead (2.0). The token
1920+:: list always ends with NEWLINE or an error token (2.5), and the
1921+:: parser stops at either, so it never runs out; if it did, the error
1922+:: would sit at 1:1.
1923+::
1054++ fail
1924++ fail
1055 |= [file=path toks=(list token) want=tape]
1925 |= [file=path toks=(list token) want=tape]
1056 ^- [%| p=error]
1926 ^- [%| p=error]
1057 ?~ toks [%| file 1 1 "expected {want}, found the end of the tokens"]
1927 ?~ toks [%| file 1 1 "expected {want}, found the end of the tokens"]
1928+ ?: ?=([%error *] lex.i.toks)
1929+ [%| file line.beg.at.i.toks col.beg.at.i.toks p.lex.i.toks]
1058 =/ l=loc (where i.toks)
1930 =/ l=loc (where i.toks)
1059 [%| file line.l col.l "expected {want}, found {(show-found i.toks)}"]
1931 [%| file line.l col.l "expected {want}, found {(show-found i.toks)}"]
1932+::
1933+:: +fail-space: a tight form found a space before its next token
1934+::
1935+:: The error sits where the space starts, just past prev, the token
1936+:: that needs its next one at once (section 3, Errors). If the next
1937+:: token is a layout or error token, it is +fail's error instead.
1938+::
1939+++ fail-space
1940+ |= [file=path prev=token toks=(list token) want=tape]
1941+ ^- [%| p=error]
1942+ ?: ?| ?=(~ toks)
1943+ ?=(?(%indent %dedent %newline) lex.i.toks)
1944+ ?=([%error *] lex.i.toks)
1945+ ==
1946+ (fail file toks want)
1947+ :+ %| file
1948+ :+ line.end.at.prev col.end.at.prev
1949+ "expected {want} right after {(show-found prev)}, found a space"
1060--
1950--
tests/golden/doc-core-02-update/tokens.txtnew file+142
@@ -0,0 +1,142 @@
1+1:1 glyph ++
2+1:4 name update
3+1:11 glyph |=
4+1:14 glyph [
5+1:15 tight glyph =
6+1:16 tight name msg
7+1:20 name m
8+1:21 tight glyph =
9+1:22 tight name model
10+1:27 tight glyph ]
11+2:3 INDENT
12+2:3 glyph ?-
13+2:6 name msg
14+3:5 INDENT
15+3:5 glyph [
16+3:6 tight lit %typed
17+3:13 name t
18+3:14 tight glyph ]
19+4:7 INDENT
20+4:7 glyph ?-
21+4:10 glyph (
22+4:11 tight name gth
23+4:15 glyph (
24+4:16 tight name lent
25+4:21 glyph (
26+4:22 tight name tuba
27+4:27 glyph (
28+4:28 tight name trip
29+4:33 name t
30+4:34 tight glyph )
31+4:35 tight glyph )
32+4:36 tight glyph )
33+4:38 lit 80
34+4:40 tight glyph )
35+5:9 INDENT
36+5:9 lit %.y
37+5:14 glyph [
38+5:15 tight name m
39+5:16 tight glyph (
40+5:17 tight name draft
41+5:22 tight glyph =
42+5:23 tight name t
43+5:25 name error
44+5:30 tight glyph =
45+5:31 tight glyph `
46+5:32 tight str "Too long"
47+5:42 tight glyph )
48+5:44 lit ~
49+5:45 tight glyph ]
50+6:9 NEWLINE
51+6:9 lit %.n
52+6:14 glyph [
53+6:15 tight name m
54+6:16 tight glyph (
55+6:17 tight name draft
56+6:22 tight glyph =
57+6:23 tight name t
58+6:25 name error
59+6:30 tight glyph =
60+6:31 tight lit ~
61+6:32 tight glyph )
62+6:34 lit ~
63+6:35 tight glyph ]
64+7:5 DEDENT
65+7:5 DEDENT
66+7:5 NEWLINE
67+7:5 lit %submit
68+7:20 glyph [
69+7:21 tight name m
70+7:22 tight glyph (
71+7:23 tight name draft
72+7:28 tight glyph =
73+7:29 tight str ""
74+7:31 tight glyph )
75+7:33 glyph ~[
76+7:35 tight glyph [
77+7:36 tight lit %poke
78+7:42 glyph (
79+7:43 tight wing todo-action.todo
80+7:60 glyph [
81+7:61 tight lit %add
82+7:66 wing draft.m
83+7:73 tight glyph ]
84+7:74 tight glyph )
85+7:76 glyph |=
86+7:78 tight lit %acked
87+7:84 tight glyph ]
88+7:85 tight glyph ]
89+7:86 tight glyph ]
90+8:5 NEWLINE
91+8:5 glyph [
92+8:6 tight lit %toggled
93+8:15 name id
94+8:17 tight glyph ]
95+8:20 glyph [
96+8:21 tight name m
97+8:23 glyph ~[
98+8:25 tight glyph [
99+8:26 tight lit %poke
100+8:32 glyph (
101+8:33 tight wing todo-action.todo
102+8:50 glyph [
103+8:51 tight lit %toggle
104+8:59 name id
105+8:61 tight glyph ]
106+8:62 tight glyph )
107+8:64 glyph |=
108+8:66 tight lit %acked
109+8:72 tight glyph ]
110+8:73 tight glyph ]
111+8:74 tight glyph ]
112+9:5 NEWLINE
113+9:5 glyph [
114+9:6 tight lit %got
115+9:11 name ts
116+9:13 tight glyph ]
117+9:20 glyph [
118+9:21 tight name m
119+9:22 tight glyph (
120+9:23 tight name todos
121+9:28 tight glyph =
122+9:29 tight name ts
123+9:31 tight glyph )
124+9:33 lit ~
125+9:34 tight glyph ]
126+10:5 NEWLINE
127+10:5 glyph [
128+10:6 tight lit %acked
129+10:13 name err
130+10:16 tight glyph ]
131+10:20 glyph [
132+10:21 tight name m
133+10:22 tight glyph (
134+10:23 tight name error
135+10:28 tight glyph =
136+10:29 tight name err
137+10:32 tight glyph )
138+10:34 lit ~
139+10:35 tight glyph ]
140+10:36 DEDENT
141+10:36 DEDENT
142+10:36 NEWLINE
tests/golden/doc-grammar-01-imports/tokens.txtnew file+15
@@ -0,0 +1,15 @@
1+1:1 glyph /-
2+1:5 name todo
3+2:1 NEWLINE
4+2:1 glyph /%
5+2:5 lit %todo-action
6+3:1 NEWLINE
7+3:1 glyph /=
8+3:5 name card
9+3:13 glyph /
10+3:14 tight knot ui
11+3:16 tight glyph /
12+3:17 tight knot components
13+3:27 tight glyph /
14+3:28 tight knot card
15+3:32 NEWLINE
tests/golden/doc-grammar-02-buttons/tokens.txtnew file+50
@@ -0,0 +1,50 @@
1+2:1 glyph ++
2+2:4 name add-button
3+2:15 glyph |=
4+2:18 name label
5+2:23 tight glyph =
6+2:24 tight aura @t
7+3:3 INDENT
8+3:3 name button
9+3:10 name label
10+3:16 lit %add
11+4:1 DEDENT
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name labelled
15+4:13 glyph |=
16+4:16 glyph [
17+4:17 tight name label
18+4:22 tight glyph =
19+4:23 tight aura @t
20+4:26 name msg
21+4:29 tight glyph =
22+4:30 tight tvar M
23+4:31 tight glyph ]
24+5:3 INDENT
25+5:3 name button
26+5:10 name label
27+5:16 name msg
28+6:1 DEDENT
29+6:1 NEWLINE
30+6:1 glyph ++
31+6:4 name wide
32+6:10 glyph ^-
33+6:13 glyph (
34+6:14 tight name list
35+6:19 name attr
36+6:23 tight glyph )
37+7:3 INDENT
38+7:3 glyph ~[
39+7:5 tight name width
40+7:10 tight glyph +
41+7:11 tight glyph [
42+7:12 tight lit %fill
43+7:18 lit 1
44+7:19 tight glyph ]
45+7:21 name pad
46+7:24 tight glyph +
47+7:25 tight lit %s2
48+7:28 tight glyph ]
49+7:29 DEDENT
50+7:29 NEWLINE
tests/golden/doc-grammar-03-view-day/tokens.txtnew file+36
@@ -0,0 +1,36 @@
1+1:1 glyph ++
2+1:4 name view
3+1:9 glyph |=
4+1:12 glyph [
5+1:13 tight name day
6+1:16 tight glyph =
7+1:17 tight aura @da
8+1:21 name n
9+1:22 tight glyph =
10+1:23 tight aura @ud
11+1:26 tight glyph ]
12+2:3 INDENT
13+2:3 name column
14+2:10 glyph ~[
15+2:12 tight name gap
16+2:15 tight glyph +
17+2:16 tight lit %s1
18+2:19 tight glyph ]
19+2:21 glyph ~[
20+3:5 INDENT
21+3:5 glyph (
22+3:6 tight name text
23+3:11 str-head "Updated "
24+3:21 tight name day
25+3:24 tight str-tail ""
26+3:26 tight glyph )
27+4:5 NEWLINE
28+4:5 glyph (
29+4:6 tight name text
30+4:11 str-head ""
31+4:13 tight name n
32+4:14 tight str-tail " items"
33+4:22 tight glyph )
34+4:23 DEDENT
35+4:23 DEDENT
36+4:23 NEWLINE
tests/golden/doc-grammar-04-step/tokens.txtnew file+86
@@ -0,0 +1,86 @@
1+1:1 glyph +$
2+1:4 name step
3+1:9 glyph $?
4+2:3 INDENT
5+2:3 glyph [
6+2:4 tight lit %move
7+2:10 lit %left
8+2:16 name n
9+2:17 tight glyph =
10+2:18 tight aura @ud
11+2:21 tight glyph ]
12+3:3 NEWLINE
13+3:3 glyph [
14+3:4 tight lit %move
15+3:10 lit %right
16+3:17 name n
17+3:18 tight glyph =
18+3:19 tight aura @ud
19+3:22 tight glyph ]
20+4:3 NEWLINE
21+4:3 glyph [
22+4:4 tight name text
23+4:8 tight glyph =
24+4:9 tight aura @t
25+4:12 lit %draft
26+4:18 tight glyph ]
27+5:3 NEWLINE
28+5:3 glyph [
29+5:4 tight name text
30+5:8 tight glyph =
31+5:9 tight aura @t
32+5:12 lit %sent
33+5:18 name at
34+5:20 tight glyph =
35+5:21 tight aura @da
36+5:24 tight glyph ]
37+6:3 NEWLINE
38+6:3 lit %stop
39+8:1 DEDENT
40+8:1 NEWLINE
41+8:1 glyph ++
42+8:4 name describe
43+8:13 glyph |=
44+8:16 name s
45+8:17 tight glyph =
46+8:18 tight name step
47+9:3 INDENT
48+9:3 glyph ?-
49+9:6 name s
50+10:5 INDENT
51+10:5 glyph [
52+10:6 tight lit %move
53+10:12 lit %left
54+10:18 name n
55+10:19 tight glyph ]
56+10:23 str-head "left "
57+10:30 tight name n
58+10:31 tight str-tail ""
59+11:5 NEWLINE
60+11:5 glyph [
61+11:6 tight lit %move
62+11:12 lit %right
63+11:19 name n
64+11:20 tight glyph ]
65+11:23 str-head "right "
66+11:31 tight name n
67+11:32 tight str-tail ""
68+12:5 NEWLINE
69+12:5 glyph [
70+12:6 tight name t
71+12:8 lit %draft
72+12:14 tight glyph ]
73+12:23 name t
74+13:5 NEWLINE
75+13:5 glyph [
76+13:6 tight name t
77+13:8 lit %sent
78+13:14 name at
79+13:16 tight glyph ]
80+13:23 name t
81+14:5 NEWLINE
82+14:5 lit %stop
83+14:23 str "stop"
84+14:29 DEDENT
85+14:29 DEDENT
86+14:29 NEWLINE
tests/golden/doc-grammar-06-cart-store/tokens.txtnew file+91
@@ -0,0 +1,91 @@
1+2:1 glyph +$
2+2:4 name state
3+2:10 glyph [
4+2:11 tight name items
5+2:16 tight glyph =
6+2:17 tight glyph (
7+2:18 tight name list
8+2:23 aura @t
9+2:25 tight glyph )
10+2:27 name open
11+2:31 tight glyph =
12+2:32 tight glyph ?
13+2:33 tight glyph ]
14+3:1 NEWLINE
15+3:1 glyph +$
16+3:4 name cart-action
17+3:16 glyph $?
18+4:3 INDENT
19+4:3 glyph [
20+4:4 tight lit %add
21+4:9 name item
22+4:13 tight glyph =
23+4:14 tight aura @t
24+4:16 tight glyph ]
25+5:3 NEWLINE
26+5:3 lit %toggle
27+6:1 DEDENT
28+6:1 NEWLINE
29+6:1 glyph +$
30+6:4 name poke
31+6:9 name cart-action
32+8:1 NEWLINE
33+8:1 glyph ++
34+8:4 name main
35+8:9 glyph (
36+8:10 tight name store
37+8:16 name init
38+8:21 name update
39+8:27 tight glyph )
40+9:1 NEWLINE
41+9:1 glyph ++
42+9:4 name init
43+9:9 glyph ^-
44+9:12 name state
45+9:18 glyph [
46+9:19 tight lit ~
47+9:21 lit %.n
48+9:24 tight glyph ]
49+10:1 NEWLINE
50+10:1 glyph ++
51+10:4 name update
52+10:11 glyph |=
53+10:14 glyph [
54+10:15 tight name a
55+10:16 tight glyph =
56+10:17 tight name cart-action
57+10:29 name s
58+10:30 tight glyph =
59+10:31 tight name state
60+10:36 tight glyph ]
61+11:3 INDENT
62+11:3 glyph ?-
63+11:6 name a
64+12:5 INDENT
65+12:5 glyph [
66+12:6 tight lit %add
67+12:11 name item
68+12:15 tight glyph ]
69+12:18 name s
70+12:19 tight glyph (
71+12:20 tight name items
72+12:25 tight glyph =
73+12:26 tight glyph [
74+12:27 tight name item
75+12:32 wing items.s
76+12:39 tight glyph ]
77+12:40 tight glyph )
78+13:5 NEWLINE
79+13:5 lit %toggle
80+13:18 name s
81+13:19 tight glyph (
82+13:20 tight name open
83+13:24 tight glyph =
84+13:25 tight glyph (
85+13:26 tight name not
86+13:30 wing open.s
87+13:36 tight glyph )
88+13:37 tight glyph )
89+13:38 DEDENT
90+13:38 DEDENT
91+13:38 NEWLINE
tests/golden/doc-grammar-07-basket/tokens.txtnew file+226
@@ -0,0 +1,226 @@
1+2:1 glyph /=
2+2:5 name cart
3+2:11 glyph /
4+2:12 tight knot ui
5+2:14 tight glyph /
6+2:15 tight knot stores
7+2:21 tight glyph /
8+2:22 tight knot cart
9+4:1 NEWLINE
10+4:1 glyph ++
11+4:4 name main
12+4:9 glyph (
13+4:10 tight name program
14+4:18 name init
15+4:23 name update
16+4:30 name view
17+4:35 name subs
18+4:39 tight glyph )
19+6:1 NEWLINE
20+6:1 glyph +$
21+6:4 name model
22+6:10 glyph [
23+6:11 tight name cart
24+6:15 tight glyph =
25+6:16 tight wing state.cart
26+6:27 name note
27+6:31 tight glyph =
28+6:32 tight aura @t
29+6:34 tight glyph ]
30+7:1 NEWLINE
31+7:1 glyph +$
32+7:4 name msg
33+7:8 glyph $?
34+8:3 INDENT
35+8:3 glyph [
36+8:4 tight lit %noted
37+8:11 name text
38+8:15 tight glyph =
39+8:16 tight aura @t
40+8:18 tight glyph ]
41+9:3 NEWLINE
42+9:3 lit %add
43+10:3 NEWLINE
44+10:3 lit %toggle
45+11:3 NEWLINE
46+11:3 glyph [
47+11:4 tight lit %got
48+11:9 name cart
49+11:13 tight glyph =
50+11:14 tight wing state.cart
51+11:24 tight glyph ]
52+12:3 NEWLINE
53+12:3 glyph [
54+12:4 tight lit %acked
55+12:11 name err
56+12:14 tight glyph =
57+12:15 tight glyph (
58+12:16 tight name unit
59+12:21 aura @t
60+12:23 tight glyph )
61+12:24 tight glyph ]
62+14:1 DEDENT
63+14:1 NEWLINE
64+14:1 glyph ++
65+14:4 name init
66+14:9 glyph |=
67+14:12 lit ~
68+15:3 INDENT
69+15:3 glyph [
70+15:4 tight glyph [
71+15:5 tight lit ~
72+15:7 lit %.n
73+15:10 tight glyph ]
74+15:12 str ""
75+15:14 tight glyph ]
76+17:1 DEDENT
77+17:1 NEWLINE
78+17:1 glyph ++
79+17:4 name update
80+17:11 glyph |=
81+17:14 glyph [
82+17:15 tight glyph =
83+17:16 tight name msg
84+17:20 name m
85+17:21 tight glyph =
86+17:22 tight name model
87+17:27 tight glyph ]
88+18:3 INDENT
89+18:3 glyph ?-
90+18:6 name msg
91+19:5 INDENT
92+19:5 glyph [
93+19:6 tight lit %noted
94+19:13 name t
95+19:14 tight glyph ]
96+19:20 glyph [
97+19:21 tight name m
98+19:22 tight glyph (
99+19:23 tight name note
100+19:27 tight glyph =
101+19:28 tight name t
102+19:29 tight glyph )
103+19:31 lit ~
104+19:32 tight glyph ]
105+20:5 NEWLINE
106+20:5 lit %add
107+20:20 glyph [
108+20:21 tight name m
109+20:22 tight glyph (
110+20:23 tight name note
111+20:27 tight glyph =
112+20:28 tight str ""
113+20:30 tight glyph )
114+20:32 glyph ~[
115+20:34 tight glyph [
116+20:35 tight lit %poke
117+20:41 glyph (
118+20:42 tight wing cart-action.cart
119+20:59 glyph [
120+20:60 tight lit %add
121+20:65 wing note.m
122+20:71 tight glyph ]
123+20:72 tight glyph )
124+20:74 glyph |=
125+20:76 tight lit %acked
126+20:82 tight glyph ]
127+20:83 tight glyph ]
128+20:84 tight glyph ]
129+21:5 NEWLINE
130+21:5 lit %toggle
131+21:20 glyph [
132+21:21 tight name m
133+21:23 glyph ~[
134+21:25 tight glyph [
135+21:26 tight lit %poke
136+21:32 glyph (
137+21:33 tight wing cart-action.cart
138+21:50 lit %toggle
139+21:57 tight glyph )
140+21:59 glyph |=
141+21:61 tight lit %acked
142+21:67 tight glyph ]
143+21:68 tight glyph ]
144+21:69 tight glyph ]
145+22:5 NEWLINE
146+22:5 glyph [
147+22:6 tight lit %got
148+22:11 name c
149+22:12 tight glyph ]
150+22:20 glyph [
151+22:21 tight name m
152+22:22 tight glyph (
153+22:23 tight name cart
154+22:27 tight glyph =
155+22:28 tight name c
156+22:29 tight glyph )
157+22:31 lit ~
158+22:32 tight glyph ]
159+23:5 NEWLINE
160+23:5 glyph [
161+23:6 tight lit %acked
162+23:13 name err
163+23:16 tight glyph ]
164+23:20 glyph [
165+23:21 tight name m
166+23:23 lit ~
167+23:24 tight glyph ]
168+25:1 DEDENT
169+25:1 DEDENT
170+25:1 NEWLINE
171+25:1 glyph ++
172+25:4 name subs
173+25:9 glyph |=
174+25:12 name m
175+25:13 tight glyph =
176+25:14 tight name model
177+26:3 INDENT
178+26:3 glyph ~[
179+26:5 tight glyph [
180+26:6 tight lit %watch
181+26:13 glyph (
182+26:14 tight wing state.cart
183+26:25 glyph |=
184+26:27 tight lit %got
185+26:31 tight glyph )
186+26:32 tight glyph ]
187+26:33 tight glyph ]
188+28:1 DEDENT
189+28:1 NEWLINE
190+28:1 glyph ++
191+28:4 name view
192+28:9 glyph |=
193+28:12 name m
194+28:13 tight glyph =
195+28:14 tight name model
196+29:3 INDENT
197+29:3 name column
198+29:10 glyph ~[
199+29:12 tight name gap
200+29:15 tight glyph +
201+29:16 tight lit %s1
202+29:19 tight glyph ]
203+29:21 glyph ~[
204+30:5 INDENT
205+30:5 glyph (
206+30:6 tight name text
207+30:11 str-head ""
208+30:13 tight glyph (
209+30:14 tight name lent
210+30:19 wing items.cart.m
211+30:31 tight glyph )
212+30:32 tight str-tail " items"
213+30:40 tight glyph )
214+31:5 NEWLINE
215+31:5 name field
216+31:11 str "Item"
217+31:18 wing note.m
218+31:25 glyph |=
219+31:27 tight lit %noted
220+32:5 NEWLINE
221+32:5 name button
222+32:12 str "Add"
223+32:18 lit %add
224+32:22 DEDENT
225+32:22 DEDENT
226+32:22 NEWLINE
tests/golden/doc-overview-01-cmd-sub/tokens.txtnew file+104
@@ -0,0 +1,104 @@
1+1:1 glyph +$
2+1:4 name cmd
3+1:8 glyph |$
4+1:11 glyph [
5+1:12 tight tvar M
6+1:13 tight glyph ]
7+1:15 glyph $?
8+2:3 INDENT
9+2:3 glyph [
10+2:4 tight lit %poke
11+2:10 name p
12+2:11 tight glyph =
13+2:12 tight name poke
14+2:17 name reply
15+2:22 tight glyph =
16+2:23 tight glyph $-(
17+2:26 tight glyph (
18+2:27 tight name unit
19+2:32 aura @t
20+2:34 tight glyph )
21+2:36 tvar M
22+2:37 tight glyph )
23+2:38 tight glyph ]
24+3:3 NEWLINE
25+3:3 glyph [
26+3:4 tight lit %go
27+3:8 name url
28+3:11 tight glyph =
29+3:12 tight aura @t
30+3:14 tight glyph ]
31+4:3 NEWLINE
32+4:3 glyph [
33+4:4 tight lit %wait
34+4:10 name gap
35+4:13 tight glyph =
36+4:14 tight aura @dr
37+4:18 name msg
38+4:21 tight glyph =
39+4:22 tight tvar M
40+4:23 tight glyph ]
41+5:3 NEWLINE
42+5:3 glyph [
43+5:4 tight lit %now
44+5:9 name reply
45+5:14 tight glyph =
46+5:15 tight glyph $-(
47+5:18 tight aura @da
48+5:22 tvar M
49+5:23 tight glyph )
50+5:24 tight glyph ]
51+6:3 NEWLINE
52+6:3 glyph [
53+6:4 tight lit %who
54+6:9 name reply
55+6:14 tight glyph =
56+6:15 tight glyph $-(
57+6:18 tight aura @p
58+6:21 tvar M
59+6:22 tight glyph )
60+6:23 tight glyph ]
61+7:1 DEDENT
62+7:1 NEWLINE
63+7:1 glyph +$
64+7:4 name sub
65+7:8 glyph |$
66+7:11 glyph [
67+7:12 tight tvar M
68+7:13 tight glyph ]
69+7:15 glyph $?
70+8:3 INDENT
71+8:3 glyph [
72+8:4 tight lit %watch
73+8:11 name a
74+8:12 tight glyph =
75+8:13 tight glyph (
76+8:14 tight name ask
77+8:18 tvar M
78+8:19 tight glyph )
79+8:20 tight glyph ]
80+9:3 NEWLINE
81+9:3 glyph [
82+9:4 tight lit %every
83+9:11 name gap
84+9:14 tight glyph =
85+9:15 tight aura @dr
86+9:19 name reply
87+9:24 tight glyph =
88+9:25 tight glyph $-(
89+9:28 tight aura @da
90+9:32 tvar M
91+9:33 tight glyph )
92+9:34 tight glyph ]
93+10:3 NEWLINE
94+10:3 glyph [
95+10:4 tight lit %url
96+10:9 name reply
97+10:14 tight glyph =
98+10:15 tight glyph $-(
99+10:18 tight name path
100+10:23 tvar M
101+10:24 tight glyph )
102+10:25 tight glyph ]
103+10:26 DEDENT
104+10:26 NEWLINE
tests/golden/doc-overview-02-theme/tokens.txtnew file+88
@@ -0,0 +1,88 @@
1+1:1 glyph ++
2+1:4 name theme
3+1:11 glyph ^-
4+1:14 name theme
5+2:3 INDENT
6+2:3 glyph [
7+2:5 name space
8+2:10 tight glyph =
9+2:11 tight glyph [
10+2:12 tight name s1
11+2:14 tight glyph =
12+2:15 tight str "4px"
13+2:21 name s2
14+2:23 tight glyph =
15+2:24 tight str "8px"
16+2:30 name s3
17+2:32 tight glyph =
18+2:33 tight str "16px"
19+2:39 tight glyph ]
20+3:5 INDENT
21+3:5 name tones
22+3:10 tight glyph =
23+3:11 tight glyph [
24+3:12 tight name normal
25+3:18 tight glyph =
26+3:19 tight str "#222"
27+3:26 name background
28+3:36 tight glyph =
29+3:37 tight str "#fff"
30+3:44 name accent
31+3:50 tight glyph =
32+3:51 tight str "#17734f"
33+3:61 name danger
34+3:67 tight glyph =
35+3:68 tight str "#b3261e"
36+3:78 name muted
37+3:83 tight glyph =
38+3:84 tight str "#5f5f5f"
39+3:93 tight glyph ]
40+4:5 NEWLINE
41+4:5 name wide
42+4:9 tight glyph =
43+4:10 tight str "60rem"
44+5:5 NEWLINE
45+5:5 name lang
46+5:9 tight glyph =
47+5:10 tight str "en"
48+6:5 NEWLINE
49+6:5 name zone
50+6:9 tight glyph =
51+6:10 tight str "UTC"
52+7:5 NEWLINE
53+7:5 name font
54+7:9 tight glyph =
55+7:10 tight glyph `
56+7:11 tight glyph %/
57+7:13 tight knot static
58+7:19 tight glyph /
59+7:20 tight knot fonts
60+7:25 tight glyph /
61+7:26 tight knot inter.woff2
62+8:5 NEWLINE
63+8:5 name dark
64+8:9 tight glyph =
65+8:10 tight glyph [
66+8:11 tight name tones
67+8:16 tight glyph =
68+8:17 tight glyph [
69+8:18 tight name normal
70+8:24 tight glyph =
71+8:25 tight str "#eee"
72+8:32 name background
73+8:42 tight glyph =
74+8:43 tight str "#111"
75+8:50 name accent
76+8:56 tight glyph =
77+8:57 tight str "#4c9"
78+8:64 name danger
79+8:70 tight glyph =
80+8:71 tight str "#f28b82"
81+8:81 name muted
82+8:86 tight glyph =
83+8:87 tight str "#aaa"
84+8:93 tight glyph ]
85+8:94 tight glyph ]
86+8:95 DEDENT
87+8:95 DEDENT
88+8:95 NEWLINE
tests/golden/doc-overview-04-todo-api/tokens.txtnew file+59
@@ -0,0 +1,59 @@
1+2:1 glyph /-
2+2:5 name todo
3+3:1 NEWLINE
4+3:1 glyph /%
5+3:5 lit %todo-action
6+4:1 NEWLINE
7+4:1 glyph /%
8+4:5 lit %todos
9+5:1 NEWLINE
10+5:1 glyph /%
11+5:5 lit %todo-update
12+6:1 NEWLINE
13+6:1 glyph /%
14+6:5 lit %todo-item
15+8:1 NEWLINE
16+8:1 glyph +$
17+8:4 name item
18+8:9 wing item.todo
19+9:1 NEWLINE
20+9:1 glyph +$
21+9:4 name poke
22+9:9 name todo-action
23+10:1 NEWLINE
24+10:1 glyph +$
25+10:4 name paths
26+10:10 glyph $?
27+11:3 INDENT
28+11:3 glyph [
29+11:4 tight lit %todos
30+11:11 glyph /
31+11:12 tight knot todos
32+11:18 name todos
33+11:23 tight glyph ]
34+12:3 NEWLINE
35+12:3 glyph [
36+12:4 tight lit %changes
37+12:13 glyph /
38+12:14 tight knot changes
39+12:22 glyph (
40+12:23 tight name facts
41+12:29 name todos
42+12:35 name todo-update
43+12:46 tight glyph )
44+12:47 tight glyph ]
45+13:3 NEWLINE
46+13:3 glyph [
47+13:4 tight lit %todo
48+13:10 glyph /
49+13:11 tight knot todo
50+13:15 tight glyph /
51+13:16 tight glyph [
52+13:17 tight name id
53+13:19 tight glyph =
54+13:20 tight aura @ud
55+13:23 tight glyph ]
56+13:25 name todo-item
57+13:34 tight glyph ]
58+13:35 DEDENT
59+13:35 NEWLINE
tests/golden/doc-overview-08-about/tokens.txtnew file+51
@@ -0,0 +1,51 @@
1+1:1 glyph ++
2+1:4 name main
3+1:9 name view
4+3:1 NEWLINE
5+3:1 glyph ++
6+3:4 name view
7+4:3 INDENT
8+4:3 name column
9+4:10 glyph ~[
10+4:12 tight name width
11+4:17 tight glyph +
12+4:18 tight glyph [
13+4:19 tight lit %fill
14+4:25 lit 1
15+4:26 tight glyph ]
16+4:28 name pad
17+4:31 tight glyph +
18+4:32 tight lit %s3
19+4:36 name gap
20+4:39 tight glyph +
21+4:40 tight lit %s2
22+4:43 tight glyph ]
23+4:45 glyph ~[
24+5:5 INDENT
25+5:5 name heading
26+5:13 lit 1
27+5:15 str "About this ship"
28+6:5 NEWLINE
29+6:5 name para
30+6:10 glyph ~[
31+6:12 tight glyph (
32+6:13 tight name text
33+6:18 str "Hosted on Urbit. This page ships no JavaScript."
34+6:67 tight glyph )
35+6:68 tight glyph ]
36+7:5 NEWLINE
37+7:5 name el
38+7:8 glyph ~[
39+7:10 tight name tone
40+7:14 tight glyph +
41+7:15 tight lit %accent
42+7:22 tight glyph ]
43+7:24 glyph (
44+7:25 tight name link
45+7:30 glyph %/
46+7:32 tight knot blog
47+7:37 str "Read the blog"
48+7:52 tight glyph )
49+7:53 DEDENT
50+7:53 DEDENT
51+7:53 NEWLINE
tests/golden/doc-overview-09-blog-index/tokens.txtnew file+62
@@ -0,0 +1,62 @@
1+1:1 glyph /-
2+1:5 name blog
3+2:1 NEWLINE
4+2:1 glyph /=
5+2:5 name api
6+2:11 glyph /
7+2:12 tight knot ui
8+2:14 tight glyph /
9+2:15 tight knot api
10+2:18 tight glyph /
11+2:19 tight knot blog
12+3:1 NEWLINE
13+3:1 glyph /=
14+3:5 name card
15+3:11 glyph /
16+3:12 tight knot ui
17+3:14 tight glyph /
18+3:15 tight knot components
19+3:25 tight glyph /
20+3:26 tight knot card
21+5:1 NEWLINE
22+5:1 glyph ++
23+5:4 name main
24+5:9 glyph (
25+5:10 tight name page
26+5:15 name load
27+5:20 name view
28+5:24 tight glyph )
29+6:1 NEWLINE
30+6:1 glyph ++
31+6:4 name load
32+6:9 glyph |=(
33+6:12 tight lit ~
34+6:14 glyph (
35+6:15 tight wing posts.api
36+6:25 name same
37+6:29 tight glyph )
38+6:30 tight glyph )
39+8:1 NEWLINE
40+8:1 glyph ++
41+8:4 name view
42+8:9 glyph |=
43+8:12 name ps
44+8:14 tight glyph =
45+8:15 tight glyph (
46+8:16 tight name list
47+8:21 wing post.blog
48+8:30 tight glyph )
49+9:3 INDENT
50+9:3 name column
51+9:10 glyph ~[
52+9:12 tight name gap
53+9:15 tight glyph +
54+9:16 tight lit %s2
55+9:19 tight glyph ]
56+9:21 glyph (
57+9:22 tight name turn
58+9:27 name ps
59+9:30 wing card.card
60+9:39 tight glyph )
61+9:40 DEDENT
62+9:40 NEWLINE
tests/golden/doc-overview-10-todo-list/tokens.txtnew file+352
@@ -0,0 +1,352 @@
1+1:1 glyph /=
2+1:5 name todo
3+1:11 glyph /
4+1:12 tight knot ui
5+1:14 tight glyph /
6+1:15 tight knot api
7+1:18 tight glyph /
8+1:19 tight knot todo
9+3:1 NEWLINE
10+3:1 glyph ++
11+3:4 name main
12+3:9 glyph (
13+3:10 tight name program
14+3:18 name init
15+3:23 name update
16+3:30 name view
17+3:35 name subs
18+3:39 tight glyph )
19+5:1 NEWLINE
20+5:1 glyph +$
21+5:4 name model
22+5:10 glyph [
23+5:11 tight name todos
24+5:16 tight glyph =
25+5:17 tight glyph (
26+5:18 tight name list
27+5:23 wing item.todo
28+5:32 tight glyph )
29+5:34 name draft
30+5:39 tight glyph =
31+5:40 tight aura @t
32+5:43 name error
33+5:48 tight glyph =
34+5:49 tight glyph (
35+5:50 tight name unit
36+5:55 aura @t
37+5:57 tight glyph )
38+5:58 tight glyph ]
39+6:1 NEWLINE
40+6:1 glyph +$
41+6:4 name msg
42+6:8 glyph $?
43+7:3 INDENT
44+7:3 glyph [
45+7:4 tight lit %typed
46+7:11 name text
47+7:15 tight glyph =
48+7:16 tight aura @t
49+7:18 tight glyph ]
50+8:3 NEWLINE
51+8:3 lit %submit
52+9:3 NEWLINE
53+9:3 glyph [
54+9:4 tight lit %toggled
55+9:13 name id
56+9:15 tight glyph =
57+9:16 tight aura @ud
58+9:19 tight glyph ]
59+10:3 NEWLINE
60+10:3 glyph [
61+10:4 tight lit %got
62+10:9 name todos
63+10:14 tight glyph =
64+10:15 tight glyph (
65+10:16 tight name list
66+10:21 wing item.todo
67+10:30 tight glyph )
68+10:31 tight glyph ]
69+11:3 NEWLINE
70+11:3 glyph [
71+11:4 tight lit %acked
72+11:11 name err
73+11:14 tight glyph =
74+11:15 tight glyph (
75+11:16 tight name unit
76+11:21 aura @t
77+11:23 tight glyph )
78+11:24 tight glyph ]
79+13:1 DEDENT
80+13:1 NEWLINE
81+13:1 glyph ++
82+13:4 name init
83+13:9 glyph |=
84+13:12 name ts
85+13:14 tight glyph =
86+13:15 tight glyph (
87+13:16 tight name list
88+13:21 wing item.todo
89+13:30 tight glyph )
90+14:3 INDENT
91+14:3 glyph [
92+14:4 tight name ts
93+14:7 str ""
94+14:10 lit ~
95+14:11 tight glyph ]
96+16:1 DEDENT
97+16:1 NEWLINE
98+16:1 glyph ++
99+16:4 name update
100+16:11 glyph |=
101+16:14 glyph [
102+16:15 tight glyph =
103+16:16 tight name msg
104+16:20 name m
105+16:21 tight glyph =
106+16:22 tight name model
107+16:27 tight glyph ]
108+17:3 INDENT
109+17:3 glyph ?-
110+17:6 name msg
111+18:5 INDENT
112+18:5 glyph [
113+18:6 tight lit %typed
114+18:13 name t
115+18:14 tight glyph ]
116+19:7 INDENT
117+19:7 glyph ?-
118+19:10 glyph (
119+19:11 tight name gth
120+19:15 glyph (
121+19:16 tight name lent
122+19:21 glyph (
123+19:22 tight name tuba
124+19:27 glyph (
125+19:28 tight name trip
126+19:33 name t
127+19:34 tight glyph )
128+19:35 tight glyph )
129+19:36 tight glyph )
130+19:38 lit 80
131+19:40 tight glyph )
132+20:9 INDENT
133+20:9 lit %.y
134+20:14 glyph [
135+20:15 tight name m
136+20:16 tight glyph (
137+20:17 tight name draft
138+20:22 tight glyph =
139+20:23 tight name t
140+20:25 name error
141+20:30 tight glyph =
142+20:31 tight glyph `
143+20:32 tight str "Too long"
144+20:42 tight glyph )
145+20:44 lit ~
146+20:45 tight glyph ]
147+21:9 NEWLINE
148+21:9 lit %.n
149+21:14 glyph [
150+21:15 tight name m
151+21:16 tight glyph (
152+21:17 tight name draft
153+21:22 tight glyph =
154+21:23 tight name t
155+21:25 name error
156+21:30 tight glyph =
157+21:31 tight lit ~
158+21:32 tight glyph )
159+21:34 lit ~
160+21:35 tight glyph ]
161+22:5 DEDENT
162+22:5 DEDENT
163+22:5 NEWLINE
164+22:5 lit %submit
165+22:20 glyph [
166+22:21 tight name m
167+22:22 tight glyph (
168+22:23 tight name draft
169+22:28 tight glyph =
170+22:29 tight str ""
171+22:31 tight glyph )
172+22:33 glyph ~[
173+22:35 tight glyph [
174+22:36 tight lit %poke
175+22:42 glyph (
176+22:43 tight wing todo-action.todo
177+22:60 glyph [
178+22:61 tight lit %add
179+22:66 wing draft.m
180+22:73 tight glyph ]
181+22:74 tight glyph )
182+22:76 glyph |=
183+22:78 tight lit %acked
184+22:84 tight glyph ]
185+22:85 tight glyph ]
186+22:86 tight glyph ]
187+23:5 NEWLINE
188+23:5 glyph [
189+23:6 tight lit %toggled
190+23:15 name id
191+23:17 tight glyph ]
192+23:20 glyph [
193+23:21 tight name m
194+23:23 glyph ~[
195+23:25 tight glyph [
196+23:26 tight lit %poke
197+23:32 glyph (
198+23:33 tight wing todo-action.todo
199+23:50 glyph [
200+23:51 tight lit %toggle
201+23:59 name id
202+23:61 tight glyph ]
203+23:62 tight glyph )
204+23:64 glyph |=
205+23:66 tight lit %acked
206+23:72 tight glyph ]
207+23:73 tight glyph ]
208+23:74 tight glyph ]
209+24:5 NEWLINE
210+24:5 glyph [
211+24:6 tight lit %got
212+24:11 name ts
213+24:13 tight glyph ]
214+24:20 glyph [
215+24:21 tight name m
216+24:22 tight glyph (
217+24:23 tight name todos
218+24:28 tight glyph =
219+24:29 tight name ts
220+24:31 tight glyph )
221+24:33 lit ~
222+24:34 tight glyph ]
223+25:5 NEWLINE
224+25:5 glyph [
225+25:6 tight lit %acked
226+25:13 name err
227+25:16 tight glyph ]
228+25:20 glyph [
229+25:21 tight name m
230+25:22 tight glyph (
231+25:23 tight name error
232+25:28 tight glyph =
233+25:29 tight name err
234+25:32 tight glyph )
235+25:34 lit ~
236+25:35 tight glyph ]
237+27:1 DEDENT
238+27:1 DEDENT
239+27:1 NEWLINE
240+27:1 glyph ++
241+27:4 name subs
242+27:9 glyph |=
243+27:12 name m
244+27:13 tight glyph =
245+27:14 tight name model
246+28:3 INDENT
247+28:3 glyph ~[
248+28:5 tight glyph [
249+28:6 tight lit %watch
250+28:13 glyph (
251+28:14 tight wing todos.todo
252+28:25 glyph |=
253+28:27 tight lit %got
254+28:31 tight glyph )
255+28:32 tight glyph ]
256+28:33 tight glyph ]
257+30:1 DEDENT
258+30:1 NEWLINE
259+30:1 glyph ++
260+30:4 name view
261+30:9 glyph |=
262+30:12 name m
263+30:13 tight glyph =
264+30:14 tight name model
265+31:3 INDENT
266+31:3 name column
267+31:10 glyph ~[
268+31:12 tight name gap
269+31:15 tight glyph +
270+31:16 tight lit %s2
271+31:19 tight glyph ]
272+31:21 glyph ~[
273+32:5 INDENT
274+32:5 name heading
275+32:13 lit 2
276+32:15 str "Todos"
277+33:5 NEWLINE
278+33:5 name each
279+33:10 glyph (
280+33:11 tight name turn
281+33:16 wing todos.m
282+33:24 name row-of
283+33:30 tight glyph )
284+34:5 NEWLINE
285+34:5 name row
286+34:9 glyph ~[
287+34:11 tight name gap
288+34:14 tight glyph +
289+34:15 tight lit %s1
290+34:18 tight glyph ]
291+34:20 glyph ~[
292+35:7 INDENT
293+35:7 name el
294+35:10 glyph ~[
295+35:12 tight name width
296+35:17 tight glyph +
297+35:18 tight glyph [
298+35:19 tight lit %fill
299+35:25 lit 1
300+35:26 tight glyph ]
301+35:27 tight glyph ]
302+35:29 glyph (
303+35:30 tight name field
304+35:36 str "New todo"
305+35:47 wing draft.m
306+35:55 glyph |=
307+35:57 tight lit %typed
308+35:63 tight glyph )
309+36:7 NEWLINE
310+36:7 name button
311+36:14 str "Add"
312+36:20 lit %submit
313+37:5 DEDENT
314+37:5 NEWLINE
315+37:5 name el
316+37:8 glyph ~[
317+37:10 tight name tone
318+37:14 tight glyph +
319+37:15 tight lit %danger
320+37:22 tight glyph ]
321+37:24 glyph (
322+37:25 tight name text
323+37:30 glyph (
324+37:31 tight name fall
325+37:36 wing error.m
326+37:44 str ""
327+37:46 tight glyph )
328+37:47 tight glyph )
329+39:1 DEDENT
330+39:1 DEDENT
331+39:1 NEWLINE
332+39:1 glyph ++
333+39:4 name row-of
334+39:11 glyph |=
335+39:14 name t
336+39:15 tight glyph =
337+39:16 tight wing item.todo
338+40:3 INDENT
339+40:3 glyph [
340+40:4 tight wing id.t
341+40:9 glyph (
342+40:10 tight name toggle
343+40:17 wing done.t
344+40:24 wing text.t
345+40:31 glyph [
346+40:32 tight lit %toggled
347+40:41 wing id.t
348+40:45 tight glyph ]
349+40:46 tight glyph )
350+40:47 tight glyph ]
351+40:48 DEDENT
352+40:48 NEWLINE
tests/golden/doc-overview-11-index/tokens.txtnew file+62
@@ -0,0 +1,62 @@
1+1:1 glyph /=
2+1:5 name todo
3+1:16 glyph /
4+1:17 tight knot ui
5+1:19 tight glyph /
6+1:20 tight knot api
7+1:23 tight glyph /
8+1:24 tight knot todo
9+2:1 NEWLINE
10+2:1 glyph /=
11+2:5 name todo-list
12+2:16 glyph /
13+2:17 tight knot ui
14+2:19 tight glyph /
15+2:20 tight knot todo-list
16+4:1 NEWLINE
17+4:1 glyph ++
18+4:4 name main
19+4:9 glyph (
20+4:10 tight name page
21+4:15 name load
22+4:20 name view
23+4:24 tight glyph )
24+5:1 NEWLINE
25+5:1 glyph ++
26+5:4 name load
27+5:9 glyph |=(
28+5:12 tight lit ~
29+5:14 glyph (
30+5:15 tight wing todos.todo
31+5:26 name same
32+5:30 tight glyph )
33+5:31 tight glyph )
34+7:1 NEWLINE
35+7:1 glyph ++
36+7:4 name view
37+7:9 glyph |=
38+7:12 name ts
39+7:14 tight glyph =
40+7:15 tight glyph (
41+7:16 tight name list
42+7:21 wing item.todo
43+7:30 tight glyph )
44+8:3 INDENT
45+8:3 name column
46+8:10 glyph ~[
47+8:12 tight name pad
48+8:15 tight glyph +
49+8:16 tight lit %s3
50+8:19 tight glyph ]
51+8:21 glyph ~[
52+9:5 INDENT
53+9:5 name heading
54+9:13 lit 1
55+9:15 str "My ship"
56+10:5 NEWLINE
57+10:5 name island
58+10:12 wing main.todo-list
59+10:27 name ts
60+10:29 DEDENT
61+10:29 DEDENT
62+10:29 NEWLINE
tests/golden/inline-base32/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit 0v5.fdf99
4+1:15 NEWLINE
tests/golden/inline-call/tokens.txtnew file+6
@@ -0,0 +1,6 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name f
4+1:8 name a
5+1:10 name b
6+1:11 NEWLINE
tests/golden/inline-cell/tokens.txtnew file+19
@@ -0,0 +1,19 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph [
4+1:7 tight name a
5+1:9 name b
6+1:11 name c
7+1:12 tight glyph ]
8+2:1 NEWLINE
9+2:1 glyph ++
10+2:4 name y
11+2:6 glyph [
12+2:7 tight name text
13+2:11 tight glyph =
14+2:12 tight str "milk"
15+2:19 name done
16+2:23 tight glyph =
17+2:24 tight lit %.n
18+2:27 tight glyph ]
19+2:28 NEWLINE
tests/golden/inline-change-done/tokens.txtnew file+9
@@ -0,0 +1,9 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name m
4+1:7 tight glyph (
5+1:8 tight name done
6+1:12 tight glyph =
7+1:13 tight lit %.y
8+1:16 tight glyph )
9+1:17 NEWLINE
tests/golden/inline-change-draft/tokens.txtnew file+12
@@ -0,0 +1,12 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name m
4+1:7 tight glyph (
5+1:8 tight name draft
6+1:13 tight glyph =
7+1:14 tight str "x"
8+1:18 name error
9+1:23 tight glyph =
10+1:24 tight lit ~
11+1:25 tight glyph )
12+1:26 NEWLINE
tests/golden/inline-crash/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph !!
4+2:1 NEWLINE
5+2:1 glyph +$
6+2:4 name y
7+2:6 glyph !!
8+2:8 NEWLINE
tests/golden/inline-ctor-typed/tokens.txtnew file+29
@@ -0,0 +1,29 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 glyph |=
4+1:8 tight lit %typed
5+2:1 NEWLINE
6+2:1 glyph +$
7+2:4 name b
8+2:6 glyph $-(
9+2:9 tight aura @t
10+2:12 tvar M
11+2:13 tight glyph )
12+3:1 NEWLINE
13+3:1 glyph ++
14+3:4 name c
15+3:6 glyph |=(
16+3:9 tight name t
17+3:11 glyph [
18+3:12 tight lit %typed
19+3:19 name t
20+3:20 tight glyph ]
21+3:21 tight glyph )
22+4:1 NEWLINE
23+4:1 glyph +$
24+4:4 name d
25+4:6 glyph [
26+4:7 tight lit %typed
27+4:14 aura @t
28+4:16 tight glyph ]
29+4:17 NEWLINE
tests/golden/inline-date/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit ~2026.10.23
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name y
7+2:6 lit ~2026.10.23..14.30.00
8+2:27 NEWLINE
tests/golden/inline-decimal/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit 1.000
4+1:11 NEWLINE
tests/golden/inline-duration/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit ~s30
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name y
7+2:6 lit ~h1.m30
8+2:13 NEWLINE
tests/golden/inline-fold-mold/tokens.txtnew file+13
@@ -0,0 +1,13 @@
1+1:1 glyph +$
2+1:4 name fold
3+1:9 glyph $-(
4+1:12 tight glyph [
5+1:13 tight glyph [
6+1:14 tight lit %todo-update
7+1:27 name todo-update
8+1:38 tight glyph ]
9+1:40 name todos
10+1:45 tight glyph ]
11+1:47 name todos
12+1:52 tight glyph )
13+1:53 NEWLINE
tests/golden/inline-gate-mold/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph +$
2+1:4 name x
3+1:6 glyph $-(
4+1:9 tight name sample
5+1:16 name product
6+1:23 tight glyph )
7+1:24 NEWLINE
tests/golden/inline-gate-samples/tokens.txtnew file+30
@@ -0,0 +1,30 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name m
5+1:10 tight glyph =
6+1:11 tight name model
7+1:17 name m
8+2:1 NEWLINE
9+2:1 glyph ++
10+2:4 name g
11+2:6 glyph |=
12+2:9 glyph =
13+2:10 tight name msg
14+2:14 name msg
15+3:1 NEWLINE
16+3:1 glyph ++
17+3:4 name h
18+3:6 glyph |=
19+3:9 glyph [
20+3:10 tight name a
21+3:11 tight glyph =
22+3:12 tight aura @
23+3:14 name b
24+3:15 tight glyph =
25+3:16 tight aura @
26+3:17 tight glyph ]
27+4:3 INDENT
28+4:3 name a
29+4:4 DEDENT
30+4:4 NEWLINE
tests/golden/inline-gate-wide/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph |=(
4+1:9 tight name p
5+1:10 tight glyph =
6+1:11 tight wing post.blog
7+1:21 wing title.p
8+1:28 tight glyph )
9+2:1 NEWLINE
10+2:1 glyph ++
11+2:4 name y
12+2:6 glyph |=(
13+2:9 tight name p
14+2:11 wing title.p
15+2:18 tight glyph )
16+2:19 NEWLINE
tests/golden/inline-generic-mold/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph +$
2+1:4 name x
3+1:6 glyph |$
4+1:9 glyph [
5+1:10 tight tvar A
6+1:11 tight glyph ]
7+1:13 name mold
8+1:17 NEWLINE
tests/golden/inline-hex/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit 0x1f
4+1:10 NEWLINE
tests/golden/inline-import-mark-face-bad/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph /%
2+1:5 name act
3+1:10 lit %todo-action
4+1:22 NEWLINE
tests/golden/inline-imports-after-definition/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit 1
4+2:1 NEWLINE
5+2:1 glyph /-
6+2:5 name todo
7+2:9 NEWLINE
tests/golden/inline-island/tokens.txtnew file+6
@@ -0,0 +1,6 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name island
4+1:13 wing main.todo-list
5+1:28 name ts
6+1:30 NEWLINE
tests/golden/inline-kinds/tokens.txtnew file+57
@@ -0,0 +1,57 @@
1+1:1 glyph +$
2+1:4 name a
3+1:6 glyph (
4+1:7 tight name element
5+1:15 glyph !!
6+1:17 tight glyph )
7+2:1 NEWLINE
8+2:1 glyph +$
9+2:4 name b
10+2:6 glyph (
11+2:7 tight name page
12+2:12 tvar R
13+2:14 tvar D
14+2:15 tight glyph )
15+3:1 NEWLINE
16+3:1 glyph +$
17+3:4 name c
18+3:6 glyph (
19+3:7 tight name program
20+3:15 tvar D
21+3:17 tvar X
22+3:19 tvar M
23+3:20 tight glyph )
24+4:1 NEWLINE
25+4:1 glyph +$
26+4:4 name d
27+4:6 glyph (
28+4:7 tight name store
29+4:13 tvar S
30+4:14 tight glyph )
31+5:1 NEWLINE
32+5:1 glyph ++
33+5:4 name e
34+5:6 glyph (
35+5:7 tight name page
36+5:12 name load
37+5:17 name view
38+5:21 tight glyph )
39+6:1 NEWLINE
40+6:1 glyph ++
41+6:4 name f
42+6:6 glyph (
43+6:7 tight name program
44+6:15 name init
45+6:20 name update
46+6:27 name view
47+6:32 name subs
48+6:36 tight glyph )
49+7:1 NEWLINE
50+7:1 glyph ++
51+7:4 name g
52+7:6 glyph (
53+7:7 tight name store
54+7:13 name init
55+7:18 name update
56+7:24 tight glyph )
57+7:25 NEWLINE
tests/golden/inline-knot/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit ~.my-post
4+1:15 NEWLINE
tests/golden/inline-leftout-barcab/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-barcab/source.jibb:1:7: `|_` is left out: modules are records
2+++ x |_ s=@
3+ ^
tests/golden/inline-leftout-barcen/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-barcen/source.jibb:1:7: `|%` is left out: modules are records
2+++ x |%
3+ ^
tests/golden/inline-leftout-barhep/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-barhep/source.jibb:1:7: `|-` is left out: gates recurse by name
2+++ x |- 1
3+ ^
tests/golden/inline-leftout-bartar/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-bartar/source.jibb:1:7: `|*` is left out: modules are records
2+++ x |* a=* a
3+ ^
tests/golden/inline-leftout-buc-paren/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-buc-paren/source.jibb:1:6: `$(…)` is left out: gates recurse by name
2+++ x $(n 1)
3+ ^
tests/golden/inline-leftout-buccen/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-buccen/source.jibb:1:7: `$%` is left out: `$?` covers unions
2++$ x $%
3+ ^
tests/golden/inline-leftout-cencol/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-cencol/source.jibb:1:7: `%:` is left out: indentation covers it
2+++ x %: f a b
3+ ^
tests/golden/inline-leftout-centis/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-centis/source.jibb:1:7: `%=` is left out: indentation covers it; write a change, as m(a=b)
2+++ x %= m note 1
3+ ^
tests/golden/inline-leftout-colon-wing/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-colon-wing/source.jibb:1:8: `a:b` is left out: names never shadow, and `.` reads imports too; write a.b
2+++ x a:b
3+ ^
tests/golden/inline-leftout-colsig/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-colsig/source.jibb:1:7: `:~` is left out: indentation covers it; write ~[…]
2+++ x :~ 1 2
3+ ^
tests/golden/inline-leftout-coltar/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-coltar/source.jibb:1:7: `:*` is left out: indentation covers it; write […]
2+++ x :* 1 2
3+ ^
tests/golden/inline-leftout-dottar/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-dottar/source.jibb:1:6: `.*` is left out: names never shadow, and `.` reads imports too
2+++ x .* a b
3+ ^
tests/golden/inline-leftout-dottis/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-dottis/source.jibb:1:6: `.=` is left out: eq and not are gates
2+++ x .= a b
3+ ^
tests/golden/inline-leftout-faslus/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-faslus/source.jibb:1:2: `/+` is left out: code also runs in the browser
2+/+ foo
3+ ^
tests/golden/inline-leftout-hephep/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-hephep/source.jibb:2:1: the closer `--` is left out: indentation covers it
2+--
3+^
tests/golden/inline-leftout-kethep-wide/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ^-
4+1:8 tight glyph (
5+1:9 tight aura @ud
6+1:13 lit 5
7+1:14 tight glyph )
8+1:15 NEWLINE
tests/golden/inline-leftout-kettar/tokens.txtnew file+5
@@ -0,0 +1,5 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph *
4+1:7 tight aura @ud
5+1:10 NEWLINE
tests/golden/inline-leftout-sail/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-sail/source.jibb:1:6: Sail's `;` runes are left out: layout is Jibb's elements
2+++ x ;p: hello
3+ ^
tests/golden/inline-leftout-sigbar/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-sigbar/source.jibb:1:7: `~|` is left out: `~&` covers debugging
2+++ x ~| %oops 1
3+ ^
tests/golden/inline-leftout-signed-float-auras/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-signed-float-auras/source.jibb:1:7: signed and floating-point auras are left out of Jibb
2++$ a @sd
3+ ^
tests/golden/inline-leftout-tis-paren/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph =
4+1:7 tight glyph (
5+1:8 tight name a
6+1:10 name b
7+1:11 tight glyph )
8+1:12 NEWLINE
tests/golden/inline-leftout-tisfas/tokens.txtnew file+19
@@ -0,0 +1,19 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name n
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:3 INDENT
8+2:3 glyph =
9+2:4 tight glyph /
10+2:7 name m
11+2:10 glyph (
12+2:11 tight name add
13+2:15 name n
14+2:17 lit 1
15+2:18 tight glyph )
16+3:3 NEWLINE
17+3:3 name m
18+3:4 DEDENT
19+3:4 NEWLINE
tests/golden/inline-leftout-tisgal/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-tisgal/source.jibb:1:6: `=<` is left out: names never shadow, and `.` reads imports too
2+++ x =< a b
3+ ^
tests/golden/inline-leftout-tisgar/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-tisgar/source.jibb:1:6: `=>` is left out: names never shadow, and `.` reads imports too
2+++ x => a b
3+ ^
tests/golden/inline-leftout-tistis/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-tistis/source.jibb:4:1: the closer `==` is left out: indentation covers it
2+==
3+^
tests/golden/inline-leftout-wutcol/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-wutcol/source.jibb:2:4: `?:` is left out: `?-` is the branch
2+ ?: b 1 2
3+ ^
tests/golden/inline-leftout-wuthep-wide/tokens.txtnew file+11
@@ -0,0 +1,11 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ?-
4+1:8 tight glyph (
5+1:9 tight name b
6+1:11 lit %.y
7+1:15 lit 1
8+1:17 lit %.n
9+1:21 lit 2
10+1:22 tight glyph )
11+1:23 NEWLINE
tests/golden/inline-leftout-wutlus/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-wutlus/source.jibb:2:4: `?+` is left out: `?-` is the branch
2+ ?+ n ~
3+ ^
tests/golden/inline-leftout-wutzap/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-wutzap/source.jibb:1:7: `?!` is left out: eq and not are gates
2+++ x ?! %.y
3+ ^
tests/golden/inline-leftout-zap-not/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-zap-not/source.jibb:1:7: `!` begins only `!!`: `!x` is left out, as not is a gate
2+++ x !x
3+ ^
tests/golden/inline-leftout-zapgar/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/inline-leftout-zapgar/source.jibb:1:7: `!>` is left out: code also runs in the browser
2+++ x !>(5)
3+ ^
tests/golden/inline-list-parens/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+1:8 tight glyph (
5+1:9 tight name text
6+1:14 str "hi"
7+1:18 tight glyph )
8+1:19 tight glyph ]
9+2:1 NEWLINE
10+2:1 glyph ++
11+2:4 name y
12+2:6 glyph ~[
13+2:8 tight name text
14+2:13 str "hi"
15+2:17 tight glyph ]
16+2:18 NEWLINE
tests/golden/inline-list/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+1:8 tight lit 1
5+1:10 lit 2
6+1:12 lit 3
7+1:13 tight glyph ]
8+2:1 NEWLINE
9+2:1 glyph ++
10+2:4 name y
11+2:6 glyph ~[
12+2:8 tight name a
13+2:10 name b
14+2:12 name c
15+2:13 tight glyph ]
16+2:14 NEWLINE
tests/golden/inline-literal-defaults/tokens.txtnew file+19
@@ -0,0 +1,19 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit %a
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 lit ~
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 lit 5
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name d
15+4:6 glyph [
16+4:7 tight name x
17+4:9 name xs
18+4:11 tight glyph ]
19+4:12 NEWLINE
tests/golden/inline-load-slug/tokens.txtnew file+15
@@ -0,0 +1,15 @@
1+1:1 glyph ++
2+1:4 name load
3+1:9 glyph |=(
4+1:12 tight glyph [
5+1:13 tight name slug
6+1:17 tight glyph =
7+1:18 tight aura @ta
8+1:21 tight glyph ]
9+1:23 glyph (
10+1:24 tight wing post.api
11+1:33 name slug
12+1:38 name same
13+1:42 tight glyph )
14+1:43 tight glyph )
15+1:44 NEWLINE
tests/golden/inline-local-names/tokens.txtnew file+34
@@ -0,0 +1,34 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name n
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:3 INDENT
8+2:3 glyph ++
9+2:6 name m
10+2:8 glyph (
11+2:9 tight name add
12+2:13 name n
13+2:15 lit 1
14+2:16 tight glyph )
15+3:3 NEWLINE
16+3:3 glyph +$
17+3:6 name pair
18+3:11 glyph [
19+3:12 tight name a
20+3:13 tight glyph =
21+3:14 tight aura @ud
22+3:18 name b
23+3:19 tight glyph =
24+3:20 tight aura @ud
25+3:23 tight glyph ]
26+4:3 NEWLINE
27+4:3 glyph ^-
28+4:6 name pair
29+4:11 glyph [
30+4:12 tight name n
31+4:14 name m
32+4:15 tight glyph ]
33+4:16 DEDENT
34+4:16 NEWLINE
tests/golden/inline-loobean/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit %.y
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name y
7+2:6 lit %.n
8+2:9 NEWLINE
tests/golden/inline-mark-digit/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+1:1 glyph /%
2+1:5 lit %todo-action-1
3+1:19 NEWLINE
tests/golden/inline-module-definitions/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph +$
2+1:4 name name
3+1:9 name mold
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name name
7+2:9 name expr
8+2:13 NEWLINE
tests/golden/inline-mold-add/tokens.txtnew file+19
@@ -0,0 +1,19 @@
1+1:1 glyph +$
2+1:4 name x
3+1:6 glyph [
4+1:7 tight aura @
5+1:9 aura @
6+1:10 tight glyph ]
7+2:1 NEWLINE
8+2:1 glyph ++
9+2:4 name y
10+2:6 glyph |=
11+2:9 name n
12+2:10 tight glyph =
13+2:11 tight aura @ud
14+2:15 glyph (
15+2:16 tight name add
16+2:20 name n
17+2:22 lit 1
18+2:23 tight glyph )
19+2:24 NEWLINE
tests/golden/inline-mold-any-empty/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph +$
2+1:4 name a
3+1:6 glyph *
4+2:1 NEWLINE
5+2:1 glyph +$
6+2:4 name b
7+2:6 glyph !!
8+2:8 NEWLINE
tests/golden/inline-mold-atoms/tokens.txtnew file+32
@@ -0,0 +1,32 @@
1+1:1 glyph +$
2+1:4 name a
3+1:6 aura @
4+2:1 NEWLINE
5+2:1 glyph +$
6+2:4 name b
7+2:6 aura @ud
8+3:1 NEWLINE
9+3:1 glyph +$
10+3:4 name c
11+3:6 aura @t
12+4:1 NEWLINE
13+4:1 glyph +$
14+4:4 name d
15+4:6 aura @p
16+5:1 NEWLINE
17+5:1 glyph +$
18+5:4 name e
19+5:6 aura @da
20+6:1 NEWLINE
21+6:1 glyph +$
22+6:4 name f
23+6:6 glyph ?
24+7:1 NEWLINE
25+7:1 glyph +$
26+7:4 name g
27+7:6 aura @tas
28+8:1 NEWLINE
29+8:1 glyph +$
30+8:4 name h
31+8:6 aura @ta
32+8:9 NEWLINE
tests/golden/inline-mold-constants/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph +$
2+1:4 name a
3+1:6 lit %add
4+2:1 NEWLINE
5+2:1 glyph +$
6+2:4 name b
7+2:6 lit ~
8+3:1 NEWLINE
9+3:1 glyph +$
10+3:4 name c
11+3:6 lit %.y
12+4:1 NEWLINE
13+4:1 glyph +$
14+4:4 name d
15+4:6 lit %.n
16+4:9 NEWLINE
tests/golden/inline-mold-containers/tokens.txtnew file+60
@@ -0,0 +1,60 @@
1+1:1 glyph +$
2+1:4 name a
3+1:6 glyph (
4+1:7 tight name list
5+1:12 tvar A
6+1:13 tight glyph )
7+2:1 NEWLINE
8+2:1 glyph +$
9+2:4 name b
10+2:6 glyph (
11+2:7 tight name unit
12+2:12 tvar A
13+2:13 tight glyph )
14+3:1 NEWLINE
15+3:1 glyph +$
16+3:4 name c
17+3:6 glyph (
18+3:7 tight name set
19+3:11 tvar A
20+3:12 tight glyph )
21+4:1 NEWLINE
22+4:1 glyph +$
23+4:4 name d
24+4:6 glyph (
25+4:7 tight name map
26+4:11 tvar K
27+4:13 tvar V
28+4:14 tight glyph )
29+5:1 NEWLINE
30+5:1 glyph +$
31+5:4 name e
32+5:6 glyph (
33+5:7 tight name mop
34+5:11 tvar K
35+5:13 tvar V
36+5:14 tight glyph )
37+6:1 NEWLINE
38+6:1 glyph +$
39+6:4 name f
40+6:6 glyph (
41+6:7 tight name qeu
42+6:11 tvar A
43+6:12 tight glyph )
44+7:1 NEWLINE
45+7:1 glyph +$
46+7:4 name g
47+7:6 glyph (
48+7:7 tight name jar
49+7:11 tvar K
50+7:13 tvar V
51+7:14 tight glyph )
52+8:1 NEWLINE
53+8:1 glyph +$
54+8:4 name h
55+8:6 glyph (
56+8:7 tight name jug
57+8:11 tvar K
58+8:13 tvar V
59+8:14 tight glyph )
60+8:15 NEWLINE
tests/golden/inline-mold-gate/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph +$
2+1:4 name x
3+1:6 glyph $-(
4+1:9 tight tvar A
5+1:11 tvar B
6+1:12 tight glyph )
7+1:13 NEWLINE
tests/golden/inline-mold-generic/tokens.txtnew file+24
@@ -0,0 +1,24 @@
1+1:1 glyph +$
2+1:4 name result
3+1:11 glyph |$
4+1:14 glyph [
5+1:15 tight tvar V
6+1:17 tvar E
7+1:18 tight glyph ]
8+1:20 glyph $?
9+2:3 INDENT
10+2:3 glyph [
11+2:4 tight lit %ok
12+2:8 name value
13+2:13 tight glyph =
14+2:14 tight tvar V
15+2:15 tight glyph ]
16+3:3 NEWLINE
17+3:3 glyph [
18+3:4 tight lit %err
19+3:9 name error
20+3:14 tight glyph =
21+3:15 tight tvar E
22+3:16 tight glyph ]
23+3:17 DEDENT
24+3:17 NEWLINE
tests/golden/inline-mold-opaque/tokens.txtnew file+12
@@ -0,0 +1,12 @@
1+1:1 glyph +$
2+1:4 name a
3+1:6 name poke
4+2:1 NEWLINE
5+2:1 glyph +$
6+2:4 name b
7+2:6 name ask
8+3:1 NEWLINE
9+3:1 glyph +$
10+3:4 name c
11+3:6 name qath
12+3:10 NEWLINE
tests/golden/inline-mold-paths/tokens.txtnew file+20
@@ -0,0 +1,20 @@
1+1:1 glyph +$
2+1:4 name a
3+1:6 glyph /
4+1:7 tight knot todos
5+2:1 NEWLINE
6+2:1 glyph +$
7+2:4 name b
8+2:6 glyph /
9+3:1 NEWLINE
10+3:1 glyph +$
11+3:4 name c
12+3:6 glyph /
13+3:7 tight knot todo
14+3:11 tight glyph /
15+3:12 tight glyph [
16+3:13 tight name id
17+3:15 tight glyph =
18+3:16 tight aura @ud
19+3:19 tight glyph ]
20+3:20 NEWLINE
tests/golden/inline-mold-records/tokens.txtnew file+40
@@ -0,0 +1,40 @@
1+1:1 glyph +$
2+1:4 name a
3+1:6 glyph [
4+1:7 tight name text
5+1:11 tight glyph =
6+1:12 tight aura @t
7+1:15 name done
8+1:19 tight glyph =
9+1:20 tight glyph ?
10+1:21 tight glyph ]
11+2:1 NEWLINE
12+2:1 glyph +$
13+2:4 name b
14+2:6 glyph [
15+2:7 tight aura @t
16+2:10 glyph ?
17+2:11 tight glyph ]
18+3:1 NEWLINE
19+3:1 glyph +$
20+3:4 name c
21+3:6 glyph [
22+3:7 tight name a
23+3:8 tight glyph =
24+3:9 tight aura @
25+3:11 name b
26+3:12 tight glyph =
27+3:13 tight aura @
28+3:14 tight glyph ]
29+4:1 NEWLINE
30+4:1 glyph +$
31+4:4 name d
32+4:6 glyph [
33+4:7 tight name x
34+4:8 tight glyph =
35+4:9 tight aura @
36+4:11 name y
37+4:12 tight glyph =
38+4:13 tight aura @
39+4:14 tight glyph ]
40+4:15 NEWLINE
tests/golden/inline-namespaces/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph +$
2+1:4 name a
3+1:6 wing todo-action.todo
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 wing todo-action.todo
8+3:1 NEWLINE
9+3:1 glyph +$
10+3:4 name c
11+3:6 wing todos.todo
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name d
15+4:6 wing todos.todo
16+4:16 NEWLINE
tests/golden/inline-no-operators/tokens.txtnew file+17
@@ -0,0 +1,17 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name eq
4+1:9 name a
5+1:11 name b
6+2:1 NEWLINE
7+2:1 glyph ++
8+2:4 name y
9+2:6 name not
10+2:10 name x
11+3:1 NEWLINE
12+3:1 glyph ++
13+3:4 name z
14+3:6 name gth
15+3:10 name a
16+3:12 name b
17+3:13 NEWLINE
tests/golden/inline-no-subs/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name subs
3+1:9 glyph |=(
4+1:12 tight name m
5+1:14 lit ~
6+1:15 tight glyph )
7+1:16 NEWLINE
tests/golden/inline-null/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit ~
4+1:7 NEWLINE
tests/golden/inline-pair/tokens.txtnew file+6
@@ -0,0 +1,6 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name gap
4+1:9 tight glyph +
5+1:10 tight lit %s2
6+1:13 NEWLINE
tests/golden/inline-pairs-two-items/tokens.txtnew file+11
@@ -0,0 +1,11 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+1:8 tight name pad
5+1:11 tight glyph +
6+1:12 tight lit %s3
7+1:16 name gap
8+1:19 tight glyph +
9+1:20 tight lit %s2
10+1:23 tight glyph ]
11+1:24 NEWLINE
tests/golden/inline-path/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph /
4+1:7 tight knot posts
5+1:12 tight glyph /
6+1:13 tight knot ~zod
7+1:17 NEWLINE
tests/golden/inline-pattern-any/tokens.txtnew file+15
@@ -0,0 +1,15 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 glyph *
12+3:8 lit ~
13+3:9 DEDENT
14+3:9 DEDENT
15+3:9 NEWLINE
tests/golden/inline-pattern-cell/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 glyph [
12+3:6 tight name a
13+3:8 name b
14+3:9 tight glyph ]
15+3:12 name b
16+4:5 NEWLINE
17+4:5 glyph *
18+4:12 lit ~
19+4:13 DEDENT
20+4:13 DEDENT
21+4:13 NEWLINE
tests/golden/inline-pattern-crash-arm/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph $?(
7+1:14 tight lit %go
8+1:18 lit %stop
9+1:23 tight glyph )
10+2:3 INDENT
11+2:3 glyph ?-
12+2:6 name s
13+3:5 INDENT
14+3:5 lit %go
15+3:12 lit 1
16+4:5 NEWLINE
17+4:5 lit %stop
18+4:12 glyph !!
19+4:14 DEDENT
20+4:14 DEDENT
21+4:14 NEWLINE
tests/golden/inline-pattern-date-bad/tokens.txtnew file+18
@@ -0,0 +1,18 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name d
5+1:10 tight glyph =
6+1:11 tight aura @da
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name d
10+3:5 INDENT
11+3:5 lit ~2026.10.23
12+3:18 lit 1
13+4:5 NEWLINE
14+4:5 glyph *
15+4:18 lit 2
16+4:19 DEDENT
17+4:19 DEDENT
18+4:19 NEWLINE
tests/golden/inline-pattern-eq/tokens.txtnew file+27
@@ -0,0 +1,27 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 glyph [
5+1:10 tight name a
6+1:11 tight glyph =
7+1:12 tight aura @
8+1:14 name b
9+1:15 tight glyph =
10+1:16 tight aura @
11+1:17 tight glyph ]
12+2:3 INDENT
13+2:3 glyph ?-
14+2:6 glyph (
15+2:7 tight name eq
16+2:10 name a
17+2:12 name b
18+2:13 tight glyph )
19+3:5 INDENT
20+3:5 lit %.y
21+3:10 str "equal"
22+4:5 NEWLINE
23+4:5 lit %.n
24+4:10 str "different"
25+4:21 DEDENT
26+4:21 DEDENT
27+4:21 NEWLINE
tests/golden/inline-pattern-head-tag/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 glyph [
12+3:6 tight lit %add
13+3:11 name t
14+3:12 tight glyph ]
15+3:15 name t
16+4:5 NEWLINE
17+4:5 glyph *
18+4:15 lit ~
19+4:16 DEDENT
20+4:16 DEDENT
21+4:16 NEWLINE
tests/golden/inline-pattern-interpolated-bad/tokens.txtnew file+20
@@ -0,0 +1,20 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight aura @t
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 str-head "a"
12+3:8 tight name b
13+3:9 tight str-tail ""
14+3:13 lit 1
15+4:5 NEWLINE
16+4:5 glyph *
17+4:13 lit 2
18+4:14 DEDENT
19+4:14 DEDENT
20+4:14 NEWLINE
tests/golden/inline-pattern-list-bad/tokens.txtnew file+23
@@ -0,0 +1,23 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph (
7+1:12 tight name list
8+1:17 aura @
9+1:18 tight glyph )
10+2:3 INDENT
11+2:3 glyph ?-
12+2:6 name s
13+3:5 INDENT
14+3:5 glyph ~[
15+3:7 tight name a
16+3:8 tight glyph ]
17+3:11 lit 1
18+4:5 NEWLINE
19+4:5 glyph *
20+4:11 lit 2
21+4:12 DEDENT
22+4:12 DEDENT
23+4:12 NEWLINE
tests/golden/inline-pattern-literals/tokens.txtnew file+24
@@ -0,0 +1,24 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 lit 1.000
12+3:13 lit %number
13+4:5 NEWLINE
14+4:5 str "milk"
15+4:13 lit %string
16+5:5 NEWLINE
17+5:5 lit ~zod
18+5:13 lit %ship
19+6:5 NEWLINE
20+6:5 glyph *
21+6:13 lit %other
22+6:19 DEDENT
23+6:19 DEDENT
24+6:19 NEWLINE
tests/golden/inline-pattern-loobean/tokens.txtnew file+18
@@ -0,0 +1,18 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name b
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name b
10+3:5 INDENT
11+3:5 lit %.y
12+3:10 lit 1
13+4:5 NEWLINE
14+4:5 lit %.n
15+4:10 lit 2
16+4:11 DEDENT
17+4:11 DEDENT
18+4:11 NEWLINE
tests/golden/inline-pattern-move-any/tokens.txtnew file+22
@@ -0,0 +1,22 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 glyph [
12+3:6 tight lit %move
13+3:12 glyph *
14+3:14 glyph *
15+3:15 tight glyph ]
16+3:18 lit 1
17+4:5 NEWLINE
18+4:5 glyph *
19+4:18 lit 2
20+4:19 DEDENT
21+4:19 DEDENT
22+4:19 NEWLINE
tests/golden/inline-pattern-name/tokens.txtnew file+15
@@ -0,0 +1,15 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 name x
12+3:8 name x
13+3:9 DEDENT
14+3:9 DEDENT
15+3:9 NEWLINE
tests/golden/inline-pattern-null/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name u
5+1:10 tight glyph =
6+1:11 tight glyph (
7+1:12 tight name unit
8+1:17 aura @t
9+1:19 tight glyph )
10+2:3 INDENT
11+2:3 glyph ?-
12+2:6 name u
13+3:5 INDENT
14+3:5 lit ~
15+3:8 str ""
16+4:5 NEWLINE
17+4:5 glyph *
18+4:8 str "something"
19+4:19 DEDENT
20+4:19 DEDENT
21+4:19 NEWLINE
tests/golden/inline-pattern-pair-bad/tokens.txtnew file+20
@@ -0,0 +1,20 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 name gap
12+3:8 tight glyph +
13+3:9 tight lit %s2
14+3:14 lit 1
15+4:5 NEWLINE
16+4:5 glyph *
17+4:14 lit 2
18+4:15 DEDENT
19+4:15 DEDENT
20+4:15 NEWLINE
tests/golden/inline-pattern-tail-tag/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 glyph [
12+3:6 tight name t
13+3:8 lit %draft
14+3:14 tight glyph ]
15+3:17 name t
16+4:5 NEWLINE
17+4:5 glyph *
18+4:17 lit ~
19+4:18 DEDENT
20+4:18 DEDENT
21+4:18 NEWLINE
tests/golden/inline-pattern-term/tokens.txtnew file+18
@@ -0,0 +1,18 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 lit %add
12+3:11 lit 1
13+4:5 NEWLINE
14+4:5 glyph *
15+4:11 lit 2
16+4:12 DEDENT
17+4:12 DEDENT
18+4:12 NEWLINE
tests/golden/inline-pattern-two-tags/tokens.txtnew file+22
@@ -0,0 +1,22 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name s
5+1:10 tight glyph =
6+1:11 tight glyph *
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name s
10+3:5 INDENT
11+3:5 glyph [
12+3:6 tight lit %move
13+3:12 lit %left
14+3:18 name n
15+3:19 tight glyph ]
16+3:22 name n
17+4:5 NEWLINE
18+4:5 glyph *
19+4:22 lit ~
20+4:23 DEDENT
21+4:23 DEDENT
22+4:23 NEWLINE
tests/golden/inline-pattern-unit/tokens.txtnew file+24
@@ -0,0 +1,24 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name u
5+1:10 tight glyph =
6+1:11 tight glyph (
7+1:12 tight name unit
8+1:17 aura @t
9+1:19 tight glyph )
10+2:3 INDENT
11+2:3 glyph ?-
12+2:6 name u
13+3:5 INDENT
14+3:5 glyph [
15+3:6 tight lit ~
16+3:8 name x
17+3:9 tight glyph ]
18+3:12 name x
19+4:5 NEWLINE
20+4:5 glyph *
21+4:12 str ""
22+4:14 DEDENT
23+4:14 DEDENT
24+4:14 NEWLINE
tests/golden/inline-qath/tokens.txtnew file+14
@@ -0,0 +1,14 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph %/
4+1:8 tight knot blog
5+2:1 NEWLINE
6+2:1 glyph ++
7+2:4 name y
8+2:6 glyph %/
9+2:8 tight knot blog
10+2:12 tight glyph /
11+2:13 tight glyph (
12+2:14 tight name slug
13+2:18 tight glyph )
14+2:19 NEWLINE
tests/golden/inline-requests/tokens.txtnew file+27
@@ -0,0 +1,27 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 glyph (
4+1:7 tight wing todo-action.todo
5+1:24 glyph [
6+1:25 tight lit %add
7+1:30 wing draft.m
8+1:37 tight glyph ]
9+1:38 tight glyph )
10+2:1 NEWLINE
11+2:1 glyph ++
12+2:4 name b
13+2:6 glyph (
14+2:7 tight wing todos.todo
15+2:18 glyph |=
16+2:20 tight lit %got
17+2:24 tight glyph )
18+3:1 NEWLINE
19+3:1 glyph ++
20+3:4 name c
21+3:6 glyph (
22+3:7 tight wing changes.todo
23+3:20 glyph |=
24+3:22 tight lit %got
25+3:27 name apply
26+3:32 tight glyph )
27+3:33 NEWLINE
tests/golden/inline-scry-case/tokens.txtnew file+20
@@ -0,0 +1,20 @@
1+1:1 glyph +$
2+1:4 name paths
3+1:10 glyph $?
4+2:3 INDENT
5+2:3 glyph [
6+2:4 tight lit %changes
7+2:13 glyph /
8+2:14 tight knot updates
9+2:22 glyph (
10+2:23 tight name facts
11+2:29 name todos
12+2:35 name todo-update
13+2:46 tight glyph )
14+2:48 name scry
15+2:52 tight glyph =
16+2:53 tight glyph /
17+2:54 tight knot todos
18+2:59 tight glyph ]
19+2:60 DEDENT
20+2:60 NEWLINE
tests/golden/inline-self-reference/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name title
3+1:10 glyph (
4+1:11 tight name trim
5+1:16 name title
6+1:21 tight glyph )
7+1:22 NEWLINE
tests/golden/inline-ship/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit ~zod
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name y
7+2:6 lit ~sampel-palnet
8+2:20 NEWLINE
tests/golden/inline-static-image/tokens.txtnew file+13
@@ -0,0 +1,13 @@
1+1:1 glyph ++
2+1:4 name logo
3+1:9 glyph (
4+1:10 tight name image
5+1:16 glyph %/
6+1:18 tight knot static
7+1:24 tight glyph /
8+1:25 tight knot img
9+1:28 tight glyph /
10+1:29 tight knot logo.png
11+1:38 str "The logo"
12+1:48 tight glyph )
13+1:49 NEWLINE
tests/golden/inline-string/tokens.txtnew file+10
@@ -0,0 +1,10 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 str "milk"
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name y
7+2:6 str-head "Since "
8+2:14 tight name day
9+2:17 tight str-tail ""
10+2:19 NEWLINE
tests/golden/inline-tag-shape/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph +$
2+1:4 name x
3+1:6 glyph [
4+1:7 tight aura @t
5+1:10 lit %draft
6+1:16 tight glyph ]
7+1:17 NEWLINE
tests/golden/inline-term/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit %add
4+1:10 NEWLINE
tests/golden/inline-text-items/tokens.txtnew file+9
@@ -0,0 +1,9 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph (
4+1:7 tight name text
5+1:12 str-head ""
6+1:14 tight name n
7+1:15 tight str-tail " items"
8+1:23 tight glyph )
9+1:24 NEWLINE
tests/golden/inline-union-wide/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph +$
2+1:4 name x
3+1:6 glyph $?(
4+1:9 tight lit %a
5+1:12 lit %b
6+1:14 tight glyph )
7+1:15 NEWLINE
tests/golden/inline-unit/tokens.txtnew file+5
@@ -0,0 +1,5 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph `
4+1:7 tight name x
5+1:8 NEWLINE
tests/golden/inline-wide-form-rune-bad/tokens.txtnew file+9
@@ -0,0 +1,9 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph |=(
4+1:9 tight name n
5+1:11 glyph ^-
6+1:14 aura @ud
7+1:18 name n
8+1:19 tight glyph )
9+1:20 NEWLINE
tests/golden/inline-wide-forms/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph |=(
4+1:9 tight name sample
5+1:16 name expr
6+1:20 tight glyph )
7+2:1 NEWLINE
8+2:1 glyph +$
9+2:4 name y
10+2:6 glyph $?(
11+2:9 tight name case
12+2:14 name case
13+2:18 tight glyph )
14+3:1 NEWLINE
15+3:1 glyph +$
16+3:4 name z
17+3:6 glyph $-(
18+3:9 tight name mold
19+3:14 name mold
20+3:18 tight glyph )
21+3:19 NEWLINE
tests/golden/inline-wide-union-call/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph +$
2+1:4 name x
3+1:6 glyph $?(
4+1:9 tight lit %a
5+1:12 name list
6+1:17 aura @t
7+1:19 tight glyph )
8+1:20 NEWLINE
tests/golden/inline-wings/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 wing title.p
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 wing card.card
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 wing space.theme.theme
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name d
15+4:6 wing get.by
16+4:12 NEWLINE
tests/golden/lex-base32-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-base32-bad-1/source.jibb:1:13: a base-32 number is 0v and digits 0-9 and a-v, in groups of five joined by dots, as 0v5.fdf99
2+++ x 0v5.fdfz9
3+ ^
tests/golden/lex-base32-ok-1/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit 0v0
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 lit 0vv
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 lit 0v5.fdf99
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name d
15+4:6 lit 0v1.00000
16+4:15 NEWLINE
tests/golden/lex-call-open-bad-1/tokens.txtnew file+10
@@ -0,0 +1,10 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph (
4+1:7 tight name f
5+1:9 name a
6+2:3 INDENT
7+2:3 name b
8+2:5 name c
9+2:6 DEDENT
10+2:6 NEWLINE
tests/golden/lex-call-open-bad-2/tokens.txtnew file+12
@@ -0,0 +1,12 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph (
4+1:7 tight name f
5+1:9 name a
6+2:3 INDENT
7+2:3 name b
8+3:5 INDENT
9+3:5 name c
10+3:6 DEDENT
11+3:6 DEDENT
12+3:6 NEWLINE
tests/golden/lex-call-open-bad-3/tokens.txtnew file+11
@@ -0,0 +1,11 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph (
4+2:3 INDENT
5+2:3 name f
6+3:3 NEWLINE
7+3:3 name a
8+4:3 NEWLINE
9+4:3 name b
10+4:4 DEDENT
11+4:4 NEWLINE
tests/golden/lex-call-open-ok-1/tokens.txtnew file+28
@@ -0,0 +1,28 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph (
4+1:7 tight name f
5+1:9 name a
6+1:11 name b
7+2:3 INDENT
8+2:3 name c
9+3:3 NEWLINE
10+3:3 name g
11+3:5 name d
12+4:3 NEWLINE
13+4:3 glyph (
14+4:4 tight name h
15+4:6 name e
16+4:7 tight glyph )
17+5:1 DEDENT
18+5:1 NEWLINE
19+5:1 glyph ++
20+5:4 name y
21+5:6 glyph (
22+5:7 tight name f
23+6:3 INDENT
24+6:3 name a
25+7:3 NEWLINE
26+7:3 name b
27+7:4 DEDENT
28+7:4 NEWLINE
tests/golden/lex-cell-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-cell-bad-1/source.jibb:1:8: unexpected `,`: items are separated by spaces
2+++ x [a, b]
3+ ^
tests/golden/lex-cell-ok-1/tokens.txtnew file+39
@@ -0,0 +1,39 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 glyph [
4+1:7 tight name a
5+1:9 name b
6+1:11 name c
7+1:12 tight glyph ]
8+2:1 NEWLINE
9+2:1 glyph ++
10+2:4 name b
11+2:6 glyph [
12+2:7 tight name text
13+2:11 tight glyph =
14+2:12 tight str "milk"
15+2:19 name done
16+2:23 tight glyph =
17+2:24 tight lit %.n
18+2:27 tight glyph ]
19+3:1 NEWLINE
20+3:1 glyph ++
21+3:4 name c
22+3:6 glyph [
23+3:7 tight glyph [
24+3:8 tight name a
25+3:10 name b
26+3:11 tight glyph ]
27+3:13 name c
28+3:14 tight glyph ]
29+4:1 NEWLINE
30+4:1 glyph ++
31+4:4 name d
32+4:6 glyph [
33+4:7 tight name a
34+4:9 glyph [
35+4:10 tight name b
36+4:12 name c
37+4:13 tight glyph ]
38+4:14 tight glyph ]
39+4:15 NEWLINE
tests/golden/lex-comment-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-comment-bad-1/source.jibb:1:10: a comment starts with `::`
2+++ x 5 : not a comment
3+ ^
tests/golden/lex-comment-ok-1/tokens.txtnew file+17
@@ -0,0 +1,17 @@
1+2:1 glyph ++
2+2:4 name x
3+2:6 lit 5
4+3:1 NEWLINE
5+3:1 glyph ++
6+3:4 name y
7+4:3 INDENT
8+4:3 lit 6
9+6:1 DEDENT
10+6:1 NEWLINE
11+6:1 glyph ++
12+6:4 name z
13+6:6 glyph ~[
14+7:3 INDENT
15+7:3 lit 1
16+7:4 DEDENT
17+7:4 NEWLINE
tests/golden/lex-comment-ok-2/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 str "a::b"
4+1:12 NEWLINE
tests/golden/lex-comment-ok-3/tokens.txtnew file+1
@@ -0,0 +1 @@
1+
tests/golden/lex-date-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-date-bad-1/source.jibb:1:21: a date is ~year.month.day, then optionally ..hours.minutes.seconds, as ~2026.10.23..14.30.00
2+++ x ~2026.10.23..14:30:00
3+ ^
tests/golden/lex-date-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-date-bad-2/source.jibb:1:24: a date is ~year.month.day, then optionally ..hours.minutes.seconds, as ~2026.10.23..14.30.00
2+++ x ~2026.10.29..14.30
3+ ^
tests/golden/lex-date-ok-1/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit ~2026.10.23
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 lit ~2026.10.23..14.30.00
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 lit ~2026.1.5
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name d
15+4:6 lit ~2026.10.23..14.30.00..ffff
16+4:33 NEWLINE
tests/golden/lex-decimal-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-decimal-bad-1/source.jibb:1:9: a decimal is digits in groups of three joined by dots, as 1.000
2+++ x 1000
3+ ^
tests/golden/lex-decimal-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-decimal-bad-2/source.jibb:1:11: a decimal is digits in groups of three joined by dots, as 1.000
2+++ x 1.0000
3+ ^
tests/golden/lex-decimal-ok-1/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit 0
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 lit 42
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 lit 1.000
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name d
15+4:6 lit 1.000.000
16+4:15 NEWLINE
tests/golden/lex-duration-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-duration-bad-1/source.jibb:1:9: a duration is units of d, h, m and s joined by dots, as ~h1.m30
2+++ x ~h1m30
3+ ^
tests/golden/lex-duration-ok-1/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit ~s30
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 lit ~h1.m30
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 lit ~m5
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name d
15+4:6 lit ~d1.h2.m3.s4
16+4:18 NEWLINE
tests/golden/lex-hex-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-hex-bad-1/source.jibb:1:8: a hexadecimal number is 0x and digits 0-9 and a-f, in groups of four joined by dots, as 0x1.ffff
2+++ x 0xg1
3+ ^
tests/golden/lex-hex-ok-1/tokens.txtnew file+16
@@ -0,0 +1,16 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit 0x0
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 lit 0x1f
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 lit 0x1.ffff
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name d
15+4:6 lit 0xdead.beef
16+4:17 NEWLINE
tests/golden/lex-indent-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-indent-bad-1/source.jibb:2:1: a tab: Jibb uses spaces only
2+ 5
3+^
tests/golden/lex-indent-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-indent-bad-2/source.jibb:4:3: this line's indentation matches no enclosing line: indent it to column 1, 5 or 7
2+ (text "b")
3+ ^
tests/golden/lex-indent-bad-3/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-indent-bad-3/source.jibb:1:3: the first line is indented: top-level lines start at column 1
2+ ++ x 5
3+ ^
tests/golden/lex-indent-ok-1/tokens.txtnew file+41
@@ -0,0 +1,41 @@
1+1:1 glyph ++
2+1:4 name view
3+1:9 glyph |=
4+1:12 name m
5+1:13 tight glyph =
6+1:14 tight name model
7+2:5 INDENT
8+2:5 name column
9+2:12 glyph ~[
10+2:14 tight name gap
11+2:17 tight glyph +
12+2:18 tight lit %s1
13+2:21 tight glyph ]
14+2:23 glyph ~[
15+3:6 INDENT
16+3:6 glyph (
17+3:7 tight name text
18+3:12 str "one"
19+3:17 tight glyph )
20+4:6 NEWLINE
21+4:6 name row
22+4:10 lit ~
23+4:12 glyph ~[
24+5:12 INDENT
25+5:12 glyph (
26+5:13 tight name text
27+5:18 str "two"
28+5:23 tight glyph )
29+6:6 DEDENT
30+6:6 NEWLINE
31+6:6 glyph (
32+6:7 tight name text
33+6:12 str "three"
34+6:19 tight glyph )
35+7:1 DEDENT
36+7:1 DEDENT
37+7:1 NEWLINE
38+7:1 glyph ++
39+7:4 name main
40+7:9 name view
41+7:13 NEWLINE
tests/golden/lex-indent-ok-2/tokens.txtnew file+36
@@ -0,0 +1,36 @@
1+1:1 glyph ++
2+1:4 name view
3+1:9 glyph |=
4+1:12 name m
5+1:13 tight glyph =
6+1:14 tight name model
7+2:3 INDENT
8+2:3 name column
9+2:10 glyph ~[
10+2:12 tight name gap
11+2:15 tight glyph +
12+2:16 tight lit %s1
13+2:19 tight glyph ]
14+2:21 glyph ~[
15+3:5 INDENT
16+3:5 glyph (
17+3:6 tight name text
18+3:11 str "a"
19+3:14 tight glyph )
20+7:5 NEWLINE
21+7:5 glyph (
22+7:6 tight name text
23+7:11 str "b"
24+7:14 tight glyph )
25+10:5 NEWLINE
26+10:5 glyph (
27+10:6 tight name text
28+10:11 str "c"
29+10:14 tight glyph )
30+12:1 DEDENT
31+12:1 DEDENT
32+12:1 NEWLINE
33+12:1 glyph ++
34+12:4 name main
35+12:9 name view
36+12:13 NEWLINE
tests/golden/lex-indent-ok-3/tokens.txtnew file+27
@@ -0,0 +1,27 @@
1+2:1 glyph +$
2+2:4 name msg
3+2:8 glyph $?
4+4:3 INDENT
5+4:3 lit %a
6+6:3 NEWLINE
7+6:3 lit %b
8+7:1 DEDENT
9+7:1 NEWLINE
10+7:1 glyph ++
11+7:4 name f
12+7:6 glyph |=
13+7:9 name b
14+7:10 tight glyph =
15+7:11 tight glyph ?
16+8:3 INDENT
17+8:3 glyph ?-
18+8:6 name b
19+10:5 INDENT
20+10:5 lit %.y
21+10:10 lit 1
22+13:5 NEWLINE
23+13:5 lit %.n
24+13:10 lit 2
25+13:11 DEDENT
26+13:11 DEDENT
27+13:11 NEWLINE
tests/golden/lex-interp-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-interp-bad-1/source.jibb:1:9: a `\` begins `\\`, `\"`, `\{` or two hex digits
2+++ x "a\qb"
3+ ^
tests/golden/lex-interp-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-interp-bad-2/source.jibb:1:8: unexpected `<`: there is no `<…>`, since `{…}` prints a value by its aura
2+++ x "{<n>}"
3+ ^
tests/golden/lex-interp-bad-3/tokens.txtnew file+5
@@ -0,0 +1,5 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 str-head ""
4+1:8 tight str-tail ""
5+1:10 NEWLINE
tests/golden/lex-interp-bad-4/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 str "a \\ b \0a c"
4+1:20 NEWLINE
tests/golden/lex-interp-ok-1/tokens.txtnew file+53
@@ -0,0 +1,53 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 str-head "Since "
4+1:14 tight name day
5+1:17 tight str-tail ""
6+2:1 NEWLINE
7+2:1 glyph ++
8+2:4 name b
9+2:6 str-head ""
10+2:8 tight glyph (
11+2:9 tight name lent
12+2:14 wing items.cart.m
13+2:26 tight glyph )
14+2:27 tight str-tail " items"
15+3:1 NEWLINE
16+3:1 glyph ++
17+3:4 name c
18+3:6 str-head ""
19+3:8 tight name n
20+3:9 tight str-tail ""
21+4:1 NEWLINE
22+4:1 glyph ++
23+4:4 name d
24+4:6 str-head "left "
25+4:13 tight name n
26+4:14 tight str-mid " and right "
27+4:27 tight name m
28+4:28 tight str-tail ""
29+5:1 NEWLINE
30+5:1 glyph ++
31+5:4 name e
32+5:6 str "a \{ brace and a \" quote"
33+6:1 NEWLINE
34+6:1 glyph ++
35+6:4 name f
36+6:6 str-head ""
37+6:8 tight name add
38+6:12 name n
39+6:14 lit 1
40+6:15 tight str-tail " is a call without parentheses"
41+7:1 NEWLINE
42+7:1 glyph ++
43+7:4 name g
44+7:6 str-head ""
45+7:8 tight glyph ^-
46+7:11 aura @ud
47+7:15 name n
48+7:16 tight str-tail " holds a rune"
49+8:1 NEWLINE
50+8:1 glyph ++
51+8:4 name h
52+8:6 str "\{x} is text"
53+8:20 NEWLINE
tests/golden/lex-interp-ok-2/tokens.txtnew file+26
@@ -0,0 +1,26 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 str-head "a "
4+1:10 tight glyph (
5+1:11 tight name weld
6+1:16 str-head "b "
7+1:20 tight name c
8+1:21 tight str-tail " d"
9+1:26 str "e"
10+1:29 tight glyph )
11+1:30 tight str-tail " f"
12+2:1 NEWLINE
13+2:1 glyph ++
14+2:4 name y
15+2:6 str-head ""
16+2:8 tight glyph (
17+2:9 tight name f
18+2:11 str "}"
19+2:14 tight glyph )
20+2:15 tight str-mid " and "
21+2:22 tight glyph (
22+2:23 tight name g
23+2:25 str "\""
24+2:29 tight glyph )
25+2:30 tight str-tail ""
26+2:32 NEWLINE
tests/golden/lex-knot-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-knot-bad-1/source.jibb:1:8: unexpected `M`: a knot holds lowercase letters, digits and - . ~ _
2+++ x ~.My-post
3+ ^
tests/golden/lex-knot-ok-1/tokens.txtnew file+12
@@ -0,0 +1,12 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit ~.my-post
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 lit ~.
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 lit ~.a_b.c~d-1
12+3:17 NEWLINE
tests/golden/lex-layout-bad-1/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name foo
4+2:3 INDENT
5+2:3 name bar
6+2:6 DEDENT
7+2:6 NEWLINE
tests/golden/lex-layout-bad-2/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name view
3+2:1 NEWLINE
4+2:1 glyph ++
5+2:4 name main
6+2:9 name view
7+2:13 NEWLINE
tests/golden/lex-layout-bad-3/tokens.txtnew file+13
@@ -0,0 +1,13 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name n
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:3 INDENT
8+2:3 name add
9+2:7 name n
10+3:3 NEWLINE
11+3:3 lit 1
12+3:4 DEDENT
13+3:4 NEWLINE
tests/golden/lex-layout-bad-4/tokens.txtnew file+18
@@ -0,0 +1,18 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name n
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name n
10+3:5 INDENT
11+3:5 lit 0
12+3:8 lit ~
13+4:3 DEDENT
14+4:3 NEWLINE
15+4:3 glyph *
16+4:6 lit ~
17+4:7 DEDENT
18+4:7 NEWLINE
tests/golden/lex-layout-ok-1/tokens.txtnew file+37
@@ -0,0 +1,37 @@
1+1:1 glyph ++
2+1:4 name view
3+1:9 glyph |=
4+1:12 name m
5+1:13 tight glyph =
6+1:14 tight name model
7+2:3 INDENT
8+2:3 name column
9+2:10 lit ~
10+2:12 glyph ~[
11+3:5 INDENT
12+3:5 glyph (
13+3:6 tight name text
14+3:11 str "one"
15+3:16 tight glyph )
16+4:5 NEWLINE
17+4:5 name row
18+4:9 lit ~
19+4:11 glyph ~[
20+5:7 INDENT
21+5:7 glyph (
22+5:8 tight name text
23+5:13 str "two"
24+5:18 tight glyph )
25+6:7 NEWLINE
26+6:7 glyph (
27+6:8 tight name text
28+6:13 str "three"
29+6:20 tight glyph )
30+7:1 DEDENT
31+7:1 DEDENT
32+7:1 DEDENT
33+7:1 NEWLINE
34+7:1 glyph ++
35+7:4 name main
36+7:9 name view
37+7:13 NEWLINE
tests/golden/lex-list-bad-1/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+1:8 tight lit 1
5+1:10 lit 2
6+1:12 lit 3
7+1:13 tight glyph )
8+1:14 NEWLINE
tests/golden/lex-list-ok-1/tokens.txtnew file+29
@@ -0,0 +1,29 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 glyph ~[
4+1:8 tight lit 1
5+1:10 lit 2
6+1:12 lit 3
7+1:13 tight glyph ]
8+2:1 NEWLINE
9+2:1 glyph ++
10+2:4 name b
11+2:6 glyph ~[
12+2:8 tight glyph (
13+2:9 tight name text
14+2:14 str "hi"
15+2:18 tight glyph )
16+2:19 tight glyph ]
17+3:1 NEWLINE
18+3:1 glyph ++
19+3:4 name c
20+3:6 glyph ~[
21+3:8 tight glyph ~[
22+3:10 tight lit 1
23+3:11 tight glyph ]
24+3:13 glyph ~[
25+3:15 tight lit 2
26+3:17 lit 3
27+3:18 tight glyph ]
28+3:19 tight glyph ]
29+3:20 NEWLINE
tests/golden/lex-loobean-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-loobean-bad-1/source.jibb:1:8: the loobeans are `%.y` and `%.n`
2+++ x %.x
3+ ^
tests/golden/lex-loobean-ok-1/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph [
4+1:7 tight lit %.y
5+1:11 lit %.n
6+1:14 tight glyph ]
7+1:15 NEWLINE
tests/golden/lex-name-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-name-bad-1/source.jibb:1:6: names are lowercase letters, digits and -
2+++ myView 5
3+ ^
tests/golden/lex-name-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-name-bad-2/source.jibb:1:8: names are lowercase letters, digits and -
2+++ x my_view
3+ ^
tests/golden/lex-name-bad-3/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-name-bad-3/source.jibb:1:5: a decimal is digits in groups of three joined by dots, as 1.000
2+++ 2nd 5
3+ ^
tests/golden/lex-name-bad-4/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-name-bad-4/source.jibb:1:4: unexpected `-`: a name starts with a letter, and Jibb has no operators
2+++ -view 5
3+ ^
tests/golden/lex-name-ok-1/tokens.txtnew file+31
@@ -0,0 +1,31 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit 1
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name todo-list-2
7+2:16 lit 2
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name x1y2
11+3:9 lit 3
12+4:1 NEWLINE
13+4:1 glyph +$
14+4:4 name my-mold-9
15+4:14 aura @ud
16+5:1 NEWLINE
17+5:1 glyph ++
18+5:4 name f
19+5:6 glyph |=
20+5:9 glyph [
21+5:10 tight name some-face
22+5:19 tight glyph =
23+5:20 tight aura @
24+5:22 name a1
25+5:24 tight glyph =
26+5:25 tight aura @
27+5:26 tight glyph ]
28+6:3 INDENT
29+6:3 name some-face
30+6:12 DEDENT
31+6:12 NEWLINE
tests/golden/lex-null-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-null-bad-1/source.jibb:1:7: `~` alone is null, and nothing here reads as a ship, date, duration or knot
2+++ x ~x
3+ ^
tests/golden/lex-null-ok-1/tokens.txtnew file+46
@@ -0,0 +1,46 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit ~
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 glyph [
8+2:7 tight lit ~
9+2:9 lit ~
10+2:10 tight glyph ]
11+3:1 NEWLINE
12+3:1 glyph ++
13+3:4 name c
14+3:6 glyph (
15+3:7 tight name f
16+3:9 lit ~
17+3:10 tight glyph )
18+4:1 NEWLINE
19+4:1 glyph +$
20+4:4 name d
21+4:6 lit ~
22+5:1 NEWLINE
23+5:1 glyph ++
24+5:4 name e
25+5:6 glyph |=
26+5:9 name u
27+5:10 tight glyph =
28+5:11 tight glyph (
29+5:12 tight name unit
30+5:17 aura @t
31+5:19 tight glyph )
32+6:3 INDENT
33+6:3 glyph ?-
34+6:6 name u
35+7:5 INDENT
36+7:5 lit ~
37+7:12 str ""
38+8:5 NEWLINE
39+8:5 glyph [
40+8:6 tight lit ~
41+8:8 name x
42+8:9 tight glyph ]
43+8:12 name x
44+8:13 DEDENT
45+8:13 DEDENT
46+8:13 NEWLINE
tests/golden/lex-open-bracket-bad-1/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name y
7+2:6 lit 5
8+2:7 NEWLINE
tests/golden/lex-open-bracket-bad-2/tokens.txtnew file+11
@@ -0,0 +1,11 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+2:3 INDENT
5+2:3 lit 1
6+3:3 NEWLINE
7+3:3 lit 2
8+4:1 DEDENT
9+4:1 NEWLINE
10+4:1 glyph ]
11+4:2 NEWLINE
tests/golden/lex-open-bracket-bad-3/tokens.txtnew file+10
@@ -0,0 +1,10 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+2:3 INDENT
5+2:3 lit 1
6+3:3 NEWLINE
7+3:3 lit 2
8+3:4 tight glyph ]
9+3:5 DEDENT
10+3:5 NEWLINE
tests/golden/lex-open-bracket-bad-4/tokens.txtnew file+13
@@ -0,0 +1,13 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph (
4+1:7 tight name column
5+1:14 lit ~
6+1:16 glyph ~[
7+2:5 INDENT
8+2:5 glyph (
9+2:6 tight name text
10+2:11 str "a"
11+2:14 tight glyph )
12+2:15 DEDENT
13+2:15 NEWLINE
tests/golden/lex-open-bracket-ok-1/tokens.txtnew file+59
@@ -0,0 +1,59 @@
1+1:1 glyph ++
2+1:4 name items
3+2:3 INDENT
4+2:3 glyph ~[
5+3:5 INDENT
6+3:5 glyph (
7+3:6 tight name text
8+3:11 str "a"
9+3:14 tight glyph )
10+4:5 NEWLINE
11+4:5 name text
12+4:10 str "b"
13+5:1 DEDENT
14+5:1 DEDENT
15+5:1 NEWLINE
16+5:1 glyph ++
17+5:4 name record
18+6:3 INDENT
19+6:3 glyph [
20+7:5 INDENT
21+7:5 name text
22+7:9 tight glyph =
23+7:10 tight str "milk"
24+8:5 NEWLINE
25+8:5 name done
26+8:9 tight glyph =
27+8:10 tight lit %.n
28+9:1 DEDENT
29+9:1 DEDENT
30+9:1 NEWLINE
31+9:1 glyph ++
32+9:4 name changed
33+10:3 INDENT
34+10:3 name m
35+10:4 tight glyph (
36+11:5 INDENT
37+11:5 name note
38+11:9 tight glyph =
39+11:10 tight str "x"
40+12:5 NEWLINE
41+12:5 name error
42+12:10 tight glyph =
43+12:11 tight lit ~
44+13:1 DEDENT
45+13:1 DEDENT
46+13:1 NEWLINE
47+13:1 glyph ++
48+13:4 name grouped
49+14:3 INDENT
50+14:3 glyph (
51+14:4 tight name f
52+14:6 name a
53+15:5 INDENT
54+15:5 name b
55+16:5 NEWLINE
56+16:5 name c
57+16:6 DEDENT
58+16:6 DEDENT
59+16:6 NEWLINE
tests/golden/lex-open-bracket-ok-2/tokens.txtnew file+29
@@ -0,0 +1,29 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+2:3 INDENT
5+2:3 glyph ~[
6+3:5 INDENT
7+3:5 lit 1
8+4:5 NEWLINE
9+4:5 lit 2
10+5:3 DEDENT
11+5:3 NEWLINE
12+5:3 glyph ~[
13+5:5 tight lit 3
14+5:7 lit 4
15+5:8 tight glyph ]
16+6:3 NEWLINE
17+6:3 glyph [
18+6:4 tight name a
19+6:5 tight glyph =
20+6:6 tight lit 1
21+7:5 INDENT
22+7:5 name b
23+7:6 tight glyph =
24+7:7 tight lit 2
25+8:3 DEDENT
26+8:3 NEWLINE
27+8:3 lit 5
28+8:4 DEDENT
29+8:4 NEWLINE
tests/golden/lex-pair-binding-bad-1/tokens.txtnew file+13
@@ -0,0 +1,13 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name pad
4+1:9 tight glyph +
5+1:10 tight name f
6+1:12 name a
7+2:1 NEWLINE
8+2:1 glyph ++
9+2:4 name y
10+2:6 glyph `
11+2:7 tight name f
12+2:9 name a
13+2:10 NEWLINE
tests/golden/lex-pair-binding-ok-1/tokens.txtnew file+17
@@ -0,0 +1,17 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name f
4+1:8 name pad
5+1:11 tight glyph +
6+1:12 tight lit %s3
7+1:16 name gap
8+1:19 tight glyph +
9+1:20 tight lit %s2
10+2:1 NEWLINE
11+2:1 glyph ++
12+2:4 name y
13+2:6 name f
14+2:8 glyph `
15+2:9 tight name a
16+2:11 name b
17+2:12 NEWLINE
tests/golden/lex-path-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-path-bad-1/source.jibb:1:7: unexpected `P`: a path segment holds lowercase letters, digits and - . ~ _
2++$ x /Posts
3+ ^
tests/golden/lex-path-ok-1/tokens.txtnew file+33
@@ -0,0 +1,33 @@
1+1:1 glyph /=
2+1:5 name card
3+1:11 glyph /
4+1:12 tight knot ui
5+1:14 tight glyph /
6+1:15 tight knot components
7+1:25 tight glyph /
8+1:26 tight knot card
9+2:1 NEWLINE
10+2:1 glyph +$
11+2:4 name a
12+2:6 glyph /
13+2:7 tight knot posts
14+2:12 tight glyph /
15+2:13 tight knot ~zod
16+3:1 NEWLINE
17+3:1 glyph +$
18+3:4 name b
19+3:6 glyph /
20+4:1 NEWLINE
21+4:1 glyph +$
22+4:4 name c
23+4:6 glyph /
24+4:7 tight knot todo
25+4:11 tight glyph /
26+4:12 tight glyph [
27+4:13 tight name id
28+4:15 tight glyph =
29+4:16 tight aura @ud
30+4:19 tight glyph ]
31+4:20 tight glyph /
32+4:21 tight knot comments
33+4:29 NEWLINE
tests/golden/lex-rune-layout-bad-1/tokens.txtnew file+13
@@ -0,0 +1,13 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name n
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+2:1 NEWLINE
8+2:1 glyph (
9+2:2 tight name add
10+2:6 name n
11+2:8 lit 1
12+2:9 tight glyph )
13+2:10 NEWLINE
tests/golden/lex-rune-layout-bad-2/tokens.txtnew file+10
@@ -0,0 +1,10 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~&
4+1:9 str "hi"
5+1:14 lit 5
6+2:1 NEWLINE
7+2:1 glyph ++
8+2:4 name y
9+2:6 lit 6
10+2:7 NEWLINE
tests/golden/lex-rune-layout-bad-3/tokens.txtnew file+9
@@ -0,0 +1,9 @@
1+1:1 glyph ++
2+1:4 name x
3+2:3 INDENT
4+2:3 glyph ~&
5+2:6 str "hi"
6+3:3 NEWLINE
7+3:3 lit 5
8+3:4 DEDENT
9+3:4 NEWLINE
tests/golden/lex-rune-layout-bad-4/tokens.txtnew file+19
@@ -0,0 +1,19 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name b
5+1:10 tight glyph =
6+1:11 tight glyph ?
7+2:3 INDENT
8+2:3 glyph ?-
9+2:6 name b
10+2:8 lit %.y
11+2:12 lit 1
12+2:14 lit %.n
13+2:18 lit 2
14+3:1 DEDENT
15+3:1 NEWLINE
16+3:1 glyph ++
17+3:4 name g
18+3:6 lit 3
19+3:7 NEWLINE
tests/golden/lex-rune-layout-ok-1/tokens.txtnew file+100
@@ -0,0 +1,100 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 glyph |=
4+1:9 name n
5+1:10 tight glyph =
6+1:11 tight aura @ud
7+1:15 name add
8+1:19 name n
9+1:21 lit 1
10+2:1 NEWLINE
11+2:1 glyph ++
12+2:4 name b
13+2:6 glyph |=
14+2:9 name n
15+2:10 tight glyph =
16+2:11 tight aura @ud
17+3:3 INDENT
18+3:3 glyph (
19+3:4 tight name add
20+3:8 name n
21+3:10 lit 1
22+3:11 tight glyph )
23+4:1 DEDENT
24+4:1 NEWLINE
25+4:1 glyph ++
26+4:4 name c
27+4:6 glyph ^-
28+4:9 aura @ud
29+4:13 lit 5
30+5:1 NEWLINE
31+5:1 glyph ++
32+5:4 name d
33+5:6 glyph ^-
34+5:9 aura @ud
35+6:3 INDENT
36+6:3 lit 5
37+7:1 DEDENT
38+7:1 NEWLINE
39+7:1 glyph ++
40+7:4 name e
41+7:6 glyph |=
42+7:9 name n
43+7:10 tight glyph =
44+7:11 tight aura @ud
45+8:3 INDENT
46+8:3 glyph ~&
47+8:6 name n
48+9:5 INDENT
49+9:5 glyph (
50+9:6 tight name add
51+9:10 name n
52+9:12 lit 1
53+9:13 tight glyph )
54+10:1 DEDENT
55+10:1 DEDENT
56+10:1 NEWLINE
57+10:1 glyph ++
58+10:4 name f
59+10:6 glyph |=
60+10:9 name b
61+10:10 tight glyph =
62+10:11 tight glyph ?
63+11:3 INDENT
64+11:3 glyph ?-
65+11:6 name b
66+12:5 INDENT
67+12:5 lit %.y
68+12:10 lit 1
69+13:5 NEWLINE
70+13:5 lit %.n
71+14:7 INDENT
72+14:7 lit 2
73+15:1 DEDENT
74+15:1 DEDENT
75+15:1 DEDENT
76+15:1 NEWLINE
77+15:1 glyph +$
78+15:4 name g
79+16:3 INDENT
80+16:3 glyph [
81+16:4 tight name a
82+16:5 tight glyph =
83+16:6 tight aura @
84+16:8 name b
85+16:9 tight glyph =
86+16:10 tight aura @
87+16:11 tight glyph ]
88+17:1 DEDENT
89+17:1 NEWLINE
90+17:1 glyph +$
91+17:4 name h
92+18:3 INDENT
93+18:3 glyph $?
94+19:5 INDENT
95+19:5 lit %a
96+20:5 NEWLINE
97+20:5 lit %b
98+20:7 DEDENT
99+20:7 DEDENT
100+20:7 NEWLINE
tests/golden/lex-ship-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-ship-bad-1/source.jibb:1:13: a ship is syllables in pairs joined by hyphens, as ~zod, ~marzod or ~sampel-palnet
2+++ x ~sampelpalnet
3+ ^
tests/golden/lex-ship-ok-1/tokens.txtnew file+12
@@ -0,0 +1,12 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit ~zod
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 lit ~marzod
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 lit ~sampel-palnet
12+3:20 NEWLINE
tests/golden/lex-spacing-bad-1/tokens.txtnew file+13
@@ -0,0 +1,13 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+1:8 tight glyph (
5+1:9 tight name text
6+1:14 str "a"
7+1:17 tight glyph )
8+1:18 tight glyph (
9+1:19 tight name text
10+1:24 str "b"
11+1:27 tight glyph )
12+1:28 tight glyph ]
13+1:29 NEWLINE
tests/golden/lex-spacing-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-spacing-bad-2/source.jibb:1:7: a tab: Jibb uses spaces only
2+++ x f a
3+ ^
tests/golden/lex-spacing-bad-3/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit 5
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name y
7+2:6 lit 6
8+2:7 NEWLINE
tests/golden/lex-spacing-bad-4/tokens.txtnew file+14
@@ -0,0 +1,14 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph [
4+1:8 name a
5+1:10 name b
6+1:12 glyph ]
7+2:1 NEWLINE
8+2:1 glyph ++
9+2:4 name y
10+2:6 glyph ~[
11+2:9 lit 1
12+2:11 lit 2
13+2:13 glyph ]
14+2:14 NEWLINE
tests/golden/lex-spacing-ok-1/tokens.txtnew file+51
@@ -0,0 +1,51 @@
1+1:1 glyph /=
2+1:5 name api
3+1:11 glyph /
4+1:12 tight knot ui
5+1:14 tight glyph /
6+1:15 tight knot api
7+1:18 tight glyph /
8+1:19 tight knot blog
9+2:1 NEWLINE
10+2:1 glyph /=
11+2:5 name card
12+2:11 glyph /
13+2:12 tight knot ui
14+2:14 tight glyph /
15+2:15 tight knot components
16+2:25 tight glyph /
17+2:26 tight knot card
18+4:1 NEWLINE
19+4:1 glyph ++
20+4:4 name short
21+4:12 lit 1
22+5:1 NEWLINE
23+5:1 glyph ++
24+5:4 name longer
25+5:12 glyph ~[
26+5:14 tight lit 1
27+5:19 lit 2
28+5:20 tight glyph ]
29+6:1 NEWLINE
30+6:1 glyph ++
31+6:4 name f
32+6:6 glyph |=
33+6:9 name s
34+6:10 tight glyph =
35+6:11 tight glyph *
36+7:3 INDENT
37+7:3 glyph ?-
38+7:6 name s
39+8:5 INDENT
40+8:5 lit %a
41+8:11 glyph (
42+8:12 tight name add
43+8:17 lit 1
44+8:20 lit 2
45+8:21 tight glyph )
46+9:5 NEWLINE
47+9:5 glyph *
48+9:11 lit ~
49+9:12 DEDENT
50+9:12 DEDENT
51+9:12 NEWLINE
tests/golden/lex-string-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-string-bad-1/source.jibb:1:6: there is no '…' form: strings are "…"
2+++ x 'milk'
3+ ^
tests/golden/lex-string-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-string-bad-2/source.jibb:1:11: this string has no closing `"` on its line
2+++ x "milk
3+ ^
tests/golden/lex-string-ok-1/tokens.txtnew file+12
@@ -0,0 +1,12 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 str "milk"
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 str ""
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 str "it's fine: 'single quotes', [brackets], ~tildes, %percents and /slashes are text"
12+3:88 NEWLINE
tests/golden/lex-term-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-term-bad-1/source.jibb:1:7: `%` begins a term, a loobean or `%/`
2+++ x %Add
3+ ^
tests/golden/lex-term-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-term-bad-2/source.jibb:1:8: unexpected `a`: a numeric term is `%` and digits only, as %1000
2+++ x %9a
3+ ^
tests/golden/lex-term-bad-3/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-term-bad-3/source.jibb:1:8: unexpected `.`: a numeric term is `%` and digits only, as %1000
2+++ x %1.000
3+ ^
tests/golden/lex-term-ok-1/tokens.txtnew file+24
@@ -0,0 +1,24 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 lit %add
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 lit %a1-b
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 lit %0
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name d
15+4:6 lit %42
16+5:1 NEWLINE
17+5:1 glyph ++
18+5:4 name e
19+5:6 lit %&
20+6:1 NEWLINE
21+6:1 glyph ++
22+6:4 name f
23+6:6 lit %|
24+6:8 NEWLINE
tests/golden/lex-tight-change-bad-1/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name m
4+1:8 glyph (
5+1:9 tight name note
6+1:14 name text
7+1:18 tight glyph )
8+1:19 NEWLINE
tests/golden/lex-tight-change-bad-2/tokens.txtnew file+9
@@ -0,0 +1,9 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name m
4+1:8 glyph (
5+1:9 tight name note
6+1:13 tight glyph =
7+1:14 tight name text
8+1:18 tight glyph )
9+1:19 NEWLINE
tests/golden/lex-tight-change-ok-1/tokens.txtnew file+36
@@ -0,0 +1,36 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 name m
4+1:7 tight glyph (
5+1:8 tight name note
6+1:12 tight glyph =
7+1:13 tight name text
8+1:17 tight glyph )
9+2:1 NEWLINE
10+2:1 glyph ++
11+2:4 name b
12+2:6 name s
13+2:7 tight glyph (
14+2:8 tight name items
15+2:13 tight glyph =
16+2:14 tight glyph [
17+2:15 tight name item
18+2:20 wing items.s
19+2:27 tight glyph ]
20+2:29 name open
21+2:33 tight glyph =
22+2:34 tight glyph (
23+2:35 tight name not
24+2:39 wing open.s
25+2:45 tight glyph )
26+2:46 tight glyph )
27+3:1 NEWLINE
28+3:1 glyph ++
29+3:4 name c
30+3:6 wing cart.m
31+3:12 tight glyph (
32+3:13 tight name note
33+3:17 tight glyph =
34+3:18 tight str ""
35+3:20 tight glyph )
36+3:21 NEWLINE
tests/golden/lex-tight-ctor-bad-1/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph (
4+1:7 tight wing state.cart
5+1:18 glyph |=
6+1:21 lit %got
7+1:25 tight glyph )
8+1:26 NEWLINE
tests/golden/lex-tight-ctor-bad-2/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph |=
4+1:9 lit %got
5+2:3 INDENT
6+2:3 lit ~
7+2:4 DEDENT
8+2:4 NEWLINE
tests/golden/lex-tight-ctor-ok-1/tokens.txtnew file+22
@@ -0,0 +1,22 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph |=
4+1:8 tight lit %got
5+2:1 NEWLINE
6+2:1 glyph ++
7+2:4 name y
8+2:6 glyph (
9+2:7 tight wing state.cart
10+2:18 glyph |=
11+2:20 tight lit %got
12+2:24 tight glyph )
13+3:1 NEWLINE
14+3:1 glyph ++
15+3:4 name z
16+3:6 glyph ~[
17+3:8 tight glyph |=
18+3:10 tight lit %noted
19+3:17 glyph |=
20+3:19 tight lit %acked
21+3:25 tight glyph ]
22+3:26 NEWLINE
tests/golden/lex-tight-opener-bad-1/tokens.txtnew file+7
@@ -0,0 +1,7 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 lit ~
4+1:8 glyph [
5+1:9 tight name a
6+1:10 tight glyph ]
7+1:11 NEWLINE
tests/golden/lex-tight-opener-bad-2/tokens.txtnew file+12
@@ -0,0 +1,12 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph (
4+1:7 tight name turn
5+1:12 name ps
6+1:15 glyph |=
7+1:18 glyph (
8+1:19 tight name p
9+1:21 wing title.p
10+1:28 tight glyph )
11+1:29 tight glyph )
12+1:30 NEWLINE
tests/golden/lex-tight-opener-bad-3/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph +$
2+1:4 name x
3+1:6 glyph $?
4+1:9 glyph (
5+1:10 tight lit %a
6+1:13 lit %b
7+1:15 tight glyph )
8+1:16 NEWLINE
tests/golden/lex-tight-opener-bad-4/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-tight-opener-bad-4/source.jibb:1:8: `$-` has only the wide form `$-(sample product)`
2++$ x $- (@t @t)
3+ ^
tests/golden/lex-tight-opener-ok-1/tokens.txtnew file+32
@@ -0,0 +1,32 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 glyph ~[
4+1:8 tight lit 1
5+1:10 lit 2
6+1:11 tight glyph ]
7+2:1 NEWLINE
8+2:1 glyph ++
9+2:4 name b
10+2:6 glyph |=(
11+2:9 tight name n
12+2:11 glyph (
13+2:12 tight name add
14+2:16 name n
15+2:18 lit 1
16+2:19 tight glyph )
17+2:20 tight glyph )
18+3:1 NEWLINE
19+3:1 glyph +$
20+3:4 name c
21+3:6 glyph $?(
22+3:9 tight lit %a
23+3:12 lit %b
24+3:14 tight glyph )
25+4:1 NEWLINE
26+4:1 glyph +$
27+4:4 name d
28+4:6 glyph $-(
29+4:9 tight aura @t
30+4:12 aura @t
31+4:14 tight glyph )
32+4:15 NEWLINE
tests/golden/lex-tight-pair-bad-1/tokens.txtnew file+8
@@ -0,0 +1,8 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+1:8 tight name gap
5+1:12 glyph +
6+1:14 lit %s2
7+1:17 tight glyph ]
8+1:18 NEWLINE
tests/golden/lex-tight-pair-ok-1/tokens.txtnew file+45
@@ -0,0 +1,45 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 name a
4+1:7 tight glyph +
5+1:8 tight name b
6+2:1 NEWLINE
7+2:1 glyph ++
8+2:4 name y
9+2:6 glyph ~[
10+2:8 tight name gap
11+2:11 tight glyph +
12+2:12 tight lit %s2
13+2:16 name width
14+2:21 tight glyph +
15+2:22 tight glyph [
16+2:23 tight lit %fill
17+2:29 lit 1
18+2:30 tight glyph ]
19+2:32 name pad
20+2:35 tight glyph +
21+2:36 tight glyph (
22+2:37 tight name f
23+2:39 name a
24+2:40 tight glyph )
25+2:42 name mark
26+2:46 tight glyph +
27+2:47 tight glyph `
28+2:48 tight name b
29+2:50 name list
30+2:54 tight glyph +
31+2:55 tight glyph ~[
32+2:57 tight lit 1
33+2:59 lit 2
34+2:60 tight glyph ]
35+2:62 name link
36+2:66 tight glyph +
37+2:67 tight glyph %/
38+2:69 tight knot blog
39+2:74 name nested
40+2:80 tight glyph +
41+2:81 tight name a
42+2:82 tight glyph +
43+2:83 tight name b
44+2:84 tight glyph ]
45+2:85 NEWLINE
tests/golden/lex-tight-qath-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-tight-qath-bad-1/source.jibb:1:7: `%` begins a term, a loobean or `%/`
2+++ x % /blog
3+ ^
tests/golden/lex-tight-qath-bad-2/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-tight-qath-bad-2/source.jibb:1:12: unexpected `?`: a path carries no query, and a segment holds lowercase letters, digits and - . ~ _
2+++ x %/blog?page=2
3+ ^
tests/golden/lex-tight-qath-bad-3/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-tight-qath-bad-3/source.jibb:1:12: unexpected `#`: a path carries no fragment, and a segment holds lowercase letters, digits and - . ~ _
2+++ x %/blog#top
3+ ^
tests/golden/lex-tight-qath-ok-1/tokens.txtnew file+42
@@ -0,0 +1,42 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 glyph %/
4+1:8 tight knot blog
5+1:12 tight glyph /
6+1:13 tight glyph (
7+1:14 tight name slug
8+1:18 tight glyph )
9+2:1 NEWLINE
10+2:1 glyph ++
11+2:4 name b
12+2:6 glyph %/
13+3:1 NEWLINE
14+3:1 glyph ++
15+3:4 name c
16+3:6 glyph %/
17+3:8 tight knot static
18+3:14 tight glyph /
19+3:15 tight knot img
20+3:18 tight glyph /
21+3:19 tight knot logo.png
22+4:1 NEWLINE
23+4:1 glyph ++
24+4:4 name d
25+4:6 glyph %/
26+4:8 tight knot blog
27+4:12 tight glyph /
28+4:13 tight glyph (
29+4:14 tight wing slug.p
30+4:20 tight glyph )
31+4:21 tight glyph /
32+4:22 tight knot comments
33+5:1 NEWLINE
34+5:1 glyph ++
35+5:4 name e
36+5:6 glyph %/
37+5:8 tight knot todo
38+5:12 tight glyph /
39+5:13 tight glyph (
40+5:14 tight name id
41+5:16 tight glyph )
42+5:17 NEWLINE
tests/golden/lex-tight-unit-bad-1/tokens.txtnew file+5
@@ -0,0 +1,5 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph `
4+1:8 name x
5+1:9 NEWLINE
tests/golden/lex-tight-unit-ok-1/tokens.txtnew file+25
@@ -0,0 +1,25 @@
1+1:1 glyph ++
2+1:4 name x
3+1:6 glyph ~[
4+1:8 tight glyph `
5+1:9 tight str "Too long"
6+1:20 glyph `
7+1:21 tight glyph [
8+1:22 tight name a
9+1:24 name b
10+1:25 tight glyph ]
11+1:27 glyph `
12+1:28 tight glyph `
13+1:29 tight name c
14+1:31 glyph `
15+1:32 tight glyph %/
16+1:34 tight knot blog
17+1:39 glyph `
18+1:40 tight glyph (
19+1:41 tight name f
20+1:43 name a
21+1:44 tight glyph )
22+1:46 glyph `
23+1:47 tight lit ~
24+1:48 tight glyph ]
25+1:49 NEWLINE
tests/golden/lex-tight-wing-bad-1/tokens.txtnew file+3
@@ -0,0 +1,3 @@
1+/tests/golden/lex-tight-wing-bad-1/source.jibb:1:12: unexpected `.`: a `.` joins the names of a wing, as title.p
2+++ x title . p
3+ ^
tests/golden/lex-tight-wing-ok-1/tokens.txtnew file+22
@@ -0,0 +1,22 @@
1+1:1 glyph ++
2+1:4 name a
3+1:6 wing a.b
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name b
7+2:6 wing space.theme.theme
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name c
11+3:6 glyph (
12+3:7 tight name lent
13+3:12 wing items.cart.m
14+3:24 tight glyph )
15+4:1 NEWLINE
16+4:1 glyph +$
17+4:4 name d
18+4:6 glyph (
19+4:7 tight name list
20+4:12 wing post.blog
21+4:21 tight glyph )
22+4:22 NEWLINE
tools/urbit_eval.py+18−11
@@ -31,6 +31,7 @@ import os
31import re
31import re
32import shutil
32import shutil
33import subprocess
33import subprocess
34+import tempfile
34
35
35from noun import bytes_to_atom, cue
36from noun import bytes_to_atom, cue
36
37
@@ -228,14 +229,20 @@ def run_eval(program, jam, timeout=None):
228 cmd = [find_urbit(), 'eval'] + (['-j', '-n'] if jam else [])
229 cmd = [find_urbit(), 'eval'] + (['-j', '-n'] if jam else [])
229 res = EvalResult()
230 res = EvalResult()
230 res.timeout = timeout
231 res.timeout = timeout
232+ # stdout goes to a file, not a pipe: urbit eval exits before a pipe
233+ # drains, so piped output is cut off at 64 KB.
234+ with tempfile.TemporaryFile() as out:
231− try:
235+ try:
232− proc = subprocess.run(cmd, input=program.encode(),
236+ proc = subprocess.run(cmd, input=program.encode(),
233− stdout=subprocess.PIPE, stderr=subprocess.PIPE,
237+ stdout=out, stderr=subprocess.PIPE,
234− timeout=timeout)
238+ timeout=timeout)
235− except subprocess.TimeoutExpired as e:
239+ except subprocess.TimeoutExpired:
236− res.timed_out = True
240+ res.timed_out = True
241+ out.seek(0)
237− res.trace = [l for l in _clean_lines(e.stdout or b'') if l.strip()]
242+ res.trace = [l for l in _clean_lines(out.read()) if l.strip()]
238− return res
243+ return res
244+ out.seek(0)
245+ stdout = out.read()
239 res.status = proc.returncode
246 res.status = proc.returncode
240 for line in _clean_lines(proc.stderr):
247 for line in _clean_lines(proc.stderr):
241 m = BAIL.match(line.strip())
248 m = BAIL.match(line.strip())
@@ -245,15 +252,15 @@ def run_eval(program, jam, timeout=None):
245 res.notes.append(line.rstrip())
252 res.notes.append(line.rstrip())
246 if not res.bail and proc.returncode == 0:
253 if not res.bail and proc.returncode == 0:
247 if not jam:
254 if not jam:
248− res.text = strip_ansi(proc.stdout.decode('utf-8', 'replace'))
255+ res.text = strip_ansi(stdout.decode('utf-8', 'replace'))
249 res.ok = True
256 res.ok = True
250 return res
257 return res
251− frame = _newt_frame(proc.stdout)
258+ frame = _newt_frame(stdout)
252 if frame is not None:
259 if frame is not None:
253 res.noun = cue(bytes_to_atom(frame))
260 res.noun = cue(bytes_to_atom(frame))
254 res.ok = True
261 res.ok = True
255 return res
262 return res
256− res.trace = [l.rstrip() for l in _clean_lines(proc.stdout) if l.strip()]
263+ res.trace = [l.rstrip() for l in _clean_lines(stdout) if l.strip()]
257 return res
264 return res
258
265
259
266