From 9719432e79542b23224dc3d0d4414a83639f8fc9 Mon Sep 17 00:00:00 2001 From: agra Date: Mon, 15 Jun 2026 11:03:29 +0300 Subject: [PATCH] =?UTF-8?q?refactor(ffi-linkage):=20Phase=209.3=20?= =?UTF-8?q?=E2=80=94=20purge=20remaining=20'foreign'=20from=20library/docs?= =?UTF-8?q?/example=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Capital-Foreign + stale-identifier comment refs: library (Foreign Java types→Runtime, foreign-class→runtime-class, foreign_class_map→runtime_class_map); docs/debugger (foreign call→extern call); docs/fork-c ledger (foreign_class_map, protocol/foreign→ runtime-class); docs/inline-asm-design Deviation-6 obsolete #foreign-vs-extern design RESOLVED to the landed extern/export reality; example comments (parseForeignClassDecl→ parseRuntimeClassDecl, checkForeignRefs→checkExternRefs, Foreign decls→Extern). Docs/ comments only — no build impact. --- docs/debugger.md | 4 +-- docs/fork-c/S0.3-reuse-delete-ledger.md | 6 ++-- docs/inline-asm-design.md | 28 +++++++++---------- examples/0415-protocols-protocols.sx | 4 +-- examples/1219-ffi-foreign.sx | 2 +- .../1220-ffi-c-import-reserved-name-params.sx | 2 +- examples/1221-ffi-cstring-returns.sx | 2 +- examples/1231-ffi-extern-undeclared-lib.sx | 2 +- ...-ffi-objc-expression-bodied-objc-method.sx | 2 +- examples/1318-ffi-objc-property-foreign.sx | 2 +- examples/1320-ffi-objc-extends-chain.sx | 2 +- library/modules/ffi/objc.sx | 4 +-- library/modules/platform/android.sx | 4 +-- library/modules/platform/android_jni.sx | 2 +- 14 files changed, 32 insertions(+), 34 deletions(-) diff --git a/docs/debugger.md b/docs/debugger.md index 11766e9..d2137b6 100644 --- a/docs/debugger.md +++ b/docs/debugger.md @@ -116,7 +116,7 @@ context: `sx_trace_push` call emitted through the normal call lowering. - **`interp`:** yields the packed `(func_id, span.start)` from its own execution context as the op's value. The separate `sx_trace_push` call - op consuming it is executed by the interp as a foreign call (via + op consuming it is executed by the interp as an extern call (via `host_ffi`/dlsym, the same path as any extern), storing the packed value in the buffer; the comptime `.trace_resolve` resolver later recovers `file:line:col` from it. @@ -257,7 +257,7 @@ both the trace path and the DWARF path. Items marked ✅ exist today; | [`src/ir/emit_llvm.zig`](../src/ir/emit_llvm.zig) | IR→LLVM orchestrator. Owns `LLVMEmitter` + the source map (`setDebugContext`); dispatches the `.trace_frame` op and the DWARF passes to the helpers below | | [`src/backend/llvm/reflection.zig`](../src/backend/llvm/reflection.zig) | `Reflection`: builds the interned `Frame` table + the tag-name / type-name tables; yields the `.trace_frame` op's value (the `Frame` global's address) — the `sx_trace_push` call itself is emitted by `lower.zig` | | [`src/backend/llvm/debug.zig`](../src/backend/llvm/debug.zig) | `DebugInfo`: builds all DWARF metadata (compile unit, per-function subprograms, per-instruction `DILocation`) | -| [`src/ir/interp.zig`](../src/ir/interp.zig) | Comptime IR interpreter. The `.trace_frame` op yields a packed `(func_id, span.start)`; the separate `sx_trace_push` call op runs as a foreign call (dlsym); `.trace_resolve` recovers comptime frames | +| [`src/ir/interp.zig`](../src/ir/interp.zig) | Comptime IR interpreter. The `.trace_frame` op yields a packed `(func_id, span.start)`; the separate `sx_trace_push` call op runs as an extern call (dlsym); `.trace_resolve` recovers comptime frames | | [`src/errors.zig`](../src/errors.zig) | `SourceLoc.compute(source, offset) → {line, col}`; the `import_sources` map type | | [`src/ir/inst.zig`](../src/ir/inst.zig) | `Inst.span`, `Function.source_file`, the `Op` union (home of the `.trace_frame` op) | | [`library/vendors/sx_trace_runtime/sx_trace.c`](../library/vendors/sx_trace_runtime/sx_trace.c) | the thread-local ring buffer + `sx_trace_report_unhandled` | diff --git a/docs/fork-c/S0.3-reuse-delete-ledger.md b/docs/fork-c/S0.3-reuse-delete-ledger.md index 1294bc3..3a3664b 100644 --- a/docs/fork-c/S0.3-reuse-delete-ledger.md +++ b/docs/fork-c/S0.3-reuse-delete-ledger.md @@ -22,7 +22,7 @@ is never merged (see `S0.2-…`). | **E-series selection rules** — own-wins / not-visible / ambiguity / direct-flat (the E1–E6a behaviors) | **resolver behavior + regression tests** (the baseline-green corpus is the mirror oracle) | S2 behavior; regressions locked S0 | | **CP rule** — body-author == layout-author | **keyed by `InstantiationId{template_decl, resolved_args}`** in the fact store | S4 | | **E6BR routed-signature cases** (the E6BR-1…4 behavioral cells) | **resolver-signature regressions** — the resolver walks every signature reference position; cases live in the resolver-target corpus, flip at S3.9 | S3.9 | -| **FFI `foreign_class_map` consumers + FFI corpus (96 entry trees / 95 active markers)** | parallel `DeclId`s land at S1 (map still the consumer); foreign classes keyed by `DeclId` at S4; runtime names stay **payload strings on facts** | S1 → S4 | +| **FFI `runtime_class_map` consumers + FFI corpus (96 entry trees / 95 active markers)** | parallel `DeclId`s land at S1 (map still the consumer); runtime classes keyed by `DeclId` at S4; runtime names stay **payload strings on facts** | S1 → S4 | ## B. DELETED / TRANSITIONAL — removed in S3/S6 @@ -41,7 +41,7 @@ is never merged (see `S0.2-…`). ## C. Dropped / absorbed / superseded plan items -- **E6c / E6d / E6e** (protocol / foreign / type-fn per-kind identity): **DROPPED as +- **E6c / E6d / E6e** (protocol / runtime-class / type-fn per-kind identity): **DROPPED as steps.** They become resolver behavior + regression tests — a whole-AST resolver walks every reference position (annotation, `size_of`, dispatch head, `Self`, vtable), closing the protocol surface the per-kind patch structurally could not @@ -50,7 +50,7 @@ is never merged (see `S0.2-…`). (`namespace_edges` → `ResolvedRef.namespace` / member). - **H** (constructor heads): **ABSORBED** into S3 `materializeType` over resolved generic/protocol/type-fn heads. -- **I** (protocol + foreign selection, loud-on-≥2): **ABSORBED** into S2 selection + S4 +- **I** (protocol + runtime-class selection, loud-on-≥2): **ABSORBED** into S2 selection + S4 `DeclId` facts. - **K** (delete dead readers): **SUPERSEDED** by the S4 `DeclId`-keyed fact store + the S6 deletions — "just delete the maps" is upgraded to "replace with `DeclId` facts." diff --git a/docs/inline-asm-design.md b/docs/inline-asm-design.md index 321fd2c..8c3e7f1 100644 --- a/docs/inline-asm-design.md +++ b/docs/inline-asm-design.md @@ -457,8 +457,7 @@ ATT, **C-calling-convention**, raw-named, link-time-resolved declaration — the same thing Zig's `extern fn` produces (also C-callconv). The reverse direction (asm calling *back into* an sx function) is handled by `export`, the define-and-expose - dual of `extern`. (The legacy prefix `#foreign` spelling that originally provided - the import path has since been replaced by the postfix `extern`/`export` keywords.) + dual of `extern`. Everything *semantic* — comptime-known template, register/memory constraints verbatim to LLVM, clobber meaning, "no-output ⇒ must be volatile," AT&T default, @@ -682,7 +681,7 @@ LLVM — `@19/include/llvm-c/Core.h:971`). No operands, no rewrite, no volatile; multiple blocks concatenate in source order (as Zig does). **Calling into an asm-defined symbol needs no new machinery** — declare it with a -lib-less `#foreign` (Deviation 6, §II.2): `my_func :: (sig) -> R #foreign;` emits +lib-less `extern` (Deviation 6, §II.2): `my_func :: (sig) -> R extern;` emits an external-linkage, raw-named, C-ABI extern that the linker resolves against the `.global` the asm block defines. @@ -721,7 +720,7 @@ No change to `src/codegen.zig` is needed (the IR/LLVM path owns this). indirect-memory (`"=*m"`) constraints, `%=` unique-id, output-to-const rejection. * **Phase 3.** Global/module asm decl (`LLVMAppendModuleInlineAsm`) + the comptime-call guard, plus Intel-dialect opt-in. Small: the extern-call path - already exists (lib-less `#foreign`). + already exists (lib-less `extern`). * **Phase 4 (optional).** Upgrade `clobbers(.name)` from dot-name sugar to a compile-time-checked per-architecture `Clobber` enum (typo-checking; same syntax). * **Phase 5 (optional).** Naked functions (`callconv`-equivalent) for full @@ -760,18 +759,17 @@ Largely settled through design review; what remains: source-compat risk)* vs globally reserved *(simpler lexer)*. 3. **Brace separator:** comma *(recommended — trailing-comma-friendly, literal-style)* vs `;` *(matches sx statement blocks)*. -4. **Asm-symbol extern spelling (Deviation 6):** reuse lib-less `#foreign` for v1 - *(works, zero new surface — but it is a C-FFI **import** binding: import-only, - C-ABI, spelled "foreign")* vs a dedicated `#extern`/linkname *(cleaner spelling, - and the only path that could also **export** an sx symbol so asm can call back - in — which `#foreign` cannot)*. **Recommend `#foreign` for v1**; revisit - `#extern` if/when asm-calls-into-sx or non-C-ABI symbols are needed. +4. **Asm-symbol extern spelling (Deviation 6): RESOLVED** — use the lib-less `extern` + keyword to call *into* an asm symbol (import), and `export` for the reverse + direction (an sx function asm can call *back into*). The dedicated linkage + keywords landed (FFI-linkage stream), so no new surface is needed and both + directions are covered. *Decided:* brace block `{ … }` (Dev 1) · `->`/`=` markers, `:` sections dropped, `<-` rejected (Dev 2) · `clobbers(.…)` enum-literal list, dot-name sugar now → checked enum later (Dev 3) · multiple value-outputs return a tuple (Dev 5). For -global asm (Dev 6) the call-*into*-asm direction reuses lib-less `#foreign` -(`specs.md:1209` updated); the extern *spelling* is open decision 4 above. +global asm (Dev 6) the call-*into*-asm direction reuses lib-less `extern` (Decision +4, resolved). ## II.11 Risks @@ -816,8 +814,8 @@ void LLVMAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, size_t Len); / (syntax) · `doc/langref.html.in:4217-4300` (spec). **sx (target, `~/projects/sx`):** `src/token.zig` · `src/lexer.zig:402` (#string) · -`src/ast.zig:13,85,721` · `src/parser.zig` (`parsePrimary`), `:319` (optional -`#foreign` library) · `src/ir/expr_typer.zig` · `src/ir/inst.zig:80,219,260` · +`src/ast.zig:13` · `src/parser.zig` (`parsePrimary`), the optional `extern` +library tail · `src/ir/expr_typer.zig` · `src/ir/inst.zig:80,219,260` · `src/ir/lower/expr.zig` · `src/ir/module.zig:300` (`declareExtern`) · `src/ir/emit_llvm.zig:167` (msgSend cache), `:1244` (extern⇒C-ABI), `:1279` (raw symbol name) · `src/ir/interp.zig` (`bailDetail`) · `src/llvm_api.zig:1-17` · @@ -995,5 +993,5 @@ asm { retq ATT, }; -my_add :: (a: i32, b: i32) -> i32 #foreign; // lib-less extern = Zig's `extern fn` +my_add :: (a: i32, b: i32) -> i32 extern; // lib-less extern = Zig's `extern fn` ``` diff --git a/examples/0415-protocols-protocols.sx b/examples/0415-protocols-protocols.sx index ffbf9be..8a0bb98 100644 --- a/examples/0415-protocols-protocols.sx +++ b/examples/0415-protocols-protocols.sx @@ -193,9 +193,9 @@ sm_first :: (a: i32, b: i32) -> (i32, !) { return v; } -// --- Foreign function binding --- +// --- Extern function binding --- -// --- Foreign function binding --- +// --- Extern function binding --- libc :: #library "c"; c_abs :: (n: i32) -> i32 extern libc "abs"; diff --git a/examples/1219-ffi-foreign.sx b/examples/1219-ffi-foreign.sx index 6d2d948..ff5dc3d 100644 --- a/examples/1219-ffi-foreign.sx +++ b/examples/1219-ffi-foreign.sx @@ -14,7 +14,7 @@ c_abs :: (n: i32) -> i32 extern libc "abs"; main :: () { // ======================================================== - // 15. FOREIGN FUNCTION BINDING + // 15. EXTERN FUNCTION BINDING // ======================================================== print("=== 15. Extern ===\n"); diff --git a/examples/1220-ffi-c-import-reserved-name-params.sx b/examples/1220-ffi-c-import-reserved-name-params.sx index 3afffac..422432e 100644 --- a/examples/1220-ffi-c-import-reserved-name-params.sx +++ b/examples/1220-ffi-c-import-reserved-name-params.sx @@ -1,5 +1,5 @@ // `#import c` extern-name exemption: C names that collide with sx's reserved -// type spellings import unedited. Foreign decls are treated as RAW — their names +// type spellings import unedited. Extern decls are treated as RAW — their names // are never type-classified nor reserved-checked — so the generated `extern` // bindings import and call without hand-edits (no backticks needed). This covers // parameter names (`i1`/`i2`), a function whose own NAME is a reserved spelling diff --git a/examples/1221-ffi-cstring-returns.sx b/examples/1221-ffi-cstring-returns.sx index 635ba13..8bd6d98 100644 --- a/examples/1221-ffi-cstring-returns.sx +++ b/examples/1221-ffi-cstring-returns.sx @@ -1,4 +1,4 @@ -// Foreign `-> [:0]u8` / `-> ?[:0]u8` returns: C hands back ONE `char *`; +// Extern `-> [:0]u8` / `-> ?[:0]u8` returns: C hands back ONE `char *`; // the fat sx string is synthesized at the call boundary ({ptr, strlen}; // NULL maps to the optional's null / an empty string) — issue 0128. // Pre-fix, the call read the pointer register pair as {ptr, len} and the diff --git a/examples/1231-ffi-extern-undeclared-lib.sx b/examples/1231-ffi-extern-undeclared-lib.sx index fd247d6..7b619ee 100644 --- a/examples/1231-ffi-extern-undeclared-lib.sx +++ b/examples/1231-ffi-extern-undeclared-lib.sx @@ -4,7 +4,7 @@ // diagnostic — the bogus library reference is caught BEFORE the symbol // would silently resolve through whatever image happens to carry it. // -// Regression (FFI-linkage Part B): `checkForeignRefs` validated only a +// Regression (FFI-linkage Part B): `checkExternRefs` validated only a // `extern` (extern-import shape) library_ref and skipped the `extern` keyword's // `extern_lib`, so a bogus `extern` lib reference compiled silently (the // symbol resolved via the default image and ran). Prerequisite for diff --git a/examples/1307-ffi-objc-expression-bodied-objc-method.sx b/examples/1307-ffi-objc-expression-bodied-objc-method.sx index 6fc262f..f175697 100644 --- a/examples/1307-ffi-objc-expression-bodied-objc-method.sx +++ b/examples/1307-ffi-objc-expression-bodied-objc-method.sx @@ -1,7 +1,7 @@ // M1.0 (xfail) — '=>' expression-body form inside '#objc_class' // member methods. // -// Today: parseForeignClassDecl ([src/parser.zig:1262]) accepts ';' +// Today: parseRuntimeClassDecl ([src/parser.zig:1262]) accepts ';' // (declaration) or '{ ... }' (block body) but not '=>'. Trying // '=>' surfaces 'expected ;' at the arrow. // diff --git a/examples/1318-ffi-objc-property-foreign.sx b/examples/1318-ffi-objc-property-foreign.sx index 25869a7..529eea0 100644 --- a/examples/1318-ffi-objc-property-foreign.sx +++ b/examples/1318-ffi-objc-property-foreign.sx @@ -30,7 +30,7 @@ probe_set_tag :: (self: *void, _cmd: *void, v: i32) callconv(.c) { g_probe_tag = v; } -// Foreign declaration with #property on `tag`. +// Extern declaration with #property on `tag`. SxPropProbe :: #objc_class("SxPropProbe") extern { alloc :: () -> *SxPropProbe; init :: (self: *SxPropProbe) -> *SxPropProbe; diff --git a/examples/1320-ffi-objc-extends-chain.sx b/examples/1320-ffi-objc-extends-chain.sx index 20bcd4d..5cda88b 100644 --- a/examples/1320-ffi-objc-extends-chain.sx +++ b/examples/1320-ffi-objc-extends-chain.sx @@ -1,4 +1,4 @@ -// M2.3 — `#extends ForeignClass` method-resolution chaining. +// M2.3 — `#extends a runtime class` method-resolution chaining. // // When `obj.method()` is called on a runtime-class pointer and // `method` isn't declared directly on the receiver's class, the diff --git a/library/modules/ffi/objc.sx b/library/modules/ffi/objc.sx index a141d51..54fcdbb 100644 --- a/library/modules/ffi/objc.sx +++ b/library/modules/ffi/objc.sx @@ -10,7 +10,7 @@ // ─── Obj-C primitive type aliases ─────────────────────────────────────── // Named stand-ins for the three opaque Obj-C runtime types. They all // resolve to `*void` at the LLVM layer (no runtime cost) but improve -// readability in foreign-class declarations and call sites. +// readability in runtime-class declarations and call sites. // // id — any Obj-C instance pointer // Class — a class object pointer @@ -80,7 +80,7 @@ NSLog :: (fmt: *NSString) extern; // `defer view.release();` and `view.retain()` directly instead of going // through `objc_msgSend` casts. M2.3's `#extends`-aware dispatch finds // these methods automatically once a class roots its `#extends` chain at -// NSObject (foreign classes in uikit.sx etc. add `#extends NSObject;` to +// NSObject (runtime classes in uikit.sx etc. add `#extends NSObject;` to // inherit the surface). // // `release` is NOT a reserved keyword in sx — modern clang ARC bans diff --git a/library/modules/platform/android.sx b/library/modules/platform/android.sx index c6e1273..3963e34 100644 --- a/library/modules/platform/android.sx +++ b/library/modules/platform/android.sx @@ -36,7 +36,7 @@ #import "modules/platform/types.sx"; #import "modules/platform/api.sx"; -// ── Foreign Java types ────────────────────────────────────────────────── +// ── Runtime Java types ────────────────────────────────────────────────── Bundle :: #jni_class("android/os/Bundle") extern { } JContext :: #jni_class("android/content/Context") extern { @@ -66,7 +66,7 @@ ActivityClass :: #jni_class("android/app/Activity") extern { setContentView :: (self: *Self, v: *JView); } -// ── Foreign C/NDK decls ───────────────────────────────────────────────── +// ── Extern C/NDK decls ───────────────────────────────────────────────── // C side of file_utils — installs the AAssetManager so `read_file_bytes` // can route through `AAssetManager_open` when running on Android. diff --git a/library/modules/platform/android_jni.sx b/library/modules/platform/android_jni.sx index 2f4ea5b..acae0f4 100644 --- a/library/modules/platform/android_jni.sx +++ b/library/modules/platform/android_jni.sx @@ -7,7 +7,7 @@ // `View` in particular collides with `modules/ui/view.sx`'s protocol. // Inside the namespace these are referenced as `Jni.Activity`, // `Jni.Window`, etc. The compiler registers the decls both qualified -// and bare in `foreign_class_map`, so cross-class refs in method +// and bare in `runtime_class_map`, so cross-class refs in method // signatures (`getWindow :: (self: *Self) -> *Window`) still resolve // against the bare name within the namespace.