Skip to content

feat(codegen): #225 PR3a — WasmGC CPS transform, multi-var live-local capture#236

Merged
hyperpolymath merged 1 commit into
mainfrom
stage-c/225-pr3-capture
May 19, 2026
Merged

feat(codegen): #225 PR3a — WasmGC CPS transform, multi-var live-local capture#236
hyperpolymath merged 1 commit into
mainfrom
stage-c/225-pr3-capture

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

#225 PR 3a — WasmGC CPS transform: multi-var live-local 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).

Design

  • Structural-conservative async boundary (owner-chosen; Effect-threaded async-boundary detection for the WasmGC CPS transform (generalise the structural-conservative recogniser) #234 tracks the effect-threaded generalisation): boundary = the let whose RHS calls a recognised async primitive (http_request_thenable). Also tightens PR2 detection (was: any ExprApp) — strictly safer.
  • Single boundary only: a recognised primitive in pre values or cont ⇒ fall back. Async→Async chaining is PR3c.
  • pre restricted to simple lets (well-defined capture set); any other shape ⇒ unchanged synchronous lowering (zero regression).
  • ADR-013 obligation 1 discharged by composition (no new borrow-checker code): borrow-check runs on the straight-line AST before the transform (verified bin/main.ml pipeline order); the PR2 once-resumption trap guarantees cont runs exactly once. Documented in the recogniser docstring.

Verification

New e2e tests/codegen/http_cps_capture.{affine,mjs}: 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). 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

… 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
@hyperpolymath hyperpolymath merged commit bf28bcd into main May 19, 2026
11 of 12 checks passed
@hyperpolymath hyperpolymath deleted the stage-c/225-pr3-capture branch May 19, 2026 08:01
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 44 issues detected

Severity Count
🔴 Critical 12
🟠 High 21
🟡 Medium 11

⚠️ Action Required: Critical security issues found!

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
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