@@ -19,9 +19,9 @@
1919:: fails: an error it finds is its last token (2.0), and +layout-error
2020:: takes it out.
2121::
22−:: Status: the types, the printers, +golden and the layout pass
23−:: (+layout, +lexer) work. +parse-tokens is a stub that returns an
24−:: error; it is implemented next, against the design below. Choices the
22+:: Status: the types, the printers, +golden, the layout pass (+layout,
23+:: +lexer) and the parser (+parse-tokens, +parser) work, and +golden
24+:: checks every tree's spans (+check-spans, section 1). Choices the
2525:: doc leaves open are marked "(doc question)": they follow the most
2626:: likely reading and are listed, with the doc's words, for the doc's
2727:: author to settle. The golden corpus's "expect:" lines give each
@@ -50,8 +50,9 @@
5050:: code, not at the line that closes them. Every node's span holds its
5151:: children's spans, in source order. The printed tree shows starts
5252:: 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.
53+:: used by milestone 2's excerpts. Until then +check-spans tests the two
54+:: rules above on every tree +golden prints, and a tree that breaks one
55+:: ends with a line "SPAN ERROR: (<kind> <start> to <end>) <why>".
5556::
5657:: ===================================================================
5758:: 2. The layout pass (+layout)
@@ -313,14 +314,15 @@
313314:: 3. The parser (+parse-tokens)
314315:: ===================================================================
315316::
316−:: Hand-written recursive descent over the token list: one arm per EBNF
317−:: rule, each taking the remaining tokens and returning (pare node): the
318−:: node and the tokens after it, or an error. Steps chain with ;< and
319−:: +then, so an error stops the parse:
317+:: Hand-written recursive descent over the token list (+parser): one
318+:: arm per EBNF rule, each taking the remaining tokens and returning
319+:: (pare node): the node and the tokens after it, or an error. Steps
320+:: chain with ;< and +then, so an error stops the parse (+read-cast):
320321::
321−:: ;< [s=shape ts=(list token)] then (mold ts)
322−:: ;< [e=expr ts=(list token)] then (expr-or-body ts)
323−:: [%& [%cast [beg.at.rune end:(span-of e)] s e] ts]
322+:: ;< [s=shape after=(list token)] then (read-mold ts)
323+:: ;< [e=expr more=(list token)] then
324+:: (read-expr-or-body "the mold" after)
325+:: [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
324326::
325327:: Why: after the layout pass the grammar is LL(2). Each choice is made by
326328:: the next token, at most with the one after it and whether it is tight:
@@ -341,10 +343,13 @@
341343:: An operand that isn't where an expression starts (a call's argument,
342344:: an item, a pair's or unit's operand, the wide gate's body) can't be a
343345:: 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.
346+:: (state.cart |= %got) is an error at the space after |=, 1:20. A loop
347+:: over many items (definitions, arms, lines, items) is a trap whose
348+:: every step, through +then, is a tail call, so a long module grows no
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.
348353::
349354:: The EBNF and its nodes (see the types below):
350355:: module { import NEWLINE } { definition NEWLINE }, then the end
@@ -462,7 +467,8 @@
462467:: out: eq is a gate", = followed tight by / is "=/ is left out: ++
463468:: defines values", and * is "*mold is left out: no defaults"; ^- or ?-
464469:: 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:
466472:: expected `]` or an item on a deeper line, found a line at the same
467473:: depth
468474:: expected the end of the line, found a deeper line; only a bracket
@@ -816,22 +822,21 @@
816822:: +parse-tokens: tokens to tree (design: section 3)
817823::
818824:: 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.
825+:: error and the layout pass's (2.0). +parser does the work.
821826::
822827++ parse-tokens
823828 |= [file=path toks=(list token)]
824829 ^- (each module error)
825− ?: ?=([[* * [%error *]] *] toks)
826− (fail file toks "a module")
827− =/ at=loc ?~(toks [1 1] (where i.toks))
828− [%| file line.at col.at "parser not implemented"]
830+ (~(read-module parser file) toks)
829831::
830832:: +golden: both stages printed, or the rendered error
831833::
832834:: tokens: the layout pass's tokens, or its error if it found one
833835:: 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
839+:: them.
835840::
836841++ golden
837842 |= [file=path src=@t]
@@ -843,8 +848,13 @@
843848 =/ par (parse-tokens file toks)
844849 ?: ?=(%| -.par) (show-error src p.par)
845850 :: a parser that accepted an error token would be wrong; say so
846− ?^ bad (show-error src u.bad)
847− (show-module p.par)
851+ ?^ bad
852+ %^ cat 3 (show-error src u.bad)
853+ '\0aPARSER ERROR: the parser accepted an error token'
854+ =/ tree=@t (show-module p.par)
855+ =/ why=(unit tape) (check-spans p.par toks)
856+ ?~ why tree
857+ (cat 3 tree (crip "\0aSPAN ERROR: {u.why}"))
848858::
849859+| %lexer
850860::
@@ -1595,6 +1605,7 @@
15951605 %indent "a deeper line"
15961606 %dedent "a shallower line"
15971607 %newline "a line at the same depth"
1608+ %'`' "`` ` ``"
15981609 ==
15991610 ?- -.x
16001611 %name "`{(trip p.x)}`"
@@ -1947,4 +1958,1344 @@
19471958 :+ %| file
19481959 :+ line.end.at.prev col.end.at.prev
19491960 "expected {want} right after {(show-found prev)}, found a space"
1961+::
1962+:: +fail-why: +fail with a hint after its message, "; <why>"
1963+::
1964+:: The layout pass's error, at an error token, stays as it is (2.0).
1965+::
1966+++ fail-why
1967+ |= [file=path toks=(list token) want=tape why=tape]
1968+ ^- [%| p=error]
1969+ =/ e=[%| p=error] (fail file toks want)
1970+ ?: &(?=(^ toks) ?=([%error *] lex.i.toks)) e
1971+ e(msg.p (weld msg.p.e "; {why}"))
1972+::
1973+:: Token tests for the parser
1974+::
1975+:: +is-layout: INDENT, DEDENT or NEWLINE
1976+::
1977+++ is-layout
1978+ |= t=token
1979+ ^- ?
1980+ ?=(?(%indent %dedent %newline) lex.t)
1981+::
1982+:: +is-closer: ) or ], or the } that ends an interpolation
1983+::
1984+++ is-closer
1985+ |= t=token
1986+ ^- ?
1987+ ?| =(%')' lex.t)
1988+ =(%']' lex.t)
1989+ ?=([?(%str-mid %str-tail) *] lex.t)
1990+ ==
1991+::
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
1995+::
1996+++ ends-call
1997+ |= t=token
1998+ ^- ?
1999+ ?| (is-layout t)
2000+ (is-closer t)
2001+ ?=([%error *] lex.t)
2002+ ==
2003+::
2004+:: +is-operand-start: a token an operand starts with; where an operand
2005+:: goes, |= is the constructor's (section 3)
2006+::
2007+++ is-operand-start
2008+ |= t=token
2009+ ^- ?
2010+ ?| ?=(?(%'%/' %'/' %'`' %'(' %'~[' %'[' %'|=(' %'|=') lex.t)
2011+ ?=([?(%lit %str %str-head %name %wing) *] lex.t)
2012+ ==
2013+::
2014+:: +is-rune: a rune that is never an operand: ^- ~& ?- !!
2015+::
2016+++ is-rune
2017+ |= t=token
2018+ ^- ?
2019+ ?=(?(%'^-' %'~&' %'?-' %'!!') lex.t)
2020+::
2021+:: +is-ctor: |= with a term tight after it, a case's constructor
2022+::
2023+++ is-ctor
2024+ |= ts=(list token)
2025+ ^- ?
2026+ ?=([[* * %'|='] [* %& [%lit %term *]] *] ts)
2027+::
2028+:: +is-rune-start: a rune where an expression starts; |= is a rune
2029+:: there unless it is the constructor
2030+::
2031+++ is-rune-start
2032+ |= ts=(list token)
2033+ ^- ?
2034+ ?~ ts |
2035+ ?| (is-rune i.ts)
2036+ &(=(%'|=' lex.i.ts) !(is-ctor ts))
2037+ ==
2038+::
2039+:: +text-piece: a string's text as its pieces: none when it is empty
2040+::
2041+++ text-piece
2042+ |= txt=@t
2043+ ^- (list piece)
2044+ ?:(=('' txt) ~ ~[[%text txt]])
2045+::
2046+:: +names-of: a name's or a wing's names
2047+::
2048+++ names-of
2049+ |= x=lexeme
2050+ ^- (list term)
2051+ ?+ x ~
2052+ [%name *] ~[p.x]
2053+ [%wing *] p.x
2054+ ==
2055+::
2056+:: +call-of: a call's elements as one expression: one alone is itself
2057+::
2058+++ call-of
2059+ |= els=(list expr)
2060+ ^- expr
2061+ ?~ els [%crash *span ~]
2062+ ?~ t.els i.els
2063+ [%call [beg:(span-of i.els) end:(span-of (rear t.els))] i.els t.els]
2064+::
2065+:: +bracket-node: a tuple, list or change from its items, ending at fin
2066+::
2067+++ bracket-node
2068+ |= $: kind=?(%tuple %list %change)
2069+ op=token
2070+ target=(unit [t=token names=(list term)])
2071+ its=(list item)
2072+ fin=loc
2073+ ==
2074+ ^- expr
2075+ ?- kind
2076+ %tuple [%tuple [beg.at.op fin] its]
2077+ %list [%list [beg.at.op fin] (turn its |=(i=item val.i))]
2078+ ::
2079+ %change
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])))
2083+ ==
2084+::
2085++| %parser
2086+::
2087+:: +parser: section 3's recursive descent over one file's tokens
2088+::
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
2096+:: by its length.
2097+::
2098+++ parser
2099+ |_ file=path
2100+ ::
2101+ :: +bad: "expected <want>, found <the next token>" (+fail)
2102+ ::
2103+ ++ bad
2104+ |= [ts=(list token) want=tape]
2105+ ^- [%| p=error]
2106+ (fail file ts want)
2107+ ::
2108+ :: +bad-why: +bad with a hint (+fail-why)
2109+ ::
2110+ ++ bad-why
2111+ |= [ts=(list token) want=tape why=tape]
2112+ ^- [%| p=error]
2113+ (fail-why file ts want why)
2114+ ::
2115+ :: +bad-space: a tight form that found a space after prev
2116+ :: (+fail-space)
2117+ ::
2118+ ++ bad-space
2119+ |= [prev=token ts=(list token) want=tape]
2120+ ^- [%| p=error]
2121+ (fail-space file prev ts want)
2122+ ::
2123+ :: +bad-at: an error inside a token (section 3, Errors)
2124+ ::
2125+ ++ bad-at
2126+ |= [at=loc msg=tape]
2127+ ^- [%| p=error]
2128+ [%| file line.at col.at msg]
2129+ ::
2130+ :: +bad-end: a line that should end and goes on
2131+ ::
2132+ ++ bad-end
2133+ |= ts=(list token)
2134+ ^- [%| p=error]
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"
2139+ ::
2140+ :: +no-space: a token tight after an item, where a space goes
2141+ ::
2142+ ++ no-space
2143+ |= ts=(list token)
2144+ ^- [%| p=error]
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)"
2148+ ::
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)
2151+ ::
2152+ ++ no-operand
2153+ |= ts=(list token)
2154+ ^- [%| p=error]
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")
2166+ (bad ts want)
2167+ ::
2168+ :: +unclosed: where the closer of the bracket op opened should be
2169+ ::
2170+ ++ unclosed
2171+ |= [op=token close=tape ts=(list token)]
2172+ ^- [%| p=error]
2173+ =/ want=tape
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")
2177+ ::
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
2181+ ::
2182+ ++ unclosed-open
2183+ |= [op=token close=tape noun=tape last=(unit span) ts=(list token)]
2184+ ^- [%| p=error]
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))
2188+ %^ bad-why ts
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")
2192+ ::
2193+ :: +wide-rune: a rune followed tight; txt( is a left-out wide form
2194+ ::
2195+ ++ wide-rune
2196+ |= [txt=tape ts=(list token)]
2197+ ^- [%| p=error]
2198+ =/ want=tape "a space after `{txt}`"
2199+ ?. ?=([[* * %'('] *] ts) (bad ts want)
2200+ %^ bad-why ts want
2201+ "the wide form `{txt}(…)` is left out: indentation covers it"
2202+ ::
2203+ :: +unnamed: a change's item or line without its name=
2204+ ::
2205+ ++ unnamed
2206+ |= ts=(list token)
2207+ ^- [%| p=error]
2208+ %^ bad-why ts "a named item"
2209+ "a change's items are named, as in m(done=%.y)"
2210+ ::
2211+ :: +read-module: { import NEWLINE } { definition NEWLINE }, then the
2212+ :: end of the tokens
2213+ ::
2214+ ++ read-module
2215+ |= ts=(list token)
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)
2223+ =| defs=(list def)
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)
2231+ ::
2232+ :: +read-import: /- name, /% term, or /= name pathlit
2233+ ::
2234+ ++ read-import
2235+ |= ts=(list token)
2236+ ^- (pare import)
2237+ ?~ ts (bad ts "an import")
2238+ =* g i.ts
2239+ =/ rest=(list token) t.ts
2240+ ?: &(?=(^ rest) tight.i.rest)
2241+ (bad rest "a space after {(show-found g)}")
2242+ ?: =(%'/%' lex.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")
2249+ =* nam i.rest
2250+ ?. =(%'/=' lex.g)
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]
2259+ ::
2260+ :: +read-pathlit: after a path's /, its knots, each after a tight /
2261+ :: and tight itself; / alone is the empty path
2262+ ::
2263+ ++ read-pathlit
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")
2269+ [%& [at.sl ~] ts]
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")
2281+ ::
2282+ :: +read-def: ++ name, then an expression or a body; +$ name, then a
2283+ :: mold on its line or alone on a deeper one
2284+ ::
2285+ ++ read-def
2286+ |= ts=(list token)
2287+ ^- (pare def)
2288+ ?~ ts (bad ts "a definition")
2289+ =* rune i.ts
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]
2312+ ::
2313+ :: +read-def-name: after ++ or +$, a space and a name
2314+ ::
2315+ ++ read-def-name
2316+ |= [rune=token ts=(list token)]
2317+ ^- (pare term)
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]
2322+ ::
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
2325+ ::
2326+ ++ read-expr-or-body
2327+ |= [what=tape ts=(list token)]
2328+ ^- (pare expr)
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}")
2333+ (read-expr ts)
2334+ ::
2335+ :: +read-body: after its INDENT, { definition NEWLINE } expr DEDENT
2336+ ::
2337+ ++ read-body
2338+ |= ts=(list token)
2339+ ^- (pare expr)
2340+ =| defs=(list def)
2341+ |- ^- (pare expr)
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"
2355+ ::
2356+ :: +read-expr: a rune, or a call
2357+ ::
2358+ ++ read-expr
2359+ |= ts=(list token)
2360+ ^- (pare expr)
2361+ ?~ ts (bad ts "an expression")
2362+ =* t i.ts
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]
2369+ ==
2370+ ::
2371+ :: +read-call: operand { operand }; one operand alone is itself
2372+ ::
2373+ ++ read-call
2374+ |= ts=(list token)
2375+ ^- (pare expr)
2376+ ;< [els=(list expr) after=(list token)] then (read-operands ts)
2377+ ?~ els (no-operand ts)
2378+ [%& (call-of els) after]
2379+ ::
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
2382+ ::
2383+ ++ read-operands
2384+ |= ts=(list token)
2385+ ^- (pare (list expr))
2386+ =| els=(list expr)
2387+ |- ^- (pare (list expr))
2388+ ?~ ts [%& (flop els) ts]
2389+ =* t i.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"
2398+ (no-operand ts)
2399+ ::
2400+ :: +read-operand: one operand, told by its first token and, after a
2401+ :: name or a wing, by a tight ( or +
2402+ ::
2403+ ++ read-operand
2404+ |= ts=(list token)
2405+ ^- (pare expr)
2406+ ?~ ts (bad ts "an expression")
2407+ =* t i.ts
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)
2422+ ==
2423+ ::
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
2426+ ::
2427+ ++ read-ref
2428+ |= [t=token ts=(list token)]
2429+ ^- (pare expr)
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]
2436+ ::
2437+ :: +read-pair: name+operand, with no spaces
2438+ ::
2439+ ++ read-pair
2440+ |= [t=token tag=term lus=token ts=(list token)]
2441+ ^- (pare expr)
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]
2445+ ::
2446+ :: +read-unit: ` and an operand, with no space
2447+ ::
2448+ ++ read-unit
2449+ |= [tic=token ts=(list token)]
2450+ ^- (pare expr)
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]
2454+ ::
2455+ :: +read-ctor: |= and a term, with no space: a case's constructor
2456+ ::
2457+ ++ read-ctor
2458+ |= [bar=token ts=(list token)]
2459+ ^- (pare expr)
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]
2463+ ::
2464+ :: +read-path: a path literal, as /posts/~zod (doc question)
2465+ ::
2466+ ++ read-path
2467+ |= [sl=token ts=(list token)]
2468+ ^- (pare expr)
2469+ ;< [[sp=span segs=(list @ta)] after=(list token)] then
2470+ (read-pathlit sl ts)
2471+ [%& [%path sp segs] after]
2472+ ::
2473+ :: +read-qath: %/, then its segments, knots or (expr), each after a
2474+ :: tight / and tight itself; %/ alone is the root
2475+ ::
2476+ ++ read-qath
2477+ |= [cen=token ts=(list token)]
2478+ ^- (pare expr)
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)
2484+ |- ^- (pare expr)
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")
2493+ ::
2494+ :: +read-qseg: an application path's segment, a knot or (expr), and
2495+ :: where it ends
2496+ ::
2497+ ++ read-qseg
2498+ |= ts=(list token)
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")
2503+ =* par i.ts
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]
2507+ ::
2508+ :: +read-string: after its str-head, a string's interpolations and
2509+ :: text: expr { str-mid expr } str-tail
2510+ ::
2511+ ++ read-string
2512+ |= [head=token ts=(list token)]
2513+ ^- (pare expr)
2514+ =/ ps=(list piece)
2515+ ?.(?=([%str-head *] lex.head) ~ (text-piece p.lex.head))
2516+ =/ op=token head
2517+ |- ^- (pare expr)
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]
2527+ ::
2528+ :: +read-group: ( expr ), or ( { operand } and its lines below, left
2529+ :: open
2530+ ::
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.
2534+ ::
2535+ ++ read-group
2536+ |= [par=token ts=(list token)]
2537+ ^- (pare expr)
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]
2553+ ::
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
2556+ ::
2557+ ++ read-bracket
2558+ |= $: kind=?(%tuple %list %change)
2559+ op=token
2560+ target=(unit [t=token names=(list term)])
2561+ ts=(list token)
2562+ ==
2563+ ^- (pare expr)
2564+ =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
2565+ =| its=(list item)
2566+ |- ^- (pare expr)
2567+ ?~ ts (bad ts "an item")
2568+ =* t i.ts
2569+ ?: =(close lex.t)
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)
2583+ ::
2584+ :: +read-item: [ name= ] operand; a tuple's item may be named, a
2585+ :: change's must be, a list's is not
2586+ ::
2587+ ++ read-item
2588+ |= [kind=?(%tuple %list %change) ts=(list token)]
2589+ ^- (pare item)
2590+ ?: &(!?=(%list kind) ?=([[* * [%name *]] [* %& %'='] *] ts))
2591+ =* nam i.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]
2602+ ::
2603+ :: +read-lines: after an open bracket's INDENT, its lines, an item
2604+ :: each, to its DEDENT
2605+ ::
2606+ ++ read-lines
2607+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
2608+ ^- (pare (list item))
2609+ =| ls=(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"
2617+ ::
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
2620+ :: (doc question)
2621+ ::
2622+ ++ read-line
2623+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
2624+ ^- (pare item)
2625+ ?: ?& ?=(?(%tuple %change) kind)
2626+ ?=([[* * [%name *]] [* %& %'='] *] ts)
2627+ ==
2628+ =* nam i.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]
2636+ ::
2637+ :: +read-gate-wide: |=( sample operand ), the one wide expression
2638+ ::
2639+ ++ read-gate-wide
2640+ |= [op=token ts=(list token)]
2641+ ^- (pare expr)
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)
2653+ %^ bad-why 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"
2656+ ::
2657+ :: +read-gate: |= sample, then an expression or a body
2658+ ::
2659+ ++ read-gate
2660+ |= [bar=token ts=(list token)]
2661+ ^- (pare expr)
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]
2667+ ::
2668+ :: +read-cast: ^- mold, then an expression or a body
2669+ ::
2670+ ++ read-cast
2671+ |= [ket=token ts=(list token)]
2672+ ^- (pare expr)
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]
2678+ ::
2679+ :: +read-trace: ~& expr, then its body below
2680+ ::
2681+ ++ read-trace
2682+ |= [sig=token ts=(list token)]
2683+ ^- (pare expr)
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]
2690+ ::
2691+ :: +read-branch: ?- expr, then its arms below, one per line
2692+ ::
2693+ ++ read-branch
2694+ |= [wut=token ts=(list token)]
2695+ ^- (pare expr)
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")
2700+ =| arms=(list arm)
2701+ =/ rest=(list token) t.after
2702+ |- ^- (pare expr)
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]
2707+ ::
2708+ :: +read-arm: a pattern, then an expression or a body
2709+ ::
2710+ ++ read-arm
2711+ |= ts=(list token)
2712+ ^- (pare arm)
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]
2720+ ::
2721+ :: +read-pattern: a term, number, string, ship, loobean, ~, * or name,
2722+ :: or a cell of patterns
2723+ ::
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).
2727+ ::
2728+ ++ read-pattern
2729+ |= ts=(list token)
2730+ ^- (pare pattern)
2731+ ?~ ts (bad ts "a pattern")
2732+ =* t i.ts
2733+ =/ next=loc [line.beg.at.t +(col.beg.at.t)]
2734+ ?+ lex.t (bad ts "a pattern")
2735+ [%lit *]
2736+ =* l p.lex.t
2737+ ?: ?=(?(%number %ship %term %loobean %null) form.l)
2738+ [%& [%lit at.t l] t.ts]
2739+ =/ what=tape
2740+ ?- form.l
2741+ %date "dates"
2742+ %duration "durations"
2743+ %knot "knots"
2744+ ==
2745+ %+ bad-at next
2746+ ;: weld
2747+ "expected a pattern, found {(show-found t)}; patterns take no "
2748+ what
2749+ ": compare values with ?- (eq a b)"
2750+ ==
2751+ ::
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]")
2757+ ::
2758+ [%str-head *]
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 `\{…}`"
2762+ ::
2763+ %'~['
2764+ %+ bad-at next
2765+ "expected a pattern, found `~[`; patterns take no lists"
2766+ ==
2767+ ::
2768+ :: +read-cell-pattern: [ pattern { pattern } ], closed on its line
2769+ ::
2770+ ++ read-cell-pattern
2771+ |= [op=token ts=(list token)]
2772+ ^- (pare pattern)
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)
2783+ ::
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)
2786+ ::
2787+ ++ read-sample
2788+ |= ts=(list token)
2789+ ^- (pare sample)
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]
2797+ =* op i.ts
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)
2809+ ::
2810+ :: +read-field: a cell mold's field: name=mold, =name, or a mold
2811+ ::
2812+ ++ read-field
2813+ |= ts=(list token)
2814+ ^- (pare field)
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]
2819+ ::
2820+ :: +read-face: name=mold, with no spaces
2821+ ::
2822+ ++ read-face
2823+ |= ts=(list token)
2824+ ^- (pare field)
2825+ ?. ?=([[* * [%name *]] [* * %'='] *] ts) (bad ts "a name")
2826+ =* nam i.ts
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]
2831+ ::
2832+ :: +read-pun: =name, with no space, for name=name
2833+ ::
2834+ ++ read-pun
2835+ |= [tis=token ts=(list token)]
2836+ ^- (pare field)
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]
2840+ ::
2841+ :: +read-mold: one mold
2842+ ::
2843+ ++ read-mold
2844+ |= ts=(list token)
2845+ ^- (pare shape)
2846+ ?~ ts (bad ts "a mold")
2847+ =* t i.ts
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)
2863+ ::
2864+ [%lit *]
2865+ ?. ?=(?(%null %term %loobean) form.p.lex.t) (bad ts "a mold")
2866+ [%& [%const at.t p.lex.t] t.ts]
2867+ ==
2868+ ::
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
2871+ ::
2872+ ++ read-molds
2873+ |= [op=token spaced=? ts=(list token)]
2874+ ^- (pare [(list shape) loc])
2875+ =| ms=(list shape)
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)
2885+ ::
2886+ :: +read-apply: ( ref mold { mold } )
2887+ ::
2888+ ++ read-apply
2889+ |= [op=token ts=(list token)]
2890+ ^- (pare shape)
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]
2896+ ::
2897+ :: +read-union-wide: $?( mold { mold } )
2898+ ::
2899+ ++ read-union-wide
2900+ |= [op=token ts=(list token)]
2901+ ^- (pare shape)
2902+ ;< [[ms=(list shape) fin=loc] after=(list token)] then
2903+ (read-molds op | ts)
2904+ [%& [%union [beg.at.op fin] ms] after]
2905+ ::
2906+ :: +read-fn: $-( mold mold )
2907+ ::
2908+ ++ read-fn
2909+ |= [op=token ts=(list token)]
2910+ ^- (pare shape)
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]
2919+ ::
2920+ :: +read-cell-mold: [ field { field } ]
2921+ ::
2922+ ++ read-cell-mold
2923+ |= [op=token ts=(list token)]
2924+ ^- (pare shape)
2925+ =| fs=(list field)
2926+ |- ^- (pare shape)
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)
2935+ ::
2936+ :: +read-union: $?, then its cases below, one mold per line
2937+ ::
2938+ ++ read-union
2939+ |= [buc=token ts=(list token)]
2940+ ^- (pare shape)
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)"
2946+ =| cs=(list shape)
2947+ =/ rest=(list token) t.ts
2948+ |- ^- (pare shape)
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")
2955+ ::
2956+ :: +read-generic: |$ [ typevar { typevar } ] mold
2957+ ::
2958+ ++ read-generic
2959+ |= [bar=token ts=(list token)]
2960+ ^- (pare shape)
2961+ ?: &(?=(^ ts) tight.i.ts) (bad ts "a space after `|$`")
2962+ ?. ?=([[* * %'['] *] ts)
2963+ (bad ts "`[` and its type variables, as in |$ [M]")
2964+ =* op i.ts
2965+ =| vs=(list @t)
2966+ =/ rest=(list token) t.ts
2967+ |- ^- (pare shape)
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)
2979+ ::
2980+ :: +read-pathmold: / [ segment { / segment } ], each / and segment
2981+ :: tight; / alone is the empty path
2982+ ::
2983+ ++ read-pathmold
2984+ |= [sl=token ts=(list token)]
2985+ ^- (pare shape)
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)
2991+ |- ^- (pare shape)
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")
3000+ ::
3001+ :: +read-pseg: a path mold's segment, a knot or [name=aura] with no
3002+ :: spaces, and where it ends
3003+ ::
3004+ ++ read-pseg
3005+ |= ts=(list token)
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")
3010+ =* op i.ts
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]
3025+ --
3026+::
3027++| %span-check
3028+::
3029+:: +outline: a node as +check-spans sees it
3030+::
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.
3035+::
3036++$ outline
3037+ $~ [%$ *span ~ ~ | ~]
3038+ $: kind=@tas
3039+ at=span
3040+ lead=(list @)
3041+ last=(list @)
3042+ open=?
3043+ kids=(list outline)
3044+ ==
3045+::
3046+:: +check-spans: whether a module's spans follow section 1's rules
3047+::
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 ~.
3054+::
3055+++ check-spans
3056+ |= [mod=module toks=(list token)]
3057+ ^- (unit tape)
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))
3063+::
3064+:: +kind-of: a token's kind: a glyph, or its lexeme's tag
3065+::
3066+++ kind-of
3067+ |= t=token
3068+ ^- @
3069+ ?@(lex.t lex.t -.lex.t)
3070+::
3071+:: +check-kids: nodes in source order, inside the span in, each checked
3072+::
3073+++ check-kids
3074+ |= [maps=[begs=(map loc @) ends=(map loc @)] in=(unit span) os=(list outline)]
3075+ ^- (unit tape)
3076+ =| prev=(unit span)
3077+ |- ^- (unit tape)
3078+ ?~ os ~
3079+ =* o i.os
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)
3087+ ?^ bad bad
3088+ $(prev `at.o, os t.os)
3089+::
3090+:: +check-outline: one node's start and end, then its children
3091+::
3092+++ check-outline
3093+ |= [maps=[begs=(map loc @) ends=(map loc @)] o=outline]
3094+ ^- (unit tape)
3095+ =* ks kids.o
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)
3101+ ?~ lead.o
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"
3111+ ~
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)) ~
3116+ ?~ last.o
3117+ ?~ tail `"has no token or child to end with"
3118+ `"should end where its last child does, at {(show-loc end.u.tail)}"
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"
3125+ ~
3126+ ?^ stop `(span-bad o u.stop)
3127+ (check-kids maps `at.o ks)
3128+::
3129+:: +span-bad: a span check's error, naming the node by kind and span
3130+::
3131+++ span-bad
3132+ |= [o=outline why=tape]
3133+ ^- tape
3134+ "({(trip kind.o)} {(show-loc beg.at.o)} to {(show-loc end.at.o)}) {why}"
3135+::
3136+:: +loc-lth: whether a comes before b
3137+::
3138+++ loc-lth
3139+ |= [a=loc b=loc]
3140+ ^- ?
3141+ ?| (lth line.a line.b)
3142+ &(=(line.a line.b) (lth col.a col.b))
3143+ ==
3144+::
3145+++ outline-import
3146+ |= i=import
3147+ ^- outline
3148+ ?- -.i
3149+ %sur [%sur at.i ~[%'/-'] ~[%name] | ~]
3150+ %mark [%mark at.i ~[%'/%'] ~[%lit] | ~]
3151+ %jibb [%jibb at.i ~[%'/='] ~[%'/' %knot] | ~]
3152+ ==
3153+::
3154+++ outline-def
3155+ |= d=def
3156+ ^- outline
3157+ ?- -.d
3158+ %mold [%mold at.d ~[%'+$'] ~ | ~[(outline-shape shape.d)]]
3159+ %value [%value at.d ~[%'++'] ~ | ~[(outline-expr val.d)]]
3160+ ==
3161+::
3162+++ outline-expr
3163+ |= e=expr
3164+ ^- outline
3165+ ?- -.e
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 ~[%'!!'] ~[%'!!'] | ~]
3177+ ::
3178+ %qath
3179+ =/ ks=(list outline)
3180+ %+ murn segs.e
3181+ |=(s=qseg ?.(?=(%expr -.s) ~ `(outline-expr p.s)))
3182+ [%qath at.e ~[%'%/'] ~[%'%/' %knot %')'] | ks]
3183+ ::
3184+ %change
3185+ =/ ks=(list outline) (turn edits.e outline-edit)
3186+ [%change at.e ~[%name %wing] ~[%')'] & ks]
3187+ ::
3188+ %gate-wide
3189+ =/ ks=(list outline)
3190+ ~[(outline-sample sample.e) (outline-expr body.e)]
3191+ [%gate-wide at.e ~[%'|=('] ~[%')'] | ks]
3192+ ::
3193+ %call
3194+ [%call at.e ~ ~ | [(outline-expr head.e) (turn args.e outline-expr)]]
3195+ ::
3196+ %gate
3197+ =/ ks=(list outline)
3198+ ~[(outline-sample sample.e) (outline-expr body.e)]
3199+ [%gate at.e ~[%'|='] ~ | ks]
3200+ ::
3201+ %cast
3202+ =/ ks=(list outline) ~[(outline-shape shape.e) (outline-expr val.e)]
3203+ [%cast at.e ~[%'^-'] ~ | ks]
3204+ ::
3205+ %trace
3206+ =/ ks=(list outline) ~[(outline-expr val.e) (outline-expr then.e)]
3207+ [%trace at.e ~[%'~&'] ~ | ks]
3208+ ::
3209+ %branch
3210+ =/ ks=(list outline)
3211+ [(outline-expr subject.e) (turn arms.e outline-arm)]
3212+ [%branch at.e ~[%'?-'] ~ | ks]
3213+ ::
3214+ %body
3215+ =/ ks=(list outline)
3216+ (snoc (turn defs.e outline-def) (outline-expr final.e))
3217+ [%body at.e ~ ~ | ks]
3218+ ==
3219+::
3220+++ outline-str
3221+ |= [at=span ps=(list piece)]
3222+ ^- outline
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]
3227+::
3228+++ outline-item
3229+ |= i=item
3230+ ^- outline
3231+ ?~ face.i [%item at.i ~ ~ | ~[(outline-expr val.i)]]
3232+ [%face at.i ~[%name] ~ | ~[(outline-expr val.i)]]
3233+::
3234+++ outline-edit
3235+ |= e=edit
3236+ ^- outline
3237+ [%edit at.e ~[%name] ~ | ~[(outline-expr val.e)]]
3238+::
3239+++ outline-arm
3240+ |= a=arm
3241+ ^- outline
3242+ [%arm at.a ~ ~ | ~[(outline-pattern pat.a) (outline-expr val.a)]]
3243+::
3244+++ outline-sample
3245+ |= s=sample
3246+ ^- outline
3247+ ?- -.s
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)]]
3253+ ==
3254+::
3255+++ outline-pattern
3256+ |= p=pattern
3257+ ^- outline
3258+ ?- -.p
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)]
3264+ ==
3265+::
3266+++ outline-shape
3267+ |= s=shape
3268+ ^- outline
3269+ ?- -.s
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)]
3279+ ::
3280+ %path
3281+ =/ ks=(list outline)
3282+ %+ murn segs.s
3283+ |= g=pseg
3284+ ^- (unit outline)
3285+ ?. ?=(%typed -.g) ~
3286+ `[%typed at.g ~[%'['] ~[%']'] | ~]
3287+ [%path at.s ~[%'/'] ~[%'/' %knot %']'] & ks]
3288+ ::
3289+ %union
3290+ =/ ks=(list outline) (turn cases.s outline-shape)
3291+ [%union at.s ~[%'$?' %'$?('] ~[%')'] & ks]
3292+ ::
3293+ %fn
3294+ =/ ks=(list outline)
3295+ ~[(outline-shape sample.s) (outline-shape product.s)]
3296+ [%fn at.s ~[%'$-('] ~[%')'] | ks]
3297+ ::
3298+ %generic
3299+ [%generic at.s ~[%'|$'] ~ | ~[(outline-shape body.s)]]
3300+ ==
19503301--