Skip to content

[Feature] purwc: a single module compilation worker - purs-wasm orchestrate mode and nix-style cache store - #46

Merged
katsujukou merged 38 commits into
mainfrom
feat/purwc
Jun 29, 2026
Merged

katsujukou merged 38 commits into
mainfrom
feat/purwc

Conversation

@katsujukou

@katsujukou katsujukou commented Jun 23, 2026 •

Copy link
Copy Markdown
Collaborator

What's in this PR

Separated compilation — ADR 0038

  • cli-lib: common CLI machinery extracted from purs-wasm / ulib-tooling into a shared package.
  • purwc: a standalone single-module worker. It compiles one module from its source and its dependencies' .pmi interfaces into three artifacts — {M}.pmi (the dependent-facing interface + optimization summary), {M}.wasm (the object), and {M}.link.json (link metadata). The .pmi is now a complete interface (no .pmo needed by dependents).
  • compile-batch: a long-lived worker mode that compiles a topo-ordered work-list in one process, amortizing Binaryen init across modules.
  • Orchestrator: purs-wasm build --orchestrate drives purwc per module (in dependency order) and links the results.

Content-addressed library store — ADR 0040

  • Cache key: nix-style source/toolchain tag hashing, and a recursive .pmi key — a module is keyed against its dependencies' .pmi keys (content-address), not their summary hashes.
  • Foreign self-merge (P2): a module's kept foreign .wat is merged into {M}.wasm, so a worker artifact is self-contained.
  • caf_init reachability ([Feature] Monomorphization (unbox polymorphic container elements) #19): per-binding reference graph emitted by the worker; the orchestrator chains caf_init only for entry-reachable modules.
  • The store: $PURS_WASM_STORE holds the {.pmi, .wasm, .link.json} triplet per library module, keyed by content. Write-back is partitioned by own vs library — a .spago dependency or a ulib shadow goes to the global store (shared across builds and projects), the project's own modules stay in the local _build. store; reuse is content-addressed and sound (version drift → key mismatch → recompile).
  • prewarm (optional): precompile a package set's library closure into the store.
  • .pmo retired (P6): the .pmi interface + the .wasm object are the artifacts; the separate optimized-MIR object is gone. The in-process whole-program path stays as an uncached differential oracle.

Fixes

  • Inliner self-pollution fix (exclude the module itself from its inline summary), and the generic-dispatch size cap lowered to 8000.
  • Lower: a non-functional recursive value around Control.Lazy.fix was mis-handled.
  • CI: the compiler-leg e2e prebuild now builds purs-wasm explicitly (it had relied on ulib-tooling transitively pulling it in, which no longer holds since the maintainer CLI was decoupled from the orchestrator).

Cleanup & docs

  • User-facing CLI messages/help no longer mention internal ADR numbers.
  • ADR 0038/0039/0040 updated to reflect what shipped; new ADR 0041 (ship pre-built corefn behind a build-time content-based compatibility gate; drop ulib install) and ADR 0042 (orchestrate as the default build; trigger-based retirement of the whole-program oracle) capture the agreed next direction (Proposed).

Checklist

CI passing is enforced by the required ci-gate status check, not by a box here.
The items below are the human-judgment gates:

  • Docs updated — any behaviour/feature/representation change is reflected in docs/ and relevant ADR(s).
  • Tests — added/updated for this change; a bug fix includes a regression guard in the routinely-run lane (unit / e2e), not only a slow test:bin script.
  • Design changes have an ADR — added or updated, with its Status set (ADR-first).
  • No perf regression — for optimizer / runtime / lowering changes, benchmarks compared (node bench/run.mjs <dir>; do not overwrite bench/snapshots/baseline.json). N/A otherwise.
  • Runtime GC-type / ABI / canonicalization — changes to the value-type substrate or the host/runtime ABI keep cross-module type canonicalization intact. N/A otherwise.

@katsujukou katsujukou changed the title Feat/purwc [Feature] purwc: a single module compilation worker - purs-wasm orchestrate mode and nix-style cache store Jun 23, 2026
@katsujukou
katsujukou merged commit 69cdd98 into main Jun 29, 2026
14 checks passed
@katsujukou
katsujukou deleted the feat/purwc branch June 29, 2026 06:39
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