on master help sign in
Infer local definitions and parse module fixtures
commit1b7dbae4f80500e867bf413b67fd61e9d5090124 authoriko <mail@iko.soy> dateFri 30 Oct 2026, 18:32 (10 hours ago) parent2d5deb2
40 files changed+1421−341
README.md+1−1 docs/compiler.md+1−1 docs/development.md+3−2 docs/prelude-inventory.md+3−3 docs/status.md+8−7 jibb-dev/lib/jibb.hoon+69−2 jibb-dev/lib/jibb/prelude.jibb+20 tests/golden/module-fixture-eof/about.txt+3 tests/golden/module-fixture-eof/module-trees.txt+4 tests/golden/module-fixture-eof/modules.txt+1 tests/golden/module-fixture-eof/modules/ui/incomplete.jibb+1 tests/golden/module-fixture-eof/source.jibb+1 tests/golden/module-fixture-eof/tokens.txt+4 tests/golden/module-fixture-eof/tree.txt+2 tests/golden/prelude-unit-list-transforms/about.txt+2−2 tests/golden/prelude-unit-list-transforms/source.jibb+20 tests/golden/prelude-unit-list-transforms/tokens.txt+197−72 tests/golden/prelude-unit-list-transforms/tree.txt+87−34 tests/golden/prelude-unit-list-transforms/types.txt+2 tests/golden/types-module-fixtures/about.txt+4 tests/golden/types-module-fixtures/module-trees.txt+13 tests/golden/types-module-fixtures/modules.txt+2 tests/golden/types-module-fixtures/modules/ui/api/blog.jibb+5 tests/golden/types-module-fixtures/modules/ui/components/card.jibb+5 tests/golden/types-module-fixtures/path.txt+1 tests/golden/types-module-fixtures/source.jibb+9 tests/golden/types-module-fixtures/tokens.txt+62 tests/golden/types-module-fixtures/tree.txt+23 tests/golden/types-module-fixtures/types.txt+4 tests/golden/types-partial-locals/about.txt+8 tests/golden/types-partial-locals/source.jibb+44 tests/golden/types-partial-locals/tokens.txt+239 tests/golden/types-partial-locals/tree.txt+122 tests/golden/types-partial-locals/types.txt+32 tests/lib/jibb.hoon+248−205 tools/golden+45−11 tools/golden_case.py+30 tools/ship+42−1 tools/testdata/selftest+30 tools/testdata/ship-selftest+24
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. A case can select Hoon molds in `imports.txt` and provide each module in `sur/<module>.txt`, or select marks in `marks.txt` and provide their source in `mar/<name>.txt`, as described in [docs/development.md](docs/development.md).
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`, or select marks in `marks.txt` and provide their source in `mar/<name>.txt`. `modules.txt` selects Jibb source fixtures, currently parsed but not typechecked; their trees go in `module-trees.txt`. See [docs/development.md](docs/development.md).
2020
2121Run them without a ship. This needs `urbit` on PATH and Python 3.
2222
docs/compiler.md+1−1
@@ -56,7 +56,7 @@ 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, unrestricted `@`, one-way widening into it and toward aura-family ancestors, 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 can infer and generalize atom constraints arising from explicit capitals or bare sample binders, preserve those constraints through aliases, instantiate them independently, and print multiple constraints. Unresolved decimal variables default to `@ud` for inferred types without gates; defaulting inside gate types and other constraint cases remain incomplete. It does not yet check a module, its imports, faces, general patterns, deferred constraints, recursive or generic molds, dependency cycles or most errors with both conflicting excerpts. Definite cast and call mismatches, incompatible branches and overlapping union cases report both sites and excerpts. Concrete branch results can join at an explicitly present parent aura or `@`; function compatibility involving nested `@` and variable-dependent joins remain unsupported except for equal types. The current dependency pass can take quadratic time on long forward chains; the milestone's speed target remains unverified. A separate conservative pass reports unions whose cases are provably disjoint or overlapping and leaves other cases unresolved; it does not claim the mold is checked. Unsupported forms are reported as such, and the partial output says the module has not been checked.
59+The inference fragment supports fixed auras, unrestricted `@`, one-way widening into it and toward aura-family ancestors, generic variables and gates, 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. Acyclic local value definitions can refer forward and generalize variables that are free of their enclosing environment; captured variables and explicit capitals remain shared. Local molds and recursive local groups remain unsupported. It can infer and generalize atom constraints arising from explicit capitals or bare sample binders, preserve those constraints through aliases, instantiate them independently, and print multiple constraints. Unresolved decimal variables default to `@ud` for inferred types without gates; defaulting inside gate types and other constraint cases remain incomplete. It does not yet check a module, its imports, faces, general patterns, deferred constraints, recursive or generic molds, dependency cycles or most errors with both conflicting excerpts. Definite cast and call mismatches, incompatible branches and overlapping union cases report both sites and excerpts. Concrete branch results can join at an explicitly present parent aura or `@`; function compatibility involving nested `@` and variable-dependent joins remain unsupported except for equal types. The current dependency pass can take quadratic time on long forward chains; the milestone's speed target remains unverified. A separate conservative pass reports unions whose cases are provably disjoint or overlapping and leaves other cases unresolved; it does not claim the mold is checked. Unsupported forms are reported as such, and the partial output says the module has not been checked.
6060
6161The separate `jibb-dev/lib/jibb-import.hoon` is an unfinished reader for selected Hoon type graphs. It handles named recursion, nested map, set, queue, list, unit, jar and jug arguments, direct ordered maps, and direct `$^` unions whose source branches can be proved disjoint. It also reads ordered map fields in records when the map arguments are syntactically fixed atom molds and other fields are fixed atom molds or standard collections of static atom molds. Collection names must not be shadowed. The reader can also import a nonrecursive mark door sample, removing its outer sample face and validating its build subject; recursive mark samples fail closed until their source modules are tracked. Nested `$^`, other nested ordered maps, general source-level disjointness and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms and unfaced cells from caller-supplied reader results for declared `/-` imports; `+golden-types-with-marks` accepts those same shapes from declared mark imports in a separate list. Other forms remain unsupported. Its disjointness proof is conservative and can reject a valid union it cannot prove disjoint. Collection recognition requires the originating `/sur` core. The reader validates direct zuse subjects and Ford subjects consisting of faced imported cores and a validated tail, checking imported cores transitively; it rejects shadowed names, inconsistent core subjects and other subject shapes. Recursive results with Ford imports are rejected until references retain their source module. Its fixtures include three real Tlon files; `tools/importer-test` compares the internal projection under eval, and the ship test compares the same golden output. `tools/type-import-test` and `tools/type-mark-test` compare bridge reports under eval and on the ship. `tools/clay-fixtures` also passes Clay-built `/sur` molds and mark samples through the Clay-built importer and partial checker.
6262
docs/development.md+3−2
@@ -79,7 +79,7 @@ tools/importer-test # Hoon importer fixture projections match
7979tools/type-import-test # importer/checker bridge golden report matches
8080tools/type-mark-test # mark/checker bridge golden report matches
8181tools/hoon check-spans-test # prints <<>>
82−tools/testdata/selftest # 20 checks, 0 failed
82+tools/testdata/selftest # 21 checks, 0 failed
8383tools/doc-blocks docs/spec # every jibb block has its case
8484tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
8585tools/ship test # the cases pass as -test arms on the ship
@@ -99,7 +99,8 @@ A case is a folder `tests/golden/<name>/` holding:
9999- the expected outputs, `tokens.txt` and `tree.txt`, each the output plus one newline.
100100- optionally, `path.txt`, the logical `/ui/.../*.jibb` path to pass to the compiler; the source remains `source.jibb`.
101101- 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.
102−- 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. `marks.txt` selects marks, one name per line, with source in `mar/<name>.txt`; both kinds may be supplied together. The reader results go to the partial checker, and a type output is required. Both runners reconstruct fixture text from `%txt` lines and identify the fixture if its compilation crashes; a crash fails the case without discarding its successful parse output. These fixtures currently handle only sources without Ford imports, not Jibb module fixtures.
102+- 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. `marks.txt` selects marks, one name per line, with source in `mar/<name>.txt`; both kinds may be supplied together. The reader results go to the partial checker, and a type output is required. Both runners reconstruct fixture text from `%txt` lines and identify the fixture if its compilation crashes; a crash fails the case without discarding its successful parse output. These fixtures currently handle only sources without Ford imports.
103+- optionally, `modules.txt` lists logical `/ui/.../*.jibb` paths, one per line. The corresponding sources live below the case's `modules/ui/` directory. Both runners parse each source at its logical path and compare the combined `module-trees.txt`; `--update` writes that output. This checks fixture syntax only: module imports and their types are not resolved by the partial checker.
103104
104105A zero-byte mark fixture currently fails ship synchronization validation after commit. Use a newline-only fixture to test an empty Hoon source on the ship.
105106
docs/prelude-inventory.md+3−3
@@ -27,9 +27,9 @@ The following is an audit of the Hoon 135 bodies, not a completed Jibb interface
2727| `biff` | Applies a gate returning a unit to a present value; absent stays absent. | Written |
2828| `bind` | Applies a gate to a present value and wraps the result; absent stays absent. | Written |
2929| `bond` | Calls a fallback trap for an absent unit, otherwise returns its value. | Missing |
30−| `both` | Returns a unit of both values when both units are present. | Missing |
31−| `clap` | Returns the present unit if only one is present; combines both values with a gate if both are present. | Missing |
32−| `clef` | Applies a gate returning a unit when both inputs are present; otherwise returns an absent unit. | Missing |
30+| `both` | Returns a unit of both values when both units are present. | Written |
31+| `clap` | Returns the present unit if only one is present; combines both values with a gate if both are present. | Missing; Hoon permits different input and output types |
32+| `clef` | Applies a gate returning a unit when both inputs are present; otherwise returns an absent unit. | Written |
3333| `drop` | Converts an absent unit to an empty list and a present unit to a singleton. | Written |
3434| `fall` | Returns the value of a present unit or the supplied fallback. | Written |
3535| `flit` | Returns a gate that wraps a value only if it satisfies the predicate. | Missing |
docs/status.md+8−7
@@ -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; partial bridges pass selected Hoon atoms and unfaced cells from `/sur` molds and marks into inference. The reader handles nonrecursive mark samples, named recursion without Ford imports, nested collections, direct ordered maps, certain ordered-map fields, and direct `$^` unions whose cases can be proved disjoint. Recursive mark samples and recursive molds in Ford-importing subjects fail closed until their origin is tracked. Nested `$^`, other nested ordered maps, general union disjointness and complete import integration remain unfinished. The inference fragment supports unrestricted `@`, selected one-way widenings including aura-family ancestors, and generalized atom constraints arising from explicit capitals or bare sample binders, including aliases. Unfixed decimal literals default to `@ud` in gate-free inferred types; other constraint cases and defaulting inside gate types still need work. Collection recognition checks the originating core and fails closed on shadows or unsupported Ford subject shapes; its golden fixtures include three real Tlon files. The prelude currently has only a few functions, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
22+The repository spec records the subsequent type-system and prelude decisions; those changes also need synchronization to the Claude document. An initial inference fragment and a standalone Hoon type reader are being tested. The fragment explicitly reports that it does not check a module; partial bridges pass selected Hoon atoms and unfaced cells from `/sur` molds and marks into inference. The reader handles nonrecursive mark samples, named recursion without Ford imports, nested collections, direct ordered maps, certain ordered-map fields, and direct `$^` unions whose cases can be proved disjoint. Recursive mark samples and recursive molds in Ford-importing subjects fail closed until their origin is tracked. Nested `$^`, other nested ordered maps, general union disjointness and complete import integration remain unfinished. The inference fragment supports unrestricted `@`, selected one-way widenings including aura-family ancestors, generalized atom constraints arising from explicit capitals or bare sample binders, and acyclic local definitions with captures. Unfixed decimal literals default to `@ud` in gate-free inferred types; recursive local groups, local molds, other constraint cases and defaulting inside gate types still need work. Collection recognition checks the originating core and fails closed on shadows or unsupported Ford subject shapes; its golden fixtures include three real Tlon files. The prelude currently has only a few functions, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
2323
2424## Milestone 1: parser and mark
2525
@@ -37,9 +37,9 @@ What the plan asks for, and where it is:
3737
3838Besides the plan's list:
3939
40−- 412 golden cases: 196 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 412-case corpus passed under `urbit eval` in 21.8 s. The fake ship passed all 416 tests, including the importer, importer/checker and mark/checker bridges, and unification checks, with 19.1 s for sync and 22.5 s for tests. The importer golden compares 74 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, reads selected molds and marks, and passes Clay-built types through the Clay-built importer and partial checker.
42−- `tools/testdata/selftest` (20 checks) and `tools/testdata/ship-selftest` test the tools themselves.
40+- 415 golden cases: 199 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 415-case corpus passed under `urbit eval` in 22.0 s. The fake ship passed all 419 tests, including the importer, importer/checker and mark/checker bridges, and unification checks, with 20.8 s for sync and 19.7 s for tests. The importer golden compares 74 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, reads selected molds and marks, and passes Clay-built types through the Clay-built importer and partial checker.
42+- `tools/testdata/selftest` (21 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).
4545
@@ -61,14 +61,15 @@ Besides the plan's list:
6161| fbeaa83 | 2026-10-30 | Extend atom constraints and nested ordered-map imports; connect Clay types to partial inference |
6262| 47a1f49 | 2026-10-30 | Read validated Ford imports, widen aura families, and show both sites of selected errors |
6363| bd37989 | 2026-10-30 | Read mark samples and test partial mark imports; reject unproven nested `$^`; preserve atom constraints through aliases |
64−| This change | 2026-10-30 | Default gate-free decimal types, validate named Hoon mold lookup, and isolate fixture failures |
64+| 2d5deb2 | 2026-10-30 | Default gate-free decimal types, validate named Hoon mold lookup, and isolate fixture failures |
65+| This change | 2026-10-30 | Infer acyclic local definitions and parse case-local Jibb module fixtures |
6566
6667## Checking it
6768
6869On a machine set up as [development.md](development.md) says:
6970
7071```
71−tools/golden # 412 cases under urbit eval
72+tools/golden # 415 cases under urbit eval
7273tools/importer-test # the Hoon importer fixture projection
7374tools/type-import-test # the importer/checker bridge fixture
7475tools/type-mark-test # the mark/checker bridge fixture
@@ -77,7 +78,7 @@ tools/testdata/selftest # the tools themselves
7778tools/doc-blocks docs/spec # the doc's examples are golden cases
7879tools/ship start
7980tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
80−tools/ship test # the same 412 cases as -test arms on the ship
81+tools/ship test # the same 415 cases as -test arms on the ship
8182tools/testdata/ship-selftest
8283tools/ship check-commit # |commit stores .jibb files
8384tools/clay-fixtures # example /sur files and marks build through Clay
jibb-dev/lib/jibb.hoon+69−2
@@ -5182,6 +5182,65 @@
51825182 * [%| "sample is not supported by partial inference"]
51835183 ==
51845184::
5185+:: Local definitions generalize only variables outside their enclosing
5186+:: environment and explicit-capital scope. Unresolved groups stay
5187+:: unsupported: this fragment does not infer recursive definitions.
5188+::
5189++$ ilocal-result (each [env=ienv state=istate] idiag)
5190+++ free-env-vars
5191+ |= [env=ienv sub=isub]
5192+ ^- (list @ud)
5193+ ?~ env ~
5194+ =/ sc=ischeme scheme.i.env
5195+ =/ ids=(list @ud) (unique-type-vars (itype-vars typ.sc))
5196+ =/ free=(list @ud) ~
5197+ |-
5198+ ?~ ids (weld free (free-env-vars t.env sub))
5199+ ?: (lien vars.sc |=(n=@ud =(n i.ids))) $(ids t.ids)
5200+ =/ resolved=itype (itype-normalize [%var i.ids] sub)
5201+ $(ids t.ids, free (weld (itype-vars resolved) free))
5202+::
5203+++ free-cap-vars
5204+ |= [caps=icaps sub=isub]
5205+ ^- (list @ud)
5206+ ?~ caps ~
5207+ (weld (itype-vars (itype-normalize [%var id.i.caps] sub)) $(caps t.caps))
5208+::
5209+++ local-names-valid
5210+ |= [ds=(list def) env=ienv state=istate]
5211+ ^- ?
5212+ =/ names=(list term) (global-value-names ds)
5213+ |-
5214+ ?~ ds &
5215+ ?. ?=(%value -.i.ds) |
5216+ ?. (unique-value-name name.i.ds names) |
5217+ ?: ?=(^ (ienv-lookup name.i.ds env)) |
5218+ ?: (lien globals.state |=(n=term =(n name.i.ds))) |
5219+ $(ds t.ds)
5220+::
5221+++ infer-local-defs
5222+ |= [ds=(list def) env=ienv state=istate]
5223+ ^- ilocal-result
5224+ =/ remaining=(list def) ~
5225+ =/ progressed=? |
5226+ |-
5227+ ?~ ds
5228+ ?~ remaining [%& env state]
5229+ ?. progressed [%| ["local definitions need unsupported inference" ~]]
5230+ $(ds (flop remaining), remaining ~, progressed |)
5231+ =/ d=def i.ds
5232+ ?> ?=(%value -.d)
5233+ =/ inferred=iresult (infer-fragment val.d env state)
5234+ ?: ?=(%| -.inferred) $(ds t.ds, remaining [d remaining])
5235+ =/ typ=itype (itype-normalize typ.p.inferred sub.state.p.inferred)
5236+ ?: (unsupported-atom-vars typ caps.state.p.inferred binders.state.p.inferred sub.state.p.inferred)
5237+ $(ds t.ds, remaining [d remaining])
5238+ =/ free=(list @ud)
5239+ (weld (free-env-vars env sub.state.p.inferred) (free-cap-vars caps.state.p.inferred sub.state.p.inferred))
5240+ =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
5241+ =. vars (skim vars |=(n=@ud !(lien free |=(f=@ud =(f n)))))
5242+ $(ds t.ds, env [[name.d [typ vars]] env], state state.p.inferred, progressed &)
5243+::
51855244++ infer-fragment
51865245 |= [e=expr env=ienv state=istate]
51875246 ^- iresult
@@ -5216,8 +5275,16 @@
52165275 $(e then.e, state state.p.traced)
52175276 %tuple (infer-simple-items items.e env state)
52185277 %body
5219− ?^ defs.e [%| ["local definitions are not supported by partial inference" ~]]
5220− $(e final.e)
5278+ ?~ defs.e $(e final.e)
5279+ =/ local-names=(list term) (global-value-names defs.e)
5280+ ?. (local-names-valid defs.e env state)
5281+ [%| ["local definitions shadow a name or use an unsupported mold" ~]]
5282+ =/ local-state=istate state(globals (weld local-names globals.state))
5283+ =/ locals=ilocal-result (infer-local-defs defs.e env local-state)
5284+ ?: ?=(%| -.locals) locals
5285+ =/ result=iresult $(e final.e, env env.p.locals, state state.p.locals)
5286+ ?: ?=(%| -.result) result
5287+ [%& typ.p.result state.p.result(globals globals.state)]
52215288 %branch
52225289 ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
52235290 ?~ t.arms.e (infer-cell-branch e env state)
jibb-dev/lib/jibb/prelude.jibb+20
@@ -156,6 +156,26 @@
156156 ~ ~
157157 [~ value] (f value)
158158
159+++ both |= args=[(unit A) (unit B)]
160+ ?- args
161+ [first second]
162+ ?- first
163+ ~ ~
164+ [~ a]
165+ ?- second
166+ ~ ~
167+ [~ b] `[a b]
168+
169+++ clef |= args=[(unit A) (unit B) $-([A B] (unit C))]
170+ ?- args
171+ [first second combine]
172+ ?- first
173+ ~ ~
174+ [~ a]
175+ ?- second
176+ ~ ~
177+ [~ b] (combine a b)
178+
159179++ skim |= args=[(list A) $-(A ?)]
160180 ?- args
161181 [xs predicate]
tests/golden/module-fixture-eof/about.txtnew file+3
@@ -0,0 +1,3 @@
1+source: Grammar, Modules: `+$` takes a mold on its line or its cases on the lines below.
2+tests: The root module parses. The supplied module fixture ends without a newline after `+$ x`; both runners preserve those bytes and report the fixture's missing mold at the same location.
3+expect: parses; the fixture's tree is an error at its end of file
tests/golden/module-fixture-eof/module-trees.txtnew file+4
@@ -0,0 +1,4 @@
1+/ui/incomplete.jibb
2+/ui/incomplete.jibb:1:5: expected a mold, on its line or a deeper one, found the end of the file
3++$ x
4+ ^
tests/golden/module-fixture-eof/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/incomplete.jibb
tests/golden/module-fixture-eof/modules/ui/incomplete.jibbnew file+1
@@ -0,0 +1 @@
1++$ x
tests/golden/module-fixture-eof/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ main 1
tests/golden/module-fixture-eof/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name main
3+1:9 lit 1
4+1:10 NEWLINE
tests/golden/module-fixture-eof/tree.txtnew file+2
@@ -0,0 +1,2 @@
1+(module
2+ (value 1:1 main (lit 1:9 1)))
tests/golden/prelude-unit-list-transforms/about.txt+2−2
@@ -1,4 +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"; Hoon 2a includes `drop`, `bind` and `biff`, and 2b includes `skim` and `skip`.
2−tests: The complete current prelude parses, including unit-to-list conversion, unit mapping and flat mapping, and the complementary list filters. Both filters retain the order of their selected items.
1+source: Overview, Prelude: "The exported inventory includes all names from the Hoon library sections listed below, excluding the groups explicitly left out"; Hoon 2a includes `drop`, `bind`, `biff`, `both` and `clef`, and 2b includes `skim` and `skip`.
2+tests: The complete current prelude parses, including unit-to-list conversion, unit mapping and flat mapping, two ways to combine units, and the complementary list filters. Both filters retain the order of their selected items.
33expect: parses
44expect-types: a partial inference report, not a checked module; unit and list gate typing is not complete
tests/golden/prelude-unit-list-transforms/source.jibb+20
@@ -156,6 +156,26 @@
156156 ~ ~
157157 [~ value] (f value)
158158
159+++ both |= args=[(unit A) (unit B)]
160+ ?- args
161+ [first second]
162+ ?- first
163+ ~ ~
164+ [~ a]
165+ ?- second
166+ ~ ~
167+ [~ b] `[a b]
168+
169+++ clef |= args=[(unit A) (unit B) $-([A B] (unit C))]
170+ ?- args
171+ [first second combine]
172+ ?- first
173+ ~ ~
174+ [~ a]
175+ ?- second
176+ ~ ~
177+ [~ b] (combine a b)
178+
159179++ skim |= args=[(list A) $-(A ?)]
160180 ?- args
161181 [xs predicate]
tests/golden/prelude-unit-list-transforms/tokens.txt+197−72
@@ -955,62 +955,55 @@
955955159:1 DEDENT
956956159:1 NEWLINE
957957159:1 glyph ++
958−159:4 name skim
958+159:4 name both
959959159:9 glyph |=
960960159:12 name args
961961159:16 tight glyph =
962962159:17 tight glyph [
963963159:18 tight glyph (
964−159:19 tight name list
964+159:19 tight name unit
965965159:24 tvar A
966966159:25 tight glyph )
967−159:27 glyph $-(
968−159:30 tight tvar A
969−159:32 glyph ?
970−159:33 tight glyph )
971−159:34 tight glyph ]
967+159:27 glyph (
968+159:28 tight name unit
969+159:33 tvar B
970+159:34 tight glyph )
971+159:35 tight glyph ]
972972160:3 INDENT
973973160:3 glyph ?-
974974160:6 name args
975975161:5 INDENT
976976161:5 glyph [
977−161:6 tight name xs
978−161:9 name predicate
977+161:6 tight name first
978+161:12 name second
979979161:18 tight glyph ]
980980162:7 INDENT
981981162:7 glyph ?-
982−162:10 name xs
982+162:10 name first
983983163:9 INDENT
984984163:9 lit ~
985985163:11 lit ~
986986164:9 NEWLINE
987987164:9 glyph [
988−164:10 tight name item
989−164:15 name rest
990−164:19 tight glyph ]
988+164:10 tight lit ~
989+164:12 name a
990+164:13 tight glyph ]
991991165:11 INDENT
992992165:11 glyph ?-
993−165:14 glyph (
994−165:15 tight name predicate
995−165:25 name item
996−165:29 tight glyph )
993+165:14 name second
997994166:13 INDENT
998−166:13 lit %.y
999−166:17 glyph [
1000−166:18 tight name item
1001−166:23 glyph (
1002−166:24 tight name skim
1003−166:29 name rest
1004−166:34 name predicate
1005−166:43 tight glyph )
1006−166:44 tight glyph ]
995+166:13 lit ~
996+166:15 lit ~
1007997167:13 NEWLINE
1008−167:13 lit %.n
1009−167:17 glyph (
1010−167:18 tight name skim
1011−167:23 name rest
1012−167:28 name predicate
1013−167:37 tight glyph )
998+167:13 glyph [
999+167:14 tight lit ~
1000+167:16 name b
1001+167:17 tight glyph ]
1002+167:19 glyph `
1003+167:20 tight glyph [
1004+167:21 tight name a
1005+167:23 name b
1006+167:24 tight glyph ]
10141007169:1 DEDENT
10151008169:1 DEDENT
10161009169:1 DEDENT
@@ -1019,66 +1012,198 @@
10191012169:1 DEDENT
10201013169:1 NEWLINE
10211014169:1 glyph ++
1022−169:4 name skip
1015+169:4 name clef
10231016169:9 glyph |=
10241017169:12 name args
10251018169:16 tight glyph =
10261019169:17 tight glyph [
10271020169:18 tight glyph (
1028−169:19 tight name list
1021+169:19 tight name unit
10291022169:24 tvar A
10301023169:25 tight glyph )
1031−169:27 glyph $-(
1032−169:30 tight tvar A
1033−169:32 glyph ?
1034−169:33 tight glyph )
1035−169:34 tight glyph ]
1024+169:27 glyph (
1025+169:28 tight name unit
1026+169:33 tvar B
1027+169:34 tight glyph )
1028+169:36 glyph $-(
1029+169:39 tight glyph [
1030+169:40 tight tvar A
1031+169:42 tvar B
1032+169:43 tight glyph ]
1033+169:45 glyph (
1034+169:46 tight name unit
1035+169:51 tvar C
1036+169:52 tight glyph )
1037+169:53 tight glyph )
1038+169:54 tight glyph ]
10361039170:3 INDENT
10371040170:3 glyph ?-
10381041170:6 name args
10391042171:5 INDENT
10401043171:5 glyph [
1041−171:6 tight name xs
1042−171:9 name predicate
1043−171:18 tight glyph ]
1044+171:6 tight name first
1045+171:12 name second
1046+171:19 name combine
1047+171:26 tight glyph ]
10441048172:7 INDENT
10451049172:7 glyph ?-
1046−172:10 name xs
1050+172:10 name first
10471051173:9 INDENT
10481052173:9 lit ~
10491053173:11 lit ~
10501054174:9 NEWLINE
10511055174:9 glyph [
1052−174:10 tight name item
1053−174:15 name rest
1054−174:19 tight glyph ]
1056+174:10 tight lit ~
1057+174:12 name a
1058+174:13 tight glyph ]
10551059175:11 INDENT
10561060175:11 glyph ?-
1057−175:14 glyph (
1058−175:15 tight name predicate
1059−175:25 name item
1060−175:29 tight glyph )
1061+175:14 name second
10611062176:13 INDENT
1062−176:13 lit %.y
1063−176:17 glyph (
1064−176:18 tight name skip
1065−176:23 name rest
1066−176:28 name predicate
1067−176:37 tight glyph )
1063+176:13 lit ~
1064+176:15 lit ~
10681065177:13 NEWLINE
1069−177:13 lit %.n
1070−177:17 glyph [
1071−177:18 tight name item
1072−177:23 glyph (
1073−177:24 tight name skip
1074−177:29 name rest
1075−177:34 name predicate
1076−177:43 tight glyph )
1077−177:44 tight glyph ]
1078−177:45 DEDENT
1079−177:45 DEDENT
1080−177:45 DEDENT
1081−177:45 DEDENT
1082−177:45 DEDENT
1083−177:45 DEDENT
1084−177:45 NEWLINE
1066+177:13 glyph [
1067+177:14 tight lit ~
1068+177:16 name b
1069+177:17 tight glyph ]
1070+177:19 glyph (
1071+177:20 tight name combine
1072+177:28 name a
1073+177:30 name b
1074+177:31 tight glyph )
1075+179:1 DEDENT
1076+179:1 DEDENT
1077+179:1 DEDENT
1078+179:1 DEDENT
1079+179:1 DEDENT
1080+179:1 DEDENT
1081+179:1 NEWLINE
1082+179:1 glyph ++
1083+179:4 name skim
1084+179:9 glyph |=
1085+179:12 name args
1086+179:16 tight glyph =
1087+179:17 tight glyph [
1088+179:18 tight glyph (
1089+179:19 tight name list
1090+179:24 tvar A
1091+179:25 tight glyph )
1092+179:27 glyph $-(
1093+179:30 tight tvar A
1094+179:32 glyph ?
1095+179:33 tight glyph )
1096+179:34 tight glyph ]
1097+180:3 INDENT
1098+180:3 glyph ?-
1099+180:6 name args
1100+181:5 INDENT
1101+181:5 glyph [
1102+181:6 tight name xs
1103+181:9 name predicate
1104+181:18 tight glyph ]
1105+182:7 INDENT
1106+182:7 glyph ?-
1107+182:10 name xs
1108+183:9 INDENT
1109+183:9 lit ~
1110+183:11 lit ~
1111+184:9 NEWLINE
1112+184:9 glyph [
1113+184:10 tight name item
1114+184:15 name rest
1115+184:19 tight glyph ]
1116+185:11 INDENT
1117+185:11 glyph ?-
1118+185:14 glyph (
1119+185:15 tight name predicate
1120+185:25 name item
1121+185:29 tight glyph )
1122+186:13 INDENT
1123+186:13 lit %.y
1124+186:17 glyph [
1125+186:18 tight name item
1126+186:23 glyph (
1127+186:24 tight name skim
1128+186:29 name rest
1129+186:34 name predicate
1130+186:43 tight glyph )
1131+186:44 tight glyph ]
1132+187:13 NEWLINE
1133+187:13 lit %.n
1134+187:17 glyph (
1135+187:18 tight name skim
1136+187:23 name rest
1137+187:28 name predicate
1138+187:37 tight glyph )
1139+189:1 DEDENT
1140+189:1 DEDENT
1141+189:1 DEDENT
1142+189:1 DEDENT
1143+189:1 DEDENT
1144+189:1 DEDENT
1145+189:1 NEWLINE
1146+189:1 glyph ++
1147+189:4 name skip
1148+189:9 glyph |=
1149+189:12 name args
1150+189:16 tight glyph =
1151+189:17 tight glyph [
1152+189:18 tight glyph (
1153+189:19 tight name list
1154+189:24 tvar A
1155+189:25 tight glyph )
1156+189:27 glyph $-(
1157+189:30 tight tvar A
1158+189:32 glyph ?
1159+189:33 tight glyph )
1160+189:34 tight glyph ]
1161+190:3 INDENT
1162+190:3 glyph ?-
1163+190:6 name args
1164+191:5 INDENT
1165+191:5 glyph [
1166+191:6 tight name xs
1167+191:9 name predicate
1168+191:18 tight glyph ]
1169+192:7 INDENT
1170+192:7 glyph ?-
1171+192:10 name xs
1172+193:9 INDENT
1173+193:9 lit ~
1174+193:11 lit ~
1175+194:9 NEWLINE
1176+194:9 glyph [
1177+194:10 tight name item
1178+194:15 name rest
1179+194:19 tight glyph ]
1180+195:11 INDENT
1181+195:11 glyph ?-
1182+195:14 glyph (
1183+195:15 tight name predicate
1184+195:25 name item
1185+195:29 tight glyph )
1186+196:13 INDENT
1187+196:13 lit %.y
1188+196:17 glyph (
1189+196:18 tight name skip
1190+196:23 name rest
1191+196:28 name predicate
1192+196:37 tight glyph )
1193+197:13 NEWLINE
1194+197:13 lit %.n
1195+197:17 glyph [
1196+197:18 tight name item
1197+197:23 glyph (
1198+197:24 tight name skip
1199+197:29 name rest
1200+197:34 name predicate
1201+197:43 tight glyph )
1202+197:44 tight glyph ]
1203+197:45 DEDENT
1204+197:45 DEDENT
1205+197:45 DEDENT
1206+197:45 DEDENT
1207+197:45 DEDENT
1208+197:45 DEDENT
1209+197:45 NEWLINE
tests/golden/prelude-unit-list-transforms/tree.txt+87−34
@@ -390,65 +390,118 @@
390390 (cell 157:9 (lit 157:10 ~) (bind 157:12 value))
391391 (group 157:19
392392 (call 157:20 (wing 157:20 f) (wing 157:22 value)))))))))))
393− (value 159:1 skim
393+ (value 159:1 both
394394 (gate 159:9
395395 (face 159:12 args
396396 (cell 159:17
397− (apply 159:18 list (tvar 159:24 A))
398− (fn 159:27 (tvar 159:30 A) (flag 159:32))))
397+ (apply 159:18 unit (tvar 159:24 A))
398+ (apply 159:27 unit (tvar 159:33 B))))
399399 (body 160:3
400400 (branch 160:3
401401 (wing 160:6 args)
402402 (arm 161:5
403− (cell 161:5 (bind 161:6 xs) (bind 161:9 predicate))
403+ (cell 161:5 (bind 161:6 first) (bind 161:12 second))
404404 (body 162:7
405405 (branch 162:7
406− (wing 162:10 xs)
406+ (wing 162:10 first)
407407 (arm 163:9 (lit 163:9 ~) (lit 163:11 ~))
408408 (arm 164:9
409− (cell 164:9 (bind 164:10 item) (bind 164:15 rest))
409+ (cell 164:9 (lit 164:10 ~) (bind 164:12 a))
410410 (body 165:11
411411 (branch 165:11
412− (group 165:14
413− (call 165:15 (wing 165:15 predicate) (wing 165:25 item)))
414− (arm 166:13
415− (lit 166:13 %.y)
416− (tuple 166:17
417− (wing 166:18 item)
418− (group 166:23
419− (call 166:24 (wing 166:24 skim) (wing 166:29 rest) (wing 166:34 predicate)))))
412+ (wing 165:14 second)
413+ (arm 166:13 (lit 166:13 ~) (lit 166:15 ~))
420414 (arm 167:13
421− (lit 167:13 %.n)
422− (group 167:17
423− (call 167:18 (wing 167:18 skim) (wing 167:23 rest) (wing 167:28 predicate))))))))))))))
424− (value 169:1 skip
415+ (cell 167:13 (lit 167:14 ~) (bind 167:16 b))
416+ (unit 167:19
417+ (tuple 167:20 (wing 167:21 a) (wing 167:23 b))))))))))))))
418+ (value 169:1 clef
425419 (gate 169:9
426420 (face 169:12 args
427421 (cell 169:17
428− (apply 169:18 list (tvar 169:24 A))
429− (fn 169:27 (tvar 169:30 A) (flag 169:32))))
422+ (apply 169:18 unit (tvar 169:24 A))
423+ (apply 169:27 unit (tvar 169:33 B))
424+ (fn 169:36
425+ (cell 169:39 (tvar 169:40 A) (tvar 169:42 B))
426+ (apply 169:45 unit (tvar 169:51 C)))))
430427 (body 170:3
431428 (branch 170:3
432429 (wing 170:6 args)
433430 (arm 171:5
434− (cell 171:5 (bind 171:6 xs) (bind 171:9 predicate))
431+ (cell 171:5 (bind 171:6 first) (bind 171:12 second) (bind 171:19 combine))
435432 (body 172:7
436433 (branch 172:7
437− (wing 172:10 xs)
434+ (wing 172:10 first)
438435 (arm 173:9 (lit 173:9 ~) (lit 173:11 ~))
439436 (arm 174:9
440− (cell 174:9 (bind 174:10 item) (bind 174:15 rest))
437+ (cell 174:9 (lit 174:10 ~) (bind 174:12 a))
441438 (body 175:11
442439 (branch 175:11
443− (group 175:14
444− (call 175:15 (wing 175:15 predicate) (wing 175:25 item)))
445− (arm 176:13
446− (lit 176:13 %.y)
447− (group 176:17
448− (call 176:18 (wing 176:18 skip) (wing 176:23 rest) (wing 176:28 predicate))))
440+ (wing 175:14 second)
441+ (arm 176:13 (lit 176:13 ~) (lit 176:15 ~))
449442 (arm 177:13
450− (lit 177:13 %.n)
451− (tuple 177:17
452− (wing 177:18 item)
453− (group 177:23
454− (call 177:24 (wing 177:24 skip) (wing 177:29 rest) (wing 177:34 predicate))))))))))))))))
443+ (cell 177:13 (lit 177:14 ~) (bind 177:16 b))
444+ (group 177:19
445+ (call 177:20 (wing 177:20 combine) (wing 177:28 a) (wing 177:30 b))))))))))))))
446+ (value 179:1 skim
447+ (gate 179:9
448+ (face 179:12 args
449+ (cell 179:17
450+ (apply 179:18 list (tvar 179:24 A))
451+ (fn 179:27 (tvar 179:30 A) (flag 179:32))))
452+ (body 180:3
453+ (branch 180:3
454+ (wing 180:6 args)
455+ (arm 181:5
456+ (cell 181:5 (bind 181:6 xs) (bind 181:9 predicate))
457+ (body 182:7
458+ (branch 182:7
459+ (wing 182:10 xs)
460+ (arm 183:9 (lit 183:9 ~) (lit 183:11 ~))
461+ (arm 184:9
462+ (cell 184:9 (bind 184:10 item) (bind 184:15 rest))
463+ (body 185:11
464+ (branch 185:11
465+ (group 185:14
466+ (call 185:15 (wing 185:15 predicate) (wing 185:25 item)))
467+ (arm 186:13
468+ (lit 186:13 %.y)
469+ (tuple 186:17
470+ (wing 186:18 item)
471+ (group 186:23
472+ (call 186:24 (wing 186:24 skim) (wing 186:29 rest) (wing 186:34 predicate)))))
473+ (arm 187:13
474+ (lit 187:13 %.n)
475+ (group 187:17
476+ (call 187:18 (wing 187:18 skim) (wing 187:23 rest) (wing 187:28 predicate))))))))))))))
477+ (value 189:1 skip
478+ (gate 189:9
479+ (face 189:12 args
480+ (cell 189:17
481+ (apply 189:18 list (tvar 189:24 A))
482+ (fn 189:27 (tvar 189:30 A) (flag 189:32))))
483+ (body 190:3
484+ (branch 190:3
485+ (wing 190:6 args)
486+ (arm 191:5
487+ (cell 191:5 (bind 191:6 xs) (bind 191:9 predicate))
488+ (body 192:7
489+ (branch 192:7
490+ (wing 192:10 xs)
491+ (arm 193:9 (lit 193:9 ~) (lit 193:11 ~))
492+ (arm 194:9
493+ (cell 194:9 (bind 194:10 item) (bind 194:15 rest))
494+ (body 195:11
495+ (branch 195:11
496+ (group 195:14
497+ (call 195:15 (wing 195:15 predicate) (wing 195:25 item)))
498+ (arm 196:13
499+ (lit 196:13 %.y)
500+ (group 196:17
501+ (call 196:18 (wing 196:18 skip) (wing 196:23 rest) (wing 196:28 predicate))))
502+ (arm 197:13
503+ (lit 197:13 %.n)
504+ (tuple 197:17
505+ (wing 197:18 item)
506+ (group 197:23
507+ (call 197:24 (wing 197:24 skip) (wing 197:29 rest) (wing 197:34 predicate))))))))))))))))
tests/golden/prelude-unit-list-transforms/types.txt+2
@@ -42,5 +42,7 @@ partial inference; module not checked
4242++ drop: sample mold is not supported by partial inference
4343++ bind: sample mold is not supported by partial inference
4444++ biff: sample mold is not supported by partial inference
45+++ both: sample mold is not supported by partial inference
46+++ clef: sample mold is not supported by partial inference
4547++ skim: sample mold is not supported by partial inference
4648++ skip: sample mold is not supported by partial inference
tests/golden/types-module-fixtures/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Overview, worked example 2: the published page imports its API and card component with `/=`.
2+tests: The case carries two Jibb module sources at their logical paths; both runners parse and compare their trees. This only checks the fixture sources, not module import resolution or typing.
3+expect: parses
4+expect-types: a partial report that does not claim module checking
tests/golden/types-module-fixtures/module-trees.txtnew file+13
@@ -0,0 +1,13 @@
1+/ui/api/blog.jibb
2+(module
3+ (mark 2:1 %posts)
4+ (mold 4:1 paths
5+ (cell 5:3 (const 5:4 %posts) (path 5:11 /posts) (ref 5:18 posts))))
6+/ui/components/card.jibb
7+(module
8+ (sur 2:1 blog)
9+ (value 4:1 card
10+ (gate 4:9
11+ (face 4:12 p (ref 4:14 post.blog))
12+ (body 5:3
13+ (call 5:3 (wing 5:3 text) (wing 5:8 title.p))))))
tests/golden/types-module-fixtures/modules.txtnew file+2
@@ -0,0 +1,2 @@
1+/ui/api/blog.jibb
2+/ui/components/card.jibb
tests/golden/types-module-fixtures/modules/ui/api/blog.jibbnew file+5
@@ -0,0 +1,5 @@
1+:: Fixture for the documented examples; not supplied by the design doc.
2+/% %posts
3+
4++$ paths
5+ [%posts /posts posts]
tests/golden/types-module-fixtures/modules/ui/components/card.jibbnew file+5
@@ -0,0 +1,5 @@
1+:: Fixture for the documented examples; not supplied by the design doc.
2+/- blog
3+
4+++ card |= p=post.blog
5+ text title.p
tests/golden/types-module-fixtures/path.txtnew file+1
@@ -0,0 +1 @@
1+/ui/blog/index.jibb
tests/golden/types-module-fixtures/source.jibbnew file+9
@@ -0,0 +1,9 @@
1+/- blog
2+/= api /ui/api/blog
3+/= card /ui/components/card
4+
5+++ main (page load view)
6+++ load |=(~ (posts.api same))
7+
8+++ view |= ps=(list post.blog)
9+ column ~[gap+%s2] (turn ps card.card)
tests/golden/types-module-fixtures/tokens.txtnew file+62
@@ -0,0 +1,62 @@
1+1:1 glyph /-
2+1:5 name blog
3+2:1 NEWLINE
4+2:1 glyph /=
5+2:5 name api
6+2:11 glyph /
7+2:12 tight knot ui
8+2:14 tight glyph /
9+2:15 tight knot api
10+2:18 tight glyph /
11+2:19 tight knot blog
12+3:1 NEWLINE
13+3:1 glyph /=
14+3:5 name card
15+3:11 glyph /
16+3:12 tight knot ui
17+3:14 tight glyph /
18+3:15 tight knot components
19+3:25 tight glyph /
20+3:26 tight knot card
21+5:1 NEWLINE
22+5:1 glyph ++
23+5:4 name main
24+5:9 glyph (
25+5:10 tight name page
26+5:15 name load
27+5:20 name view
28+5:24 tight glyph )
29+6:1 NEWLINE
30+6:1 glyph ++
31+6:4 name load
32+6:9 glyph |=(
33+6:12 tight lit ~
34+6:14 glyph (
35+6:15 tight wing posts.api
36+6:25 name same
37+6:29 tight glyph )
38+6:30 tight glyph )
39+8:1 NEWLINE
40+8:1 glyph ++
41+8:4 name view
42+8:9 glyph |=
43+8:12 name ps
44+8:14 tight glyph =
45+8:15 tight glyph (
46+8:16 tight name list
47+8:21 wing post.blog
48+8:30 tight glyph )
49+9:3 INDENT
50+9:3 name column
51+9:10 glyph ~[
52+9:12 tight name gap
53+9:15 tight glyph +
54+9:16 tight lit %s2
55+9:19 tight glyph ]
56+9:21 glyph (
57+9:22 tight name turn
58+9:27 name ps
59+9:30 wing card.card
60+9:39 tight glyph )
61+9:40 DEDENT
62+9:40 NEWLINE
tests/golden/types-module-fixtures/tree.txtnew file+23
@@ -0,0 +1,23 @@
1+(module
2+ (sur 1:1 blog)
3+ (jibb 2:1 api /ui/api/blog)
4+ (jibb 3:1 card /ui/components/card)
5+ (value 5:1 main
6+ (group 5:9
7+ (call 5:10 (wing 5:10 page) (wing 5:15 load) (wing 5:20 view))))
8+ (value 6:1 load
9+ (gate-wide 6:9
10+ (const 6:12 ~)
11+ (group 6:14
12+ (call 6:15 (wing 6:15 posts.api) (wing 6:25 same)))))
13+ (value 8:1 view
14+ (gate 8:9
15+ (face 8:12 ps
16+ (apply 8:15 list (ref 8:21 post.blog)))
17+ (body 9:3
18+ (call 9:3
19+ (wing 9:3 column)
20+ (list 9:10
21+ (pair 9:12 gap (lit 9:16 %s2)))
22+ (group 9:21
23+ (call 9:22 (wing 9:22 turn) (wing 9:27 ps) (wing 9:30 card.card))))))))
tests/golden/types-module-fixtures/types.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2+++ main: multiple arguments are not supported by partial inference
3+++ load: sample mold is not supported by partial inference
4+++ view: sample mold is not supported by partial inference
tests/golden/types-partial-locals/about.txtnew file+8
@@ -0,0 +1,8 @@
1+Grammar, Modules: "Names may refer to each other in any order, and no name
2+may shadow one already in scope". Definitions at the start of a body are
3+visible to one another and its final expression. Partial inference resolves
4+acyclic local values, generalizing their free variables except those captured
5+from enclosing bindings or explicit capitals. It declines recursive groups,
6+local molds, duplicate names and shadowing. A module remains unchecked.
7+expect: parses
8+expect-types: a partial inference report, not a checked module
tests/golden/types-partial-locals/source.jibbnew file+44
@@ -0,0 +1,44 @@
1+++ global |= g g
2+++ good |= x
3+ ++ first (id ~zod)
4+ ++ id |= y y
5+ ++ capture |= y x
6+ [(capture first) (capture (id "hi"))]
7+++ conflict |= x
8+ ++ capture |= y x
9+ ~& ^- @t (capture ~zod)
10+ ^- @p (capture "hi")
11+++ duplicate |= x
12+ ++ f x
13+ ++ f x
14+ x
15+++ shadow |= x
16+ ++ x ~zod
17+ x
18+++ global-shadow |= x
19+ ++ global x
20+ x
21+++ missing |= x
22+ ++ a b
23+ ++ b a
24+ x
25+++ caps |= x=A
26+ ++ same |= y=A y
27+ ~& (same "hi")
28+ (same ~zod)
29+++ unused-bad |= x
30+ ++ unknown nope
31+ x
32+++ local-mold |= x
33+ +$ item @t
34+ x
35+++ wrap |= y |=(z y)
36+++ through-global |= x
37+ ++ local (wrap x)
38+ ~& ^- @t (local ~zod)
39+ ^- @p (local "hi")
40+++ nested-shadow |= x
41+ ++ f |= y
42+ ++ f y
43+ y
44+ x
tests/golden/types-partial-locals/tokens.txtnew file+239
@@ -0,0 +1,239 @@
1+1:1 glyph ++
2+1:4 name global
3+1:11 glyph |=
4+1:14 name g
5+1:16 name g
6+2:1 NEWLINE
7+2:1 glyph ++
8+2:4 name good
9+2:9 glyph |=
10+2:12 name x
11+3:3 INDENT
12+3:3 glyph ++
13+3:6 name first
14+3:12 glyph (
15+3:13 tight name id
16+3:16 lit ~zod
17+3:20 tight glyph )
18+4:3 NEWLINE
19+4:3 glyph ++
20+4:6 name id
21+4:9 glyph |=
22+4:12 name y
23+4:14 name y
24+5:3 NEWLINE
25+5:3 glyph ++
26+5:6 name capture
27+5:14 glyph |=
28+5:17 name y
29+5:19 name x
30+6:3 NEWLINE
31+6:3 glyph [
32+6:4 tight glyph (
33+6:5 tight name capture
34+6:13 name first
35+6:18 tight glyph )
36+6:20 glyph (
37+6:21 tight name capture
38+6:29 glyph (
39+6:30 tight name id
40+6:33 str "hi"
41+6:37 tight glyph )
42+6:38 tight glyph )
43+6:39 tight glyph ]
44+7:1 DEDENT
45+7:1 NEWLINE
46+7:1 glyph ++
47+7:4 name conflict
48+7:13 glyph |=
49+7:16 name x
50+8:3 INDENT
51+8:3 glyph ++
52+8:6 name capture
53+8:14 glyph |=
54+8:17 name y
55+8:19 name x
56+9:3 NEWLINE
57+9:3 glyph ~&
58+9:6 glyph ^-
59+9:9 aura @t
60+9:12 glyph (
61+9:13 tight name capture
62+9:21 lit ~zod
63+9:25 tight glyph )
64+10:5 INDENT
65+10:5 glyph ^-
66+10:8 aura @p
67+10:11 glyph (
68+10:12 tight name capture
69+10:20 str "hi"
70+10:24 tight glyph )
71+11:1 DEDENT
72+11:1 DEDENT
73+11:1 NEWLINE
74+11:1 glyph ++
75+11:4 name duplicate
76+11:14 glyph |=
77+11:17 name x
78+12:3 INDENT
79+12:3 glyph ++
80+12:6 name f
81+12:8 name x
82+13:3 NEWLINE
83+13:3 glyph ++
84+13:6 name f
85+13:8 name x
86+14:3 NEWLINE
87+14:3 name x
88+15:1 DEDENT
89+15:1 NEWLINE
90+15:1 glyph ++
91+15:4 name shadow
92+15:11 glyph |=
93+15:14 name x
94+16:3 INDENT
95+16:3 glyph ++
96+16:6 name x
97+16:8 lit ~zod
98+17:3 NEWLINE
99+17:3 name x
100+18:1 DEDENT
101+18:1 NEWLINE
102+18:1 glyph ++
103+18:4 name global-shadow
104+18:18 glyph |=
105+18:21 name x
106+19:3 INDENT
107+19:3 glyph ++
108+19:6 name global
109+19:13 name x
110+20:3 NEWLINE
111+20:3 name x
112+21:1 DEDENT
113+21:1 NEWLINE
114+21:1 glyph ++
115+21:4 name missing
116+21:12 glyph |=
117+21:15 name x
118+22:3 INDENT
119+22:3 glyph ++
120+22:6 name a
121+22:8 name b
122+23:3 NEWLINE
123+23:3 glyph ++
124+23:6 name b
125+23:8 name a
126+24:3 NEWLINE
127+24:3 name x
128+25:1 DEDENT
129+25:1 NEWLINE
130+25:1 glyph ++
131+25:4 name caps
132+25:9 glyph |=
133+25:12 name x
134+25:13 tight glyph =
135+25:14 tight tvar A
136+26:3 INDENT
137+26:3 glyph ++
138+26:6 name same
139+26:11 glyph |=
140+26:14 name y
141+26:15 tight glyph =
142+26:16 tight tvar A
143+26:18 name y
144+27:3 NEWLINE
145+27:3 glyph ~&
146+27:6 glyph (
147+27:7 tight name same
148+27:12 str "hi"
149+27:16 tight glyph )
150+28:5 INDENT
151+28:5 glyph (
152+28:6 tight name same
153+28:11 lit ~zod
154+28:15 tight glyph )
155+29:1 DEDENT
156+29:1 DEDENT
157+29:1 NEWLINE
158+29:1 glyph ++
159+29:4 name unused-bad
160+29:15 glyph |=
161+29:18 name x
162+30:3 INDENT
163+30:3 glyph ++
164+30:6 name unknown
165+30:14 name nope
166+31:3 NEWLINE
167+31:3 name x
168+32:1 DEDENT
169+32:1 NEWLINE
170+32:1 glyph ++
171+32:4 name local-mold
172+32:15 glyph |=
173+32:18 name x
174+33:3 INDENT
175+33:3 glyph +$
176+33:6 name item
177+33:11 aura @t
178+34:3 NEWLINE
179+34:3 name x
180+35:1 DEDENT
181+35:1 NEWLINE
182+35:1 glyph ++
183+35:4 name wrap
184+35:9 glyph |=
185+35:12 name y
186+35:14 glyph |=(
187+35:17 tight name z
188+35:19 name y
189+35:20 tight glyph )
190+36:1 NEWLINE
191+36:1 glyph ++
192+36:4 name through-global
193+36:19 glyph |=
194+36:22 name x
195+37:3 INDENT
196+37:3 glyph ++
197+37:6 name local
198+37:12 glyph (
199+37:13 tight name wrap
200+37:18 name x
201+37:19 tight glyph )
202+38:3 NEWLINE
203+38:3 glyph ~&
204+38:6 glyph ^-
205+38:9 aura @t
206+38:12 glyph (
207+38:13 tight name local
208+38:19 lit ~zod
209+38:23 tight glyph )
210+39:5 INDENT
211+39:5 glyph ^-
212+39:8 aura @p
213+39:11 glyph (
214+39:12 tight name local
215+39:18 str "hi"
216+39:22 tight glyph )
217+40:1 DEDENT
218+40:1 DEDENT
219+40:1 NEWLINE
220+40:1 glyph ++
221+40:4 name nested-shadow
222+40:18 glyph |=
223+40:21 name x
224+41:3 INDENT
225+41:3 glyph ++
226+41:6 name f
227+41:8 glyph |=
228+41:11 name y
229+42:5 INDENT
230+42:5 glyph ++
231+42:8 name f
232+42:10 name y
233+43:5 NEWLINE
234+43:5 name y
235+44:3 DEDENT
236+44:3 NEWLINE
237+44:3 name x
238+44:4 DEDENT
239+44:4 NEWLINE
tests/golden/types-partial-locals/tree.txtnew file+122
@@ -0,0 +1,122 @@
1+(module
2+ (value 1:1 global
3+ (gate 1:11 (bind 1:14 g) (wing 1:16 g)))
4+ (value 2:1 good
5+ (gate 2:9
6+ (bind 2:12 x)
7+ (body 3:3
8+ (value 3:3 first
9+ (group 3:12
10+ (call 3:13 (wing 3:13 id) (lit 3:16 ~zod))))
11+ (value 4:3 id
12+ (gate 4:9 (bind 4:12 y) (wing 4:14 y)))
13+ (value 5:3 capture
14+ (gate 5:14 (bind 5:17 y) (wing 5:19 x)))
15+ (tuple 6:3
16+ (group 6:4
17+ (call 6:5 (wing 6:5 capture) (wing 6:13 first)))
18+ (group 6:20
19+ (call 6:21
20+ (wing 6:21 capture)
21+ (group 6:29
22+ (call 6:30 (wing 6:30 id) (str 6:33 "hi")))))))))
23+ (value 7:1 conflict
24+ (gate 7:13
25+ (bind 7:16 x)
26+ (body 8:3
27+ (value 8:3 capture
28+ (gate 8:14 (bind 8:17 y) (wing 8:19 x)))
29+ (trace 9:3
30+ (cast 9:6
31+ (aura 9:9 @t)
32+ (group 9:12
33+ (call 9:13 (wing 9:13 capture) (lit 9:21 ~zod))))
34+ (body 10:5
35+ (cast 10:5
36+ (aura 10:8 @p)
37+ (group 10:11
38+ (call 10:12 (wing 10:12 capture) (str 10:20 "hi")))))))))
39+ (value 11:1 duplicate
40+ (gate 11:14
41+ (bind 11:17 x)
42+ (body 12:3
43+ (value 12:3 f (wing 12:8 x))
44+ (value 13:3 f (wing 13:8 x))
45+ (wing 14:3 x))))
46+ (value 15:1 shadow
47+ (gate 15:11
48+ (bind 15:14 x)
49+ (body 16:3
50+ (value 16:3 x (lit 16:8 ~zod))
51+ (wing 17:3 x))))
52+ (value 18:1 global-shadow
53+ (gate 18:18
54+ (bind 18:21 x)
55+ (body 19:3
56+ (value 19:3 global (wing 19:13 x))
57+ (wing 20:3 x))))
58+ (value 21:1 missing
59+ (gate 21:12
60+ (bind 21:15 x)
61+ (body 22:3
62+ (value 22:3 a (wing 22:8 b))
63+ (value 23:3 b (wing 23:8 a))
64+ (wing 24:3 x))))
65+ (value 25:1 caps
66+ (gate 25:9
67+ (face 25:12 x (tvar 25:14 A))
68+ (body 26:3
69+ (value 26:3 same
70+ (gate 26:11
71+ (face 26:14 y (tvar 26:16 A))
72+ (wing 26:18 y)))
73+ (trace 27:3
74+ (group 27:6
75+ (call 27:7 (wing 27:7 same) (str 27:12 "hi")))
76+ (body 28:5
77+ (group 28:5
78+ (call 28:6 (wing 28:6 same) (lit 28:11 ~zod))))))))
79+ (value 29:1 unused-bad
80+ (gate 29:15
81+ (bind 29:18 x)
82+ (body 30:3
83+ (value 30:3 unknown (wing 30:14 nope))
84+ (wing 31:3 x))))
85+ (value 32:1 local-mold
86+ (gate 32:15
87+ (bind 32:18 x)
88+ (body 33:3
89+ (mold 33:3 item (aura 33:11 @t))
90+ (wing 34:3 x))))
91+ (value 35:1 wrap
92+ (gate 35:9
93+ (bind 35:12 y)
94+ (gate-wide 35:14 (bind 35:17 z) (wing 35:19 y))))
95+ (value 36:1 through-global
96+ (gate 36:19
97+ (bind 36:22 x)
98+ (body 37:3
99+ (value 37:3 local
100+ (group 37:12
101+ (call 37:13 (wing 37:13 wrap) (wing 37:18 x))))
102+ (trace 38:3
103+ (cast 38:6
104+ (aura 38:9 @t)
105+ (group 38:12
106+ (call 38:13 (wing 38:13 local) (lit 38:19 ~zod))))
107+ (body 39:5
108+ (cast 39:5
109+ (aura 39:8 @p)
110+ (group 39:11
111+ (call 39:12 (wing 39:12 local) (str 39:18 "hi")))))))))
112+ (value 40:1 nested-shadow
113+ (gate 40:18
114+ (bind 40:21 x)
115+ (body 41:3
116+ (value 41:3 f
117+ (gate 41:8
118+ (bind 41:11 y)
119+ (body 42:5
120+ (value 42:5 f (wing 42:10 y))
121+ (wing 43:5 y))))
122+ (wing 44:3 x)))))
tests/golden/types-partial-locals/types.txtnew file+32
@@ -0,0 +1,32 @@
1+partial inference; module not checked
2+++ global: $-(A A)
3+++ good: $-(A [A A])
4+++ conflict: cast mold and expression type do not unify
5+/tests/golden/types-partial-locals/source.jibb:10:8: cast mold has type @p
6+ ^- @p (capture "hi")
7+ ^
8+/tests/golden/types-partial-locals/source.jibb:10:11: expression has type @t
9+ ^- @p (capture "hi")
10+ ^
11+++ duplicate: local definitions shadow a name or use an unsupported mold
12+++ shadow: local definitions shadow a name or use an unsupported mold
13+++ global-shadow: local definitions shadow a name or use an unsupported mold
14+++ missing: local definitions need unsupported inference
15+++ caps: call's sample and argument types do not unify
16+/tests/golden/types-partial-locals/source.jibb:28:6: called gate has type $-(@t @t)
17+ (same ~zod)
18+ ^
19+/tests/golden/types-partial-locals/source.jibb:28:11: argument has type @p
20+ (same ~zod)
21+ ^
22+++ unused-bad: local definitions need unsupported inference
23+++ local-mold: local definitions shadow a name or use an unsupported mold
24+++ wrap: $-(A $-(B A))
25+++ through-global: cast mold and expression type do not unify
26+/tests/golden/types-partial-locals/source.jibb:39:8: cast mold has type @p
27+ ^- @p (local "hi")
28+ ^
29+/tests/golden/types-partial-locals/source.jibb:39:11: expression has type @t
30+ ^- @p (local "hi")
31+ ^
32+++ nested-shadow: local definitions need unsupported inference
tests/lib/jibb.hoon+248−205
@@ -1136,171 +1136,187 @@
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-1c-structural/source/jibb
1140−/* tok-373 %txt /tests/golden/prelude-1c-structural/tokens/txt
1141−/* tre-373 %txt /tests/golden/prelude-1c-structural/tree/txt
1142−/* typ-373 %txt /tests/golden/prelude-1c-structural/types/txt
1143−/* src-374 %jibb /tests/golden/prelude-3g-basic/source/jibb
1144−/* tok-374 %txt /tests/golden/prelude-3g-basic/tokens/txt
1145−/* tre-374 %txt /tests/golden/prelude-3g-basic/tree/txt
1146−/* typ-374 %txt /tests/golden/prelude-3g-basic/types/txt
1147−/* src-375 %jibb /tests/golden/prelude-3g-like/source/jibb
1148−/* tok-375 %txt /tests/golden/prelude-3g-like/tokens/txt
1149−/* tre-375 %txt /tests/golden/prelude-3g-like/tree/txt
1150−/* typ-375 %txt /tests/golden/prelude-3g-like/types/txt
1151−/* src-376 %jibb /tests/golden/prelude-3g-structural/source/jibb
1152−/* tok-376 %txt /tests/golden/prelude-3g-structural/tokens/txt
1153−/* tre-376 %txt /tests/golden/prelude-3g-structural/tree/txt
1154−/* typ-376 %txt /tests/golden/prelude-3g-structural/types/txt
1155−/* src-377 %jibb /tests/golden/prelude-core-functions/source/jibb
1156−/* tok-377 %txt /tests/golden/prelude-core-functions/tokens/txt
1157−/* tre-377 %txt /tests/golden/prelude-core-functions/tree/txt
1158−/* typ-377 %txt /tests/golden/prelude-core-functions/types/txt
1159−/* src-378 %jibb /tests/golden/prelude-list-helpers/source/jibb
1160−/* tok-378 %txt /tests/golden/prelude-list-helpers/tokens/txt
1161−/* tre-378 %txt /tests/golden/prelude-list-helpers/tree/txt
1162−/* typ-378 %txt /tests/golden/prelude-list-helpers/types/txt
1163−/* src-379 %jibb /tests/golden/prelude-list-unit/source/jibb
1164−/* tok-379 %txt /tests/golden/prelude-list-unit/tokens/txt
1165−/* tre-379 %txt /tests/golden/prelude-list-unit/tree/txt
1166−/* typ-379 %txt /tests/golden/prelude-list-unit/types/txt
1167−/* src-380 %jibb /tests/golden/prelude-unit-list-transforms/source/jibb
1168−/* tok-380 %txt /tests/golden/prelude-unit-list-transforms/tokens/txt
1169−/* tre-380 %txt /tests/golden/prelude-unit-list-transforms/tree/txt
1170−/* typ-380 %txt /tests/golden/prelude-unit-list-transforms/types/txt
1171−/* src-381 %jibb /tests/golden/types-import-mark/source/jibb
1172−/* tok-381 %txt /tests/golden/types-import-mark/tokens/txt
1173−/* tre-381 %txt /tests/golden/types-import-mark/tree/txt
1174−/* typ-381 %txt /tests/golden/types-import-mark/types/txt
1175−/* imp-381-1 %txt /tests/golden/types-import-mark/sur/fixture/txt
1176−/* mark-381-1 %txt /tests/golden/types-import-mark/mar/label/txt
1177−/* src-382 %jibb /tests/golden/types-import-missing-mold/source/jibb
1178−/* tok-382 %txt /tests/golden/types-import-missing-mold/tokens/txt
1179−/* tre-382 %txt /tests/golden/types-import-missing-mold/tree/txt
1180−/* typ-382 %txt /tests/golden/types-import-missing-mold/types/txt
1181−/* imp-382-1 %txt /tests/golden/types-import-missing-mold/sur/fixture/txt
1182−/* src-383 %jibb /tests/golden/types-import-sur/source/jibb
1183−/* tok-383 %txt /tests/golden/types-import-sur/tokens/txt
1184−/* tre-383 %txt /tests/golden/types-import-sur/tree/txt
1185−/* typ-383 %txt /tests/golden/types-import-sur/types/txt
1186−/* imp-383-1 %txt /tests/golden/types-import-sur/sur/fixture/txt
1187−/* imp-383-2 %txt /tests/golden/types-import-sur/sur/fixture/txt
1188−/* src-384 %jibb /tests/golden/types-partial-apply/source/jibb
1189−/* tok-384 %txt /tests/golden/types-partial-apply/tokens/txt
1190−/* tre-384 %txt /tests/golden/types-partial-apply/tree/txt
1191−/* typ-384 %txt /tests/golden/types-partial-apply/types/txt
1192−/* src-385 %jibb /tests/golden/types-partial-atom-alias/source/jibb
1193−/* tok-385 %txt /tests/golden/types-partial-atom-alias/tokens/txt
1194−/* tre-385 %txt /tests/golden/types-partial-atom-alias/tree/txt
1195−/* typ-385 %txt /tests/golden/types-partial-atom-alias/types/txt
1196−/* src-386 %jibb /tests/golden/types-partial-atom-constraint/source/jibb
1197−/* tok-386 %txt /tests/golden/types-partial-atom-constraint/tokens/txt
1198−/* tre-386 %txt /tests/golden/types-partial-atom-constraint/tree/txt
1199−/* typ-386 %txt /tests/golden/types-partial-atom-constraint/types/txt
1200−/* src-387 %jibb /tests/golden/types-partial-atom-widening/source/jibb
1201−/* tok-387 %txt /tests/golden/types-partial-atom-widening/tokens/txt
1202−/* tre-387 %txt /tests/golden/types-partial-atom-widening/tree/txt
1203−/* typ-387 %txt /tests/golden/types-partial-atom-widening/types/txt
1204−/* src-388 %jibb /tests/golden/types-partial-aura/source/jibb
1205−/* tok-388 %txt /tests/golden/types-partial-aura/tokens/txt
1206−/* tre-388 %txt /tests/golden/types-partial-aura/tree/txt
1207−/* typ-388 %txt /tests/golden/types-partial-aura/types/txt
1208−/* src-389 %jibb /tests/golden/types-partial-aura-family/source/jibb
1209−/* tok-389 %txt /tests/golden/types-partial-aura-family/tokens/txt
1210−/* tre-389 %txt /tests/golden/types-partial-aura-family/tree/txt
1211−/* typ-389 %txt /tests/golden/types-partial-aura-family/types/txt
1212−/* src-390 %jibb /tests/golden/types-partial-aura-generalization/source/jibb
1213−/* tok-390 %txt /tests/golden/types-partial-aura-generalization/tokens/txt
1214−/* tre-390 %txt /tests/golden/types-partial-aura-generalization/tree/txt
1215−/* typ-390 %txt /tests/golden/types-partial-aura-generalization/types/txt
1216−/* src-391 %jibb /tests/golden/types-partial-bare-atom/source/jibb
1217−/* tok-391 %txt /tests/golden/types-partial-bare-atom/tokens/txt
1218−/* tre-391 %txt /tests/golden/types-partial-bare-atom/tree/txt
1219−/* typ-391 %txt /tests/golden/types-partial-bare-atom/types/txt
1220−/* src-392 %jibb /tests/golden/types-partial-branch-widening/source/jibb
1221−/* tok-392 %txt /tests/golden/types-partial-branch-widening/tokens/txt
1222−/* tre-392 %txt /tests/golden/types-partial-branch-widening/tree/txt
1223−/* typ-392 %txt /tests/golden/types-partial-branch-widening/types/txt
1224−/* src-393 %jibb /tests/golden/types-partial-conflicting-sites/source/jibb
1225−/* tok-393 %txt /tests/golden/types-partial-conflicting-sites/tokens/txt
1226−/* tre-393 %txt /tests/golden/types-partial-conflicting-sites/tree/txt
1227−/* typ-393 %txt /tests/golden/types-partial-conflicting-sites/types/txt
1228−/* src-394 %jibb /tests/golden/types-partial-decimal-default/source/jibb
1229−/* tok-394 %txt /tests/golden/types-partial-decimal-default/tokens/txt
1230−/* tre-394 %txt /tests/golden/types-partial-decimal-default/tree/txt
1231−/* typ-394 %txt /tests/golden/types-partial-decimal-default/types/txt
1232−/* src-395 %jibb /tests/golden/types-partial-dependency-chain/source/jibb
1233−/* tok-395 %txt /tests/golden/types-partial-dependency-chain/tokens/txt
1234−/* tre-395 %txt /tests/golden/types-partial-dependency-chain/tree/txt
1235−/* typ-395 %txt /tests/golden/types-partial-dependency-chain/types/txt
1236−/* src-396 %jibb /tests/golden/types-partial-explicit-capital/source/jibb
1237−/* tok-396 %txt /tests/golden/types-partial-explicit-capital/tokens/txt
1238−/* tre-396 %txt /tests/golden/types-partial-explicit-capital/tree/txt
1239−/* typ-396 %txt /tests/golden/types-partial-explicit-capital/types/txt
1240−/* src-397 %jibb /tests/golden/types-partial-forward/source/jibb
1241−/* tok-397 %txt /tests/golden/types-partial-forward/tokens/txt
1242−/* tre-397 %txt /tests/golden/types-partial-forward/tree/txt
1243−/* typ-397 %txt /tests/golden/types-partial-forward/types/txt
1244−/* src-398 %jibb /tests/golden/types-partial-generalization/source/jibb
1245−/* tok-398 %txt /tests/golden/types-partial-generalization/tokens/txt
1246−/* tre-398 %txt /tests/golden/types-partial-generalization/tree/txt
1247−/* typ-398 %txt /tests/golden/types-partial-generalization/types/txt
1248−/* src-399 %jibb /tests/golden/types-partial-identity/source/jibb
1249−/* tok-399 %txt /tests/golden/types-partial-identity/tokens/txt
1250−/* tre-399 %txt /tests/golden/types-partial-identity/tree/txt
1251−/* typ-399 %txt /tests/golden/types-partial-identity/types/txt
1252−/* src-400 %jibb /tests/golden/types-partial-independent-atoms/source/jibb
1253−/* tok-400 %txt /tests/golden/types-partial-independent-atoms/tokens/txt
1254−/* tre-400 %txt /tests/golden/types-partial-independent-atoms/tree/txt
1255−/* typ-400 %txt /tests/golden/types-partial-independent-atoms/types/txt
1256−/* src-401 %jibb /tests/golden/types-partial-many-atom-constraints/source/jibb
1257−/* tok-401 %txt /tests/golden/types-partial-many-atom-constraints/tokens/txt
1258−/* tre-401 %txt /tests/golden/types-partial-many-atom-constraints/tree/txt
1259−/* typ-401 %txt /tests/golden/types-partial-many-atom-constraints/types/txt
1260−/* src-402 %jibb /tests/golden/types-partial-mold-bare-aura/source/jibb
1261−/* tok-402 %txt /tests/golden/types-partial-mold-bare-aura/tokens/txt
1262−/* tre-402 %txt /tests/golden/types-partial-mold-bare-aura/tree/txt
1263−/* typ-402 %txt /tests/golden/types-partial-mold-bare-aura/types/txt
1264−/* src-403 %jibb /tests/golden/types-partial-mold-composite/source/jibb
1265−/* tok-403 %txt /tests/golden/types-partial-mold-composite/tokens/txt
1266−/* tre-403 %txt /tests/golden/types-partial-mold-composite/tree/txt
1267−/* typ-403 %txt /tests/golden/types-partial-mold-composite/types/txt
1268−/* src-404 %jibb /tests/golden/types-partial-mold-forward/source/jibb
1269−/* tok-404 %txt /tests/golden/types-partial-mold-forward/tokens/txt
1270−/* tre-404 %txt /tests/golden/types-partial-mold-forward/tree/txt
1271−/* typ-404 %txt /tests/golden/types-partial-mold-forward/types/txt
1272−/* src-405 %jibb /tests/golden/types-partial-mold-recursive/source/jibb
1273−/* tok-405 %txt /tests/golden/types-partial-mold-recursive/tokens/txt
1274−/* tre-405 %txt /tests/golden/types-partial-mold-recursive/tree/txt
1275−/* typ-405 %txt /tests/golden/types-partial-mold-recursive/types/txt
1276−/* src-406 %jibb /tests/golden/types-partial-occurs/source/jibb
1277−/* tok-406 %txt /tests/golden/types-partial-occurs/tokens/txt
1278−/* tre-406 %txt /tests/golden/types-partial-occurs/tree/txt
1279−/* typ-406 %txt /tests/golden/types-partial-occurs/types/txt
1280−/* src-407 %jibb /tests/golden/types-partial-projection/source/jibb
1281−/* tok-407 %txt /tests/golden/types-partial-projection/tokens/txt
1282−/* tre-407 %txt /tests/golden/types-partial-projection/tree/txt
1283−/* typ-407 %txt /tests/golden/types-partial-projection/types/txt
1284−/* src-408 %jibb /tests/golden/types-partial-shadow-global/source/jibb
1285−/* tok-408 %txt /tests/golden/types-partial-shadow-global/tokens/txt
1286−/* tre-408 %txt /tests/golden/types-partial-shadow-global/tree/txt
1287−/* typ-408 %txt /tests/golden/types-partial-shadow-global/types/txt
1288−/* src-409 %jibb /tests/golden/types-partial-shared-tvar/source/jibb
1289−/* tok-409 %txt /tests/golden/types-partial-shared-tvar/tokens/txt
1290−/* tre-409 %txt /tests/golden/types-partial-shared-tvar/tree/txt
1291−/* typ-409 %txt /tests/golden/types-partial-shared-tvar/types/txt
1292−/* src-410 %jibb /tests/golden/types-partial-union-cases/source/jibb
1293−/* tok-410 %txt /tests/golden/types-partial-union-cases/tokens/txt
1294−/* tre-410 %txt /tests/golden/types-partial-union-cases/tree/txt
1295−/* typ-410 %txt /tests/golden/types-partial-union-cases/types/txt
1296−/* src-411 %jibb /tests/golden/types-partial-union-edges/source/jibb
1297−/* tok-411 %txt /tests/golden/types-partial-union-edges/tokens/txt
1298−/* tre-411 %txt /tests/golden/types-partial-union-edges/tree/txt
1299−/* typ-411 %txt /tests/golden/types-partial-union-edges/types/txt
1300−/* src-412 %jibb /tests/golden/types-partial-unresolved-tag/source/jibb
1301−/* tok-412 %txt /tests/golden/types-partial-unresolved-tag/tokens/txt
1302−/* tre-412 %txt /tests/golden/types-partial-unresolved-tag/tree/txt
1303−/* typ-412 %txt /tests/golden/types-partial-unresolved-tag/types/txt
1139+/* src-373 %jibb /tests/golden/module-fixture-eof/source/jibb
1140+/* tok-373 %txt /tests/golden/module-fixture-eof/tokens/txt
1141+/* tre-373 %txt /tests/golden/module-fixture-eof/tree/txt
1142+/* mtre-373 %txt /tests/golden/module-fixture-eof/module-trees/txt
1143+/* mod-373-1 %jibb /tests/golden/module-fixture-eof/modules/ui/incomplete/jibb
1144+/* src-374 %jibb /tests/golden/prelude-1c-structural/source/jibb
1145+/* tok-374 %txt /tests/golden/prelude-1c-structural/tokens/txt
1146+/* tre-374 %txt /tests/golden/prelude-1c-structural/tree/txt
1147+/* typ-374 %txt /tests/golden/prelude-1c-structural/types/txt
1148+/* src-375 %jibb /tests/golden/prelude-3g-basic/source/jibb
1149+/* tok-375 %txt /tests/golden/prelude-3g-basic/tokens/txt
1150+/* tre-375 %txt /tests/golden/prelude-3g-basic/tree/txt
1151+/* typ-375 %txt /tests/golden/prelude-3g-basic/types/txt
1152+/* src-376 %jibb /tests/golden/prelude-3g-like/source/jibb
1153+/* tok-376 %txt /tests/golden/prelude-3g-like/tokens/txt
1154+/* tre-376 %txt /tests/golden/prelude-3g-like/tree/txt
1155+/* typ-376 %txt /tests/golden/prelude-3g-like/types/txt
1156+/* src-377 %jibb /tests/golden/prelude-3g-structural/source/jibb
1157+/* tok-377 %txt /tests/golden/prelude-3g-structural/tokens/txt
1158+/* tre-377 %txt /tests/golden/prelude-3g-structural/tree/txt
1159+/* typ-377 %txt /tests/golden/prelude-3g-structural/types/txt
1160+/* src-378 %jibb /tests/golden/prelude-core-functions/source/jibb
1161+/* tok-378 %txt /tests/golden/prelude-core-functions/tokens/txt
1162+/* tre-378 %txt /tests/golden/prelude-core-functions/tree/txt
1163+/* typ-378 %txt /tests/golden/prelude-core-functions/types/txt
1164+/* src-379 %jibb /tests/golden/prelude-list-helpers/source/jibb
1165+/* tok-379 %txt /tests/golden/prelude-list-helpers/tokens/txt
1166+/* tre-379 %txt /tests/golden/prelude-list-helpers/tree/txt
1167+/* typ-379 %txt /tests/golden/prelude-list-helpers/types/txt
1168+/* src-380 %jibb /tests/golden/prelude-list-unit/source/jibb
1169+/* tok-380 %txt /tests/golden/prelude-list-unit/tokens/txt
1170+/* tre-380 %txt /tests/golden/prelude-list-unit/tree/txt
1171+/* typ-380 %txt /tests/golden/prelude-list-unit/types/txt
1172+/* src-381 %jibb /tests/golden/prelude-unit-list-transforms/source/jibb
1173+/* tok-381 %txt /tests/golden/prelude-unit-list-transforms/tokens/txt
1174+/* tre-381 %txt /tests/golden/prelude-unit-list-transforms/tree/txt
1175+/* typ-381 %txt /tests/golden/prelude-unit-list-transforms/types/txt
1176+/* src-382 %jibb /tests/golden/types-import-mark/source/jibb
1177+/* tok-382 %txt /tests/golden/types-import-mark/tokens/txt
1178+/* tre-382 %txt /tests/golden/types-import-mark/tree/txt
1179+/* typ-382 %txt /tests/golden/types-import-mark/types/txt
1180+/* imp-382-1 %txt /tests/golden/types-import-mark/sur/fixture/txt
1181+/* mark-382-1 %txt /tests/golden/types-import-mark/mar/label/txt
1182+/* src-383 %jibb /tests/golden/types-import-missing-mold/source/jibb
1183+/* tok-383 %txt /tests/golden/types-import-missing-mold/tokens/txt
1184+/* tre-383 %txt /tests/golden/types-import-missing-mold/tree/txt
1185+/* typ-383 %txt /tests/golden/types-import-missing-mold/types/txt
1186+/* imp-383-1 %txt /tests/golden/types-import-missing-mold/sur/fixture/txt
1187+/* src-384 %jibb /tests/golden/types-import-sur/source/jibb
1188+/* tok-384 %txt /tests/golden/types-import-sur/tokens/txt
1189+/* tre-384 %txt /tests/golden/types-import-sur/tree/txt
1190+/* typ-384 %txt /tests/golden/types-import-sur/types/txt
1191+/* imp-384-1 %txt /tests/golden/types-import-sur/sur/fixture/txt
1192+/* imp-384-2 %txt /tests/golden/types-import-sur/sur/fixture/txt
1193+/* src-385 %jibb /tests/golden/types-module-fixtures/source/jibb
1194+/* tok-385 %txt /tests/golden/types-module-fixtures/tokens/txt
1195+/* tre-385 %txt /tests/golden/types-module-fixtures/tree/txt
1196+/* typ-385 %txt /tests/golden/types-module-fixtures/types/txt
1197+/* mtre-385 %txt /tests/golden/types-module-fixtures/module-trees/txt
1198+/* mod-385-1 %jibb /tests/golden/types-module-fixtures/modules/ui/api/blog/jibb
1199+/* mod-385-2 %jibb /tests/golden/types-module-fixtures/modules/ui/components/card/jibb
1200+/* src-386 %jibb /tests/golden/types-partial-apply/source/jibb
1201+/* tok-386 %txt /tests/golden/types-partial-apply/tokens/txt
1202+/* tre-386 %txt /tests/golden/types-partial-apply/tree/txt
1203+/* typ-386 %txt /tests/golden/types-partial-apply/types/txt
1204+/* src-387 %jibb /tests/golden/types-partial-atom-alias/source/jibb
1205+/* tok-387 %txt /tests/golden/types-partial-atom-alias/tokens/txt
1206+/* tre-387 %txt /tests/golden/types-partial-atom-alias/tree/txt
1207+/* typ-387 %txt /tests/golden/types-partial-atom-alias/types/txt
1208+/* src-388 %jibb /tests/golden/types-partial-atom-constraint/source/jibb
1209+/* tok-388 %txt /tests/golden/types-partial-atom-constraint/tokens/txt
1210+/* tre-388 %txt /tests/golden/types-partial-atom-constraint/tree/txt
1211+/* typ-388 %txt /tests/golden/types-partial-atom-constraint/types/txt
1212+/* src-389 %jibb /tests/golden/types-partial-atom-widening/source/jibb
1213+/* tok-389 %txt /tests/golden/types-partial-atom-widening/tokens/txt
1214+/* tre-389 %txt /tests/golden/types-partial-atom-widening/tree/txt
1215+/* typ-389 %txt /tests/golden/types-partial-atom-widening/types/txt
1216+/* src-390 %jibb /tests/golden/types-partial-aura/source/jibb
1217+/* tok-390 %txt /tests/golden/types-partial-aura/tokens/txt
1218+/* tre-390 %txt /tests/golden/types-partial-aura/tree/txt
1219+/* typ-390 %txt /tests/golden/types-partial-aura/types/txt
1220+/* src-391 %jibb /tests/golden/types-partial-aura-family/source/jibb
1221+/* tok-391 %txt /tests/golden/types-partial-aura-family/tokens/txt
1222+/* tre-391 %txt /tests/golden/types-partial-aura-family/tree/txt
1223+/* typ-391 %txt /tests/golden/types-partial-aura-family/types/txt
1224+/* src-392 %jibb /tests/golden/types-partial-aura-generalization/source/jibb
1225+/* tok-392 %txt /tests/golden/types-partial-aura-generalization/tokens/txt
1226+/* tre-392 %txt /tests/golden/types-partial-aura-generalization/tree/txt
1227+/* typ-392 %txt /tests/golden/types-partial-aura-generalization/types/txt
1228+/* src-393 %jibb /tests/golden/types-partial-bare-atom/source/jibb
1229+/* tok-393 %txt /tests/golden/types-partial-bare-atom/tokens/txt
1230+/* tre-393 %txt /tests/golden/types-partial-bare-atom/tree/txt
1231+/* typ-393 %txt /tests/golden/types-partial-bare-atom/types/txt
1232+/* src-394 %jibb /tests/golden/types-partial-branch-widening/source/jibb
1233+/* tok-394 %txt /tests/golden/types-partial-branch-widening/tokens/txt
1234+/* tre-394 %txt /tests/golden/types-partial-branch-widening/tree/txt
1235+/* typ-394 %txt /tests/golden/types-partial-branch-widening/types/txt
1236+/* src-395 %jibb /tests/golden/types-partial-conflicting-sites/source/jibb
1237+/* tok-395 %txt /tests/golden/types-partial-conflicting-sites/tokens/txt
1238+/* tre-395 %txt /tests/golden/types-partial-conflicting-sites/tree/txt
1239+/* typ-395 %txt /tests/golden/types-partial-conflicting-sites/types/txt
1240+/* src-396 %jibb /tests/golden/types-partial-decimal-default/source/jibb
1241+/* tok-396 %txt /tests/golden/types-partial-decimal-default/tokens/txt
1242+/* tre-396 %txt /tests/golden/types-partial-decimal-default/tree/txt
1243+/* typ-396 %txt /tests/golden/types-partial-decimal-default/types/txt
1244+/* src-397 %jibb /tests/golden/types-partial-dependency-chain/source/jibb
1245+/* tok-397 %txt /tests/golden/types-partial-dependency-chain/tokens/txt
1246+/* tre-397 %txt /tests/golden/types-partial-dependency-chain/tree/txt
1247+/* typ-397 %txt /tests/golden/types-partial-dependency-chain/types/txt
1248+/* src-398 %jibb /tests/golden/types-partial-explicit-capital/source/jibb
1249+/* tok-398 %txt /tests/golden/types-partial-explicit-capital/tokens/txt
1250+/* tre-398 %txt /tests/golden/types-partial-explicit-capital/tree/txt
1251+/* typ-398 %txt /tests/golden/types-partial-explicit-capital/types/txt
1252+/* src-399 %jibb /tests/golden/types-partial-forward/source/jibb
1253+/* tok-399 %txt /tests/golden/types-partial-forward/tokens/txt
1254+/* tre-399 %txt /tests/golden/types-partial-forward/tree/txt
1255+/* typ-399 %txt /tests/golden/types-partial-forward/types/txt
1256+/* src-400 %jibb /tests/golden/types-partial-generalization/source/jibb
1257+/* tok-400 %txt /tests/golden/types-partial-generalization/tokens/txt
1258+/* tre-400 %txt /tests/golden/types-partial-generalization/tree/txt
1259+/* typ-400 %txt /tests/golden/types-partial-generalization/types/txt
1260+/* src-401 %jibb /tests/golden/types-partial-identity/source/jibb
1261+/* tok-401 %txt /tests/golden/types-partial-identity/tokens/txt
1262+/* tre-401 %txt /tests/golden/types-partial-identity/tree/txt
1263+/* typ-401 %txt /tests/golden/types-partial-identity/types/txt
1264+/* src-402 %jibb /tests/golden/types-partial-independent-atoms/source/jibb
1265+/* tok-402 %txt /tests/golden/types-partial-independent-atoms/tokens/txt
1266+/* tre-402 %txt /tests/golden/types-partial-independent-atoms/tree/txt
1267+/* typ-402 %txt /tests/golden/types-partial-independent-atoms/types/txt
1268+/* src-403 %jibb /tests/golden/types-partial-locals/source/jibb
1269+/* tok-403 %txt /tests/golden/types-partial-locals/tokens/txt
1270+/* tre-403 %txt /tests/golden/types-partial-locals/tree/txt
1271+/* typ-403 %txt /tests/golden/types-partial-locals/types/txt
1272+/* src-404 %jibb /tests/golden/types-partial-many-atom-constraints/source/jibb
1273+/* tok-404 %txt /tests/golden/types-partial-many-atom-constraints/tokens/txt
1274+/* tre-404 %txt /tests/golden/types-partial-many-atom-constraints/tree/txt
1275+/* typ-404 %txt /tests/golden/types-partial-many-atom-constraints/types/txt
1276+/* src-405 %jibb /tests/golden/types-partial-mold-bare-aura/source/jibb
1277+/* tok-405 %txt /tests/golden/types-partial-mold-bare-aura/tokens/txt
1278+/* tre-405 %txt /tests/golden/types-partial-mold-bare-aura/tree/txt
1279+/* typ-405 %txt /tests/golden/types-partial-mold-bare-aura/types/txt
1280+/* src-406 %jibb /tests/golden/types-partial-mold-composite/source/jibb
1281+/* tok-406 %txt /tests/golden/types-partial-mold-composite/tokens/txt
1282+/* tre-406 %txt /tests/golden/types-partial-mold-composite/tree/txt
1283+/* typ-406 %txt /tests/golden/types-partial-mold-composite/types/txt
1284+/* src-407 %jibb /tests/golden/types-partial-mold-forward/source/jibb
1285+/* tok-407 %txt /tests/golden/types-partial-mold-forward/tokens/txt
1286+/* tre-407 %txt /tests/golden/types-partial-mold-forward/tree/txt
1287+/* typ-407 %txt /tests/golden/types-partial-mold-forward/types/txt
1288+/* src-408 %jibb /tests/golden/types-partial-mold-recursive/source/jibb
1289+/* tok-408 %txt /tests/golden/types-partial-mold-recursive/tokens/txt
1290+/* tre-408 %txt /tests/golden/types-partial-mold-recursive/tree/txt
1291+/* typ-408 %txt /tests/golden/types-partial-mold-recursive/types/txt
1292+/* src-409 %jibb /tests/golden/types-partial-occurs/source/jibb
1293+/* tok-409 %txt /tests/golden/types-partial-occurs/tokens/txt
1294+/* tre-409 %txt /tests/golden/types-partial-occurs/tree/txt
1295+/* typ-409 %txt /tests/golden/types-partial-occurs/types/txt
1296+/* src-410 %jibb /tests/golden/types-partial-projection/source/jibb
1297+/* tok-410 %txt /tests/golden/types-partial-projection/tokens/txt
1298+/* tre-410 %txt /tests/golden/types-partial-projection/tree/txt
1299+/* typ-410 %txt /tests/golden/types-partial-projection/types/txt
1300+/* src-411 %jibb /tests/golden/types-partial-shadow-global/source/jibb
1301+/* tok-411 %txt /tests/golden/types-partial-shadow-global/tokens/txt
1302+/* tre-411 %txt /tests/golden/types-partial-shadow-global/tree/txt
1303+/* typ-411 %txt /tests/golden/types-partial-shadow-global/types/txt
1304+/* src-412 %jibb /tests/golden/types-partial-shared-tvar/source/jibb
1305+/* tok-412 %txt /tests/golden/types-partial-shared-tvar/tokens/txt
1306+/* tre-412 %txt /tests/golden/types-partial-shared-tvar/tree/txt
1307+/* typ-412 %txt /tests/golden/types-partial-shared-tvar/types/txt
1308+/* src-413 %jibb /tests/golden/types-partial-union-cases/source/jibb
1309+/* tok-413 %txt /tests/golden/types-partial-union-cases/tokens/txt
1310+/* tre-413 %txt /tests/golden/types-partial-union-cases/tree/txt
1311+/* typ-413 %txt /tests/golden/types-partial-union-cases/types/txt
1312+/* src-414 %jibb /tests/golden/types-partial-union-edges/source/jibb
1313+/* tok-414 %txt /tests/golden/types-partial-union-edges/tokens/txt
1314+/* tre-414 %txt /tests/golden/types-partial-union-edges/tree/txt
1315+/* typ-414 %txt /tests/golden/types-partial-union-edges/types/txt
1316+/* src-415 %jibb /tests/golden/types-partial-unresolved-tag/source/jibb
1317+/* tok-415 %txt /tests/golden/types-partial-unresolved-tag/tokens/txt
1318+/* tre-415 %txt /tests/golden/types-partial-unresolved-tag/tree/txt
1319+/* typ-415 %txt /tests/golden/types-partial-unresolved-tag/types/txt
13041320|%
13051321:: one arm per case
13061322::
@@ -2048,86 +2064,92 @@
20482064 (check ~.lex-tight-wing-bad-1 src-371 `tok-371 `tre-371)
20492065++ test-lex-tight-wing-ok-1
20502066 (check ~.lex-tight-wing-ok-1 src-372 `tok-372 `tre-372)
2067+++ test-module-fixture-eof
2068+ (weld (check ~.module-fixture-eof src-373 `tok-373 `tre-373) (check-module-trees ~.module-fixture-eof `mtre-373 ~[['/ui/incomplete.jibb' ~[~.ui ~.incomplete ~.jibb] mod-373-1]]))
20512069++ test-prelude-1c-structural
2052− (weld (check ~.prelude-1c-structural src-373 `tok-373 `tre-373) (check-types ~.prelude-1c-structural ~[%tests %golden ~.prelude-1c-structural %source %jibb] src-373 `typ-373))
2070+ (weld (check ~.prelude-1c-structural src-374 `tok-374 `tre-374) (check-types ~.prelude-1c-structural ~[%tests %golden ~.prelude-1c-structural %source %jibb] src-374 `typ-374))
20532071++ test-prelude-3g-basic
2054− (weld (check ~.prelude-3g-basic src-374 `tok-374 `tre-374) (check-types ~.prelude-3g-basic ~[%tests %golden ~.prelude-3g-basic %source %jibb] src-374 `typ-374))
2072+ (weld (check ~.prelude-3g-basic src-375 `tok-375 `tre-375) (check-types ~.prelude-3g-basic ~[%tests %golden ~.prelude-3g-basic %source %jibb] src-375 `typ-375))
20552073++ test-prelude-3g-like
2056− (weld (check ~.prelude-3g-like src-375 `tok-375 `tre-375) (check-types ~.prelude-3g-like ~[%tests %golden ~.prelude-3g-like %source %jibb] src-375 `typ-375))
2074+ (weld (check ~.prelude-3g-like src-376 `tok-376 `tre-376) (check-types ~.prelude-3g-like ~[%tests %golden ~.prelude-3g-like %source %jibb] src-376 `typ-376))
20572075++ test-prelude-3g-structural
2058− (weld (check ~.prelude-3g-structural src-376 `tok-376 `tre-376) (check-types ~.prelude-3g-structural ~[%tests %golden ~.prelude-3g-structural %source %jibb] src-376 `typ-376))
2076+ (weld (check ~.prelude-3g-structural src-377 `tok-377 `tre-377) (check-types ~.prelude-3g-structural ~[%tests %golden ~.prelude-3g-structural %source %jibb] src-377 `typ-377))
20592077++ test-prelude-core-functions
2060− (weld (check ~.prelude-core-functions src-377 `tok-377 `tre-377) (check-types ~.prelude-core-functions ~[%tests %golden ~.prelude-core-functions %source %jibb] src-377 `typ-377))
2078+ (weld (check ~.prelude-core-functions src-378 `tok-378 `tre-378) (check-types ~.prelude-core-functions ~[%tests %golden ~.prelude-core-functions %source %jibb] src-378 `typ-378))
20612079++ test-prelude-list-helpers
2062− (weld (check ~.prelude-list-helpers src-378 `tok-378 `tre-378) (check-types ~.prelude-list-helpers ~[%tests %golden ~.prelude-list-helpers %source %jibb] src-378 `typ-378))
2080+ (weld (check ~.prelude-list-helpers src-379 `tok-379 `tre-379) (check-types ~.prelude-list-helpers ~[%tests %golden ~.prelude-list-helpers %source %jibb] src-379 `typ-379))
20632081++ test-prelude-list-unit
2064− (weld (check ~.prelude-list-unit src-379 `tok-379 `tre-379) (check-types ~.prelude-list-unit ~[%tests %golden ~.prelude-list-unit %source %jibb] src-379 `typ-379))
2082+ (weld (check ~.prelude-list-unit src-380 `tok-380 `tre-380) (check-types ~.prelude-list-unit ~[%tests %golden ~.prelude-list-unit %source %jibb] src-380 `typ-380))
20652083++ test-prelude-unit-list-transforms
2066− (weld (check ~.prelude-unit-list-transforms src-380 `tok-380 `tre-380) (check-types ~.prelude-unit-list-transforms ~[%tests %golden ~.prelude-unit-list-transforms %source %jibb] src-380 `typ-380))
2084+ (weld (check ~.prelude-unit-list-transforms src-381 `tok-381 `tre-381) (check-types ~.prelude-unit-list-transforms ~[%tests %golden ~.prelude-unit-list-transforms %source %jibb] src-381 `typ-381))
20672085++ test-types-import-mark
2068− (weld (check ~.types-import-mark src-381 `tok-381 `tre-381) (check-mark-types ~.types-import-mark ~[%tests %golden ~.types-import-mark %source %jibb] src-381 `typ-381 ~[[%fixture %title imp-381-1]] ~[[%label mark-381-1]]))
2086+ (weld (check ~.types-import-mark src-382 `tok-382 `tre-382) (check-mark-types ~.types-import-mark ~[%tests %golden ~.types-import-mark %source %jibb] src-382 `typ-382 ~[[%fixture %title imp-382-1]] ~[[%label mark-382-1]]))
20692087++ test-types-import-missing-mold
2070− (weld (check ~.types-import-missing-mold src-382 `tok-382 `tre-382) (check-import-types ~.types-import-missing-mold ~[%tests %golden ~.types-import-missing-mold %source %jibb] src-382 `typ-382 ~[[%fixture %missing imp-382-1]]))
2088+ (weld (check ~.types-import-missing-mold src-383 `tok-383 `tre-383) (check-import-types ~.types-import-missing-mold ~[%tests %golden ~.types-import-missing-mold %source %jibb] src-383 `typ-383 ~[[%fixture %missing imp-383-1]]))
20712089++ test-types-import-sur
2072− (weld (check ~.types-import-sur src-383 `tok-383 `tre-383) (check-import-types ~.types-import-sur ~[%tests %golden ~.types-import-sur %source %jibb] src-383 `typ-383 ~[[%fixture %title imp-383-1] [%fixture %pair imp-383-2]]))
2090+ (weld (check ~.types-import-sur src-384 `tok-384 `tre-384) (check-import-types ~.types-import-sur ~[%tests %golden ~.types-import-sur %source %jibb] src-384 `typ-384 ~[[%fixture %title imp-384-1] [%fixture %pair imp-384-2]]))
2091+++ test-types-module-fixtures
2092+ (weld (weld (check-at ~.types-module-fixtures ~[~.ui ~.blog ~.index ~.jibb] src-385 `tok-385 `tre-385) (check-types ~.types-module-fixtures ~[~.ui ~.blog ~.index ~.jibb] src-385 `typ-385)) (check-module-trees ~.types-module-fixtures `mtre-385 ~[['/ui/api/blog.jibb' ~[~.ui ~.api ~.blog ~.jibb] mod-385-1] ['/ui/components/card.jibb' ~[~.ui ~.components ~.card ~.jibb] mod-385-2]]))
20732093++ test-types-partial-apply
2074− (weld (check ~.types-partial-apply src-384 `tok-384 `tre-384) (check-types ~.types-partial-apply ~[%tests %golden ~.types-partial-apply %source %jibb] src-384 `typ-384))
2094+ (weld (check ~.types-partial-apply src-386 `tok-386 `tre-386) (check-types ~.types-partial-apply ~[%tests %golden ~.types-partial-apply %source %jibb] src-386 `typ-386))
20752095++ test-types-partial-atom-alias
2076− (weld (check ~.types-partial-atom-alias src-385 `tok-385 `tre-385) (check-types ~.types-partial-atom-alias ~[%tests %golden ~.types-partial-atom-alias %source %jibb] src-385 `typ-385))
2096+ (weld (check ~.types-partial-atom-alias src-387 `tok-387 `tre-387) (check-types ~.types-partial-atom-alias ~[%tests %golden ~.types-partial-atom-alias %source %jibb] src-387 `typ-387))
20772097++ test-types-partial-atom-constraint
2078− (weld (check ~.types-partial-atom-constraint src-386 `tok-386 `tre-386) (check-types ~.types-partial-atom-constraint ~[%tests %golden ~.types-partial-atom-constraint %source %jibb] src-386 `typ-386))
2098+ (weld (check ~.types-partial-atom-constraint src-388 `tok-388 `tre-388) (check-types ~.types-partial-atom-constraint ~[%tests %golden ~.types-partial-atom-constraint %source %jibb] src-388 `typ-388))
20792099++ test-types-partial-atom-widening
2080− (weld (check ~.types-partial-atom-widening src-387 `tok-387 `tre-387) (check-types ~.types-partial-atom-widening ~[%tests %golden ~.types-partial-atom-widening %source %jibb] src-387 `typ-387))
2100+ (weld (check ~.types-partial-atom-widening src-389 `tok-389 `tre-389) (check-types ~.types-partial-atom-widening ~[%tests %golden ~.types-partial-atom-widening %source %jibb] src-389 `typ-389))
20812101++ test-types-partial-aura
2082− (weld (check ~.types-partial-aura src-388 `tok-388 `tre-388) (check-types ~.types-partial-aura ~[%tests %golden ~.types-partial-aura %source %jibb] src-388 `typ-388))
2102+ (weld (check ~.types-partial-aura src-390 `tok-390 `tre-390) (check-types ~.types-partial-aura ~[%tests %golden ~.types-partial-aura %source %jibb] src-390 `typ-390))
20832103++ test-types-partial-aura-family
2084− (weld (check ~.types-partial-aura-family src-389 `tok-389 `tre-389) (check-types ~.types-partial-aura-family ~[%tests %golden ~.types-partial-aura-family %source %jibb] src-389 `typ-389))
2104+ (weld (check ~.types-partial-aura-family src-391 `tok-391 `tre-391) (check-types ~.types-partial-aura-family ~[%tests %golden ~.types-partial-aura-family %source %jibb] src-391 `typ-391))
20852105++ test-types-partial-aura-generalization
2086− (weld (check ~.types-partial-aura-generalization src-390 `tok-390 `tre-390) (check-types ~.types-partial-aura-generalization ~[%tests %golden ~.types-partial-aura-generalization %source %jibb] src-390 `typ-390))
2106+ (weld (check ~.types-partial-aura-generalization src-392 `tok-392 `tre-392) (check-types ~.types-partial-aura-generalization ~[%tests %golden ~.types-partial-aura-generalization %source %jibb] src-392 `typ-392))
20872107++ test-types-partial-bare-atom
2088− (weld (check ~.types-partial-bare-atom src-391 `tok-391 `tre-391) (check-types ~.types-partial-bare-atom ~[%tests %golden ~.types-partial-bare-atom %source %jibb] src-391 `typ-391))
2108+ (weld (check ~.types-partial-bare-atom src-393 `tok-393 `tre-393) (check-types ~.types-partial-bare-atom ~[%tests %golden ~.types-partial-bare-atom %source %jibb] src-393 `typ-393))
20892109++ test-types-partial-branch-widening
2090− (weld (check ~.types-partial-branch-widening src-392 `tok-392 `tre-392) (check-types ~.types-partial-branch-widening ~[%tests %golden ~.types-partial-branch-widening %source %jibb] src-392 `typ-392))
2110+ (weld (check ~.types-partial-branch-widening src-394 `tok-394 `tre-394) (check-types ~.types-partial-branch-widening ~[%tests %golden ~.types-partial-branch-widening %source %jibb] src-394 `typ-394))
20912111++ test-types-partial-conflicting-sites
2092− (weld (check ~.types-partial-conflicting-sites src-393 `tok-393 `tre-393) (check-types ~.types-partial-conflicting-sites ~[%tests %golden ~.types-partial-conflicting-sites %source %jibb] src-393 `typ-393))
2112+ (weld (check ~.types-partial-conflicting-sites src-395 `tok-395 `tre-395) (check-types ~.types-partial-conflicting-sites ~[%tests %golden ~.types-partial-conflicting-sites %source %jibb] src-395 `typ-395))
20932113++ test-types-partial-decimal-default
2094− (weld (check ~.types-partial-decimal-default src-394 `tok-394 `tre-394) (check-types ~.types-partial-decimal-default ~[%tests %golden ~.types-partial-decimal-default %source %jibb] src-394 `typ-394))
2114+ (weld (check ~.types-partial-decimal-default src-396 `tok-396 `tre-396) (check-types ~.types-partial-decimal-default ~[%tests %golden ~.types-partial-decimal-default %source %jibb] src-396 `typ-396))
20952115++ test-types-partial-dependency-chain
2096− (weld (check ~.types-partial-dependency-chain src-395 `tok-395 `tre-395) (check-types ~.types-partial-dependency-chain ~[%tests %golden ~.types-partial-dependency-chain %source %jibb] src-395 `typ-395))
2116+ (weld (check ~.types-partial-dependency-chain src-397 `tok-397 `tre-397) (check-types ~.types-partial-dependency-chain ~[%tests %golden ~.types-partial-dependency-chain %source %jibb] src-397 `typ-397))
20972117++ test-types-partial-explicit-capital
2098− (weld (check ~.types-partial-explicit-capital src-396 `tok-396 `tre-396) (check-types ~.types-partial-explicit-capital ~[%tests %golden ~.types-partial-explicit-capital %source %jibb] src-396 `typ-396))
2118+ (weld (check ~.types-partial-explicit-capital src-398 `tok-398 `tre-398) (check-types ~.types-partial-explicit-capital ~[%tests %golden ~.types-partial-explicit-capital %source %jibb] src-398 `typ-398))
20992119++ test-types-partial-forward
2100− (weld (check ~.types-partial-forward src-397 `tok-397 `tre-397) (check-types ~.types-partial-forward ~[%tests %golden ~.types-partial-forward %source %jibb] src-397 `typ-397))
2120+ (weld (check ~.types-partial-forward src-399 `tok-399 `tre-399) (check-types ~.types-partial-forward ~[%tests %golden ~.types-partial-forward %source %jibb] src-399 `typ-399))
21012121++ test-types-partial-generalization
2102− (weld (check ~.types-partial-generalization src-398 `tok-398 `tre-398) (check-types ~.types-partial-generalization ~[%tests %golden ~.types-partial-generalization %source %jibb] src-398 `typ-398))
2122+ (weld (check ~.types-partial-generalization src-400 `tok-400 `tre-400) (check-types ~.types-partial-generalization ~[%tests %golden ~.types-partial-generalization %source %jibb] src-400 `typ-400))
21032123++ test-types-partial-identity
2104− (weld (check ~.types-partial-identity src-399 `tok-399 `tre-399) (check-types ~.types-partial-identity ~[%tests %golden ~.types-partial-identity %source %jibb] src-399 `typ-399))
2124+ (weld (check ~.types-partial-identity src-401 `tok-401 `tre-401) (check-types ~.types-partial-identity ~[%tests %golden ~.types-partial-identity %source %jibb] src-401 `typ-401))
21052125++ test-types-partial-independent-atoms
2106− (weld (check ~.types-partial-independent-atoms src-400 `tok-400 `tre-400) (check-types ~.types-partial-independent-atoms ~[%tests %golden ~.types-partial-independent-atoms %source %jibb] src-400 `typ-400))
2126+ (weld (check ~.types-partial-independent-atoms src-402 `tok-402 `tre-402) (check-types ~.types-partial-independent-atoms ~[%tests %golden ~.types-partial-independent-atoms %source %jibb] src-402 `typ-402))
2127+++ test-types-partial-locals
2128+ (weld (check ~.types-partial-locals src-403 `tok-403 `tre-403) (check-types ~.types-partial-locals ~[%tests %golden ~.types-partial-locals %source %jibb] src-403 `typ-403))
21072129++ test-types-partial-many-atom-constraints
2108− (weld (check ~.types-partial-many-atom-constraints src-401 `tok-401 `tre-401) (check-types ~.types-partial-many-atom-constraints ~[%tests %golden ~.types-partial-many-atom-constraints %source %jibb] src-401 `typ-401))
2130+ (weld (check ~.types-partial-many-atom-constraints src-404 `tok-404 `tre-404) (check-types ~.types-partial-many-atom-constraints ~[%tests %golden ~.types-partial-many-atom-constraints %source %jibb] src-404 `typ-404))
21092131++ test-types-partial-mold-bare-aura
2110− (weld (check ~.types-partial-mold-bare-aura src-402 `tok-402 `tre-402) (check-types ~.types-partial-mold-bare-aura ~[%tests %golden ~.types-partial-mold-bare-aura %source %jibb] src-402 `typ-402))
2132+ (weld (check ~.types-partial-mold-bare-aura src-405 `tok-405 `tre-405) (check-types ~.types-partial-mold-bare-aura ~[%tests %golden ~.types-partial-mold-bare-aura %source %jibb] src-405 `typ-405))
21112133++ test-types-partial-mold-composite
2112− (weld (check ~.types-partial-mold-composite src-403 `tok-403 `tre-403) (check-types ~.types-partial-mold-composite ~[%tests %golden ~.types-partial-mold-composite %source %jibb] src-403 `typ-403))
2134+ (weld (check ~.types-partial-mold-composite src-406 `tok-406 `tre-406) (check-types ~.types-partial-mold-composite ~[%tests %golden ~.types-partial-mold-composite %source %jibb] src-406 `typ-406))
21132135++ test-types-partial-mold-forward
2114− (weld (check ~.types-partial-mold-forward src-404 `tok-404 `tre-404) (check-types ~.types-partial-mold-forward ~[%tests %golden ~.types-partial-mold-forward %source %jibb] src-404 `typ-404))
2136+ (weld (check ~.types-partial-mold-forward src-407 `tok-407 `tre-407) (check-types ~.types-partial-mold-forward ~[%tests %golden ~.types-partial-mold-forward %source %jibb] src-407 `typ-407))
21152137++ test-types-partial-mold-recursive
2116− (weld (check ~.types-partial-mold-recursive src-405 `tok-405 `tre-405) (check-types ~.types-partial-mold-recursive ~[%tests %golden ~.types-partial-mold-recursive %source %jibb] src-405 `typ-405))
2138+ (weld (check ~.types-partial-mold-recursive src-408 `tok-408 `tre-408) (check-types ~.types-partial-mold-recursive ~[%tests %golden ~.types-partial-mold-recursive %source %jibb] src-408 `typ-408))
21172139++ test-types-partial-occurs
2118− (weld (check ~.types-partial-occurs src-406 `tok-406 `tre-406) (check-types ~.types-partial-occurs ~[%tests %golden ~.types-partial-occurs %source %jibb] src-406 `typ-406))
2140+ (weld (check ~.types-partial-occurs src-409 `tok-409 `tre-409) (check-types ~.types-partial-occurs ~[%tests %golden ~.types-partial-occurs %source %jibb] src-409 `typ-409))
21192141++ test-types-partial-projection
2120− (weld (check ~.types-partial-projection src-407 `tok-407 `tre-407) (check-types ~.types-partial-projection ~[%tests %golden ~.types-partial-projection %source %jibb] src-407 `typ-407))
2142+ (weld (check ~.types-partial-projection src-410 `tok-410 `tre-410) (check-types ~.types-partial-projection ~[%tests %golden ~.types-partial-projection %source %jibb] src-410 `typ-410))
21212143++ test-types-partial-shadow-global
2122− (weld (check ~.types-partial-shadow-global src-408 `tok-408 `tre-408) (check-types ~.types-partial-shadow-global ~[%tests %golden ~.types-partial-shadow-global %source %jibb] src-408 `typ-408))
2144+ (weld (check ~.types-partial-shadow-global src-411 `tok-411 `tre-411) (check-types ~.types-partial-shadow-global ~[%tests %golden ~.types-partial-shadow-global %source %jibb] src-411 `typ-411))
21232145++ test-types-partial-shared-tvar
2124− (weld (check ~.types-partial-shared-tvar src-409 `tok-409 `tre-409) (check-types ~.types-partial-shared-tvar ~[%tests %golden ~.types-partial-shared-tvar %source %jibb] src-409 `typ-409))
2146+ (weld (check ~.types-partial-shared-tvar src-412 `tok-412 `tre-412) (check-types ~.types-partial-shared-tvar ~[%tests %golden ~.types-partial-shared-tvar %source %jibb] src-412 `typ-412))
21252147++ test-types-partial-union-cases
2126− (weld (check ~.types-partial-union-cases src-410 `tok-410 `tre-410) (check-types ~.types-partial-union-cases ~[%tests %golden ~.types-partial-union-cases %source %jibb] src-410 `typ-410))
2148+ (weld (check ~.types-partial-union-cases src-413 `tok-413 `tre-413) (check-types ~.types-partial-union-cases ~[%tests %golden ~.types-partial-union-cases %source %jibb] src-413 `typ-413))
21272149++ test-types-partial-union-edges
2128− (weld (check ~.types-partial-union-edges src-411 `tok-411 `tre-411) (check-types ~.types-partial-union-edges ~[%tests %golden ~.types-partial-union-edges %source %jibb] src-411 `typ-411))
2150+ (weld (check ~.types-partial-union-edges src-414 `tok-414 `tre-414) (check-types ~.types-partial-union-edges ~[%tests %golden ~.types-partial-union-edges %source %jibb] src-414 `typ-414))
21292151++ test-types-partial-unresolved-tag
2130− (weld (check ~.types-partial-unresolved-tag src-412 `tok-412 `tre-412) (check-types ~.types-partial-unresolved-tag ~[%tests %golden ~.types-partial-unresolved-tag %source %jibb] src-412 `typ-412))
2152+ (weld (check ~.types-partial-unresolved-tag src-415 `tok-415 `tre-415) (check-types ~.types-partial-unresolved-tag ~[%tests %golden ~.types-partial-unresolved-tag %source %jibb] src-415 `typ-415))
21312153::
21322154:: +check: run golden:jibb on a case and compare both outputs
21332155::
@@ -2238,4 +2260,25 @@
22382260 =/ cor=type -:(ride -:!>(..zuse) text)
22392261 [name.fixture (read-mark:jibb-import name.fixture cor)]
22402262 (golden-types-with-marks:jibb at src external mark-external)
2263+::
2264+++ check-module-trees
2265+ |= [case=@ta want=(unit wain) fixtures=(list [label=@t at=path source=@t])]
2266+ ^- tang
2267+ =/ result (mule |.((module-trees-result fixtures)))
2268+ ?: ?=(%| -.result)
2269+ [leaf+"module fixture parsing crashed" p.result]
2270+ (compare (file case "module-trees.txt") want p.result)
2271+::
2272+++ module-trees-result
2273+ |= fixtures=(list [label=@t at=path source=@t])
2274+ ^- @t
2275+ =/ actual=@t
2276+ %+ rap 3
2277+ %+ join '\0a'
2278+ %+ turn fixtures
2279+ |= fixture=[label=@t at=path source=@t]
2280+ ~_ leaf+(trip label.fixture)
2281+ =/ out (golden:jibb at.fixture source.fixture)
2282+ (rap 3 ~[label.fixture '\0a' tree.out])
2283+ actual
22412284--
tools/golden+45−11
@@ -46,7 +46,7 @@ KNOT = re.compile(r'^[a-z0-9\-.~_]+$')
4646HARNESS = r""":: The harness tools/golden writes after the library. It runs
4747:: golden:lib on each case under mule and returns one cord of fields,
4848:: each <length>:<bytes>, first jibb-golden and the case count, then
49−:: per case its name, ok or crash, tokens, tree and types.
49+:: per case its name, status, tokens, tree, types and module trees.
5050::
5151=> [lib=. ..zuse]
5252|^ %+ rap 3
@@ -55,18 +55,21 @@ HARNESS = r""":: The harness tools/golden writes after the library. It runs
5555 ==
5656::
5757++ run
58− |= [name=@t metadata=[logical=(unit path) check=? imports=(list [module=term mold=term source=@t]) marks=(list [name=term source=@t])] src=@t]
58+ |= [name=@t metadata=[logical=(unit path) check=? imports=(list [module=term mold=term source=@t]) marks=(list [name=term source=@t]) modules=(list [label=@t at=path source=@t])] src=@t]
5959 ^- @t
6060 =/ at=path ?~(logical.metadata (file name) u.logical.metadata)
6161 =/ parsed (mule |.((golden:lib at src)))
6262 ?: ?=(%| -.parsed)
6363 =/ why=@t (crash p.parsed)
64− (fields ~[name 'crash' why why why])
64+ (fields ~[name 'crash' why why why why])
6565 =/ out=[tokens=@t tree=@t] p.parsed
6666 =/ typed (mule |.({types-expr}))
6767 ?: ?=(%| -.typed)
68− (fields ~[name 'types-crash' tokens.out tree.out (crash p.typed)])
69− (fields ~[name 'ok' tokens.out tree.out p.typed])
68+ (fields ~[name 'types-crash' tokens.out tree.out (crash p.typed) ''])
69+ =/ modules (mule |.({modules-expr}))
70+ ?: ?=(%| -.modules)
71+ (fields ~[name 'modules-crash' tokens.out tree.out p.typed (crash p.modules)])
72+ (fields ~[name 'ok' tokens.out tree.out p.typed p.modules])
7073::
7174++ file
7275 |= name=@
@@ -92,9 +95,23 @@ HARNESS = r""":: The harness tools/golden writes after the library. It runs
9295 |= b=@t
9396 (rap 3 ~[(crip (a-co:co (met 3 b))) ':' b ','])
9497{import-helper}
98+{module-helper}
9599--
96100"""
97101
102+MODULE_HELPER = r"""
103+++ module-trees
104+ |= fixtures=(list [label=@t at=path source=@t])
105+ ^- @t
106+ %+ rap 3
107+ %+ join '\0a'
108+ %+ turn fixtures
109+ |= fixture=[label=@t at=path source=@t]
110+ ~_ leaf+(trip label.fixture)
111+ =/ out (golden:lib at.fixture source.fixture)
112+ (rap 3 ~[label.fixture '\0a' tree.out])
113+"""
114+
98115IMPORT_HELPER = r"""
99116++ import-types
100117 |= fixtures=(list [module=term mold=term source=@t])
@@ -143,6 +160,7 @@ class Case:
143160 self.logical_path = golden_case.source_path(folder)
144161 self.imports = golden_case.sur_imports(folder)
145162 self.marks = golden_case.mark_imports(folder)
163+ self.modules = golden_case.module_fixtures(folder)
146164 except ValueError as e:
147165 raise ue.ToolError(str(e))
148166 self.want_types = golden_case.wants_types(folder)
@@ -193,10 +211,17 @@ def run_lines(case):
193211 source = '(rap 3 `(list @t)`~[%s])' % ' '.join(ue.cord_literal(p) for p in parts)
194212 fixtures.append('[%%%s %s]' % (name, source))
195213 marks = '~[' + ' '.join(fixtures) + ']' if fixtures else '~'
196− out = [' %%^ run %s [%s %s %s %s]' % (
214+ fixtures = []
215+ for logical, at, path in case.modules:
216+ with open(path, 'rb') as f:
217+ parts = ue.cord_pieces(f.read())
218+ source = '(rap 3 `(list @t)`~[%s])' % ' '.join(ue.cord_literal(p) for p in parts)
219+ fixtures.append('[%s %s %s]' % (ue.cord_literal(logical.encode()), at, source))
220+ modules = '~[' + ' '.join(fixtures) + ']' if fixtures else '~'
221+ out = [' %%^ run %s [%s %s %s %s %s]' % (
197222 ue.cord_literal(case.name.encode()),
198223 '`' + case.logical_path if case.logical_path else '~',
199− '%.y' if case.want_types else '%.n', imports, marks),
224+ '%.y' if case.want_types else '%.n', imports, marks, modules),
200225 ' %- text',
201226 ' :~ ' + ue.cord_literal(lines[0])]
202227 out += [' ' + ue.cord_literal(line) for line in lines[1:]]
@@ -209,6 +234,7 @@ def golden_program(lib_path, cases):
209234 runs = '\n'.join(line for case in cases for line in run_lines(case))
210235 imported = any(c.imports or c.marks for c in cases)
211236 has_marks = any(c.marks for c in cases)
237+ has_modules = any(c.modules for c in cases)
212238 harness = HARNESS
213239 if imported:
214240 reader = ue.read_text(os.path.join(ue.ROOT, 'jibb-dev', 'lib', 'jibb-import.hoon'))
@@ -224,7 +250,9 @@ def golden_program(lib_path, cases):
224250 prog.add(harness.replace('{count}', str(len(cases)))
225251 .replace('{runs}', runs)
226252 .replace('{types-expr}', types_expr if any(c.want_types for c in cases) else "''")
227− .replace('{import-helper}', IMPORT_HELPER if imported else ''),
253+ .replace('{import-helper}', IMPORT_HELPER if imported else '')
254+ .replace('{modules-expr}', '(module-trees modules.metadata)' if has_modules else "''")
255+ .replace('{module-helper}', MODULE_HELPER if has_modules else ''),
228256 '(harness)', 'harness')
229257 return prog
230258
@@ -258,14 +286,14 @@ def decode(prog, noun, cases):
258286 except ValueError as e:
259287 raise ue.ToolError('the harness output is malformed: %s' % e)
260288 if fields[:2] != [MAGIC, str(len(cases)).encode()] or \
261− len(fields) != 2 + 5 * len(cases):
289+ len(fields) != 2 + 6 * len(cases):
262290 raise ue.ToolError('the harness output has the wrong shape')
263291 for i, case in enumerate(cases):
264− name, status, tokens, tree, types = fields[2 + 5 * i:7 + 5 * i]
292+ name, status, tokens, tree, types, modules = fields[2 + 6 * i:8 + 6 * i]
265293 if name != case.name.encode():
266294 raise ue.ToolError('the harness output is out of order at %s'
267295 % case.name)
268− case.crashed = status in (b'crash', b'types-crash')
296+ case.crashed = status in (b'crash', b'types-crash', b'modules-crash')
269297 if status == b'crash':
270298 tokens, case.crash_at = crash_text(
271299 prog, tokens.decode('utf-8', 'surrogateescape').split('\n'))
@@ -274,9 +302,15 @@ def decode(prog, noun, cases):
274302 case.crash_kind = 'types'
275303 types, case.crash_at = crash_text(
276304 prog, types.decode('utf-8', 'surrogateescape').split('\n'))
305+ elif status == b'modules-crash':
306+ case.crash_kind = 'module-trees'
307+ modules, case.crash_at = crash_text(
308+ prog, modules.decode('utf-8', 'surrogateescape').split('\n'))
277309 case.outputs = {'tokens': tokens, 'tree': tree}
278310 if case.want_types:
279311 case.outputs['types'] = types
312+ if case.modules:
313+ case.outputs['module-trees'] = modules
280314
281315
282316def eval_crash(prog, res, case):
tools/golden_case.py+30
@@ -17,6 +17,11 @@ def source_path(folder):
1717 except UnicodeError:
1818 raise ValueError('%s: path must be UTF-8' % filename)
1919 path = raw[:-1] if raw.endswith('\n') else raw
20+ return ui_path(path, filename)
21+
22+
23+def ui_path(path, filename):
24+ """Validate a logical Jibb path and render it as a Hoon path."""
2025 parts = path.split('/')
2126 if len(parts) < 3 or parts[:2] != ['', 'ui'] or not parts[-1].endswith('.jibb'):
2227 raise ValueError('%s: expected an absolute /ui/.../*.jibb path' % filename)
@@ -95,3 +100,28 @@ def mark_imports(folder):
95100 if out and not wants_types(folder):
96101 raise ValueError('%s: imported marks require a types output' % filename)
97102 return out
103+
104+
105+def module_fixtures(folder):
106+ """Logical Jibb paths, Hoon paths, and sources in a case's modules tree."""
107+ filename = os.path.join(folder, 'modules.txt')
108+ try:
109+ with open(filename, encoding='utf-8') as f:
110+ lines = list(f)
111+ except FileNotFoundError:
112+ return []
113+ except UnicodeError:
114+ raise ValueError('%s: module paths must be UTF-8' % filename)
115+ out, seen = [], set()
116+ for number, line in enumerate(lines, 1):
117+ logical = line[:-1] if line.endswith('\n') else line
118+ where = '%s:%d' % (filename, number)
119+ hoon_path = ui_path(logical, where)
120+ if logical in seen:
121+ raise ValueError('%s: duplicate module fixture' % where)
122+ fixture = os.path.join(folder, 'modules', *logical.split('/')[1:])
123+ if not os.path.isfile(fixture):
124+ raise ValueError('%s: no fixture at %s' % (where, fixture))
125+ seen.add(logical)
126+ out.append((logical, hoon_path, fixture))
127+ return out
tools/ship+42−1
@@ -1054,12 +1054,15 @@ def generate_tests(golden):
10541054 cases = golden_cases(golden)
10551055 has_imports = False
10561056 has_marks = False
1057+ has_modules = False
10571058 for _, folder in cases:
10581059 try:
10591060 sur = golden_case.sur_imports(folder)
10601061 marks = golden_case.mark_imports(folder)
1062+ modules = golden_case.module_fixtures(folder)
10611063 has_imports |= bool(sur or marks)
10621064 has_marks |= bool(marks)
1065+ has_modules |= bool(modules)
10631066 except ValueError as e:
10641067 raise Unable(str(e))
10651068 lines = [fill(TESTS_HEADER, SOURCE=show(golden)).rstrip('\n'),
@@ -1075,6 +1078,7 @@ def generate_tests(golden):
10751078 logical = golden_case.source_path(folder)
10761079 imports = golden_case.sur_imports(folder)
10771080 marks = golden_case.mark_imports(folder)
1081+ modules = golden_case.module_fixtures(folder)
10781082 except ValueError as e:
10791083 raise Unable(str(e))
10801084 args = ['~.%s' % name]
@@ -1121,6 +1125,20 @@ def generate_tests(golden):
11211125 else:
11221126 call = '(weld %s (check-types ~.%s %s src-%d %s))' % (
11231127 call, name, path, i, expected_types)
1128+ if modules:
1129+ if os.path.isfile(os.path.join(folder, 'module-trees.txt')):
1130+ lines.append('/* mtre-%d %%txt %s/module-trees/txt' % (i, base))
1131+ expected_modules = '`mtre-%d' % i
1132+ else:
1133+ expected_modules = '~'
1134+ fixtures = []
1135+ for j, (module, at, _) in enumerate(modules, 1):
1136+ face = 'mod-%d-%d' % (i, j)
1137+ lines.append('/* %s %%jibb %s/modules%s/jibb' %
1138+ (face, base, module[:-5]))
1139+ fixtures.append('[%s %s %s]' % (hoon_cord(module.encode()), at, face))
1140+ call = '(weld %s (check-module-trees ~.%s %s ~[%s]))' % (
1141+ call, name, expected_modules, ' '.join(fixtures))
11241142 arms.append('++ %s\n %s' % (arm, call))
11251143 lines.append('|%')
11261144 if arms:
@@ -1188,6 +1206,29 @@ def generate_tests(golden):
11881206 =/ cor=type -:(ride -:!>(..zuse) text)
11891207 [name.fixture (read-mark:jibb-import name.fixture cor)]
11901208 (golden-types-with-marks:jibb at src external mark-external)
1209+'''
1210+ if has_modules:
1211+ types_helper += '''::
1212+++ check-module-trees
1213+ |= [case=@ta want=(unit wain) fixtures=(list [label=@t at=path source=@t])]
1214+ ^- tang
1215+ =/ result (mule |.((module-trees-result fixtures)))
1216+ ?: ?=(%| -.result)
1217+ [leaf+"module fixture parsing crashed" p.result]
1218+ (compare (file case "module-trees.txt") want p.result)
1219+::
1220+++ module-trees-result
1221+ |= fixtures=(list [label=@t at=path source=@t])
1222+ ^- @t
1223+ =/ actual=@t
1224+ %+ rap 3
1225+ %+ join '\\0a'
1226+ %+ turn fixtures
1227+ |= fixture=[label=@t at=path source=@t]
1228+ ~_ leaf+(trip label.fixture)
1229+ =/ out (golden:jibb at.fixture source.fixture)
1230+ (rap 3 ~[label.fixture '\\0a' tree.out])
1231+ actual
11911232'''
11921233 return '\n'.join(lines) + '\n' + TESTS_HELPERS.replace('\n--\n', '\n' + types_helper + '--\n')
11931234
@@ -1673,7 +1714,7 @@ def cmd_test(ship, args):
16731714 f.write(content)
16741715 say('updated %s from %s' % (show(TESTS_LIB), show(golden)))
16751716 for _name, folder in golden_cases(golden):
1676− for fn in ('tokens.txt', 'tree.txt', 'types.txt'):
1717+ for fn in ('tokens.txt', 'tree.txt', 'types.txt', 'module-trees.txt'):
16771718 data = _read(os.path.join(folder, fn))
16781719 if data and not data.endswith(b'\n'):
16791720 warn("%s has no final newline: the ship can't see that (the "
tools/testdata/selftest+30
@@ -287,6 +287,36 @@ def check_crash_isolated(c, tmp):
287287 '--update should not write a crash:\n' + out)
288288
289289
290+def check_module_fixtures(c, tmp):
291+ cases = copy_cases(tmp)
292+ folder = os.path.join(cases, 'basic')
293+ module = os.path.join(folder, 'modules', 'ui', 'card.jibb')
294+ os.makedirs(os.path.dirname(module))
295+ with open(module, 'w') as f:
296+ f.write('++ card 1\n')
297+ manifest = os.path.join(folder, 'modules.txt')
298+ with open(manifest, 'w') as f:
299+ f.write('/ui/card.jibb\n')
300+ status, out = golden('--dir', cases, '--lib', STUB, '--case', 'basic', '--update')
301+ actual = read(os.path.join(folder, 'module-trees.txt'))
302+ c.expect(status == 0 and actual == b'/ui/card.jibb\n++ card 1\n',
303+ 'module trees update: %d %r\n%s' % (status, actual, out))
304+ status, out = golden('--dir', cases, '--lib', STUB, '--case', 'basic')
305+ c.expect(status == 0, 'module trees compare: ' + out)
306+ with open(manifest, 'w') as f:
307+ f.write('/ui/../card.jibb\n')
308+ status, out = golden('--dir', cases, '--lib', STUB, '--case', 'basic')
309+ c.expect(status == 2 and 'path components' in out, 'invalid module path: ' + out)
310+ with open(manifest, 'w') as f:
311+ f.write('/ui/card.jibb\n/ui/card.jibb\n')
312+ status, out = golden('--dir', cases, '--lib', STUB, '--case', 'basic')
313+ c.expect(status == 2 and 'duplicate module fixture' in out, 'duplicate module: ' + out)
314+ with open(manifest, 'w') as f:
315+ f.write('/ui/missing.jibb\n')
316+ status, out = golden('--dir', cases, '--lib', STUB, '--case', 'basic')
317+ c.expect(status == 2 and 'no fixture' in out, 'missing module: ' + out)
318+
319+
290320def check_fixture_crash_isolated(c, tmp):
291321 """A bad Hoon fixture must not hide the Jibb parse or other cases."""
292322 original = os.path.join(ROOT, 'tests', 'golden', 'types-import-mark')
tools/testdata/ship-selftest+24
@@ -151,6 +151,30 @@ def generator_checks(tmp):
151151 bad_path = False
152152 check('invalid logical paths are rejected', bad_path)
153153
154+ module_cases = os.path.join(tmp, 'modules')
155+ write_case(module_cases, 'main', b'++ main 1\n')
156+ folder = os.path.join(module_cases, 'main')
157+ os.makedirs(os.path.join(folder, 'modules', 'ui'))
158+ with open(os.path.join(folder, 'modules', 'ui', 'card.jibb'), 'w') as f:
159+ f.write('++ card 1\n')
160+ with open(os.path.join(folder, 'modules.txt'), 'w') as f:
161+ f.write('/ui/card.jibb\n')
162+ out = ship.generate_tests(module_cases)
163+ check('Jibb module fixtures are parsed with their logical paths',
164+ '/tests/golden/main/modules/ui/card/jibb' in out and
165+ "['/ui/card.jibb' ~[~.ui ~.card ~.jibb] mod-1-1]" in out and
166+ '(golden:jibb at.fixture source.fixture)' in out and
167+ '(check-module-trees ~.main ~' in out, out)
168+ with open(os.path.join(folder, 'modules.txt'), 'a') as f:
169+ f.write('/ui/card.jibb\n')
170+ try:
171+ ship.generate_tests(module_cases)
172+ except ship.Unable as e:
173+ duplicate_module = 'duplicate module fixture' in str(e)
174+ else:
175+ duplicate_module = False
176+ check('duplicate module fixtures are rejected', duplicate_module)
177+
154178 imported = os.path.join(tmp, 'imported')
155179 write_case(imported, 'molds', b'/- fixture\n++ x 1\n')
156180 folder = os.path.join(imported, 'molds')