on master help sign in
Resolve contextual tags and check Hoon union cases
4406f6fiko
docs/compiler.md+2−2
@@ -56,9 +56,9 @@ The core is split into chapters, `+| %name`, in this order:
56| `%span-check` | `+check-spans`, which `+golden` runs on every tree, and `+check-spans-test` |
56| `%span-check` | `+check-spans`, which `+golden` runs on every tree, and `+check-spans-test` |
57| `%type-inference` | The initial inference fragment and its unification helpers; not yet a module type checker |
57| `%type-inference` | The initial inference fragment and its unification helpers; not yet a module type checker |
58
58
59−The inference fragment supports fixed auras, unrestricted `@`, one-way widening into it and toward aura-family ancestors, generic variables and gates, faced and unfaced cells, cell sample binders, known record field reads, a two-binder cell pattern, a complete two-arm loobean branch, closed local mold aliases and acyclic forward value references. It instantiates generalized top-level definitions when they are used. Acyclic local value definitions can refer forward and generalize variables that are free of their enclosing environment; captured variables and explicit capitals remain shared. Acyclic simple local mold aliases can also refer forward, and are scoped to the body, not its gate's sample. Nonrecursive generic aliases of supported molds can be applied at exact arity, including locally and through library interfaces; their parameters are lexical. Recursive local groups and recursive or union molds remain unsupported. It can infer and generalize atom constraints arising from explicit capitals or bare sample binders, preserve those constraints through aliases, instantiate them independently, and print multiple constraints. Unresolved decimal variables default to `@ud` for inferred types without gates; defaulting inside gate types and other constraint cases remain incomplete. It does not yet check a module, complete imports, general patterns, deferred constraints, recursive or union molds, dependency cycles or most errors with both conflicting excerpts. Definite cast and call mismatches, incompatible branches and overlapping union cases report both sites and excerpts. Concrete branch results can join at an explicitly present parent aura or `@`. Some known tuple and record positions acquire matching faces, while variable-dependent face merges and ambiguous call-result propagation remain unsupported; function compatibility involving nested `@` and variable-dependent joins remain unsupported except for equal types. The current dependency pass can take quadratic time on long forward chains; the milestone's speed target remains unverified. A separate conservative pass reports unions whose cases are provably disjoint or overlapping and leaves other cases unresolved; it does not claim the mold is checked. Unsupported forms are reported as such, and the partial output says the module has not been checked.
59+The inference fragment supports fixed auras, unrestricted `@`, one-way widening into it and toward aura-family ancestors, generic variables and gates, faced and unfaced cells, cell sample binders, known record field reads, a two-binder cell pattern, a complete two-arm loobean branch, closed local mold aliases and acyclic forward value references. It instantiates generalized top-level definitions when they are used. Acyclic local value definitions can refer forward and generalize variables that are free of their enclosing environment; captured variables and explicit capitals remain shared. Acyclic simple local mold aliases can also refer forward, and are scoped to the body, not its gate's sample. Nonrecursive generic aliases of supported molds can be applied at exact arity, including locally and through library interfaces; their parameters are lexical. Closed, provably disjoint nonrecursive unions and tagged single-case molds support contextual term values and `|=%tag` constructors; unresolved tags remain pending. Recursive local groups, recursive molds and generic unions remain unsupported. It can infer and generalize atom constraints arising from explicit capitals or bare sample binders, preserve those constraints through aliases, instantiate them independently, and print multiple constraints. Unresolved decimal variables default to `@ud` for inferred types without gates; defaulting inside gate types and other constraint cases remain incomplete. It does not yet check a module, complete imports, general patterns, general deferred constraints, recursive molds, dependency cycles or most errors with both conflicting excerpts. Definite cast and call mismatches, incompatible branches and overlapping union cases report both sites and excerpts. Concrete branch results can join at an explicitly present parent aura or `@`. Some known tuple and record positions acquire matching faces, while variable-dependent face merges, tag context across branches, union type printing and ambiguous call-result propagation remain unsupported; function compatibility involving nested `@` and variable-dependent joins remain unsupported except for equal types. The current dependency pass can take quadratic time on long forward chains; the milestone's speed target remains unverified. A separate conservative pass reports unions whose cases are provably disjoint or overlapping and leaves other cases unresolved; it does not claim the mold is checked. Unsupported forms are reported as such, and the partial output says the module has not been checked.
60
60
61−The separate `jibb-dev/lib/jibb-import.hoon` is an unfinished reader for selected Hoon type graphs. It handles named recursion, nested map, set, queue, list, unit, jar and jug arguments, direct ordered maps, and direct `$^` unions whose source branches can be proved disjoint. It also reads ordered map fields in records when the map arguments are syntactically fixed atom molds and other fields are fixed atom molds or standard collections of static atom molds. Collection names must not be shadowed. The reader can also import a mark door sample, removing its outer sample face and validating its build subject. A single nested `$^` in a record is checked when its branches and sibling fields use only aura atom molds such as `@ud`, constant tags and records built from them; both source branches are re-evaluated, unchanged siblings are verified and overlapping cases are rejected. Other nested `$^`, including `$^` in collection arguments, is rejected; other nested ordered maps, general source-level disjointness and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms and nested faced or unfaced cells with valid Jibb face names from caller-supplied reader results for declared `/-` imports; `+golden-types-with-marks` accepts those same shapes from declared mark imports in a separate list. Other forms remain unsupported. Its disjointness proof is conservative and can reject a valid union it cannot prove disjoint. Collection recognition requires the originating `/sur` core. The reader validates direct zuse subjects and Ford subjects consisting of faced imported cores and a validated tail, checking imported cores transitively; it rejects shadowed names, inconsistent core subjects and other subject shapes. For a recursive reference, the reader matches the exact Hoon hold against named arms in validated cores, including transitive Ford imports; it rejects missing, unlabelled or ambiguous origins. Its fixtures include three real Tlon files; `tools/importer-test` compares the internal projection under eval, and the ship test compares the same golden output. `tools/type-import-test` and `tools/type-mark-test` compare bridge reports under eval and on the ship. `tools/clay-fixtures` also passes Clay-built `/sur` molds and mark samples through the Clay-built importer and partial checker.
61+The separate `jibb-dev/lib/jibb-import.hoon` is an unfinished reader for selected Hoon type graphs. It handles named recursion, nested map, set, queue, list, unit, jar and jug arguments, direct ordered maps, and direct `$^` unions whose source branches can be proved disjoint. It also reads ordered map fields in records when the map arguments are syntactically fixed atom molds and other fields are fixed atom molds or standard collections of static atom molds. Collection names must not be shadowed. The reader can also import a mark door sample, removing its outer sample face and validating its build subject. The reader checks explicit Hoon `$%`, `$?` and `$^` unions against the Grammar’s disjointness rule (doc question 22). It re-evaluates statically recognizable source branches before Hoon can collapse them, checks materialized fork cases, and rejects shapes it cannot prove disjoint. Static records may also have verified standard-collection and `path` siblings. Explicit unions in collection arguments remain unsupported; other nested ordered maps, general source-level disjointness and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms and nested faced or unfaced cells with valid Jibb face names from caller-supplied reader results for declared `/-` imports; `+golden-types-with-marks` accepts those same shapes from declared mark imports in a separate list. Other forms remain unsupported. Its disjointness proof is conservative and can reject a valid union it cannot prove disjoint. Collection recognition requires the originating `/sur` core. The reader validates direct zuse subjects and Ford subjects consisting of faced imported cores and a validated tail, checking imported cores transitively; it rejects shadowed names, inconsistent core subjects and other subject shapes. For a recursive reference, the reader matches the exact Hoon hold against named arms in validated cores, including transitive Ford imports; it rejects missing, unlabelled or ambiguous origins. Its fixtures include three real Tlon files; `tools/importer-test` compares the internal projection under eval, and the ship test compares the same golden output. `tools/type-import-test` and `tools/type-mark-test` compare bridge reports under eval and on the ship. `tools/clay-fixtures` also passes Clay-built `/sur` molds and mark samples through the Clay-built importer and partial checker.
62
62
63Callers that have a `/sur` core and a name can use `+read-named`: it checks for a locally declared arm before asking Hoon to evaluate the mold, and reports evaluation failures with the final Hoon trace line. `+read-mold-in` remains available when the caller already has the selected type. The checker currently treats a failed import as unsupported rather than rendering the importer's error.
63Callers that have a `/sur` core and a name can use `+read-named`: it checks for a locally declared arm before asking Hoon to evaluate the mold, and reports evaluation failures with the final Hoon trace line. `+read-mold-in` remains available when the caller already has the selected type. The checker currently treats a failed import as unsupported rather than rendering the importer's error.
64
64
docs/development.md+1−1
@@ -62,7 +62,7 @@ git clone https://github.com/urbit/tools /root/src/tools
62| `tools/importer-test` | Compares the partial Hoon importer's diagnostic trees and errors with `tests/importer/tree.txt` under `urbit eval` |
62| `tools/importer-test` | Compares the partial Hoon importer's diagnostic trees and errors with `tests/importer/tree.txt` under `urbit eval` |
63| `tools/type-import-test` | Composes the Hoon importer with the partial checker and compares `tests/type-import/expected.txt` under eval |
63| `tools/type-import-test` | Composes the Hoon importer with the partial checker and compares `tests/type-import/expected.txt` under eval |
64| `tools/type-mark-test` | Checks the partial checker’s mark import boundary against `tests/type-mark/expected.txt` under eval |
64| `tools/type-mark-test` | Checks the partial checker’s mark import boundary against `tests/type-mark/expected.txt` under eval |
65−| `tools/type-module-scope-test` | Checks the partial module checker’s prelude boundary against `tests/type-module-scope/expected.txt` under eval |
65+| `tools/type-module-scope-test` | Checks the partial module checker’s prelude boundary and duplicate-source rejection against `tests/type-module-scope/expected.txt` under eval |
66| `tools/clay-fixtures` | Syncs `my-app`, builds its example `/sur` files and marks through Clay, checks selected mold and mark projections and the partial checker, and records Ford and mark subject shapes on the fake ship |
66| `tools/clay-fixtures` | Syncs `my-app`, builds its example `/sur` files and marks through Clay, checks selected mold and mark projections and the partial checker, and records Ford and mark subject shapes on the fake ship |
67| `tools/hoon` | Evaluates Hoon with the library in scope, as `tools/hoon '(golden /a/b/jibb (crip "++ main view"))'`; `--cord name=file` binds a file's text, `-f` reads the expression from a file |
67| `tools/hoon` | Evaluates Hoon with the library in scope, as `tools/hoon '(golden /a/b/jibb (crip "++ main view"))'`; `--cord name=file` binds a file's text, `-f` reads the expression from a file |
68| `tools/doc-blocks` | Checks the doc's `jibb` blocks against the `doc-*` golden cases: `tools/doc-blocks docs/spec` |
68| `tools/doc-blocks` | Checks the doc's `jibb` blocks against the `doc-*` golden cases: `tools/doc-blocks docs/spec` |
docs/open-questions.md+1−1
@@ -41,7 +41,7 @@ Found while writing [prompts/milestone-2.md](prompts/milestone-2.md) and checkin
4119. **Settled: Hoon aura families and `step.hoon`.** On 2026-10-30, @iko chose `step.hoon` for Hoon 1c `step`, avoiding a clash with the Grammar example's `step`, and chose one-way widening across Hoon aura families: for example, `@ud` and `@ux` fit `@u`, and `@tD` fits `@t`. The reverse needs a check. The `step.hoon` group representation is not implemented yet.
4119. **Settled: Hoon aura families and `step.hoon`.** On 2026-10-30, @iko chose `step.hoon` for Hoon 1c `step`, avoiding a clash with the Grammar example's `step`, and chose one-way widening across Hoon aura families: for example, `@ud` and `@ux` fit `@u`, and `@tD` fits `@t`. The reverse needs a check. The `step.hoon` group representation is not implemented yet.
4220. **The type of Hoon `clap`.** Hoon allows its two input units and combining gate's result to have different types. If only one unit is present it returns that unit; when both are present it returns the combining gate's result. Jibb branches normally need a common type, while every union written in Jibb has a name. Should the Jibb gate require a shared type, infer an unnamed union of the possible values, or wait for a different typing design? Asked @iko on 2026-10-30. `clap` is not implemented while this is open.
4220. **The type of Hoon `clap`.** Hoon allows its two input units and combining gate's result to have different types. If only one unit is present it returns that unit; when both are present it returns the combining gate's result. Jibb branches normally need a common type, while every union written in Jibb has a name. Should the Jibb gate require a shared type, infer an unnamed union of the possible values, or wait for a different typing design? Asked @iko on 2026-10-30. `clap` is not implemented while this is open.
4321. **Duplicate faces in imported Hoon records.** Hoon permits `[a=@ud a=@t]`, and its lookup picks the first `a`. Should Jibb reject the imported type where it is used, use the first field, or permit the type but reject access to the ambiguous field? Asked @iko on 2026-10-30. The inference fragment currently permits the type but declines ambiguous field access (doc question).
4321. **Duplicate faces in imported Hoon records.** Hoon permits `[a=@ud a=@t]`, and its lookup picks the first `a`. Should Jibb reject the imported type where it is used, use the first field, or permit the type but reject access to the ambiguous field? Asked @iko on 2026-10-30. The inference fragment currently permits the type but declines ambiguous field access (doc question).
44−22. **Overlapping imported `$%` and `$?` cases.** The Grammar says a union whose cases don't all differ as nouns is rejected, while the import table explicitly mentions that condition only for `$^`; its `$%` and `$?` row says they become a union. Does the general disjointness rule reject imported `$%` and `$?` cases such as `[%x @ud]` and `[%x @t]` where the type is used? Asked @iko on 2026-10-30. The general rule is the provisional reading (doc question); the importer currently accepts some overlaps, and a fix is in progress.
44+22. **Overlapping imported `$%` and `$?` cases.** The Grammar says a union whose cases don't all differ as nouns is rejected, while the import table explicitly mentions that condition only for `$^`; its `$%` and `$?` row says they become a union. Does the general disjointness rule reject imported `$%` and `$?` cases such as `[%x @ud]` and `[%x @t]` where the type is used? Asked @iko on 2026-10-30. The general rule is the provisional reading (doc question); the importer rejects recognizable overlaps and fails closed when it cannot verify them.
45
45
46## Grammar questions never put to the doc's author
46## Grammar questions never put to the doc's author
47
47
docs/status.md+7−6
@@ -19,7 +19,7 @@ On 2026-10-30, @iko decided that Jibb drops `$?`, so a `+$` takes a union's case
19
19
20## Milestone 2: in progress
20## Milestone 2: in progress
21
21
22−The repository spec records the subsequent type-system and prelude decisions; those changes also need synchronization to the Claude document. An initial inference fragment and a standalone Hoon type reader are being tested. The fragment explicitly reports that it does not check a module; partial bridges pass selected Hoon atoms and nested faced or unfaced cells from `/sur` molds and marks into inference. The reader handles mark samples, recursive molds whose origins can be verified through Ford imports, nested collections, direct ordered maps, certain ordered-map fields, and direct `$^` unions whose cases can be proved disjoint. Ambiguous recursive origins fail closed; one nested `$^` in a static record of aura and constant-tag molds is checked, while other nested `$^`, nested ordered maps, general union disjointness and complete import integration remain unfinished. The partial checker resolves a subset of ordinary library imports in dependency order using supplied Jibb sources and the current prelude names, caches completed interfaces per run, and detects missing sources and cycles. It does not yet check API or kind semantics, and the prelude inventory is incomplete. The inference fragment supports unrestricted `@`, selected one-way widenings including aura-family ancestors, generalized atom constraints arising from explicit capitals or bare sample binders, acyclic local value definitions with captures, simple and nonrecursive generic mold aliases, and selected faced record casts and field reads. Variable-dependent face merges remain unsupported. Unfixed decimal literals default to `@ud` in gate-free inferred types; recursive local groups, recursive and union generic molds, other constraint cases and defaulting inside gate types still need work. Collection recognition checks the originating core and fails closed on shadows or unsupported Ford subject shapes; its golden fixtures include three real Tlon files. The prelude currently has only a few functions, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
22+The repository spec records the subsequent type-system and prelude decisions; those changes also need synchronization to the Claude document. An initial inference fragment and a standalone Hoon type reader are being tested. The fragment explicitly reports that it does not check a module; partial bridges pass selected Hoon atoms and nested faced or unfaced cells from `/sur` molds and marks into inference. The reader handles mark samples, recursive molds whose origins can be verified through Ford imports, nested collections, direct ordered maps, certain ordered-map fields, and direct `$^` unions whose cases can be proved disjoint. Ambiguous recursive origins fail closed; recognizable explicit unions are checked from source before Hoon can collapse their cases (doc question 22), while other nested unions, nested ordered maps, general union disjointness and complete import integration remain unfinished. The partial checker resolves a subset of ordinary library imports in dependency order using supplied Jibb sources and the current prelude names, caches completed interfaces per run, and detects missing sources and cycles. It does not yet check API or kind semantics, and the prelude inventory is incomplete. The inference fragment supports unrestricted `@`, selected one-way widenings including aura-family ancestors, generalized atom constraints arising from explicit capitals or bare sample binders, acyclic local value definitions with captures, simple and nonrecursive generic mold aliases, selected faced record casts and field reads, and contextual tags and constructors for closed disjoint unions. Variable-dependent face merges remain unsupported. Unfixed decimal literals default to `@ud` in gate-free inferred types; recursive local groups, recursive and union generic molds, branch tag context, union type printing, other constraint cases and defaulting inside gate types still need work. Collection recognition checks the originating core and fails closed on shadows or unsupported Ford subject shapes; its golden fixtures include three real Tlon files. The prelude currently has only a few functions, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
23
23
24## Milestone 1: parser and mark
24## Milestone 1: parser and mark
25
25
@@ -37,8 +37,8 @@ What the plan asks for, and where it is:
37
37
38Besides the plan's list:
38Besides the plan's list:
39
39
40−- 459 golden cases: 243 that parse and 216 that fail, each failure at a stated line and column. One failing case has an unclear expectation (corpus question 3). The newer type-output cases exercise only the partial inference fragment. Each case's `about.txt` quotes the doc's words it tests.
40+- 468 golden cases: 252 that parse and 216 that fail, each failure at a stated line and column. One failing case has an unclear expectation (corpus question 3). The newer type-output cases exercise only the partial inference fragment. Each case's `about.txt` quotes the doc's words it tests.
41−- The 459-case corpus passed under `urbit eval` in 33.6 s. The fake ship passed all 464 tests, including the importer, importer/checker and mark/checker bridges, module scope and unification checks, with 24.0 s for sync and 29.8 s for tests. The importer golden compares 110 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, checks a recursive Ford import's origin, and passes Clay-built types through the Clay-built importer and partial checker.
41+- The 468-case corpus passed under `urbit eval` in 31.7 s. The fake ship passed all 473 tests, including the importer, importer/checker and mark/checker bridges, module scope and unification checks, with 27.0 s for sync and 18.8 s for tests. The importer golden compares 130 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, checks a recursive Ford import's origin, and passes Clay-built types through the Clay-built importer and partial checker.
42- `tools/testdata/selftest` (22 checks) and `tools/testdata/ship-selftest` test the tools themselves.
42- `tools/testdata/selftest` (22 checks) and `tools/testdata/ship-selftest` test the tools themselves.
43- Two independent audits before 7c739b7, one of which compared the library with a reference parser written in Python from the doc over about 19,000 generated programs. Before ab797a9, a second Python parser, written from the decisions, agreed with the library on 8,000 generated programs and 900 hand-written probes.
43- Two independent audits before 7c739b7, one of which compared the library with a reference parser written in Python from the doc over about 19,000 generated programs. Before ab797a9, a second Python parser, written from the decisions, agreed with the library on 8,000 generated programs and 900 hand-written probes.
44- Speed: starting `urbit eval` and building the library takes about 8 s. After that, a 2,000-line module of 400 definitions parses in about a second. Loops over definitions, arms, lines and items grow no stack; nesting costs a few stack frames a level, and 100,000 nested brackets still parse (library section 3).
44- Speed: starting `urbit eval` and building the library takes about 8 s. After that, a 2,000-line module of 400 definitions parses in about a second. Loops over definitions, arms, lines and items grow no stack; nesting costs a few stack frames a level, and 100,000 nested brackets still parse (library section 3).
@@ -67,14 +67,15 @@ Besides the plan's list:
67| 529736a | 2026-10-30 | Infer supported library import graphs and guard nested Hoon `$^` in collections |
67| 529736a | 2026-10-30 | Infer supported library import graphs and guard nested Hoon `$^` in collections |
68| 8bf1b12 | 2026-10-30 | Infer selected record faces and check nested `$^` in static Hoon records |
68| 8bf1b12 | 2026-10-30 | Infer selected record faces and check nested `$^` in static Hoon records |
69| d8ac47d | 2026-10-30 | Cache library interfaces, preserve imported Hoon record faces, and check nested tagged unions |
69| d8ac47d | 2026-10-30 | Cache library interfaces, preserve imported Hoon record faces, and check nested tagged unions |
70−| This change | 2026-10-30 | Infer nonrecursive generic mold aliases with lexical parameters |
70+| edd9277 | 2026-10-30 | Infer nonrecursive generic mold aliases with lexical parameters |
71+| This change | 2026-10-30 | Resolve selected contextual tags and check explicit imported unions |
71
72
72## Checking it
73## Checking it
73
74
74On a machine set up as [development.md](development.md) says:
75On a machine set up as [development.md](development.md) says:
75
76
76```
77```
77−tools/golden # 459 cases under urbit eval
78+tools/golden # 468 cases under urbit eval
78tools/importer-test # the Hoon importer fixture projection
79tools/importer-test # the Hoon importer fixture projection
79tools/type-import-test # the importer/checker bridge fixture
80tools/type-import-test # the importer/checker bridge fixture
80tools/type-mark-test # the mark/checker bridge fixture
81tools/type-mark-test # the mark/checker bridge fixture
@@ -84,7 +85,7 @@ tools/testdata/selftest # the tools themselves
84tools/doc-blocks docs/spec # the doc's examples are golden cases
85tools/doc-blocks docs/spec # the doc's examples are golden cases
85tools/ship start
86tools/ship start
86tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
87tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
87−tools/ship test # the same 459 cases as -test arms on the ship
88+tools/ship test # the same 468 cases as -test arms on the ship
88tools/testdata/ship-selftest
89tools/testdata/ship-selftest
89tools/ship check-commit # |commit stores .jibb files
90tools/ship check-commit # |commit stores .jibb files
90tools/clay-fixtures # example /sur files and marks build through Clay
91tools/clay-fixtures # example /sur files and marks build through Clay
jibb-dev/lib/jibb-import.hoon+126−9
@@ -383,6 +383,30 @@
383 ?: ?=([%bckt ^ ^] h) &
383 ?: ?=([%bckt ^ ^] h) &
384 |($(h -.h) $(h +.h))
384 |($(h -.h) $(h +.h))
385::
385::
386+:: (doc question 22) The Grammar's disjointness rule is applied to
387+:: imported $% and $? too. The import table singles out $^, so @iko
388+:: has been asked whether that general rule also covers those unions.
389+++ has-spec-general-union
390+ |= h=*
391+ ^- ?
392+ ?@ h |
393+ ?: ?=([%bcwt [^ [^ *]]] h) &
394+ ?: ?=([%bccn [^ [^ *]]] h) &
395+ |($(h -.h) $(h +.h))
396+::
397+++ has-fits-union
398+ |= h=*
399+ ^- ?
400+ ?@ h |
401+ ?: ?=([%wtcl [%fits *] * *] h) &
402+ |($(h -.h) $(h +.h))
403+::
404+++ fits-union-at
405+ |= [h=hoon axis=@ud]
406+ ^- ?
407+ ?. ?=([%fits *] h) |
408+ |(=(q.h ~[[%.y axis]]) =(q.h ~[[%.y (mul 2 axis)]]))
409+::
386++ has-cell-union
410++ has-cell-union
387 |= h=hoon
411 |= h=hoon
388 ^- ?
412 ^- ?
@@ -403,6 +427,7 @@
403 |($(h -.h, axis (mul 2 axis)) $(h +.h, axis (add 1 (mul 2 axis))))
427 |($(h -.h, axis (mul 2 axis)) $(h +.h, axis (add 1 (mul 2 axis))))
404 ?+ h (has-cell-union-any h)
428 ?+ h (has-cell-union-any h)
405 [%note *] $(h q.h)
429 [%note *] $(h q.h)
430+ [%dbug *] $(h q.h)
406 [%ktts *] $(h q.h)
431 [%ktts *] $(h q.h)
407 [%wtcl *]
432 [%wtcl *]
408 ?: =(p.h [%dtwt [%$ (mul 2 axis)]]) &
433 ?: =(p.h [%dtwt [%$ (mul 2 axis)]]) &
@@ -438,9 +463,17 @@
438 &($(h -.h, axis (mul 2 axis)) $(h +.h, axis (add 1 (mul 2 axis))))
463 &($(h -.h, axis (mul 2 axis)) $(h +.h, axis (add 1 (mul 2 axis))))
439 ?+ h |
464 ?+ h |
440 [%note *] $(h q.h)
465 [%note *] $(h q.h)
466+ [%dbug *] $(h q.h)
441 [%ktts *] $(h q.h)
467 [%ktts *] $(h q.h)
442 [%ktls *] ?=([%sand *] p.h)
468 [%ktls *] ?=([%sand *] p.h)
469+ [%cncl *]
470+ ?: =(h [%cncl [%tsgr [%wing ~[[%.y 7]]] [%wing ~[%path]]] ~[[%$ axis]]]) &
471+ (static-collection h)
472+ [%wtcl *]
473+ ?. (fits-union-at p.h axis) |
474+ &($(h q.h) $(h r.h))
443 [%wtgr *]
475 [%wtgr *]
476+ ?: =(h [%wtgr [%dtts [%bust %noun] [%$ axis]] [%rock %n 0]]) &
444 ?. ?=([%dtts [%$ *] [%rock %$ *]] p.h) |
477 ?. ?=([%dtts [%$ *] [%rock %$ *]] p.h) |
445 ?. ?=([%rock %tas *] q.h) |
478 ?. ?=([%rock %tas *] q.h) |
446 ?^ q.q.h |
479 ?^ q.q.h |
@@ -466,12 +499,16 @@
466 =/ out $(h q.h)
499 =/ out $(h q.h)
467 ?~ out ~
500 ?~ out ~
468 [~ [h(q one.u.out) h(q two.u.out)]]
501 [~ [h(q one.u.out) h(q two.u.out)]]
502+ [%dbug *]
503+ =/ out $(h q.h)
504+ ?~ out ~
505+ [~ [h(q one.u.out) h(q two.u.out)]]
469 [%ktts *]
506 [%ktts *]
470 =/ out $(h q.h)
507 =/ out $(h q.h)
471 ?~ out ~
508 ?~ out ~
472 [~ [h(q one.u.out) h(q two.u.out)]]
509 [~ [h(q one.u.out) h(q two.u.out)]]
473 [%wtcl *]
510 [%wtcl *]
474− ?. =(p.h [%dtwt [%$ (mul 2 axis)]]) ~
511+ ?. |(=(p.h [%dtwt [%$ (mul 2 axis)]]) (fits-union-at p.h axis)) ~
475 ?. &((fixed-cell-mold q.h axis) (fixed-cell-mold r.h axis)) ~
512 ?. &((fixed-cell-mold q.h axis) (fixed-cell-mold r.h axis)) ~
476 [~ [q.h r.h]]
513 [~ [q.h r.h]]
477 ==
514 ==
@@ -493,6 +530,7 @@
493 ?: =(a b) [%& a]
530 ?: =(a b) [%& a]
494 [%| 'a nested Hoon $^ union needs a source-level disjointness check']
531 [%| 'a nested Hoon $^ union needs a source-level disjointness check']
495 [%note *] $(h q.h)
532 [%note *] $(h q.h)
533+ [%dbug *] $(h q.h)
496 [%ktts *]
534 [%ktts *]
497 ?. &(?=([%face *] a) ?=([%face *] b))
535 ?. &(?=([%face *] a) ?=([%face *] b))
498 [%| 'a nested Hoon $^ union needs a source-level disjointness check']
536 [%| 'a nested Hoon $^ union needs a source-level disjointness check']
@@ -502,11 +540,26 @@
502 ?. ?=([%& *] child) child
540 ?. ?=([%& *] child) child
503 [%& [%face name.a p.child]]
541 [%& [%face name.a p.child]]
504 [%wtcl *]
542 [%wtcl *]
505− ?. =(p.h [%dtwt [%$ (mul 2 axis)]])
543+ ?. |(=(p.h [%dtwt [%$ (mul 2 axis)]]) (fits-union-at p.h axis))
506− [%| 'a nested Hoon $^ union needs a source-level disjointness check']
544+ [%| 'a Hoon union needs a source-level disjointness check']
545+ ?. (disjoint a b)
546+ ?: ?=([%fits *] p.h) [%| 'a Hoon union has overlapping cases']
507− ?. (disjoint a b) [%| 'a Hoon $^ union has overlapping cases']
547+ [%| 'a Hoon $^ union has overlapping cases']
508− [%& [%fork (sort ~[a b] |=(pair=[imported imported] (dor -.pair +.pair)))]]
548+ [%& [%fork (sort (weld (union-cases a) (union-cases b)) |=(pair=[imported imported] (dor -.pair +.pair)))]]
509 ==
549 ==
550+++ union-cases
551+ |= a=imported
552+ ^- (list imported)
553+ ?. ?=([%fork *] a) ~[a]
554+ (zing (turn cases.a |=(item=imported (union-cases item))))
555+::
556+++ all-disjoint
557+ |= cases=(list imported)
558+ ^- ?
559+ ?~ cases &
560+ ?. (levy t.cases |=(item=imported (disjoint i.cases item))) |
561+ $(cases t.cases)
562+::
510++ disjoint
563++ disjoint
511 |= [a=imported b=imported]
564 |= [a=imported b=imported]
512 ^- ?
565 ^- ?
@@ -729,11 +782,16 @@
729 [%fork *]
782 [%fork *]
730 =/ cases=(list imported)
783 =/ cases=(list imported)
731 (turn ~(tap in:..zuse p.typ) |=(t=type ^$(typ t)))
784 (turn ~(tap in:..zuse p.typ) |=(t=type ^$(typ t)))
785+ =/ err (first-bads cases)
786+ ?^ err [%bad u.err]
787+ ?. (all-disjoint cases) [%bad 'a Hoon union has overlapping cases']
732 [%fork (sort cases |=(pair=[imported imported] (dor -.pair +.pair)))]
788 [%fork (sort cases |=(pair=[imported imported] (dor -.pair +.pair)))]
733 [%hint *] $(typ q.typ)
789 [%hint *] $(typ q.typ)
734 [%hold *]
790 [%hold *]
735 ?: &(?=([%tsls [%note * *] *] q.typ) (has-spec-cell-union q.typ))
791 ?: &(?=([%tsls [%note * *] *] q.typ) (has-spec-cell-union q.typ))
736 [%bad 'a Hoon $^ union needs a source-level disjointness check']
792 [%bad 'a Hoon $^ union needs a source-level disjointness check']
793+ ?: &(?=([%tsls [%note * *] *] q.typ) (has-spec-general-union q.typ))
794+ [%bad 'a Hoon union needs a source-level disjointness check']
737 =/ named=(unit term) (match-signature q.typ sig)
795 =/ named=(unit term) (match-signature q.typ sig)
738 ?^ named
796 ?^ named
739 =/ name u.named
797 =/ name u.named
@@ -799,17 +857,23 @@
799 ?: (disjoint first second)
857 ?: (disjoint first second)
800 [%fork (sort ~[first second] |=(pair=[imported imported] (dor -.pair +.pair)))]
858 [%fork (sort ~[first second] |=(pair=[imported imported] (dor -.pair +.pair)))]
801 [%bad 'a Hoon $^ union has overlapping cases']
859 [%bad 'a Hoon $^ union has overlapping cases']
802− ?: (has-cell-union q.typ)
860+ ?: |((has-cell-union q.typ) (has-fits-union q.typ))
861+ =/ cannot=@t
862+ ?: (has-fits-union q.typ) 'a Hoon union needs a source-level disjointness check'
863+ 'a Hoon $^ union needs a source-level disjointness check'
864+ =/ checked-names=(list term) ~[%map %set %qeu %list %unit %jar %jug %path]
865+ ?: (lien checked-names |=(n=term &((source-uses q.typ n) !(alias-safe context n))))
866+ [%bad 'Hoon collection provenance is unavailable or shadowed']
803 ?. ?=([%tsls [%note * *] *] q.typ)
867 ?. ?=([%tsls [%note * *] *] q.typ)
804− [%bad 'a Hoon $^ union needs a source-level disjointness check']
868+ [%bad cannot]
805 =/ original=hoon q.typ
869 =/ original=hoon q.typ
806 ?> ?=([%tsls [%note * *] *] original)
870 ?> ?=([%tsls [%note * *] *] original)
807 =/ body=hoon q.p.original
871 =/ body=hoon q.p.original
808 =/ split (split-cell-record body 6)
872 =/ split (split-cell-record body 6)
809− ?~ split [%bad 'a Hoon $^ union needs a source-level disjointness check']
873+ ?~ split [%bad cannot]
810 =/ try=(each [type type] tang)
874 =/ try=(each [type type] tang)
811 (mule |.([(~(play ut p.typ) original(q.p one.u.split)) (~(play ut p.typ) original(q.p two.u.split))]))
875 (mule |.([(~(play ut p.typ) original(q.p one.u.split)) (~(play ut p.typ) original(q.p two.u.split))]))
812− ?. ?=([%& *] try) [%bad 'a Hoon $^ union needs a source-level disjointness check']
876+ ?. ?=([%& *] try) [%bad cannot]
813 =/ first $(typ -.p.try, seen [[typ nm] seen])
877 =/ first $(typ -.p.try, seen [[typ nm] seen])
814 =/ second $(typ +.p.try, seen [[typ nm] seen])
878 =/ second $(typ +.p.try, seen [[typ nm] seen])
815 =/ err (first-bads ~[first second])
879 =/ err (first-bads ~[first second])
@@ -1021,6 +1085,39 @@
1021 [%| *] "error: {(trip p.result)}"
1085 [%| *] "error: {(trip p.result)}"
1022 ==
1086 ==
1023::
1087::
1088+:: Clay includes debug spans around source nodes. Reproduce that
1089+:: shape without Clay so the same regression runs under eval and -test.
1090+++ decorate-union-source
1091+ |= h=hoon
1092+ ^- hoon
1093+ =/ at=spot [/tests/importer/synthetic/hoon [[1 1] [1 2]]]
1094+ ?^ -.h [%dbug at [$(h -.h) $(h +.h)]]
1095+ ?+ h [%dbug at h]
1096+ [%note *] [%dbug at h(q $(h q.h))]
1097+ [%ktts *] [%dbug at h(q $(h q.h))]
1098+ [%wtcl *] [%dbug at h(q $(h q.h), r $(h r.h))]
1099+ ==
1100+::
1101+++ debug-union-fixture
1102+ |= [cor=type name=term]
1103+ ^- (each imported @t)
1104+ =/ typ=type (~(play ut cor) (ream (cat 3 '*' name)))
1105+ ?. ?=([%hold *] typ) [%| 'synthetic union is not a hold']
1106+ =/ original=hoon q.typ
1107+ ?. ?=([%tsls [%note * *] *] original) [%| 'synthetic union source is unavailable']
1108+ =/ source=hoon original(q.p (decorate-union-source q.p.original))
1109+ (read-mold %small name typ(q source))
1110+::
1111+++ overlap-fork-fixture
1112+ ^- type
1113+ =/ nodes=(list type) ~[[%atom %ud ~] [%atom %t ~]]
1114+ [%fork (silt nodes)]
1115+::
1116+++ invalid-fork-fixture
1117+ ^- type
1118+ =/ nodes=(list type) ~[[%atom %ud ~] [%atom %sd ~]]
1119+ [%fork (silt nodes)]
1120+::
1024++ fixture-output
1121++ fixture-output
1025 |= [small=@t epic=@t presence=@t docs=@t shadow=@t shadow-static=@t ford=@t mark=@t mark-rec=@t mark-gate=@t mark-basic=@t origin-trans=@t origin-first=@t origin-other=@t]
1122 |= [small=@t epic=@t presence=@t docs=@t shadow=@t shadow-static=@t ford=@t mark=@t mark-rec=@t mark-gate=@t mark-basic=@t origin-trans=@t origin-first=@t origin-other=@t]
1026 ^- wain
1123 ^- wain
@@ -1119,6 +1216,26 @@
1119 (crip "gate: {(show-result (sample %gate-test))}")
1216 (crip "gate: {(show-result (sample %gate-test))}")
1120 (crip "vase: {(show-result vase)}")
1217 (crip "vase: {(show-result vase)}")
1121 (crip "failed-branch: {(show-result (read-mold %external %bad bad-branch-fixture))}")
1218 (crip "failed-branch: {(show-result (read-mold %external %bad bad-branch-fixture))}")
1219+ (crip "debug-union: {(show-result (debug-union-fixture sc %action))}")
1220+ (crip "debug-union-overlap: {(show-result (debug-union-fixture sc %explicit-wut-overlap))}")
1221+ (crip "debug-nested-cell: {(show-result (debug-union-fixture sc %nested-valid-cell))}")
1222+ (crip "debug-nested-cell-overlap: {(show-result (debug-union-fixture sc %nested-invalid-cell))}")
1223+ (crip "explicit-graph: {(show-result (read-mold %raw %raw overlap-fork-fixture))}")
1224+ (crip "explicit-graph-unsupported: {(show-result (read-mold %raw %raw invalid-fork-fixture))}")
1225+ (crip "explicit-wut-safe: {(show-result (sample %explicit-wut-safe))}")
1226+ (crip "explicit-percent-overlap: {(show-result (sample %explicit-percent-overlap))}")
1227+ (crip "explicit-wut-overlap: {(show-result (sample %explicit-wut-overlap))}")
1228+ (crip "explicit-collapsed: {(show-result (sample %explicit-collapsed))}")
1229+ (crip "explicit-subsumed: {(show-result (sample %explicit-subsumed))}")
1230+ (crip "explicit-three: {(show-result (sample %explicit-three))}")
1231+ (crip "explicit-unknown: {(show-result (sample %explicit-unknown))}")
1232+ (crip "explicit-nested: {(show-result (sample %explicit-nested))}")
1233+ (crip "explicit-list: {(show-result (sample %explicit-list))}")
1234+ (crip "explicit-set: {(show-result (sample %explicit-set))}")
1235+ (crip "explicit-faces: {(show-result (sample %explicit-faces))}")
1236+ (crip "explicit-alias: {(show-result (sample %explicit-alias))}")
1237+ (crip "explicit-ford: {(show-result (read-named %outer %bad-union trans))}")
1238+ (crip "explicit-shadow-path: {(show-result (read-named %shadow %path-shadow xc))}")
1122 (crip "list-bckt-field: {(show-result (sample %list-bckt-field))}")
1239 (crip "list-bckt-field: {(show-result (sample %list-bckt-field))}")
1123 (crip "list-noun-overlap: {(show-result (sample %list-noun-overlap))}")
1240 (crip "list-noun-overlap: {(show-result (sample %list-noun-overlap))}")
1124 (crip "list-null-overlap: {(show-result (sample %list-null-overlap))}")
1241 (crip "list-null-overlap: {(show-result (sample %list-null-overlap))}")
jibb-dev/lib/jibb.hoon+185−7
@@ -4606,6 +4606,9 @@
4606 [%atom aura=@ta]
4606 [%atom aura=@ta]
4607 [%any-atom ~]
4607 [%any-atom ~]
4608 [%flag ~]
4608 [%flag ~]
4609+ [%tag id=@ud literal=lit constructor=?]
4610+ [%const literal=lit]
4611+ [%union cases=(list itype)]
4609 [%face name=term body=itype]
4612 [%face name=term body=itype]
4610 [%fn sample=itype product=itype]
4613 [%fn sample=itype product=itype]
4611 [%cell hed=itype tal=itype]
4614 [%cell hed=itype tal=itype]
@@ -4636,6 +4639,10 @@
4636 =/ found=(unit itype) (itype-lookup id.t sub)
4639 =/ found=(unit itype) (itype-lookup id.t sub)
4637 ?~ found t
4640 ?~ found t
4638 $(t u.found)
4641 $(t u.found)
4642+ %tag
4643+ =/ found=(unit itype) (itype-lookup id.t sub)
4644+ ?~ found t
4645+ $(t u.found)
4639 ==
4646 ==
4640::
4647::
4641++ itype-occurs
4648++ itype-occurs
@@ -4649,6 +4656,9 @@
4649 %atom |
4656 %atom |
4650 %any-atom |
4657 %any-atom |
4651 %flag |
4658 %flag |
4659+ %tag =(n id.t)
4660+ %const |
4661+ %union (lien cases.t |=(c=itype (itype-occurs n c sub)))
4652 %face $(t body.t)
4662 %face $(t body.t)
4653 %fn |($(t sample.t) $(t product.t))
4663 %fn |($(t sample.t) $(t product.t))
4654 %cell |($(t hed.t) $(t tal.t))
4664 %cell |($(t hed.t) $(t tal.t))
@@ -4688,6 +4698,8 @@
4688 ?: ?=(%avar -.b)
4698 ?: ?=(%avar -.b)
4689 ?. |(?=(%atom -.a) ?=(%any-atom -.a) ?=(%flag -.a)) ~
4699 ?. |(?=(%atom -.a) ?=(%any-atom -.a) ?=(%flag -.a)) ~
4690 `[[id.b a] sub]
4700 `[[id.b a] sub]
4701+ ?: &(?=(%const -.a) ?=(%const -.b))
4702+ ?:(=(val.literal.a val.literal.b) `sub ~)
4691 ?: &(?=(%atom -.a) ?=(%atom -.b)) ~
4703 ?: &(?=(%atom -.a) ?=(%atom -.b)) ~
4692 ?: &(?=(%face -.a) ?=(%face -.b))
4704 ?: &(?=(%face -.a) ?=(%face -.b))
4693 ?. =(name.a name.b) ~
4705 ?. =(name.a name.b) ~
@@ -4719,6 +4731,9 @@
4719 %atom |
4731 %atom |
4720 %any-atom &
4732 %any-atom &
4721 %flag |
4733 %flag |
4734+ %tag |
4735+ %const |
4736+ %union (lien cases.t |=(c=itype (itype-has-any-atom c sub)))
4722 %face $(t body.t)
4737 %face $(t body.t)
4723 %fn |($(t sample.t) $(t product.t))
4738 %fn |($(t sample.t) $(t product.t))
4724 %cell |($(t hed.t) $(t tal.t))
4739 %cell |($(t hed.t) $(t tal.t))
@@ -4773,6 +4788,9 @@
4773 %atom &
4788 %atom &
4774 %any-atom &
4789 %any-atom &
4775 %flag &
4790 %flag &
4791+ %tag &
4792+ %const &
4793+ %union (lien cases.typ |=(c=itype (itype-has-fixed-atom c)))
4776 %face $(typ body.typ)
4794 %face $(typ body.typ)
4777 %fn |($(typ sample.typ) $(typ product.typ))
4795 %fn |($(typ sample.typ) $(typ product.typ))
4778 %cell |($(typ hed.typ) $(typ tal.typ))
4796 %cell |($(typ hed.typ) $(typ tal.typ))
@@ -4843,11 +4861,83 @@
4843 ?- -.t
4861 ?- -.t
4844 %var &
4862 %var &
4845 %cell &
4863 %cell &
4864+ %union &
4846 %face $(t body.t)
4865 %face $(t body.t)
4847 %fn |($(t sample.t) $(t product.t))
4866 %fn |($(t sample.t) $(t product.t))
4848 * |
4867 * |
4849 ==
4868 ==
4850::
4869::
4870+++ pending-tags
4871+ |= [tags=(list @ud) sub=isub]
4872+ ^- ?
4873+ ?~ tags |
4874+ ?~ (itype-lookup i.tags sub) &
4875+ $(tags t.tags)
4876+::
4877+:: Tags remain constrained until a mold selects a case or permitted atom
4878+:: type. Never generalize an unresolved tag through aliases or cells.
4879+::
4880+++ itype-has-tag
4881+ |= t=itype
4882+ ^- ?
4883+ ?- -.t
4884+ %tag &
4885+ %face $(t body.t)
4886+ %fn |($(t sample.t) $(t product.t))
4887+ %cell |($(t hed.t) $(t tal.t))
4888+ %union (lien cases.t |=(c=itype (itype-has-tag c)))
4889+ * |
4890+ ==
4891+::
4892+++ itype-has-union
4893+ |= t=itype
4894+ ^- ?
4895+ ?- -.t
4896+ %union &
4897+ %face $(t body.t)
4898+ %fn |($(t sample.t) $(t product.t))
4899+ %cell |($(t hed.t) $(t tal.t))
4900+ * |
4901+ ==
4902+::
4903+++ itype-fit-cases
4904+ |= [actual=itype cases=(list itype) sub=isub next=@ud]
4905+ ^- ifit
4906+ =/ good=(unit ifit) ~
4907+ =/ pending=? |
4908+ |-
4909+ ?~ cases
4910+ ?: pending [%unknown ~]
4911+ ?~ good [%bad ~]
4912+ u.good
4913+ =/ trial=ifit (itype-fit actual i.cases sub next)
4914+ ?- -.trial
4915+ %unknown $(cases t.cases, pending &)
4916+ %bad $(cases t.cases)
4917+ %ok
4918+ ?^ good [%unknown ~]
4919+ $(cases t.cases, good `trial)
4920+ ==
4921+::
4922+:: A constructor needs a case with its tag at the head and a payload
4923+:: compatible with the expected gate sample. Other case forms do not
4924+:: identify a constructor.
4925+::
4926+++ itype-fit-ctor-cases
4927+ |= [tag=lit sample=itype cases=(list itype) sub=isub next=@ud]
4928+ ^- ifit
4929+ =/ found=(unit ifit) ~
4930+ |-
4931+ ?~ cases ?~(found [%bad ~] u.found)
4932+ =/ c=itype (itype-walk i.cases sub)
4933+ ?. ?=(%cell -.c) $(cases t.cases)
4934+ =/ head=itype (itype-walk hed.c sub)
4935+ ?. ?=(%const -.head) $(cases t.cases)
4936+ ?. =(val.literal.head val.tag) $(cases t.cases)
4937+ ?^ found [%unknown ~]
4938+ =/ trial=ifit (itype-fit sample tal.c sub next)
4939+ $(cases t.cases, found `trial)
4940+::
4851++ itype-fit
4941++ itype-fit
4852 |= [actual=itype expected=itype sub=isub next=@ud]
4942 |= [actual=itype expected=itype sub=isub next=@ud]
4853 ^- ifit
4943 ^- ifit
@@ -4856,6 +4946,51 @@
4856 =. actual (itype-walk actual sub)
4946 =. actual (itype-walk actual sub)
4857 =. expected (itype-walk expected sub)
4947 =. expected (itype-walk expected sub)
4858 ?: =(actual expected) [%ok sub next]
4948 ?: =(actual expected) [%ok sub next]
4949+ ?: &(?=(%union -.actual) ?=(%union -.expected)) [%unknown ~]
4950+ ?: ?=(%union -.actual) [%unknown ~]
4951+ ?: &(?=(%union -.expected) |(?=(%avar -.actual) ?=(%nvar -.actual))) [%unknown ~]
4952+ ?: &(?=(%union -.expected) !?=(%var -.actual))
4953+ (itype-fit-cases actual cases.expected sub next)
4954+ ?: ?=(%tag -.actual)
4955+ ?: ?=(%var -.expected)
4956+ =/ u=(unit isub) (itype-unify actual expected sub)
4957+ ?~ u [%bad ~]
4958+ [%ok u.u next]
4959+ ?: |(?=(%avar -.expected) ?=(%nvar -.expected)) [%unknown ~]
4960+ ?: ?=(%face -.expected) $(expected body.expected)
4961+ ?: constructor.actual
4962+ ?. ?=(%fn -.expected) [%bad ~]
4963+ =/ product=itype (itype-walk product.expected sub)
4964+ =/ cases=(list itype) ?:(?=(%union -.product) cases.product ~[product])
4965+ =/ trial=ifit (itype-fit-ctor-cases literal.actual sample.expected cases sub next)
4966+ ?. ?=(%ok -.trial) trial
4967+ [%ok [[id.actual expected] sub.trial] next.trial]
4968+ ?: ?=(%const -.expected)
4969+ ?:(=(val.literal.actual val.literal.expected) [%ok [[id.actual expected] sub] next] [%bad ~])
4970+ ?: ?=(%atom -.expected)
4971+ ?: |(=(%tas aura.expected) =(%ta aura.expected))
4972+ [%ok [[id.actual expected] sub] next]
4973+ [%bad ~]
4974+ ?: ?=(%flag -.expected)
4975+ ?:(|(=(0 val.literal.actual) =(1 val.literal.actual)) [%ok [[id.actual expected] sub] next] [%bad ~])
4976+ ?: ?=(%any-atom -.expected) [%ok [[id.actual expected] sub] next]
4977+ [%bad ~]
4978+ ?: ?=(%const -.actual)
4979+ ?: ?=(%var -.expected)
4980+ =/ u=(unit isub) (itype-unify actual expected sub)
4981+ ?~ u [%bad ~]
4982+ [%ok u.u next]
4983+ ?: |(?=(%avar -.expected) ?=(%nvar -.expected)) [%unknown ~]
4984+ ?: ?=(%face -.expected) $(expected body.expected)
4985+ ?: ?=(%const -.expected)
4986+ ?:(=(val.literal.actual val.literal.expected) [%ok sub next] [%bad ~])
4987+ ?: ?=(%atom -.expected)
4988+ ?: |(=(%tas aura.expected) =(%ta aura.expected)) [%ok sub next]
4989+ [%bad ~]
4990+ ?: ?=(%flag -.expected)
4991+ ?:(|(=(0 val.literal.actual) =(1 val.literal.actual)) [%ok sub next] [%bad ~])
4992+ ?: ?=(%any-atom -.expected) [%ok sub next]
4993+ [%bad ~]
4859 ?: &(uncertain (itype-face-asym actual expected sub)) [%unknown ~]
4994 ?: &(uncertain (itype-face-asym actual expected sub)) [%unknown ~]
4860 ?: ?=(%any-atom -.expected)
4995 ?: ?=(%any-atom -.expected)
4861 ?: |(?=(%atom -.actual) ?=(%avar -.actual) ?=(%nvar -.actual) ?=(%flag -.actual)) [%ok sub next]
4996 ?: |(?=(%atom -.actual) ?=(%avar -.actual) ?=(%nvar -.actual) ?=(%flag -.actual)) [%ok sub next]
@@ -4943,7 +5078,7 @@
4943:: This core has no Ford dependencies; unrecognized payloads fail closed.
5078:: This core has no Ford dependencies; unrecognized payloads fail closed.
4944+$ iexternals (list [module=term name=term result=*])
5079+$ iexternals (list [module=term name=term result=*])
4945+$ imark-externals (list [mark=term result=*])
5080+$ imark-externals (list [mark=term result=*])
4946−+$ istate [next=@ud sub=isub caps=icaps binders=(list @ud) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) params=iparams active=(list term) in-mold=?]
5081++$ istate [next=@ud sub=isub caps=icaps binders=(list @ud) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) params=iparams active=(list term) tags=(list @ud) in-mold=?]
4947+$ idiag [msg=tape sites=(list [at=span note=tape])]
5082+$ idiag [msg=tape sites=(list [at=span note=tape])]
4948+$ iresult (each [typ=itype state=istate] idiag)
5083+$ iresult (each [typ=itype state=istate] idiag)
4949+$ isample-result (each [typ=itype env=ienv state=istate] tape)
5084+$ isample-result (each [typ=itype env=ienv state=istate] tape)
@@ -4963,6 +5098,8 @@
4963 |= [t=itype sub=isub]
5098 |= [t=itype sub=isub]
4964 ^- itype
5099 ^- itype
4965 =. t (itype-walk t sub)
5100 =. t (itype-walk t sub)
5101+ ?: ?=(%union -.t)
5102+ [%union (turn cases.t |=(c=itype (itype-normalize c sub)))]
4966 ?: ?=(%face -.t)
5103 ?: ?=(%face -.t)
4967 [%face name.t $(t body.t)]
5104 [%face name.t $(t body.t)]
4968 ?: ?=(%fn -.t)
5105 ?: ?=(%fn -.t)
@@ -4983,6 +5120,9 @@
4983 %fn &
5120 %fn &
4984 %cell |($(t hed.t) $(t tal.t))
5121 %cell |($(t hed.t) $(t tal.t))
4985 %face $(t body.t)
5122 %face $(t body.t)
5123+ %union (lien cases.t |=(c=itype (itype-has-gate c)))
5124+ %tag |
5125+ %const |
4986 %var |
5126 %var |
4987 %avar |
5127 %avar |
4988 %nvar |
5128 %nvar |
@@ -5012,6 +5152,9 @@
5012 %atom ~
5152 %atom ~
5013 %any-atom ~
5153 %any-atom ~
5014 %flag ~
5154 %flag ~
5155+ %tag ~
5156+ %const ~
5157+ %union (zing (turn cases.t |=(c=itype (itype-vars c))))
5015 %face $(t body.t)
5158 %face $(t body.t)
5016 %fn (weld $(t sample.t) $(t product.t))
5159 %fn (weld $(t sample.t) $(t product.t))
5017 %cell (weld $(t hed.t) $(t tal.t))
5160 %cell (weld $(t hed.t) $(t tal.t))
@@ -5045,6 +5188,9 @@
5045 %atom t
5188 %atom t
5046 %any-atom t
5189 %any-atom t
5047 %flag t
5190 %flag t
5191+ %tag t
5192+ %const t
5193+ %union [%union (turn cases.t |=(c=itype (itype-rename c ren)))]
5048 %face [%face name.t $(t body.t)]
5194 %face [%face name.t $(t body.t)]
5049 %fn [%fn $(t sample.t) $(t product.t)]
5195 %fn [%fn $(t sample.t) $(t product.t)]
5050 %cell [%cell $(t hed.t) $(t tal.t)]
5196 %cell [%cell $(t hed.t) $(t tal.t)]
@@ -5063,6 +5209,9 @@
5063 %atom |
5209 %atom |
5064 %any-atom |
5210 %any-atom |
5065 %flag |
5211 %flag |
5212+ %tag |
5213+ %const |
5214+ %union (lien cases.t |=(c=itype (itype-var-is-atom n c)))
5066 %face $(t body.t)
5215 %face $(t body.t)
5067 %fn |($(t sample.t) $(t product.t))
5216 %fn |($(t sample.t) $(t product.t))
5068 %cell |($(t hed.t) $(t tal.t))
5217 %cell |($(t hed.t) $(t tal.t))
@@ -5301,6 +5450,16 @@
5301 ?: =(0 aura.sh) `[[%any-atom ~] state]
5450 ?: =(0 aura.sh) `[[%any-atom ~] state]
5302 `[[%atom aura.sh] state]
5451 `[[%atom aura.sh] state]
5303 %flag `[[%flag ~] state]
5452 %flag `[[%flag ~] state]
5453+ %const
5454+ ?. =(%term form.lit.sh) ~
5455+ `[[%const lit.sh] state]
5456+ %union
5457+ =/ pairs=(list upair) (union-pairs cases.sh molds.state)
5458+ ?. (levy pairs |=(p=upair =(%disjoint relation.p))) ~
5459+ =/ cs=(unit [types=(list itype) state=istate]) (infer-shape-args cases.sh state)
5460+ ?~ cs ~
5461+ ?: (lien types.u.cs |=(t=itype ?=(^ (itype-vars t)))) ~
5462+ `[[%union types.u.cs] state.u.cs]
5304 %cell (infer-simple-fields fields.sh state)
5463 %cell (infer-simple-fields fields.sh state)
5305 %fn
5464 %fn
5306 =/ arg=(unit [typ=itype state=istate]) $(sh sample.sh)
5465 =/ arg=(unit [typ=itype state=istate]) $(sh sample.sh)
@@ -5528,6 +5687,8 @@
5528 =/ inferred=iresult (infer-fragment val.d env state)
5687 =/ inferred=iresult (infer-fragment val.d env state)
5529 ?: ?=(%| -.inferred) $(ds t.ds, remaining [d remaining])
5688 ?: ?=(%| -.inferred) $(ds t.ds, remaining [d remaining])
5530 =/ typ=itype (itype-normalize typ.p.inferred sub.state.p.inferred)
5689 =/ typ=itype (itype-normalize typ.p.inferred sub.state.p.inferred)
5690+ ?: |((pending-tags tags.state.p.inferred sub.state.p.inferred) (itype-has-tag typ))
5691+ $(ds t.ds, remaining [d remaining])
5531 ?: (unsupported-atom-vars typ caps.state.p.inferred binders.state.p.inferred sub.state.p.inferred)
5692 ?: (unsupported-atom-vars typ caps.state.p.inferred binders.state.p.inferred sub.state.p.inferred)
5532 $(ds t.ds, remaining [d remaining])
5693 $(ds t.ds, remaining [d remaining])
5533 =/ free=(list @ud)
5694 =/ free=(list @ud)
@@ -5583,6 +5744,7 @@
5583 %duration [%& [%atom %dr] state]
5744 %duration [%& [%atom %dr] state]
5584 %knot [%& [%atom %ta] state]
5745 %knot [%& [%atom %ta] state]
5585 %loobean [%& [%flag ~] state]
5746 %loobean [%& [%flag ~] state]
5747+ %term [%& [%tag next.state lit.e |] state(next +(next.state), tags [next.state tags.state])]
5586 * [%| ["literal needs contextual inference" ~]]
5748 * [%| ["literal needs contextual inference" ~]]
5587 ==
5749 ==
5588 %str
5750 %str
@@ -5604,6 +5766,7 @@
5604 =/ instance=[typ=itype state=istate] (instantiate-scheme u.scheme state)
5766 =/ instance=[typ=itype state=istate] (instantiate-scheme u.scheme state)
5605 [%& typ.instance state.instance]
5767 [%& typ.instance state.instance]
5606 %group $(e inner.e)
5768 %group $(e inner.e)
5769+ %ctor [%& [%tag next.state tag.e &] state(next +(next.state), tags [next.state tags.state])]
5607 %trace
5770 %trace
5608 =/ traced=iresult $(e val.e)
5771 =/ traced=iresult $(e val.e)
5609 ?: ?=(%| -.traced) traced
5772 ?: ?=(%| -.traced) traced
@@ -5653,6 +5816,8 @@
5653 [%| ["branch widening is not supported by partial inference" ~]]
5816 [%| ["branch widening is not supported by partial inference" ~]]
5654 =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
5817 =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
5655 ?~ joined
5818 ?~ joined
5819+ ?: |((itype-has-tag ltype) (itype-has-tag rtype) (itype-has-union ltype) (itype-has-union rtype))
5820+ [%| ["branch tag or union context is not supported by partial inference" ~]]
5656 =/ common=(unit itype) (itype-concrete-join typ.p.left typ.p.right sub.state.p.right)
5821 =/ common=(unit itype) (itype-concrete-join typ.p.left typ.p.right sub.state.p.right)
5657 ?^ common [%& u.common state.p.right]
5822 ?^ common [%& u.common state.p.right]
5658 ?: |((itype-has-face typ.p.left sub.state.p.right) (itype-has-face typ.p.right sub.state.p.right))
5823 ?: |((itype-has-face typ.p.left sub.state.p.right) (itype-has-face typ.p.right sub.state.p.right))
@@ -5710,8 +5875,7 @@
5710 * [%| ["expression is not supported by partial inference" ~]]
5875 * [%| ["expression is not supported by partial inference" ~]]
5711 ==
5876 ==
5712::
5877::
5713−:: Unfaced tuple expressions are the one supported cell construction.
5878+:: Tuple and record expressions preserve their explicitly written faces.
5714−:: Faced cells wait for the representation to preserve record faces.
5715::
5879::
5716++ infer-simple-items
5880++ infer-simple-items
5717 |= [items=(list item) env=ienv state=istate]
5881 |= [items=(list item) env=ienv state=istate]
@@ -5774,6 +5938,9 @@
5774 %atom "@{(trip aura.t)}"
5938 %atom "@{(trip aura.t)}"
5775 %any-atom "@"
5939 %any-atom "@"
5776 %flag "?"
5940 %flag "?"
5941+ %tag (trip txt.literal.t)
5942+ %const (trip txt.literal.t)
5943+ %union "<union>"
5777 %face "[{(trip name.t)}={$(t body.t)}]"
5944 %face "[{(trip name.t)}={$(t body.t)}]"
5778 %fn "$-({$(t sample.t)} {$(t product.t)})"
5945 %fn "$-({$(t sample.t)} {$(t product.t)})"
5779 %cell "[{(show-itype-item hed.t sub)} {(show-itype-item tal.t sub)}]"
5946 %cell "[{(show-itype-item hed.t sub)} {(show-itype-item tal.t sub)}]"
@@ -5799,6 +5966,9 @@
5799 %atom |
5966 %atom |
5800 %any-atom |
5967 %any-atom |
5801 %flag |
5968 %flag |
5969+ %tag |
5970+ %const |
5971+ %union (lien cases.typ |=(c=itype (itype-has-nvar c)))
5802 %face $(typ body.typ)
5972 %face $(typ body.typ)
5803 %fn |($(typ sample.typ) $(typ product.typ))
5973 %fn |($(typ sample.typ) $(typ product.typ))
5804 %cell |($(typ hed.typ) $(typ tal.typ))
5974 %cell |($(typ hed.typ) $(typ tal.typ))
@@ -5808,7 +5978,7 @@
5808 |= [label=tape typ=itype sub=isub]
5978 |= [label=tape typ=itype sub=isub]
5809 ^- tape
5979 ^- tape
5810 =/ normalized=itype (itype-normalize typ sub)
5980 =/ normalized=itype (itype-normalize typ sub)
5811− ?: |(?=(%var -.normalized) ?=(%avar -.normalized) (itype-has-nvar normalized)) label
5981+ ?: |(?=(%var -.normalized) ?=(%avar -.normalized) (itype-has-nvar normalized) (itype-has-tag normalized) (itype-has-union normalized)) label
5812 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
5982 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
5813 ?: (gth (lent vars) 26) label
5983 ?: (gth (lent vars) 26) label
5814 =/ printable=itype (canonical-itype normalized vars)
5984 =/ printable=itype (canonical-itype normalized vars)
@@ -5850,6 +6020,9 @@
5850 %atom |
6020 %atom |
5851 %any-atom |
6021 %any-atom |
5852 %flag |
6022 %flag |
6023+ %tag |
6024+ %const |
6025+ %union (lien cases.t |=(c=itype (has-atom-var n c)))
5853 %face $(t body.t)
6026 %face $(t body.t)
5854 %fn |($(t sample.t) $(t product.t))
6027 %fn |($(t sample.t) $(t product.t))
5855 %cell |($(t hed.t) $(t tal.t))
6028 %cell |($(t hed.t) $(t tal.t))
@@ -5924,10 +6097,11 @@
5924 ?: ?=(%mold -.d) $(ds t.ds)
6097 ?: ?=(%mold -.d) $(ds t.ds)
5925 ?. (unique-value-name name.d globals) $(ds t.ds)
6098 ?. (unique-value-name name.d globals) $(ds t.ds)
5926 ?^ (ienv-lookup name.d env) $(ds t.ds)
6099 ?^ (ienv-lookup name.d env) $(ds t.ds)
5927− =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ |])
6100+ =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ |])
5928 ?: ?=(%| -.result) $(ds t.ds)
6101 ?: ?=(%| -.result) $(ds t.ds)
5929 ?: (constrained-capitals caps.state.p.result sub.state.p.result) $(ds t.ds)
6102 ?: (constrained-capitals caps.state.p.result sub.state.p.result) $(ds t.ds)
5930 =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
6103 =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
6104+ ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ)) $(ds t.ds)
5931 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result) $(ds t.ds)
6105 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result) $(ds t.ds)
5932 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
6106 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
5933 ?: (gth (lent vars) 26) $(ds t.ds)
6107 ?: (gth (lent vars) 26) $(ds t.ds)
@@ -6233,7 +6407,7 @@
6233 =/ surs=(list term) (collect-sur-imports imports.mod)
6407 =/ surs=(list term) (collect-sur-imports imports.mod)
6234 =/ marks=(list term) (collect-mark-imports imports.mod)
6408 =/ marks=(list term) (collect-mark-imports imports.mod)
6235 =/ reserved=(list term) (weld prelude-molds (turn resolved.p.js |=(j=[face=term interface=ifile] face.j)))
6409 =/ reserved=(list term) (weld prelude-molds (turn resolved.p.js |=(j=[face=term interface=ifile] face.j)))
6236− =/ state=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks resolved.p.js reserved ~ ~ |]
6410+ =/ state=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks resolved.p.js reserved ~ ~ ~ |]
6237 =/ mts=(each imold-types @t) (module-mold-types molds state)
6411 =/ mts=(each imold-types @t) (module-mold-types molds state)
6238 ?: ?=(%| -.mts) [%| (crip "{(trip p.mts)}: {(spud at)}")]
6412 ?: ?=(%| -.mts) [%| (crip "{(trip p.mts)}: {(spud at)}")]
6239 =/ env=ienv (resolve-supported-defs defs.mod molds globals externals surs mark-externals marks resolved.p.js reserved)
6413 =/ env=ienv (resolve-supported-defs defs.mod molds globals externals surs mark-externals marks resolved.p.js reserved)
@@ -6306,12 +6480,16 @@
6306 $(ds t.ds, lines [(show-partial-mold file src d molds) lines])
6480 $(ds t.ds, lines [(show-partial-mold file src d molds) lines])
6307 ?. (unique-value-name name.d globals)
6481 ?. (unique-value-name name.d globals)
6308 $(ds t.ds, lines [(crip "++ {(trip name.d)}: name already in scope") lines])
6482 $(ds t.ds, lines [(crip "++ {(trip name.d)}: name already in scope") lines])
6309− =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ |])
6483+ =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ |])
6310 ?: ?=(%| -.result)
6484 ?: ?=(%| -.result)
6311 $(ds t.ds, lines [(show-inference-diagnostic file src name.d p.result) lines])
6485 $(ds t.ds, lines [(show-inference-diagnostic file src name.d p.result) lines])
6312 ?: (constrained-capitals caps.state.p.result sub.state.p.result)
6486 ?: (constrained-capitals caps.state.p.result sub.state.p.result)
6313 $(ds t.ds, lines [(crip "++ {(trip name.d)}: explicit capital constraints are not supported by partial inference") lines])
6487 $(ds t.ds, lines [(crip "++ {(trip name.d)}: explicit capital constraints are not supported by partial inference") lines])
6314 =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
6488 =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
6489+ ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ))
6490+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: tag needs context in partial inference") lines])
6491+ ?: (itype-has-union typ)
6492+ $(ds t.ds, lines [(crip "++ {(trip name.d)}: union type printing is not supported by partial inference") lines])
6315 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result)
6493 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result)
6316 $(ds t.ds, lines [(crip "++ {(trip name.d)}: unresolved aura-variable inference") lines])
6494 $(ds t.ds, lines [(crip "++ {(trip name.d)}: unresolved aura-variable inference") lines])
6317 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
6495 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
tests/golden/module-cache-incomplete/about.txt+1−1
@@ -1,4 +1,4 @@
1source: Grammar, Modules: "Everything is exported and read through the import's face"; Imports: "Import cycles are errors".
1source: Grammar, Modules: "Everything is exported and read through the import's face"; Imports: "Import cycles are errors".
2−tests: A shared library with an unsupported mold yields no partial interface, even though one value could be inferred.
2+tests: A shared library with a generic union mold, which partial inference does not yet support, yields no interface even though one value could be inferred.
3expect: parses
3expect: parses
4expect-types: a partial inference report
4expect-types: a partial inference report
tests/golden/module-cache-incomplete/module-trees.txt+6−1
@@ -1,6 +1,11 @@
1/ui/bad.jibb
1/ui/bad.jibb
2(module
2(module
3 (mold 1:1 choice
3 (mold 1:1 choice
4+ (generic 1:11 A
4− (union 2:3 (const 2:3 %a) (const 3:3 %b)))
5+ (union 2:3
6+ (cell 2:3
7+ (const 2:4 %some)
8+ (face 2:10 value (tvar 2:16 A)))
9+ (const 3:3 %none))))
5 (value 4:1 id
10 (value 4:1 id
6 (gate-wide 4:7 (bind 4:10 x) (wing 4:12 x))))
11 (gate-wide 4:7 (bind 4:10 x) (wing 4:12 x))))
tests/golden/module-cache-incomplete/modules/ui/bad.jibb+3−3
@@ -1,4 +1,4 @@
1−+$ choice
1++$ choice |$ [A]
2− %a
2+ [%some value=A]
3− %b
3+ %none
4++ id |=(x x)
4++ id |=(x x)
tests/golden/types-partial-local-molds/about.txt+2−1
@@ -2,7 +2,8 @@ Grammar, Modules: "Local definitions may start any body, visible to each
2other and the final expression"; a gate's sample cannot see a mold in that
2other and the final expression"; a gate's sample cannot see a mold in that
3gate's body. Partial inference supports acyclic local aliases of simple
3gate's body. Partial inference supports acyclic local aliases of simple
4molds and resolves them in any order. It rejects duplicate or shadowed molds
4molds and resolves them in any order. It rejects duplicate or shadowed molds
5−and leaves recursive or union molds unsupported, even if unused. Mold and
5+and leaves recursive molds unsupported, even if unused. A closed disjoint
6+union mold is accepted, including when unused. Mold and
6value namespaces remain separate. The report does not claim the module is
7value namespaces remain separate. The report does not claim the module is
7checked.
8checked.
8expect: parses
9expect: parses
tests/golden/types-partial-local-molds/types.txt+1−1
@@ -5,7 +5,7 @@ partial inference; module not checked
5++ duplicate: local molds shadow a name
5++ duplicate: local molds shadow a name
6++ shadow: local molds shadow a name
6++ shadow: local molds shadow a name
7++ recursive: local molds need unsupported inference
7++ recursive: local molds need unsupported inference
8−++ unused-union: local molds need unsupported inference
8+++ unused-union: $-(A A)
9++ same-names: $-(@t @t)
9++ same-names: $-(@t @t)
10++ no-leak: cast mold is not supported by partial inference
10++ no-leak: cast mold is not supported by partial inference
11++ nested-shadow: local definitions need unsupported inference
11++ nested-shadow: local definitions need unsupported inference
tests/golden/types-partial-unresolved-tag/about.txt+1−1
@@ -1,4 +1,4 @@
1source: Grammar tab, Molds: "every expression has a principal type, and there is no general subtyping".
1source: Grammar tab, Molds: "every expression has a principal type, and there is no general subtyping".
2−tests: partial inference reports a tag whose contextual inference is not implemented; the report does not claim the module checks.
2+tests: Partial inference reports a tag whose type is not fixed by context; the report does not claim the module checks.
3expect: parses
3expect: parses
4expect-types: a partial inference report, not a checked module
4expect-types: a partial inference report, not a checked module
tests/golden/types-partial-unresolved-tag/types.txt+1−1
@@ -1,2 +1,2 @@
1partial inference; module not checked
1partial inference; module not checked
2−++ message: literal needs contextual inference
2+++ message: tag needs context in partial inference
tests/golden/types-union-alias/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A local alias retains the named union context for a bare tag.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-alias/source.jibbnew file+5
@@ -0,0 +1,5 @@
1++$ msg
2+ [%noted text=@t]
3+ %add
4++$ alias msg
5+++ via ^- alias %add
tests/golden/types-union-alias/tokens.txtnew file+23
@@ -0,0 +1,23 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %noted
6+2:11 name text
7+2:15 tight glyph =
8+2:16 tight aura @t
9+2:18 tight glyph ]
10+3:3 NEWLINE
11+3:3 lit %add
12+4:1 DEDENT
13+4:1 NEWLINE
14+4:1 glyph +$
15+4:4 name alias
16+4:10 name msg
17+5:1 NEWLINE
18+5:1 glyph ++
19+5:4 name via
20+5:8 glyph ^-
21+5:11 name alias
22+5:17 lit %add
23+5:21 NEWLINE
tests/golden/types-union-alias/tree.txtnew file+10
@@ -0,0 +1,10 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %noted)
6+ (face 2:11 text (aura 2:16 @t)))
7+ (const 3:3 %add)))
8+ (mold 4:1 alias (ref 4:10 msg))
9+ (value 5:1 via
10+ (cast 5:8 (ref 5:11 alias) (lit 5:17 %add))))
tests/golden/types-union-alias/types.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3++$ alias: not checked
4+++ via: union type printing is not supported by partial inference
tests/golden/types-union-context-flow/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Tag resolution: tags take their union from context and constrained variables do not generalize.
2+tests: Resolving one tag does not resolve another; union context can reach tags in a branch and through a generic call when supported.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-context-flow/source.jibbnew file+13
@@ -0,0 +1,13 @@
1++$ msg
2+ %add
3+ %remove
4+++ only-one
5+ ~& ^- msg %add
6+ %unknown
7+++ choose |= b=?
8+ ^- msg
9+ ?- b
10+ %.y %add
11+ %.n %remove
12+++ id |=(x x)
13+++ through ^- msg (id %add)
tests/golden/types-union-context-flow/tokens.txtnew file+58
@@ -0,0 +1,58 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 lit %add
5+3:3 NEWLINE
6+3:3 lit %remove
7+4:1 DEDENT
8+4:1 NEWLINE
9+4:1 glyph ++
10+4:4 name only-one
11+5:3 INDENT
12+5:3 glyph ~&
13+5:6 glyph ^-
14+5:9 name msg
15+5:13 lit %add
16+6:5 INDENT
17+6:5 lit %unknown
18+7:1 DEDENT
19+7:1 DEDENT
20+7:1 NEWLINE
21+7:1 glyph ++
22+7:4 name choose
23+7:11 glyph |=
24+7:14 name b
25+7:15 tight glyph =
26+7:16 tight glyph ?
27+8:3 INDENT
28+8:3 glyph ^-
29+8:6 name msg
30+9:5 INDENT
31+9:5 glyph ?-
32+9:8 name b
33+10:7 INDENT
34+10:7 lit %.y
35+10:11 lit %add
36+11:7 NEWLINE
37+11:7 lit %.n
38+11:11 lit %remove
39+12:1 DEDENT
40+12:1 DEDENT
41+12:1 DEDENT
42+12:1 NEWLINE
43+12:1 glyph ++
44+12:4 name id
45+12:7 glyph |=(
46+12:10 tight name x
47+12:12 name x
48+12:13 tight glyph )
49+13:1 NEWLINE
50+13:1 glyph ++
51+13:4 name through
52+13:12 glyph ^-
53+13:15 name msg
54+13:19 glyph (
55+13:20 tight name id
56+13:23 lit %add
57+13:27 tight glyph )
58+13:28 NEWLINE
tests/golden/types-union-context-flow/tree.txtnew file+26
@@ -0,0 +1,26 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3 (const 2:3 %add) (const 3:3 %remove)))
4+ (value 4:1 only-one
5+ (body 5:3
6+ (trace 5:3
7+ (cast 5:6 (ref 5:9 msg) (lit 5:13 %add))
8+ (body 6:5 (lit 6:5 %unknown)))))
9+ (value 7:1 choose
10+ (gate 7:11
11+ (face 7:14 b (flag 7:16))
12+ (body 8:3
13+ (cast 8:3
14+ (ref 8:6 msg)
15+ (body 9:5
16+ (branch 9:5
17+ (wing 9:8 b)
18+ (arm 10:7 (lit 10:7 %.y) (lit 10:11 %add))
19+ (arm 11:7 (lit 11:7 %.n) (lit 11:11 %remove))))))))
20+ (value 12:1 id
21+ (gate-wide 12:7 (bind 12:10 x) (wing 12:12 x)))
22+ (value 13:1 through
23+ (cast 13:12
24+ (ref 13:15 msg)
25+ (group 13:19
26+ (call 13:20 (wing 13:20 id) (lit 13:23 %add))))))
tests/golden/types-union-context-flow/types.txtnew file+6
@@ -0,0 +1,6 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ only-one: tag needs context in partial inference
4+++ choose: branch tag or union context is not supported by partial inference
5+++ id: $-(A A)
6+++ through: union type printing is not supported by partial inference
tests/golden/types-union-import/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Modules: tags take their union from context and modules export their definitions through an import face.
2+tests: A closed union exported by a Jibb library supplies the context of a tag in its caller.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-import/module-trees.txtnew file+8
@@ -0,0 +1,8 @@
1+/ui/lib.jibb
2+(module
3+ (mold 1:1 msg
4+ (union 2:3
5+ (cell 2:3
6+ (const 2:4 %noted)
7+ (face 2:11 text (aura 2:16 @t)))
8+ (const 3:3 %add))))
tests/golden/types-union-import/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/lib.jibb
tests/golden/types-union-import/modules/ui/lib.jibbnew file+3
@@ -0,0 +1,3 @@
1++$ msg
2+ [%noted text=@t]
3+ %add
tests/golden/types-union-import/source.jibbnew file+2
@@ -0,0 +1,2 @@
1+/= lib /ui/lib
2+++ selected ^- msg.lib %add
tests/golden/types-union-import/tokens.txtnew file+13
@@ -0,0 +1,13 @@
1+1:1 glyph /=
2+1:5 name lib
3+1:9 glyph /
4+1:10 tight knot ui
5+1:12 tight glyph /
6+1:13 tight knot lib
7+2:1 NEWLINE
8+2:1 glyph ++
9+2:4 name selected
10+2:13 glyph ^-
11+2:16 wing msg.lib
12+2:24 lit %add
13+2:28 NEWLINE
tests/golden/types-union-import/tree.txtnew file+4
@@ -0,0 +1,4 @@
1+(module
2+ (jibb 1:1 lib /ui/lib)
3+ (value 2:1 selected
4+ (cast 2:13 (ref 2:16 msg.lib) (lit 2:24 %add))))
tests/golden/types-union-import/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+++ selected: union type printing is not supported by partial inference
tests/golden/types-union-overlap/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A union whose atom cases overlap is reported and cannot be treated as a valid type.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-overlap/source.jibbnew file+4
@@ -0,0 +1,4 @@
1++$ overlap
2+ @t
3+ @ud
4+++ identity |=(x x)
tests/golden/types-union-overlap/tokens.txtnew file+15
@@ -0,0 +1,15 @@
1+1:1 glyph +$
2+1:4 name overlap
3+2:3 INDENT
4+2:3 aura @t
5+3:3 NEWLINE
6+3:3 aura @ud
7+4:1 DEDENT
8+4:1 NEWLINE
9+4:1 glyph ++
10+4:4 name identity
11+4:13 glyph |=(
12+4:16 tight name x
13+4:18 name x
14+4:19 tight glyph )
15+4:20 NEWLINE
tests/golden/types-union-overlap/tree.txtnew file+5
@@ -0,0 +1,5 @@
1+(module
2+ (mold 1:1 overlap
3+ (union 2:3 (aura 2:3 @t) (aura 3:3 @ud)))
4+ (value 4:1 identity
5+ (gate-wide 4:13 (bind 4:16 x) (wing 4:18 x))))
tests/golden/types-union-overlap/types.txtnew file+9
@@ -0,0 +1,9 @@
1+partial inference; module not checked
2++$ overlap: overlapping cases; mold not checked
3+/tests/golden/types-union-overlap/source.jibb:2:3: first union case
4+ @t
5+ ^
6+/tests/golden/types-union-overlap/source.jibb:3:3: overlapping case
7+ @ud
8+ ^
9+++ identity: $-(A A)
tests/golden/types-union-singleton/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A nonunion mold counts as a union of one for tagged cells and a tagged constructor. A constructor also works against a union or as a typed argument; wrong input, missing tag and missing context fail, including through a polymorphic identity.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-singleton/source.jibbnew file+16
@@ -0,0 +1,16 @@
1++$ go [%go url=@t]
2++$ typed [%typed text=@t]
3++$ msg
4+ [%noted text=@t]
5+ %add
6+++ go-value ^- go [%go "hi"]
7+++ constructor ^- $-(@t typed) |=%typed
8+++ union-constructor ^- $-(@t msg) |=%noted
9+++ wrong-input ^- $-(@ud typed) |=%typed
10+++ missing ^- $-(@t typed) |=%missing
11+++ no-context |=%typed
12+++ use |= f=$-(@t typed) (f "hi")
13+++ test (use |=%typed)
14+++ bad-call (use |=%nope)
15+++ id |=(x x)
16+++ through (id |=%typed)
tests/golden/types-union-singleton/tokens.txtnew file+130
@@ -0,0 +1,130 @@
1+1:1 glyph +$
2+1:4 name go
3+1:7 glyph [
4+1:8 tight lit %go
5+1:12 name url
6+1:15 tight glyph =
7+1:16 tight aura @t
8+1:18 tight glyph ]
9+2:1 NEWLINE
10+2:1 glyph +$
11+2:4 name typed
12+2:10 glyph [
13+2:11 tight lit %typed
14+2:18 name text
15+2:22 tight glyph =
16+2:23 tight aura @t
17+2:25 tight glyph ]
18+3:1 NEWLINE
19+3:1 glyph +$
20+3:4 name msg
21+4:3 INDENT
22+4:3 glyph [
23+4:4 tight lit %noted
24+4:11 name text
25+4:15 tight glyph =
26+4:16 tight aura @t
27+4:18 tight glyph ]
28+5:3 NEWLINE
29+5:3 lit %add
30+6:1 DEDENT
31+6:1 NEWLINE
32+6:1 glyph ++
33+6:4 name go-value
34+6:13 glyph ^-
35+6:16 name go
36+6:19 glyph [
37+6:20 tight lit %go
38+6:24 str "hi"
39+6:28 tight glyph ]
40+7:1 NEWLINE
41+7:1 glyph ++
42+7:4 name constructor
43+7:16 glyph ^-
44+7:19 glyph $-(
45+7:22 tight aura @t
46+7:25 name typed
47+7:30 tight glyph )
48+7:32 glyph |=
49+7:34 tight lit %typed
50+8:1 NEWLINE
51+8:1 glyph ++
52+8:4 name union-constructor
53+8:22 glyph ^-
54+8:25 glyph $-(
55+8:28 tight aura @t
56+8:31 name msg
57+8:34 tight glyph )
58+8:36 glyph |=
59+8:38 tight lit %noted
60+9:1 NEWLINE
61+9:1 glyph ++
62+9:4 name wrong-input
63+9:16 glyph ^-
64+9:19 glyph $-(
65+9:22 tight aura @ud
66+9:26 name typed
67+9:31 tight glyph )
68+9:33 glyph |=
69+9:35 tight lit %typed
70+10:1 NEWLINE
71+10:1 glyph ++
72+10:4 name missing
73+10:12 glyph ^-
74+10:15 glyph $-(
75+10:18 tight aura @t
76+10:21 name typed
77+10:26 tight glyph )
78+10:28 glyph |=
79+10:30 tight lit %missing
80+11:1 NEWLINE
81+11:1 glyph ++
82+11:4 name no-context
83+11:15 glyph |=
84+11:17 tight lit %typed
85+12:1 NEWLINE
86+12:1 glyph ++
87+12:4 name use
88+12:8 glyph |=
89+12:11 name f
90+12:12 tight glyph =
91+12:13 tight glyph $-(
92+12:16 tight aura @t
93+12:19 name typed
94+12:24 tight glyph )
95+12:26 glyph (
96+12:27 tight name f
97+12:29 str "hi"
98+12:33 tight glyph )
99+13:1 NEWLINE
100+13:1 glyph ++
101+13:4 name test
102+13:9 glyph (
103+13:10 tight name use
104+13:14 glyph |=
105+13:16 tight lit %typed
106+13:22 tight glyph )
107+14:1 NEWLINE
108+14:1 glyph ++
109+14:4 name bad-call
110+14:13 glyph (
111+14:14 tight name use
112+14:18 glyph |=
113+14:20 tight lit %nope
114+14:25 tight glyph )
115+15:1 NEWLINE
116+15:1 glyph ++
117+15:4 name id
118+15:7 glyph |=(
119+15:10 tight name x
120+15:12 name x
121+15:13 tight glyph )
122+16:1 NEWLINE
123+16:1 glyph ++
124+16:4 name through
125+16:12 glyph (
126+16:13 tight name id
127+16:16 glyph |=
128+16:18 tight lit %typed
129+16:24 tight glyph )
130+16:25 NEWLINE
tests/golden/types-union-singleton/tree.txtnew file+53
@@ -0,0 +1,53 @@
1+(module
2+ (mold 1:1 go
3+ (cell 1:7
4+ (const 1:8 %go)
5+ (face 1:12 url (aura 1:16 @t))))
6+ (mold 2:1 typed
7+ (cell 2:10
8+ (const 2:11 %typed)
9+ (face 2:18 text (aura 2:23 @t))))
10+ (mold 3:1 msg
11+ (union 4:3
12+ (cell 4:3
13+ (const 4:4 %noted)
14+ (face 4:11 text (aura 4:16 @t)))
15+ (const 5:3 %add)))
16+ (value 6:1 go-value
17+ (cast 6:13
18+ (ref 6:16 go)
19+ (tuple 6:19 (lit 6:20 %go) (str 6:24 "hi"))))
20+ (value 7:1 constructor
21+ (cast 7:16
22+ (fn 7:19 (aura 7:22 @t) (ref 7:25 typed))
23+ (ctor 7:32 %typed)))
24+ (value 8:1 union-constructor
25+ (cast 8:22
26+ (fn 8:25 (aura 8:28 @t) (ref 8:31 msg))
27+ (ctor 8:36 %noted)))
28+ (value 9:1 wrong-input
29+ (cast 9:16
30+ (fn 9:19 (aura 9:22 @ud) (ref 9:26 typed))
31+ (ctor 9:33 %typed)))
32+ (value 10:1 missing
33+ (cast 10:12
34+ (fn 10:15 (aura 10:18 @t) (ref 10:21 typed))
35+ (ctor 10:28 %missing)))
36+ (value 11:1 no-context (ctor 11:15 %typed))
37+ (value 12:1 use
38+ (gate 12:8
39+ (face 12:11 f
40+ (fn 12:13 (aura 12:16 @t) (ref 12:19 typed)))
41+ (group 12:26
42+ (call 12:27 (wing 12:27 f) (str 12:29 "hi")))))
43+ (value 13:1 test
44+ (group 13:9
45+ (call 13:10 (wing 13:10 use) (ctor 13:14 %typed))))
46+ (value 14:1 bad-call
47+ (group 14:13
48+ (call 14:14 (wing 14:14 use) (ctor 14:18 %nope))))
49+ (value 15:1 id
50+ (gate-wide 15:7 (bind 15:10 x) (wing 15:12 x)))
51+ (value 16:1 through
52+ (group 16:12
53+ (call 16:13 (wing 16:13 id) (ctor 16:16 %typed)))))
tests/golden/types-union-singleton/types.txtnew file+33
@@ -0,0 +1,33 @@
1+partial inference; module not checked
2++$ go: not checked
3++$ typed: not checked
4++$ msg: cases proven disjoint; mold not checked
5+++ go-value: [%go url=@t]
6+++ constructor: $-(@t [%typed text=@t])
7+++ union-constructor: union type printing is not supported by partial inference
8+++ wrong-input: cast mold and expression type do not unify
9+/tests/golden/types-union-singleton/source.jibb:9:19: cast mold has type $-(@ud [%typed text=@t])
10+++ wrong-input ^- $-(@ud typed) |=%typed
11+ ^
12+/tests/golden/types-union-singleton/source.jibb:9:33: expression
13+++ wrong-input ^- $-(@ud typed) |=%typed
14+ ^
15+++ missing: cast mold and expression type do not unify
16+/tests/golden/types-union-singleton/source.jibb:10:15: cast mold has type $-(@t [%typed text=@t])
17+++ missing ^- $-(@t typed) |=%missing
18+ ^
19+/tests/golden/types-union-singleton/source.jibb:10:28: expression
20+++ missing ^- $-(@t typed) |=%missing
21+ ^
22+++ no-context: tag needs context in partial inference
23+++ use: $-($-(@t [%typed text=@t]) [%typed text=@t])
24+++ test: [%typed text=@t]
25+++ bad-call: call's sample and argument types do not unify
26+/tests/golden/types-union-singleton/source.jibb:14:14: called gate has type $-($-(@t [%typed text=@t]) [%typed text=@t])
27+++ bad-call (use |=%nope)
28+ ^
29+/tests/golden/types-union-singleton/source.jibb:14:18: argument
30+++ bad-call (use |=%nope)
31+ ^
32+++ id: $-(A A)
33+++ through: tag needs context in partial inference
tests/golden/types-union-tag-atoms/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Tag resolution: a tag may fit an atom type by its noun value; a loobean has the two atoms `%.y` and `%.n`.
2+tests: `%$` and `%1` fit a loobean by value, `%2` does not, and `%1` and `%&` fit the requested atom auras.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-tag-atoms/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ zero ^- ? %$
2+++ one ^- ? %1
3+++ two ^- ? %2
4+++ numeric ^- @tas %1
5+++ bit ^- @ta %&
tests/golden/types-union-tag-atoms/tokens.txtnew file+30
@@ -0,0 +1,30 @@
1+1:1 glyph ++
2+1:4 name zero
3+1:9 glyph ^-
4+1:12 glyph ?
5+1:14 lit %$
6+2:1 NEWLINE
7+2:1 glyph ++
8+2:4 name one
9+2:8 glyph ^-
10+2:11 glyph ?
11+2:13 lit %1
12+3:1 NEWLINE
13+3:1 glyph ++
14+3:4 name two
15+3:8 glyph ^-
16+3:11 glyph ?
17+3:13 lit %2
18+4:1 NEWLINE
19+4:1 glyph ++
20+4:4 name numeric
21+4:12 glyph ^-
22+4:15 aura @tas
23+4:20 lit %1
24+5:1 NEWLINE
25+5:1 glyph ++
26+5:4 name bit
27+5:8 glyph ^-
28+5:11 aura @ta
29+5:15 lit %&
30+5:17 NEWLINE
tests/golden/types-union-tag-atoms/tree.txtnew file+11
@@ -0,0 +1,11 @@
1+(module
2+ (value 1:1 zero
3+ (cast 1:9 (flag 1:12) (lit 1:14 %$)))
4+ (value 2:1 one
5+ (cast 2:8 (flag 2:11) (lit 2:13 %1)))
6+ (value 3:1 two
7+ (cast 3:8 (flag 3:11) (lit 3:13 %2)))
8+ (value 4:1 numeric
9+ (cast 4:12 (aura 4:15 @tas) (lit 4:20 %1)))
10+ (value 5:1 bit
11+ (cast 5:8 (aura 5:11 @ta) (lit 5:15 %&))))
tests/golden/types-union-tag-atoms/types.txtnew file+12
@@ -0,0 +1,12 @@
1+partial inference; module not checked
2+++ zero: ?
3+++ one: ?
4+++ two: cast mold and expression type do not unify
5+/tests/golden/types-union-tag-atoms/source.jibb:3:11: cast mold has type ?
6+++ two ^- ? %2
7+ ^
8+/tests/golden/types-union-tag-atoms/source.jibb:3:13: expression
9+++ two ^- ? %2
10+ ^
11+++ numeric: @tas
12+++ bit: @ta
tests/golden/types-union-tags/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A closed disjoint union resolves bare and record tags in context; an absent tag remains an error.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-tags/source.jibbnew file+6
@@ -0,0 +1,6 @@
1++$ msg
2+ [%noted text=@t]
3+ %add
4+++ simple ^- msg %add
5+++ record ^- msg [%noted "hi"]
6+++ wrong ^- msg %missing
tests/golden/types-union-tags/tokens.txtnew file+34
@@ -0,0 +1,34 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %noted
6+2:11 name text
7+2:15 tight glyph =
8+2:16 tight aura @t
9+2:18 tight glyph ]
10+3:3 NEWLINE
11+3:3 lit %add
12+4:1 DEDENT
13+4:1 NEWLINE
14+4:1 glyph ++
15+4:4 name simple
16+4:11 glyph ^-
17+4:14 name msg
18+4:18 lit %add
19+5:1 NEWLINE
20+5:1 glyph ++
21+5:4 name record
22+5:11 glyph ^-
23+5:14 name msg
24+5:18 glyph [
25+5:19 tight lit %noted
26+5:26 str "hi"
27+5:30 tight glyph ]
28+6:1 NEWLINE
29+6:1 glyph ++
30+6:4 name wrong
31+6:10 glyph ^-
32+6:13 name msg
33+6:17 lit %missing
34+6:25 NEWLINE
tests/golden/types-union-tags/tree.txtnew file+15
@@ -0,0 +1,15 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %noted)
6+ (face 2:11 text (aura 2:16 @t)))
7+ (const 3:3 %add)))
8+ (value 4:1 simple
9+ (cast 4:11 (ref 4:14 msg) (lit 4:18 %add)))
10+ (value 5:1 record
11+ (cast 5:11
12+ (ref 5:14 msg)
13+ (tuple 5:18 (lit 5:19 %noted) (str 5:26 "hi"))))
14+ (value 6:1 wrong
15+ (cast 6:10 (ref 6:13 msg) (lit 6:17 %missing))))
tests/golden/types-union-tags/types.txtnew file+11
@@ -0,0 +1,11 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ simple: union type printing is not supported by partial inference
4+++ record: union type printing is not supported by partial inference
5+++ wrong: cast mold and expression type do not unify
6+/tests/golden/types-union-tags/source.jibb:6:13: cast mold
7+++ wrong ^- msg %missing
8+ ^
9+/tests/golden/types-union-tags/source.jibb:6:17: expression
10+++ wrong ^- msg %missing
11+ ^
tests/golden/types-union-unresolved-flow/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Tag resolution: "A constrained variable, and any it mentions, doesn't generalize" and an unresolved tag needs context.
2+tests: An unresolved tag remains unresolved through an alias, a cell, a gate and a discarded trace; partial inference must not guess a type.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-unresolved-flow/source.jibbnew file+7
@@ -0,0 +1,7 @@
1+++ first %add
2+++ alias first
3+++ cell [%add 1]
4+++ gate |= x %add
5+++ traced
6+ ~& %add
7+ 1
tests/golden/types-union-unresolved-flow/tokens.txtnew file+31
@@ -0,0 +1,31 @@
1+1:1 glyph ++
2+1:4 name first
3+1:10 lit %add
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name alias
7+2:10 name first
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name cell
11+3:9 glyph [
12+3:10 tight lit %add
13+3:15 lit 1
14+3:16 tight glyph ]
15+4:1 NEWLINE
16+4:1 glyph ++
17+4:4 name gate
18+4:9 glyph |=
19+4:12 name x
20+4:14 lit %add
21+5:1 NEWLINE
22+5:1 glyph ++
23+5:4 name traced
24+6:3 INDENT
25+6:3 glyph ~&
26+6:6 lit %add
27+7:5 INDENT
28+7:5 lit 1
29+7:6 DEDENT
30+7:6 DEDENT
31+7:6 NEWLINE
tests/golden/types-union-unresolved-flow/tree.txtnew file+12
@@ -0,0 +1,12 @@
1+(module
2+ (value 1:1 first (lit 1:10 %add))
3+ (value 2:1 alias (wing 2:10 first))
4+ (value 3:1 cell
5+ (tuple 3:9 (lit 3:10 %add) (lit 3:15 1)))
6+ (value 4:1 gate
7+ (gate 4:9 (bind 4:12 x) (lit 4:14 %add)))
8+ (value 5:1 traced
9+ (body 6:3
10+ (trace 6:3
11+ (lit 6:6 %add)
12+ (body 7:5 (lit 7:5 1))))))
tests/golden/types-union-unresolved-flow/types.txtnew file+6
@@ -0,0 +1,6 @@
1+partial inference; module not checked
2+++ first: tag needs context in partial inference
3+++ alias: name is not available to partial inference
4+++ cell: tag needs context in partial inference
5+++ gate: tag needs context in partial inference
6+++ traced: tag needs context in partial inference
tests/golden/types-union-unresolved/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A tag with no context stays unresolved and asks for a type rather than being guessed.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-unresolved/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ alone %add
tests/golden/types-union-unresolved/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name alone
3+1:10 lit %add
4+1:14 NEWLINE
tests/golden/types-union-unresolved/tree.txtnew file+2
@@ -0,0 +1,2 @@
1+(module
2+ (value 1:1 alone (lit 1:10 %add)))
tests/golden/types-union-unresolved/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+++ alone: tag needs context in partial inference
tests/importer/about.txt+5−4
@@ -2,10 +2,11 @@
2recursion, and unsupported forms. `shadow.txt` checks local generator
2recursion, and unsupported forms. `shadow.txt` checks local generator
3shadowing and missing provenance. `shadow-static.txt` checks that a local
3shadowing and missing provenance. `shadow-static.txt` checks that a local
4list shadow alongside a nested ordered map is rejected. Static sibling
4list shadow alongside a nested ordered map is rejected. Static sibling
5−collections and dependent sibling molds are tested separately. A single nested `$^` in a record of aura atom molds, constant tags and records is checked
5+collections and dependent sibling molds are tested separately. Explicit Hoon `$%`, `$?` and `$^` unions are checked from source where
6+their branches are static, including cases Hoon would collapse. Materialized
6−from its source branches. Named or validated siblings and branches, multiple `$^` cases,
7+forks are checked too. Named or validated branches, multiple nested unions,
7−and `$^` in collection arguments fail closed before Hoon can collapse
8+and explicit unions in collection arguments fail closed; nested `$@` cases
8−overlapping branches; nested `$@` cases remain supported. `ford.txt`
9+remain supported. The provisional reading is recorded in doc question 22. `ford.txt`
9checks a synthetic imported subject and selected mold; other cases check
10checks a synthetic imported subject and selected mold; other cases check
10transitive imports, named mold lookup, missing names, shadowing, unprovenanced
11transitive imports, named mold lookup, missing names, shadowing, unprovenanced
11recursive holds, malformed
12recursive holds, malformed
tests/importer/ford.txt+1
@@ -2,6 +2,7 @@
2+$ lists (list @ud)
2+$ lists (list @ud)
3+$ wrapped item:small
3+$ wrapped item:small
4+$ recursive chain:small
4+$ recursive chain:small
5++$ bad-union explicit-wut-overlap:small
5+$ tagged-record nested-tagged:small
6+$ tagged-record nested-tagged:small
6+$ nested-record nested-valid-cell:small
7+$ nested-record nested-valid-cell:small
7+$ local $@(~ [v=@ud next=local])
8+$ local $@(~ [v=@ud next=local])
tests/importer/origin-transitive.txt+1
@@ -1,5 +1,6 @@
1|%
1|%
2+$ wrapped recursive:intermediate
2+$ wrapped recursive:intermediate
3++$ bad-union bad-union:intermediate
3+$ tagged tagged-record:intermediate
4+$ tagged tagged-record:intermediate
4+$ nested nested-record:intermediate
5+$ nested nested-record:intermediate
5--
6--
tests/importer/shadow-static.txt+2
@@ -1,4 +1,6 @@
1|%
1|%
2++ list list:..zuse
2++ list list:..zuse
3+++ path path:..zuse
4++$ path-shadow [?(%fil %dir) pa=path nam=@t]
3+$ bad [a=((mop @ud @t) lte) b=(list @ud)]
5+$ bad [a=((mop @ud @t) lte) b=(list @ud)]
4--
6--
tests/importer/small.txt+12
@@ -26,6 +26,18 @@
26+$ signed @sd
26+$ signed @sd
27+$ float @rd
27+$ float @rd
28+$ gate-test $-(@ud @ud)
28+$ gate-test $-(@ud @ud)
29++$ explicit-wut-safe $?([%ok @ud] [%err @t])
30++$ explicit-percent-overlap $%([%x @ud] [%x @t])
31++$ explicit-wut-overlap $?([%x @ud] [%x @t])
32++$ explicit-collapsed $?([%x @ud] [%x @ud])
33++$ explicit-subsumed $?(@u @ud)
34++$ explicit-three $?([%a @ud] [%b @t] [%c @p])
35++$ explicit-unknown $?([%x word] [%y @t])
36++$ explicit-nested [value=$?([%x @ud] [%x @t]) other=@ud]
37++$ explicit-list (list $?([%x @ud] [%x @t]))
38++$ explicit-set (set $%([%x @ud] [%x @ud]))
39++$ explicit-faces (list [bcwt=@t bccn=@ud])
40++$ explicit-alias explicit-wut-overlap
29+$ list-bckt-field (list [bckt=@ud value=@t])
41+$ list-bckt-field (list [bckt=@ud value=@t])
30+$ list-noun-overlap (list $^(* @ud))
42+$ list-noun-overlap (list $^(* @ud))
31+$ list-null-overlap (list $^(~ @ud))
43+$ list-null-overlap (list $^(~ @ud))
tests/importer/tree.txt+21−1
@@ -46,6 +46,26 @@ float: error: signed and float auras cannot be imported
46gate: error: cores and gates cannot be imported
46gate: error: cores and gates cannot be imported
47vase: error: vases cannot be imported
47vase: error: vases cannot be imported
48failed-branch: error: a Hoon $^ union needs a source-level disjointness check
48failed-branch: error: a Hoon $^ union needs a source-level disjointness check
49+debug-union: (union [add text=@t] [remove id=@ud])
50+debug-union-overlap: error: a Hoon union has overlapping cases
51+debug-nested-cell: [id=@ud value=(union [a=@ud b=@t] @ud)]
52+debug-nested-cell-overlap: error: a Hoon $^ union has overlapping cases
53+explicit-graph: error: a Hoon union has overlapping cases
54+explicit-graph-unsupported: error: signed and float auras cannot be imported
55+explicit-wut-safe: (union [ok @ud] [err @t])
56+explicit-percent-overlap: error: a Hoon union has overlapping cases
57+explicit-wut-overlap: error: a Hoon union has overlapping cases
58+explicit-collapsed: error: a Hoon union has overlapping cases
59+explicit-subsumed: error: a Hoon union has overlapping cases
60+explicit-three: (union [a @ud] [b @t] [c @p])
61+explicit-unknown: error: a Hoon union needs a source-level disjointness check
62+explicit-nested: error: a Hoon union has overlapping cases
63+explicit-list: error: a Hoon union needs a source-level disjointness check
64+explicit-set: error: a Hoon union needs a source-level disjointness check
65+explicit-faces: (list [bcwt=@t bccn=@ud])
66+explicit-alias: error: a Hoon union has overlapping cases
67+explicit-ford: error: a Hoon union has overlapping cases
68+explicit-shadow-path: error: Hoon collection provenance is unavailable or shadowed
49list-bckt-field: (list [bckt=@ud value=@t])
69list-bckt-field: (list [bckt=@ud value=@t])
50list-noun-overlap: error: a Hoon $^ union needs a source-level disjointness check
70list-noun-overlap: error: a Hoon $^ union needs a source-level disjointness check
51list-null-overlap: error: a Hoon $^ union needs a source-level disjointness check
71list-null-overlap: error: a Hoon $^ union needs a source-level disjointness check
@@ -71,7 +91,7 @@ nested-first-cell: [value=(union [a=@ud b=@t] @ud) id=@t]
71nested-alias-cell: [id=@ud value=(union [a=@ud b=@t] @ud)]
91nested-alias-cell: [id=@ud value=(union [a=@ud b=@t] @ud)]
72nested-multiple-cell: error: a Hoon $^ union needs a source-level disjointness check
92nested-multiple-cell: error: a Hoon $^ union needs a source-level disjointness check
73nested-named-sibling: error: a Hoon $^ union needs a source-level disjointness check
93nested-named-sibling: error: a Hoon $^ union needs a source-level disjointness check
74−nested-list-sibling: error: a Hoon $^ union needs a source-level disjointness check
94+nested-list-sibling: [id=(list @ud) value=(union [a=@ud b=@t] @ud)]
75nested-validated-sibling: error: a Hoon $^ union needs a source-level disjointness check
95nested-validated-sibling: error: a Hoon $^ union needs a source-level disjointness check
76nested-validated-branch: error: a Hoon $^ union needs a source-level disjointness check
96nested-validated-branch: error: a Hoon $^ union needs a source-level disjointness check
77nested-named-branch: error: a Hoon $^ union needs a source-level disjointness check
97nested-named-branch: error: a Hoon $^ union needs a source-level disjointness check
tests/lib/jibb-module-scope.hoon+10−1
@@ -20,5 +20,14 @@
20 =/ bad (golden-types-with-prelude:jibb /ui/main/jibb source ~ ~ fixtures (crip "+$"))
20 =/ bad (golden-types-with-prelude:jibb /ui/main/jibb source ~ ~ fixtures (crip "+$"))
21 =/ conflict=@t (crip "/= value /ui/dep\0a++ identity |= x x\0a")
21 =/ conflict=@t (crip "/= value /ui/dep\0a++ identity |= x x\0a")
22 =/ collision (golden-types-with-prelude:jibb /ui/main/jibb conflict ~ ~ fixtures prelude)
22 =/ collision (golden-types-with-prelude:jibb /ui/main/jibb conflict ~ ~ fixtures prelude)
23+ =/ library=@t (crip "++ pass |=(x x)\0a")
24+ =/ duplicate-source=@t (crip "/= dep /ui/dup\0a++ main-value 1\0a")
25+ =/ duplicates=(list [at=path source=@t])
26+ ~[[~[%ui %dup %jibb] library] [~[%ui %dup %jibb] library]]
27+ =/ duplicate (golden-types-with-prelude:jibb /ui/main/jibb duplicate-source ~ ~ duplicates prelude)
28+ =/ after-source=@t (crip "/= first /ui/safe\0a/= second /ui/dup\0a++ main-value 1\0a")
29+ =/ after-fixtures=(list [at=path source=@t])
30+ [[~[%ui %safe %jibb] library] duplicates]
31+ =/ after (golden-types-with-prelude:jibb /ui/main/jibb after-source ~ ~ after-fixtures prelude)
23− (of-wain:format ~[okay empty bad collision])
32+ (of-wain:format ~[okay empty bad collision duplicate after])
24--
33--
tests/lib/jibb.hoon+56
@@ -1562,6 +1562,44 @@
1562/* tok-459 %txt /tests/golden/types-record-to-tuple/tokens/txt
1562/* tok-459 %txt /tests/golden/types-record-to-tuple/tokens/txt
1563/* tre-459 %txt /tests/golden/types-record-to-tuple/tree/txt
1563/* tre-459 %txt /tests/golden/types-record-to-tuple/tree/txt
1564/* typ-459 %txt /tests/golden/types-record-to-tuple/types/txt
1564/* typ-459 %txt /tests/golden/types-record-to-tuple/types/txt
1565+/* src-460 %jibb /tests/golden/types-union-alias/source/jibb
1566+/* tok-460 %txt /tests/golden/types-union-alias/tokens/txt
1567+/* tre-460 %txt /tests/golden/types-union-alias/tree/txt
1568+/* typ-460 %txt /tests/golden/types-union-alias/types/txt
1569+/* src-461 %jibb /tests/golden/types-union-context-flow/source/jibb
1570+/* tok-461 %txt /tests/golden/types-union-context-flow/tokens/txt
1571+/* tre-461 %txt /tests/golden/types-union-context-flow/tree/txt
1572+/* typ-461 %txt /tests/golden/types-union-context-flow/types/txt
1573+/* src-462 %jibb /tests/golden/types-union-import/source/jibb
1574+/* tok-462 %txt /tests/golden/types-union-import/tokens/txt
1575+/* tre-462 %txt /tests/golden/types-union-import/tree/txt
1576+/* mod-462-1 %jibb /tests/golden/types-union-import/modules/ui/lib/jibb
1577+/* typ-462 %txt /tests/golden/types-union-import/types/txt
1578+/* mtre-462 %txt /tests/golden/types-union-import/module-trees/txt
1579+/* src-463 %jibb /tests/golden/types-union-overlap/source/jibb
1580+/* tok-463 %txt /tests/golden/types-union-overlap/tokens/txt
1581+/* tre-463 %txt /tests/golden/types-union-overlap/tree/txt
1582+/* typ-463 %txt /tests/golden/types-union-overlap/types/txt
1583+/* src-464 %jibb /tests/golden/types-union-singleton/source/jibb
1584+/* tok-464 %txt /tests/golden/types-union-singleton/tokens/txt
1585+/* tre-464 %txt /tests/golden/types-union-singleton/tree/txt
1586+/* typ-464 %txt /tests/golden/types-union-singleton/types/txt
1587+/* src-465 %jibb /tests/golden/types-union-tag-atoms/source/jibb
1588+/* tok-465 %txt /tests/golden/types-union-tag-atoms/tokens/txt
1589+/* tre-465 %txt /tests/golden/types-union-tag-atoms/tree/txt
1590+/* typ-465 %txt /tests/golden/types-union-tag-atoms/types/txt
1591+/* src-466 %jibb /tests/golden/types-union-tags/source/jibb
1592+/* tok-466 %txt /tests/golden/types-union-tags/tokens/txt
1593+/* tre-466 %txt /tests/golden/types-union-tags/tree/txt
1594+/* typ-466 %txt /tests/golden/types-union-tags/types/txt
1595+/* src-467 %jibb /tests/golden/types-union-unresolved/source/jibb
1596+/* tok-467 %txt /tests/golden/types-union-unresolved/tokens/txt
1597+/* tre-467 %txt /tests/golden/types-union-unresolved/tree/txt
1598+/* typ-467 %txt /tests/golden/types-union-unresolved/types/txt
1599+/* src-468 %jibb /tests/golden/types-union-unresolved-flow/source/jibb
1600+/* tok-468 %txt /tests/golden/types-union-unresolved-flow/tokens/txt
1601+/* tre-468 %txt /tests/golden/types-union-unresolved-flow/tree/txt
1602+/* typ-468 %txt /tests/golden/types-union-unresolved-flow/types/txt
1565|%
1603|%
1566:: one arm per case
1604:: one arm per case
1567::
1605::
@@ -2483,6 +2521,24 @@
2483 (weld (check ~.types-record-nested src-458 `tok-458 `tre-458) (check-types ~.types-record-nested ~[%tests %golden ~.types-record-nested %source %jibb] src-458 `typ-458))
2521 (weld (check ~.types-record-nested src-458 `tok-458 `tre-458) (check-types ~.types-record-nested ~[%tests %golden ~.types-record-nested %source %jibb] src-458 `typ-458))
2484++ test-types-record-to-tuple
2522++ test-types-record-to-tuple
2485 (weld (check ~.types-record-to-tuple src-459 `tok-459 `tre-459) (check-types ~.types-record-to-tuple ~[%tests %golden ~.types-record-to-tuple %source %jibb] src-459 `typ-459))
2523 (weld (check ~.types-record-to-tuple src-459 `tok-459 `tre-459) (check-types ~.types-record-to-tuple ~[%tests %golden ~.types-record-to-tuple %source %jibb] src-459 `typ-459))
2524+++ test-types-union-alias
2525+ (weld (check ~.types-union-alias src-460 `tok-460 `tre-460) (check-types ~.types-union-alias ~[%tests %golden ~.types-union-alias %source %jibb] src-460 `typ-460))
2526+++ test-types-union-context-flow
2527+ (weld (check ~.types-union-context-flow src-461 `tok-461 `tre-461) (check-types ~.types-union-context-flow ~[%tests %golden ~.types-union-context-flow %source %jibb] src-461 `typ-461))
2528+++ test-types-union-import
2529+ (weld (weld (check ~.types-union-import src-462 `tok-462 `tre-462) (check-module-types ~.types-union-import ~[%tests %golden ~.types-union-import %source %jibb] src-462 `typ-462 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-462-1]])) (check-module-trees ~.types-union-import `mtre-462 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-462-1]]))
2530+++ test-types-union-overlap
2531+ (weld (check ~.types-union-overlap src-463 `tok-463 `tre-463) (check-types ~.types-union-overlap ~[%tests %golden ~.types-union-overlap %source %jibb] src-463 `typ-463))
2532+++ test-types-union-singleton
2533+ (weld (check ~.types-union-singleton src-464 `tok-464 `tre-464) (check-types ~.types-union-singleton ~[%tests %golden ~.types-union-singleton %source %jibb] src-464 `typ-464))
2534+++ test-types-union-tag-atoms
2535+ (weld (check ~.types-union-tag-atoms src-465 `tok-465 `tre-465) (check-types ~.types-union-tag-atoms ~[%tests %golden ~.types-union-tag-atoms %source %jibb] src-465 `typ-465))
2536+++ test-types-union-tags
2537+ (weld (check ~.types-union-tags src-466 `tok-466 `tre-466) (check-types ~.types-union-tags ~[%tests %golden ~.types-union-tags %source %jibb] src-466 `typ-466))
2538+++ test-types-union-unresolved
2539+ (weld (check ~.types-union-unresolved src-467 `tok-467 `tre-467) (check-types ~.types-union-unresolved ~[%tests %golden ~.types-union-unresolved %source %jibb] src-467 `typ-467))
2540+++ test-types-union-unresolved-flow
2541+ (weld (check ~.types-union-unresolved-flow src-468 `tok-468 `tre-468) (check-types ~.types-union-unresolved-flow ~[%tests %golden ~.types-union-unresolved-flow %source %jibb] src-468 `typ-468))
2486::
2542::
2487:: +check: run golden:jibb on a case and compare both outputs
2543:: +check: run golden:jibb on a case and compare both outputs
2488::
2544::
tests/type-module-scope/about.txt+2
@@ -3,3 +3,5 @@ source. Names from the prelude occupy separate value and mold namespaces;
3import faces cannot shadow either. This synthetic prelude exercises a value
3import faces cannot shadow either. This synthetic prelude exercises a value
4whose name is used as an imported mold and a mold whose name is used as an
4whose name is used as an imported mold and a mold whose name is used as an
5imported value. Empty and malformed prelude sources fail closed.
5imported value. Empty and malformed prelude sources fail closed.
6+Duplicate module sources are rejected both directly and after a distinct
7+sibling module has been cached; they cannot produce an interface.
tests/type-module-scope/expected.txt+4
@@ -7,3 +7,7 @@ partial inference; module not checked
7prelude source does not parse; module import inference unsupported
7prelude source does not parse; module import inference unsupported
8partial inference; module not checked
8partial inference; module not checked
9module has conflicting names
9module has conflicting names
10+partial inference; module not checked
11+duplicate module sources: /ui/dup/jibb
12+partial inference; module not checked
13+duplicate module sources: /ui/dup/jibb
tools/importer-test+1−1
@@ -34,4 +34,4 @@ if result.stdout != expected:
34 result.stdout.decode().splitlines(keepends=True),
34 result.stdout.decode().splitlines(keepends=True),
35 fromfile='expected tree.txt', tofile='actual types'))
35 fromfile='expected tree.txt', tofile='actual types'))
36 sys.exit(1)
36 sys.exit(1)
37−print('importer golden: 110 projections passed')
37+print('importer golden: 130 projections passed')