refactor(ffi-linkage): Phase 9.3-src — purge 'foreign' from src/ comments + a user-facing diagnostic

Reword every 'foreign' comment to the extern/runtime-class vocabulary matching the
renamed identifiers (foreign call→extern call, foreign class→runtime class, foreign
path→runtime path, the #foreign-literal comment mentions → extern, etc.). Also fixes
two USER-FACING issues: the 'expected … #foreign … after type annotation' parse error
no longer advertises the removed keyword, and the Android 'no #jni_main' help
diagnostic now shows '#jni_class(…) extern' instead of the rejected '#foreign
#jni_class'. Removed the now-dead prefix-#foreign-vs-postfix conflict branch in
parseRuntimeClassDecl (the caller rejects #foreign before it runs).

src/ now contains 'foreign' ONLY in the hash_foreign token machinery + its 4
rejection messages — the deprecation mechanism (kept per the 9.0 recommendation; the
message MUST name #foreign to guide migration). Snapshot-neutral; suite green
(646 corpus / 444 unit, 0 failed).
This commit is contained in:
agra
2026-06-15 09:35:00 +03:00
parent e99383fcb4
commit dc51c4b5bf
35 changed files with 172 additions and 180 deletions

View File

@@ -174,7 +174,7 @@ pub const Interpreter = struct {
max_call_depth: u32 = 256,
/// Active sx call-frame chain (oldest→newest), maintained across `call` for
/// `trace.print_interpreter_frames()` (ERR E4.1). Only sx-bodied frames are
/// tracked — foreign calls return before the frame is pushed.
/// tracked — extern calls return before the frame is pushed.
call_chain: std.ArrayList(FuncId) = .empty,
/// File → source text (the diagnostics' import_sources). Set by the host
@@ -218,7 +218,7 @@ pub const Interpreter = struct {
return error.CannotEvalComptime;
}
/// Like `bailDetail` but returns a `TypeError` — for foreign-arg
/// Like `bailDetail` but returns a `TypeError` — for extern-arg
/// marshalling sites that previously erased the reason.
fn typeErrorDetail(comptime msg: []const u8) InterpError {
if (last_bail_detail == null) last_bail_detail = msg;
@@ -258,7 +258,7 @@ pub const Interpreter = struct {
/// Write `val` to the raw host address `addr` using exactly the
/// number of bytes declared by `val_ty`. Used when the
/// protocol-dispatch chain bottoms out at a foreign-libc-malloc
/// protocol-dispatch chain bottoms out at a extern-libc-malloc
/// pointer and sx code stores through it. Comptime safety is the
/// caller's responsibility — wild writes will fault.
fn storeAtRawPtr(self: *Interpreter, addr: i64, val: Value, val_ty: @import("types.zig").TypeId) InterpError!void {
@@ -414,7 +414,7 @@ pub const Interpreter = struct {
.heap_ptr => |hp| blk: {
// `heapSlice` returns the slice already advanced by `hp.offset`,
// so its `.ptr` IS the offset address. Adding `hp.offset` again
// double-counts and lands the foreign call past the buffer end.
// double-counts and lands the extern call past the buffer end.
_ = self.heapSlice(hp) orelse return error.TypeError;
break :blk @intFromPtr(self.heap.items[hp.id].ptr) + hp.offset;
},
@@ -451,7 +451,7 @@ pub const Interpreter = struct {
},
// Raw host pointer (from libc_malloc-backed
// cstring). Read bytes from real memory and copy
// into a null-terminated buffer the foreign call
// into a null-terminated buffer the extern call
// can consume.
.int => |addr| {
const src: [*]const u8 = @ptrFromInt(@as(usize, @bitCast(addr)));
@@ -461,12 +461,12 @@ pub const Interpreter = struct {
tmp.append(self.alloc, buf) catch return error.TypeError;
break :blk @intFromPtr(buf.ptr);
},
else => return typeErrorDetail("comptime foreign call: unsupported aggregate data-field kind (expected heap_ptr/string/int)"),
else => return typeErrorDetail("comptime extern call: unsupported aggregate data-field kind (expected heap_ptr/string/int)"),
}
}
return typeErrorDetail("comptime foreign call: aggregate arg must be a {ptr, len} fat-pointer pair");
return typeErrorDetail("comptime extern call: aggregate arg must be a {ptr, len} fat-pointer pair");
},
else => return typeErrorDetail("comptime foreign call: unsupported arg Value kind"),
else => return typeErrorDetail("comptime extern call: unsupported arg Value kind"),
};
}
@@ -491,7 +491,7 @@ pub const Interpreter = struct {
fn callExtern(self: *Interpreter, func: *const inst_mod.Function, args: []const Value) InterpError!Value {
const name = self.module.types.getString(func.name);
// A foreign call may not return (e.g. `process.exit` → `_exit`), which
// A extern call may not return (e.g. `process.exit` → `_exit`), which
// would discard the interpreter's buffered `print` output (otherwise
// flushed only after `#run` completes). Flush it first so comptime
// diagnostics emitted just before a terminating call survive.
@@ -499,13 +499,13 @@ pub const Interpreter = struct {
_ = std.c.write(1, self.output.items.ptr, self.output.items.len);
self.output.clearRetainingCapacity();
}
const symbol = (host_ffi.lookupSymbol(self.alloc, name) catch return bailDetail("comptime foreign call: dlsym error looking up symbol")) orelse {
if (last_bail_detail == null) last_bail_detail = "comptime foreign call: symbol not found via dlsym (target-specific binding called at compile time?)";
const symbol = (host_ffi.lookupSymbol(self.alloc, name) catch return bailDetail("comptime extern call: dlsym error looking up symbol")) orelse {
if (last_bail_detail == null) last_bail_detail = "comptime extern call: symbol not found via dlsym (target-specific binding called at compile time?)";
return error.CannotEvalComptime;
};
var packed_args: [8]usize = undefined;
if (args.len > packed_args.len) return bailDetail("comptime foreign call: more than 8 args (host_ffi trampolines max out at 8)");
if (args.len > packed_args.len) return bailDetail("comptime extern call: more than 8 args (host_ffi trampolines max out at 8)");
var tmp = std.ArrayList([]u8).empty;
defer {
@@ -517,7 +517,7 @@ pub const Interpreter = struct {
}
const argv = packed_args[0..args.len];
// Variadic foreign functions (declared `args: ..T`) must be
// Variadic extern functions (declared `args: ..T`) must be
// dispatched through C-variadic trampolines so the trailing
// args land in the right place per the target's variadic
// ABI. The fixed-arity trampolines would put them in arg
@@ -567,7 +567,7 @@ pub const Interpreter = struct {
const func = self.module.getFunction(func_id);
if (func.is_extern or func.blocks.items.len == 0) {
// Dispatch to host libc via dlsym. Lets `#run` (and the
// post-link bundler) call ordinary foreign symbols like
// post-link bundler) call ordinary extern symbols like
// `puts`, `getenv`, `posix_spawn`, etc.
return self.callExtern(func, args);
}
@@ -863,7 +863,7 @@ pub const Interpreter = struct {
const byte: u8 = @intCast(@as(u64, @bitCast(val.asInt() orelse return error.TypeError)) & 0xFF);
self.heapStoreByte(hp, byte);
},
// Raw host pointer (from foreign call, e.g. libc_malloc).
// Raw host pointer (from extern call, e.g. libc_malloc).
// `val_ty` carries the declared destination width so we
// write exactly that many bytes — no neighbor clobber.
.int => |p| {
@@ -1452,7 +1452,7 @@ pub const Interpreter = struct {
.offset = hp.offset + @as(u32, @intCast(offset)),
} } };
},
// Raw host pointer (from foreign call return,
// Raw host pointer (from extern call return,
// e.g. libc_malloc). Byte-addressed offset
// matches the heap_ptr branch above — both
// are u8-granular for sx's string/slice ops.
@@ -1534,7 +1534,7 @@ pub const Interpreter = struct {
const result = try self.call(fid, args);
return .{ .value = result };
},
else => return bailDetail("comptime call_indirect: callee is not a func_ref Value (raw fn-pointers from foreign calls aren't dispatchable in interp)"),
else => return bailDetail("comptime call_indirect: callee is not a func_ref Value (raw fn-pointers from extern calls aren't dispatchable in interp)"),
}
},