on master help sign in
Check atom widening and nested Hoon imports
commitbe6d2a59807daff4c8ffd46f87427a2fd8116fd9 authoriko <mail@iko.soy> dateFri 30 Oct 2026, 17:39 (16 hours ago) parent51ce4d9
52 files changed+1556−178
README.md+1−1 docs/compiler.md+2−2 docs/development.md+1 docs/open-questions.md+1−1 docs/spec/decisions.md+1−1 docs/spec/grammar.md+1−1 docs/status.md+7−6 jibb-dev/lib/jibb-import.hoon+155−30 jibb-dev/lib/jibb.hoon+79−9 jibb-dev/lib/jibb/prelude.jibb+11 tests/golden/prelude-3g-basic/about.txt+4 tests/golden/prelude-3g-basic/source.jibb+60 tests/golden/prelude-3g-basic/tokens.txt+340 tests/golden/prelude-3g-basic/tree.txt+150 tests/golden/prelude-3g-basic/types.txt+15 tests/golden/prelude-list-unit/about.txt+1−1 tests/golden/types-import-sur/about.txt+4 tests/golden/types-import-sur/imports.txt+2 tests/golden/types-import-sur/source.jibb+3 tests/golden/types-import-sur/sur/fixture.txt+4 tests/golden/types-import-sur/tokens.txt+19 tests/golden/types-import-sur/tree.txt+10 tests/golden/types-import-sur/types.txt+3 tests/golden/types-partial-atom-widening/about.txt+4 tests/golden/types-partial-atom-widening/source.jibb+9 tests/golden/types-partial-atom-widening/tokens.txt+79 tests/golden/types-partial-atom-widening/tree.txt+35 tests/golden/types-partial-atom-widening/types.txt+10 tests/golden/types-partial-bare-atom/about.txt+4−3 tests/golden/types-partial-bare-atom/types.txt+2−2 tests/golden/types-partial-independent-atoms/about.txt+4 tests/golden/types-partial-independent-atoms/source.jibb+2 tests/golden/types-partial-independent-atoms/tokens.txt+21 tests/golden/types-partial-independent-atoms/tree.txt+11 tests/golden/types-partial-independent-atoms/types.txt+3 tests/golden/types-partial-mold-bare-aura/about.txt+2−2 tests/golden/types-partial-mold-bare-aura/types.txt+1−1 tests/golden/types-partial-union-edges/about.txt+3 tests/golden/types-partial-union-edges/source.jibb+24 tests/golden/types-partial-union-edges/tokens.txt+97 tests/golden/types-partial-union-edges/tree.txt+33 tests/golden/types-partial-union-edges/types.txt+9 tests/importer/shadow.txt+2 tests/importer/small.txt+4 tests/importer/tree.txt+6−1 tests/lib/jibb.hoon+152−106 tools/golden+36−7 tools/golden_case.py+34 tools/importer-test+1−1 tools/ship+36−3 tools/testdata/selftest+13 tools/testdata/ship-selftest+45
README.md+1−1
@@ -16,7 +16,7 @@ Milestone 1 of the doc's eight, the parser and the `%jibb` mark, is done; milest
1616
1717## Golden tests
1818
19−Each case, `tests/golden/<case>/`, holds `source.jibb`, `about.txt` (where it comes from, what it tests, the expected outcome), and the expected outputs: `tokens.txt` from the layout pass and `tree.txt` from the parser. A file holds the output plus one trailing newline. A case may also have a `path.txt` specifying its logical `/ui/.../*.jibb` path. An `expect-types:` line in `about.txt` opts it into the provisional `golden-types` checker output in `types.txt`; `--update` creates it.
19+Each case, `tests/golden/<case>/`, holds `source.jibb`, `about.txt` (where it comes from, what it tests, the expected outcome), and the expected outputs: `tokens.txt` from the layout pass and `tree.txt` from the parser. A file holds the output plus one trailing newline. A case may also have a `path.txt` specifying its logical `/ui/.../*.jibb` path. An `expect-types:` line in `about.txt` opts it into the provisional `golden-types` checker output in `types.txt`; `--update` creates it. A case can select Hoon molds in `imports.txt` and provide each module in `sur/<module>.txt`, as described in [docs/development.md](docs/development.md).
2020
2121Run them without a ship. This needs `urbit` on PATH and Python 3.
2222
docs/compiler.md+2−2
@@ -56,9 +56,9 @@ The core is split into chapters, `+| %name`, in this order:
5656| `%span-check` | `+check-spans`, which `+golden` runs on every tree, and `+check-spans-test` |
5757| `%type-inference` | The initial inference fragment and its unification helpers; not yet a module type checker |
5858
59−The inference fragment supports fixed auras, generic variables and gates, unfaced cells, 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. It does not yet check a module, its imports, faces, general patterns, deferred constraints, recursive or generic molds, dependency cycles or errors with both conflicting excerpts. 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 `@` and one-way widening into it, generic variables and gates, unfaced cells, 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. It does not yet check a module, its imports, faces, general patterns, deferred constraints, generalized atom constraints, recursive or generic molds, dependency cycles or errors with both conflicting excerpts. Function compatibility involving nested `@` remains 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.
6060
61−The separate `jibb-dev/lib/jibb-import.hoon` is an unfinished reader for selected Hoon type graphs. It handles named recursion, several collections, jar and jug in ordinary record fields, and direct `$^` unions whose source branches can be proved disjoint. Nested `$^`, nested collection arguments, ordered maps, general source-level disjointness, marks and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms and unfaced cells from caller-supplied reader results for declared `/-` imports; 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, built directly against zuse, and rejects locally shadowed names and subjects with unresolved Ford imports. 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 the corresponding ship test compose the importer with the inference fragment and compare a separate golden report.
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. Nested `$^`, nested ordered maps, general source-level disjointness, marks and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms and unfaced cells from caller-supplied reader results for declared `/-` imports; 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, built directly against zuse, and rejects locally shadowed names and subjects with unresolved Ford imports. 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 the corresponding ship test compose the importer with the inference fragment and compare a separate golden report.
6262
6363And the design notes:
6464
docs/development.md+1
@@ -97,6 +97,7 @@ A case is a folder `tests/golden/<name>/` holding:
9797- the expected outputs, `tokens.txt` and `tree.txt`, each the output plus one newline.
9898- optionally, `path.txt`, the logical `/ui/.../*.jibb` path to pass to the compiler; the source remains `source.jibb`.
9999- optionally, an `expect-types:` line in `about.txt` opts the case into `+golden-types`; `types.txt` holds its output plus one newline and `--update` creates it. A `types.txt` also opts in when the line is absent. This interface is provisional while the checker is under construction.
100+- optionally, `imports.txt` selects Hoon `/sur` molds, one `module mold` pair per line. Each module's source goes in `sur/<module>.txt` and is compiled against zuse by both runners. The selected reader results go to the partial checker; a type output is required. This currently handles only sources without Ford imports, not marks or Jibb module fixtures.
100101
101102Names say what a case is for:
102103
docs/open-questions.md+1−1
@@ -32,7 +32,7 @@ Found while writing [prompts/milestone-2.md](prompts/milestone-2.md) and checkin
323210. **Settled: navigation commands.** On 2026-10-30, @iko chose separate declarations for application paths and unchecked cords, with `link-unsafe`, `image-unsafe` and `go-unsafe` for the unchecked forms. `image-unsafe` takes a sized URL record. Both navigation declarations produce `[%go url=@t]`; `go` converts the application path to a cord including the app's base path.
333311. **Settled: stores and derived gates.** On 2026-10-30, @iko said a store's `+$ poke` is a declaration, like an API file's, not a mold; a derived name clashes with an import face; and an island watching a request whose case has a separate `scry=` path has a type error. The todo API's request is renamed `todo-by-id` so it does not clash with `/- todo`. The checker must account for the fact that a store's kind is determined by the type of `main`.
343412. **Settled: how to print a union without a name.** On 2026-10-30, @iko said to print its cases separated by spaces, as `%approve %deny`. This is print-only, not Jibb syntax.
35−13. **Settled: how to print a gate-free constraint.** On 2026-10-30, @iko agreed to print the type followed by `where A contains no gates`, as `$-([A A] ?) where A contains no gates`.
35+13. **Settled: how to print type constraints.** On 2026-10-30, @iko chose `$-([A A] A) where A is an atom` for an atom constraint and `$-([A A] ?) where A contains no gates` for a gate-free constraint.
363614. **Settled: how the prelude implements foundational operations.** On 2026-10-30, @iko chose private low-level primitives in the internal prelude module, with the public foundational gates implemented in Jibb on top of them.
373715. **Settled: unrestricted atoms and shared auras.** On 2026-10-30, @iko said `@` means any atom, independently at each occurrence, so Hoon `dime` and `pint` keep their bare-`@` fields. A specific atom such as `@ud` fits where `@` is expected; an `@` value needs a check to fit `@ud`. Shared atom types use one capital, with the atom constraint inferred from its body, as for `add` taking `[A A]` and returning `A`.
383816. **Settled: loobeans in union disjointness.** On 2026-10-30, @iko said `?` counts as its two atoms, `%.y` and `%.n`: it is disjoint from any cell and overlaps the constants 0 and 1.
docs/spec/decisions.md+1−1
@@ -26,7 +26,7 @@ The choices behind the Language tab, made on 2026-10-23; a later date marks a re
2626| Definitions | `++` for values, `+$` for molds; no `=/` | Decided |
2727| Unions | No `$?`: a `+$` with its cases on the lines below is a union, so every union written in Jibb has a name; one case is just that mold; a mold that isn't a union counts as a union of one case for tags and `\|=%tag`; a generic's `\|$` comes right after the `+$`'s name; tags anywhere; cases differ as nouns, with `?` treated as the two atoms `%.y` and `%.n`, disjoint from cells and overlapping constants 0 and 1, and `!!` or any cell with an empty position disjoint from every case; a tag literal or `~` waits for its union, and an unresolved one is an error | Decided 2026-10-30 |
2828| Printed unnamed unions | Print the cases separated by spaces, as `%approve %deny`; this is print-only, not Jibb syntax | Decided 2026-10-30 |
29−| Printed gate-free constraints | Print the type followed by `where A contains no gates`, as `$-([A A] ?) where A contains no gates` | Decided 2026-10-30 |
29+| Printed type constraints | Print an atom constraint as `$-([A A] A) where A is an atom` and a gate-free constraint as `$-([A A] ?) where A contains no gates` | Decided 2026-10-30 |
3030| Branching | `?-` only, loobeans included; exhaustive, with explicit catch-alls; covered arms are errors; failures say `!!` | Decided 2026-10-29 |
3131| Equality and negation | The gates `eq` and `not`, with Hoon's bitwise `not` exposed as `not.bit`; `eq`'s arguments and map and set keys contain no gates, even nested; the checker infers and generalizes that constraint; union matching never inspects a gate to distinguish cases | Decided 2026-10-30 |
3232| Special rules | No built-ins; type-directed rules are welcome, each listed in the Grammar tab | Decided 2026-10-29 |
docs/spec/grammar.md+1−1
@@ -132,7 +132,7 @@ A mold is only a type: never called on a noun, and with no default. Types are in
132132- **Opaque**: `poke`, `ask` and `qath`, built only by derived gates, `pure` and application-path literals. `(facts full diff …)` appears only in an API file's `paths`.
133133- **Identity**: recursive molds go by name and module.
134134
135−`eq`'s arguments and map and set keys must contain no gates, even nested inside another value. The checker infers this gate-free constraint on type variables and retains it when generalizing a `++`, so a generic helper that calls `eq` stays generic over gate-free types. Printed types show the constraint as `$-([A A] ?) where A contains no gates`. Union-case matching treats gates as opaque and never inspects a gate to distinguish cases.
135+`eq`'s arguments and map and set keys must contain no gates, even nested inside another value. The checker infers this gate-free constraint on type variables and retains it when generalizing a `++`, so a generic helper that calls `eq` stays generic over gate-free types. Printed types show the constraint as `$-([A A] ?) where A contains no gates`. An inferred atom constraint prints as `$-([A A] A) where A is an atom`. Union-case matching treats gates as opaque and never inspects a gate to distinguish cases.
136136
137137## Tag resolution
138138
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
1919
2020## Milestone 2: in progress
2121
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; a partial bridge passes selected Hoon atoms and unfaced cells into inference, while the reader and bridge do not cover every supported Hoon type. It reads named recursion, several collections, jar and jug in record fields, and direct `$^` unions whose cases can be proved disjoint. Nested `$^`, nested collection arguments, ordered maps, marks and general union disjointness remain unfinished. Collection recognition checks the originating core and fails closed on local shadows or unresolved Ford subjects; 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; a partial bridge passes selected Hoon atoms and unfaced cells into inference, while the reader and bridge do not cover every supported Hoon type. It reads named recursion, nested collections, direct ordered maps, and direct `$^` unions whose cases can be proved disjoint. Nested `$^`, nested ordered maps, marks and general union disjointness remain unfinished. The inference fragment supports unrestricted `@` and selected one-way widenings; generalized atom constraints still need work. Collection recognition checks the originating core and fails closed on local shadows or unresolved Ford subjects; 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.
2323
2424## Milestone 1: parser and mark
2525
@@ -37,8 +37,8 @@ What the plan asks for, and where it is:
3737
3838Besides the plan's list:
3939
40−- 393 golden cases: 177 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 393-case corpus passed under `urbit eval` in 20.0 s. The fake ship passed all 396 tests, including the importer, importer/checker bridge and unification checks, with 18.9 s for sync and 8.9 s for tests. The importer golden compares 35 projections; `tools/clay-fixtures` also built all seven example Hoon fixtures through Clay.
40+- 398 golden cases: 182 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 398-case corpus passed under `urbit eval` in 19.6 s. The fake ship passed all 401 tests, including the importer, importer/checker bridge and unification checks, with 18.2 s for sync and 10.5 s for tests. The importer golden compares 40 projections; `tools/clay-fixtures` also built all seven example Hoon fixtures through Clay.
4242- `tools/testdata/selftest` (19 checks) and `tools/testdata/ship-selftest` test the tools themselves.
4343- 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.
4444- 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).
@@ -55,14 +55,15 @@ Besides the plan's list:
5555| ab797a9 | 2026-10-30 | The 12 grammar decisions of 2026-10-30: four changed the parser, eight confirmed it |
5656| aad6ddb | 2026-10-30 | Drop `$?`; `+$` takes union cases below its name |
5757| 1dd92a6 | 2026-10-30 | Begin type inference and Hoon imports |
58−| This change | 2026-10-30 | Extend partial inference and importer, record type and prelude decisions |
58+| 51ce4d9 | 2026-10-30 | Extend partial inference and importer, record type and prelude decisions |
59+| This change | 2026-10-30 | Add atom widening, nested collections and case-local Hoon import fixtures |
5960
6061## Checking it
6162
6263On a machine set up as [development.md](development.md) says:
6364
6465```
65−tools/golden # 393 cases under urbit eval
66+tools/golden # 398 cases under urbit eval
6667tools/importer-test # the Hoon importer fixture projection
6768tools/type-import-test # the importer/checker bridge fixture
6869tools/hoon check-spans-test # prints <<>> when the span checker works
@@ -70,7 +71,7 @@ tools/testdata/selftest # the tools themselves
7071tools/doc-blocks docs/spec # the doc's examples are golden cases
7172tools/ship start
7273tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
73−tools/ship test # the same 393 cases as -test arms on the ship
74+tools/ship test # the same 398 cases as -test arms on the ship
7475tools/testdata/ship-selftest
7576tools/ship check-commit # |commit stores .jibb files
7677tools/clay-fixtures # example /sur files and marks build through Clay
jibb-dev/lib/jibb-import.hoon+155−30
@@ -13,8 +13,8 @@
1313:: A direct $^ is read from its original branches and accepted only when
1414:: their imported shapes prove disjoint. Nested $^ and some valid but
1515:: unprovably disjoint cases remain unsupported. Source-level overlap in
16−:: other unions, nested collection arguments, ordered maps, Ford import
17−:: provenance, marks and full error locations still need work.
16+:: other unions, nested ordered maps, Ford import provenance, marks and
17+:: full error locations still need work.
1818::
1919:: The checker has a small bridge for successful unfaced atom and cell
2020:: results; it rejects other importer shapes. Failures return %|; no
@@ -102,6 +102,11 @@
102102 =/ w=wing p.p.q.p.body
103103 ?: =(w ~[%jar]) [~ %jar]
104104 ?: =(w ~[%jug]) [~ %jug]
105+ ?: =(w ~[%map]) [~ %map]
106+ ?: =(w ~[%set]) [~ %set]
107+ ?: =(w ~[%qeu]) [~ %qeu]
108+ ?: =(w ~[%list]) [~ %list]
109+ ?: =(w ~[%unit]) [~ %unit]
105110 ~
106111::
107112++ hold-alias
@@ -112,6 +117,77 @@
112117::
113118:: Reconcile source aliases with the expanded type in corresponding
114119:: cells and fields. Return an error unless every alias is accounted for.
120+++ recover-spec
121+ |= [src=spec out=imported]
122+ ^- (each imported @t)
123+ ?. (has-hidden-alias src) [%& out]
124+ ?. ?=([%make [%wing *] *] src)
125+ [%| 'nested collection arguments need source-aware import']
126+ =/ w=wing p.p.src
127+ =/ name=term
128+ ?: =(w ~[%jar]) %jar
129+ ?: =(w ~[%jug]) %jug
130+ ?: =(w ~[%map]) %map
131+ ?: =(w ~[%set]) %set
132+ ?: =(w ~[%qeu]) %qeu
133+ ?: =(w ~[%list]) %list
134+ ?: =(w ~[%unit]) %unit
135+ %$
136+ ?: =(%$ name) [%| 'nested collection arguments need source-aware import']
137+ =/ original=(each imported @t)
138+ ?: |(=(%jar name) =(%jug name))
139+ ?. ?=([%apply %map [* [%apply * [* ~]] ~]] out)
140+ [%| 'nested collection arguments need source-aware import']
141+ =/ inn i.args.i.t.args.out
142+ ?. |(&(?=(%jar name) ?=(%list name.i.t.args.out)) &(?=(%jug name) ?=(%set name.i.t.args.out)))
143+ [%| 'nested collection arguments need source-aware import']
144+ [%& [%apply name ~[i.args.out inn]]]
145+ [%& out]
146+ ?. ?=([%& *] original) original
147+ =/ fixed=imported p.original
148+ ?. ?=([%apply *] fixed) [%| 'nested collection arguments need source-aware import']
149+ ?. =(name name.fixed) [%| 'nested collection arguments need source-aware import']
150+ =/ args (recover-specs q.src args.fixed)
151+ ?- args
152+ [%| *] args
153+ [%& *] [%& [%apply name p.args]]
154+ ==
155+::
156+++ recover-specs
157+ |= [src=(list spec) args=(list imported)]
158+ ^- (each (list imported) @t)
159+ ?~ src ?~(args [%& ~] [%| 'collection argument count mismatch'])
160+ ?~ args [%| 'collection argument count mismatch']
161+ =/ first (recover-spec i.src i.args)
162+ ?- first
163+ [%| *] [%| p.first]
164+ [%& *]
165+ =/ rest $(src t.src, args t.args)
166+ ?- rest
167+ [%| *] rest
168+ [%& *] [%& [p.first p.rest]]
169+ ==
170+ ==
171+::
172+++ recover-hoons
173+ |= [src=(list hoon) args=(list imported)]
174+ ^- (each (list imported) @t)
175+ ?~ src ?~(args [%& ~] [%| 'collection argument count mismatch'])
176+ ?~ args [%| 'collection argument count mismatch']
177+ =/ first=(each imported @t)
178+ ?. (has-hidden-alias i.src) [%& i.args]
179+ ?. ?=([%ktcl *] i.src) [%| 'nested collection arguments need source-aware import']
180+ (recover-spec p.i.src i.args)
181+ ?- first
182+ [%| *] [%| p.first]
183+ [%& *]
184+ =/ rest $(src t.src, args t.args)
185+ ?- rest
186+ [%| *] rest
187+ [%& *] [%& [p.first p.rest]]
188+ ==
189+ ==
190+::
115191++ recover-alias
116192 |= [src=hoon out=imported]
117193 ^- (each imported @t)
@@ -141,25 +217,28 @@
141217 [%cncl *]
142218 =/ alias (source-alias src)
143219 ?~ alias [%| 'a nested collection alias needs source-aware import']
144− ?: (gth (alias-count src) 1)
145− [%| 'nested collection arguments need source-aware import']
146− ?. ?=([%apply %map [* [%apply * [* ~]] ~]] out)
147− [%| 'a nested collection alias needs source-aware import']
148− =/ inner i.args.i.t.args.out
149− ?: &(?=(%jar u.alias) ?=(%list name.i.t.args.out))
150− [%& [%apply %jar ~[i.args.out inner]]]
151− ?: &(?=(%jug u.alias) ?=(%set name.i.t.args.out))
152− [%& [%apply %jug ~[i.args.out inner]]]
153− [%| 'a nested collection alias needs source-aware import']
220+ =/ original=(each imported @t)
221+ ?: |(=(%jar u.alias) =(%jug u.alias))
222+ ?. ?=([%apply %map [* [%apply * [* ~]] ~]] out)
223+ [%| 'a nested collection alias needs source-aware import']
224+ =/ inner i.args.i.t.args.out
225+ ?. |(&(?=(%jar u.alias) ?=(%list name.i.t.args.out)) &(?=(%jug u.alias) ?=(%set name.i.t.args.out)))
226+ [%| 'a nested collection alias needs source-aware import']
227+ [%& [%apply u.alias ~[i.args.out inner]]]
228+ [%& out]
229+ ?. ?=([%& *] original) original
230+ =/ fixed=imported p.original
231+ ?. ?=([%apply *] fixed) [%| 'a nested collection alias needs source-aware import']
232+ ?. =(name.fixed u.alias) [%| 'a nested collection alias needs source-aware import']
233+ ?> ?=([%tsgr *] p.src)
234+ ?> ?=([%cncl *] q.p.src)
235+ =/ args (recover-hoons q.q.p.src args.fixed)
236+ ?- args
237+ [%| *] [%| p.args]
238+ [%& *] [%& [%apply u.alias p.args]]
239+ ==
154240 ==
155241::
156−++ alias-count
157− |= h=*
158− ^- @ud
159− ?: |(=(h [%wing ~[%jar]]) =(h [%wing ~[%jug]]) =(h [%wing ~[%mop]])) 1
160− ?@ h 0
161− (add $(h -.h) $(h +.h))
162−::
163242++ has-hidden-alias
164243 |= h=*
165244 ^- ?
@@ -282,6 +361,34 @@
282361 ?@ src |
283362 |($(src -.src) $(src +.src))
284363::
364+++ mop-arguments-raw
365+ |= h=type
366+ ^- (unit [key=type value=type])
367+ ?. ?=([%hold *] h) ~
368+ =/ original=hoon q.h
369+ ?. ?=([%tsls [%note * *] *] original) ~
370+ =/ body=hoon q.p.original
371+ ?. ?=([%cncl *] body) ~
372+ ?. ?=([%tsgr *] p.body) ~
373+ =/ b=hoon q.p.body
374+ ?. ?=([%cncl *] b) ~
375+ ?. ?=([%cncl *] p.b) ~
376+ ?. ?=([%wing *] p.p.b) ~
377+ ?. =(p.p.p.b ~[%mop]) ~
378+ =/ specs=(list spec) ;;((list spec) q.p.b)
379+ ?. ?=([* [* ~]] specs) ~
380+ [~ [(~(play ut p.h) [%kttr i.specs]) (~(play ut p.h) [%kttr i.t.specs])]]
381+::
382+++ mop-arguments
383+ |= h=type
384+ ^- (unit [key=type value=type])
385+ =/ attempt=(each (unit [key=type value=type]) tang)
386+ (mule |.((mop-arguments-raw h)))
387+ ?- attempt
388+ [%& *] p.attempt
389+ [%| *] ~
390+ ==
391+::
285392++ match-signature
286393 |= [h=hoon sig=signatures]
287394 ^- (unit term)
@@ -340,6 +447,13 @@
340447 [%bad 'Hoon collection provenance is unavailable or shadowed']
341448 ?: &((source-uses q.typ %jug) !(alias-safe context %jug))
342449 [%bad 'Hoon collection provenance is unavailable or shadowed']
450+ ?: &((source-uses q.typ %mop) !(alias-safe context %mop))
451+ [%bad 'Hoon collection provenance is unavailable or shadowed']
452+ =/ mop (mop-arguments typ)
453+ ?^ mop
454+ [%apply %mop ~[$(typ key.u.mop) $(typ value.u.mop)]]
455+ ?: (source-uses q.typ %mop)
456+ [%bad 'a nested Hoon mop needs source-aware import']
343457 =/ branches (cell-branches typ)
344458 ?^ branches
345459 =/ first $(typ left.u.branches, seen [[typ nm] seen])
@@ -363,16 +477,13 @@
363477 [%& *] p.corrected
364478 [%| *] [%bad p.corrected]
365479 ==
366− ?: (gth (alias-count q.typ) 1)
367− [%bad 'nested collection arguments need source-aware import']
368− ?. ?=([%apply %map [* [%apply * [* ~]] ~]] body)
480+ ?. ?=([%tsls [%note * *] *] q.typ)
369481 [%bad 'a Hoon collection alias could not be recovered']
370− =/ inner i.args.i.t.args.body
371− ?: &(?=(%jar u.alias) ?=(%list name.i.t.args.body))
372− [%apply %jar ~[i.args.body inner]]
373− ?: &(?=(%jug u.alias) ?=(%set name.i.t.args.body))
374− [%apply %jug ~[i.args.body inner]]
375− [%bad 'a Hoon collection alias could not be recovered']
482+ =/ corrected (recover-alias q.p.q.typ body)
483+ ?- corrected
484+ [%& *] p.corrected
485+ [%| *] [%bad p.corrected]
486+ ==
376487 ==
377488::
378489++ first-bad
@@ -464,8 +575,15 @@
464575 [%cell [%face %values [%apply %jar ~[[%atom %ud ~] [%atom %t ~]]]] [%face %cache [%apply %jug ~[[%atom %ud ~] [%atom %t ~]]]]]
465576 =/ errors ?: =((sample %paired-aliases) [%& expect-paired]) errors
466577 ['multiple collection aliases are preserved' errors]
467− =/ errors ?: =((sample %nested-alias) [%| 'nested collection arguments need source-aware import']) errors
468− ['nested collection arguments remain unsupported' errors]
578+ =/ expect-nested-alias=imported
579+ [%apply %jar ~[[%atom %ud ~] [%apply %jug ~[[%atom %ud ~] [%atom %t ~]]]]]
580+ =/ errors ?: =((sample %nested-alias) [%& expect-nested-alias]) errors
581+ ['nested collection arguments preserve names' errors]
582+ =/ expect-mop=imported [%apply %mop ~[[%atom %ud ~] [%atom %t ~]]]
583+ =/ errors ?: =((sample %mop-test) [%& expect-mop]) errors
584+ ['ordered map name and arguments' errors]
585+ =/ errors ?: =((sample %nested-mop) [%| 'a nested Hoon mop needs source-aware import']) errors
586+ ['nested ordered map remains unsupported' errors]
469587 =/ errors ?: =((sample %signed) [%| 'signed and float auras cannot be imported']) errors
470588 ['signed aura rejected' errors]
471589 =/ errors ?: =((sample %float) [%| 'signed and float auras cannot be imported']) errors
@@ -480,6 +598,8 @@
480598 ['disjoint cell union' errors]
481599 =/ errors ?: =((sample %invalid-cell) [%| 'a Hoon $^ union has overlapping cases']) errors
482600 ['overlapping cell union is rejected' errors]
601+ =/ errors ?: =((shad %mm) [%| 'Hoon collection provenance is unavailable or shadowed']) errors
602+ ['local mop shadow is rejected' errors]
483603 =/ errors ?: =((shad %aa) [%| 'Hoon collection provenance is unavailable or shadowed']) errors
484604 ['local jar shadow is rejected' errors]
485605 =/ errors ?: =((shad %bb) [%| 'Hoon collection provenance is unavailable or shadowed']) errors
@@ -571,6 +691,10 @@
571691 (crip "nested-jar: {(show-result (sample %nested-jar))}")
572692 (crip "paired-aliases: {(show-result (sample %paired-aliases))}")
573693 (crip "nested-alias: {(show-result (sample %nested-alias))}")
694+ (crip "compound: {(show-result (sample %compound))}")
695+ (crip "compound-fields: {(show-result (sample %compound-fields))}")
696+ (crip "mop: {(show-result (sample %mop-test))}")
697+ (crip "nested-mop: {(show-result (sample %nested-mop))}")
574698 (crip "signed: {(show-result (sample %signed))}")
575699 (crip "float: {(show-result (sample %float))}")
576700 (crip "gate: {(show-result (sample %gate-test))}")
@@ -584,6 +708,7 @@
584708 (crip "chapter-wrapped-hit: {?:(=((chapter-has [~ chapter-tree] %jar) [~ &]) "yes" "no")}")
585709 (crip "chapter-direct-miss: {?:(=((chapter-has chapter-tree %jug) [~ &]) "yes" "no")}")
586710 (crip "chapter-wrapped-miss: {?:(=((chapter-has [~ chapter-tree] %jug) [~ &]) "yes" "no")}")
711+ (crip "shadow-mop: {(show-result (shad %mm))}")
587712 (crip "shadow-jar: {(show-result (shad %aa))}")
588713 (crip "shadow-jug: {(show-result (shad %bb))}")
589714 (crip "no-provenance: {(show-result (read-mold %small %jar-test (~(play ut sc) (ream '*jar-test'))))}")
jibb-dev/lib/jibb.hoon+79−9
@@ -4592,14 +4592,17 @@
45924592:: capital variables in molds share one allocation within the definition.
45934593:: Decimal literals have atom-only variables; until their constraints
45944594:: can be printed and generalized, an unresolved one is unsupported.
4595−:: Bare @ is unsupported until its unrestricted-atom rule is implemented.
4596−:: Only unfaced cells are represented here.
4595+:: Bare @ is a separate unrestricted atom type. A directional fit check
4596+:: permits concrete atoms to widen to it, never the reverse. A fit that
4597+:: needs a not-yet-implemented constraint remains unsupported. Only
4598+:: unfaced cells are represented here.
45974599::
45984600+$ itype
45994601 $~ [%var 0]
46004602 $% [%var id=@ud]
46014603 [%avar id=@ud]
46024604 [%atom aura=@ta]
4605+ [%any-atom ~]
46034606 [%flag ~]
46044607 [%fn sample=itype product=itype]
46054608 [%cell hed=itype tal=itype]
@@ -4636,6 +4639,7 @@
46364639 %var =(n id.t)
46374640 %avar =(n id.t)
46384641 %atom |
4642+ %any-atom |
46394643 %flag |
46404644 %fn |($(t sample.t) $(t product.t))
46414645 %cell |($(t hed.t) $(t tal.t))
@@ -4676,6 +4680,59 @@
46764680 $(a tal.a, b tal.b, sub u.first)
46774681 ~
46784682::
4683+:: +itype-fit: one-way widening from an actual type to an expected type
4684+::
4685+:: Variables that would need a generalized atom constraint, and
4686+:: function compatibility involving unrestricted @, remain unknown.
4687+::
4688++$ ifit $%([%ok sub=isub] [%bad ~] [%unknown ~])
4689+++ itype-has-any-atom
4690+ |= [t=itype sub=isub]
4691+ ^- ?
4692+ =. t (itype-walk t sub)
4693+ ?- -.t
4694+ %var |
4695+ %avar |
4696+ %atom |
4697+ %any-atom &
4698+ %flag |
4699+ %fn |($(t sample.t) $(t product.t))
4700+ %cell |($(t hed.t) $(t tal.t))
4701+ ==
4702+::
4703+++ itype-fit
4704+ |= [actual=itype expected=itype sub=isub]
4705+ ^- ifit
4706+ =. actual (itype-walk actual sub)
4707+ =. expected (itype-walk expected sub)
4708+ ?: =(actual expected) [%ok sub]
4709+ ?: ?=(%any-atom -.expected)
4710+ ?: |(?=(%atom -.actual) ?=(%avar -.actual) ?=(%flag -.actual)) [%ok sub]
4711+ ?: ?=(%var -.actual) [%unknown ~]
4712+ [%bad ~]
4713+ ?: ?=(%any-atom -.actual)
4714+ ?: ?=(%var -.expected)
4715+ =/ unified=(unit isub) (itype-unify actual expected sub)
4716+ ?~ unified [%bad ~]
4717+ [%ok u.unified]
4718+ ?: ?=(%avar -.expected) [%unknown ~]
4719+ [%bad ~]
4720+ ?: &(?=(%cell -.actual) ?=(%cell -.expected))
4721+ =/ first=ifit $(actual hed.actual, expected hed.expected)
4722+ ?. ?=(%ok -.first) first
4723+ $(actual tal.actual, expected tal.expected, sub sub.first)
4724+ ?: &(?=(%var -.actual) (itype-has-any-atom expected sub))
4725+ [%unknown ~]
4726+ ?: |(?=(%var -.actual) ?=(%var -.expected))
4727+ =/ unified=(unit isub) (itype-unify actual expected sub)
4728+ ?~ unified [%bad ~]
4729+ [%ok u.unified]
4730+ ?: |((itype-has-any-atom actual sub) (itype-has-any-atom expected sub))
4731+ [%unknown ~]
4732+ =/ unified=(unit isub) (itype-unify actual expected sub)
4733+ ?~ unified [%bad ~]
4734+ [%ok u.unified]
4735+::
46794736++ itype-unify-test
46804737 ^- (list tape)
46814738 =/ a=itype [%var 0]
@@ -4745,6 +4802,7 @@
47454802 %var ~[id.t]
47464803 %avar ~[id.t]
47474804 %atom ~
4805+ %any-atom ~
47484806 %flag ~
47494807 %fn (weld $(t sample.t) $(t product.t))
47504808 %cell (weld $(t hed.t) $(t tal.t))
@@ -4769,6 +4827,7 @@
47694827 u.found
47704828 %avar t
47714829 %atom t
4830+ %any-atom t
47724831 %flag t
47734832 %fn [%fn $(t sample.t) $(t product.t)]
47744833 %cell [%cell $(t hed.t) $(t tal.t)]
@@ -4872,7 +4931,7 @@
48724931 ^- (unit [typ=itype state=istate])
48734932 ?- -.sh
48744933 %aura
4875− ?: =(0 aura.sh) ~
4934+ ?: =(0 aura.sh) `[[%any-atom ~] state]
48764935 `[[%atom aura.sh] state]
48774936 %flag `[[%flag ~] state]
48784937 %cell (infer-simple-fields fields.sh state)
@@ -4993,16 +5052,20 @@
49935052 =/ right=iresult $(e val.y, state state.p.left)
49945053 ?: ?=(%| -.right) right
49955054 =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
4996− ?~ joined [%| "branch arms have incompatible types"]
5055+ ?~ joined
5056+ ?: |((itype-has-any-atom typ.p.left sub.state.p.right) (itype-has-any-atom typ.p.right sub.state.p.right))
5057+ [%| "branch widening is not supported by partial inference"]
5058+ [%| "branch arms have incompatible types"]
49975059 [%& typ.p.left state.p.right(sub u.joined)]
49985060 %cast
49995061 =/ target=(unit [typ=itype state=istate]) (infer-simple-shape shape.e state)
50005062 ?~ target [%| "cast mold is not supported by partial inference"]
50015063 =/ value=iresult $(e val.e, state state.u.target)
50025064 ?: ?=(%| -.value) value
5003− =/ uni=(unit isub) (itype-unify typ.u.target typ.p.value sub.state.p.value)
5004− ?~ uni [%| "cast mold and expression type do not unify"]
5005− [%& typ.u.target state.p.value(sub u.uni)]
5065+ =/ fit=ifit (itype-fit typ.p.value typ.u.target sub.state.p.value)
5066+ ?: ?=(%unknown -.fit) [%| "cast constraint is not supported by partial inference"]
5067+ ?: ?=(%bad -.fit) [%| "cast mold and expression type do not unify"]
5068+ [%& typ.u.target state.p.value(sub sub.fit)]
50065069 %crash [%& [%var next.state] state(next +(next.state))]
50075070 %gate
50085071 =/ sam=isample-result (infer-sample sample.e env state)
@@ -5024,9 +5087,14 @@
50245087 =/ arg=iresult $(e i.args.e, state state.p.head)
50255088 ?: ?=(%| -.arg) arg
50265089 =/ st=istate state.p.arg
5090+ =/ ht=itype (itype-walk typ.p.head sub.st)
5091+ ?: ?=(%fn -.ht)
5092+ =/ fit=ifit (itype-fit typ.p.arg sample.ht sub.st)
5093+ ?: ?=(%unknown -.fit) [%| "call constraint is not supported by partial inference"]
5094+ ?: ?=(%bad -.fit) [%| "call's sample and argument types do not unify"]
5095+ [%& product.ht st(sub sub.fit)]
50275096 =/ result=itype [%var next.st]
5028− =/ uni=(unit isub)
5029− (itype-unify typ.p.head [%fn typ.p.arg result] sub.st)
5097+ =/ uni=(unit isub) (itype-unify ht [%fn typ.p.arg result] sub.st)
50305098 ?~ uni [%| "call's sample and argument types do not unify"]
50315099 [%& result st(next +(next.st), sub u.uni)]
50325100 * [%| "expression is not supported by partial inference"]
@@ -5086,6 +5154,7 @@
50865154 "T{<id.t>}"
50875155 %avar "@"
50885156 %atom "@{(trip aura.t)}"
5157+ %any-atom "@"
50895158 %flag "?"
50905159 %fn "$-({$(t sample.t)} {$(t product.t)})"
50915160 %cell "[{$(t hed.t)} {$(t tal.t)}]"
@@ -5101,6 +5170,7 @@
51015170 %avar &
51025171 %var |
51035172 %atom |
5173+ %any-atom |
51045174 %flag |
51055175 %fn |($(t sample.t) $(t product.t))
51065176 %cell |($(t hed.t) $(t tal.t))
jibb-dev/lib/jibb/prelude.jibb+11
@@ -47,3 +47,14 @@
4747 ?- xs
4848 ~ ~
4949 [item rest] [(f item) (turn rest f)]
50+
51++$ dime [p=@ta q=@]
52+
53++$ hair [p=@ud q=@ud]
54+
55++$ pint [p=[p=@ q=@] q=[p=@ q=@]]
56+
57++$ coin
58+ [%$ p=dime]
59+ [%blob p=*]
60+ [%many p=(list coin)]
tests/golden/prelude-3g-basic/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Overview, Prelude: "The exported inventory includes all names from the Hoon library sections listed below, excluding the groups explicitly left out"; 3g includes `dime`, `hair`, `pint` and `coin`.
2+tests: The prelude's 3g atom and position molds, and the recursive `coin` union with its `%$` term case; bare `@` fields accept atoms independently.
3+expect: parses
4+expect-types: a partial inference report, not a checked module; union-case disjointness is checked but the molds remain unchecked
tests/golden/prelude-3g-basic/source.jibbnew file+60
@@ -0,0 +1,60 @@
1+:: Initial prelude functions. The rest of the inventory is still to come.
2+++ same |= x=A x
3+
4+++ head |= p=[A B]
5+ ?- p
6+ [a b] a
7+
8+++ tail |= p=[A B]
9+ ?- p
10+ [a b] b
11+
12+++ not |= b=?
13+ ?- b
14+ %.y %.n
15+ %.n %.y
16+
17++$ list |$ [A]
18+ ~
19+ [i=A t=(list A)]
20+
21++$ unit |$ [A]
22+ ~
23+ [~ u=A]
24+
25+++ fall |= args=[(unit A) A]
26+ ?- args
27+ [maybe fallback]
28+ ?- maybe
29+ ~ fallback
30+ [~ value] value
31+
32+++ need |= maybe=(unit A)
33+ ?- maybe
34+ ~ !!
35+ [~ value] value
36+
37+++ weld |= args=[(list A) (list A)]
38+ ?- args
39+ [xs ys]
40+ ?- xs
41+ ~ ys
42+ [item rest] [item (weld rest ys)]
43+
44+++ turn |= args=[(list A) $-(A B)]
45+ ?- args
46+ [xs f]
47+ ?- xs
48+ ~ ~
49+ [item rest] [(f item) (turn rest f)]
50+
51++$ dime [p=@ta q=@]
52+
53++$ hair [p=@ud q=@ud]
54+
55++$ pint [p=[p=@ q=@] q=[p=@ q=@]]
56+
57++$ coin
58+ [%$ p=dime]
59+ [%blob p=*]
60+ [%many p=(list coin)]
tests/golden/prelude-3g-basic/tokens.txtnew file+340
@@ -0,0 +1,340 @@
1+2:1 glyph ++
2+2:4 name same
3+2:9 glyph |=
4+2:12 name x
5+2:13 tight glyph =
6+2:14 tight tvar A
7+2:16 name x
8+4:1 NEWLINE
9+4:1 glyph ++
10+4:4 name head
11+4:9 glyph |=
12+4:12 name p
13+4:13 tight glyph =
14+4:14 tight glyph [
15+4:15 tight tvar A
16+4:17 tvar B
17+4:18 tight glyph ]
18+5:3 INDENT
19+5:3 glyph ?-
20+5:6 name p
21+6:5 INDENT
22+6:5 glyph [
23+6:6 tight name a
24+6:8 name b
25+6:9 tight glyph ]
26+6:11 name a
27+8:1 DEDENT
28+8:1 DEDENT
29+8:1 NEWLINE
30+8:1 glyph ++
31+8:4 name tail
32+8:9 glyph |=
33+8:12 name p
34+8:13 tight glyph =
35+8:14 tight glyph [
36+8:15 tight tvar A
37+8:17 tvar B
38+8:18 tight glyph ]
39+9:3 INDENT
40+9:3 glyph ?-
41+9:6 name p
42+10:5 INDENT
43+10:5 glyph [
44+10:6 tight name a
45+10:8 name b
46+10:9 tight glyph ]
47+10:11 name b
48+12:1 DEDENT
49+12:1 DEDENT
50+12:1 NEWLINE
51+12:1 glyph ++
52+12:4 name not
53+12:8 glyph |=
54+12:11 name b
55+12:12 tight glyph =
56+12:13 tight glyph ?
57+13:3 INDENT
58+13:3 glyph ?-
59+13:6 name b
60+14:5 INDENT
61+14:5 lit %.y
62+14:9 lit %.n
63+15:5 NEWLINE
64+15:5 lit %.n
65+15:9 lit %.y
66+17:1 DEDENT
67+17:1 DEDENT
68+17:1 NEWLINE
69+17:1 glyph +$
70+17:4 name list
71+17:9 glyph |$
72+17:12 glyph [
73+17:13 tight tvar A
74+17:14 tight glyph ]
75+18:3 INDENT
76+18:3 lit ~
77+19:3 NEWLINE
78+19:3 glyph [
79+19:4 tight name i
80+19:5 tight glyph =
81+19:6 tight tvar A
82+19:8 name t
83+19:9 tight glyph =
84+19:10 tight glyph (
85+19:11 tight name list
86+19:16 tvar A
87+19:17 tight glyph )
88+19:18 tight glyph ]
89+21:1 DEDENT
90+21:1 NEWLINE
91+21:1 glyph +$
92+21:4 name unit
93+21:9 glyph |$
94+21:12 glyph [
95+21:13 tight tvar A
96+21:14 tight glyph ]
97+22:3 INDENT
98+22:3 lit ~
99+23:3 NEWLINE
100+23:3 glyph [
101+23:4 tight lit ~
102+23:6 name u
103+23:7 tight glyph =
104+23:8 tight tvar A
105+23:9 tight glyph ]
106+25:1 DEDENT
107+25:1 NEWLINE
108+25:1 glyph ++
109+25:4 name fall
110+25:9 glyph |=
111+25:12 name args
112+25:16 tight glyph =
113+25:17 tight glyph [
114+25:18 tight glyph (
115+25:19 tight name unit
116+25:24 tvar A
117+25:25 tight glyph )
118+25:27 tvar A
119+25:28 tight glyph ]
120+26:3 INDENT
121+26:3 glyph ?-
122+26:6 name args
123+27:5 INDENT
124+27:5 glyph [
125+27:6 tight name maybe
126+27:12 name fallback
127+27:20 tight glyph ]
128+28:7 INDENT
129+28:7 glyph ?-
130+28:10 name maybe
131+29:9 INDENT
132+29:9 lit ~
133+29:11 name fallback
134+30:9 NEWLINE
135+30:9 glyph [
136+30:10 tight lit ~
137+30:12 name value
138+30:17 tight glyph ]
139+30:19 name value
140+32:1 DEDENT
141+32:1 DEDENT
142+32:1 DEDENT
143+32:1 DEDENT
144+32:1 NEWLINE
145+32:1 glyph ++
146+32:4 name need
147+32:9 glyph |=
148+32:12 name maybe
149+32:17 tight glyph =
150+32:18 tight glyph (
151+32:19 tight name unit
152+32:24 tvar A
153+32:25 tight glyph )
154+33:3 INDENT
155+33:3 glyph ?-
156+33:6 name maybe
157+34:5 INDENT
158+34:5 lit ~
159+34:7 glyph !!
160+35:5 NEWLINE
161+35:5 glyph [
162+35:6 tight lit ~
163+35:8 name value
164+35:13 tight glyph ]
165+35:15 name value
166+37:1 DEDENT
167+37:1 DEDENT
168+37:1 NEWLINE
169+37:1 glyph ++
170+37:4 name weld
171+37:9 glyph |=
172+37:12 name args
173+37:16 tight glyph =
174+37:17 tight glyph [
175+37:18 tight glyph (
176+37:19 tight name list
177+37:24 tvar A
178+37:25 tight glyph )
179+37:27 glyph (
180+37:28 tight name list
181+37:33 tvar A
182+37:34 tight glyph )
183+37:35 tight glyph ]
184+38:3 INDENT
185+38:3 glyph ?-
186+38:6 name args
187+39:5 INDENT
188+39:5 glyph [
189+39:6 tight name xs
190+39:9 name ys
191+39:11 tight glyph ]
192+40:7 INDENT
193+40:7 glyph ?-
194+40:10 name xs
195+41:9 INDENT
196+41:9 lit ~
197+41:11 name ys
198+42:9 NEWLINE
199+42:9 glyph [
200+42:10 tight name item
201+42:15 name rest
202+42:19 tight glyph ]
203+42:21 glyph [
204+42:22 tight name item
205+42:27 glyph (
206+42:28 tight name weld
207+42:33 name rest
208+42:38 name ys
209+42:40 tight glyph )
210+42:41 tight glyph ]
211+44:1 DEDENT
212+44:1 DEDENT
213+44:1 DEDENT
214+44:1 DEDENT
215+44:1 NEWLINE
216+44:1 glyph ++
217+44:4 name turn
218+44:9 glyph |=
219+44:12 name args
220+44:16 tight glyph =
221+44:17 tight glyph [
222+44:18 tight glyph (
223+44:19 tight name list
224+44:24 tvar A
225+44:25 tight glyph )
226+44:27 glyph $-(
227+44:30 tight tvar A
228+44:32 tvar B
229+44:33 tight glyph )
230+44:34 tight glyph ]
231+45:3 INDENT
232+45:3 glyph ?-
233+45:6 name args
234+46:5 INDENT
235+46:5 glyph [
236+46:6 tight name xs
237+46:9 name f
238+46:10 tight glyph ]
239+47:7 INDENT
240+47:7 glyph ?-
241+47:10 name xs
242+48:9 INDENT
243+48:9 lit ~
244+48:11 lit ~
245+49:9 NEWLINE
246+49:9 glyph [
247+49:10 tight name item
248+49:15 name rest
249+49:19 tight glyph ]
250+49:21 glyph [
251+49:22 tight glyph (
252+49:23 tight name f
253+49:25 name item
254+49:29 tight glyph )
255+49:31 glyph (
256+49:32 tight name turn
257+49:37 name rest
258+49:42 name f
259+49:43 tight glyph )
260+49:44 tight glyph ]
261+51:1 DEDENT
262+51:1 DEDENT
263+51:1 DEDENT
264+51:1 DEDENT
265+51:1 NEWLINE
266+51:1 glyph +$
267+51:4 name dime
268+51:9 glyph [
269+51:10 tight name p
270+51:11 tight glyph =
271+51:12 tight aura @ta
272+51:16 name q
273+51:17 tight glyph =
274+51:18 tight aura @
275+51:19 tight glyph ]
276+53:1 NEWLINE
277+53:1 glyph +$
278+53:4 name hair
279+53:9 glyph [
280+53:10 tight name p
281+53:11 tight glyph =
282+53:12 tight aura @ud
283+53:16 name q
284+53:17 tight glyph =
285+53:18 tight aura @ud
286+53:21 tight glyph ]
287+55:1 NEWLINE
288+55:1 glyph +$
289+55:4 name pint
290+55:9 glyph [
291+55:10 tight name p
292+55:11 tight glyph =
293+55:12 tight glyph [
294+55:13 tight name p
295+55:14 tight glyph =
296+55:15 tight aura @
297+55:17 name q
298+55:18 tight glyph =
299+55:19 tight aura @
300+55:20 tight glyph ]
301+55:22 name q
302+55:23 tight glyph =
303+55:24 tight glyph [
304+55:25 tight name p
305+55:26 tight glyph =
306+55:27 tight aura @
307+55:29 name q
308+55:30 tight glyph =
309+55:31 tight aura @
310+55:32 tight glyph ]
311+55:33 tight glyph ]
312+57:1 NEWLINE
313+57:1 glyph +$
314+57:4 name coin
315+58:3 INDENT
316+58:3 glyph [
317+58:4 tight lit %$
318+58:7 name p
319+58:8 tight glyph =
320+58:9 tight name dime
321+58:13 tight glyph ]
322+59:3 NEWLINE
323+59:3 glyph [
324+59:4 tight lit %blob
325+59:10 name p
326+59:11 tight glyph =
327+59:12 tight glyph *
328+59:13 tight glyph ]
329+60:3 NEWLINE
330+60:3 glyph [
331+60:4 tight lit %many
332+60:10 name p
333+60:11 tight glyph =
334+60:12 tight glyph (
335+60:13 tight name list
336+60:18 name coin
337+60:22 tight glyph )
338+60:23 tight glyph ]
339+60:24 DEDENT
340+60:24 NEWLINE
tests/golden/prelude-3g-basic/tree.txtnew file+150
@@ -0,0 +1,150 @@
1+(module
2+ (value 2:1 same
3+ (gate 2:9
4+ (face 2:12 x (tvar 2:14 A))
5+ (wing 2:16 x)))
6+ (value 4:1 head
7+ (gate 4:9
8+ (face 4:12 p
9+ (cell 4:14 (tvar 4:15 A) (tvar 4:17 B)))
10+ (body 5:3
11+ (branch 5:3
12+ (wing 5:6 p)
13+ (arm 6:5
14+ (cell 6:5 (bind 6:6 a) (bind 6:8 b))
15+ (wing 6:11 a))))))
16+ (value 8:1 tail
17+ (gate 8:9
18+ (face 8:12 p
19+ (cell 8:14 (tvar 8:15 A) (tvar 8:17 B)))
20+ (body 9:3
21+ (branch 9:3
22+ (wing 9:6 p)
23+ (arm 10:5
24+ (cell 10:5 (bind 10:6 a) (bind 10:8 b))
25+ (wing 10:11 b))))))
26+ (value 12:1 not
27+ (gate 12:8
28+ (face 12:11 b (flag 12:13))
29+ (body 13:3
30+ (branch 13:3
31+ (wing 13:6 b)
32+ (arm 14:5 (lit 14:5 %.y) (lit 14:9 %.n))
33+ (arm 15:5 (lit 15:5 %.n) (lit 15:9 %.y))))))
34+ (mold 17:1 list
35+ (generic 17:9 A
36+ (union 18:3
37+ (const 18:3 ~)
38+ (cell 19:3
39+ (face 19:4 i (tvar 19:6 A))
40+ (face 19:8 t
41+ (apply 19:10 list (tvar 19:16 A)))))))
42+ (mold 21:1 unit
43+ (generic 21:9 A
44+ (union 22:3
45+ (const 22:3 ~)
46+ (cell 23:3
47+ (const 23:4 ~)
48+ (face 23:6 u (tvar 23:8 A))))))
49+ (value 25:1 fall
50+ (gate 25:9
51+ (face 25:12 args
52+ (cell 25:17
53+ (apply 25:18 unit (tvar 25:24 A))
54+ (tvar 25:27 A)))
55+ (body 26:3
56+ (branch 26:3
57+ (wing 26:6 args)
58+ (arm 27:5
59+ (cell 27:5 (bind 27:6 maybe) (bind 27:12 fallback))
60+ (body 28:7
61+ (branch 28:7
62+ (wing 28:10 maybe)
63+ (arm 29:9 (lit 29:9 ~) (wing 29:11 fallback))
64+ (arm 30:9
65+ (cell 30:9 (lit 30:10 ~) (bind 30:12 value))
66+ (wing 30:19 value)))))))))
67+ (value 32:1 need
68+ (gate 32:9
69+ (face 32:12 maybe
70+ (apply 32:18 unit (tvar 32:24 A)))
71+ (body 33:3
72+ (branch 33:3
73+ (wing 33:6 maybe)
74+ (arm 34:5 (lit 34:5 ~) (crash 34:7))
75+ (arm 35:5
76+ (cell 35:5 (lit 35:6 ~) (bind 35:8 value))
77+ (wing 35:15 value))))))
78+ (value 37:1 weld
79+ (gate 37:9
80+ (face 37:12 args
81+ (cell 37:17
82+ (apply 37:18 list (tvar 37:24 A))
83+ (apply 37:27 list (tvar 37:33 A))))
84+ (body 38:3
85+ (branch 38:3
86+ (wing 38:6 args)
87+ (arm 39:5
88+ (cell 39:5 (bind 39:6 xs) (bind 39:9 ys))
89+ (body 40:7
90+ (branch 40:7
91+ (wing 40:10 xs)
92+ (arm 41:9 (lit 41:9 ~) (wing 41:11 ys))
93+ (arm 42:9
94+ (cell 42:9 (bind 42:10 item) (bind 42:15 rest))
95+ (tuple 42:21
96+ (wing 42:22 item)
97+ (group 42:27
98+ (call 42:28 (wing 42:28 weld) (wing 42:33 rest) (wing 42:38 ys))))))))))))
99+ (value 44:1 turn
100+ (gate 44:9
101+ (face 44:12 args
102+ (cell 44:17
103+ (apply 44:18 list (tvar 44:24 A))
104+ (fn 44:27 (tvar 44:30 A) (tvar 44:32 B))))
105+ (body 45:3
106+ (branch 45:3
107+ (wing 45:6 args)
108+ (arm 46:5
109+ (cell 46:5 (bind 46:6 xs) (bind 46:9 f))
110+ (body 47:7
111+ (branch 47:7
112+ (wing 47:10 xs)
113+ (arm 48:9 (lit 48:9 ~) (lit 48:11 ~))
114+ (arm 49:9
115+ (cell 49:9 (bind 49:10 item) (bind 49:15 rest))
116+ (tuple 49:21
117+ (group 49:22
118+ (call 49:23 (wing 49:23 f) (wing 49:25 item)))
119+ (group 49:31
120+ (call 49:32 (wing 49:32 turn) (wing 49:37 rest) (wing 49:42 f))))))))))))
121+ (mold 51:1 dime
122+ (cell 51:9
123+ (face 51:10 p (aura 51:12 @ta))
124+ (face 51:16 q (aura 51:18 @))))
125+ (mold 53:1 hair
126+ (cell 53:9
127+ (face 53:10 p (aura 53:12 @ud))
128+ (face 53:16 q (aura 53:18 @ud))))
129+ (mold 55:1 pint
130+ (cell 55:9
131+ (face 55:10 p
132+ (cell 55:12
133+ (face 55:13 p (aura 55:15 @))
134+ (face 55:17 q (aura 55:19 @))))
135+ (face 55:22 q
136+ (cell 55:24
137+ (face 55:25 p (aura 55:27 @))
138+ (face 55:29 q (aura 55:31 @))))))
139+ (mold 57:1 coin
140+ (union 58:3
141+ (cell 58:3
142+ (const 58:4 %$)
143+ (face 58:7 p (ref 58:9 dime)))
144+ (cell 59:3
145+ (const 59:4 %blob)
146+ (face 59:10 p (noun 59:12)))
147+ (cell 60:3
148+ (const 60:4 %many)
149+ (face 60:10 p
150+ (apply 60:12 list (ref 60:18 coin)))))))
tests/golden/prelude-3g-basic/types.txtnew file+15
@@ -0,0 +1,15 @@
1+partial inference; module not checked
2+++ same: $-(A A)
3+++ head: $-([A B] A)
4+++ tail: $-([A B] B)
5+++ not: $-(? ?)
6++$ list: cases proven disjoint; mold not checked
7++$ unit: cases proven disjoint; mold not checked
8+++ fall: sample mold is not supported by partial inference
9+++ need: sample mold is not supported by partial inference
10+++ weld: sample mold is not supported by partial inference
11+++ turn: sample mold is not supported by partial inference
12++$ dime: not checked
13++$ hair: not checked
14++$ pint: not checked
15++$ coin: cases proven disjoint; mold not checked
tests/golden/prelude-list-unit/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Overview, Prelude: "Hoon's standard library regrouped, written in Jibb"; its data molds include `unit` and `list`, its unit helpers include `fall` and `need`, and its list helpers include `weld` and `turn`.
2−tests: The current prelude's generic recursive list and unit molds and its Jibb-written helpers; the partial inference report does not yet resolve these molds or check recursive gates.
2+tests: The prelude's generic recursive list and unit molds and its Jibb-written helpers; the partial inference report does not yet resolve these molds or check recursive gates.
33expect: parses
44expect-types: a partial inference report, not a checked module
tests/golden/types-import-sur/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Imports: `/- todo` imports molds from a Hoon `/sur` file.
2+tests: a golden case supplies its own Hoon source and selected molds; both the eval and ship runners pass the reader's results into partial inference.
3+expect: parses
4+expect-types: a partial report with the imported atom and unfaced cell types
tests/golden/types-import-sur/imports.txtnew file+2
@@ -0,0 +1,2 @@
1+fixture title
2+fixture pair
tests/golden/types-import-sur/source.jibbnew file+3
@@ -0,0 +1,3 @@
1+/- fixture
2+++ identity |= x=title.fixture x
3+++ pair-identity |= x=pair.fixture x
tests/golden/types-import-sur/sur/fixture.txtnew file+4
@@ -0,0 +1,4 @@
1+|%
2++$ title @t
3++$ pair [@ud @t]
4+--
tests/golden/types-import-sur/tokens.txtnew file+19
@@ -0,0 +1,19 @@
1+1:1 glyph /-
2+1:5 name fixture
3+2:1 NEWLINE
4+2:1 glyph ++
5+2:4 name identity
6+2:13 glyph |=
7+2:16 name x
8+2:17 tight glyph =
9+2:18 tight wing title.fixture
10+2:32 name x
11+3:1 NEWLINE
12+3:1 glyph ++
13+3:4 name pair-identity
14+3:18 glyph |=
15+3:21 name x
16+3:22 tight glyph =
17+3:23 tight wing pair.fixture
18+3:36 name x
19+3:37 NEWLINE
tests/golden/types-import-sur/tree.txtnew file+10
@@ -0,0 +1,10 @@
1+(module
2+ (sur 1:1 fixture)
3+ (value 2:1 identity
4+ (gate 2:13
5+ (face 2:16 x (ref 2:18 title.fixture))
6+ (wing 2:32 x)))
7+ (value 3:1 pair-identity
8+ (gate 3:18
9+ (face 3:21 x (ref 3:23 pair.fixture))
10+ (wing 3:36 x))))
tests/golden/types-import-sur/types.txtnew file+3
@@ -0,0 +1,3 @@
1+partial inference; module not checked
2+++ identity: $-(@t @t)
3+++ pair-identity: $-([@ud @t] [@ud @t])
tests/golden/types-partial-atom-widening/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: `@` is any atom; a specific atom fits `@`, but an `@` value needs a check to fit a specific aura. Shared atom types use an atom-constrained capital.
2+tests: calls and casts widen concrete atoms and loobeans, reject unchecked narrowing, and leave uninferred atom constraints unsupported.
3+expect: parses
4+expect-types: a partial inference report, not a checked module
tests/golden/types-partial-atom-widening/source.jibbnew file+9
@@ -0,0 +1,9 @@
1+++ atom-id |= x=@ x
2+++ call (atom-id ~zod)
3+++ widen ^- @ ~zod
4+++ flag ^- @ %.y
5+++ narrow |= x=@ ^- @ud x
6+++ constrained |= x=A ^- @ x
7+++ nested |= x |=(f=$-([@ @] @t) (f x))
8++$ open @
9+++ named |= x=open x
tests/golden/types-partial-atom-widening/tokens.txtnew file+79
@@ -0,0 +1,79 @@
1+1:1 glyph ++
2+1:4 name atom-id
3+1:12 glyph |=
4+1:15 name x
5+1:16 tight glyph =
6+1:17 tight aura @
7+1:19 name x
8+2:1 NEWLINE
9+2:1 glyph ++
10+2:4 name call
11+2:9 glyph (
12+2:10 tight name atom-id
13+2:18 lit ~zod
14+2:22 tight glyph )
15+3:1 NEWLINE
16+3:1 glyph ++
17+3:4 name widen
18+3:10 glyph ^-
19+3:13 aura @
20+3:15 lit ~zod
21+4:1 NEWLINE
22+4:1 glyph ++
23+4:4 name flag
24+4:9 glyph ^-
25+4:12 aura @
26+4:14 lit %.y
27+5:1 NEWLINE
28+5:1 glyph ++
29+5:4 name narrow
30+5:11 glyph |=
31+5:14 name x
32+5:15 tight glyph =
33+5:16 tight aura @
34+5:18 glyph ^-
35+5:21 aura @ud
36+5:25 name x
37+6:1 NEWLINE
38+6:1 glyph ++
39+6:4 name constrained
40+6:16 glyph |=
41+6:19 name x
42+6:20 tight glyph =
43+6:21 tight tvar A
44+6:23 glyph ^-
45+6:26 aura @
46+6:28 name x
47+7:1 NEWLINE
48+7:1 glyph ++
49+7:4 name nested
50+7:11 glyph |=
51+7:14 name x
52+7:16 glyph |=(
53+7:19 tight name f
54+7:20 tight glyph =
55+7:21 tight glyph $-(
56+7:24 tight glyph [
57+7:25 tight aura @
58+7:27 aura @
59+7:28 tight glyph ]
60+7:30 aura @t
61+7:32 tight glyph )
62+7:34 glyph (
63+7:35 tight name f
64+7:37 name x
65+7:38 tight glyph )
66+7:39 tight glyph )
67+8:1 NEWLINE
68+8:1 glyph +$
69+8:4 name open
70+8:9 aura @
71+9:1 NEWLINE
72+9:1 glyph ++
73+9:4 name named
74+9:10 glyph |=
75+9:13 name x
76+9:14 tight glyph =
77+9:15 tight name open
78+9:20 name x
79+9:21 NEWLINE
tests/golden/types-partial-atom-widening/tree.txtnew file+35
@@ -0,0 +1,35 @@
1+(module
2+ (value 1:1 atom-id
3+ (gate 1:12
4+ (face 1:15 x (aura 1:17 @))
5+ (wing 1:19 x)))
6+ (value 2:1 call
7+ (group 2:9
8+ (call 2:10 (wing 2:10 atom-id) (lit 2:18 ~zod))))
9+ (value 3:1 widen
10+ (cast 3:10 (aura 3:13 @) (lit 3:15 ~zod)))
11+ (value 4:1 flag
12+ (cast 4:9 (aura 4:12 @) (lit 4:14 %.y)))
13+ (value 5:1 narrow
14+ (gate 5:11
15+ (face 5:14 x (aura 5:16 @))
16+ (cast 5:18 (aura 5:21 @ud) (wing 5:25 x))))
17+ (value 6:1 constrained
18+ (gate 6:16
19+ (face 6:19 x (tvar 6:21 A))
20+ (cast 6:23 (aura 6:26 @) (wing 6:28 x))))
21+ (value 7:1 nested
22+ (gate 7:11
23+ (bind 7:14 x)
24+ (gate-wide 7:16
25+ (face 7:19 f
26+ (fn 7:21
27+ (cell 7:24 (aura 7:25 @) (aura 7:27 @))
28+ (aura 7:30 @t)))
29+ (group 7:34
30+ (call 7:35 (wing 7:35 f) (wing 7:37 x))))))
31+ (mold 8:1 open (aura 8:9 @))
32+ (value 9:1 named
33+ (gate 9:10
34+ (face 9:13 x (ref 9:15 open))
35+ (wing 9:20 x))))
tests/golden/types-partial-atom-widening/types.txtnew file+10
@@ -0,0 +1,10 @@
1+partial inference; module not checked
2+++ atom-id: $-(@ @)
3+++ call: @
4+++ widen: @
5+++ flag: @
6+++ narrow: cast mold and expression type do not unify
7+++ constrained: cast constraint is not supported by partial inference
8+++ nested: call constraint is not supported by partial inference
9++$ open: not checked
10+++ named: $-(@ @)
tests/golden/types-partial-bare-atom/about.txt+4−3
@@ -1,3 +1,4 @@
1−source: `@` is an unrestricted bare atom; each occurrence is independent.
2−tests: partial inference does not specialize a bare atom to the aura supplied by a call.
3−expect: parses; type analysis reports both samples as unsupported
1+source: `@` is any atom, independently at each occurrence; a specific atom fits where `@` is expected.
2+tests: an unrestricted sample accepts a specific atom and retains its unrestricted result type.
3+expect: parses
4+expect-types: a partial inference report, not a checked module
tests/golden/types-partial-bare-atom/types.txt+2−2
@@ -1,3 +1,3 @@
11partial inference; module not checked
2−++ f: sample mold is not supported by partial inference
3−++ g: sample mold is not supported by partial inference
2+++ f: @
3+++ g: $-(@ @)
tests/golden/types-partial-independent-atoms/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: each bare `@` independently accepts any atom; a specific atom fits where `@` is expected.
2+tests: two fields independently widen a ship and a cord and remain unrestricted in the result.
3+expect: parses
4+expect-types: a partial inference report, not a checked module
tests/golden/types-partial-independent-atoms/source.jibbnew file+2
@@ -0,0 +1,2 @@
1+++ f |= p=[@ @] p
2+++ x (f [~zod "hi"])
tests/golden/types-partial-independent-atoms/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph ++
2+1:4 name f
3+1:6 glyph |=
4+1:9 name p
5+1:10 tight glyph =
6+1:11 tight glyph [
7+1:12 tight aura @
8+1:14 aura @
9+1:15 tight glyph ]
10+1:17 name p
11+2:1 NEWLINE
12+2:1 glyph ++
13+2:4 name x
14+2:6 glyph (
15+2:7 tight name f
16+2:9 glyph [
17+2:10 tight lit ~zod
18+2:15 str "hi"
19+2:19 tight glyph ]
20+2:20 tight glyph )
21+2:21 NEWLINE
tests/golden/types-partial-independent-atoms/tree.txtnew file+11
@@ -0,0 +1,11 @@
1+(module
2+ (value 1:1 f
3+ (gate 1:6
4+ (face 1:9 p
5+ (cell 1:11 (aura 1:12 @) (aura 1:14 @)))
6+ (wing 1:17 p)))
7+ (value 2:1 x
8+ (group 2:6
9+ (call 2:7
10+ (wing 2:7 f)
11+ (tuple 2:9 (lit 2:10 ~zod) (str 2:15 "hi"))))))
tests/golden/types-partial-independent-atoms/types.txtnew file+3
@@ -0,0 +1,3 @@
1+partial inference; module not checked
2+++ f: $-([@ @] [@ @])
3+++ x: [@ @]
tests/golden/types-partial-mold-bare-aura/about.txt+2−2
@@ -1,4 +1,4 @@
1−source: Grammar tab, Molds: "every expression has a principal type, and there is no general subtyping".
2−tests: a bare-aura mold is explicitly unsupported by partial inference.
1+source: `@` is any atom; a specific atom fits where `@` is expected.
2+tests: a named unrestricted atom mold accepts a decimal value and remains unrestricted.
33expect: parses
44expect-types: a partial inference report, not a checked module
tests/golden/types-partial-mold-bare-aura/types.txt+1−1
@@ -1,3 +1,3 @@
11partial inference; module not checked
22+$ vague: not checked
3−++ datum: cast mold is not supported by partial inference
3+++ datum: @
tests/golden/types-partial-union-edges/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: `!!` is the empty mold; union cases differ as nouns, and matching never inspects gates to distinguish cases.
2+tests: empty molds and cells containing them are disjoint; named unions compare each case; gates remain opaque unless tags differ.
3+expect: parses; empty and distinct tags are disjoint, a shared named case overlaps, and gate-only distinctions remain unresolved
tests/golden/types-partial-union-edges/source.jibbnew file+24
@@ -0,0 +1,24 @@
1++$ empty
2+ !!
3+ %a
4++$ empty-cell
5+ [%a !!]
6+ [%a @t]
7++$ inner
8+ %a
9+ %b
10++$ named-disjoint
11+ inner
12+ %c
13++$ named-overlap
14+ inner
15+ %b
16++$ opaque
17+ $-(@t @t)
18+ @ud
19++$ tagged-gates
20+ [%a $-(@t @t)]
21+ [%b $-(@t @t)]
22++$ same-tag-gates
23+ [%a $-(@t @t)]
24+ [%a $-(@ud @ud)]
tests/golden/types-partial-union-edges/tokens.txtnew file+97
@@ -0,0 +1,97 @@
1+1:1 glyph +$
2+1:4 name empty
3+2:3 INDENT
4+2:3 glyph !!
5+3:3 NEWLINE
6+3:3 lit %a
7+4:1 DEDENT
8+4:1 NEWLINE
9+4:1 glyph +$
10+4:4 name empty-cell
11+5:3 INDENT
12+5:3 glyph [
13+5:4 tight lit %a
14+5:7 glyph !!
15+5:9 tight glyph ]
16+6:3 NEWLINE
17+6:3 glyph [
18+6:4 tight lit %a
19+6:7 aura @t
20+6:9 tight glyph ]
21+7:1 DEDENT
22+7:1 NEWLINE
23+7:1 glyph +$
24+7:4 name inner
25+8:3 INDENT
26+8:3 lit %a
27+9:3 NEWLINE
28+9:3 lit %b
29+10:1 DEDENT
30+10:1 NEWLINE
31+10:1 glyph +$
32+10:4 name named-disjoint
33+11:3 INDENT
34+11:3 name inner
35+12:3 NEWLINE
36+12:3 lit %c
37+13:1 DEDENT
38+13:1 NEWLINE
39+13:1 glyph +$
40+13:4 name named-overlap
41+14:3 INDENT
42+14:3 name inner
43+15:3 NEWLINE
44+15:3 lit %b
45+16:1 DEDENT
46+16:1 NEWLINE
47+16:1 glyph +$
48+16:4 name opaque
49+17:3 INDENT
50+17:3 glyph $-(
51+17:6 tight aura @t
52+17:9 aura @t
53+17:11 tight glyph )
54+18:3 NEWLINE
55+18:3 aura @ud
56+19:1 DEDENT
57+19:1 NEWLINE
58+19:1 glyph +$
59+19:4 name tagged-gates
60+20:3 INDENT
61+20:3 glyph [
62+20:4 tight lit %a
63+20:7 glyph $-(
64+20:10 tight aura @t
65+20:13 aura @t
66+20:15 tight glyph )
67+20:16 tight glyph ]
68+21:3 NEWLINE
69+21:3 glyph [
70+21:4 tight lit %b
71+21:7 glyph $-(
72+21:10 tight aura @t
73+21:13 aura @t
74+21:15 tight glyph )
75+21:16 tight glyph ]
76+22:1 DEDENT
77+22:1 NEWLINE
78+22:1 glyph +$
79+22:4 name same-tag-gates
80+23:3 INDENT
81+23:3 glyph [
82+23:4 tight lit %a
83+23:7 glyph $-(
84+23:10 tight aura @t
85+23:13 aura @t
86+23:15 tight glyph )
87+23:16 tight glyph ]
88+24:3 NEWLINE
89+24:3 glyph [
90+24:4 tight lit %a
91+24:7 glyph $-(
92+24:10 tight aura @ud
93+24:14 aura @ud
94+24:17 tight glyph )
95+24:18 tight glyph ]
96+24:19 DEDENT
97+24:19 NEWLINE
tests/golden/types-partial-union-edges/tree.txtnew file+33
@@ -0,0 +1,33 @@
1+(module
2+ (mold 1:1 empty
3+ (union 2:3 (void 2:3) (const 3:3 %a)))
4+ (mold 4:1 empty-cell
5+ (union 5:3
6+ (cell 5:3 (const 5:4 %a) (void 5:7))
7+ (cell 6:3 (const 6:4 %a) (aura 6:7 @t))))
8+ (mold 7:1 inner
9+ (union 8:3 (const 8:3 %a) (const 9:3 %b)))
10+ (mold 10:1 named-disjoint
11+ (union 11:3 (ref 11:3 inner) (const 12:3 %c)))
12+ (mold 13:1 named-overlap
13+ (union 14:3 (ref 14:3 inner) (const 15:3 %b)))
14+ (mold 16:1 opaque
15+ (union 17:3
16+ (fn 17:3 (aura 17:6 @t) (aura 17:9 @t))
17+ (aura 18:3 @ud)))
18+ (mold 19:1 tagged-gates
19+ (union 20:3
20+ (cell 20:3
21+ (const 20:4 %a)
22+ (fn 20:7 (aura 20:10 @t) (aura 20:13 @t)))
23+ (cell 21:3
24+ (const 21:4 %b)
25+ (fn 21:7 (aura 21:10 @t) (aura 21:13 @t)))))
26+ (mold 22:1 same-tag-gates
27+ (union 23:3
28+ (cell 23:3
29+ (const 23:4 %a)
30+ (fn 23:7 (aura 23:10 @t) (aura 23:13 @t)))
31+ (cell 24:3
32+ (const 24:4 %a)
33+ (fn 24:7 (aura 24:10 @ud) (aura 24:14 @ud))))))
tests/golden/types-partial-union-edges/types.txtnew file+9
@@ -0,0 +1,9 @@
1+partial inference; module not checked
2++$ empty: cases proven disjoint; mold not checked
3++$ empty-cell: cases proven disjoint; mold not checked
4++$ inner: cases proven disjoint; mold not checked
5++$ named-disjoint: cases proven disjoint; mold not checked
6++$ named-overlap: overlapping cases at 14:3 and 15:3; mold not checked
7++$ opaque: case disjointness unresolved; mold not checked
8++$ tagged-gates: cases proven disjoint; mold not checked
9++$ same-tag-gates: case disjointness unresolved; mold not checked
tests/importer/shadow.txt+2
@@ -1,8 +1,10 @@
11|%
22+| %hiding
33++ jar |$([key value] (map key (list value)))
4+++ mop mop:..zuse
45++ jug |$([key value] (map key (set value)))
56+| %defs
7++$ mm ((mop @ud @t) lte)
68+$ aa (jar @ud @t)
79+$ bb [field=(jug @ud @t)]
810--
tests/importer/small.txt+4
@@ -10,6 +10,10 @@
1010+$ nested-jar [field=(jar @ud @t)]
1111+$ paired-aliases [values=(jar @ud @t) cache=(jug @ud @t)]
1212+$ nested-alias (jar @ud (jug @ud @t))
13++$ compound (map @ud (list (jar @ud (jug @t @ud))))
14++$ compound-fields [one=(map @ud (jar @t @ud)) two=(list (jug @t @ud))]
15++$ mop-test ((mop @ud @t) lte)
16++$ nested-mop [table=((mop @ud @t) lte) other=@ud]
1317+$ signed @sd
1418+$ float @rd
1519+$ gate-test $-(@ud @ud)
tests/importer/tree.txt+6−1
@@ -7,7 +7,11 @@ jar: (jar @ud @t)
77jug: (jug @ud @t)
88nested-jar: field=(jar @ud @t)
99paired-aliases: [values=(jar @ud @t) cache=(jug @ud @t)]
10−nested-alias: error: nested collection arguments need source-aware import
10+nested-alias: (jar @ud (jug @ud @t))
11+compound: (map @ud (list (jar @ud (jug @t @ud))))
12+compound-fields: [one=(map @ud (jar @t @ud)) two=(list (jug @t @ud))]
13+mop: (mop @ud @t)
14+nested-mop: error: a nested Hoon mop needs source-aware import
1115signed: error: signed and float auras cannot be imported
1216float: error: signed and float auras cannot be imported
1317gate: error: cores and gates cannot be imported
@@ -21,6 +25,7 @@ chapter-direct-hit: yes
2125chapter-wrapped-hit: yes
2226chapter-direct-miss: no
2327chapter-wrapped-miss: no
28+shadow-mop: error: Hoon collection provenance is unavailable or shadowed
2429shadow-jar: error: Hoon collection provenance is unavailable or shadowed
2530shadow-jug: error: Hoon collection provenance is unavailable or shadowed
2631no-provenance: error: Hoon collection provenance is unavailable or shadowed
tests/lib/jibb.hoon+152−106
@@ -19,7 +19,7 @@
1919:: after it), so only tools/golden, and tools/ship test's own warning,
2020:: catch an expected file without its final newline.
2121::
22−/+ jibb
22+/+ jibb, jibb-import
2323/* src-1 %jibb /tests/golden/doc-core-02-update/source/jibb
2424/* tok-1 %txt /tests/golden/doc-core-02-update/tokens/txt
2525/* tre-1 %txt /tests/golden/doc-core-02-update/tree/txt
@@ -1136,90 +1136,112 @@
11361136/* src-372 %jibb /tests/golden/lex-tight-wing-ok-1/source/jibb
11371137/* tok-372 %txt /tests/golden/lex-tight-wing-ok-1/tokens/txt
11381138/* tre-372 %txt /tests/golden/lex-tight-wing-ok-1/tree/txt
1139−/* src-373 %jibb /tests/golden/prelude-core-functions/source/jibb
1140−/* tok-373 %txt /tests/golden/prelude-core-functions/tokens/txt
1141−/* tre-373 %txt /tests/golden/prelude-core-functions/tree/txt
1142−/* typ-373 %txt /tests/golden/prelude-core-functions/types/txt
1143−/* src-374 %jibb /tests/golden/prelude-list-unit/source/jibb
1144−/* tok-374 %txt /tests/golden/prelude-list-unit/tokens/txt
1145−/* tre-374 %txt /tests/golden/prelude-list-unit/tree/txt
1146−/* typ-374 %txt /tests/golden/prelude-list-unit/types/txt
1147−/* src-375 %jibb /tests/golden/types-partial-apply/source/jibb
1148−/* tok-375 %txt /tests/golden/types-partial-apply/tokens/txt
1149−/* tre-375 %txt /tests/golden/types-partial-apply/tree/txt
1150−/* typ-375 %txt /tests/golden/types-partial-apply/types/txt
1151−/* src-376 %jibb /tests/golden/types-partial-aura/source/jibb
1152−/* tok-376 %txt /tests/golden/types-partial-aura/tokens/txt
1153−/* tre-376 %txt /tests/golden/types-partial-aura/tree/txt
1154−/* typ-376 %txt /tests/golden/types-partial-aura/types/txt
1155−/* src-377 %jibb /tests/golden/types-partial-aura-generalization/source/jibb
1156−/* tok-377 %txt /tests/golden/types-partial-aura-generalization/tokens/txt
1157−/* tre-377 %txt /tests/golden/types-partial-aura-generalization/tree/txt
1158−/* typ-377 %txt /tests/golden/types-partial-aura-generalization/types/txt
1159−/* src-378 %jibb /tests/golden/types-partial-bare-atom/source/jibb
1160−/* tok-378 %txt /tests/golden/types-partial-bare-atom/tokens/txt
1161−/* tre-378 %txt /tests/golden/types-partial-bare-atom/tree/txt
1162−/* typ-378 %txt /tests/golden/types-partial-bare-atom/types/txt
1163−/* src-379 %jibb /tests/golden/types-partial-dependency-chain/source/jibb
1164−/* tok-379 %txt /tests/golden/types-partial-dependency-chain/tokens/txt
1165−/* tre-379 %txt /tests/golden/types-partial-dependency-chain/tree/txt
1166−/* typ-379 %txt /tests/golden/types-partial-dependency-chain/types/txt
1167−/* src-380 %jibb /tests/golden/types-partial-explicit-capital/source/jibb
1168−/* tok-380 %txt /tests/golden/types-partial-explicit-capital/tokens/txt
1169−/* tre-380 %txt /tests/golden/types-partial-explicit-capital/tree/txt
1170−/* typ-380 %txt /tests/golden/types-partial-explicit-capital/types/txt
1171−/* src-381 %jibb /tests/golden/types-partial-forward/source/jibb
1172−/* tok-381 %txt /tests/golden/types-partial-forward/tokens/txt
1173−/* tre-381 %txt /tests/golden/types-partial-forward/tree/txt
1174−/* typ-381 %txt /tests/golden/types-partial-forward/types/txt
1175−/* src-382 %jibb /tests/golden/types-partial-generalization/source/jibb
1176−/* tok-382 %txt /tests/golden/types-partial-generalization/tokens/txt
1177−/* tre-382 %txt /tests/golden/types-partial-generalization/tree/txt
1178−/* typ-382 %txt /tests/golden/types-partial-generalization/types/txt
1179−/* src-383 %jibb /tests/golden/types-partial-identity/source/jibb
1180−/* tok-383 %txt /tests/golden/types-partial-identity/tokens/txt
1181−/* tre-383 %txt /tests/golden/types-partial-identity/tree/txt
1182−/* typ-383 %txt /tests/golden/types-partial-identity/types/txt
1183−/* src-384 %jibb /tests/golden/types-partial-mold-bare-aura/source/jibb
1184−/* tok-384 %txt /tests/golden/types-partial-mold-bare-aura/tokens/txt
1185−/* tre-384 %txt /tests/golden/types-partial-mold-bare-aura/tree/txt
1186−/* typ-384 %txt /tests/golden/types-partial-mold-bare-aura/types/txt
1187−/* src-385 %jibb /tests/golden/types-partial-mold-composite/source/jibb
1188−/* tok-385 %txt /tests/golden/types-partial-mold-composite/tokens/txt
1189−/* tre-385 %txt /tests/golden/types-partial-mold-composite/tree/txt
1190−/* typ-385 %txt /tests/golden/types-partial-mold-composite/types/txt
1191−/* src-386 %jibb /tests/golden/types-partial-mold-forward/source/jibb
1192−/* tok-386 %txt /tests/golden/types-partial-mold-forward/tokens/txt
1193−/* tre-386 %txt /tests/golden/types-partial-mold-forward/tree/txt
1194−/* typ-386 %txt /tests/golden/types-partial-mold-forward/types/txt
1195−/* src-387 %jibb /tests/golden/types-partial-mold-recursive/source/jibb
1196−/* tok-387 %txt /tests/golden/types-partial-mold-recursive/tokens/txt
1197−/* tre-387 %txt /tests/golden/types-partial-mold-recursive/tree/txt
1198−/* typ-387 %txt /tests/golden/types-partial-mold-recursive/types/txt
1199−/* src-388 %jibb /tests/golden/types-partial-occurs/source/jibb
1200−/* tok-388 %txt /tests/golden/types-partial-occurs/tokens/txt
1201−/* tre-388 %txt /tests/golden/types-partial-occurs/tree/txt
1202−/* typ-388 %txt /tests/golden/types-partial-occurs/types/txt
1203−/* src-389 %jibb /tests/golden/types-partial-projection/source/jibb
1204−/* tok-389 %txt /tests/golden/types-partial-projection/tokens/txt
1205−/* tre-389 %txt /tests/golden/types-partial-projection/tree/txt
1206−/* typ-389 %txt /tests/golden/types-partial-projection/types/txt
1207−/* src-390 %jibb /tests/golden/types-partial-shadow-global/source/jibb
1208−/* tok-390 %txt /tests/golden/types-partial-shadow-global/tokens/txt
1209−/* tre-390 %txt /tests/golden/types-partial-shadow-global/tree/txt
1210−/* typ-390 %txt /tests/golden/types-partial-shadow-global/types/txt
1211−/* src-391 %jibb /tests/golden/types-partial-shared-tvar/source/jibb
1212−/* tok-391 %txt /tests/golden/types-partial-shared-tvar/tokens/txt
1213−/* tre-391 %txt /tests/golden/types-partial-shared-tvar/tree/txt
1214−/* typ-391 %txt /tests/golden/types-partial-shared-tvar/types/txt
1215−/* src-392 %jibb /tests/golden/types-partial-union-cases/source/jibb
1216−/* tok-392 %txt /tests/golden/types-partial-union-cases/tokens/txt
1217−/* tre-392 %txt /tests/golden/types-partial-union-cases/tree/txt
1218−/* typ-392 %txt /tests/golden/types-partial-union-cases/types/txt
1219−/* src-393 %jibb /tests/golden/types-partial-unresolved-tag/source/jibb
1220−/* tok-393 %txt /tests/golden/types-partial-unresolved-tag/tokens/txt
1221−/* tre-393 %txt /tests/golden/types-partial-unresolved-tag/tree/txt
1222−/* typ-393 %txt /tests/golden/types-partial-unresolved-tag/types/txt
1139+/* src-373 %jibb /tests/golden/prelude-3g-basic/source/jibb
1140+/* tok-373 %txt /tests/golden/prelude-3g-basic/tokens/txt
1141+/* tre-373 %txt /tests/golden/prelude-3g-basic/tree/txt
1142+/* typ-373 %txt /tests/golden/prelude-3g-basic/types/txt
1143+/* src-374 %jibb /tests/golden/prelude-core-functions/source/jibb
1144+/* tok-374 %txt /tests/golden/prelude-core-functions/tokens/txt
1145+/* tre-374 %txt /tests/golden/prelude-core-functions/tree/txt
1146+/* typ-374 %txt /tests/golden/prelude-core-functions/types/txt
1147+/* src-375 %jibb /tests/golden/prelude-list-unit/source/jibb
1148+/* tok-375 %txt /tests/golden/prelude-list-unit/tokens/txt
1149+/* tre-375 %txt /tests/golden/prelude-list-unit/tree/txt
1150+/* typ-375 %txt /tests/golden/prelude-list-unit/types/txt
1151+/* src-376 %jibb /tests/golden/types-import-sur/source/jibb
1152+/* tok-376 %txt /tests/golden/types-import-sur/tokens/txt
1153+/* tre-376 %txt /tests/golden/types-import-sur/tree/txt
1154+/* typ-376 %txt /tests/golden/types-import-sur/types/txt
1155+/* imp-376-1 %txt /tests/golden/types-import-sur/sur/fixture/txt
1156+/* imp-376-2 %txt /tests/golden/types-import-sur/sur/fixture/txt
1157+/* src-377 %jibb /tests/golden/types-partial-apply/source/jibb
1158+/* tok-377 %txt /tests/golden/types-partial-apply/tokens/txt
1159+/* tre-377 %txt /tests/golden/types-partial-apply/tree/txt
1160+/* typ-377 %txt /tests/golden/types-partial-apply/types/txt
1161+/* src-378 %jibb /tests/golden/types-partial-atom-widening/source/jibb
1162+/* tok-378 %txt /tests/golden/types-partial-atom-widening/tokens/txt
1163+/* tre-378 %txt /tests/golden/types-partial-atom-widening/tree/txt
1164+/* typ-378 %txt /tests/golden/types-partial-atom-widening/types/txt
1165+/* src-379 %jibb /tests/golden/types-partial-aura/source/jibb
1166+/* tok-379 %txt /tests/golden/types-partial-aura/tokens/txt
1167+/* tre-379 %txt /tests/golden/types-partial-aura/tree/txt
1168+/* typ-379 %txt /tests/golden/types-partial-aura/types/txt
1169+/* src-380 %jibb /tests/golden/types-partial-aura-generalization/source/jibb
1170+/* tok-380 %txt /tests/golden/types-partial-aura-generalization/tokens/txt
1171+/* tre-380 %txt /tests/golden/types-partial-aura-generalization/tree/txt
1172+/* typ-380 %txt /tests/golden/types-partial-aura-generalization/types/txt
1173+/* src-381 %jibb /tests/golden/types-partial-bare-atom/source/jibb
1174+/* tok-381 %txt /tests/golden/types-partial-bare-atom/tokens/txt
1175+/* tre-381 %txt /tests/golden/types-partial-bare-atom/tree/txt
1176+/* typ-381 %txt /tests/golden/types-partial-bare-atom/types/txt
1177+/* src-382 %jibb /tests/golden/types-partial-dependency-chain/source/jibb
1178+/* tok-382 %txt /tests/golden/types-partial-dependency-chain/tokens/txt
1179+/* tre-382 %txt /tests/golden/types-partial-dependency-chain/tree/txt
1180+/* typ-382 %txt /tests/golden/types-partial-dependency-chain/types/txt
1181+/* src-383 %jibb /tests/golden/types-partial-explicit-capital/source/jibb
1182+/* tok-383 %txt /tests/golden/types-partial-explicit-capital/tokens/txt
1183+/* tre-383 %txt /tests/golden/types-partial-explicit-capital/tree/txt
1184+/* typ-383 %txt /tests/golden/types-partial-explicit-capital/types/txt
1185+/* src-384 %jibb /tests/golden/types-partial-forward/source/jibb
1186+/* tok-384 %txt /tests/golden/types-partial-forward/tokens/txt
1187+/* tre-384 %txt /tests/golden/types-partial-forward/tree/txt
1188+/* typ-384 %txt /tests/golden/types-partial-forward/types/txt
1189+/* src-385 %jibb /tests/golden/types-partial-generalization/source/jibb
1190+/* tok-385 %txt /tests/golden/types-partial-generalization/tokens/txt
1191+/* tre-385 %txt /tests/golden/types-partial-generalization/tree/txt
1192+/* typ-385 %txt /tests/golden/types-partial-generalization/types/txt
1193+/* src-386 %jibb /tests/golden/types-partial-identity/source/jibb
1194+/* tok-386 %txt /tests/golden/types-partial-identity/tokens/txt
1195+/* tre-386 %txt /tests/golden/types-partial-identity/tree/txt
1196+/* typ-386 %txt /tests/golden/types-partial-identity/types/txt
1197+/* src-387 %jibb /tests/golden/types-partial-independent-atoms/source/jibb
1198+/* tok-387 %txt /tests/golden/types-partial-independent-atoms/tokens/txt
1199+/* tre-387 %txt /tests/golden/types-partial-independent-atoms/tree/txt
1200+/* typ-387 %txt /tests/golden/types-partial-independent-atoms/types/txt
1201+/* src-388 %jibb /tests/golden/types-partial-mold-bare-aura/source/jibb
1202+/* tok-388 %txt /tests/golden/types-partial-mold-bare-aura/tokens/txt
1203+/* tre-388 %txt /tests/golden/types-partial-mold-bare-aura/tree/txt
1204+/* typ-388 %txt /tests/golden/types-partial-mold-bare-aura/types/txt
1205+/* src-389 %jibb /tests/golden/types-partial-mold-composite/source/jibb
1206+/* tok-389 %txt /tests/golden/types-partial-mold-composite/tokens/txt
1207+/* tre-389 %txt /tests/golden/types-partial-mold-composite/tree/txt
1208+/* typ-389 %txt /tests/golden/types-partial-mold-composite/types/txt
1209+/* src-390 %jibb /tests/golden/types-partial-mold-forward/source/jibb
1210+/* tok-390 %txt /tests/golden/types-partial-mold-forward/tokens/txt
1211+/* tre-390 %txt /tests/golden/types-partial-mold-forward/tree/txt
1212+/* typ-390 %txt /tests/golden/types-partial-mold-forward/types/txt
1213+/* src-391 %jibb /tests/golden/types-partial-mold-recursive/source/jibb
1214+/* tok-391 %txt /tests/golden/types-partial-mold-recursive/tokens/txt
1215+/* tre-391 %txt /tests/golden/types-partial-mold-recursive/tree/txt
1216+/* typ-391 %txt /tests/golden/types-partial-mold-recursive/types/txt
1217+/* src-392 %jibb /tests/golden/types-partial-occurs/source/jibb
1218+/* tok-392 %txt /tests/golden/types-partial-occurs/tokens/txt
1219+/* tre-392 %txt /tests/golden/types-partial-occurs/tree/txt
1220+/* typ-392 %txt /tests/golden/types-partial-occurs/types/txt
1221+/* src-393 %jibb /tests/golden/types-partial-projection/source/jibb
1222+/* tok-393 %txt /tests/golden/types-partial-projection/tokens/txt
1223+/* tre-393 %txt /tests/golden/types-partial-projection/tree/txt
1224+/* typ-393 %txt /tests/golden/types-partial-projection/types/txt
1225+/* src-394 %jibb /tests/golden/types-partial-shadow-global/source/jibb
1226+/* tok-394 %txt /tests/golden/types-partial-shadow-global/tokens/txt
1227+/* tre-394 %txt /tests/golden/types-partial-shadow-global/tree/txt
1228+/* typ-394 %txt /tests/golden/types-partial-shadow-global/types/txt
1229+/* src-395 %jibb /tests/golden/types-partial-shared-tvar/source/jibb
1230+/* tok-395 %txt /tests/golden/types-partial-shared-tvar/tokens/txt
1231+/* tre-395 %txt /tests/golden/types-partial-shared-tvar/tree/txt
1232+/* typ-395 %txt /tests/golden/types-partial-shared-tvar/types/txt
1233+/* src-396 %jibb /tests/golden/types-partial-union-cases/source/jibb
1234+/* tok-396 %txt /tests/golden/types-partial-union-cases/tokens/txt
1235+/* tre-396 %txt /tests/golden/types-partial-union-cases/tree/txt
1236+/* typ-396 %txt /tests/golden/types-partial-union-cases/types/txt
1237+/* src-397 %jibb /tests/golden/types-partial-union-edges/source/jibb
1238+/* tok-397 %txt /tests/golden/types-partial-union-edges/tokens/txt
1239+/* tre-397 %txt /tests/golden/types-partial-union-edges/tree/txt
1240+/* typ-397 %txt /tests/golden/types-partial-union-edges/types/txt
1241+/* src-398 %jibb /tests/golden/types-partial-unresolved-tag/source/jibb
1242+/* tok-398 %txt /tests/golden/types-partial-unresolved-tag/tokens/txt
1243+/* tre-398 %txt /tests/golden/types-partial-unresolved-tag/tree/txt
1244+/* typ-398 %txt /tests/golden/types-partial-unresolved-tag/types/txt
12231245|%
12241246:: one arm per case
12251247::
@@ -1967,48 +1989,58 @@
19671989 (check ~.lex-tight-wing-bad-1 src-371 `tok-371 `tre-371)
19681990++ test-lex-tight-wing-ok-1
19691991 (check ~.lex-tight-wing-ok-1 src-372 `tok-372 `tre-372)
1992+++ test-prelude-3g-basic
1993+ (weld (check ~.prelude-3g-basic src-373 `tok-373 `tre-373) (check-types ~.prelude-3g-basic ~[%tests %golden ~.prelude-3g-basic %source %jibb] src-373 `typ-373))
19701994++ test-prelude-core-functions
1971− (weld (check ~.prelude-core-functions src-373 `tok-373 `tre-373) (check-types ~.prelude-core-functions ~[%tests %golden ~.prelude-core-functions %source %jibb] src-373 `typ-373))
1995+ (weld (check ~.prelude-core-functions src-374 `tok-374 `tre-374) (check-types ~.prelude-core-functions ~[%tests %golden ~.prelude-core-functions %source %jibb] src-374 `typ-374))
19721996++ test-prelude-list-unit
1973− (weld (check ~.prelude-list-unit src-374 `tok-374 `tre-374) (check-types ~.prelude-list-unit ~[%tests %golden ~.prelude-list-unit %source %jibb] src-374 `typ-374))
1997+ (weld (check ~.prelude-list-unit src-375 `tok-375 `tre-375) (check-types ~.prelude-list-unit ~[%tests %golden ~.prelude-list-unit %source %jibb] src-375 `typ-375))
1998+++ test-types-import-sur
1999+ (weld (check ~.types-import-sur src-376 `tok-376 `tre-376) (check-import-types ~.types-import-sur ~[%tests %golden ~.types-import-sur %source %jibb] src-376 `typ-376 ~[[%fixture %title imp-376-1] [%fixture %pair imp-376-2]]))
19742000++ test-types-partial-apply
1975− (weld (check ~.types-partial-apply src-375 `tok-375 `tre-375) (check-types ~.types-partial-apply ~[%tests %golden ~.types-partial-apply %source %jibb] src-375 `typ-375))
2001+ (weld (check ~.types-partial-apply src-377 `tok-377 `tre-377) (check-types ~.types-partial-apply ~[%tests %golden ~.types-partial-apply %source %jibb] src-377 `typ-377))
2002+++ test-types-partial-atom-widening
2003+ (weld (check ~.types-partial-atom-widening src-378 `tok-378 `tre-378) (check-types ~.types-partial-atom-widening ~[%tests %golden ~.types-partial-atom-widening %source %jibb] src-378 `typ-378))
19762004++ test-types-partial-aura
1977− (weld (check ~.types-partial-aura src-376 `tok-376 `tre-376) (check-types ~.types-partial-aura ~[%tests %golden ~.types-partial-aura %source %jibb] src-376 `typ-376))
2005+ (weld (check ~.types-partial-aura src-379 `tok-379 `tre-379) (check-types ~.types-partial-aura ~[%tests %golden ~.types-partial-aura %source %jibb] src-379 `typ-379))
19782006++ test-types-partial-aura-generalization
1979− (weld (check ~.types-partial-aura-generalization src-377 `tok-377 `tre-377) (check-types ~.types-partial-aura-generalization ~[%tests %golden ~.types-partial-aura-generalization %source %jibb] src-377 `typ-377))
2007+ (weld (check ~.types-partial-aura-generalization src-380 `tok-380 `tre-380) (check-types ~.types-partial-aura-generalization ~[%tests %golden ~.types-partial-aura-generalization %source %jibb] src-380 `typ-380))
19802008++ test-types-partial-bare-atom
1981− (weld (check ~.types-partial-bare-atom src-378 `tok-378 `tre-378) (check-types ~.types-partial-bare-atom ~[%tests %golden ~.types-partial-bare-atom %source %jibb] src-378 `typ-378))
2009+ (weld (check ~.types-partial-bare-atom src-381 `tok-381 `tre-381) (check-types ~.types-partial-bare-atom ~[%tests %golden ~.types-partial-bare-atom %source %jibb] src-381 `typ-381))
19822010++ test-types-partial-dependency-chain
1983− (weld (check ~.types-partial-dependency-chain src-379 `tok-379 `tre-379) (check-types ~.types-partial-dependency-chain ~[%tests %golden ~.types-partial-dependency-chain %source %jibb] src-379 `typ-379))
2011+ (weld (check ~.types-partial-dependency-chain src-382 `tok-382 `tre-382) (check-types ~.types-partial-dependency-chain ~[%tests %golden ~.types-partial-dependency-chain %source %jibb] src-382 `typ-382))
19842012++ test-types-partial-explicit-capital
1985− (weld (check ~.types-partial-explicit-capital src-380 `tok-380 `tre-380) (check-types ~.types-partial-explicit-capital ~[%tests %golden ~.types-partial-explicit-capital %source %jibb] src-380 `typ-380))
2013+ (weld (check ~.types-partial-explicit-capital src-383 `tok-383 `tre-383) (check-types ~.types-partial-explicit-capital ~[%tests %golden ~.types-partial-explicit-capital %source %jibb] src-383 `typ-383))
19862014++ test-types-partial-forward
1987− (weld (check ~.types-partial-forward src-381 `tok-381 `tre-381) (check-types ~.types-partial-forward ~[%tests %golden ~.types-partial-forward %source %jibb] src-381 `typ-381))
2015+ (weld (check ~.types-partial-forward src-384 `tok-384 `tre-384) (check-types ~.types-partial-forward ~[%tests %golden ~.types-partial-forward %source %jibb] src-384 `typ-384))
19882016++ test-types-partial-generalization
1989− (weld (check ~.types-partial-generalization src-382 `tok-382 `tre-382) (check-types ~.types-partial-generalization ~[%tests %golden ~.types-partial-generalization %source %jibb] src-382 `typ-382))
2017+ (weld (check ~.types-partial-generalization src-385 `tok-385 `tre-385) (check-types ~.types-partial-generalization ~[%tests %golden ~.types-partial-generalization %source %jibb] src-385 `typ-385))
19902018++ test-types-partial-identity
1991− (weld (check ~.types-partial-identity src-383 `tok-383 `tre-383) (check-types ~.types-partial-identity ~[%tests %golden ~.types-partial-identity %source %jibb] src-383 `typ-383))
2019+ (weld (check ~.types-partial-identity src-386 `tok-386 `tre-386) (check-types ~.types-partial-identity ~[%tests %golden ~.types-partial-identity %source %jibb] src-386 `typ-386))
2020+++ test-types-partial-independent-atoms
2021+ (weld (check ~.types-partial-independent-atoms src-387 `tok-387 `tre-387) (check-types ~.types-partial-independent-atoms ~[%tests %golden ~.types-partial-independent-atoms %source %jibb] src-387 `typ-387))
19922022++ test-types-partial-mold-bare-aura
1993− (weld (check ~.types-partial-mold-bare-aura src-384 `tok-384 `tre-384) (check-types ~.types-partial-mold-bare-aura ~[%tests %golden ~.types-partial-mold-bare-aura %source %jibb] src-384 `typ-384))
2023+ (weld (check ~.types-partial-mold-bare-aura src-388 `tok-388 `tre-388) (check-types ~.types-partial-mold-bare-aura ~[%tests %golden ~.types-partial-mold-bare-aura %source %jibb] src-388 `typ-388))
19942024++ test-types-partial-mold-composite
1995− (weld (check ~.types-partial-mold-composite src-385 `tok-385 `tre-385) (check-types ~.types-partial-mold-composite ~[%tests %golden ~.types-partial-mold-composite %source %jibb] src-385 `typ-385))
2025+ (weld (check ~.types-partial-mold-composite src-389 `tok-389 `tre-389) (check-types ~.types-partial-mold-composite ~[%tests %golden ~.types-partial-mold-composite %source %jibb] src-389 `typ-389))
19962026++ test-types-partial-mold-forward
1997− (weld (check ~.types-partial-mold-forward src-386 `tok-386 `tre-386) (check-types ~.types-partial-mold-forward ~[%tests %golden ~.types-partial-mold-forward %source %jibb] src-386 `typ-386))
2027+ (weld (check ~.types-partial-mold-forward src-390 `tok-390 `tre-390) (check-types ~.types-partial-mold-forward ~[%tests %golden ~.types-partial-mold-forward %source %jibb] src-390 `typ-390))
19982028++ test-types-partial-mold-recursive
1999− (weld (check ~.types-partial-mold-recursive src-387 `tok-387 `tre-387) (check-types ~.types-partial-mold-recursive ~[%tests %golden ~.types-partial-mold-recursive %source %jibb] src-387 `typ-387))
2029+ (weld (check ~.types-partial-mold-recursive src-391 `tok-391 `tre-391) (check-types ~.types-partial-mold-recursive ~[%tests %golden ~.types-partial-mold-recursive %source %jibb] src-391 `typ-391))
20002030++ test-types-partial-occurs
2001− (weld (check ~.types-partial-occurs src-388 `tok-388 `tre-388) (check-types ~.types-partial-occurs ~[%tests %golden ~.types-partial-occurs %source %jibb] src-388 `typ-388))
2031+ (weld (check ~.types-partial-occurs src-392 `tok-392 `tre-392) (check-types ~.types-partial-occurs ~[%tests %golden ~.types-partial-occurs %source %jibb] src-392 `typ-392))
20022032++ test-types-partial-projection
2003− (weld (check ~.types-partial-projection src-389 `tok-389 `tre-389) (check-types ~.types-partial-projection ~[%tests %golden ~.types-partial-projection %source %jibb] src-389 `typ-389))
2033+ (weld (check ~.types-partial-projection src-393 `tok-393 `tre-393) (check-types ~.types-partial-projection ~[%tests %golden ~.types-partial-projection %source %jibb] src-393 `typ-393))
20042034++ test-types-partial-shadow-global
2005− (weld (check ~.types-partial-shadow-global src-390 `tok-390 `tre-390) (check-types ~.types-partial-shadow-global ~[%tests %golden ~.types-partial-shadow-global %source %jibb] src-390 `typ-390))
2035+ (weld (check ~.types-partial-shadow-global src-394 `tok-394 `tre-394) (check-types ~.types-partial-shadow-global ~[%tests %golden ~.types-partial-shadow-global %source %jibb] src-394 `typ-394))
20062036++ test-types-partial-shared-tvar
2007− (weld (check ~.types-partial-shared-tvar src-391 `tok-391 `tre-391) (check-types ~.types-partial-shared-tvar ~[%tests %golden ~.types-partial-shared-tvar %source %jibb] src-391 `typ-391))
2037+ (weld (check ~.types-partial-shared-tvar src-395 `tok-395 `tre-395) (check-types ~.types-partial-shared-tvar ~[%tests %golden ~.types-partial-shared-tvar %source %jibb] src-395 `typ-395))
20082038++ test-types-partial-union-cases
2009− (weld (check ~.types-partial-union-cases src-392 `tok-392 `tre-392) (check-types ~.types-partial-union-cases ~[%tests %golden ~.types-partial-union-cases %source %jibb] src-392 `typ-392))
2039+ (weld (check ~.types-partial-union-cases src-396 `tok-396 `tre-396) (check-types ~.types-partial-union-cases ~[%tests %golden ~.types-partial-union-cases %source %jibb] src-396 `typ-396))
2040+++ test-types-partial-union-edges
2041+ (weld (check ~.types-partial-union-edges src-397 `tok-397 `tre-397) (check-types ~.types-partial-union-edges ~[%tests %golden ~.types-partial-union-edges %source %jibb] src-397 `typ-397))
20102042++ test-types-partial-unresolved-tag
2011− (weld (check ~.types-partial-unresolved-tag src-393 `tok-393 `tre-393) (check-types ~.types-partial-unresolved-tag ~[%tests %golden ~.types-partial-unresolved-tag %source %jibb] src-393 `typ-393))
2043+ (weld (check ~.types-partial-unresolved-tag src-398 `tok-398 `tre-398) (check-types ~.types-partial-unresolved-tag ~[%tests %golden ~.types-partial-unresolved-tag %source %jibb] src-398 `typ-398))
20122044::
20132045:: +check: run golden:jibb on a case and compare both outputs
20142046::
@@ -2069,4 +2101,18 @@
20692101 |= [case=@ta at=path src=@t want=(unit wain)]
20702102 ^- tang
20712103 (compare (file case "types.txt") want (golden-types:jibb at src))
2104+::
2105+++ check-import-types
2106+ |= [case=@ta at=path src=@t want=(unit wain) fixtures=(list [module=term mold=term source=wain])]
2107+ ^- tang
2108+ ?: (lien fixtures |=(f=[module=term mold=term source=wain] ?=(~ source.f)))
2109+ ~[leaf+"an imported Hoon fixture is missing or empty"]
2110+ =/ external=(list [module=term name=term result=*])
2111+ %+ turn fixtures
2112+ |= fixture=[module=term mold=term source=wain]
2113+ =/ text=@t (rap 3 (turn source.fixture |=(line=@t (cat 3 line '\0a'))))
2114+ =/ cor=type -:(ride -:!>(..zuse) text)
2115+ =/ typ=type (~(play ut cor) (ream (cat 3 '*' mold.fixture)))
2116+ [module.fixture mold.fixture (read-mold-in:jibb-import module.fixture mold.fixture typ cor)]
2117+ (compare (file case "types.txt") want (golden-types-imports:jibb at src external))
20722118--
tools/golden+36−7
@@ -55,7 +55,7 @@ HARNESS = r""":: The harness tools/golden writes after the library. It runs
5555 ==
5656::
5757++ run
58− |= [name=@t metadata=[logical=(unit path) check=?] src=@t]
58+ |= [name=@t metadata=[logical=(unit path) check=? imports=(list [module=term mold=term source=@t])] src=@t]
5959 ^- @t
6060 =/ at=path ?~(logical.metadata (file name) u.logical.metadata)
6161 =/ res (mule |.([(golden:lib at src) {types-expr}]))
@@ -88,9 +88,21 @@ HARNESS = r""":: The harness tools/golden writes after the library. It runs
8888 %+ turn a
8989 |= b=@t
9090 (rap 3 ~[(crip (a-co:co (met 3 b))) ':' b ','])
91+{import-helper}
9192--
9293"""
9394
95+IMPORT_HELPER = r"""
96+++ import-types
97+ |= fixtures=(list [module=term mold=term source=@t])
98+ ^- (list [module=term name=term result=*])
99+ %+ turn fixtures
100+ |= fixture=[module=term mold=term source=@t]
101+ =/ cor=type -:(ride -:!>(..zuse) source.fixture)
102+ =/ typ=type (~(play ut cor) (ream (cat 3 '*' mold.fixture)))
103+ [module.fixture mold.fixture (read-mold-in:reader module.fixture mold.fixture typ cor)]
104+"""
105+
94106
95107EPILOG = """\
96108A file holds its output plus one trailing newline. A crash's output is
@@ -108,6 +120,7 @@ class Case:
108120 self.source_path = os.path.join(folder, 'source.jibb')
109121 try:
110122 self.logical_path = golden_case.source_path(folder)
123+ self.imports = golden_case.sur_imports(folder)
111124 except ValueError as e:
112125 raise ue.ToolError(str(e))
113126 self.want_types = golden_case.wants_types(folder)
@@ -143,10 +156,17 @@ def run_lines(case):
143156 into several cords, as Hoon reads a long cord literal in about
144157 quadratic time (ue.cord_pieces)."""
145158 lines = ue.cord_pieces(case.source)
146− out = [' %%^ run %s [%s %s]' % (
159+ fixtures = []
160+ for module, mold, path in case.imports:
161+ with open(path, 'rb') as f:
162+ parts = ue.cord_pieces(f.read())
163+ source = '(rap 3 `(list @t)`~[%s])' % ' '.join(ue.cord_literal(p) for p in parts)
164+ fixtures.append('[%%%s %%%s %s]' % (module, mold, source))
165+ imports = '~[' + ' '.join(fixtures) + ']' if fixtures else '~'
166+ out = [' %%^ run %s [%s %s %s]' % (
147167 ue.cord_literal(case.name.encode()),
148168 '`' + case.logical_path if case.logical_path else '~',
149− '%.y' if case.want_types else '%.n'),
169+ '%.y' if case.want_types else '%.n', imports),
150170 ' %- text',
151171 ' :~ ' + ue.cord_literal(lines[0])]
152172 out += [' ' + ue.cord_literal(line) for line in lines[1:]]
@@ -157,11 +177,20 @@ def run_lines(case):
157177def golden_program(lib_path, cases):
158178 prog = ue.library_program(lib_path)
159179 runs = '\n'.join(line for case in cases for line in run_lines(case))
160− prog.add(HARNESS.replace('{count}', str(len(cases)))
180+ imported = any(c.imports for c in cases)
181+ harness = HARNESS
182+ if imported:
183+ reader = ue.read_text(os.path.join(ue.ROOT, 'jibb-dev', 'lib', 'jibb-import.hoon'))
184+ harness = harness.replace('=> [lib=. ..zuse]',
185+ '=/ jibb-lib .\n=/ reader\n' + reader +
186+ '\n=> [lib=jibb-lib reader=reader ..zuse]')
187+ types_expr = ("?:(check.metadata ?~(imports.metadata (golden-types:lib at src) "
188+ "(golden-types-imports:lib at src (import-types imports.metadata))) '')"
189+ if imported else "?:(check.metadata (golden-types:lib at src) '')")
190+ prog.add(harness.replace('{count}', str(len(cases)))
161191 .replace('{runs}', runs)
162− .replace('{types-expr}',
163− '?:(check.metadata (golden-types:lib at src) \'\')'
164− if any(c.want_types for c in cases) else "''"),
192+ .replace('{types-expr}', types_expr if any(c.want_types for c in cases) else "''")
193+ .replace('{import-helper}', IMPORT_HELPER if imported else ''),
165194 '(harness)', 'harness')
166195 return prog
167196
tools/golden_case.py+34
@@ -3,6 +3,7 @@ import os
33import re
44
55KNOT = re.compile(r'^[a-z0-9.\-_~]+$')
6+TERM = re.compile(r'^[a-z][a-z0-9-]*$')
67
78
89def source_path(folder):
@@ -33,3 +34,36 @@ def wants_types(folder):
3334 except FileNotFoundError:
3435 marked = False
3536 return marked or os.path.isfile(os.path.join(folder, 'types.txt'))
37+
38+
39+def sur_imports(folder):
40+ """Selected /sur molds as (module, mold, fixture path), in file order.
41+
42+ fixtures are plain text so the ship's -test does not build them as Hoon
43+ test files. Each module is compiled once per selected mold for now.
44+ """
45+ filename = os.path.join(folder, 'imports.txt')
46+ try:
47+ with open(filename, encoding='utf-8') as f:
48+ lines = list(f)
49+ except FileNotFoundError:
50+ return []
51+ except UnicodeError:
52+ raise ValueError('%s: imports must be UTF-8' % filename)
53+ out, seen = [], set()
54+ for number, line in enumerate(lines, 1):
55+ parts = line.split()
56+ if len(parts) != 2 or not all(TERM.fullmatch(p) for p in parts):
57+ raise ValueError('%s:%d: expected a module and mold name' %
58+ (filename, number))
59+ module, mold = parts
60+ if (module, mold) in seen:
61+ raise ValueError('%s:%d: duplicate imported mold' % (filename, number))
62+ fixture = os.path.join(folder, 'sur', module + '.txt')
63+ if not os.path.isfile(fixture):
64+ raise ValueError('%s:%d: no fixture at %s' % (filename, number, fixture))
65+ seen.add((module, mold))
66+ out.append((module, mold, fixture))
67+ if out and not wants_types(folder):
68+ raise ValueError('%s: imported molds require a types output' % filename)
69+ return out
tools/importer-test+1−1
@@ -25,4 +25,4 @@ if result.stdout != expected:
2525 result.stdout.decode().splitlines(keepends=True),
2626 fromfile='expected tree.txt', tofile='actual types'))
2727 sys.exit(1)
28−print('importer golden: 35 projections passed')
28+print('importer golden: 40 projections passed')
tools/ship+36−3
@@ -1052,7 +1052,14 @@ def arm_names(names):
10521052
10531053def generate_tests(golden):
10541054 cases = golden_cases(golden)
1055− lines = [fill(TESTS_HEADER, SOURCE=show(golden)).rstrip('\n'), '/+ jibb']
1055+ has_imports = False
1056+ for _, folder in cases:
1057+ try:
1058+ has_imports |= bool(golden_case.sur_imports(folder))
1059+ except ValueError as e:
1060+ raise Unable(str(e))
1061+ lines = [fill(TESTS_HEADER, SOURCE=show(golden)).rstrip('\n'),
1062+ '/+ jibb, jibb-import' if has_imports else '/+ jibb']
10561063 arms = []
10571064 for i, ((name, folder), arm) in enumerate(
10581065 zip(cases, arm_names([c[0] for c in cases])), 1):
@@ -1062,6 +1069,7 @@ def generate_tests(golden):
10621069 # path literal in Hoon can't, though /* takes them
10631070 try:
10641071 logical = golden_case.source_path(folder)
1072+ imports = golden_case.sur_imports(folder)
10651073 except ValueError as e:
10661074 raise Unable(str(e))
10671075 args = ['~.%s' % name]
@@ -1083,8 +1091,17 @@ def generate_tests(golden):
10831091 else:
10841092 expected_types = '~'
10851093 path = logical or '~[%%tests %%golden ~.%s %%source %%jibb]' % name
1086− call = '(weld %s (check-types ~.%s %s src-%d %s))' % (
1087− call, name, path, i, expected_types)
1094+ if imports:
1095+ fixtures = []
1096+ for j, (module, mold, _) in enumerate(imports, 1):
1097+ face = 'imp-%d-%d' % (i, j)
1098+ lines.append('/* %s %%txt %s/sur/%s/txt' % (face, base, module))
1099+ fixtures.append('[%%%s %%%s %s]' % (module, mold, face))
1100+ call = '(weld %s (check-import-types ~.%s %s src-%d %s ~[%s]))' % (
1101+ call, name, path, i, expected_types, ' '.join(fixtures))
1102+ else:
1103+ call = '(weld %s (check-types ~.%s %s src-%d %s))' % (
1104+ call, name, path, i, expected_types)
10881105 arms.append('++ %s\n %s' % (arm, call))
10891106 lines.append('|%')
10901107 if arms:
@@ -1098,6 +1115,22 @@ def generate_tests(golden):
10981115 |= [case=@ta at=path src=@t want=(unit wain)]
10991116 ^- tang
11001117 (compare (file case "types.txt") want (golden-types:jibb at src))
1118+'''
1119+ if has_imports:
1120+ types_helper += '''::
1121+++ check-import-types
1122+ |= [case=@ta at=path src=@t want=(unit wain) fixtures=(list [module=term mold=term source=wain])]
1123+ ^- tang
1124+ ?: (lien fixtures |=(f=[module=term mold=term source=wain] ?=(~ source.f)))
1125+ ~[leaf+"an imported Hoon fixture is missing or empty"]
1126+ =/ external=(list [module=term name=term result=*])
1127+ %+ turn fixtures
1128+ |= fixture=[module=term mold=term source=wain]
1129+ =/ text=@t (rap 3 (turn source.fixture |=(line=@t (cat 3 line '\\0a'))))
1130+ =/ cor=type -:(ride -:!>(..zuse) text)
1131+ =/ typ=type (~(play ut cor) (ream (cat 3 '*' mold.fixture)))
1132+ [module.fixture mold.fixture (read-mold-in:jibb-import module.fixture mold.fixture typ cor)]
1133+ (compare (file case "types.txt") want (golden-types-imports:jibb at src external))
11011134'''
11021135 return '\n'.join(lines) + '\n' + TESTS_HELPERS.replace('\n--\n', '\n' + types_helper + '--\n')
11031136
tools/testdata/selftest+13
@@ -171,6 +171,19 @@ def check_types_and_logical_path(c, tmp):
171171 f.write('/ui/api/../todo.jibb\n')
172172 status, out = golden('--dir', cases, '--lib', STUB, '--case', 'basic')
173173 c.expect(status == 2, 'invalid path: %d\n%s' % (status, out))
174+ os.remove(os.path.join(folder, 'path.txt'))
175+ with open(os.path.join(folder, 'imports.txt'), 'w') as f:
176+ f.write('missing title\n')
177+ status, out = golden('--dir', cases, '--lib', STUB, '--case', 'basic')
178+ c.expect(status == 2 and 'no fixture' in out, 'missing fixture: ' + out)
179+ os.makedirs(os.path.join(folder, 'sur'))
180+ with open(os.path.join(folder, 'sur', 'missing.txt'), 'w') as f:
181+ f.write('|%\n+$ title @t\n--\n')
182+ with open(os.path.join(folder, 'imports.txt'), 'w') as f:
183+ f.write('missing title\nmissing title\n')
184+ status, out = golden('--dir', cases, '--lib', STUB, '--case', 'basic')
185+ c.expect(status == 2 and 'duplicate imported mold' in out,
186+ 'duplicate imported mold: ' + out)
174187
175188
176189def check_mismatch_diff(c, tmp):
tools/testdata/ship-selftest+45
@@ -151,6 +151,51 @@ def generator_checks(tmp):
151151 bad_path = False
152152 check('invalid logical paths are rejected', bad_path)
153153
154+ imported = os.path.join(tmp, 'imported')
155+ write_case(imported, 'molds', b'/- fixture\n++ x 1\n')
156+ folder = os.path.join(imported, 'molds')
157+ os.makedirs(os.path.join(folder, 'sur'))
158+ with open(os.path.join(folder, 'types.txt'), 'w') as f:
159+ f.write('expected\n')
160+ with open(os.path.join(folder, 'sur', 'fixture.txt'), 'w') as f:
161+ f.write('|%\n+$ title @t\n--\n')
162+ with open(os.path.join(folder, 'imports.txt'), 'w') as f:
163+ f.write('fixture title\n')
164+ out = ship.generate_tests(imported)
165+ check('selected Hoon molds are supplied to the checker on the ship',
166+ '/+ jibb, jibb-import\n' in out and
167+ '/tests/golden/molds/sur/fixture/txt' in out and
168+ '[%fixture %title imp-1-1]' in out and
169+ '(golden-types-imports:jibb at src external)' in out, out)
170+ with open(os.path.join(folder, 'imports.txt'), 'a') as f:
171+ f.write('fixture title\n')
172+ try:
173+ ship.generate_tests(imported)
174+ except ship.Unable as e:
175+ bad_import = 'duplicate imported mold' in str(e)
176+ else:
177+ bad_import = False
178+ check('duplicate imported molds are rejected', bad_import)
179+ with open(os.path.join(folder, 'imports.txt'), 'w') as f:
180+ f.write('missing title\n')
181+ try:
182+ ship.generate_tests(imported)
183+ except ship.Unable as e:
184+ missing_import = 'no fixture' in str(e)
185+ else:
186+ missing_import = False
187+ check('missing imported Hoon fixtures are rejected', missing_import)
188+ with open(os.path.join(folder, 'imports.txt'), 'w') as f:
189+ f.write('fixture title\n')
190+ os.remove(os.path.join(folder, 'types.txt'))
191+ try:
192+ ship.generate_tests(imported)
193+ except ship.Unable as e:
194+ no_types = 'require a types output' in str(e)
195+ else:
196+ no_types = False
197+ check('import fixtures require type output', no_types)
198+
154199 normal = ship.assemble('jibb-dev')
155200 normal_tests = {p for p in normal.files if p.startswith('tests/lib/') and
156201 p.endswith('.hoon')}