Skip to content

feat(stdlib): STDLIB-04a — Mut effect externs (make_ref/get/set) → real impl (Closes #328)#334

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/stdlib-04a-mut-externs
May 24, 2026
Merged

feat(stdlib): STDLIB-04a — Mut effect externs (make_ref/get/set) → real impl (Closes #328)#334
hyperpolymath merged 1 commit into
mainfrom
claude/stdlib-04a-mut-externs

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Lands real implementations of the three Mut effect externs declared in stdlib/effects.affine:

extern fn make_ref<T>(x: T) -> Ref<T> / Mut;
extern fn get<T>(r: Ref<T>) -> T / Mut;
extern fn set<T>(r: Ref<T>, x: T) -> Unit / Mut;

Before this PR they were stubs — the surface parsed and typechecked, but no backend wired the runtime semantics, so any caller would compile and then fail at runtime with make_ref is not defined.

Changes

  • lib/interp.ml — three new VBuiltin entries: make_ref allocates a VMut cell (the existing runtime mutable-cell variant in Value); get/set route through the standard deref / assign primitives. Reuses the same store the borrow-surface &mut already uses.
  • lib/codegen_deno.ml — three new entries in deno_builtins: make_ref{__cell: x}, get((r).__cell), set(((r).__cell = x), null). Single-field object so get/set are O(1); set returns null (Unit) via comma-expression to match the signature.
  • test/test_e2e.ml — three hermetic tests under E2E STDLIB-04a Mut #328:
    1. Int round-trip: make_ref(7); set(r, 42); get(r) == 42
    2. String round-trip (value-polymorphic): make_ref("alpha"); set(r, "omega"); get(r) == "omega"
    3. Deno codegen emits __cell shape (proves the new table entries actually fire).
  • docs/TECH-DEBT.adoc — row 04a marked DONE per the audit-split contract from docs(tech-debt): split STDLIB-04 into 04a–04e per per-extern audit (Refs #175) #333.

Conceptual note

These are runtime mutable cells (Ref<T> parameterised type), distinct from the borrow-checker's &/&mut references — different concept that happens to share the word "ref". The Mut effect on the signatures is what marks the call sites as observably stateful.

Test plan

  • Three new hermetic tests added to the gate (E2E STDLIB-04a Mut #328)
  • No change to stdlib AOT gate count (no new stdlib file)
  • CI: dune runtest green (gate moves from 281 → 284)
  • Hypatia DOC-FORMAT: no .md introduced

Closes #328. Refs #175.


Generated by Claude Code

… impl (Closes #328)

The `Mut` effect externs declared in `stdlib/effects.affine` were stubs:
the surface parsed but no backend wired the runtime semantics, so any
caller would compile and then fail with "make_ref is not defined" at
runtime. This lands the real implementations.

  * interp.ml — `make_ref` allocates a `VMut` cell; `get`/`set` route
    through the existing cell deref/assign primitives (same store used
    by the borrow-surface `&mut`).
  * codegen_deno.ml — lowers to a single-field `{__cell: x}` object so
    `get`/`set` are O(1) field access; `set` is a comma-expression
    returning `null` to match the `Unit` signature.
  * test_e2e.ml — 3 hermetic tests under "E2E STDLIB-04a Mut #328":
    Int round-trip, String round-trip (value-polymorphic), and a
    Deno-codegen assertion that the emitted JS contains `__cell`
    (proves the new builtin-table entries actually fire).

These are runtime mutable cells (`Ref<T>` parameterised type), distinct
from the borrow-checker `&`/`&mut` references — different concept that
happens to share the word "ref". Updates `docs/TECH-DEBT.adoc` row 04a
to DONE per the audit-split contract (Refs #175).

Closes #328. Refs #175.
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 143 issues detected

Severity Count
🔴 Critical 13
🟠 High 70
🟡 Medium 60

⚠️ 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": "Action actions/checkout@v6 needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action denoland/setup-deno@v2 needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "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"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath merged commit 99ae5e3 into main May 24, 2026
14 of 18 checks passed
@hyperpolymath hyperpolymath deleted the claude/stdlib-04a-mut-externs branch May 24, 2026 04:38
hyperpolymath pushed a commit that referenced this pull request May 24, 2026
Reconciles PR #336 (CORE-02 / #234 / ADR-016 truth ledger to
DELIVERED) with two intervening main commits:

  f45afa1  feat(borrow): NLL last-use expiry for ref-bindings
           (CORE-01 pt3 Slice A, Refs #177) (#335)
  99ae5e3  feat(stdlib): STDLIB-04a — Mut effect externs
           (make_ref/get/set) → real impl (Closes #328) (#334)

Single conflict, docs/TECH-DEBT.adoc — HEAD updated CORE-02 (now
CLOSED 2026-05-19 with full ADR-016 S1..S4 narrative); origin/main
(#335) updated CORE-01 (Part 3 Slice A NLL last-use expiry LANDED).
Independent adjacent rows; resolution takes both — neither side
loses information.

The PR's comment edits in lib/codegen.ml, lib/effect_sites.ml,
lib/typecheck.ml, and the test/test_main.ml suite-label change all
survive intact through the merge.

Pure documentation + merge content. Zero behavioural risk.
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.

STDLIB-04a: Mut effect externs (make_ref / get / set) → real implementations

2 participants