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:
@@ -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,
|
||||
} });
|
||||
|
||||
Reference in New Issue
Block a user