docs(ffi-linkage): checkpoint — Phase 3 complete (aggregate extern/export)
This commit is contained in:
@@ -5,12 +5,18 @@ 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 3.0** (xfail) — `examples/1348-ffi-objc-extern-class.sx` exercises the new
|
||||
postfix-`extern` aggregate spelling (`NSObject :: #objc_class("NSObject") extern { … }`,
|
||||
the new way to write `#foreign #objc_class("NSObject") { … }`). RED: parser rejects
|
||||
`extern` after the `#objc_class(...)` directive (`expected '{'`). Green-state snapshots
|
||||
hand-authored (exit 0, stdout `extern-class dispatch ok`). Suite: 639 corpus / 443 unit,
|
||||
**1 fail (1348, the intended xfail)**. Step 3.1 wires parse+lowering to green it.
|
||||
**Phase 3.1** (green) — **PHASE 3 COMPLETE.** Postfix `extern`/`export` on `#objc_class`/
|
||||
`#jni_class` aggregates fully works. `parseForeignClassDecl` now parses an optional
|
||||
`extern`/`export` modifier in the slot **between** the `("X")` directive args and the `{`
|
||||
body (`parser.zig:~1409`): `extern`→`is_foreign_eff = true` (reference an existing runtime
|
||||
class, == legacy `#foreign`); `export`→`is_foreign_eff = false` (define + register a new sx
|
||||
class, == bare `#objc_class` with no `#foreign`). The modifier maps straight onto the same
|
||||
`is_foreign` decision the prefix `#foreign` already fed the node, so **no `objc_class.zig`/
|
||||
lowering change was needed** — the new surface reuses the existing reference-vs-define path.
|
||||
Examples: **1348** (objc `extern` import, dispatches `NSObject.alloc().init()` → green via
|
||||
JIT), **1349** (objc `export` defined class, `SxBar.alloc()`/`bump`/`get` → `counter: 2`),
|
||||
**1426** (jni `extern` import, parse-only `parse-only ok`). Suite green (641 corpus / 443
|
||||
unit, 0 fail).
|
||||
|
||||
### Prior: Phase 2.2 (green) — **PHASE 2 COMPLETE.** `export` (define + expose) fully works:
|
||||
external linkage + C ABI + no sx ctx + force-lowered root + optional `"csym"` rename.
|
||||
@@ -47,13 +53,15 @@ gate). Examples: 1223 (extern bare fn), 1224 (extern fn rename), 1225 (extern ba
|
||||
global), 1226 (export bare fn, AOT), 1227 (export fn rename, AOT).
|
||||
|
||||
## Next step
|
||||
**Phase 3.1** (green) — wire the postfix `extern`/`export` aggregate path. `parseForeignClassDecl`
|
||||
already consumes the directive + `("X")` + body; add an optional postfix-modifier slot
|
||||
**after** the `)` and before the `{`: `extern`→reference (== `is_foreign`), `export`→
|
||||
define+register (== no `#foreign`). Map the postfix modifier onto the same downstream
|
||||
`is_foreign` decision that `tryParseForeignClassPrefix` feeds, so `objc_class.zig` lowering
|
||||
is unchanged. Green 1348; add a jni postfix test + an `export` (defined-class) test for the
|
||||
per-runtime coverage. Then Phase 4 (interplay/diagnostics/docs + the A→B gate: unit test that
|
||||
**Phase 4 — interplay, diagnostics, docs (+ the A→B gate).** (a) Diagnostics for combining
|
||||
the surfaces: reject `extern`+`export` together; decide/handle prefix `#foreign` **and**
|
||||
postfix `extern`/`export` on the same aggregate (today the postfix silently overrides
|
||||
`is_foreign` — Phase 4 should reject the redundant/contradictory combo, mirroring the fn
|
||||
path). (b) `extern`+`callconv` stacking/redundancy on fns. (c) docs — `specs.md`/`readme.md`
|
||||
document the three `extern`/`export` axes (fns, globals, aggregates); `#foreign` stays
|
||||
documented until the Part B cutover. (d) **GATE A→B (hard):** unit test asserting `#foreign`
|
||||
and `extern`/`export` lower to identical IR for a sample fn / global / **class** — lock
|
||||
before any Part B migration. Also pick up the two **Deferred** items below at this gate. (interplay/diagnostics/docs + the A→B gate: unit test that
|
||||
`#foreign` and `extern`/`export` lower to identical IR) before Part B migration.
|
||||
|
||||
**FUTURE MILESTONE — C→sx-by-name in JIT (`sx run`).** Investigated this session
|
||||
@@ -143,6 +151,17 @@ historical carve-out — keep `issues/*.md` provenance, gate the live tree only.
|
||||
- (3.0) Added `examples/1348-ffi-objc-extern-class.sx` (postfix `extern` on `#objc_class`,
|
||||
new spelling of `#foreign #objc_class`). RED (parser: `expected '{'` after the
|
||||
directive). Hand-authored green snapshots. `xfail` commit; 3.1 greens it.
|
||||
- (3.1a) Wired the postfix `extern`/`export` aggregate slot in `parseForeignClassDecl`
|
||||
(optional modifier between `("X")` and `{`; `var is_foreign_eff` overrides the passed
|
||||
`is_foreign`, threaded into the `foreign_class_decl` node). No lowering change — reuses
|
||||
the existing `is_foreign` reference-vs-define path. 1348 green. Suite green (639/443).
|
||||
`green` commit. **PHASE 3 COMPLETE.**
|
||||
- (3.1b) Behavior-lock: added `examples/1426-ffi-jni-extern-class.sx` (jni `extern`,
|
||||
parse-only) + `examples/1349-ffi-objc-export-class.sx` (objc `export` defined class,
|
||||
`counter: 2`). Both pass against the 3.1a parser change (locked in their own commit per
|
||||
the cadence rule). Suite green (641/443). `lock` commit. (Note: `-Dupdate-goldens`
|
||||
newline-normalizes empty stderr → reverted unrelated 1226/1227 churn, kept new stderr
|
||||
0-byte per repo convention; runner normalizes both.)
|
||||
|
||||
## Known issues
|
||||
- **Workflow hazard (1.2):** an editor format-on-save (or `zig fmt`) clobbered the
|
||||
|
||||
Reference in New Issue
Block a user