@@ -4611,6 +4611,7 @@
46114611 [%tag id=@ud literal=lit constructor=?]
46124612 [%const literal=lit]
46134613 [%collection name=term args=(list itype)]
4614+ [%recursive module=term name=term label=(unit @t)]
46144615 [%union cases=(list itype) origin=(unit [at=path name=term]) label=(unit @t) args=(list itype)]
46154616 [%face name=term body=itype]
46164617 [%fn sample=itype product=itype]
@@ -4663,6 +4664,7 @@
46634664 %tag =(n id.t)
46644665 %const |
46654666 %union |((lien cases.t |=(c=itype (itype-occurs n c sub))) (lien args.t |=(c=itype (itype-occurs n c sub))))
4667+ %recursive |
46664668 %collection (lien args.t |=(c=itype (itype-occurs n c sub)))
46674669 %face $(t body.t)
46684670 %fn |($(t sample.t) $(t product.t))
@@ -4681,6 +4683,8 @@
46814683 =. a (itype-walk a sub)
46824684 =. b (itype-walk b sub)
46834685 ?: =(a b) `sub
4686+ ?: &(?=(%recursive -.a) ?=(%recursive -.b))
4687+ ?:(&(=(module.a module.b) =(name.a name.b)) `sub ~)
46844688 ?: &(?=(%union -.a) ?=(%union -.b))
46854689 ?. =(origin.a origin.b) ~
46864690 ?: &(?=(~ args.a) ?=(~ args.b)) ?:(=(cases.a cases.b) `sub ~)
@@ -4756,6 +4760,7 @@
47564760 %tag |
47574761 %const |
47584762 %union |((lien cases.t |=(c=itype (itype-has-any-atom c sub))) (lien args.t |=(c=itype (itype-has-any-atom c sub))))
4763+ %recursive |
47594764 %collection (lien args.t |=(c=itype (itype-has-any-atom c sub)))
47604765 %face $(t body.t)
47614766 %fn |($(t sample.t) $(t product.t))
@@ -4825,6 +4830,7 @@
48254830 %tag &
48264831 %const &
48274832 %union |((lien cases.typ |=(c=itype (itype-has-fixed-atom c))) (lien args.typ |=(c=itype (itype-has-fixed-atom c))))
4833+ %recursive |
48284834 %collection (lien args.typ |=(c=itype (itype-has-fixed-atom c)))
48294835 %face $(typ body.typ)
48304836 %fn |($(typ sample.typ) $(typ product.typ))
@@ -4909,6 +4915,7 @@
49094915 %var &
49104916 %cell &
49114917 %union &
4918+ %recursive &
49124919 %collection &
49134920 %face $(t body.t)
49144921 %fn |($(t sample.t) $(t product.t))
@@ -4975,6 +4982,32 @@
49754982 * |
49764983 ==
49774984::
4985+++ itype-has-recursive
4986+ |= t=itype
4987+ ^- ?
4988+ ?- -.t
4989+ %recursive &
4990+ %collection (lien args.t |=(c=itype (itype-has-recursive c)))
4991+ %union (lien (weld args.t cases.t) |=(c=itype (itype-has-recursive c)))
4992+ %face $(t body.t)
4993+ %cell |($(t hed.t) $(t tal.t))
4994+ %fn |($(t sample.t) $(t product.t))
4995+ * |
4996+ ==
4997+::
4998+++ itype-has-hidden-recursive
4999+ |= t=itype
5000+ ^- ?
5001+ ?- -.t
5002+ %recursive ?=(~ label.t)
5003+ %collection (lien args.t |=(c=itype (itype-has-hidden-recursive c)))
5004+ %union (lien (weld args.t cases.t) |=(c=itype (itype-has-hidden-recursive c)))
5005+ %face $(t body.t)
5006+ %cell |($(t hed.t) $(t tal.t))
5007+ %fn |($(t sample.t) $(t product.t))
5008+ * |
5009+ ==
5010+::
49785011++ itype-fit-cases
49795012 |= [actual=itype cases=(list itype) sub=isub next=@ud]
49805013 ^- ifit
@@ -5022,6 +5055,9 @@
50225055 =. actual (itype-walk actual sub)
50235056 =. expected (itype-walk expected sub)
50245057 ?: =(actual expected) [%ok sub next]
5058+ ?: &(?=(%recursive -.actual) ?=(%recursive -.expected))
5059+ ?:(&(=(module.actual module.expected) =(name.actual name.expected)) [%ok sub next] [%bad ~])
5060+ ?: &(|(?=(%recursive -.actual) ?=(%recursive -.expected)) !|(?=(%var -.actual) ?=(%var -.expected))) [%unknown ~]
50255061 ?: &(?=(%union -.actual) ?=(%union -.expected))
50265062 ?. =(origin.actual origin.expected) [%unknown ~]
50275063 ?: &(?=(~ args.actual) ?=(~ args.expected))
@@ -5112,6 +5148,7 @@
51125148 =/ unified=(unit isub) (itype-unify actual expected sub)
51135149 ?~ unified
51145150 ?: |(?=(%face -.actual) ?=(%face -.expected)) [%unknown ~]
5151+ ?: |((itype-has-recursive (itype-normalize actual sub)) (itype-has-recursive (itype-normalize expected sub))) [%unknown ~]
51155152 ?: (itype-family-related actual expected sub) [%unknown ~]
51165153 [%bad ~]
51175154 [%ok u.unified next]
@@ -5126,6 +5163,7 @@
51265163 =/ unified=(unit isub) (itype-unify actual expected sub)
51275164 ?~ unified
51285165 ?: |((itype-has-union (itype-normalize actual sub)) (itype-has-union (itype-normalize expected sub))) [%unknown ~]
5166+ ?: |((itype-has-recursive (itype-normalize actual sub)) (itype-has-recursive (itype-normalize expected sub))) [%unknown ~]
51295167 ?: (itype-family-related actual expected sub) [%unknown ~]
51305168 [%bad ~]
51315169 [%ok u.unified next]
@@ -5171,6 +5209,20 @@
51715209 ["collection arguments should preserve aura-family uncertainty" problems]
51725210 =? problems !(itype-face-asym [%collection %list ~[[%face %x txt]]] list-t ~)
51735211 ["collection arguments should preserve face uncertainty" problems]
5212+ =/ recursive=itype [%recursive %fixture %chain `'chain.fixture']
5213+ =/ same-recursive=itype [%recursive %fixture %chain ~]
5214+ =/ other-recursive=itype [%recursive %other %chain `'chain.other']
5215+ =? problems ?=(~ (itype-unify recursive same-recursive ~))
5216+ ["recursive identity should not depend on its visible name" problems]
5217+ =? problems ?=(^ (itype-unify recursive other-recursive ~))
5218+ ["recursive identity should include the source module" problems]
5219+ =/ recursive-fit=ifit (itype-fit recursive txt ~ 0)
5220+ =? problems !?=(%unknown -.recursive-fit)
5221+ ["opaque recursive types should not be unfolded by a fit" problems]
5222+ =/ nested-fit=ifit
5223+ (itype-fit [%collection %list ~[a]] list-t ~[[0 recursive]] 1)
5224+ =? problems !?=(%unknown -.nested-fit)
5225+ ["recursive types behind substitutions should remain uncertain" problems]
51745226 problems
51755227::
51765228:: The expression inference below is deliberately a fragment: bindings,
@@ -5231,6 +5283,7 @@
52315283 ?- -.t
52325284 %fn &
52335285 %cell |($(t hed.t) $(t tal.t))
5286+ %recursive |
52345287 %collection (lien args.t |=(c=itype (itype-has-gate c)))
52355288 %face $(t body.t)
52365289 %union (lien cases.t |=(c=itype (itype-has-gate c)))
@@ -5269,6 +5322,7 @@
52695322 %tag ~
52705323 %const ~
52715324 %union (zing (turn (weld args.t cases.t) |=(c=itype (itype-vars c))))
5325+ %recursive ~
52725326 %collection (zing (turn args.t |=(c=itype (itype-vars c))))
52735327 %face $(t body.t)
52745328 %fn (weld $(t sample.t) $(t product.t))
@@ -5306,6 +5360,7 @@
53065360 %tag t
53075361 %const t
53085362 %union [%union (turn cases.t |=(c=itype (itype-rename c ren))) origin.t label.t (turn args.t |=(c=itype (itype-rename c ren)))]
5363+ %recursive t
53095364 %collection [%collection name.t (turn args.t |=(c=itype (itype-rename c ren)))]
53105365 %face [%face name.t $(t body.t)]
53115366 %fn [%fn $(t sample.t) $(t product.t)]
@@ -5328,6 +5383,7 @@
53285383 %tag |
53295384 %const |
53305385 %union |((lien cases.t |=(c=itype (itype-var-is-atom n c))) (lien args.t |=(c=itype (itype-var-is-atom n c))))
5386+ %recursive |
53315387 %collection (lien args.t |=(c=itype (itype-var-is-atom n c)))
53325388 %face $(t body.t)
53335389 %fn |($(t sample.t) $(t product.t))
@@ -5405,6 +5461,69 @@
54055461 ?. (is-lower i.chars) |
54065462 (levy t.chars |=(c=@tD (in c name-mask)))
54075463::
5464+:: A source-aware reader result is trusted for origin. Validate every
5465+:: supplied branch and keep the recursive mold opaque: unfolding its
5466+:: root while naming only its tail would change its type identity.
5467++$ irec-pattern [pat=upat has=?]
5468+++ rec-pattern
5469+ |= [node=* module=term name=term]
5470+ ^- (unit irec-pattern)
5471+ ?@ node ~
5472+ ?+ -.node ~
5473+ %atom
5474+ ?: ?=([%atom %n [~ @]] node)
5475+ ?. =(0 +>+.node) ~
5476+ `[[%atom `0] |]
5477+ ?: ?=([%atom %tas [~ @]] node)
5478+ =/ value=@ +>+.node
5479+ ?. |(=(value 0) (jibb-face-name value)) ~
5480+ `[[%atom `value] |]
5481+ ?. ?=([%atom @ ~] node) ~
5482+ =/ aura=@ta (@ta +<.node)
5483+ ?. |(?=(?(%u %ud %ux %uv %t %ta %tas %p %da %dr) aura) =('tD' aura)) ~
5484+ `[[%atom ~] |]
5485+ %ref
5486+ ?. ?=([%ref @ @] node) ~
5487+ ?. &(=(module +<.node) =(name +>.node)) ~
5488+ `[[%unknown ~] &]
5489+ %face
5490+ ?. ?=([%face @ *] node) ~
5491+ ?. (jibb-face-name +<.node) ~
5492+ $(node +>.node)
5493+ %cell
5494+ ?. ?=([%cell * *] node) ~
5495+ =/ left $(node +<.node)
5496+ ?~ left ~
5497+ =/ right $(node +>.node)
5498+ ?~ right ~
5499+ `[[%cell pat.u.left pat.u.right] |(has.u.left has.u.right)]
5500+ %fork
5501+ =/ cases (rec-patterns +.node module name)
5502+ ?~ cases ~
5503+ ?~ pats.u.cases ~
5504+ ?~ t.pats.u.cases ~
5505+ ?. (rec-patterns-disjoint pats.u.cases) ~
5506+ `[[%or pats.u.cases] has.u.cases]
5507+ ==
5508+::
5509+++ rec-patterns
5510+ |= [nodes=* module=term name=term]
5511+ ^- (unit [pats=(list upat) has=?])
5512+ ?@ nodes ?:(=(nodes 0) `[~ |] ~)
5513+ =/ first (rec-pattern -.nodes module name)
5514+ ?~ first ~
5515+ =/ rest $(nodes +.nodes)
5516+ ?~ rest ~
5517+ `[[pat.u.first pats.u.rest] |(has.u.first has.u.rest)]
5518+::
5519+++ rec-patterns-disjoint
5520+ |= pats=(list upat)
5521+ ^- ?
5522+ ?~ pats &
5523+ ?. (levy t.pats |=(p=upat =(%disjoint (union-relate i.pats p)))) |
5524+ $(pats t.pats)
5525+::
5526+::
54085527++ import-to-itype
54095528 |= node=*
54105529 ^- (unit itype)
@@ -5496,7 +5615,14 @@
54965615 =/ result=* result.i.found
54975616 ?@ result ~
54985617 ?. ?=(%& -.result) ~
5499− (import-to-itype +.result)
5618+ =/ node=* +.result
5619+ ?@ node (import-to-itype node)
5620+ ?: ?=(%ref -.node) (import-to-itype node)
5621+ =/ pattern=(unit irec-pattern) (rec-pattern node module name)
5622+ ?~ pattern (import-to-itype node)
5623+ ?. has.u.pattern (import-to-itype node)
5624+ `[%recursive module name `(crip "{(trip name)}.{(trip module)}")]
5625+
55005626::
55015627++ collect-sur-imports
55025628 |= imports=(list import)
@@ -5571,6 +5697,7 @@
55715697 ?~ alias ~
55725698 `(crip "{(trip u.alias)}.{(trip face)}")
55735699 [%union (turn cases.t |=(c=itype (itype-in-import c iface face))) origin.t label (turn args.t |=(c=itype (itype-in-import c iface face)))]
5700+ %recursive [%recursive module.t name.t ~]
55745701 %collection [%collection name.t (turn args.t |=(c=itype (itype-in-import c iface face)))]
55755702 %face [%face name.t $(t body.t)]
55765703 %fn [%fn $(t sample.t) $(t product.t)]
@@ -6006,6 +6133,85 @@
60066133 [%| ["branch arm does not fit its expected union" ~[[context "expected union"] [(span-of e) "branch arm"]]]]
60076134 [%& expected state.p.value(sub sub.fit, next next.fit)]
60086135::
6136+:: The supported unit pattern covers exactly an atom zero and a cell
6137+:: headed by zero, with a single binder for its payload. Unresolved
6138+:: subjects and all other pattern matrices stay outside this fragment.
6139+::
6140+++ unit-empty-pattern
6141+ |= p=pattern
6142+ ^- ?
6143+ ?. ?=(%lit -.p) |
6144+ =(%null form.lit.p)
6145+::
6146+++ unit-payload-pattern
6147+ |= p=pattern
6148+ ^- (unit term)
6149+ ?. ?=(%cell -.p) ~
6150+ ?~ items.p ~
6151+ ?~ t.items.p ~
6152+ ?^ t.t.items.p ~
6153+ ?. (unit-empty-pattern i.items.p) ~
6154+ ?. ?=(%bind -.i.t.items.p) ~
6155+ `name.i.t.items.p
6156+::
6157+++ unit-empty-case
6158+ |= t=itype
6159+ ^- ?
6160+ ?. ?=(%const -.t) |
6161+ =(0 val.literal.t)
6162+::
6163+++ unit-payload-case
6164+ |= t=itype
6165+ ^- (unit itype)
6166+ ?. ?=(%cell -.t) ~
6167+ ?. (unit-empty-case hed.t) ~
6168+ =/ payload=itype tal.t
6169+ =? payload ?=(%face -.payload) body.payload
6170+ `payload
6171+::
6172+++ unit-union-payload
6173+ |= t=itype
6174+ ^- (unit itype)
6175+ ?. ?=(%union -.t) ~
6176+ ?~ cases.t ~
6177+ ?~ t.cases.t ~
6178+ ?^ t.t.cases.t ~
6179+ ?: (unit-empty-case i.cases.t) (unit-payload-case i.t.cases.t)
6180+ ?: (unit-empty-case i.t.cases.t) (unit-payload-case i.cases.t)
6181+ ~
6182+::
6183+++ infer-unit-branch
6184+ |= [e=expr env=ienv state=istate]
6185+ ^- iresult
6186+ ?> ?=(%branch -.e)
6187+ ?~ arms.e [%| ["unit branch is not supported by partial inference" ~]]
6188+ ?~ t.arms.e [%| ["unit branch is not supported by partial inference" ~]]
6189+ ?^ t.t.arms.e [%| ["unit branch is not supported by partial inference" ~]]
6190+ =/ x=arm i.arms.e
6191+ =/ y=arm i.t.arms.e
6192+ =/ first-empty=? (unit-empty-pattern pat.x)
6193+ =/ first-name=(unit term) (unit-payload-pattern pat.x)
6194+ =/ second-name=(unit term) (unit-payload-pattern pat.y)
6195+ ?. |(&(first-empty ?=(^ second-name)) &((unit-empty-pattern pat.y) ?=(^ first-name)))
6196+ [%| ["unit branch pattern is not supported by partial inference" ~]]
6197+ =/ binder=(unit term) ?:(first-empty second-name first-name)
6198+ ?~ binder [%| ["unit branch pattern is not supported by partial inference" ~]]
6199+ ?: |(?=(^ (ienv-lookup u.binder env)) (lien globals.state |=(n=term =(n u.binder))))
6200+ [%| ["pattern binder shadows a name" ~]]
6201+ =/ subject=iresult (infer-fragment subject.e env state)
6202+ ?: ?=(%| -.subject) subject
6203+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
6204+ =/ payload=(unit itype) (unit-union-payload typ)
6205+ ?~ payload [%| ["unit branch subject is not supported by partial inference" ~]]
6206+ =/ extended=ienv [[u.binder [u.payload ~]] env]
6207+ =/ left=iresult (infer-fragment val.x ?:(first-empty env extended) state.p.subject)
6208+ ?: ?=(%| -.left) left
6209+ =/ right=iresult (infer-fragment val.y ?:(first-empty extended env) state.p.left)
6210+ ?: ?=(%| -.right) right
6211+ =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
6212+ ?~ joined [%| ["unit branch results need unsupported inference" ~]]
6213+ [%& typ.p.left state.p.right(sub u.joined)]
6214+::
60096215++ infer-fragment
60106216 |= [e=expr env=ienv state=istate]
60116217 ^- iresult
@@ -6073,6 +6279,8 @@
60736279 ?^ t.t.arms.e [%| ["branch is not supported by partial inference" ~]]
60746280 =/ x=arm i.arms.e
60756281 =/ y=arm i.t.arms.e
6282+ ?: |((unit-empty-pattern pat.x) (unit-empty-pattern pat.y))
6283+ (infer-unit-branch e env state)
60766284 ?. ?=(%lit -.pat.x) [%| ["branch pattern is not supported by partial inference" ~]]
60776285 ?. ?=(%lit -.pat.y) [%| ["branch pattern is not supported by partial inference" ~]]
60786286 ?. &(=(%loobean form.lit.pat.x) =(%loobean form.lit.pat.y))
@@ -6093,6 +6301,8 @@
60936301 [%| ["branch widening is not supported by partial inference" ~]]
60946302 =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
60956303 ?~ joined
6304+ ?: |((itype-has-recursive ltype) (itype-has-recursive rtype))
6305+ [%| ["recursive branch matching is not supported by partial inference" ~]]
60966306 ?: |((itype-has-tag ltype) (itype-has-tag rtype) (itype-has-union ltype) (itype-has-union rtype))
60976307 [%| ["branch tag or union context is not supported by partial inference" ~]]
60986308 =/ common=(unit itype) (itype-concrete-join typ.p.left typ.p.right sub.state.p.right)
@@ -6197,6 +6407,8 @@
61976407 =/ subject=iresult (infer-fragment subject.e env state)
61986408 ?: ?=(%| -.subject) subject
61996409 =/ st=istate state.p.subject
6410+ ?: (itype-has-recursive (itype-normalize typ.p.subject sub.st))
6411+ [%| ["recursive pattern is not supported by partial inference" ~]]
62006412 ?: (itype-has-face typ.p.subject sub.st)
62016413 [%| ["record patterns are not supported by partial inference" ~]]
62026414 =/ head=itype [%var next.st]
@@ -6228,6 +6440,7 @@
62286440 ?~ label.t (show-itype-cases cases.t sub)
62296441 ?~ args.t (trip u.label.t)
62306442 "({(trip u.label.t)} {(show-itype-cases args.t sub)})"
6443+ %recursive ?~(label.t "recursive mold" (trip u.label.t))
62316444 %collection "({(trip name.t)} {(show-itype-cases args.t sub)})"
62326445 %face "[{(trip name.t)}={(show-itype-context body.t sub)}]"
62336446 %fn "$-({(show-itype-context sample.t sub)} {(show-itype-context product.t sub)})"
@@ -6271,6 +6484,7 @@
62716484 %tag |
62726485 %const |
62736486 %union |((lien cases.typ |=(c=itype (itype-has-nvar c))) (lien args.typ |=(c=itype (itype-has-nvar c))))
6487+ %recursive |
62746488 %collection (lien args.typ |=(c=itype (itype-has-nvar c)))
62756489 %face $(typ body.typ)
62766490 %fn |($(typ sample.typ) $(typ product.typ))
@@ -6282,6 +6496,7 @@
62826496 ^- tape
62836497 =/ normalized=itype (itype-normalize typ sub)
62846498 ?: |(?=(%var -.normalized) ?=(%avar -.normalized) (itype-has-nvar normalized) (itype-has-tag normalized) (itype-has-union normalized)) label
6499+ ?: (itype-has-hidden-recursive normalized) label
62856500 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
62866501 ?: (gth (lent vars) 26) label
62876502 =/ printable=itype (canonical-itype normalized vars)
@@ -6348,6 +6563,7 @@
63486563 %tag |
63496564 %const |
63506565 %union |((lien cases.t |=(c=itype (has-atom-var n c))) (lien args.t |=(c=itype (has-atom-var n c))))
6566+ %recursive |
63516567 %collection (lien args.t |=(c=itype (has-atom-var n c)))
63526568 %face $(t body.t)
63536569 %fn |($(t sample.t) $(t product.t))
@@ -6820,6 +7036,8 @@
68207036 $(ds t.ds, lines [(crip "++ {(trip name.d)}: `~` needs context in partial inference") lines])
68217037 ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ))
68227038 $(ds t.ds, lines [(crip "++ {(trip name.d)}: tag needs context in partial inference") lines])
7039+ ?: (itype-has-hidden-recursive typ)
7040+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: recursive mold name is not available in this scope") lines])
68237041 ?: (itype-has-hidden-generic typ)
68247042 $(ds t.ds, lines [(crip "++ {(trip name.d)}: generic union name is not available in this scope") lines])
68257043 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result)