diff --git a/current/CHECKPOINT-EXTERN-EXPORT.md b/current/CHECKPOINT-EXTERN-EXPORT.md index 162ba68..9d8eb96 100644 --- a/current/CHECKPOINT-EXTERN-EXPORT.md +++ b/current/CHECKPOINT-EXTERN-EXPORT.md @@ -5,7 +5,38 @@ Companion to `current/PLAN-EXTERN-EXPORT.md` — one merged plan: **Part A** add every commit, one step at a time per the cadence rule. ## Last completed step -**Phase 8 — CUTOVER: parser hard-rejects `#foreign`** (`feat!` commit `3811311`, +**Phase 9.1 (partial) — internal linkage-identifier purge** (commits `b838f63` 9.1a, +`b78e7dd` 9.1b, `cd14794` 9.1c). **PHASE 9 STARTED.** Decision 6 = PURGE EVERYTHING, +scoped (user, 2026-06-15): purge `foreign` from **all `.sx` files + all documentation + +all our Zig (`src/`)**, analyzing each grep hit — **legitimate keeps stay** +(SQLITE_CONSTRAINT_FOREIGNKEY + other SQLite API constant names, vendored +`library/vendors/sqlite/c/*`, `1176-diagnostics-foreign-removed.sx` [the rejection test +MUST contain `#foreign`], the parser rejection-message string + `hash_foreign` token +[kept so `#foreign` keeps its friendly deprecation error]). +- **9.1a** (`b838f63`): 5 collision-free linkage renames — `callForeign`→`callExtern`, + `marshalForeignArg`→`marshalExternArg`, `dedupeForeignSymbol`→`dedupeExternSymbol`, + `foreign_name_map`→`extern_name_map`, `is_foreign_c_api`→`is_extern_c_api`. +- **9.1b** (`b78e7dd`): the "foreign symbol already bound" diagnostic (decl.zig) + + resolveFuncByName panic (call.zig) → "extern symbol". Intentional 1172 regen. +- **9.1c** (`cd14794`): **deleted** the dead `VarDecl.is_foreign`/`foreign_lib`/ + `foreign_name` fields (the global `#foreign` path rejects → write-dead; 3 coalescing + readers in decl.zig simplified to `vd.extern_name`/`vd.is_extern`). +All snapshot-neutral except the intentional 1172 regen; suite green (646/444). + +**COLLISION ANALYSIS (done — drives the rest of 9.1/9.2):** +- `is_foreign` lives on FnDecl?(no — flipped to `extern_export`), **VarDecl (deleted in + 9.1c)**, and **ForeignClassDecl (ast.zig:903 — STILL LIVE**, distinguishes runtime-class + reference vs define; renamed in 9.2, not 9.1). +- `is_extern`/`extern_lib`/`extern_name` already exist (VarDecl + IR insts) — so the + old `foreign_*` linkage names could NOT be blind-renamed onto them; 9.1c deleted the + dead VarDecl trio instead of renaming. +- `foreign_expr` (25) is **still BUILT by `c_import.zig` auto-synthesis** (`#import c + {#include}` synthesizes fn bodies as `foreign_expr`). To eliminate it: migrate that + synth path to build the extern shape (empty-block body + `extern_export = .extern_`), + exactly the Phase 5.0 fn-body flip but for auto-synth — THEN delete the `foreign_expr` + node + all readers. This is the last 9.1 item. + +### Prior: Phase 8 — CUTOVER: parser hard-rejects `#foreign` (`feat!` commit `3811311`, preceded by the 8.0 xfail `8180faf` + 3 pre-cutover `refactor`s `2cce6a3`/`720556b`/ `d132aab`). **PHASE 8 COMPLETE.** The prefix `#foreign` linkage directive is removed: all four parse sites (const-with-type 316, data global 425, fn body 2065, runtime-class @@ -257,44 +288,47 @@ AOT), 1227 (export fn rename, AOT), 1348 (objc extern class), 1349 (objc export (jni extern class), 1174/1175 (interplay diagnostics). ## Next step -**PART B — Phase 9 (total `foreign` purge — the zero-`foreign` invariant).** Phases 5–8 -COMPLETE: `extern`/`export` is the sole C-linkage SURFACE; `#foreign` is hard-rejected. -**Decision 6 RATIFIED (user, 2026-06-15): PURGE EVERYTHING** — the Phase 9.4 gate is -absolute (`grep -rniE 'foreign' src/ library/ examples/ issues/ specs.md readme.md -CLAUDE.md` → 0), including `issues/*.md` writeups. +**PART B — finish Phase 9 (the scoped `foreign` purge).** Phases 5–8 + 9.1a/b/c COMPLETE. +**Gate (scoped per user 2026-06-15):** `grep -rniIE 'foreign'` → 0 across `.sx` files, +all docs, and our `src/` Zig — EXCLUDING the legitimate keeps listed in Last completed +step (SQLite API names, vendored C, the rejection test/message + `hash_foreign` token). -Remaining `foreign` footprint (run `grep -rniIE 'foreign'` per area to scope each step): -- **Comment-only `#foreign` in `examples/`** — the deferred provenance comments (0716, - 0729, 1216, 1223/1224/1225/1229/1230/1231, 1332, 1348, 1349, 1426 + the migrated - feature tests' leftover comments + issues/0030.sx). ⚠ Many CONTRAST `#foreign` vs - `extern` ("no `#foreign`, no `#library`") — a blind `s/#foreign/extern/` yields - nonsense; rewrite each comment to stay coherent. Mechanical-ish but needs reading. -- **`issues/*.md` prose** (~12 files) — bug writeups referencing `#foreign`. Rewrite to - `extern`/`export` per Decision 6 (purge everything). Provenance is preserved in the - git history + the `(Regression issue NNNN)` note, not the keyword spelling. -- **Internal `src/` identifiers** (Phase 9.1/9.2 — the big mechanical rename): - - 9.1 linkage: `foreign_expr`(still BUILT by `c_import.zig` auto-synthesis — migrate - that path first, then the node folds away) · `is_foreign`→`is_extern` · `foreign_lib`/ - `foreign_name`→`extern_*` · `foreign_name_map`→`extern_name_map` · `callForeign`→ - `callExtern` · `marshalForeignArg` · `is_foreign_c_api` · `dedupeForeignSymbol` · the - "foreign symbol already bound" diagnostic text → "extern symbol" (surfaces in 1172). - - 9.2 runtime-class → `Runtime*Class*` (Decision 5 ratified): `ForeignClassDecl`(65) · - `ForeignMethodDecl` · `ForeignClassMember` · `ForeignFieldDecl` · `foreign_class_map` · - `current_foreign_class`/`_method` · `foreign_path` · `parse/tryParseForeignClass*` · - `lowerForeign{Method,Static}Call` · `findForeign*InChain` · `resolveForeign*` · - `register*ForeignClass*` · `*ForeignRefs` · `ForeignRuntime`. - - 9.0 surface: the `hash_foreign` token + lexer entry + the 4 parse-path REJECTION - stubs + the `lex hash_foreign` test. ⚠ DESIGN CHOICE: keep the token so `#foreign` - keeps its nice migration message, or delete it (→ generic "unknown directive")? - Recommend KEEP the token + rejection through at least one release for a good - deprecation, deferring the token deletion. Decide before 9.0. - - 9.3 docs: `CLAUDE.md` still references `#foreign` in several places (file-roles, - bundling, the rejected-patterns examples) — purge those too for the gate. -- **9.4 acceptance gate:** the absolute grep → 0 across all gated areas. - -Suggested order: 9.3-examples (comment rewrite) + issues/*.md first (low-risk text), then -9.1/9.2 internal renames (mechanical, snapshot-neutral — but 9.1's diagnostic-text rename -intentionally regens 1172), then 9.0 surface decision, then the 9.4 gate. +Remaining, in suggested (dependency-safe) order: +1. **9.1d — eliminate `foreign_expr`** (last linkage item): migrate `c_import.zig` + auto-synthesis to build the extern shape instead of a `foreign_expr` body (the Phase + 5.0 fn-body flip applied to auto-synth), then delete the `foreign_expr` AST node + + `ForeignExpr` + all readers (25). Snapshot-neutral; verify full corpus (the `#import c` + examples 1215/1216/1217 + sqlite 1624 exercise it). +2. **9.2 — runtime-class family rename → `Runtime*` (Decision 5).** The BIG one, do as + small per-identifier commits with `zig build` after each (snapshot-neutral). Targets + (counts): `ForeignClassDecl`(65)→`RuntimeClassDecl` · `foreign_path`(62)→`runtime_path` + · `foreign_class_map`(44) · `current_foreign_class`(34)/`_method` · `ForeignMethodDecl`(31) + · `foreign_class_decl`(30) · `foreign_expr`-gone-by-now · `ForeignClassMember`(20) · + `ForeignFieldDecl`(15) · `ForeignClassDecl.is_foreign`(the live one)→e.g. `is_reference` + · `parse/tryParseForeignClass*` · `lowerForeign{Method,Static}Call` · + `findForeign*InChain` · `resolveForeign*` · `register*ForeignClass*` · `*ForeignRefs` · + `ForeignRuntime` · `current_foreign_class`/`_method`. ⚠ COUPLED .sx↔.zig hook names: + `jni_main_foreign_path_at`/`jni_main_foreign_paths`/`hookJniMainForeignPathAt`/ + `foreignPathToJavaName`/`splitForeignPath` span build.sx + bundle.sx + compiler_hooks.zig + + specs.md (2975/3049) — rename all four sites together. +3. **9.x-src-comments** — the ~200 bare-`foreign` comments in `src/` (rename last, since + many reference identifiers that 9.1d/9.2 rename; do AFTER those so the comment text + matches the new names). +4. **9.3-examples comments** — the deferred `.sx` provenance comments (0716, 0729, 1205/ + 1207/1216/1218/1219/1220, 1223-1231, 1306/1308/1315/1318/1320/1321/1331/1332/1348/1349, + 1412/1414/1417/1418/1419/1426, 0117/0415, 1140/1141/1125, issues/0030.sx). ⚠ Many + CONTRAST `#foreign` vs `extern` ("no `#foreign`, no `#library`") or reference renamed + internals — rewrite each to stay coherent (NOT blind sed). ALSO: `1219-ffi-foreign.sx` + prints `"foreign-rename: {}"` to STDOUT — changing it regens the snapshot (intentional). +5. **9.3-issues** — `issues/*.md` writeups (~20 files) → rewrite `#foreign`/`foreign` to + `extern`/`export`/`runtime-class` per the renames. +6. **9.3-docs** — specs.md (12: rename "Foreign Function Interface" heading → "C Interop"; + the `#import c` "foreign declarations" prose; the jni_main_foreign_path_at refs with #2), + readme.md (2), CLAUDE.md (2: host_ffi `#foreign("c")` ref + "foreign calls"). +7. **9.0 surface decision** — keep `hash_foreign` token + rejection (recommended: good + deprecation) vs delete it. If kept, the token + the rejection-message string + 1176 are + permanent legitimate keeps; the gate excludes them. +8. **9.4 gate** — `grep -rniIE 'foreign'` over the gated set minus the keep-list → 0. - **6.2 verification note (carry forward):** the `platform/` runtime modules (uikit/android/android_jni) are NOT compiled by any marker'd host corpus test — verify future platform-adjacent migrations via direct `sx ir` on importers (1610/1606 compile @@ -423,6 +457,16 @@ Part A ratified (bare / postfix / `⇒ callconv(.c)` / lib-separate). Part B: deleted at cutover). Affects only diagnostic wording — IR/behavior identical either way. ## Log +- (9.1c) Deleted dead `VarDecl.is_foreign`/`foreign_lib`/`foreign_name` (global `#foreign` + rejects → write-dead); 3 decl.zig readers simplified to `vd.extern_name`/`vd.is_extern`. + Snapshot-neutral; suite green (646/444). `refactor` `cd14794`. +- (9.1b) "foreign symbol already bound" diagnostic + resolveFuncByName panic → "extern + symbol"; intentional 1172 regen. Suite green. `refactor` `b78e7dd`. +- (9.1a) **PHASE 9 STARTED.** 5 collision-free linkage renames (callForeign→callExtern, + marshalForeignArg, dedupeForeignSymbol, foreign_name_map→extern_name_map, + is_foreign_c_api). Snapshot-neutral; suite green. `refactor` `b838f63`. Decision 6 + scoped by user: purge `.sx` + docs + our `src/` Zig, keep legitimate hits (SQLite API + names, vendored C, the rejection test/message + hash_foreign token). - (8.1 cutover) **PHASE 8 COMPLETE.** Parser hard-rejects `#foreign` at all 4 sites (const/global/fn-body via `self.fail`; runtime-class via `self.failAt` at the caller, new helper); greens xfail 1176. Deleted obsolete 1174 + 1620, the GATE A→B test +