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:
@@ -30,7 +30,7 @@ pub fn lowerCall(self: *Lowering, c_in: *const ast.Call) Ref {
|
||||
var c = c_in;
|
||||
// A bare reserved-type-name spelling in call position parses as a
|
||||
// `.type_expr` (e.g. `i2(4)`), but if a function of that name is in
|
||||
// scope — a backtick-declared sx fn or a `#import c` foreign fn whose C
|
||||
// scope — a backtick-declared sx fn or a `#import c` extern fn whose C
|
||||
// name collides with a reserved type spelling — it is a CALL to that
|
||||
// function. `TypeName(val)` is not a cast (casts are `cast(T, val)`), so
|
||||
// there is no ambiguity. Rewrite the callee to an identifier so the
|
||||
@@ -38,7 +38,7 @@ pub fn lowerCall(self: *Lowering, c_in: *const ast.Call) Ref {
|
||||
// reference that already resolves via scope/globals.
|
||||
//
|
||||
// Scoped to RAW provenance: only a backtick (`is_raw`) or `#import c`
|
||||
// foreign fn declaration may legally carry a reserved-name spelling
|
||||
// extern fn declaration may legally carry a reserved-name spelling
|
||||
// (the decl check rejects every bare reserved-name sx fn). Refusing the
|
||||
// rewrite for a non-raw match keeps a genuine reserved type spelling a
|
||||
// type — belt-and-suspenders should any future path ever reintroduce a
|
||||
@@ -603,7 +603,7 @@ pub fn lowerCall(self: *Lowering, c_in: *const ast.Call) Ref {
|
||||
return self.lowerSuperCall(fa.field, args.items, c.callee.span);
|
||||
}
|
||||
|
||||
// `Alias.method(args)` where Alias is a foreign-class
|
||||
// `Alias.method(args)` where Alias is a runtime-class
|
||||
// identifier and `method` is a `static` member — JNI
|
||||
// dispatch via FindClass + GetStaticMethodID + CallStatic*,
|
||||
// OR (for `new`) via FindClass + GetMethodID("<init>") +
|
||||
@@ -1251,7 +1251,7 @@ pub fn allocViaContext(self: *Lowering, size_ref: Ref, void_ptr_ty: TypeId) Ref
|
||||
} }, void_ptr_ty);
|
||||
}
|
||||
|
||||
/// Emit a call to a foreign-declared function looked up by name.
|
||||
/// Emit a call to a extern-declared function looked up by name.
|
||||
/// Used for the compiler-internal byte-copy in the protocol-erasure
|
||||
/// heap path and the closure env-copy path, both of which need
|
||||
/// libc `memcpy` after the `#builtin` form was dropped.
|
||||
@@ -1285,7 +1285,7 @@ fn protocolHasMethod(proto_info: anytype, name: []const u8) bool {
|
||||
}
|
||||
|
||||
pub fn resolveFuncByName(self: *Lowering, name: []const u8) ?FuncId {
|
||||
// Check foreign name map first (e.g., "c_abs" → "abs")
|
||||
// Check extern name map first (e.g., "c_abs" → "abs")
|
||||
const effective_name = self.extern_name_map.get(name) orelse name;
|
||||
const name_id = self.module.types.internString(effective_name);
|
||||
for (self.module.functions.items, 0..) |func, i| {
|
||||
|
||||
@@ -305,7 +305,7 @@ pub fn lowerLambda(self: *Lowering, lam: *const ast.Lambda) Ref {
|
||||
// be passed directly. For a capture-free closure whose return type matches
|
||||
// the slot, emit an adapter with the bare ABI. Reject the cases the bare
|
||||
// ABI can't represent: a capturing closure (env has nowhere to live), and
|
||||
// a failable closure into a non-failable slot (foreign code can't observe
|
||||
// a failable closure into a non-failable slot (extern code can't observe
|
||||
// the error channel — ERR E5.1 FFI-boundary rule).
|
||||
if (self.target_type) |tt| {
|
||||
if (!tt.isBuiltin() and self.module.types.get(tt) == .function) {
|
||||
@@ -319,7 +319,7 @@ pub fn lowerLambda(self: *Lowering, lam: *const ast.Lambda) Ref {
|
||||
const adapter = self.createClosureToBareFnAdapter(func_id, self.module.types.get(tt).function, ret_ty, lam.body.span);
|
||||
return self.builder.emit(.{ .func_ref = adapter }, tt);
|
||||
} else if (self.errorChannelOf(ret_ty) != null and self.errorChannelOf(slot_ret) == null) {
|
||||
if (self.diagnostics) |d| d.addFmt(.err, lam.body.span, "failable closure cannot be assigned to a non-failable function-type slot; foreign code can't observe the error channel — handle the error in a wrapper closure that absorbs it", .{});
|
||||
if (self.diagnostics) |d| d.addFmt(.err, lam.body.span, "failable closure cannot be assigned to a non-failable function-type slot; extern code can't observe the error channel — handle the error in a wrapper closure that absorbs it", .{});
|
||||
} else if (self.diagnostics) |d| {
|
||||
d.addFmt(.err, lam.body.span, "closure return type does not match the function-type slot", .{});
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ pub fn checkRequiredEntryPoints(self: *Lowering) void {
|
||||
diags.addFmt(.err, null, "target is Android but no `#jni_main` Activity declared. " ++
|
||||
"The OS launches a Java-side Activity that delegates lifecycle " ++
|
||||
"callbacks into sx — declare one like:\n\n" ++
|
||||
" Bundle :: #foreign #jni_class(\"android/os/Bundle\") {{ }}\n\n" ++
|
||||
" Bundle :: #jni_class(\"android/os/Bundle\") extern {{ }}\n\n" ++
|
||||
" MyApp :: #jni_main #jni_class(\"co/example/MyApp\") {{\n" ++
|
||||
" onCreate :: (self: *Self, b: *Bundle) {{ /* ... */ }}\n" ++
|
||||
" }}", .{});
|
||||
@@ -375,7 +375,7 @@ pub fn detectContextDecl(decls: []const *const Node) bool {
|
||||
}
|
||||
|
||||
/// Returns true if a sx function declaration should receive the
|
||||
/// implicit `__sx_ctx` parameter. False for foreign-libc bindings,
|
||||
/// implicit `__sx_ctx` parameter. False for extern-libc bindings,
|
||||
/// #builtin / #compiler bodies, and C-conv functions (which keep
|
||||
/// their literal C ABI). Also false for OS-called entry points
|
||||
/// (`isExportedEntryName`): main and JNI hooks are invoked by the
|
||||
@@ -1101,7 +1101,7 @@ pub fn registerTopLevelGlobal(self: *Lowering, vd: *const ast.VarDecl) void {
|
||||
// Use self.resolveType so type aliases like `Handle :: u32;` resolve
|
||||
// to their target type (not a synthetic empty struct). When the
|
||||
// user omitted the annotation, infer from the initializer
|
||||
// expression; foreign globals with no annotation are diagnosed
|
||||
// expression; extern globals with no annotation are diagnosed
|
||||
// because their type can't be inferred without an initializer.
|
||||
const var_ty: TypeId = if (vd.type_annotation) |ta|
|
||||
self.resolveType(ta)
|
||||
@@ -1113,7 +1113,7 @@ pub fn registerTopLevelGlobal(self: *Lowering, vd: *const ast.VarDecl) void {
|
||||
break :blk .void;
|
||||
};
|
||||
// Foreign / extern globals reference a symbol defined in libSystem etc.
|
||||
// (`_NSConcreteStackBlock : *void #foreign;` or `… : *void extern;`). The C
|
||||
// (`_NSConcreteStackBlock : *void extern;` or `… : *void extern;`). The C
|
||||
// symbol name is the optional override (`extern_name`) or the sx name itself.
|
||||
const sym_name = vd.extern_name orelse vd.name;
|
||||
const name_id = self.module.types.internString(sym_name);
|
||||
@@ -1397,7 +1397,7 @@ pub fn lowerRetainedSameNameAuthors(self: *Lowering) void {
|
||||
if (winner == fd) continue;
|
||||
|
||||
// Only plain free functions get an out-of-line slot; generic /
|
||||
// foreign / builtin / #compiler authors keep their existing
|
||||
// extern / builtin / #compiler authors keep their existing
|
||||
// dispatch (mirrors lazyLowerFunction / declareFunction guards).
|
||||
if (!isPlainFreeFn(fd)) continue;
|
||||
|
||||
@@ -1452,7 +1452,7 @@ pub const TypeHeadResolution = union(enum) {
|
||||
pending,
|
||||
/// A flat-visible author DOES declare `name` as a type, but its TypeId
|
||||
/// slot is not registered yet — a forward / self / mutual reference
|
||||
/// resolved mid-registration (`next: *ArenaChunk`), or a foreign /
|
||||
/// resolved mid-registration (`next: *ArenaChunk`), or an extern /
|
||||
/// lazily-registered author with no `findByName` slot. `resolveNominalLeaf`
|
||||
/// keeps the empty-struct stub, which `internNamedTypeDecl` ADOPTS (key-
|
||||
/// stable `updatePreservingKey`) when the type registers — so the forward
|
||||
@@ -1513,7 +1513,7 @@ pub const TypeHeadResolution = union(enum) {
|
||||
/// same module is one author): `≥2 distinct` → `.ambiguous`; exactly one
|
||||
/// that DIFFERS from the winner → select it; otherwise `.none`.
|
||||
///
|
||||
/// Generic / comptime / foreign / builtin authors are never rerouted — the
|
||||
/// Generic / comptime / extern / builtin authors are never rerouted — the
|
||||
/// existing dispatch owns those shapes; `isPlainFreeFn` filters them out
|
||||
/// BEFORE the count gate (so a same-name collision of non-plain authors is
|
||||
/// NOT ambiguous), and the selector returns `.none`. No eager
|
||||
@@ -1540,7 +1540,7 @@ pub fn selectPlainCallableAuthor(self: *Lowering, name: []const u8, caller_file:
|
||||
|
||||
// Caller does not author `name` as a fn → its flat-reachable authors.
|
||||
// Filter to plain free functions BEFORE counting: a same-name collision
|
||||
// of non-plain authors (e.g. two flat-imported modules each `#foreign`ing
|
||||
// of non-plain authors (e.g. two flat-imported modules each `extern`ing
|
||||
// the same symbol) is NOT counted as ambiguous — it falls through to
|
||||
// `.none` and the existing first-wins path.
|
||||
var the_one: ?*const ast.FnDecl = null;
|
||||
@@ -1597,7 +1597,7 @@ pub fn selectNominalLeaf(self: *Lowering, name: []const u8, from: []const u8, ra
|
||||
}
|
||||
// Bare nominal name. A bare TYPE name is visible iff a flat-import-
|
||||
// reachable module authors it AS A TYPE — and a TYPE author is EITHER a
|
||||
// named type (struct/enum/union/error-set/protocol/foreign class) OR a
|
||||
// named type (struct/enum/union/error-set/protocol/runtime class) OR a
|
||||
// type ALIAS (`Name :: <type>`, a `const_decl` whose value resolved to a
|
||||
// type, recorded in E0's `type_aliases_by_source`). Both kinds are gated
|
||||
// identically: `moduleTypeAuthor` is the SINGLE source of truth, so a
|
||||
@@ -1741,7 +1741,7 @@ pub fn selectNominalLeaf(self: *Lowering, name: []const u8, from: []const u8, ra
|
||||
}
|
||||
|
||||
/// TRUE iff `raw` declares a NAMED TYPE — struct / enum / union / error-set /
|
||||
/// protocol / foreign class. A `fn_decl`, a value-or-alias `const_decl`, and a
|
||||
/// protocol / runtime class. A `fn_decl`, a value-or-alias `const_decl`, and a
|
||||
/// `namespace_decl` are NOT named types. A type ALIAS is a `const_decl`;
|
||||
/// it is recognised via `type_aliases_by_source` separately from named types.
|
||||
pub fn isNamedTypeKind(raw: resolver_mod.RawDeclRef) bool {
|
||||
@@ -1766,7 +1766,7 @@ pub fn isNamedTypeKind(raw: resolver_mod.RawDeclRef) bool {
|
||||
/// through `internNamedTypeDecl` (`registerEnumDecl` / `registerUnionDecl`),
|
||||
/// keyed by the raw-facts decl pointer, with the `findByName` fallback for a
|
||||
/// single author registered before its slot lands. error-set / protocol /
|
||||
/// foreign-class keep the legacy `findByName` resolution (their same-name
|
||||
/// runtime-class keep the legacy `findByName` resolution (their same-name
|
||||
/// shadows are later E6 sub-steps — E6b/E6c/E6d).
|
||||
pub fn namedRefTid(self: *Lowering, ref: resolver_mod.RawDeclRef, name: []const u8) ?TypeId {
|
||||
const table = &self.module.types;
|
||||
@@ -1831,7 +1831,7 @@ pub fn localTypeInAnySource(self: *Lowering, name: []const u8) bool {
|
||||
/// Resolve the bare TYPE leaf to a `TypeId` for `resolveTypeWithBindings`.
|
||||
/// Routes through the source-aware `selectNominalLeaf`. `.pending` (forward
|
||||
/// alias) and `.forward` (a real author not interned yet — self / forward /
|
||||
/// foreign reference) keep the empty-struct stub, which the type ADOPTS on
|
||||
/// extern reference) keep the empty-struct stub, which the type ADOPTS on
|
||||
/// registration (`internNamedTypeDecl`). `.undeclared` (NO author anywhere)
|
||||
/// is genuinely-undeclared: in a NON-main module — which the
|
||||
/// `UnknownTypeChecker` trusts and never walks — the leaf is the only guard,
|
||||
@@ -2298,14 +2298,14 @@ pub fn lazyLowerFunction(self: *Lowering, name: []const u8) void {
|
||||
if (self.lookupObjcDefinedClassForMethod(name)) |fcd| {
|
||||
self.current_runtime_class = fcd;
|
||||
}
|
||||
// No AST? (builtins, foreign functions, or imported functions not in this file)
|
||||
// No AST? (builtins, extern functions, or imported functions not in this file)
|
||||
const fd = self.program_index.fn_ast_map.get(name) orelse return;
|
||||
// Foreign declarations stay as extern stubs but need to be REGISTERED
|
||||
// in the current module so callers get a real FuncId. Without this,
|
||||
// a comptime-lowered function (e.g. `concat` from std.sx pulled into
|
||||
// a fresh ct_module via `evalComptimeString`) emits `.call` against a
|
||||
// FuncId that doesn't exist locally; the interp can't find the
|
||||
// foreign target and silently no-ops instead of dispatching to libc.
|
||||
// extern target and silently no-ops instead of dispatching to libc.
|
||||
if (fd.extern_export == .extern_) {
|
||||
if (self.resolveFuncByName(name) == null) {
|
||||
self.declareFunction(fd, name);
|
||||
@@ -2511,10 +2511,10 @@ pub fn lowerFunction(self: *Lowering, fd: *const ast.FnDecl, name: []const u8, i
|
||||
}) catch unreachable;
|
||||
}
|
||||
|
||||
// Check if the function body is a builtin or foreign declaration (no body
|
||||
// Check if the function body is a builtin or extern declaration (no body
|
||||
// needed). `extern` imports are declare-only too (empty placeholder body).
|
||||
if (fd.body.data == .builtin_expr or fd.body.data == .compiler_expr or fd.extern_export == .extern_) {
|
||||
// Already declared by scanDecls/declareFunction (which handles #foreign renames)
|
||||
// Already declared by scanDecls/declareFunction (which handles #extern renames)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -567,7 +567,7 @@ pub fn lowerFieldAccess(self: *Lowering, fa: *const ast.FieldAccess, span: ast.S
|
||||
}
|
||||
|
||||
// M2.2 — `obj.field` where `field` is declared with `#property`
|
||||
// on a foreign Obj-C class lowers as `[obj field]` (the synthesized
|
||||
// on a runtime Obj-C class lowers as `[obj field]` (the synthesized
|
||||
// getter). Receiver stays opaque — no auto-deref.
|
||||
if (self.lookupObjcPropertyOnPointer(fa.object, fa.field)) |prop| {
|
||||
return self.lowerObjcPropertyGetter(fa.object, prop, fa.field, span);
|
||||
|
||||
@@ -228,7 +228,7 @@ pub fn lowerJniCall(self: *Lowering, fic: *const ast.FfiIntrinsicCall) Ref {
|
||||
} }, ret_ty);
|
||||
}
|
||||
|
||||
/// Lower an `inst.method(args)` call where `inst`'s type is a foreign-class
|
||||
/// Lower an `inst.method(args)` call where `inst`'s type is a runtime-class
|
||||
/// alias declared by `#jni_class("...") { ... }` (or its parallel forms).
|
||||
/// JNI runtimes lower directly to `jni_msg_send` with a descriptor derived
|
||||
/// from the method's sx signature; Obj-C / Swift runtimes are deferred to
|
||||
@@ -252,7 +252,7 @@ pub fn lowerRuntimeMethodCall(
|
||||
// child receiver, not the parent.
|
||||
const found = self.findRuntimeMethodInChain(fcd, method_name) orelse {
|
||||
if (self.diagnostics) |d| {
|
||||
d.addFmt(.err, span, "no method '{s}' on foreign class '{s}' (or any `#extends` ancestor)", .{ method_name, fcd.name });
|
||||
d.addFmt(.err, span, "no method '{s}' on runtime class '{s}' (or any `#extends` ancestor)", .{ method_name, fcd.name });
|
||||
}
|
||||
return Ref.none;
|
||||
};
|
||||
@@ -263,7 +263,7 @@ pub fn lowerRuntimeMethodCall(
|
||||
// receiver derives a selector from the sx method name (default
|
||||
// mangling: split on `_`, each piece becomes a keyword with a
|
||||
// trailing `:`; niladic stays verbatim) and lowers to
|
||||
// `objc_msg_send`. Both foreign and sx-defined classes flow
|
||||
// `objc_msg_send`. Both runtime and sx-defined classes flow
|
||||
// through the same path — sx-defined classes have their IMPs
|
||||
// registered at module-init (M1.2 A.4b.iii) so `objc_msgSend`
|
||||
// finds them. The Swift runtimes still bail — Phase 4.
|
||||
@@ -292,7 +292,7 @@ pub fn lowerRuntimeMethodCall(
|
||||
const env_ref = self.jni_env_stack.items[self.jni_env_stack.items.len - 1];
|
||||
|
||||
// Build a ClassRegistry snapshot so descriptor derivation can
|
||||
// resolve `*Foo` cross-class refs to their foreign paths.
|
||||
// resolve `*Foo` cross-class refs to their runtime paths.
|
||||
var registry = jni_descriptor.ClassRegistry.init(self.alloc);
|
||||
defer registry.deinit();
|
||||
var it = self.program_index.runtime_class_map.iterator();
|
||||
@@ -353,8 +353,8 @@ pub fn lowerRuntimeMethodCall(
|
||||
// `self.objc()`. Emission-heavy IMP builders live in lower/objc_class.zig;
|
||||
// the `lowerObjc*Call` lowering paths are below.
|
||||
|
||||
/// Resolve a foreign-class member type, substituting `Self` (and `*Self`)
|
||||
/// with the foreign class's own struct type. Without this substitution
|
||||
/// Resolve a runtime-class member type, substituting `Self` (and `*Self`)
|
||||
/// with the runtime class's own struct type. Without this substitution
|
||||
/// chained calls like `Cls.alloc().init()` see the inner result as a
|
||||
/// fictitious `Self` struct and the next dispatch lookup fails.
|
||||
pub fn resolveRuntimeClassMemberType(
|
||||
@@ -559,7 +559,7 @@ pub fn lowerObjcStaticCall(
|
||||
} }, ret_ty);
|
||||
}
|
||||
|
||||
/// Lower `Alias.new(args)` where `Alias` is a foreign-class identifier
|
||||
/// Lower `Alias.new(args)` where `Alias` is a runtime-class identifier
|
||||
/// with `static new :: (...) -> *Self;` — JNI constructor dispatch:
|
||||
/// `FindClass + GetMethodID("<init>", "(args)V") + NewObject(env,
|
||||
/// clazz, mid, args...)`. Returns the new jobject.
|
||||
@@ -587,7 +587,7 @@ pub fn lowerRuntimeStaticCall(
|
||||
return Ref.none;
|
||||
}
|
||||
if (!std.mem.eql(u8, method.name, "new")) {
|
||||
if (self.diagnostics) |d| d.addFmt(.err, span, "static foreign-class call '{s}.{s}' not yet supported via `Alias.method()` syntax \u{2014} only `new` is wired today; use `#jni_static_call` directly for other static methods", .{ fcd.name, method.name });
|
||||
if (self.diagnostics) |d| d.addFmt(.err, span, "static runtime-class call '{s}.{s}' not yet supported via `Alias.method()` syntax \u{2014} only `new` is wired today; use `#jni_static_call` directly for other static methods", .{ fcd.name, method.name });
|
||||
return Ref.none;
|
||||
}
|
||||
|
||||
@@ -628,7 +628,7 @@ pub fn lowerRuntimeStaticCall(
|
||||
};
|
||||
|
||||
// sx-side return type is `*Self` — resolve to a pointer to the
|
||||
// foreign-class struct type so method dispatch on the new
|
||||
// runtime-class struct type so method dispatch on the new
|
||||
// jobject works (`view := SurfaceView.new(ctx); view.getHolder()`).
|
||||
// At LLVM level still ptr; the sx type table is what method
|
||||
// resolution consults.
|
||||
@@ -671,7 +671,7 @@ pub fn lowerRuntimeStaticCall(
|
||||
/// method's name (the common case — `super.onCreate(b)` from inside
|
||||
/// `onCreate :: (self, b)` override), the enclosing method's
|
||||
/// signature is reused. Other method names require the parent class
|
||||
/// to be declared via `#foreign #jni_class` so the signature can be
|
||||
/// to be declared via `#jni_class(…) extern` so the signature can be
|
||||
/// looked up.
|
||||
pub fn lowerSuperCall(
|
||||
self: *Lowering,
|
||||
@@ -701,7 +701,7 @@ pub fn lowerSuperCall(
|
||||
|
||||
// Resolve method signature. Same-name fast path reuses the
|
||||
// enclosing method's descriptor; cross-method super calls require
|
||||
// the parent class to be declared via `#foreign #jni_class`.
|
||||
// the parent class to be declared via `#jni_class(…) extern`.
|
||||
var descriptor: []const u8 = "";
|
||||
var resolved_method: ?ast.RuntimeMethodDecl = null;
|
||||
if (self.current_runtime_method) |em| {
|
||||
@@ -725,7 +725,7 @@ pub fn lowerSuperCall(
|
||||
}
|
||||
}
|
||||
const method = resolved_method orelse {
|
||||
if (self.diagnostics) |d| d.addFmt(.err, span, "no method '{s}' found for `super.{s}(...)` — declare the parent class via `#foreign #jni_class` to make cross-method super calls available", .{ method_name, method_name });
|
||||
if (self.diagnostics) |d| d.addFmt(.err, span, "no method '{s}' found for `super.{s}(...)` — declare the parent class via `#jni_class(…) extern` to make cross-method super calls available", .{ method_name, method_name });
|
||||
return Ref.none;
|
||||
};
|
||||
|
||||
@@ -780,13 +780,13 @@ pub fn lowerSuperCall(
|
||||
|
||||
// ── Foreign-class registration ──────────────────────────────────
|
||||
|
||||
/// Register a foreign-class declaration. The alias goes into
|
||||
/// Register a runtime-class declaration. The alias goes into
|
||||
/// `runtime_class_map` for method-dispatch lookup. The underlying
|
||||
/// type (e.g. `*Activity`) is resolved via the existing struct
|
||||
/// fallback in `type_bridge.resolveTypeName` (which interns unknown
|
||||
/// named types as 0-field structs).
|
||||
///
|
||||
/// sx-defined Obj-C classes (no `#foreign`, runtime == .objc_class)
|
||||
/// sx-defined Obj-C classes (no `extern`, runtime == .objc_class)
|
||||
/// also land in `module.objc_defined_class_cache` in declaration
|
||||
/// order AND have their bodied methods registered into `fn_ast_map`
|
||||
/// under qualified names `<ClassName>.<methodName>`. Lazy lowering
|
||||
@@ -821,7 +821,7 @@ pub fn registerRuntimeClassDecl(self: *Lowering, fcd: *const ast.RuntimeClassDec
|
||||
/// Resolve the `#extends ParentAlias` declaration on a sx-defined
|
||||
/// `#objc_class` to the actual Obj-C runtime class name. Falls
|
||||
/// back to "NSObject" when no `#extends` is declared.
|
||||
/// Aliases that resolve to foreign Obj-C classes use the
|
||||
/// Aliases that resolve to runtime Obj-C classes use the
|
||||
/// runtime_path; aliases for OTHER sx-defined classes use the
|
||||
/// alias name directly (which equals the Obj-C class name for
|
||||
/// sx-defined classes).
|
||||
@@ -1007,7 +1007,7 @@ pub fn getJniEnvTlFids(self: *Lowering) struct { get: FuncId, set: FuncId } {
|
||||
return .{ .get = self.jni_env_tl_get_fid.?, .set = self.jni_env_tl_set_fid.? };
|
||||
}
|
||||
|
||||
/// When a namespaced import (`Ns :: #import "..."`) contains foreign-class
|
||||
/// When a namespaced import (`Ns :: #import "..."`) contains runtime-class
|
||||
/// declarations, ALSO register them under their qualified name `Ns.Class`
|
||||
/// so receiver types like `*Ns.Class` can find the fcd. The recursive
|
||||
/// scan/lower already handles bare-name registration; this only adds the
|
||||
@@ -1169,7 +1169,7 @@ pub fn synthesizeJniMainStub(self: *Lowering, fcd: *const ast.RuntimeClassDecl,
|
||||
}
|
||||
|
||||
/// JNI param/return type resolution: user-declared types pass through
|
||||
/// `resolveType` so the method body can dispatch on richer foreign-class
|
||||
/// `resolveType` so the method body can dispatch on richer runtime-class
|
||||
/// types (`holder.getSurface()` etc.). At LLVM level both `*SurfaceHolder`
|
||||
/// and `*void` lower to the same `ptr`, so the C ABI shape Java sees is
|
||||
/// unchanged — only sx-side method resolution benefits.
|
||||
|
||||
@@ -808,14 +808,14 @@ pub fn hasComptimeParams(fd: *const ast.FnDecl) bool {
|
||||
}
|
||||
|
||||
/// A plain free function: no type params (not generic) and an ordinary sx
|
||||
/// body (not `#foreign` / `#builtin` / `#compiler` / `extern`). Only these get
|
||||
/// body (not `extern` / `#builtin` / `#compiler` / `extern`). Only these get
|
||||
/// an out-of-line identity-addressable slot — the bare-call disambiguation
|
||||
/// and the shadow-author lowering pass leave every other shape
|
||||
/// to the existing name-keyed dispatch.
|
||||
pub fn isPlainFreeFn(fd: *const ast.FnDecl) bool {
|
||||
if (fd.type_params.len > 0) return false;
|
||||
// An `extern` import is an external C symbol with no sx-lowerable body —
|
||||
// name-keyed first-wins dispatch like a `#foreign` body, never a plain free
|
||||
// name-keyed first-wins dispatch like a `extern` body, never a plain free
|
||||
// fn. `export` DEFINES a real body, so it stays plain-free.
|
||||
if (fd.extern_export == .extern_) return false;
|
||||
return switch (fd.body.data) {
|
||||
@@ -1032,7 +1032,7 @@ pub fn headNameOfCallee(callee: *const Node) ?HeadName {
|
||||
/// (`.proceed`) when import facts are unwired, the source context is absent,
|
||||
/// the default-Context emitter is running (built-in infrastructure resolves
|
||||
/// independent of the user's import style, F1), the querying source is the OWN
|
||||
/// author, a single flat author is not registered yet (a forward / foreign /
|
||||
/// author, a single flat author is not registered yet (a forward / extern /
|
||||
/// generic template — the caller instantiates it), or `name` is a block-local
|
||||
/// of this source / no type author at all. Library-internal heads stay visible
|
||||
/// because every instantiation kind is source-pinned to the template's defining
|
||||
|
||||
@@ -257,7 +257,7 @@ pub fn shadowNominalId(self: *Lowering, name_id: types.StringId) u32 {
|
||||
}
|
||||
|
||||
/// TRUE iff `name` is authored AS A NAMED TYPE (struct / enum / union /
|
||||
/// error-set / protocol / foreign class) by ≥2 DISTINCT modules in the import
|
||||
/// error-set / protocol / runtime class) by ≥2 DISTINCT modules in the import
|
||||
/// raw facts — the authoritative same-name-shadow signal (the only case where
|
||||
/// distinct `nominal_id`s are needed). Module distinctness is by LEXICALLY
|
||||
/// NORMALIZED path: one logical file reached through several spellings
|
||||
|
||||
@@ -53,7 +53,7 @@ pub fn lowerObjcDefinedClassMethods(self: *Lowering) void {
|
||||
self.emitObjcDefinedClassImps();
|
||||
}
|
||||
|
||||
/// If `obj_expr` is typed as a pointer to a foreign Obj-C class
|
||||
/// If `obj_expr` is typed as a pointer to a runtime Obj-C class
|
||||
/// and that class (or any of its `#extends` ancestors) declares a
|
||||
/// `#property` field with the given name, return the
|
||||
/// `RuntimeFieldDecl`. M2.2 + M2.3.
|
||||
@@ -257,7 +257,7 @@ pub fn lowerObjcPropertySetter(self: *Lowering, obj_expr: *const ast.Node, field
|
||||
|
||||
/// Get a FuncId for an external C-callconv function. If a function
|
||||
/// with this exported name already exists in the module (e.g.
|
||||
/// declared by stdlib `#foreign` decl), return it; otherwise
|
||||
/// declared by stdlib `extern` decl), return it; otherwise
|
||||
/// declare it fresh with the given signature.
|
||||
///
|
||||
/// One helper instead of a `get<Name>Fid` per runtime function —
|
||||
@@ -729,7 +729,7 @@ pub fn emitObjcDefinedClassImp(self: *Lowering, fcd: *const ast.RuntimeClassDecl
|
||||
|
||||
// Pass the Obj-C receiver pointer through to the sx body as
|
||||
// `self`. The body's `self: *Self` type resolves to the
|
||||
// foreign-class stub (the opaque Obj-C type), matching Apple's
|
||||
// runtime-class stub (the opaque Obj-C type), matching Apple's
|
||||
// Obj-C semantics where `self` IS the object. `self.field`
|
||||
// access on a sx-defined class is rewritten by lowerFieldAccess
|
||||
// to go through `object_getIvar(self, __sx_state_ivar)` and
|
||||
|
||||
Reference in New Issue
Block a user