@@ -405,6 +405,7 @@
405405:: Why: after the layout pass the grammar is LL(2). Each choice is made by
406406:: the next token, at most with the one after it and whether it is tight:
407407:: name, then = tight a face (items, lines, fields, samples)
408+:: wing, then = tight a change's item or line, wing=value
408409:: name, then + tight a pair
409410:: name or wing, then ( tight a change
410411:: |=, then a term tight a constructor; else, where an
@@ -472,7 +473,9 @@
472473:: that line, as () is no group. A ( followed by a rune is
473474:: the closed form. Lines of an open group or list take no
474475:: name= (doc question)
475−:: change every item and line has name= (the EBNF's "items named")
476+:: change every item and line has name= or wing=, as open.cart=
477+:: (the EBNF's edit) -> %change of edits, each with its
478+:: names as written; a tuple's item takes no wing=
476479:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch.
477480:: !! is an operand, not a rune (Decisions): alone where an
478481:: expression goes it is a call of one operand, and !! a
@@ -604,11 +607,12 @@
604607:: found the end of the line" (+fail-space). No later line can give
605608:: a tight form its next token. A wing and a ( after a space are no
606609:: error: that is a call; nor is / or %/ alone, a whole path. A
607−:: change's item is name=, so a name there with no = right after it
608−:: fails just past the name, whatever follows: `m(b c)` at the
609−:: space, `m(b)` at the ), `m(a"x)` at the " with the layout pass's
610−:: message after the parser's (+unnamed, +moved). `m(a==1)` has its
611−:: =, and fails at the second, where the layout pass does.
610+:: change's item is name= or wing=, so a name or a wing there with
611+:: no = right after it fails just past it, whatever follows: `m(b c)`
612+:: and `m(a.b 1)` at the space, `m(b)` at the ), `m(a"x)` at the "
613+:: with the layout pass's message after the parser's (+unnamed,
614+:: +moved). `m(a==1)` has its =, and fails at the second, where the
615+:: layout pass does.
612616:: - Where the place needs text on its own line and the line ends,
613617:: whatever line comes next: at the end of that line, just past its
614618:: last token, "found the end of the line" (+fail-line), as no later
@@ -964,9 +968,10 @@
964968::
965969+$ item $~([*span ~ *expr] [at=span face=(unit term) val=expr])
966970::
967−:: +edit: a change's item or line, name=value
971+:: +edit: a change's item or line, name=value or wing=value; names
972+:: as written, as a %wing's: open.cart is ~[%open %cart]
968973::
969−+$ edit $~([*span %$ *expr] [at=span name=term val=expr])
974++$ edit $~([*span ~ *expr] [at=span names=(list term) val=expr])
970975::
971976:: +arm: a ?- arm, a pattern and an expression or body
972977::
@@ -2280,7 +2285,7 @@
22802285++ sexp-edit
22812286 |= e=edit
22822287 ^- sexp
2283− (nod "edit" at.e (trip name.e) ~[(sexp-expr val.e)])
2288+ (nod "edit" at.e (show-names names.e) ~[(sexp-expr val.e)])
22842289::
22852290++ sexp-arm
22862291 |= a=arm
@@ -2689,24 +2694,32 @@
26892694 ?~ t.els i.els
26902695 [%call [beg:(span-of i.els) end:(span-of (rear t.els))] i.els t.els]
26912696::
2697+:: +slot: a bracket's item or line as read, before +bracket-node
2698+:: makes it an item or an edit: its name=, or a change's wing=, else ~
2699+::
2700++$ slot [at=span face=(list term) val=expr]
2701+::
26922702:: +bracket-node: a tuple, list or change from its items, ending at fin
26932703::
26942704++ bracket-node
26952705 |= $: kind=?(%tuple %list %change)
26962706 op=token
26972707 target=(unit [t=token names=(list term)])
2698− its=(list item)
2708+ its=(list slot)
26992709 fin=loc
27002710 ==
27012711 ^- expr
27022712 ?- kind
2703− %tuple [%tuple [beg.at.op fin] its]
2704− %list [%list [beg.at.op fin] (turn its |=(i=item val.i))]
2713+ %tuple
2714+ :+ %tuple [beg.at.op fin]
2715+ (turn its |=(i=slot ^-(item [at.i ?~(face.i ~ `i.face.i) val.i])))
2716+ ::
2717+ %list [%list [beg.at.op fin] (turn its |=(i=slot val.i))]
27052718 ::
27062719 %change
27072720 =/ beg=loc ?~(target beg.at.op beg.at.t.u.target)
27082721 :^ %change [beg fin] ?~(target ~ names.u.target)
2709− (turn its |=(i=item ^-(edit [at.i ?~(face.i %$ u.face.i) val.i])))
2722+ (turn its |=(i=slot ^-(edit [at.i face.i val.i])))
27102723 ==
27112724::
27122725+| %parser
@@ -2927,23 +2940,22 @@
29272940 ::
29282941 :: +unnamed: a change's item or line without its name=
29292942 ::
2930− :: A name could still begin one, so the error is just past it, as
2931− :: a tight form's is (+fail-space): `m(b c)` at the space, `m(b)`
2932− :: at the ). So is an error token's text there, unless it begins
2933− :: with the =: `m(a"x)` at the ", with the layout pass's message
2934− :: after the parser's (+moved), but `m(a==1)` at the lexer's error,
2935− :: the second =. So is a wing's first name: `m(a.b=1)` fails at the
2936− :: dot (+fail-in). At an error token whose text can't begin a name,
2937− :: at that text, as `m( @sd` at the @ (+fail-in).
2943+ :: A name or a wing could still begin one, so the error is just
2944+ :: past it, as a tight form's is (+fail-space): `m(b c)` and
2945+ :: `m(a.b 1)` at the space, `m(b)` at the ). So is an error token's
2946+ :: text there, unless it begins with the =: `m(a"x)` at the ", with
2947+ :: the layout pass's message after the parser's (+moved), but
2948+ :: `m(a==1)` at the lexer's error, the second =. At an error token
2949+ :: whose text can't begin a name, at that text, as `m( @sd` at the
2950+ :: @ (+fail-in).
29382951 ::
29392952 ++ unnamed
29402953 |= ts=(list token)
29412954 ^- [%| p=error]
29422955 =/ why=tape "a change's items are named, as in m(done=%.y)"
29432956 ?: ?=([[* * [%error *]] *] ts) (bad-in ts "a named item" lower-mask)
2944− ?: ?=([[* * [%wing *]] *] ts)
2945− (bad-in-why ts "a named item" lower-mask why)
2946− ?. ?=([[* * [%name *]] *] ts) (bad-why ts "a named item" why)
2957+ ?. ?=([[* * ?([%name *] [%wing *])] *] ts)
2958+ (bad-why ts "a named item" why)
29472959 =/ want=tape "`=` right after {(show-found i.ts)}"
29482960 ?: ?& ?=([* [* * [%error *]] *] ts)
29492961 =(end.at.i.ts from.lex.i.t.ts)
@@ -3462,9 +3474,9 @@
34623474 (unclosed par ")" after)
34633475 ;< [els=(list expr) after=(list token)] then (read-operands ts)
34643476 ?: ?=([[* * %indent] *] after)
3465− ;< [ls=(list item) more=(list token)] then
3477+ ;< [ls=(list slot) more=(list token)] then
34663478 (read-lines %group t.after)
3467− =/ inner=expr (call-of (weld els (turn ls |=(i=item val.i))))
3479+ =/ inner=expr (call-of (weld els (turn ls |=(i=slot val.i))))
34683480 [%& [%group [beg.at.par end:(span-of inner)] inner] more]
34693481 ?~ els
34703482 ?: ?=([[* * ?(%newline %dedent)] *] after)
@@ -3489,7 +3501,7 @@
34893501 ==
34903502 ^- (pare expr)
34913503 =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
3492− =| its=(list item)
3504+ =| its=(list slot)
34933505 |- ^- (pare expr)
34943506 ?~ ts (bad ts "an item")
34953507 =* t i.ts
@@ -3497,8 +3509,8 @@
34973509 [%& (bracket-node kind op target (flop its) end.at.t) t.ts]
34983510 ?: (is-closer t) (unclosed op (trip close) ts)
34993511 ?: ?=(%indent lex.t)
3500− ;< [ls=(list item) more=(list token)] then (read-lines kind t.ts)
3501− =/ every=(list item) (weld (flop its) ls)
3512+ ;< [ls=(list slot) more=(list token)] then (read-lines kind t.ts)
3513+ =/ every=(list slot) (weld (flop its) ls)
35023514 =/ fin=loc ?~(every end.at.op end.at:(rear every))
35033515 [%& (bracket-node kind op target every fin) more]
35043516 ?: &(?=(^ its) (shut op `at.i.its ts))
@@ -3506,21 +3518,21 @@
35063518 ?: ?=(?(%newline %dedent) lex.t)
35073519 (unclosed-open op (trip close) "an item" ts)
35083520 ?: &(tight.t ?=(^ its)) (no-space ts)
3509− ;< [i=item more=(list token)] then (read-item kind ts)
3521+ ;< [i=slot more=(list token)] then (read-item kind ts)
35103522 $(its [i its], ts more)
35113523 ::
35123524 :: +read-item: [ name= ] operand; a tuple's item may be named, a
3513− :: change's must be, a list's is not
3525+ :: change's must be, by a name or a wing, a list's is not
35143526 ::
35153527 ++ read-item
35163528 |= [kind=?(%tuple %list %change) ts=(list token)]
3517− ^- (pare item)
3518− ?: &(!?=(%list kind) ?=([[* * [%name *]] [* %& %'='] *] ts))
3529+ ^- (pare slot)
3530+ ?: &(?=([* * *] ts) (named-item kind ts))
35193531 =* nam i.ts
35203532 =/ rest=(list token) t.t.ts
35213533 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
35223534 ;< [v=expr after=(list token)] then (read-operand rest)
3523− [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
3535+ [%& [[beg.at.nam end:(span-of v)] (names-of lex.nam) v] after]
35243536 ?: ?=(%change kind) (unnamed ts)
35253537 ?: &(?=(^ ts) (is-rune i.ts))
35263538 %: bad-in-why ts "an expression" operand-mask
@@ -3529,15 +3541,25 @@
35293541 ;< [v=expr after=(list token)] then (read-operand ts)
35303542 [%& [(span-of v) ~ v] after]
35313543 ::
3544+ :: +named-item: whether ts begins an item's or a line's name=: a
3545+ :: tuple's or a change's name, or a change's wing, then = tight
3546+ ::
3547+ ++ named-item
3548+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
3549+ ^- ?
3550+ ?. ?=([* [* %& %'='] *] ts) |
3551+ ?: ?=([[* * [%name *]] *] ts) ?=(?(%tuple %change) kind)
3552+ &(?=(%change kind) ?=([[* * [%wing *]] *] ts))
3553+ ::
35323554 :: +read-lines: after an open bracket's INDENT, its lines, an item
35333555 :: each, to its DEDENT
35343556 ::
35353557 ++ read-lines
35363558 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3537− ^- (pare (list item))
3538− =| ls=(list item)
3539− |- ^- (pare (list item))
3540− ;< [l=item after=(list token)] then (read-line kind ts)
3559+ ^- (pare (list slot))
3560+ =| ls=(list slot)
3561+ |- ^- (pare (list slot))
3562+ ;< [l=slot after=(list token)] then (read-line kind ts)
35413563 ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
35423564 ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
35433565 ?. ?=([[* * ?(%')' %']')] *] after) (bad-end-in after (tail-can val.l))
@@ -3564,22 +3586,20 @@
35643586 "its items end at the first line that isn't deeper"
35653587 ::
35663588 :: +read-line: an open bracket's line, [ name= ] expr; a tuple's may
3567− :: be named, a change's must be, a list's and a group's are not
3568− :: (doc question)
3589+ :: be named, a change's must be, by a name or a wing, a list's and a
3590+ :: group's are not (doc question)
35693591 ::
35703592 ++ read-line
35713593 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3572− ^- (pare item)
3594+ ^- (pare slot)
35733595 =/ cf (closer-first ts "an item")
35743596 ?^ cf u.cf
3575− ?: ?& ?=(?(%tuple %change) kind)
3576− ?=([[* * [%name *]] [* %& %'='] *] ts)
3577− ==
3597+ ?: &(?=([* * *] ts) (named-item kind ts))
35783598 =* nam i.ts
35793599 =/ rest=(list token) t.t.ts
35803600 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
35813601 ;< [v=expr after=(list token)] then (read-expr rest)
3582− [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
3602+ [%& [[beg.at.nam end:(span-of v)] (names-of lex.nam) v] after]
35833603 ?: ?=(%change kind) (unnamed ts)
35843604 ;< [v=expr after=(list token)] then (read-expr ts)
35853605 [%& [(span-of v) ~ v] after]
@@ -4437,7 +4457,7 @@
44374457++ outline-edit
44384458 |= e=edit
44394459 ^- outline
4440− [%edit at.e ~[%name] %kid ~[(outline-expr val.e)]]
4460+ [%edit at.e ~[%name %wing] %kid ~[(outline-expr val.e)]]
44414461::
44424462++ outline-arm
44434463 |= a=arm
@@ -8735,7 +8755,9 @@
87358755 `subject
87368756::
87378757:: Infer changes only against a fully known record spine. Retain the
8738−:: target type; unknown spines and repeated edits remain unsupported.
8758+:: target type; unknown spines and overlapping edits remain unsupported.
8759+:: An edit's wing, as open.cart, reads through record fields only,
8760+:: outermost first, and its value fits the field it names.
87398761++ change-spine-known
87408762 |= [t=itype sub=isub]
87418763 ^- ?
@@ -8747,19 +8769,18 @@
87478769 $(t tal.t)
87488770::
87498771++ infer-change-edits
8750− |= [edits=(list edit) target=itype env=ienv state=istate seen=(list term)]
8772+ |= [edits=(list edit) target=itype env=ienv state=istate seen=(list (list term))]
87518773 ^- iresult
87528774 ?~ edits [%& target state]
87538775 =/ entry=edit i.edits
8754− ?: (lien seen |=(name=term =(name name.entry)))
8776+ =/ outer=(list term) (flop names.entry)
8777+ ?: (lien seen |=(prior=(list term) (wing-overlap prior outer)))
87558778 [%| ["repeated change fields are not supported by partial inference" ~]]
87568779 ?. (change-spine-known target sub.state)
87578780 [%| ["change target needs a known record in partial inference" ~]]
8758− =/ found=(list itype) (record-fields-named name.entry target sub.state)
8759− ?~ found
8760− [%| ["record has no field `{(trip name.entry)}`" ~[[at.entry "unknown field"]]]]
8761− ?^ t.found [%| ["change field is ambiguous in partial inference" ~]]
8762− =/ expected=itype i.found
8781+ =/ field=(each itype idiag) (change-wing-field entry target sub.state)
8782+ ?: ?=(%| -.field) [%| p.field]
8783+ =/ expected=itype p.field
87638784 =/ value=iresult (infer-call-context-arg val.entry expected env state at.entry)
87648785 ?: ?=(%| -.value) value
87658786 =/ fit=ifit (itype-fit typ.p.value expected sub.state.p.value next.state.p.value)
@@ -8768,7 +8789,67 @@
87688789 =/ decimal=(unit idiag) (decimal-misfit val.entry typ.p.value expected sub.state.p.value next.state.p.value)
87698790 ?^ decimal [%| u.decimal]
87708791 [%| ["change field and replacement do not unify" ~[[at.entry (site-type-note "expected replacement" expected sub.state.p.value)] [(span-of val.entry) (site-type-note "replacement" typ.p.value sub.state.p.value)]]]]
8771− $(edits t.edits, state state.p.value(sub sub.fit, next next.fit), seen [name.entry seen])
8792+ $(edits t.edits, state state.p.value(sub sub.fit, next next.fit), seen [outer seen])
8793+::
8794+:: +change-wing-field: the type of the field an edit's wing names in
8795+:: a known record target, read through record fields, outermost first
8796+::
8797+++ change-wing-field
8798+ |= [entry=edit target=itype sub=isub]
8799+ ^- (each itype idiag)
8800+ =/ outer=(list term) (flop names.entry)
8801+ =/ k=@ud (lent names.entry)
8802+ =/ typ=itype target
8803+ =| through=(unit [name=term at=span])
8804+ |- ^- (each itype idiag)
8805+ ?~ outer [%& typ]
8806+ =/ here=span (edit-name-at entry (dec k))
8807+ ?: &(?=(^ through) !(change-spine-known typ sub))
8808+ ?. (itype-not-record typ sub)
8809+ [%| ["change wing needs a known record in partial inference" ~]]
8810+ =/ label=tape "field `{(trip name.u.through)}`"
8811+ :- %|
8812+ :- "change wing `{(show-names names.entry)}` goes through `{(trip name.u.through)}`, which is not a record"
8813+ ~[[at.u.through (site-type-note label typ sub)]]
8814+ =/ found=(list itype) (record-fields-named i.outer typ sub)
8815+ ?~ found
8816+ [%| ["record has no field `{(trip i.outer)}`" ~[[here "unknown field"]]]]
8817+ ?^ t.found [%| ["change field is ambiguous in partial inference" ~]]
8818+ $(outer t.outer, k (dec k), typ i.found, through `[i.outer here])
8819+::
8820+:: +edit-name-at: where the kth name of an edit's wing is written,
8821+:: counting from 0: its names are joined by dots from the edit's start
8822+::
8823+++ edit-name-at
8824+ |= [e=edit k=@ud]
8825+ ^- span
8826+ =/ col=@ud col.beg.at.e
8827+ =/ ns=(list term) names.e
8828+ |- ^- span
8829+ ?~ ns at.e
8830+ =/ len=@ud (met 3 i.ns)
8831+ ?: =(0 k) [[line.beg.at.e col] [line.beg.at.e (add col len)]]
8832+ $(ns t.ns, k (dec k), col +((add col len)))
8833+::
8834+:: +itype-not-record: whether a type is surely no record: an atom, a
8835+:: loobean, a list or other collection, a gate, a union or a noun
8836+::
8837+++ itype-not-record
8838+ |= [t=itype sub=isub]
8839+ ^- ?
8840+ =. t (itype-walk t sub)
8841+ ?=(?(%atom %any-atom %flag %const %tag %collection %fn %union %noun %empty) -.t)
8842+::
8843+:: +wing-overlap: whether two edits' wings, outermost first, name the
8844+:: same field or one a field inside the other's
8845+::
8846+++ wing-overlap
8847+ |= [a=(list term) b=(list term)]
8848+ ^- ?
8849+ ?~ a &
8850+ ?~ b &
8851+ ?. =(i.a i.b) |
8852+ $(a t.a, b t.b)
87728853::
87738854:: Backtick constructs the canonical prelude unit, after checking its
87748855:: prepared template has the standard null and [~ u=A] cases.
@@ -11948,13 +12029,29 @@
1194812029 =/ first=(unit idiag) ?:(?=(%expr -.i.segs) (duplicate-expr p.i.segs) ~)
1194912030 ?^ first first
1195012031 $(segs t.segs)
12032+:: A change's items each set a field once: two that name the same field,
12033+:: or one a field inside the other's, as cart and open.cart, overlap.
1195112034++ duplicate-edits
1195212035 |= edits=(list edit)
1195312036 ^- (unit idiag)
12037+ =| seen=(list edit)
12038+ |- ^- (unit idiag)
1195412039 ?~ edits ~
11955− =/ first (duplicate-expr val.i.edits)
12040+ =/ e=edit i.edits
12041+ =/ prior=(list edit)
12042+ (skim seen |=(p=edit (wing-overlap (flop names.p) (flop names.e))))
12043+ ?^ prior
12044+ =/ same=? =(names.i.prior names.e)
12045+ =/ sites=(list [at=span note=tape])
12046+ :~ [at.i.prior "first field"]
12047+ [at.e ?:(same "repeated field" "overlapping field")]
12048+ ==
12049+ ?: same `["change field `{(show-names names.e)}` is repeated" sites]
12050+ =/ a=tape (show-names names.i.prior)
12051+ `["change fields `{a}` and `{(show-names names.e)}` overlap" sites]
12052+ =/ first (duplicate-expr val.e)
1195612053 ?^ first first
11957− $(edits t.edits)
12054+ $(edits t.edits, seen [e seen])
1195812055++ duplicate-arms
1195912056 |= arms=(list arm)
1196012057 ^- (unit idiag)