Skip to content

Latest commit

 

History

History
272 lines (215 loc) · 9.49 KB

File metadata and controls

272 lines (215 loc) · 9.49 KB

Stdlib extern Audit (STDLIB-04)

Important

STDLIB-04 ("residual extern builtins → real implementations") is a long-tail ledger unit, not a single PR. The stdlib currently declares 135 extern fn and 24 extern type bindings across 11 files. Treating them as one undifferentiated pile is the failure mode this audit prevents.

This document is the triage: it groups every extern by purpose, target-availability, current adapter coverage, and unblock condition. Implementation PRs reference this document and close one row at a time.

Counts (live, 2026-05-23)

Module extern fn extern type Class

effects.affine

14

0

Built-ins (interpreter)

io.affine

5

0

Built-ins (interpreter)

Crypto.affine

3

0

Built-ins (interpreter)

Http.affine

8

1

Typed-boundary bridge (ADR-018 / #225 CPS line)

Network.affine

2

0

Adapter-side (Deno-ESM target)

Deno.affine

24

3

Adapter-side (Deno-ESM target)

Sqlite.affine

6

1

Adapter-side (Deno-ESM target)

Vscode.affine

55

12

Adapter-side (packages/affine-vscode)

VscodeLanguageClient.affine

4

2

Adapter-side (packages/affine-vscode)

Grammy.affine

10

3

Adapter-side (Deno-ESM target)

Ajv.affine

4

2

Adapter-side (Deno-ESM target)

Total

135

24

Classification (what "real implementation" means per row)

extern declarations are type-only signatures: they tell the compiler the shape of a function/type that exists at the host boundary. "Real implementation" means different things depending on which boundary the extern rides over. We recognise four classes:

Class Definition "Real impl" criterion

Built-in (interpreter)

Side-effecting primitive that must be available to interpreter eval (affinescript eval) — e.g. println, read_file, random_string. Has no AffineScript-side body; the interpreter matches the symbol name and dispatches a host-side handler.

Interp.register_builtin (or equivalent) wires the name to an OCaml function. Today some of these are stubbed or partial; the unblock is implementing the OCaml handler.

Typed-boundary bridge

Crosses the language boundary with a contract (e.g. Http.fetch returns a typed Json after CPS lowering). Has a producer-side type signature here and a verifier-side contract in hyperpolymath/typed-wasm (or the convergence ABI).

Producer-side codegen path + verifier-side type contract
runtime adapter all green. Http.fetch is the canonical example (landed via the #225 CPS line, PR1..PR3d).

Adapter-side (Deno-ESM)

Compiles via the --deno-esm backend; the extern is realised by the emitted ESM importing a JS module. The "real impl" is the adapter shim in packages/<adapter>/mod.js (or equivalent).

Adapter package exists, the symbol is exported, and a cross-runtime smoke test under affinescript-deno-test/ exercises it.

Adapter-side (Node / VS Code host)

Compiles via the Node-CJS backend; the emitted .cjs calls into packages/affine-vscode/mod.js (or another Node-side adapter) at activate-time. The "real impl" is the JS-side handle table and the per-method wrapper.

packages/affine-vscode (or sibling) exposes the symbol via the shared handle table; in-editor smoke under editors/vscode/test/ exercises it.

Per-module triage

effects.affine (14 fn, 0 type) — Built-in

extern fn Status Notes

print(String)

adequate

Interpreter + WASI preview1 emit.

println(String)

adequate

Same.

read_line() → String

stub-only

Interpreter has placeholder; not yet wired through codegen-deno.

read_file(path)

adequate

Interpreter + WASI preview1.

write_file(path, content)

adequate

Same.

make_ref<T> / get<T> / set<T>

adequate

Interpreter wires to ref cells; codegen targets reject (mutable cells are not in the GC backend yet — see CORE-02-adjacent gap).

panic(msg)

adequate

Throws effect-row punt; interpreter raises; codegen emits unreachable.

error<T>(msg)

adequate

Same shape as panic.

int_to_string/string_to_int

partial

Interpreter only; deno backend re-exports JS native; wasm-core has no string story.

string_length/string_concat

partial

Same.

Per-row unblock: not a single PR. read_line for the non-interpreter targets is the next concrete row; everything else is "adequate for the current consumer surface".

io.affine (5 fn, 0 type) — Built-in

extern fn Status Notes

chdir(path)

stub-only

Interpreter only.

create_dir(path)

stub-only

Same.

remove_dir(path)

stub-only

Same.

list_dir(path)

stub-only

Same.

setenv(name, value)

stub-only

Blocked on INT-03 S5 (native env/argv) for cross-target parity.

Unblock: INT-03 S5 (native clocks/env/argv) for the WASI path; deno backend can ship adapter coverage independently.

Crypto.affine (3 fn, 0 type) — Built-in

extern fn Status Notes

random_string(n)

partial

Interpreter wires Random.string; deno target uses crypto.randomUUID-derived bytes; wasm-core absent.

random_f64()

partial

Same.

time_ms()

partial

Same; deno + interpreter; INT-03 S4a (WASI clock) covers WASI emit.

Unblock: noted for completeness; not on the critical path.

Http.affine (8 fn, 1 type) — Typed-boundary bridge

Status: DONE — STDLIB-01 closed. See docs/TECH-DEBT.adoc STDLIB-01: ADR-018 delivery plan complete; Deno-ESM (#226)
typed-wasm CPS line PR1..PR3d (#227/#233/#236/#237/#238/#266) all merged.

Network.affine (2 fn, 0 type) — Adapter-side (Deno-ESM)

extern fn Status Notes

hostname() → String

stub-only

No adapter package; not on a known consumer’s critical path.

tcp_connect(host, port) → Socket

stub-only

Same; gates on Tokio-style async ABI which isn’t designed yet.

Unblock: lowest-priority class; no consumer requesting it.

Deno.affine (24 fn, 3 type) — Adapter-side (Deno-ESM)

Largest non-Vscode adapter. Covers Deno.readFile, Deno.cwd, Deno.run, file-system primitives, env access, etc.

Surface area Status Notes

Filesystem reads (readTextFile, readDir)

partial

packages/affine-js loader uses some of these; not a full adapter shim.

Filesystem writes (writeTextFile, mkdir, remove)

stub-only

No consumer yet.

Process (run, Deno.exit, env, args)

stub-only

Overlaps with INT-03 S5 (WASI env/argv).

HTTP server (Deno.serve)

stub-only

Overlaps with affinescript-tea runtime + INT-07.

Unblock: bulk of this should fold into packages/affine-deno (does not yet exist as a sibling to affine-vscode); creation of that package is the meta-unblock.

Sqlite.affine (6 fn, 1 type) — Adapter-side (Deno-ESM)

open, prepare, exec, query, close, transaction. All stub-only. No adapter package. Unblocks when a consumer (currently none) requests it.

Vscode.affine (55 fn, 12 type) — Adapter-side (Node/VS Code)

Largest extern surface in the repo. Already has an adapter (packages/affine-vscode/mod.js) and is load-bearing — issue #35 Phase 3 (VS Code extension migration from TS to AffineScript) is shipping against it.

Surface area Status Notes

commands.registerCommand family

done

Live in editors/vscode/src/extension.affine; smoke-tested via PR #317.

window (show*, activeTextEditor, terminals, …​)

partial

Used by extension.affine; not all 55 surface methods exercised.

workspace (getConfiguration, fileSystemWatcher, …​)

partial

Same.

languages (createDiagnosticCollection, …​)

partial

Same.

String marshalling helpers

done

Shared handle table.

Unblock: the unused methods get filled in row-by-row when a consumer needs them; there is no requirement to implement all 55 before #35 Phase 4 (rattlescript-face sweep) closes.

VscodeLanguageClient.affine (4 fn, 2 type) — Adapter-side (Node)

LSP client wrapper. Already adapter-covered; #317 smoke tests it end-to-end. No outstanding rows.

Grammy.affine (10 fn, 3 type) — Adapter-side (Deno-ESM)

Telegram bot framework adapter. Stub-only; no consumer.

Ajv.affine (4 fn, 2 type) — Adapter-side (Deno-ESM)

JSON-schema validator adapter. Stub-only; no consumer.

Implementation policy

Per the testing standards (docs/standards/TESTING.adoc):

  • Every extern implementation PR must add at least one smoke test under the matching adapter’s test path (or affinescript- deno-test/ for the Deno-ESM class, editors/vscode/test/ for the VS Code class, an interpreter alcotest for the built-in class).

  • The extern row in this document moves from stub-only / partial to done only when the smoke test lands.

  • No PR may stub a new extern without recording it here.

Cross-references

  • TECH-DEBT.adoc — STDLIB-04 ledger entry (S3, open).

  • ECOSYSTEM.adoc — INT-01..12 integration roadmap that extern adapters ride on.

  • standards/TESTING.adoc — smoke-test requirements per class.

  • packages/affine-vscode/mod.js — the canonical Node/VS-Code-host adapter shape.

Update protocol

Each row’s status is in-line with the implementation reality and is updated by the PR that lands the implementation. This is not a status mirror for STATE.a2ml; STATE.a2ml’s drift-flag points here for STDLIB-04 specifics.