diff --git a/current/CHECKPOINT-EXTERN-EXPORT.md b/current/CHECKPOINT-EXTERN-EXPORT.md index 3043f99..162ba68 100644 --- a/current/CHECKPOINT-EXTERN-EXPORT.md +++ b/current/CHECKPOINT-EXTERN-EXPORT.md @@ -5,7 +5,26 @@ 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 7.4 — migrate straggler examples `#foreign`→`extern`** (`refactor` commit +**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 +prefix via caller 260) reject it with the migration message *"`#foreign` has been +removed; use the postfix `extern` (import) / `export` (define) linkage keyword +instead"*; added a span-aware `failAt` for the runtime-class case (the lookahead +consumes the token before the reject decision). New example **1176** +(`diagnostics-foreign-removed`) pins it. **Pre-cutover migrations** (all green, +behavior-preserving): the 7 identity `ffi-foreign-*` test DECLS (`2cce6a3`), the two +keyword-neutral diagnostic tests 1172 + 1228 with intentional snapshot regens +(`720556b`), and the 4 multi-file example companions Phase 7 missed (0729/a+b, 1617/c, +1623/mod — `d132aab`). **Deleted** obsolete tests 1174 (`#foreign`+postfix conflict, now +unreachable) + 1620 (`#foreign nosuchunit`, superseded by extern twin 1231), the GATE +A→B unit test + `lowerSrcToIr` helper (nothing left to compare), and converted the +in-source `parse void function with foreign body` parser test to postfix `extern`. +specs.md + readme.md document `extern`/`export` as the sole C-linkage surface. Suite +green (646 corpus / 444 unit, 0 failed). + +### Prior: Phase 7.4 — migrate straggler examples `#foreign`→`extern` (`refactor` commit `1a8991a`). **PHASE 7 MIGRATABLE WORK COMPLETE (7.1–7.4 done).** Migrated 16 fn/global examples across categories (0415/0602/0603/1024/1025/1605/1607-1609/1611/1616/1619/ 1622/1628/1635/1636). Marker'd ones corpus-validated; the 3 unmarked uikit importers @@ -238,34 +257,44 @@ 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 8 (cutover: hard-reject the `#foreign` keyword).** Phases 5–7 COMPLETE: -the entire `library/` tree + all incidentally-`#foreign` examples are on `extern`/`export`; -only the 24-file keep-list (see Last completed step) still spells `#foreign`, by design. +**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. -- **Phase 8.0** (`xfail`): add `examples/11xx-diagnostics-foreign-removed.sx` expecting a - clean "`#foreign` removed; use `extern`/`export`" diagnostic — RED while `#foreign` is - still accepted. -- **Phase 8.1** (`green`): parser hard-rejects `#foreign` (mirror the variadic `name: ..T` - cutover). **This is the breaking moment for the 24-file keep-list** — every kept file - must be dealt with IN this phase (or a 7.5 pre-step right before it): - - Identity feature tests (1205/1207/1218/1219/1306/1318) → migrate their decls to - `extern`/`export` (the `.ir`/output stays identical per the A→B gate; may also - `git mv` to drop the now-stale `ffi-foreign-*` name + reseed `expected/`). Dedup vs the - existing extern twins (1224/1225/1229/1230/1231) — delete if fully redundant. - - `foreign`-asserting diagnostics (1172/1174/1219/1228/1620) → these tested `#foreign` - behavior; convert to assert the NEW rejection diagnostic, or retarget to `extern` - equivalents, regenerating snapshots intentionally (this is the one place regen is - correct — it's a deliberate behavior change, not a silent diff). - - Comment-only / provenance prose (0716/0729/1216/1223-1231/1332/1348/1349/1426 + - issues/0030) → migrate the comment text to `extern` for live-tree files (Phase 9.3 - needs zero `foreign` in `examples/`); `issues/*.md` prose governed by Decision 6. - - `specs.md` drops `#foreign`, documents `extern`/`export` only. -- Then **Phase 9** (total `foreign` purge — internal identifiers + docs; needs Decision 5 - [done] + Decision 6). -- **Decision 6 (STILL OPEN)** governs the `issues/*.md` + comment-prose carve-out — the - recommended default (keep provenance, gate only the live tree) has been applied through - Phase 7; **ratify it with the user before Phase 8.1/9** since it decides how much of the - keep-list + issues prose must change. +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. - **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 @@ -374,9 +403,11 @@ general `isNameVisible` gate already denied it; only the diagnostic wording dive Part A ratified (bare / postfix / `⇒ callconv(.c)` / lib-separate). Part B: - **Decision 5 RATIFIED** (user, 2026-06-14): runtime-class rename target = `Runtime*Class*` (object-model axis, not linkage). Drives the Phase 9.2 identifier renames. -- **Decision 6 STILL OPEN**: historical carve-out — keep `issues/*.md` (+ design-doc prose) - as provenance & gate only the live tree (recommended) vs purge everything. The user did - NOT confirm this at the Part A milestone; confirm before Phase 9. +- **Decision 6 RATIFIED** (user, 2026-06-15): **PURGE EVERYTHING** — the Phase 9.4 gate is + absolute, including `issues/*.md` writeups (NOT the recommended keep-provenance default). + Every `#foreign`/`foreign` reference in the gated tree (`src/ library/ examples/ issues/ + specs.md readme.md CLAUDE.md`) is rewritten to `extern`/`export`; provenance lives in git + history + `(Regression issue NNNN)` notes, not the keyword spelling. - **Decision 7 RATIFIED** (user, 2026-06-15): **accept the churn** — `#foreign`-spelled decls produce `extern`-worded diagnostics; example 1620 regenerated (only snapshot moved). Aligns with Part B's extern-only end state; the interim oddity is cosmetic and removed at @@ -392,6 +423,21 @@ Part A ratified (bare / postfix / `⇒ callconv(.c)` / lib-separate). Part B: deleted at cutover). Affects only diagnostic wording — IR/behavior identical either way. ## Log +- (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 + + `lowerSrcToIr` helper; converted the in-source parser test to postfix `extern`; + `extern_export` → `const`. specs.md + readme.md drop `#foreign`. Suite green + (646/444). `feat!` `3811311`. +- (8.0 xfail) Added `1176-diagnostics-foreign-removed.sx` pinning the desired rejection. + RED (still accepted). `test`/xfail `8180faf`. +- (8 pre-cutover) Migrated the 4 multi-file example companions Phase 7 missed + (0729/a+b, 1617/c, 1623/mod). `refactor` `d132aab`. +- (8 pre-cutover) Migrated keyword-neutral diagnostics 1172 (decl→extern, message stays + internal "foreign symbol") + 1228 (→ two foreign-free extern symbols c_abs_one/_two), + intentional snapshot regens reviewed. `refactor` `720556b`. +- (8 pre-cutover) Migrated the 7 identity `ffi-foreign-*` test decls to extern/export + (decls only; comments left for Phase 9.3). `refactor` `2cce6a3`. - (7.4 stragglers) **PHASE 7 MIGRATABLE WORK COMPLETE.** Migrated 16 fn/global examples (0415/0602/0603/1024/1025/1605/1607-1609/1611/1616/1619/1622/1628/1635/1636) `#foreign`→ `extern`; 1607/1608/1616 (unmarked) verified by `sx ir` probes. 24-file keep-list remains