refactor(ffi-linkage): Phase 9.2b — rename runtime-class fns + state → runtime_* / is_reference

The runtime-class object-model identifiers (Decision 5): parse/lower/find/resolve/
register/stamp fns Foreign→Runtime (parseRuntimeClassDecl, lowerRuntimeMethodCall,
findRuntimeMethodInChain, resolveRuntimeMethodReturnType, registerRuntimeClassDecl,
runtimeClassStructType, runtimeKindForOffset, …); state foreign_class_map→
runtime_class_map, current_foreign_class/_method→current_runtime_*, the
foreign_class_decl union variant→runtime_class_decl, foreign_method/static/instance/
class→runtime_*; and the reference-vs-define flag is_foreign→is_reference (+
is_foreign_eff→is_reference_eff) now that it only lives on RuntimeClassDecl.
Snapshot-neutral; suite green (646/444).

Remaining 9.2: the foreign_path family (coupled .sx hooks: jni_main_foreign_path_at
spans build.sx/bundle.sx/compiler_hooks.zig/specs.md) + the extern-ref validators
(checkForeignRefs etc. → Extern, linkage not runtime) + bare 'foreign' comments.
This commit is contained in:
agra
2026-06-15 09:01:04 +03:00
parent 3354446412
commit 5c8af6eb73
22 changed files with 205 additions and 205 deletions

View File

@@ -258,15 +258,15 @@ pub const Parser = struct {
// `#foreign` flips that to "reference an existing class on the foreign side."
// `#jni_main` flags the class as the launchable entry (Android Activity).
const prefix_loc = self.current.loc;
if (self.tryParseForeignClassPrefix()) |prefix| {
if (self.tryParseRuntimeClassPrefix()) |prefix| {
// Phase 8 cutover: the prefix `#foreign` on a runtime-class directive is
// removed — reference an existing class via the postfix `extern` modifier
// (`X :: #objc_class("…") extern { … }`) instead. `prefix_loc` pins the
// diagnostic to the `#foreign` token (already consumed by the lookahead).
if (prefix.is_foreign) {
if (prefix.is_reference) {
return self.failAt(prefix_loc, "`#foreign` has been removed; use the postfix `extern` (import) / `export` (define) linkage keyword instead");
}
return self.parseForeignClassDecl(name, start_pos, prefix.runtime, prefix.is_foreign, prefix.is_main, name_is_raw);
return self.parseRuntimeClassDecl(name, start_pos, prefix.runtime, prefix.is_reference, prefix.is_main, name_is_raw);
}
// C-style union declaration
@@ -1280,7 +1280,7 @@ pub const Parser = struct {
} });
}
fn foreignRuntimeForCurrent(self: *Parser) ?ast.RuntimeKind {
fn runtimeKindForCurrent(self: *Parser) ?ast.RuntimeKind {
return switch (self.current.tag) {
.hash_jni_class => .jni_class,
.hash_jni_interface => .jni_interface,
@@ -1295,7 +1295,7 @@ pub const Parser = struct {
const RuntimeClassPrefix = struct {
runtime: ast.RuntimeKind,
is_foreign: bool,
is_reference: bool,
is_main: bool,
};
@@ -1305,16 +1305,16 @@ pub const Parser = struct {
/// directive (possibly after modifiers). Consumes the modifier tokens
/// only when a runtime directive follows; otherwise leaves the parser
/// state untouched.
fn tryParseForeignClassPrefix(self: *Parser) ?RuntimeClassPrefix {
fn tryParseRuntimeClassPrefix(self: *Parser) ?RuntimeClassPrefix {
// Peek ahead through modifier tokens to confirm a directive follows.
var lookahead_idx: usize = 0;
var is_foreign = false;
var is_reference = false;
var is_main = false;
while (true) {
const tag = self.peekTag(lookahead_idx);
switch (tag) {
.hash_foreign => {
is_foreign = true;
is_reference = true;
lookahead_idx += 1;
},
.hash_jni_main => {
@@ -1324,11 +1324,11 @@ pub const Parser = struct {
else => break,
}
}
const runtime = self.foreignRuntimeForOffset(lookahead_idx) orelse return null;
const runtime = self.runtimeKindForOffset(lookahead_idx) orelse return null;
// Commit: consume modifier tokens.
var i: usize = 0;
while (i < lookahead_idx) : (i += 1) self.advance();
return .{ .runtime = runtime, .is_foreign = is_foreign, .is_main = is_main };
return .{ .runtime = runtime, .is_reference = is_reference, .is_main = is_main };
}
fn peekTag(self: *Parser, offset: usize) Tag {
@@ -1349,7 +1349,7 @@ pub const Parser = struct {
return self.peekTag(1) == .identifier and self.peekTag(2) == .r_paren;
}
fn foreignRuntimeForOffset(self: *Parser, offset: usize) ?ast.RuntimeKind {
fn runtimeKindForOffset(self: *Parser, offset: usize) ?ast.RuntimeKind {
const tag = self.peekTag(offset);
return switch (tag) {
.hash_jni_class => .jni_class,
@@ -1363,7 +1363,7 @@ pub const Parser = struct {
};
}
fn parseForeignClassDecl(self: *Parser, name: []const u8, start_pos: u32, runtime: ast.RuntimeKind, is_foreign: bool, is_main: bool, name_is_raw: bool) anyerror!*Node {
fn parseRuntimeClassDecl(self: *Parser, name: []const u8, start_pos: u32, runtime: ast.RuntimeKind, is_reference: bool, is_main: bool, name_is_raw: bool) anyerror!*Node {
self.advance(); // skip directive token
try self.expect(.l_paren);
@@ -1380,20 +1380,20 @@ pub const Parser = struct {
// `#foreign` modifier (mirrors `struct #compiler` postfix placement).
// `… extern { … }` ⇒ reference an existing runtime class (== `#foreign`).
// `… export { … }` ⇒ define + register a new sx class (== no `#foreign`).
// Maps straight onto the existing `is_foreign` decision so lowering is
// Maps straight onto the existing `is_reference` decision so lowering is
// unchanged. The legacy prefix `#foreign` form still works via the
// `is_foreign` argument; interplay/diagnostics for combining them is Phase 4.
var is_foreign_eff = is_foreign;
// `is_reference` argument; interplay/diagnostics for combining them is Phase 4.
var is_reference_eff = is_reference;
if (self.current.tag == .kw_extern or self.current.tag == .kw_export) {
// Prefix `#foreign` and the postfix `extern`/`export` keyword are two
// spellings of the same linkage axis — combining them is contradictory
// (`#foreign`=import vs `export`=define) or redundant (`#foreign … extern`).
// Reject at the postfix keyword rather than let it silently override.
if (is_foreign) {
if (is_reference) {
const kw = if (self.current.tag == .kw_export) "export" else "extern";
return self.failFmt("conflicting linkage: prefix '#foreign' cannot be combined with postfix '{s}'; use either '#foreign' or postfix 'extern'/'export', not both", .{kw});
}
is_foreign_eff = self.current.tag == .kw_extern;
is_reference_eff = self.current.tag == .kw_extern;
self.advance();
}
@@ -1619,12 +1619,12 @@ pub const Parser = struct {
}
try self.expect(.r_brace);
return try self.createNode(start_pos, .{ .foreign_class_decl = .{
return try self.createNode(start_pos, .{ .runtime_class_decl = .{
.name = name,
.foreign_path = foreign_path,
.runtime = runtime,
.members = try members.toOwnedSlice(self.allocator),
.is_foreign = is_foreign_eff,
.is_reference = is_reference_eff,
.is_main = is_main,
.is_raw = name_is_raw,
} });