Skip to content

feat(multimodule): per-module split + tw link — the killer feature over genuinely separate binaries (#140)#203

Merged
hyperpolymath merged 1 commit into
mainfrom
feat/module-split
Jul 7, 2026
Merged

feat(multimodule): per-module split + tw link — the killer feature over genuinely separate binaries (#140)#203
hyperpolymath merged 1 commit into
mainfrom
feat/module-split

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Item 2 of the construction sequence (owner: "2 yes").

module Name { … } blocks (the grammar's v1.2 form) now drive a real per-module split: parse_modules parses each block standalone, then re-parses importers seeded with the producer's actual region schemas — so cross-module accesses lower against the producer's real field offsets and instance counts, not the expected subset's packing. tw build --split emits one wasm per module and tw link runs the ADR-0007 link-graph pass over the built binaries:

tw build game.twasm --split   →  game.physics.wasm + game.ai.wasm + game.render.wasm
tw link game.*.wasm           →  CERTIFIED ai imports physics.Entity
                                 CERTIFIED render imports physics.Entity

The examples/02 killer feature now runs over genuinely separate binaries instead of a merged parse (fixture: tests/fixtures/multimodule/game.twasm). Also lands #140's remaining deliverable — the producer-emitted callee/caller differential pair, committed under tests/fixtures/producer_pair/ (clean caller accepted, double-caller rejected).

181 workspace tests, 0 failures.

🤖 Generated with Claude Code

…er genuinely separate binaries (#140)

- parser: `module Name [isolated] { … }` blocks (the grammar's v1.2 L13
  form) now drive a real per-module split. `parse_modules` slices the
  source, parses each block standalone, then RE-parses importers seeded
  with the producer's ACTUAL region schemas (real field offsets + real
  instance counts) so cross-module accesses and scans lower against the
  producer's layout, not the expected subset's packing. The merged
  single-module view (`parse_module`) flattens blocks, preserving the
  corpus contract. NOTE: module blocks previously hit skip_declaration
  and were silently DROPPED from the parse.
- tw CLI: `tw build --split` emits `<stem>.<module>.wasm` per block;
  `tw link <files…>` runs the ADR-0007 link-graph pass over built
  modules (names = file stems), printing CERTIFIED/VIOLATION lines and
  failing non-zero on violations.
- tests/fixtures/multimodule/game.twasm: examples/02 restructured with
  real module blocks (lowerable bodies); 4 tests: split + seeding
  (actual schema, matching byte_size), 3 binaries validate + link with
  2 certificates, mutant expectation rejected at link, merged view
  unchanged.
- #140 differential pair: producer-emitted callee/caller ownership
  fixtures committed under tests/fixtures/producer_pair/ (clean caller
  ACCEPTED, double-caller REJECTED LinearImportCalledMultiple) with
  provenance README — byte-level drift armour mirroring c5_real and
  zig_producer.

End-to-end: `tw build game.twasm --split` -> 3 wasm files -> `tw link`
-> "2 certificate(s), no violations".

Workspace: 181 tests, 0 failures.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hyperpolymath
hyperpolymath merged commit 5d67603 into main Jul 7, 2026
24 checks passed
@hyperpolymath
hyperpolymath deleted the feat/module-split branch July 7, 2026 05:41
@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant