@@ -405,6 +405,7 @@
405:: Why: after the layout pass the grammar is LL(2). Each choice is made by
405:: Why: after the layout pass the grammar is LL(2). Each choice is made by
406:: the next token, at most with the one after it and whether it is tight:
406:: the next token, at most with the one after it and whether it is tight:
407:: name, then = tight a face (items, lines, fields, samples)
407:: name, then = tight a face (items, lines, fields, samples)
408+:: wing, then = tight a change's item or line, wing=value
408:: name, then + tight a pair
409:: name, then + tight a pair
409:: name or wing, then ( tight a change
410:: name or wing, then ( tight a change
410:: |=, then a term tight a constructor; else, where an
411:: |=, then a term tight a constructor; else, where an
@@ -472,7 +473,9 @@
472:: that line, as () is no group. A ( followed by a rune is
473:: that line, as () is no group. A ( followed by a rune is
473:: the closed form. Lines of an open group or list take no
474:: the closed form. Lines of an open group or list take no
474:: name= (doc question)
475:: 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=
476:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch.
479:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch.
477:: !! is an operand, not a rune (Decisions): alone where an
480:: !! is an operand, not a rune (Decisions): alone where an
478:: expression goes it is a call of one operand, and !! a
481:: expression goes it is a call of one operand, and !! a
@@ -604,11 +607,12 @@
604:: found the end of the line" (+fail-space). No later line can give
607:: found the end of the line" (+fail-space). No later line can give
605:: a tight form its next token. A wing and a ( after a space are no
608:: a tight form its next token. A wing and a ( after a space are no
606:: error: that is a call; nor is / or %/ alone, a whole path. A
609:: 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
610+:: change's item is name= or wing=, so a name or a wing there with
608−:: fails just past the name, whatever follows: `m(b c)` at the
611+:: no = right after it fails just past it, whatever follows: `m(b c)`
609−:: space, `m(b)` at the ), `m(a"x)` at the " with the layout pass's
612+:: and `m(a.b 1)` at the space, `m(b)` at the ), `m(a"x)` at the "
610−:: message after the parser's (+unnamed, +moved). `m(a==1)` has its
613+:: with the layout pass's message after the parser's (+unnamed,
611−:: =, and fails at the second, where the layout pass does.
614+:: +moved). `m(a==1)` has its =, and fails at the second, where the
612:: - Where the place needs text on its own line and the line ends,
616:: - Where the place needs text on its own line and the line ends,
613:: whatever line comes next: at the end of that line, just past its
617:: whatever line comes next: at the end of that line, just past its
614:: last token, "found the end of the line" (+fail-line), as no later
618:: last token, "found the end of the line" (+fail-line), as no later
@@ -964,9 +968,10 @@
965+$ item $~([*span ~ *expr] [at=span face=(unit term) val=expr])
969+$ item $~([*span ~ *expr] [at=span face=(unit term) val=expr])
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]
969−+$ edit $~([*span %$ *expr] [at=span name=term val=expr])
974++$ edit $~([*span ~ *expr] [at=span names=(list term) val=expr])
971:: +arm: a ?- arm, a pattern and an expression or body
976:: +arm: a ?- arm, a pattern and an expression or body
@@ -2280,7 +2285,7 @@
2280++ sexp-edit
2285++ sexp-edit
2281 |= e=edit
2286 |= e=edit
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)])
2285++ sexp-arm
2290++ sexp-arm
2286 |= a=arm
2291 |= a=arm
@@ -2689,24 +2694,32 @@
2689 ?~ t.els i.els
2694 ?~ t.els i.els
2690 [%call [beg:(span-of i.els) end:(span-of (rear t.els))] i.els t.els]
2695 [%call [beg:(span-of i.els) end:(span-of (rear t.els))] i.els t.els]
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 ~
2700++$ slot [at=span face=(list term) val=expr]
2692:: +bracket-node: a tuple, list or change from its items, ending at fin
2702:: +bracket-node: a tuple, list or change from its items, ending at fin
2694++ bracket-node
2704++ bracket-node
2695 |= $: kind=?(%tuple %list %change)
2705 |= $: kind=?(%tuple %list %change)
2696 op=token
2706 op=token
2697 target=(unit [t=token names=(list term)])
2707 target=(unit [t=token names=(list term)])
2698− its=(list item)
2708+ its=(list slot)
2703− %tuple [%tuple [beg.at.op fin] its]
2714+ :+ %tuple [beg.at.op fin]
2704− %list [%list [beg.at.op fin] (turn its |=(i=item val.i))]
2715+ (turn its |=(i=slot ^-(item [at.i ?~(face.i ~ `i.face.i) val.i])))
2717+ %list [%list [beg.at.op fin] (turn its |=(i=slot val.i))]
2707 =/ beg=loc ?~(target beg.at.op beg.at.t.u.target)
2720 =/ beg=loc ?~(target beg.at.op beg.at.t.u.target)
2708 :^ %change [beg fin] ?~(target ~ names.u.target)
2721 :^ %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])))
2712+| %parser
2725+| %parser
@@ -2927,23 +2940,22 @@
2928 :: +unnamed: a change's item or line without its name=
2941 :: +unnamed: a change's item or line without its name=
2930− :: A name could still begin one, so the error is just past it, as
2943+ :: A name or a wing could still begin one, so the error is just
2931− :: a tight form's is (+fail-space): `m(b c)` at the space, `m(b)`
2944+ :: past it, as a tight form's is (+fail-space): `m(b c)` and
2932− :: at the ). So is an error token's text there, unless it begins
2945+ :: `m(a.b 1)` at the space, `m(b)` at the ). So is an error token's
2933− :: with the =: `m(a"x)` at the ", with the layout pass's message
2946+ :: text there, unless it begins with the =: `m(a"x)` at the ", with
2934− :: after the parser's (+moved), but `m(a==1)` at the lexer's error,
2947+ :: the layout pass's message after the parser's (+moved), but
2935− :: the second =. So is a wing's first name: `m(a.b=1)` fails at the
2948+ :: `m(a==1)` at the lexer's error, the second =. At an error token
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).
2949+ :: whose text can't begin a name, at that text, as `m( @sd` at the
2939 ++ unnamed
2952 ++ unnamed
2940 |= ts=(list token)
2953 |= ts=(list token)
2941 ^- [%| p=error]
2954 ^- [%| p=error]
2942 =/ why=tape "a change's items are named, as in m(done=%.y)"
2955 =/ why=tape "a change's items are named, as in m(done=%.y)"
2943 ?: ?=([[* * [%error *]] *] ts) (bad-in ts "a named item" lower-mask)
2956 ?: ?=([[* * [%error *]] *] ts) (bad-in ts "a named item" lower-mask)
2944− ?: ?=([[* * [%wing *]] *] ts)
2957+ ?. ?=([[* * ?([%name *] [%wing *])] *] ts)
2945− (bad-in-why ts "a named item" lower-mask why)
2946− ?. ?=([[* * [%name *]] *] ts) (bad-why ts "a named item" why)
2958+ (bad-why ts "a named item" why)
2947 =/ want=tape "`=` right after {(show-found i.ts)}"
2959 =/ want=tape "`=` right after {(show-found i.ts)}"
2948 ?: ?& ?=([* [* * [%error *]] *] ts)
2960 ?: ?& ?=([* [* * [%error *]] *] ts)
2949 =(end.at.i.ts from.lex.i.t.ts)
2961 =(end.at.i.ts from.lex.i.t.ts)
@@ -3462,9 +3474,9 @@
3462 (unclosed par ")" after)
3474 (unclosed par ")" after)
3463 ;< [els=(list expr) after=(list token)] then (read-operands ts)
3475 ;< [els=(list expr) after=(list token)] then (read-operands ts)
3464 ?: ?=([[* * %indent] *] after)
3476 ?: ?=([[* * %indent] *] after)
3465− ;< [ls=(list item) more=(list token)] then
3477+ ;< [ls=(list slot) more=(list token)] then
3466 (read-lines %group t.after)
3478 (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))))
3468 [%& [%group [beg.at.par end:(span-of inner)] inner] more]
3480 [%& [%group [beg.at.par end:(span-of inner)] inner] more]
3470 ?: ?=([[* * ?(%newline %dedent)] *] after)
3482 ?: ?=([[* * ?(%newline %dedent)] *] after)
@@ -3489,7 +3501,7 @@
3490 ^- (pare expr)
3502 ^- (pare expr)
3491 =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
3503 =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
3492− =| its=(list item)
3504+ =| its=(list slot)
3493 |- ^- (pare expr)
3505 |- ^- (pare expr)
3494 ?~ ts (bad ts "an item")
3506 ?~ ts (bad ts "an item")
3495 =* t i.ts
3507 =* t i.ts
@@ -3497,8 +3509,8 @@
3497 [%& (bracket-node kind op target (flop its) end.at.t) t.ts]
3509 [%& (bracket-node kind op target (flop its) end.at.t) t.ts]
3498 ?: (is-closer t) (unclosed op (trip close) ts)
3510 ?: (is-closer t) (unclosed op (trip close) ts)
3499 ?: ?=(%indent lex.t)
3511 ?: ?=(%indent lex.t)
3500− ;< [ls=(list item) more=(list token)] then (read-lines kind t.ts)
3512+ ;< [ls=(list slot) more=(list token)] then (read-lines kind t.ts)
3501− =/ every=(list item) (weld (flop its) ls)
3513+ =/ every=(list slot) (weld (flop its) ls)
3502 =/ fin=loc ?~(every end.at.op end.at:(rear every))
3514 =/ fin=loc ?~(every end.at.op end.at:(rear every))
3503 [%& (bracket-node kind op target every fin) more]
3515 [%& (bracket-node kind op target every fin) more]
3504 ?: &(?=(^ its) (shut op `at.i.its ts))
3516 ?: &(?=(^ its) (shut op `at.i.its ts))
@@ -3506,21 +3518,21 @@
3506 ?: ?=(?(%newline %dedent) lex.t)
3518 ?: ?=(?(%newline %dedent) lex.t)
3507 (unclosed-open op (trip close) "an item" ts)
3519 (unclosed-open op (trip close) "an item" ts)
3508 ?: &(tight.t ?=(^ its)) (no-space ts)
3520 ?: &(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)
3510 $(its [i its], ts more)
3522 $(its [i its], ts more)
3512 :: +read-item: [ name= ] operand; a tuple's item may be named, a
3524 :: +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
3515 ++ read-item
3527 ++ read-item
3516 |= [kind=?(%tuple %list %change) ts=(list token)]
3528 |= [kind=?(%tuple %list %change) ts=(list token)]
3517− ^- (pare item)
3529+ ^- (pare slot)
3518− ?: &(!?=(%list kind) ?=([[* * [%name *]] [* %& %'='] *] ts))
3530+ ?: &(?=([* * *] ts) (named-item kind ts))
3519 =* nam i.ts
3531 =* nam i.ts
3520 =/ rest=(list token) t.t.ts
3532 =/ rest=(list token) t.t.ts
3521 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3533 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3522 ;< [v=expr after=(list token)] then (read-operand rest)
3534 ;< [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]
3524 ?: ?=(%change kind) (unnamed ts)
3536 ?: ?=(%change kind) (unnamed ts)
3525 ?: &(?=(^ ts) (is-rune i.ts))
3537 ?: &(?=(^ ts) (is-rune i.ts))
3526 %: bad-in-why ts "an expression" operand-mask
3538 %: bad-in-why ts "an expression" operand-mask
@@ -3529,15 +3541,25 @@
3529 ;< [v=expr after=(list token)] then (read-operand ts)
3541 ;< [v=expr after=(list token)] then (read-operand ts)
3530 [%& [(span-of v) ~ v] after]
3542 [%& [(span-of v) ~ v] after]
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
3548+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
3550+ ?. ?=([* [* %& %'='] *] ts) |
3551+ ?: ?=([[* * [%name *]] *] ts) ?=(?(%tuple %change) kind)
3552+ &(?=(%change kind) ?=([[* * [%wing *]] *] ts))
3532 :: +read-lines: after an open bracket's INDENT, its lines, an item
3554 :: +read-lines: after an open bracket's INDENT, its lines, an item
3533 :: each, to its DEDENT
3555 :: each, to its DEDENT
3535 ++ read-lines
3557 ++ read-lines
3536 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3558 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3537− ^- (pare (list item))
3559+ ^- (pare (list slot))
3538− =| ls=(list item)
3560+ =| ls=(list slot)
3539− |- ^- (pare (list item))
3561+ |- ^- (pare (list slot))
3540− ;< [l=item after=(list token)] then (read-line kind ts)
3562+ ;< [l=slot after=(list token)] then (read-line kind ts)
3541 ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
3563 ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
3542 ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
3564 ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
3543 ?. ?=([[* * ?(%')' %']')] *] after) (bad-end-in after (tail-can val.l))
3565 ?. ?=([[* * ?(%')' %']')] *] after) (bad-end-in after (tail-can val.l))
@@ -3564,22 +3586,20 @@
3564 "its items end at the first line that isn't deeper"
3586 "its items end at the first line that isn't deeper"
3566 :: +read-line: an open bracket's line, [ name= ] expr; a tuple's may
3588 :: +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
3589+ :: be named, a change's must be, by a name or a wing, a list's and a
3568− :: (doc question)
3590+ :: group's are not (doc question)
3570 ++ read-line
3592 ++ read-line
3571 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3593 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3572− ^- (pare item)
3594+ ^- (pare slot)
3573 =/ cf (closer-first ts "an item")
3595 =/ cf (closer-first ts "an item")
3574 ?^ cf u.cf
3596 ?^ cf u.cf
3575− ?: ?& ?=(?(%tuple %change) kind)
3597+ ?: &(?=([* * *] ts) (named-item kind ts))
3576− ?=([[* * [%name *]] [* %& %'='] *] ts)
3578 =* nam i.ts
3598 =* nam i.ts
3579 =/ rest=(list token) t.t.ts
3599 =/ rest=(list token) t.t.ts
3580 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3600 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3581 ;< [v=expr after=(list token)] then (read-expr rest)
3601 ;< [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]
3583 ?: ?=(%change kind) (unnamed ts)
3603 ?: ?=(%change kind) (unnamed ts)
3584 ;< [v=expr after=(list token)] then (read-expr ts)
3604 ;< [v=expr after=(list token)] then (read-expr ts)
3585 [%& [(span-of v) ~ v] after]
3605 [%& [(span-of v) ~ v] after]
@@ -4437,7 +4457,7 @@
4437++ outline-edit
4457++ outline-edit
4438 |= e=edit
4458 |= e=edit
4439 ^- outline
4459 ^- outline
4440− [%edit at.e ~[%name] %kid ~[(outline-expr val.e)]]
4460+ [%edit at.e ~[%name %wing] %kid ~[(outline-expr val.e)]]
4442++ outline-arm
4462++ outline-arm
4443 |= a=arm
4463 |= a=arm
@@ -8735,7 +8755,9 @@
8735 `subject
8755 `subject
8737:: Infer changes only against a fully known record spine. Retain the
8757:: 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.
8739++ change-spine-known
8761++ change-spine-known
8740 |= [t=itype sub=isub]
8762 |= [t=itype sub=isub]
@@ -8747,19 +8769,18 @@
8747 $(t tal.t)
8769 $(t tal.t)
8749++ infer-change-edits
8771++ 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))]
8751 ^- iresult
8773 ^- iresult
8752 ?~ edits [%& target state]
8774 ?~ edits [%& target state]
8753 =/ entry=edit i.edits
8775 =/ 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)))
8755 [%| ["repeated change fields are not supported by partial inference" ~]]
8778 [%| ["repeated change fields are not supported by partial inference" ~]]
8756 ?. (change-spine-known target sub.state)
8779 ?. (change-spine-known target sub.state)
8757 [%| ["change target needs a known record in partial inference" ~]]
8780 [%| ["change target needs a known record in partial inference" ~]]
8758− =/ found=(list itype) (record-fields-named name.entry target sub.state)
8781+ =/ field=(each itype idiag) (change-wing-field entry target sub.state)
8759− ?~ found
8782+ ?: ?=(%| -.field) [%| p.field]
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
8783+ =/ expected=itype p.field
8763 =/ value=iresult (infer-call-context-arg val.entry expected env state at.entry)
8784 =/ value=iresult (infer-call-context-arg val.entry expected env state at.entry)
8764 ?: ?=(%| -.value) value
8785 ?: ?=(%| -.value) value
8765 =/ fit=ifit (itype-fit typ.p.value expected sub.state.p.value next.state.p.value)
8786 =/ fit=ifit (itype-fit typ.p.value expected sub.state.p.value next.state.p.value)
@@ -8768,7 +8789,67 @@
8768 =/ decimal=(unit idiag) (decimal-misfit val.entry typ.p.value expected sub.state.p.value next.state.p.value)
8789 =/ decimal=(unit idiag) (decimal-misfit val.entry typ.p.value expected sub.state.p.value next.state.p.value)
8769 ?^ decimal [%| u.decimal]
8790 ?^ decimal [%| u.decimal]
8770 [%| ["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)]]]]
8791 [%| ["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])
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
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)
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)}`"
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)
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])
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
8826+ =/ col=@ud col.beg.at.e
8827+ =/ ns=(list term) names.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)))
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
8838+ |= [t=itype sub=isub]
8840+ =. t (itype-walk t sub)
8841+ ?=(?(%atom %any-atom %flag %const %tag %collection %fn %union %noun %empty) -.t)
8843+:: +wing-overlap: whether two edits' wings, outermost first, name the
8844+:: same field or one a field inside the other's
8847+ |= [a=(list term) b=(list term)]
8773:: Backtick constructs the canonical prelude unit, after checking its
8854:: Backtick constructs the canonical prelude unit, after checking its
8774:: prepared template has the standard null and [~ u=A] cases.
8855:: prepared template has the standard null and [~ u=A] cases.
@@ -11948,13 +12029,29 @@
11948 =/ first=(unit idiag) ?:(?=(%expr -.i.segs) (duplicate-expr p.i.segs) ~)
12029 =/ first=(unit idiag) ?:(?=(%expr -.i.segs) (duplicate-expr p.i.segs) ~)
11949 ?^ first first
12030 ?^ first first
11950 $(segs t.segs)
12031 $(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.
11951++ duplicate-edits
12034++ duplicate-edits
11952 |= edits=(list edit)
12035 |= edits=(list edit)
11953 ^- (unit idiag)
12036 ^- (unit idiag)
12037+ =| seen=(list edit)
12038+ |- ^- (unit idiag)
11954 ?~ edits ~
12039 ?~ edits ~
12041+ =/ prior=(list edit)
12042+ (skim seen |=(p=edit (wing-overlap (flop names.p) (flop names.e))))
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")]
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]
11955− =/ first (duplicate-expr val.i.edits)
12052+ =/ first (duplicate-expr val.e)
11956 ?^ first first
12053 ?^ first first
11957− $(edits t.edits)
12054+ $(edits t.edits, seen [e seen])
11958++ duplicate-arms
12055++ duplicate-arms
11959 |= arms=(list arm)
12056 |= arms=(list arm)
11960 ^- (unit idiag)
12057 ^- (unit idiag)