@@ -19,9 +19,9 @@
19:: fails: an error it finds is its last token (2.0), and +layout-error
19:: fails: an error it finds is its last token (2.0), and +layout-error
20:: takes it out.
20:: takes it out.
22−:: Status: the types, the printers, +golden and the layout pass
22+:: Status: the types, the printers, +golden, the layout pass (+layout,
23−:: (+layout, +lexer) work. +parse-tokens is a stub that returns an
23+:: +lexer) and the parser (+parse-tokens, +parser) work, and +golden
24−:: error; it is implemented next, against the design below. Choices the
24+:: checks every tree's spans (+check-spans, section 1). Choices the
25:: doc leaves open are marked "(doc question)": they follow the most
25:: doc leaves open are marked "(doc question)": they follow the most
26:: likely reading and are listed, with the doc's words, for the doc's
26:: likely reading and are listed, with the doc's words, for the doc's
27:: author to settle. The golden corpus's "expect:" lines give each
27:: author to settle. The golden corpus's "expect:" lines give each
@@ -50,8 +50,9 @@
50:: code, not at the line that closes them. Every node's span holds its
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
51:: children's spans, in source order. The printed tree shows starts
52:: only, and milestone 1's errors use starts only, so ends are first
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
53+:: used by milestone 2's excerpts. Until then +check-spans tests the two
54−:: the two rules above on every golden tree.
54+:: rules above on every tree +golden prints, and a tree that breaks one
55+:: ends with a line "SPAN ERROR: (<kind> <start> to <end>) <why>".
56:: ===================================================================
57:: ===================================================================
57:: 2. The layout pass (+layout)
58:: 2. The layout pass (+layout)
@@ -313,14 +314,15 @@
313:: 3. The parser (+parse-tokens)
314:: 3. The parser (+parse-tokens)
314:: ===================================================================
315:: ===================================================================
316−:: Hand-written recursive descent over the token list: one arm per EBNF
317+:: Hand-written recursive descent over the token list (+parser): one
317−:: rule, each taking the remaining tokens and returning (pare node): the
318+:: arm per EBNF rule, each taking the remaining tokens and returning
318−:: node and the tokens after it, or an error. Steps chain with ;< and
319+:: (pare node): the node and the tokens after it, or an error. Steps
319−:: +then, so an error stops the parse:
320+:: chain with ;< and +then, so an error stops the parse (+read-cast):
321−:: ;< [s=shape ts=(list token)] then (mold ts)
322+:: ;< [s=shape after=(list token)] then (read-mold ts)
322−:: ;< [e=expr ts=(list token)] then (expr-or-body ts)
323+:: ;< [e=expr more=(list token)] then
324+:: (read-expr-or-body "the mold" after)
323−:: [%& [%cast [beg.at.rune end:(span-of e)] s e] ts]
325+:: [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
325:: Why: after the layout pass the grammar is LL(2). Each choice is made by
327:: Why: after the layout pass the grammar is LL(2). Each choice is made by
326:: the next token, at most with the one after it and whether it is tight:
328:: the next token, at most with the one after it and whether it is tight:
@@ -341,10 +343,13 @@
341:: An operand that isn't where an expression starts (a call's argument,
343:: 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
344:: 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:
345:: 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
346+:: (state.cart |= %got) is an error at the space after |=, 1:20. A loop
345−:: over many items (definitions, arms, lines, items) may recurse: vere's
347+:: over many items (definitions, arms, lines, items) is a trap whose
346−:: stack takes ten million plain frames, so no Jibb file nests or runs
348+:: every step, through +then, is a tail call, so a long module grows no
347−:: long enough to overflow it.
349+:: stack. Nesting does, by a few frames a level: 100.000 nested
350+:: parentheses parse, and so does a 20.000-line module. +golden's tree
351+:: is another matter: its indent grows with depth, so 7.000 nested
352+:: parentheses print as 49 MB and 10.000 run out of memory.
349:: The EBNF and its nodes (see the types below):
354:: The EBNF and its nodes (see the types below):
350:: module { import NEWLINE } { definition NEWLINE }, then the end
355:: module { import NEWLINE } { definition NEWLINE }, then the end
@@ -462,7 +467,8 @@
462:: out: eq is a gate", = followed tight by / is "=/ is left out: ++
467:: out: eq is a gate", = followed tight by / is "=/ is left out: ++
463:: defines values", and * is "*mold is left out: no defaults"; ^- or ?-
468:: defines values", and * is "*mold is left out: no defaults"; ^- or ?-
464:: followed tight by ( is "the wide form ^-(…) is left out: indentation
469:: followed tight by ( is "the wide form ^-(…) is left out: indentation
465−:: covers it". Examples:
470+:: covers it". The messages quote that code in backticks (2.0), as in
471+:: "`=(a b)` is left out: eq is a gate". Examples:
466:: expected `]` or an item on a deeper line, found a line at the same
472:: expected `]` or an item on a deeper line, found a line at the same
468:: expected the end of the line, found a deeper line; only a bracket
474:: expected the end of the line, found a deeper line; only a bracket
@@ -816,22 +822,21 @@
816:: +parse-tokens: tokens to tree (design: section 3)
822:: +parse-tokens: tokens to tree (design: section 3)
818:: It accepts no error token, so it fails at the first of its own
824:: 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
825+:: error and the layout pass's (2.0). +parser does the work.
820−:: that comes first, as the parser will, and fails otherwise.
822++ parse-tokens
827++ parse-tokens
823 |= [file=path toks=(list token)]
828 |= [file=path toks=(list token)]
824 ^- (each module error)
829 ^- (each module error)
825− ?: ?=([[* * [%error *]] *] toks)
830+ (~(read-module parser file) toks)
826− (fail file toks "a module")
827− =/ at=loc ?~(toks [1 1] (where i.toks))
828− [%| file line.at col.at "parser not implemented"]
830:: +golden: both stages printed, or the rendered error
832:: +golden: both stages printed, or the rendered error
832:: tokens: the layout pass's tokens, or its error if it found one
834:: tokens: the layout pass's tokens, or its error if it found one
833:: tree: the parser's tree, or the first error of either stage, which
835:: 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)
836+:: the parser reports since it accepts no error token (2.0). A tree
837+:: whose spans break section 1's rules (+check-spans) gets a last
838+:: line saying how, "SPAN ERROR: …", so every golden case checks
837 |= [file=path src=@t]
842 |= [file=path src=@t]
@@ -843,8 +848,13 @@
843 =/ par (parse-tokens file toks)
848 =/ par (parse-tokens file toks)
844 ?: ?=(%| -.par) (show-error src p.par)
849 ?: ?=(%| -.par) (show-error src p.par)
845 :: a parser that accepted an error token would be wrong; say so
850 :: a parser that accepted an error token would be wrong; say so
846− ?^ bad (show-error src u.bad)
852+ %^ cat 3 (show-error src u.bad)
853+ '\0aPARSER ERROR: the parser accepted an error token'
847− (show-module p.par)
854+ =/ tree=@t (show-module p.par)
855+ =/ why=(unit tape) (check-spans p.par toks)
857+ (cat 3 tree (crip "\0aSPAN ERROR: {u.why}"))
@@ -1595,6 +1605,7 @@
1595 %indent "a deeper line"
1605 %indent "a deeper line"
1596 %dedent "a shallower line"
1606 %dedent "a shallower line"
1597 %newline "a line at the same depth"
1607 %newline "a line at the same depth"
1600 %name "`{(trip p.x)}`"
1611 %name "`{(trip p.x)}`"
@@ -1947,4 +1958,1344 @@
1947 :+ %| file
1958 :+ %| file
1948 :+ line.end.at.prev col.end.at.prev
1959 :+ line.end.at.prev col.end.at.prev
1949 "expected {want} right after {(show-found prev)}, found a space"
1960 "expected {want} right after {(show-found prev)}, found a space"
1962+:: +fail-why: +fail with a hint after its message, "; <why>"
1964+:: The layout pass's error, at an error token, stays as it is (2.0).
1967+ |= [file=path toks=(list token) want=tape why=tape]
1969+ =/ e=[%| p=error] (fail file toks want)
1970+ ?: &(?=(^ toks) ?=([%error *] lex.i.toks)) e
1971+ e(msg.p (weld msg.p.e "; {why}"))
1973+:: Token tests for the parser
1975+:: +is-layout: INDENT, DEDENT or NEWLINE
1980+ ?=(?(%indent %dedent %newline) lex.t)
1982+:: +is-closer: ) or ], or the } that ends an interpolation
1989+ ?=([?(%str-mid %str-tail) *] lex.t)
1992+:: +ends-call: a token that ends a call, or the operands on a group's
1993+:: first line, without an error of their own: a layout token, a
1994+:: closer, or the layout pass's error
2001+ ?=([%error *] lex.t)
2004+:: +is-operand-start: a token an operand starts with; where an operand
2005+:: goes, |= is the constructor's (section 3)
2010+ ?| ?=(?(%'%/' %'/' %'`' %'(' %'~[' %'[' %'|=(' %'|=') lex.t)
2011+ ?=([?(%lit %str %str-head %name %wing) *] lex.t)
2014+:: +is-rune: a rune that is never an operand: ^- ~& ?- !!
2019+ ?=(?(%'^-' %'~&' %'?-' %'!!') lex.t)
2021+:: +is-ctor: |= with a term tight after it, a case's constructor
2026+ ?=([[* * %'|='] [* %& [%lit %term *]] *] ts)
2028+:: +is-rune-start: a rune where an expression starts; |= is a rune
2029+:: there unless it is the constructor
2036+ &(=(%'|=' lex.i.ts) !(is-ctor ts))
2039+:: +text-piece: a string's text as its pieces: none when it is empty
2044+ ?:(=('' txt) ~ ~[[%text txt]])
2046+:: +names-of: a name's or a wing's names
2056+:: +call-of: a call's elements as one expression: one alone is itself
2061+ ?~ els [%crash *span ~]
2063+ [%call [beg:(span-of i.els) end:(span-of (rear t.els))] i.els t.els]
2065+:: +bracket-node: a tuple, list or change from its items, ending at fin
2068+ |= $: kind=?(%tuple %list %change)
2070+ target=(unit [t=token names=(list term)])
2076+ %tuple [%tuple [beg.at.op fin] its]
2077+ %list [%list [beg.at.op fin] (turn its |=(i=item val.i))]
2080+ =/ beg=loc ?~(target beg.at.op beg.at.t.u.target)
2081+ :^ %change [beg fin] ?~(target ~ names.u.target)
2082+ (turn its |=(i=item ^-(edit [at.i ?~(face.i %$ u.face.i) val.i])))
2087+:: +parser: section 3's recursive descent over one file's tokens
2089+:: Each +read- arm reads one rule of the EBNF from the head of the
2090+:: tokens it is given and returns (pare node): the node and the
2091+:: tokens after it, or the first error. It decides by the next token,
2092+:: at most with the one after it and whether that one is tight
2093+:: (section 3), so it never backtracks. A loop over items is a trap
2094+:: whose every step, through +then, is a tail call, so a long module
2095+:: grows no stack; only nesting does, and a line's nesting is bounded
2101+ :: +bad: "expected <want>, found <the next token>" (+fail)
2104+ |= [ts=(list token) want=tape]
2106+ (fail file ts want)
2108+ :: +bad-why: +bad with a hint (+fail-why)
2111+ |= [ts=(list token) want=tape why=tape]
2113+ (fail-why file ts want why)
2115+ :: +bad-space: a tight form that found a space after prev
2119+ |= [prev=token ts=(list token) want=tape]
2121+ (fail-space file prev ts want)
2123+ :: +bad-at: an error inside a token (section 3, Errors)
2126+ |= [at=loc msg=tape]
2128+ [%| file line.at col.at msg]
2130+ :: +bad-end: a line that should end and goes on
2135+ ?. ?=([[* * %indent] *] ts) (bad ts "the end of the line")
2136+ %^ bad-why ts "the end of the line"
2137+ %+ weld "only a bracket open at the end of a line, "
2138+ "or a rune's body, takes deeper lines"
2140+ :: +no-space: a token tight after an item, where a space goes
2145+ ?. ?=([[* * %'='] *] ts) (bad ts "a space between items")
2146+ %^ bad-why ts "a space between items"
2147+ "`name=value` goes in a cell, as [a=1], or a change, as m(a=1)"
2149+ :: +no-operand: a token where an operand goes that starts none, with
2150+ :: a hint for the left-out forms the lexer can't see (2.6)
2155+ =/ want=tape "an expression"
2156+ ?: ?=([[* * %'='] [* %& %'('] *] ts)
2157+ (bad-why ts want "`=(a b)` is left out: eq is a gate")
2158+ ?: ?=([[* * %'='] [* %& %'/'] *] ts)
2159+ (bad-why ts want "`=/` is left out: `++` defines values")
2160+ ?: ?=([[* * %'*'] *] ts)
2161+ (bad-why ts want "`*mold` is left out: no defaults")
2162+ ?: ?=([[* * %'+'] *] ts)
2163+ (bad-why ts want "a pair takes no spaces, as gap+%s2")
2164+ ?: &(?=(^ ts) (is-rune i.ts))
2165+ (bad-why ts want "a rune here goes in parentheses")
2168+ :: +unclosed: where the closer of the bracket op opened should be
2171+ |= [op=token close=tape ts=(list token)]
2174+ "`{close}` to close the {(show-found op)} at {(show-loc beg.at.op)}"
2175+ ?. ?=([[* * %indent] *] ts) (bad ts want)
2176+ (bad-why ts want "this bracket closes on its line")
2178+ :: +unclosed-open: a bracket that may be left open, whose line ends
2179+ :: with neither its closer nor deeper lines; last is its last item's
2180+ :: span, and noun names its items
2183+ |= [op=token close=tape noun=tape last=(unit span) ts=(list token)]
2185+ ?. ?=([[* * ?(%newline %dedent)] *] ts) (unclosed op close ts)
2186+ :: its last item ends on a later line: an item left open took them
2187+ ?: &(?=(^ last) (gth line.end.u.last line.beg.at.op))
2189+ "`{close}` to close the {(show-found op)} at {(show-loc beg.at.op)}"
2190+ "only the last bracket open at the end of a line takes the deeper lines"
2191+ (bad ts "`{close}` or {noun} on a deeper line")
2193+ :: +wide-rune: a rune followed tight; txt( is a left-out wide form
2196+ |= [txt=tape ts=(list token)]
2198+ =/ want=tape "a space after `{txt}`"
2199+ ?. ?=([[* * %'('] *] ts) (bad ts want)
2201+ "the wide form `{txt}(…)` is left out: indentation covers it"
2203+ :: +unnamed: a change's item or line without its name=
2208+ %^ bad-why ts "a named item"
2209+ "a change's items are named, as in m(done=%.y)"
2211+ :: +read-module: { import NEWLINE } { definition NEWLINE }, then the
2212+ :: end of the tokens
2216+ ^- (each module error)
2217+ =| ims=(list import)
2218+ |- ^- (each module error)
2219+ ?: ?=([[* * ?(%'/-' %'/%' %'/=')] *] ts)
2220+ ;< [im=import after=(list token)] then (read-import ts)
2221+ ?. ?=([[* * %newline] *] after) (bad-end after)
2222+ $(ims [im ims], ts t.after)
2224+ |- ^- (each module error)
2225+ ?~ ts [%& (flop ims) (flop defs)]
2226+ ?: ?=([[* * ?(%'/-' %'/%' %'/=')] *] ts)
2227+ (bad-why ts "a definition" "imports come first")
2228+ ;< [d=def after=(list token)] then (read-def ts)
2229+ ?. ?=([[* * %newline] *] after) (bad-end after)
2230+ $(defs [d defs], ts t.after)
2232+ :: +read-import: /- name, /% term, or /= name pathlit
2237+ ?~ ts (bad ts "an import")
2239+ =/ rest=(list token) t.ts
2240+ ?: &(?=(^ rest) tight.i.rest)
2241+ (bad rest "a space after {(show-found g)}")
2243+ ?: ?=([[* * [%lit %term %tas *]] *] rest)
2244+ [%& [%mark [beg.at.g end.at.i.rest] val.p.lex.i.rest] t.rest]
2245+ =/ want=tape "a mark's term, as `%todo-action`"
2246+ ?. ?=([[* * [%name *]] *] rest) (bad rest want)
2247+ (bad-why rest want "`/%` takes no face: it names the type after its mark")
2248+ ?. ?=([[* * [%name *]] *] rest) (bad rest "a name")
2251+ [%& [%sur [beg.at.g end.at.nam] p.lex.nam] t.rest]
2252+ =/ more=(list token) t.rest
2253+ ?: &(?=(^ more) tight.i.more) (bad more "a space after the name")
2254+ ?. ?=([[* * %'/'] *] more)
2255+ (bad more "a module's path, as /ui/components/card")
2256+ ;< [[sp=span segs=(list @ta)] after=(list token)] then
2257+ (read-pathlit i.more t.more)
2258+ [%& [%jibb [beg.at.g end.sp] p.lex.nam segs] after]
2260+ :: +read-pathlit: after a path's /, its knots, each after a tight /
2261+ :: and tight itself; / alone is the empty path
2264+ |= [sl=token ts=(list token)]
2265+ ^- (pare [span (list @ta)])
2266+ ?. ?=([[* %& [%knot *]] *] ts)
2267+ ?: &(?=(^ ts) tight.i.ts !(is-closer i.ts))
2268+ (bad ts "a path segment")
2270+ =/ segs=(list @ta) ~[p.lex.i.ts]
2271+ =/ fin=loc end.at.i.ts
2272+ =/ rest=(list token) t.ts
2273+ |- ^- (pare [span (list @ta)])
2274+ ?. ?=([[* %& %'/'] *] rest)
2275+ [%& [[beg.at.sl fin] (flop segs)] rest]
2276+ =/ nex=(list token) t.rest
2277+ ?: ?=([[* %& [%knot *]] *] nex)
2278+ $(segs [p.lex.i.nex segs], fin end.at.i.nex, rest t.nex)
2279+ ?: &(?=(^ nex) tight.i.nex) (bad nex "a path segment")
2280+ (bad-space i.rest nex "a path segment")
2282+ :: +read-def: ++ name, then an expression or a body; +$ name, then a
2283+ :: mold on its line or alone on a deeper one
2288+ ?~ ts (bad ts "a definition")
2290+ ?: =(%'++' lex.rune)
2291+ ;< [nam=term after=(list token)] then (read-def-name rune t.ts)
2292+ ;< [e=expr more=(list token)] then
2293+ (read-expr-or-body "the name" after)
2294+ [%& [%value [beg.at.rune end:(span-of e)] nam e] more]
2295+ ?: (is-closer rune)
2296+ %^ bad-why ts "a definition"
2297+ "this closes no bracket, as one open at the end of its line needs none"
2298+ ?. =(%'+$' lex.rune) (bad ts "a definition")
2299+ ;< [nam=term after=(list token)] then (read-def-name rune t.ts)
2300+ ?: ?=([[* * %indent] *] after)
2301+ ;< [s=shape more=(list token)] then (read-mold t.after)
2302+ ?: ?=([[* * %dedent] *] more)
2303+ [%& [%mold [beg.at.rune end:(span-of s)] nam s] t.more]
2304+ ?. ?=([[* * %newline] *] more) (bad-end more)
2305+ %^ bad-why more "the end of the mold"
2306+ "a `+$` takes one mold; a union is `$?` with its cases below"
2307+ ?: ?=([[* * ?(%newline %dedent)] *] after)
2308+ (bad after "a mold, on its line or a deeper one")
2309+ ?: &(?=(^ after) tight.i.after) (bad after "a space after the name")
2310+ ;< [s=shape more=(list token)] then (read-mold after)
2311+ [%& [%mold [beg.at.rune end:(span-of s)] nam s] more]
2313+ :: +read-def-name: after ++ or +$, a space and a name
2316+ |= [rune=token ts=(list token)]
2318+ ?: &(?=(^ ts) tight.i.ts)
2319+ (bad ts "a space after {(show-found rune)}")
2320+ ?. ?=([[* * [%name *]] *] ts) (bad ts "a name")
2321+ [%& p.lex.i.ts t.ts]
2323+ :: +read-expr-or-body: a space and an expression on the line, or a
2324+ :: body on deeper lines; what names what comes before, for errors
2326+ ++ read-expr-or-body
2327+ |= [what=tape ts=(list token)]
2329+ ?: ?=([[* * %indent] *] ts) (read-body t.ts)
2330+ ?: ?=([[* * ?(%newline %dedent)] *] ts)
2331+ (bad ts "an expression, or a body on deeper lines")
2332+ ?: &(?=(^ ts) tight.i.ts) (bad ts "a space after {what}")
2335+ :: +read-body: after its INDENT, { definition NEWLINE } expr DEDENT
2342+ ?: ?=([[* * ?(%'++' %'+$')] *] ts)
2343+ ;< [d=def after=(list token)] then (read-def ts)
2344+ ?: ?=([[* * %newline] *] after) $(defs [d defs], ts t.after)
2345+ ?. ?=([[* * %dedent] *] after) (bad-end after)
2346+ (bad after "the body's final expression, after its definitions")
2347+ ;< [e=expr after=(list token)] then (read-expr ts)
2348+ ?: ?=([[* * %dedent] *] after)
2349+ =/ ds=(list def) (flop defs)
2350+ =/ beg=loc ?~(ds beg:(span-of e) beg:(span-of i.ds))
2351+ [%& [%body [beg end:(span-of e)] ds e] t.after]
2352+ ?. ?=([[* * %newline] *] after) (bad-end after)
2353+ %^ bad-why after "the end of the body"
2354+ "a body's final expression is its last line"
2356+ :: +read-expr: a rune, or a call
2361+ ?~ ts (bad ts "an expression")
2363+ ?+ lex.t (read-call ts)
2364+ %'|=' ?:((is-ctor ts) (read-call ts) (read-gate t t.ts))
2365+ %'^-' (read-cast t t.ts)
2366+ %'~&' (read-trace t t.ts)
2367+ %'?-' (read-branch t t.ts)
2368+ %'!!' [%& [%crash at.t ~] t.ts]
2371+ :: +read-call: operand { operand }; one operand alone is itself
2376+ ;< [els=(list expr) after=(list token)] then (read-operands ts)
2377+ ?~ els (no-operand ts)
2378+ [%& (call-of els) after]
2380+ :: +read-operands: a call's operands, or those on a group's first
2381+ :: line, to the end of the call; each after the first follows a space
2385+ ^- (pare (list expr))
2387+ |- ^- (pare (list expr))
2388+ ?~ ts [%& (flop els) ts]
2390+ ?: (ends-call t) [%& (flop els) ts]
2391+ ?: &(tight.t ?=(^ els)) (no-space ts)
2392+ ?: (is-operand-start t)
2393+ ;< [e=expr more=(list token)] then (read-operand ts)
2394+ $(els [e els], ts more)
2395+ ?: &(?=(^ els) (is-rune t))
2396+ %^ bad-why ts "an expression"
2397+ "inside a call, a rune goes in parentheses"
2400+ :: +read-operand: one operand, told by its first token and, after a
2401+ :: name or a wing, by a tight ( or +
2406+ ?~ ts (bad ts "an expression")
2408+ ?+ lex.t (no-operand ts)
2409+ [%lit *] [%& [%lit at.t p.lex.t] t.ts]
2410+ [%str *] [%& [%str at.t (text-piece p.lex.t)] t.ts]
2411+ [%str-head *] (read-string t t.ts)
2412+ [%name *] (read-ref t t.ts)
2413+ [%wing *] (read-ref t t.ts)
2414+ %'%/' (read-qath t t.ts)
2415+ %'/' (read-path t t.ts)
2416+ %'`' (read-unit t t.ts)
2417+ %'(' (read-group t t.ts)
2418+ %'~[' (read-bracket %list t ~ t.ts)
2419+ %'[' (read-bracket %tuple t ~ t.ts)
2420+ %'|=(' (read-gate-wide t t.ts)
2421+ %'|=' (read-ctor t t.ts)
2424+ :: +read-ref: after a name or wing, a tight ( makes a change, and
2425+ :: after a name a tight + a pair; else it is a wing
2428+ |= [t=token ts=(list token)]
2430+ =/ names=(list term) (names-of lex.t)
2431+ ?: ?=([[* %& %'('] *] ts)
2432+ (read-bracket %change i.ts `[t names] t.ts)
2433+ ?: &(?=([[* %& %'+'] *] ts) ?=([%name *] lex.t))
2434+ (read-pair t p.lex.t i.ts t.ts)
2435+ [%& [%wing at.t names] ts]
2437+ :: +read-pair: name+operand, with no spaces
2440+ |= [t=token tag=term lus=token ts=(list token)]
2442+ ?: |(?=(~ ts) !tight.i.ts) (bad-space lus ts "an operand")
2443+ ;< [v=expr after=(list token)] then (read-operand ts)
2444+ [%& [%pair [beg.at.t end:(span-of v)] tag v] after]
2446+ :: +read-unit: ` and an operand, with no space
2449+ |= [tic=token ts=(list token)]
2451+ ?: |(?=(~ ts) !tight.i.ts) (bad-space tic ts "an operand")
2452+ ;< [v=expr after=(list token)] then (read-operand ts)
2453+ [%& [%unit [beg.at.tic end:(span-of v)] v] after]
2455+ :: +read-ctor: |= and a term, with no space: a case's constructor
2458+ |= [bar=token ts=(list token)]
2460+ ?: |(?=(~ ts) !tight.i.ts) (bad-space bar ts "a term")
2461+ ?. ?=([[* * [%lit %term *]] *] ts) (bad ts "a term")
2462+ [%& [%ctor [beg.at.bar end.at.i.ts] p.lex.i.ts] t.ts]
2464+ :: +read-path: a path literal, as /posts/~zod (doc question)
2467+ |= [sl=token ts=(list token)]
2469+ ;< [[sp=span segs=(list @ta)] after=(list token)] then
2470+ (read-pathlit sl ts)
2471+ [%& [%path sp segs] after]
2473+ :: +read-qath: %/, then its segments, knots or (expr), each after a
2474+ :: tight / and tight itself; %/ alone is the root
2477+ |= [cen=token ts=(list token)]
2479+ ?. ?=([[* %& ?([%knot *] %'(')] *] ts)
2480+ ?: &(?=(^ ts) tight.i.ts !(is-closer i.ts))
2481+ (bad ts "a path segment")
2482+ [%& [%qath at.cen ~] ts]
2483+ =| segs=(list qseg)
2485+ ;< [[s=qseg fin=loc] after=(list token)] then (read-qseg ts)
2486+ ?. ?=([[* %& %'/'] *] after)
2487+ [%& [%qath [beg.at.cen fin] (flop [s segs])] after]
2488+ =/ nex=(list token) t.after
2489+ ?: ?=([[* %& ?([%knot *] %'(')] *] nex)
2490+ $(segs [s segs], ts nex)
2491+ ?: &(?=(^ nex) tight.i.nex) (bad nex "a path segment")
2492+ (bad-space i.after nex "a path segment")
2494+ :: +read-qseg: an application path's segment, a knot or (expr), and
2499+ ^- (pare [qseg loc])
2500+ ?: ?=([[* * [%knot *]] *] ts)
2501+ [%& [[%knot p.lex.i.ts] end.at.i.ts] t.ts]
2502+ ?. ?=([[* * %'('] *] ts) (bad ts "a path segment")
2504+ ;< [e=expr after=(list token)] then (read-expr t.ts)
2505+ ?. ?=([[* * %')'] *] after) (unclosed par ")" after)
2506+ [%& [[%expr e] end.at.i.after] t.after]
2508+ :: +read-string: after its str-head, a string's interpolations and
2509+ :: text: expr { str-mid expr } str-tail
2512+ |= [head=token ts=(list token)]
2515+ ?.(?=([%str-head *] lex.head) ~ (text-piece p.lex.head))
2518+ ;< [e=expr after=(list token)] then (read-expr ts)
2519+ =. ps [[%expr e] ps]
2520+ ?: ?=([[* * [%str-mid *]] *] after)
2521+ $(ps (weld (text-piece p.lex.i.after) ps), op i.after, ts t.after)
2522+ ?. ?=([[* * [%str-tail *]] *] after)
2523+ =/ brace=loc [line.end.at.op (dec (max 2 col.end.at.op))]
2524+ (bad after "`}` to close the `\{` at {(show-loc brace)}")
2525+ =. ps (weld (text-piece p.lex.i.after) ps)
2526+ [%& [%str [beg.at.head end.at.i.after] (flop ps)] t.after]
2528+ :: +read-group: ( expr ), or ( { operand } and its lines below, left
2531+ :: A ( followed by a rune is the closed form. Else the group holds
2532+ :: its first line's operands and then its lines as one call, or the
2533+ :: one element alone.
2536+ |= [par=token ts=(list token)]
2538+ ?: (is-rune-start ts)
2539+ ;< [e=expr after=(list token)] then (read-expr ts)
2540+ ?. ?=([[* * %')'] *] after) (unclosed par ")" after)
2541+ [%& [%group [beg.at.par end.at.i.after] e] t.after]
2542+ ;< [els=(list expr) after=(list token)] then (read-operands ts)
2543+ ?: ?=([[* * %')'] *] after)
2544+ ?~ els (bad after "an expression")
2545+ [%& [%group [beg.at.par end.at.i.after] (call-of els)] t.after]
2546+ ?. ?=([[* * %indent] *] after)
2547+ =/ last=(unit span) ?~(els ~ `(span-of (rear els)))
2548+ (unclosed-open par ")" "an argument" last after)
2549+ ;< [ls=(list item) more=(list token)] then
2550+ (read-lines %group t.after)
2551+ =/ inner=expr (call-of (weld els (turn ls |=(i=item val.i))))
2552+ [%& [%group [beg.at.par end:(span-of inner)] inner] more]
2554+ :: +read-bracket: a tuple's, list's or change's items, to its closer
2555+ :: on the line, or to the end of its lines below when left open
2558+ |= $: kind=?(%tuple %list %change)
2560+ target=(unit [t=token names=(list term)])
2564+ =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
2567+ ?~ ts (bad ts "an item")
2570+ [%& (bracket-node kind op target (flop its) end.at.t) t.ts]
2571+ ?: (is-closer t) (unclosed op (trip close) ts)
2572+ ?: ?=(%indent lex.t)
2573+ ;< [ls=(list item) more=(list token)] then (read-lines kind t.ts)
2574+ =/ all=(list item) (weld (flop its) ls)
2575+ =/ fin=loc ?~(all end.at.op end.at:(rear all))
2576+ [%& (bracket-node kind op target all fin) more]
2577+ ?: ?=(?(%newline %dedent) lex.t)
2578+ =/ last=(unit span) ?~(its ~ `at.i.its)
2579+ (unclosed-open op (trip close) "an item" last ts)
2580+ ?: &(tight.t ?=(^ its)) (no-space ts)
2581+ ;< [i=item more=(list token)] then (read-item kind ts)
2582+ $(its [i its], ts more)
2584+ :: +read-item: [ name= ] operand; a tuple's item may be named, a
2585+ :: change's must be, a list's is not
2588+ |= [kind=?(%tuple %list %change) ts=(list token)]
2590+ ?: &(!?=(%list kind) ?=([[* * [%name *]] [* %& %'='] *] ts))
2592+ =/ rest=(list token) t.t.ts
2593+ ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
2594+ ;< [v=expr after=(list token)] then (read-operand rest)
2595+ [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
2596+ ?: ?=(%change kind) (unnamed ts)
2597+ ?: &(?=(^ ts) (is-rune i.ts))
2598+ %^ bad-why ts "an expression"
2599+ "inside brackets, a rune goes in parentheses"
2600+ ;< [v=expr after=(list token)] then (read-operand ts)
2601+ [%& [(span-of v) ~ v] after]
2603+ :: +read-lines: after an open bracket's INDENT, its lines, an item
2604+ :: each, to its DEDENT
2607+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
2608+ ^- (pare (list item))
2610+ |- ^- (pare (list item))
2611+ ;< [l=item after=(list token)] then (read-line kind ts)
2612+ ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
2613+ ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
2614+ ?. ?=([[* * ?(%')' %']')] *] after) (bad-end after)
2615+ %^ bad-why after "the end of the line"
2616+ "a bracket open at the end of its line takes no closer"
2618+ :: +read-line: an open bracket's line, [ name= ] expr; a tuple's may
2619+ :: be named, a change's must be, a list's and a group's are not
2623+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
2625+ ?: ?& ?=(?(%tuple %change) kind)
2626+ ?=([[* * [%name *]] [* %& %'='] *] ts)
2629+ =/ rest=(list token) t.t.ts
2630+ ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
2631+ ;< [v=expr after=(list token)] then (read-expr rest)
2632+ [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
2633+ ?: ?=(%change kind) (unnamed ts)
2634+ ;< [v=expr after=(list token)] then (read-expr ts)
2635+ [%& [(span-of v) ~ v] after]
2637+ :: +read-gate-wide: |=( sample operand ), the one wide expression
2640+ |= [op=token ts=(list token)]
2642+ ;< [s=sample after=(list token)] then (read-sample ts)
2643+ ?: ?=([[* * %')'] *] after) (bad after "the gate's body")
2644+ ?: &(?=(^ after) tight.i.after) (bad after "a space after the sample")
2645+ ?: &(?=(^ after) (is-rune i.after))
2646+ %^ bad-why after "an expression"
2647+ "the wide gate's body is an operand, so a rune goes in parentheses"
2648+ ;< [b=expr more=(list token)] then (read-operand after)
2649+ ?: ?=([[* * %')'] *] more)
2650+ [%& [%gate-wide [beg.at.op end.at.i.more] s b] t.more]
2651+ ?. &(?=(^ more) !tight.i.more (is-operand-start i.more))
2652+ (unclosed op ")" more)
2654+ "`)` to close the `|=(` at {(show-loc beg.at.op)}"
2655+ "the wide gate's body is one operand, so a call goes in parentheses"
2657+ :: +read-gate: |= sample, then an expression or a body
2660+ |= [bar=token ts=(list token)]
2662+ ?: &(?=(^ ts) tight.i.ts) (bad ts "a space after `|=`")
2663+ ;< [s=sample after=(list token)] then (read-sample ts)
2664+ ;< [e=expr more=(list token)] then
2665+ (read-expr-or-body "the sample" after)
2666+ [%& [%gate [beg.at.bar end:(span-of e)] s e] more]
2668+ :: +read-cast: ^- mold, then an expression or a body
2671+ |= [ket=token ts=(list token)]
2673+ ?: &(?=(^ ts) tight.i.ts) (wide-rune "^-" ts)
2674+ ;< [s=shape after=(list token)] then (read-mold ts)
2675+ ;< [e=expr more=(list token)] then
2676+ (read-expr-or-body "the mold" after)
2677+ [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
2679+ :: +read-trace: ~& expr, then its body below
2682+ |= [sig=token ts=(list token)]
2684+ ?: &(?=(^ ts) tight.i.ts) (bad ts "a space after `~&`")
2685+ ;< [v=expr after=(list token)] then (read-expr ts)
2686+ ?. ?=([[* * %indent] *] after)
2687+ (bad after "`~&`'s body on deeper lines")
2688+ ;< [b=expr more=(list token)] then (read-body t.after)
2689+ [%& [%trace [beg.at.sig end:(span-of b)] v b] more]
2691+ :: +read-branch: ?- expr, then its arms below, one per line
2694+ |= [wut=token ts=(list token)]
2696+ ?: &(?=(^ ts) tight.i.ts) (wide-rune "?-" ts)
2697+ ;< [s=expr after=(list token)] then (read-expr ts)
2698+ ?. ?=([[* * %indent] *] after)
2699+ (bad after "`?-`'s arms on deeper lines")
2701+ =/ rest=(list token) t.after
2703+ ;< [a=arm more=(list token)] then (read-arm rest)
2704+ ?: ?=([[* * %newline] *] more) $(arms [a arms], rest t.more)
2705+ ?. ?=([[* * %dedent] *] more) (bad-end more)
2706+ [%& [%branch [beg.at.wut end.at.a] s (flop [a arms])] t.more]
2708+ :: +read-arm: a pattern, then an expression or a body
2713+ ;< [p=pattern after=(list token)] then (read-pattern ts)
2714+ ?: ?=([[* %& %'+'] *] after)
2715+ %^ bad-why after "a space after the pattern"
2716+ "patterns take no pairs: write a cell, as [%gap %s2]"
2717+ ;< [e=expr more=(list token)] then
2718+ (read-expr-or-body "the pattern" after)
2719+ [%& [[beg:(span-of p) end:(span-of e)] p e] more]
2721+ :: +read-pattern: a term, number, string, ship, loobean, ~, * or name,
2722+ :: or a cell of patterns
2724+ :: A date, duration or knot fails at its second character, since ~
2725+ :: alone is null and no ship goes on so; ~[ at its [; and a string
2726+ :: with {…} at its { (section 3, Errors).
2731+ ?~ ts (bad ts "a pattern")
2733+ =/ next=loc [line.beg.at.t +(col.beg.at.t)]
2734+ ?+ lex.t (bad ts "a pattern")
2737+ ?: ?=(?(%number %ship %term %loobean %null) form.l)
2738+ [%& [%lit at.t l] t.ts]
2742+ %duration "durations"
2747+ "expected a pattern, found {(show-found t)}; patterns take no "
2749+ ": compare values with ?- (eq a b)"
2752+ [%str *] [%& [%str at.t p.lex.t] t.ts]
2753+ %'*' [%& [%any at.t ~] t.ts]
2754+ [%name *] [%& [%bind at.t p.lex.t] t.ts]
2755+ %'[' (read-cell-pattern t t.ts)
2756+ %'`' (bad-why ts "a pattern" "patterns take no units: write [~ x]")
2759+ %+ bad-at [line.end.at.t (dec (max 2 col.end.at.t))]
2760+ %+ weld "expected a pattern, found a string with `\{…}`; "
2761+ "patterns take strings without `\{…}`"
2765+ "expected a pattern, found `~[`; patterns take no lists"
2768+ :: +read-cell-pattern: [ pattern { pattern } ], closed on its line
2770+ ++ read-cell-pattern
2771+ |= [op=token ts=(list token)]
2773+ =| ps=(list pattern)
2774+ |- ^- (pare pattern)
2775+ ?: ?=([[* * %']'] *] ts)
2776+ ?~ ps (bad ts "a pattern")
2777+ [%& [%cell [beg.at.op end.at.i.ts] (flop ps)] t.ts]
2778+ ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
2779+ (unclosed op "]" ts)
2780+ ?: &(?=(^ ps) ?=(^ ts) tight.i.ts) (no-space ts)
2781+ ;< [p=pattern after=(list token)] then (read-pattern ts)
2782+ $(ps [p ps], ts after)
2784+ :: +read-sample: a gate's sample, a field, except that a bare name
2785+ :: binds, alone or in a cell sample at any depth (section 3)
2790+ ?: ?=([[* * [%name *]] [* %& %'='] *] ts) (read-face ts)
2791+ ?: ?=([[* * [%name *]] *] ts) [%& [%bind at.i.ts p.lex.i.ts] t.ts]
2792+ ?: ?=([[* * %'='] *] ts) (read-pun i.ts t.ts)
2793+ ?: &(?=(^ ts) (is-layout i.ts)) (bad ts "a sample")
2794+ ?. ?=([[* * %'['] *] ts)
2795+ ;< [s=shape after=(list token)] then (read-mold ts)
2796+ [%& [%bare (span-of s) s] after]
2798+ =| ss=(list sample)
2799+ =/ rest=(list token) t.ts
2800+ |- ^- (pare sample)
2801+ ?: ?=([[* * %']'] *] rest)
2802+ ?~ ss (bad rest "a sample")
2803+ [%& [%cell [beg.at.op end.at.i.rest] (flop ss)] t.rest]
2804+ ?: &(?=(^ rest) |((is-closer i.rest) (is-layout i.rest)))
2805+ (unclosed op "]" rest)
2806+ ?: &(?=(^ ss) ?=(^ rest) tight.i.rest) (no-space rest)
2807+ ;< [s=sample after=(list token)] then (read-sample rest)
2808+ $(ss [s ss], rest after)
2810+ :: +read-field: a cell mold's field: name=mold, =name, or a mold
2815+ ?: ?=([[* * [%name *]] [* %& %'='] *] ts) (read-face ts)
2816+ ?: ?=([[* * %'='] *] ts) (read-pun i.ts t.ts)
2817+ ;< [s=shape after=(list token)] then (read-mold ts)
2818+ [%& [%bare (span-of s) s] after]
2820+ :: +read-face: name=mold, with no spaces
2825+ ?. ?=([[* * [%name *]] [* * %'='] *] ts) (bad ts "a name")
2827+ =/ rest=(list token) t.t.ts
2828+ ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a mold")
2829+ ;< [s=shape after=(list token)] then (read-mold rest)
2830+ [%& [%face [beg.at.nam end:(span-of s)] p.lex.nam s] after]
2832+ :: +read-pun: =name, with no space, for name=name
2835+ |= [tis=token ts=(list token)]
2837+ ?: |(?=(~ ts) !tight.i.ts) (bad-space tis ts "a name")
2838+ ?. ?=([[* * [%name *]] *] ts) (bad ts "a name")
2839+ [%& [%pun [beg.at.tis end.at.i.ts] p.lex.i.ts] t.ts]
2841+ :: +read-mold: one mold
2846+ ?~ ts (bad ts "a mold")
2848+ ?+ lex.t (bad ts "a mold")
2849+ [%aura *] [%& [%aura at.t p.lex.t] t.ts]
2850+ %'*' [%& [%noun at.t ~] t.ts]
2851+ %'!!' [%& [%void at.t ~] t.ts]
2852+ %'?' [%& [%flag at.t ~] t.ts]
2853+ [%name *] [%& [%ref at.t ~[p.lex.t]] t.ts]
2854+ [%wing *] [%& [%ref at.t p.lex.t] t.ts]
2855+ [%tvar *] [%& [%tvar at.t p.lex.t] t.ts]
2856+ %'/' (read-pathmold t t.ts)
2857+ %'(' (read-apply t t.ts)
2858+ %'[' (read-cell-mold t t.ts)
2859+ %'$?' (read-union t t.ts)
2860+ %'$?(' (read-union-wide t t.ts)
2861+ %'$-(' (read-fn t t.ts)
2862+ %'|$' (read-generic t t.ts)
2865+ ?. ?=(?(%null %term %loobean) form.p.lex.t) (bad ts "a mold")
2866+ [%& [%const at.t p.lex.t] t.ts]
2869+ :: +read-molds: molds to the ) of the bracket op opened: after a
2870+ :: space each, or but the first if not spaced; at least one
2873+ |= [op=token spaced=? ts=(list token)]
2874+ ^- (pare [(list shape) loc])
2876+ |- ^- (pare [(list shape) loc])
2877+ ?: ?=([[* * %')'] *] ts)
2878+ ?~ ms (bad ts "a mold")
2879+ [%& [(flop ms) end.at.i.ts] t.ts]
2880+ ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
2881+ (unclosed op ")" ts)
2882+ ?: &(?=(^ ts) tight.i.ts |(spaced ?=(^ ms))) (no-space ts)
2883+ ;< [m=shape after=(list token)] then (read-mold ts)
2884+ $(ms [m ms], ts after)
2886+ :: +read-apply: ( ref mold { mold } )
2889+ |= [op=token ts=(list token)]
2891+ ?. ?=([[* * ?([%name *] [%wing *])] *] ts)
2892+ (bad ts "a mold's name, as in (list @t)")
2893+ ;< [[ms=(list shape) fin=loc] after=(list token)] then
2894+ (read-molds op & t.ts)
2895+ [%& [%apply [beg.at.op fin] (names-of lex.i.ts) ms] after]
2897+ :: +read-union-wide: $?( mold { mold } )
2900+ |= [op=token ts=(list token)]
2902+ ;< [[ms=(list shape) fin=loc] after=(list token)] then
2903+ (read-molds op | ts)
2904+ [%& [%union [beg.at.op fin] ms] after]
2906+ :: +read-fn: $-( mold mold )
2909+ |= [op=token ts=(list token)]
2911+ ;< [a=shape after=(list token)] then (read-mold ts)
2912+ ?: ?=([[* * %')'] *] after) (bad after "a mold, the product")
2913+ ?: &(?=(^ after) |((is-closer i.after) (is-layout i.after)))
2914+ (unclosed op ")" after)
2915+ ?: &(?=(^ after) tight.i.after) (no-space after)
2916+ ;< [b=shape more=(list token)] then (read-mold after)
2917+ ?. ?=([[* * %')'] *] more) (unclosed op ")" more)
2918+ [%& [%fn [beg.at.op end.at.i.more] a b] t.more]
2920+ :: +read-cell-mold: [ field { field } ]
2923+ |= [op=token ts=(list token)]
2927+ ?: ?=([[* * %']'] *] ts)
2928+ ?~ fs (bad ts "a mold")
2929+ [%& [%cell [beg.at.op end.at.i.ts] (flop fs)] t.ts]
2930+ ?: &(?=(^ ts) |((is-closer i.ts) (is-layout i.ts)))
2931+ (unclosed op "]" ts)
2932+ ?: &(?=(^ fs) ?=(^ ts) tight.i.ts) (no-space ts)
2933+ ;< [f=field after=(list token)] then (read-field ts)
2934+ $(fs [f fs], ts after)
2936+ :: +read-union: $?, then its cases below, one mold per line
2939+ |= [buc=token ts=(list token)]
2941+ ?. ?=([[* * %indent] *] ts)
2942+ ?: ?=([[* * ?(%newline %dedent)] *] ts)
2943+ (bad ts "`$?`'s cases on deeper lines")
2944+ %^ bad-why ts "the end of the line"
2945+ "`$?` takes its cases on deeper lines, one per line, or write $?(%a %b)"
2947+ =/ rest=(list token) t.ts
2949+ ;< [c=shape after=(list token)] then (read-mold rest)
2950+ ?: ?=([[* * %newline] *] after) $(cs [c cs], rest t.after)
2951+ ?: ?=([[* * %dedent] *] after)
2952+ [%& [%union [beg.at.buc end:(span-of c)] (flop [c cs])] t.after]
2953+ ?: ?=([[* * %indent] *] after) (bad-end after)
2954+ (bad-why after "the end of the line" "a union takes one case per line")
2956+ :: +read-generic: |$ [ typevar { typevar } ] mold
2959+ |= [bar=token ts=(list token)]
2961+ ?: &(?=(^ ts) tight.i.ts) (bad ts "a space after `|$`")
2962+ ?. ?=([[* * %'['] *] ts)
2963+ (bad ts "`[` and its type variables, as in |$ [M]")
2966+ =/ rest=(list token) t.ts
2968+ ?: ?=([[* * %']'] *] rest)
2969+ ?~ vs (bad rest "a type variable")
2970+ =/ more=(list token) t.rest
2971+ ?: &(?=(^ more) tight.i.more) (bad more "a space after `]`")
2972+ ;< [b=shape after=(list token)] then (read-mold more)
2973+ [%& [%generic [beg.at.bar end:(span-of b)] (flop vs) b] after]
2974+ ?: &(?=(^ rest) |((is-closer i.rest) (is-layout i.rest)))
2975+ (unclosed op "]" rest)
2976+ ?: &(?=(^ vs) ?=(^ rest) tight.i.rest) (no-space rest)
2977+ ?. ?=([[* * [%tvar *]] *] rest) (bad rest "a type variable")
2978+ $(vs [p.lex.i.rest vs], rest t.rest)
2980+ :: +read-pathmold: / [ segment { / segment } ], each / and segment
2981+ :: tight; / alone is the empty path
2984+ |= [sl=token ts=(list token)]
2986+ ?. ?=([[* %& ?([%knot *] %'[')] *] ts)
2987+ ?: &(?=(^ ts) tight.i.ts !(is-closer i.ts))
2988+ (bad ts "a path segment")
2989+ [%& [%path at.sl ~] ts]
2990+ =| segs=(list pseg)
2992+ ;< [[s=pseg fin=loc] after=(list token)] then (read-pseg ts)
2993+ ?. ?=([[* %& %'/'] *] after)
2994+ [%& [%path [beg.at.sl fin] (flop [s segs])] after]
2995+ =/ nex=(list token) t.after
2996+ ?: ?=([[* %& ?([%knot *] %'[')] *] nex)
2997+ $(segs [s segs], ts nex)
2998+ ?: &(?=(^ nex) tight.i.nex) (bad nex "a path segment")
2999+ (bad-space i.after nex "a path segment")
3001+ :: +read-pseg: a path mold's segment, a knot or [name=aura] with no
3002+ :: spaces, and where it ends
3006+ ^- (pare [pseg loc])
3007+ ?: ?=([[* * [%knot *]] *] ts)
3008+ [%& [[%knot p.lex.i.ts] end.at.i.ts] t.ts]
3009+ ?. ?=([[* * %'['] *] ts) (bad ts "a path segment")
3011+ =/ r1=(list token) t.ts
3012+ ?: |(?=(~ r1) !tight.i.r1) (bad-space op r1 "a name")
3013+ ?. ?=([[* * [%name *]] *] r1) (bad r1 "a name")
3014+ =/ r2=(list token) t.r1
3015+ ?: |(?=(~ r2) !tight.i.r2) (bad-space i.r1 r2 "`=`")
3016+ ?. ?=([[* * %'='] *] r2) (bad r2 "`=`")
3017+ =/ r3=(list token) t.r2
3018+ ?: |(?=(~ r3) !tight.i.r3) (bad-space i.r2 r3 "an aura")
3019+ ?. ?=([[* * [%aura *]] *] r3) (bad r3 "an aura")
3020+ =/ r4=(list token) t.r3
3021+ ?: |(?=(~ r4) !tight.i.r4) (bad-space i.r3 r4 "`]`")
3022+ ?. ?=([[* * %']'] *] r4) (bad r4 "`]`")
3023+ =/ at=span [beg.at.op end.at.i.r4]
3024+ [%& [[%typed at p.lex.i.r1 p.lex.i.r3] end.at.i.r4] t.r4]
3029+:: +outline: a node as +check-spans sees it
3031+:: lead lists the kinds (+kind-of) of token the node may start with,
3032+:: or is ~ when it starts with its first child; last likewise for its
3033+:: end, and open lets a bracket that may be left open end with its
3034+:: last child instead.
3037+ $~ [%$ *span ~ ~ | ~]
3043+ kids=(list outline)
3046+:: +check-spans: whether a module's spans follow section 1's rules
3048+:: A node starts at its first token and ends where its last token
3049+:: ends, never at a layout token: at its own token where it has one
3050+:: there (a rune, a name, an opener or a closer), else where its
3051+:: first or last child does. Its children's spans lie inside its own
3052+:: in source order, and so do the module's imports and definitions.
3053+:: Gives the first node that breaks a rule, and how, or ~.
3056+ |= [mod=module toks=(list token)]
3058+ =/ real=(list token) (skip toks is-layout)
3059+ =/ begs=(map loc @) (malt (turn real |=(t=token [beg.at.t (kind-of t)])))
3060+ =/ ends=(map loc @) (malt (turn real |=(t=token [end.at.t (kind-of t)])))
3061+ %^ check-kids [begs ends] ~
3062+ (weld (turn imports.mod outline-import) (turn defs.mod outline-def))
3064+:: +kind-of: a token's kind: a glyph, or its lexeme's tag
3069+ ?@(lex.t lex.t -.lex.t)
3071+:: +check-kids: nodes in source order, inside the span in, each checked
3074+ |= [maps=[begs=(map loc @) ends=(map loc @)] in=(unit span) os=(list outline)]
3076+ =| prev=(unit span)
3080+ ?: &(?=(^ in) (loc-lth beg.at.o beg.u.in))
3081+ `(span-bad o "starts before its parent")
3082+ ?: &(?=(^ in) (loc-lth end.u.in end.at.o))
3083+ `(span-bad o "ends after its parent")
3084+ ?: &(?=(^ prev) (loc-lth beg.at.o end.u.prev))
3085+ `(span-bad o "starts before the node before it ends")
3086+ =/ bad=(unit tape) (check-outline maps o)
3088+ $(prev `at.o, os t.os)
3090+:: +check-outline: one node's start and end, then its children
3093+ |= [maps=[begs=(map loc @) ends=(map loc @)] o=outline]
3096+ =/ head=(unit span) ?~(ks ~ `at.i.ks)
3097+ =/ tail=(unit span) ?~(ks ~ `at:(rear ks))
3098+ ?. (loc-lth beg.at.o end.at.o) `(span-bad o "is empty")
3099+ :: the start: its own token, or its first child's
3100+ =/ start=(unit tape)
3102+ ?~ head `"has no token or child to start with"
3103+ ?: =(beg.at.o beg.u.head) ~
3104+ `"should start where its first child does, at {(show-loc beg.u.head)}"
3105+ =/ k=(unit @) (~(get by begs.maps) beg.at.o)
3106+ ?~ k `"starts where no token does"
3107+ ?. (lien `(list @)`lead.o |=(a=@ =(a u.k)))
3108+ `"starts at a token of a kind it can't start with"
3109+ ?: &(?=(^ head) !(loc-lth beg.at.o beg.u.head))
3110+ `"should start with its own token, before its first child"
3112+ ?^ start `(span-bad o u.start)
3113+ :: the end: its own token, or its last child's
3114+ =/ stop=(unit tape)
3115+ ?: &(|(?=(~ last.o) open.o) ?=(^ tail) =(end.at.o end.u.tail)) ~
3117+ ?~ tail `"has no token or child to end with"
3118+ `"should end where its last child does, at {(show-loc end.u.tail)}"
3119+ =/ k=(unit @) (~(get by ends.maps) end.at.o)
3120+ ?~ k `"ends where no token does"
3121+ ?. (lien `(list @)`last.o |=(a=@ =(a u.k)))
3122+ `"ends at a token of a kind it can't end with"
3123+ ?: &(?=(^ tail) !(loc-lth end.u.tail end.at.o))
3124+ `"should end with its own token, after its last child"
3126+ ?^ stop `(span-bad o u.stop)
3127+ (check-kids maps `at.o ks)
3129+:: +span-bad: a span check's error, naming the node by kind and span
3132+ |= [o=outline why=tape]
3134+ "({(trip kind.o)} {(show-loc beg.at.o)} to {(show-loc end.at.o)}) {why}"
3136+:: +loc-lth: whether a comes before b
3141+ ?| (lth line.a line.b)
3142+ &(=(line.a line.b) (lth col.a col.b))
3149+ %sur [%sur at.i ~[%'/-'] ~[%name] | ~]
3150+ %mark [%mark at.i ~[%'/%'] ~[%lit] | ~]
3151+ %jibb [%jibb at.i ~[%'/='] ~[%'/' %knot] | ~]
3158+ %mold [%mold at.d ~[%'+$'] ~ | ~[(outline-shape shape.d)]]
3159+ %value [%value at.d ~[%'++'] ~ | ~[(outline-expr val.d)]]
3166+ %lit [%lit at.e ~[%lit] ~[%lit] | ~]
3167+ %str (outline-str at.e pieces.e)
3168+ %path [%path at.e ~[%'/'] ~[%'/' %knot] | ~]
3169+ %wing [%wing at.e ~[%name %wing] ~[%name %wing] | ~]
3170+ %pair [%pair at.e ~[%name] ~ | ~[(outline-expr val.e)]]
3171+ %unit [%unit at.e ~[%'`'] ~ | ~[(outline-expr val.e)]]
3172+ %group [%group at.e ~[%'('] ~[%')'] & ~[(outline-expr inner.e)]]
3173+ %list [%list at.e ~[%'~['] ~[%']'] & (turn items.e outline-expr)]
3174+ %tuple [%tuple at.e ~[%'['] ~[%']'] & (turn items.e outline-item)]
3175+ %ctor [%ctor at.e ~[%'|='] ~[%lit] | ~]
3176+ %crash [%crash at.e ~[%'!!'] ~[%'!!'] | ~]
3179+ =/ ks=(list outline)
3181+ |=(s=qseg ?.(?=(%expr -.s) ~ `(outline-expr p.s)))
3182+ [%qath at.e ~[%'%/'] ~[%'%/' %knot %')'] | ks]
3185+ =/ ks=(list outline) (turn edits.e outline-edit)
3186+ [%change at.e ~[%name %wing] ~[%')'] & ks]
3189+ =/ ks=(list outline)
3190+ ~[(outline-sample sample.e) (outline-expr body.e)]
3191+ [%gate-wide at.e ~[%'|=('] ~[%')'] | ks]
3194+ [%call at.e ~ ~ | [(outline-expr head.e) (turn args.e outline-expr)]]
3197+ =/ ks=(list outline)
3198+ ~[(outline-sample sample.e) (outline-expr body.e)]
3199+ [%gate at.e ~[%'|='] ~ | ks]
3202+ =/ ks=(list outline) ~[(outline-shape shape.e) (outline-expr val.e)]
3203+ [%cast at.e ~[%'^-'] ~ | ks]
3206+ =/ ks=(list outline) ~[(outline-expr val.e) (outline-expr then.e)]
3207+ [%trace at.e ~[%'~&'] ~ | ks]
3210+ =/ ks=(list outline)
3211+ [(outline-expr subject.e) (turn arms.e outline-arm)]
3212+ [%branch at.e ~[%'?-'] ~ | ks]
3215+ =/ ks=(list outline)
3216+ (snoc (turn defs.e outline-def) (outline-expr final.e))
3217+ [%body at.e ~ ~ | ks]
3221+ |= [at=span ps=(list piece)]
3223+ =/ ks=(list outline)
3224+ (murn ps |=(p=piece ?.(?=(%expr -.p) ~ `(outline-expr p.p))))
3225+ ?~ ks [%str at ~[%str] ~[%str] | ~]
3226+ [%str at ~[%str-head] ~[%str-tail] | ks]
3231+ ?~ face.i [%item at.i ~ ~ | ~[(outline-expr val.i)]]
3232+ [%face at.i ~[%name] ~ | ~[(outline-expr val.i)]]
3237+ [%edit at.e ~[%name] ~ | ~[(outline-expr val.e)]]
3242+ [%arm at.a ~ ~ | ~[(outline-pattern pat.a) (outline-expr val.a)]]
3248+ %bind [%bind at.s ~[%name] ~[%name] | ~]
3249+ %face [%face at.s ~[%name] ~ | ~[(outline-shape shape.s)]]
3250+ %pun [%pun at.s ~[%'='] ~[%name] | ~]
3251+ %cell [%cell at.s ~[%'['] ~[%']'] | (turn items.s outline-sample)]
3252+ %bare [%bare at.s ~ ~ | ~[(outline-shape shape.s)]]
3259+ %lit [%lit at.p ~[%lit] ~[%lit] | ~]
3260+ %str [%str at.p ~[%str] ~[%str] | ~]
3261+ %any [%any at.p ~[%'*'] ~[%'*'] | ~]
3262+ %bind [%bind at.p ~[%name] ~[%name] | ~]
3263+ %cell [%cell at.p ~[%'['] ~[%']'] | (turn items.p outline-pattern)]
3270+ %aura [%aura at.s ~[%aura] ~[%aura] | ~]
3271+ %noun [%noun at.s ~[%'*'] ~[%'*'] | ~]
3272+ %void [%void at.s ~[%'!!'] ~[%'!!'] | ~]
3273+ %flag [%flag at.s ~[%'?'] ~[%'?'] | ~]
3274+ %const [%const at.s ~[%lit] ~[%lit] | ~]
3275+ %ref [%ref at.s ~[%name %wing] ~[%name %wing] | ~]
3276+ %tvar [%tvar at.s ~[%tvar] ~[%tvar] | ~]
3277+ %apply [%apply at.s ~[%'('] ~[%')'] | (turn args.s outline-shape)]
3278+ %cell [%cell at.s ~[%'['] ~[%']'] | (turn fields.s outline-sample)]
3281+ =/ ks=(list outline)
3285+ ?. ?=(%typed -.g) ~
3286+ `[%typed at.g ~[%'['] ~[%']'] | ~]
3287+ [%path at.s ~[%'/'] ~[%'/' %knot %']'] & ks]
3290+ =/ ks=(list outline) (turn cases.s outline-shape)
3291+ [%union at.s ~[%'$?' %'$?('] ~[%')'] & ks]
3294+ =/ ks=(list outline)
3295+ ~[(outline-shape sample.s) (outline-shape product.s)]
3296+ [%fn at.s ~[%'$-('] ~[%')'] | ks]
3299+ [%generic at.s ~[%'|$'] ~ | ~[(outline-shape body.s)]]