feat(codegen): #225 PR3a — WasmGC CPS transform, multi-var live-local capture#236
Merged
Conversation
… capture Lifts PR2's zero-capture restriction. An Async fn body may now be <simple pre-lets>; let binder = <async-prim call>; <cont>, where cont references prelude-bound live locals alongside the async result binder. The prelude runs synchronously; the continuation is reified via the existing #199 ExprLambda path, which env-captures binder + every referenced pre-local (the #199 path already marshals N captures — no new closure code). Async boundary identification is structural-conservative (owner-chosen, affinescript#234 tracks the effect-threaded generalisation): the boundary is the let whose RHS calls a recognised async primitive (http_request_thenable). This also TIGHTENS PR2 detection (was: any ExprApp) — strictly safer. Single boundary only; a recognised primitive appearing in pre values or cont ⇒ fall back (Async→Async chaining is PR3c, affinescript#... PR3c task). pre is restricted to simple lets so the captured set is well-defined; any other shape ⇒ the unchanged synchronous lowering (zero regression). ADR-013 obligation 1 (affine/linear capture used exactly once; double-resumption impossible) is discharged by composition, not new static machinery: borrow-check runs on this straight-line AST BEFORE the transform (verified pipeline order in bin/main.ml), and the PR2 once-resumption trap guarantees cont executes exactly once. Documented in the recogniser docstring. New e2e tests/codegen/http_cps_capture.{affine,mjs}: a prelude local tag=7 captured across the split; continuation sees addTag(7, 200) ⇒ 7200, fires once, second entry traps. Full tools/run_codegen_wasm_tests.sh green (incl. PR2 base + PR1 skeleton, no regression); dune test --force 258 green. Conforms to typed-wasm ADR-005 (accessor model). Refs #225 #160
🔍 Hypatia Security ScanFindings: 44 issues detected
View findings[
{
"reason": "Stray AI.a2ml in root -- use 0-AI-MANIFEST.a2ml only",
"type": "banned",
"file": "AI.a2ml",
"action": "delete",
"rule_module": "root_hygiene",
"severity": "high"
},
{
"reason": "Superseded by 0-AI-MANIFEST.a2ml",
"type": "banned",
"file": "AI.djot",
"action": "delete",
"rule_module": "root_hygiene",
"severity": "high"
},
{
"reason": "Issue in quality.yml",
"type": "missing_workflow",
"file": "quality.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in security-policy.yml",
"type": "missing_workflow",
"file": "security-policy.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
"type": "unpinned_action",
"file": "governance.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/example/smoke_driver.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/cli.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/lib/compile.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/affinescript/affinescript/affinescript-deno-test/lib/runner.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
hyperpolymath
added a commit
that referenced
this pull request
May 19, 2026
…lete) Both targets of the portable Http primitive are green: - Deno-ESM #160 — PR #226 (shipped). - typed-wasm #225 — the ADR-013 CPS line PR1..PR3d all merged: #227 (PR1 verified Thenable foundation), #233 (PR2 base case), #236 (PR3a env capture), #237 (PR3b affine-capture obligation), #238 (PR3c Async→Async chaining), #266 (PR3d typed Response reader + http_fetch-parity wasm e2e). The transparent `fetch/get -> Response` source surface is delivered on both targets; ADR-013's delivery plan is complete. Ledger STDLIB-01 + the ADR-013 delivery plan truthed. Two follow-ups remain independently tracked (NOT part of this slice): effect-threaded boundary generalisation #234; estate-wide #199/#205 re-validation #235. Gate: `dune test --force` 278/278 (docs only; zero regression). Closes #160 Closes #225
hyperpolymath
added a commit
that referenced
this pull request
May 19, 2026
…lete) (#268) Both targets of the portable Http primitive are green: - Deno-ESM #160 — PR #226 (shipped). - typed-wasm #225 — the ADR-013 CPS line PR1..PR3d all merged: #227 (PR1 verified Thenable foundation), #233 (PR2 base case), #236 (PR3a env capture), #237 (PR3b affine-capture obligation), #238 (PR3c Async→Async chaining), #266 (PR3d typed Response reader + http_fetch-parity wasm e2e). The transparent `fetch/get -> Response` source surface is delivered on both targets; ADR-013's delivery plan is complete. Ledger STDLIB-01 + the ADR-013 delivery plan truthed. Two follow-ups remain independently tracked (NOT part of this slice): effect-threaded boundary generalisation #234; estate-wide #199/#205 re-validation #235. Gate: `dune test --force` 278/278 (docs only; zero regression). Closes #160 Closes #225
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#225 PR 3a — WasmGC CPS transform: multi-var live-local capture
Lifts PR2's zero-capture restriction. An
Asyncfn body may now be<simple pre-lets>; let binder = <async-prim call>; <cont>, wherecontreferences prelude-bound live locals alongside the async result binder. The prelude runs synchronously; the continuation is reified via the existing #199 ExprLambda path, which env-capturesbinder+ every referenced pre-local (the #199 path already marshals N captures — no new closure code).Design
letwhose RHS calls a recognised async primitive (http_request_thenable). Also tightens PR2 detection (was: anyExprApp) — strictly safer.prevalues orcont⇒ fall back. Async→Async chaining is PR3c.prerestricted to simplelets (well-defined capture set); any other shape ⇒ unchanged synchronous lowering (zero regression).bin/main.mlpipeline order); the PR2 once-resumption trap guaranteescontruns exactly once. Documented in the recogniser docstring.Verification
New e2e
tests/codegen/http_cps_capture.{affine,mjs}: prelude localtag=7captured across the split → continuation seesaddTag(7, 200)⇒7200, fires once, second entry traps. Fulltools/run_codegen_wasm_tests.shgreen (incl. PR2 base + PR1 skeleton, no regression);dune test --force258 green.Conforms to typed-wasm ADR-005 (accessor model). First slice of former PR3, split per the one-fix-per-PR method. Refs #225 #160 (NOT Closes — joint-close is the final #225 PR).
🤖 Generated with Claude Code