diff --git a/src/ast.zig b/src/ast.zig index aaa4281..b876a02 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -93,7 +93,7 @@ pub const Node = struct { protocol_decl: ProtocolDecl, impl_block: ImplBlock, ffi_intrinsic_call: FfiIntrinsicCall, - foreign_class_decl: RuntimeClassDecl, + runtime_class_decl: RuntimeClassDecl, jni_env_block: JniEnvBlock, pub fn declName(self: Data) ?[]const u8 { @@ -109,7 +109,7 @@ pub const Node = struct { .ufcs_alias => |d| d.name, .c_import_decl => |d| d.name, .protocol_decl => |d| d.name, - .foreign_class_decl => |d| d.name, + .runtime_class_decl => |d| d.name, else => null, }; } @@ -888,7 +888,7 @@ pub const RuntimeClassDecl = struct { foreign_path: []const u8, // directive arg: "java/path/Foo" / "NSString" / "Foundation.URL" runtime: RuntimeKind, members: []const RuntimeClassMember = &.{}, - is_foreign: bool = false, // `#foreign #...` prefix — class is provided by the foreign runtime; we only reference it + is_reference: bool = false, // `#foreign #...` prefix — class is provided by the foreign runtime; we only reference it is_main: bool = false, // `#jni_main` / `#objc_main` — class is the launchable entry (Activity / UIApplicationDelegate / ...) /// True when the sx-side alias NAME was a backtick raw identifier — exempt /// from the reserved-type-name decl check. diff --git a/src/backend/llvm/ffi_ctors.zig b/src/backend/llvm/ffi_ctors.zig index 56df039..67587f7 100644 --- a/src/backend/llvm/ffi_ctors.zig +++ b/src/backend/llvm/ffi_ctors.zig @@ -295,7 +295,7 @@ pub const FfiCtors = struct { // Parent class — pre-resolved Obj-C runtime name from // lower.zig (M2.3 resolveObjcParentName). Stored on the // cache entry so emit_llvm doesn't re-walk - // foreign_class_map here. + // runtime_class_map here. const parent_name = entry_kv.parent_objc_name; const parent_str_global = self.e.emitPrivateCString(parent_name, "OBJC_CLASS_NAME_"); diff --git a/src/core.zig b/src/core.zig index 34de8ce..da0a39f 100644 --- a/src/core.zig +++ b/src/core.zig @@ -359,12 +359,12 @@ pub const Compilation = struct { return module; } - /// Walk `lowering.program_index.foreign_class_map` and render Java sources for every + /// Walk `lowering.program_index.runtime_class_map` and render Java sources for every /// `#jni_main #jni_class("...")` declaration. Renders happen here so the /// AST + class-registry snapshot stay confined to the lowering pass; the /// downstream APK pipeline only needs `{foreign_path, java_source}` pairs. fn collectJniMainEmissions(self: *Compilation, lowering: *ir.Lowering) !void { - // `foreign_class_map` registers each decl under bare + qualified names — + // `runtime_class_map` registers each decl under bare + qualified names — // dedupe by foreign_path so a single decl emits one .java. var seen = std.StringHashMap(void).init(self.allocator); defer seen.deinit(); @@ -373,7 +373,7 @@ pub const Compilation = struct { // and `#extends Alias` resolution. var registry = std.StringHashMap([]const u8).init(self.allocator); defer registry.deinit(); - var it_reg = lowering.program_index.foreign_class_map.iterator(); + var it_reg = lowering.program_index.runtime_class_map.iterator(); while (it_reg.next()) |entry| { try registry.put(entry.key_ptr.*, entry.value_ptr.*.foreign_path); } @@ -384,11 +384,11 @@ pub const Compilation = struct { // .so loading via another class. const lib_name = libNameFromOutputPath(self.target_config.output_path); - var it = lowering.program_index.foreign_class_map.iterator(); + var it = lowering.program_index.runtime_class_map.iterator(); while (it.next()) |entry| { const fcd = entry.value_ptr.*; if (!fcd.is_main) continue; - if (fcd.is_foreign) continue; + if (fcd.is_reference) continue; if (fcd.runtime != .jni_class) continue; if (seen.contains(fcd.foreign_path)) continue; try seen.put(fcd.foreign_path, {}); diff --git a/src/imports.zig b/src/imports.zig index 8d353c2..5ac891c 100644 --- a/src/imports.zig +++ b/src/imports.zig @@ -371,7 +371,7 @@ pub const ResolvedModule = struct { /// symbol, not split into a duplicate `__stdinp.1`. fn isPerSourceDecl(decl: *const Node) bool { return switch (decl.data) { - .struct_decl, .enum_decl, .union_decl, .error_set_decl, .protocol_decl, .foreign_class_decl => true, + .struct_decl, .enum_decl, .union_decl, .error_set_decl, .protocol_decl, .runtime_class_decl => true, .const_decl => |cd| cd.value.data != .fn_decl, else => false, }; @@ -463,7 +463,7 @@ pub const RawDeclRef = union(enum) { union_decl: *const ast.UnionDecl, error_set_decl: *const ast.ErrorSetDecl, protocol_decl: *const ast.ProtocolDecl, - foreign_class_decl: *const ast.RuntimeClassDecl, + runtime_class_decl: *const ast.RuntimeClassDecl, namespace_decl: *const ast.NamespaceDecl, }; @@ -513,7 +513,7 @@ pub fn rawDeclRefOf(decl: *const Node) ?RawDeclRef { .union_decl => |*d| .{ .union_decl = d }, .error_set_decl => |*d| .{ .error_set_decl = d }, .protocol_decl => |*d| .{ .protocol_decl = d }, - .foreign_class_decl => |*d| .{ .foreign_class_decl = d }, + .runtime_class_decl => |*d| .{ .runtime_class_decl = d }, .namespace_decl => |*d| .{ .namespace_decl = d }, else => null, }; @@ -592,7 +592,7 @@ pub const DeclKind = enum { @"union", error_set, protocol, - foreign_class, + runtime_class, namespace, }; @@ -606,7 +606,7 @@ fn declKindOf(ref: RawDeclRef) DeclKind { .union_decl => .@"union", .error_set_decl => .error_set, .protocol_decl => .protocol, - .foreign_class_decl => .foreign_class, + .runtime_class_decl => .runtime_class, .namespace_decl => .namespace, }; } @@ -815,9 +815,9 @@ fn stampFnBodySource(decl: *Node, file_path: []const u8) void { // An sx-defined `#objc_class` / `#jni_class`: its IMP trampolines are // emitted at lowering time (possibly from another module's context), so // record the defining path AND stamp each method body (E4). - .foreign_class_decl => { - decl.data.foreign_class_decl.source_file = file_path; - stampForeignClassMethodSources(decl.data.foreign_class_decl, file_path); + .runtime_class_decl => { + decl.data.runtime_class_decl.source_file = file_path; + stampRuntimeClassMethodSources(decl.data.runtime_class_decl, file_path); }, .const_decl => |cd| switch (cd.value.data) { .fn_decl => |fd| fd.body.source_file = file_path, @@ -827,9 +827,9 @@ fn stampFnBodySource(decl: *Node, file_path: []const u8) void { // bodies need the defining path stamped just like a top-level fn. .struct_decl => |sd| stampStructMethodSources(sd, file_path), .protocol_decl => cd.value.data.protocol_decl.source_file = file_path, - .foreign_class_decl => { - cd.value.data.foreign_class_decl.source_file = file_path; - stampForeignClassMethodSources(cd.value.data.foreign_class_decl, file_path); + .runtime_class_decl => { + cd.value.data.runtime_class_decl.source_file = file_path; + stampRuntimeClassMethodSources(cd.value.data.runtime_class_decl, file_path); }, else => {}, }, @@ -853,7 +853,7 @@ fn stampStructMethodSources(sd: ast.StructDecl, file_path: []const u8) void { /// Stamp the defining module path onto every bodied method of an sx-defined /// foreign class, so the method's sx body lowers in the class's own module. -fn stampForeignClassMethodSources(fcd: ast.RuntimeClassDecl, file_path: []const u8) void { +fn stampRuntimeClassMethodSources(fcd: ast.RuntimeClassDecl, file_path: []const u8) void { for (fcd.members) |m| { if (m == .method) { if (m.method.body) |b| b.source_file = file_path; diff --git a/src/ir/calls.test.zig b/src/ir/calls.test.zig index 3a27612..196dda4 100644 --- a/src/ir/calls.test.zig +++ b/src/ir/calls.test.zig @@ -360,7 +360,7 @@ test "plan: foreign-class instance vs static dispatch" { .{ .method = .{ .name = "stringWithUTF8String", .params = &.{}, .param_names = &.{}, .return_type = typeExpr(alloc, "i64"), .is_static = true } }, }; var fcd = ast.RuntimeClassDecl{ .name = "NSString", .foreign_path = "NSString", .runtime = .objc_class, .members = &members }; - l.program_index.foreign_class_map.put("NSString", &fcd) catch unreachable; + l.program_index.runtime_class_map.put("NSString", &fcd) catch unreachable; _ = module.types.intern(.{ .@"struct" = .{ .name = module.types.internString("NSString"), .fields = &.{} } }); // Instance: `cast(NSString, _).length` — receiver prepended. @@ -368,9 +368,9 @@ test "plan: foreign-class instance vs static dispatch" { const recv = callNode(alloc, ident(alloc, "cast"), &[_]*Node{ typeExpr(alloc, "NSString"), intLit(alloc, 0) }); const call = callNode(alloc, fieldAccess(alloc, recv, "length"), &.{}); const p = cr.plan(&call.data.call); - try std.testing.expectEqual(CallPlan.Kind.foreign_instance, p.kind); - try std.testing.expectEqualStrings("length", p.target.foreign_method.name); - try std.testing.expect(!p.target.foreign_method.is_static); + try std.testing.expectEqual(CallPlan.Kind.runtime_instance, p.kind); + try std.testing.expectEqualStrings("length", p.target.runtime_method.name); + try std.testing.expect(!p.target.runtime_method.is_static); try std.testing.expectEqual(TypeId.i64, p.return_type); try std.testing.expect(p.prepends_receiver); } @@ -378,9 +378,9 @@ test "plan: foreign-class instance vs static dispatch" { { const call = callNode(alloc, fieldAccess(alloc, ident(alloc, "NSString"), "stringWithUTF8String"), &.{}); const p = cr.plan(&call.data.call); - try std.testing.expectEqual(CallPlan.Kind.foreign_static, p.kind); - try std.testing.expectEqualStrings("stringWithUTF8String", p.target.foreign_method.name); - try std.testing.expect(p.target.foreign_method.is_static); + try std.testing.expectEqual(CallPlan.Kind.runtime_static, p.kind); + try std.testing.expectEqualStrings("stringWithUTF8String", p.target.runtime_method.name); + try std.testing.expect(p.target.runtime_method.is_static); try std.testing.expect(!p.prepends_receiver); } } diff --git a/src/ir/calls.zig b/src/ir/calls.zig index adf139d..3e8afaa 100644 --- a/src/ir/calls.zig +++ b/src/ir/calls.zig @@ -51,8 +51,8 @@ pub const CallPlan = struct { /// type prefix). Distinct from `namespace_fn` precisely because the /// receiver IS prepended (`prepends_receiver`). free_fn_ufcs, - foreign_instance, - foreign_static, + runtime_instance, + runtime_static, /// `pkg.fn(args)` — the receiver is a namespace / module prefix, NOT a /// value, so nothing is prepended. namespace_fn, @@ -82,7 +82,7 @@ pub const CallPlan = struct { /// Protocol method, by index in the protocol's method table. protocol_method: u32, /// Foreign-class method (Obj-C / JNI), with its static-ness. - foreign_method: struct { name: []const u8, is_static: bool }, + runtime_method: struct { name: []const u8, is_static: bool }, /// Enum / tagged-union type under construction. constructed: TypeId, }; @@ -254,13 +254,13 @@ pub const CallResolver = struct { const inner_info = self.l.module.types.get(recv_inner); if (inner_info == .@"struct") { const sn = self.l.module.types.getString(inner_info.@"struct".name); - if (self.l.program_index.foreign_class_map.get(sn)) |fcd| { + if (self.l.program_index.runtime_class_map.get(sn)) |fcd| { for (fcd.members) |m| switch (m) { .method => |md| if (!md.is_static and std.mem.eql(u8, md.name, cfa.field)) { return .{ - .kind = .foreign_instance, - .return_type = self.l.resolveForeignMethodReturnType(fcd, md), - .target = .{ .foreign_method = .{ .name = md.name, .is_static = false } }, + .kind = .runtime_instance, + .return_type = self.l.resolveRuntimeMethodReturnType(fcd, md), + .target = .{ .runtime_method = .{ .name = md.name, .is_static = false } }, .prepends_receiver = true, }; }, @@ -396,13 +396,13 @@ pub const CallResolver = struct { }; if (type_name) |tn| { // Foreign-class static method: `Alias.static_method(args)`. - if (self.l.program_index.foreign_class_map.get(tn)) |fcd| { + if (self.l.program_index.runtime_class_map.get(tn)) |fcd| { for (fcd.members) |m| switch (m) { .method => |md| if (md.is_static and std.mem.eql(u8, md.name, cfa.field)) { return .{ - .kind = .foreign_static, - .return_type = self.l.resolveForeignMethodReturnType(fcd, md), - .target = .{ .foreign_method = .{ .name = md.name, .is_static = true } }, + .kind = .runtime_static, + .return_type = self.l.resolveRuntimeMethodReturnType(fcd, md), + .target = .{ .runtime_method = .{ .name = md.name, .is_static = true } }, }; }, else => {}, diff --git a/src/ir/ffi_objc.zig b/src/ir/ffi_objc.zig index c02a665..5d0d2b4 100644 --- a/src/ir/ffi_objc.zig +++ b/src/ir/ffi_objc.zig @@ -179,7 +179,7 @@ pub const ObjcLowering = struct { const is_objc_obj = blk: { if (pointee_info != .@"struct") break :blk false; const name = self.l.module.types.getString(pointee_info.@"struct".name); - break :blk self.l.program_index.foreign_class_map.get(name) != null; + break :blk self.l.program_index.runtime_class_map.get(name) != null; }; if (is_objc_obj) { try out.append(self.l.alloc, '@'); @@ -319,7 +319,7 @@ pub const ObjcLowering = struct { const pointee_info = self.l.module.types.get(ptr_info.pointer.pointee); if (pointee_info != .@"struct") return false; const struct_name = self.l.module.types.getString(pointee_info.@"struct".name); - const fcd = self.l.program_index.foreign_class_map.get(struct_name) orelse return false; + const fcd = self.l.program_index.runtime_class_map.get(struct_name) orelse return false; return fcd.runtime == .objc_class or fcd.runtime == .objc_protocol; } @@ -383,7 +383,7 @@ pub const ObjcLowering = struct { const pointee_info = self.l.module.types.get(pointee); if (pointee_info != .@"struct") break :blk false; const struct_name = self.l.module.types.getString(pointee_info.@"struct".name); - const fcd = self.l.program_index.foreign_class_map.get(struct_name) orelse break :blk false; + const fcd = self.l.program_index.runtime_class_map.get(struct_name) orelse break :blk false; break :blk fcd.runtime == .objc_class or fcd.runtime == .objc_protocol; }; diff --git a/src/ir/jni_java_emit.test.zig b/src/ir/jni_java_emit.test.zig index 894a471..76f2690 100644 --- a/src/ir/jni_java_emit.test.zig +++ b/src/ir/jni_java_emit.test.zig @@ -1,7 +1,7 @@ // Tests for jni_java_emit.zig — #jni_main pipeline slice 1. // Locks in the Java source emitted from `RuntimeClassDecl` AST nodes: // package split, class header, @Override delegate pattern, primitive -// type mapping, cross-class refs through the foreign_class registry. +// type mapping, cross-class refs through the runtime_class registry. const std = @import("std"); const ast = @import("../ast.zig"); diff --git a/src/ir/lower.test.zig b/src/ir/lower.test.zig index 003e91a..c2008fc 100644 --- a/src/ir/lower.test.zig +++ b/src/ir/lower.test.zig @@ -389,7 +389,7 @@ test "lower: objcDefinedStateStructType collects user-declared fields" { .foreign_path = "SxFoo", .runtime = .objc_class, .members = &members, - .is_foreign = false, + .is_reference = false, .is_main = false, }; @@ -421,7 +421,7 @@ test "lower: objcDefinedStateStructType handles empty field set" { .foreign_path = "SxEmpty", .runtime = .objc_class, .members = &.{}, - .is_foreign = false, + .is_reference = false, .is_main = false, }; @@ -453,7 +453,7 @@ test "lower: objcDefinedStateStructType skips non-field members" { .foreign_path = "SxMixed", .runtime = .objc_class, .members = &members, - .is_foreign = false, + .is_reference = false, .is_main = false, }; @@ -481,10 +481,10 @@ test "lower: objcTypeEncodingFromSignature emits @ for Obj-C class pointers" { .foreign_path = "NSString", .runtime = .objc_class, .members = &.{}, - .is_foreign = true, + .is_reference = true, .is_main = false, }; - try lowering.program_index.foreign_class_map.put("NSString", &ns_fcd); + try lowering.program_index.runtime_class_map.put("NSString", &ns_fcd); // Return *NSString, no args: "@@:" const e1 = try lowering.objc().objcTypeEncodingFromSignature(ns_ptr, &.{}, null); @@ -514,10 +514,10 @@ test "lower: objcTypeEncodingFromSignature unwraps optional to wire type" { .foreign_path = "NSString", .runtime = .objc_class, .members = &.{}, - .is_foreign = true, + .is_reference = true, .is_main = false, }; - try lowering.program_index.foreign_class_map.put("NSString", &ns_fcd); + try lowering.program_index.runtime_class_map.put("NSString", &ns_fcd); // `?i64 -> ?*NSString` collapses to `q -> @` at the Obj-C boundary. const opt_i64 = module.types.optionalOf(.i64); @@ -683,10 +683,10 @@ test "lower: isObjcClassPointer recognises pointer-to-foreign-Obj-C-class" { .foreign_path = "NSString", .runtime = .objc_class, .members = &.{}, - .is_foreign = true, + .is_reference = true, .is_main = false, }; - try lowering.program_index.foreign_class_map.put("NSString", &ns_fcd); + try lowering.program_index.runtime_class_map.put("NSString", &ns_fcd); try std.testing.expect(lowering.objc().isObjcClassPointer(ns_ptr)); // *NSCopying where NSCopying is a registered Obj-C *protocol* → also true @@ -699,10 +699,10 @@ test "lower: isObjcClassPointer recognises pointer-to-foreign-Obj-C-class" { .foreign_path = "NSCopying", .runtime = .objc_protocol, .members = &.{}, - .is_foreign = true, + .is_reference = true, .is_main = false, }; - try lowering.program_index.foreign_class_map.put("NSCopying", &proto_fcd); + try lowering.program_index.runtime_class_map.put("NSCopying", &proto_fcd); try std.testing.expect(lowering.objc().isObjcClassPointer(proto_ptr)); // *Plain where Plain is a non-foreign struct → false. @@ -731,10 +731,10 @@ test "lower: objcPropertyKind defaults + explicit ARC modifiers" { .foreign_path = "NSString", .runtime = .objc_class, .members = &.{}, - .is_foreign = true, + .is_reference = true, .is_main = false, }; - try lowering.program_index.foreign_class_map.put("NSString", &ns_fcd); + try lowering.program_index.runtime_class_map.put("NSString", &ns_fcd); // Primitive field, no modifiers → assign (the non-object default). const prim = ast.RuntimeFieldDecl{ .name = "count", .field_type = typeKeyword(alloc, "i32"), .is_property = true }; @@ -756,10 +756,10 @@ test "lower: objcPropertyKind defaults + explicit ARC modifiers" { .foreign_path = "NSCoding", .runtime = .objc_protocol, .members = &.{}, - .is_foreign = true, + .is_reference = true, .is_main = false, }; - try lowering.program_index.foreign_class_map.put("NSCoding", &proto_fcd); + try lowering.program_index.runtime_class_map.put("NSCoding", &proto_fcd); const proto_ty = typeKeyword(alloc, "*NSCoding"); defer alloc.destroy(proto_ty); const proto_default = ast.RuntimeFieldDecl{ .name = "coder", .field_type = proto_ty, .is_property = true }; diff --git a/src/ir/lower.zig b/src/ir/lower.zig index 86da672..7cf99ed 100644 --- a/src/ir/lower.zig +++ b/src/ir/lower.zig @@ -275,8 +275,8 @@ pub const Lowering = struct { trace_clear_fid: ?FuncId = null, // extern `sx_trace_clear` needs_trace_runtime: bool = false, // set when lowering emits a trace push/clear; signals Compilation to auto-link sx_trace.c chain_fail_target: ?ChainFailTarget = null, // ERR E2.4: when set, a failable `or` chain routes its TOTAL failure here (an absorbing consumer like `catch`) instead of propagating to the function - current_foreign_class: ?*const ast.RuntimeClassDecl = null, // set while lowering a `#jni_main` (or any sx-defined `#jni_class`) bodied method — `super.method(args)` dispatch resolves the parent class against this fcd's `#extends` - current_foreign_method: ?ast.RuntimeMethodDecl = null, // the specific method whose body is being lowered; `super.(...)` reuses its signature + current_runtime_class: ?*const ast.RuntimeClassDecl = null, // set while lowering a `#jni_main` (or any sx-defined `#jni_class`) bodied method — `super.method(args)` dispatch resolves the parent class against this fcd's `#extends` + current_runtime_method: ?ast.RuntimeMethodDecl = null, // the specific method whose body is being lowered; `super.(...)` reuses its signature type_bindings: ?std.StringHashMap(TypeId) = null, // generic type param bindings ($T → concrete TypeId) current_match_tags: ?[]const u64 = null, // type tags for current match arm (for runtime dispatch) force_block_value: bool = false, // set by lowerBlockValue to extract if-else values @@ -844,9 +844,9 @@ pub const Lowering = struct { // lowerFieldAccess to go through the `__sx_state` ivar // (object_getIvar + struct_gep) when needed — see M1.2 A.3. if (node.data == .type_expr and std.mem.eql(u8, node.data.type_expr.name, "Self")) { - if (self.current_foreign_class) |fcd| { + if (self.current_runtime_class) |fcd| { if (fcd.runtime == .objc_class or fcd.runtime == .objc_protocol) { - return self.foreignClassStructType(fcd); + return self.runtimeClassStructType(fcd); } } } @@ -1770,15 +1770,15 @@ pub const Lowering = struct { pub const getSelRegisterNameFid = lower_ffi.getSelRegisterNameFid; pub const lowerFfiIntrinsicCall = lower_ffi.lowerFfiIntrinsicCall; pub const lowerJniCall = lower_ffi.lowerJniCall; - pub const lowerForeignMethodCall = lower_ffi.lowerForeignMethodCall; - pub const resolveForeignClassMemberType = lower_ffi.resolveForeignClassMemberType; - pub const resolveForeignMethodReturnType = lower_ffi.resolveForeignMethodReturnType; - pub const foreignClassStructType = lower_ffi.foreignClassStructType; + pub const lowerRuntimeMethodCall = lower_ffi.lowerRuntimeMethodCall; + pub const resolveRuntimeClassMemberType = lower_ffi.resolveRuntimeClassMemberType; + pub const resolveRuntimeMethodReturnType = lower_ffi.resolveRuntimeMethodReturnType; + pub const runtimeClassStructType = lower_ffi.runtimeClassStructType; pub const lowerObjcMethodCall = lower_ffi.lowerObjcMethodCall; pub const lowerObjcStaticCall = lower_ffi.lowerObjcStaticCall; - pub const lowerForeignStaticCall = lower_ffi.lowerForeignStaticCall; + pub const lowerRuntimeStaticCall = lower_ffi.lowerRuntimeStaticCall; pub const lowerSuperCall = lower_ffi.lowerSuperCall; - pub const registerForeignClassDecl = lower_ffi.registerForeignClassDecl; + pub const registerRuntimeClassDecl = lower_ffi.registerRuntimeClassDecl; pub const resolveObjcParentName = lower_ffi.resolveObjcParentName; pub const declareObjcDefinedStateIvarGlobal = lower_ffi.declareObjcDefinedStateIvarGlobal; pub const declareObjcDefinedClassGlobal = lower_ffi.declareObjcDefinedClassGlobal; @@ -1786,15 +1786,15 @@ pub const Lowering = struct { pub const synthesizeFnDeclFromObjcMethod = lower_ffi.synthesizeFnDeclFromObjcMethod; pub const lookupObjcDefinedClassForMethod = lower_ffi.lookupObjcDefinedClassForMethod; pub const getJniEnvTlFids = lower_ffi.getJniEnvTlFids; - pub const registerNamespacedForeignClasses = lower_ffi.registerNamespacedForeignClasses; + pub const registerNamespacedRuntimeClasses = lower_ffi.registerNamespacedRuntimeClasses; pub const synthesizeJniMainStubs = lower_ffi.synthesizeJniMainStubs; pub const synthesizeJniMainStub = lower_ffi.synthesizeJniMainStub; // --- moved to lower/objc_class.zig (lower_objc_class) --- pub const lowerObjcDefinedClassMethods = lower_objc_class.lowerObjcDefinedClassMethods; pub const lookupObjcPropertyOnPointer = lower_objc_class.lookupObjcPropertyOnPointer; - pub const findForeignMethodInChain = lower_objc_class.findForeignMethodInChain; - pub const findForeignPropertyInChain = lower_objc_class.findForeignPropertyInChain; + pub const findRuntimeMethodInChain = lower_objc_class.findRuntimeMethodInChain; + pub const findRuntimePropertyInChain = lower_objc_class.findRuntimePropertyInChain; pub const lookupObjcDefinedStateFieldOnPointer = lower_objc_class.lookupObjcDefinedStateFieldOnPointer; pub const lowerObjcDefinedStateFieldRead = lower_objc_class.lowerObjcDefinedStateFieldRead; pub const lowerObjcDefinedStateForObj = lower_objc_class.lowerObjcDefinedStateForObj; diff --git a/src/ir/lower/call.zig b/src/ir/lower/call.zig index df48a96..ec79f3c 100644 --- a/src/ir/lower/call.zig +++ b/src/ir/lower/call.zig @@ -610,10 +610,10 @@ pub fn lowerCall(self: *Lowering, c_in: *const ast.Call) Ref { // NewObject. Falls through to existing paths when no match. if (fa.object.data == .identifier) { const alias = fa.object.data.identifier.name; - if (self.program_index.foreign_class_map.get(alias)) |fcd| { + if (self.program_index.runtime_class_map.get(alias)) |fcd| { for (fcd.members) |m| switch (m) { .method => |md| if (md.is_static and std.mem.eql(u8, md.name, fa.field)) { - return self.lowerForeignStaticCall(fcd, md, args.items, c.callee.span); + return self.lowerRuntimeStaticCall(fcd, md, args.items, c.callee.span); }, else => {}, }; @@ -896,9 +896,9 @@ pub fn lowerCall(self: *Lowering, c_in: *const ast.Call) Ref { // (or its parallel forms). Routes to the JNI dispatch // shape, descriptor derived from the sx signature. const struct_name = self.getStructTypeName(obj_ty); - if (struct_name) |sname_for_foreign| { - if (self.program_index.foreign_class_map.get(sname_for_foreign)) |fcd| { - return self.lowerForeignMethodCall(fcd, fa.field, obj, args.items, c.callee.span); + if (struct_name) |sname_for_runtime| { + if (self.program_index.runtime_class_map.get(sname_for_runtime)) |fcd| { + return self.lowerRuntimeMethodCall(fcd, fa.field, obj, args.items, c.callee.span); } } @@ -2237,17 +2237,17 @@ pub fn resolveCallParamTypes(self: *Lowering, c: *const ast.Call, sel_author: ?* } if (self.getStructTypeName(obj_ty)) |sname| { // Foreign-class receiver (`#objc_class` / `#jni_class` / etc.): - // resolve the method from `foreign_class_map` walking `#extends`. + // resolve the method from `runtime_class_map` walking `#extends`. // Without this path, `target_type` for each arg falls back to // whatever `self.target_type` was on entry — typically the // enclosing fn's return type — which silently truncates `xx ptr` // casts inside e.g. a `BOOL`-returning method body. - if (self.program_index.foreign_class_map.get(sname)) |fcd| { - if (self.findForeignMethodInChain(fcd, fa.field)) |found| { + if (self.program_index.runtime_class_map.get(sname)) |fcd| { + if (self.findRuntimeMethodInChain(fcd, fa.field)) |found| { const md = found.method; - const saved_fc = self.current_foreign_class; - defer self.current_foreign_class = saved_fc; - self.current_foreign_class = found.fcd; + const saved_fc = self.current_runtime_class; + defer self.current_runtime_class = saved_fc; + self.current_runtime_class = found.fcd; const user_param_start: usize = if (md.is_static) 0 else 1; if (md.params.len > user_param_start) { var types_list = std.ArrayList(TypeId).empty; diff --git a/src/ir/lower/decl.zig b/src/ir/lower/decl.zig index 1e1cc4d..9ef55c0 100644 --- a/src/ir/lower/decl.zig +++ b/src/ir/lower/decl.zig @@ -204,10 +204,10 @@ pub fn checkRequiredEntryPoints(self: *Lowering) void { const tc = self.target_config orelse return; if (!tc.isAndroid()) return; - var it = self.program_index.foreign_class_map.iterator(); + var it = self.program_index.runtime_class_map.iterator(); while (it.next()) |entry| { const fcd = entry.value_ptr.*; - if (fcd.is_main and !fcd.is_foreign and fcd.runtime == .jni_class) return; + if (fcd.is_main and !fcd.is_reference and fcd.runtime == .jni_class) return; } if (self.diagnostics) |diags| { @@ -341,11 +341,11 @@ pub fn lowerDecls(self: *Lowering, decls: []const *const Node) void { .impl_block => { self.protocolResolver().registerImplBlock(&decl.data.impl_block, is_imported, decl); }, - .foreign_class_decl => { - self.registerForeignClassDecl(&decl.data.foreign_class_decl); + .runtime_class_decl => { + self.registerRuntimeClassDecl(&decl.data.runtime_class_decl); }, .namespace_decl => |ns| { - self.registerNamespacedForeignClasses(ns); + self.registerNamespacedRuntimeClasses(ns); if (self.main_file != null) { self.registerNamespaceQualifiedFns(ns.name, ns.own_decls); self.lowerDecls(ns.decls); @@ -769,11 +769,11 @@ pub fn scanDecls(self: *Lowering, decls: []const *const Node) void { .impl_block => { self.protocolResolver().registerImplBlock(&decl.data.impl_block, is_imported, decl); }, - .foreign_class_decl => { - self.registerForeignClassDecl(&decl.data.foreign_class_decl); + .runtime_class_decl => { + self.registerRuntimeClassDecl(&decl.data.runtime_class_decl); }, .namespace_decl => |ns| { - self.registerNamespacedForeignClasses(ns); + self.registerNamespacedRuntimeClasses(ns); if (self.main_file != null) { self.scanDecls(ns.decls); self.registerNamespaceQualifiedFns(ns.name, ns.own_decls); @@ -1746,7 +1746,7 @@ pub fn selectNominalLeaf(self: *Lowering, name: []const u8, from: []const u8, ra /// it is recognised via `type_aliases_by_source` separately from named types. pub fn isNamedTypeKind(raw: resolver_mod.RawDeclRef) bool { return switch (raw) { - .struct_decl, .enum_decl, .union_decl, .error_set_decl, .protocol_decl, .foreign_class_decl => true, + .struct_decl, .enum_decl, .union_decl, .error_set_decl, .protocol_decl, .runtime_class_decl => true, .fn_decl, .const_decl, .var_decl, .namespace_decl => false, }; } @@ -1774,7 +1774,7 @@ pub fn namedRefTid(self: *Lowering, ref: resolver_mod.RawDeclRef, name: []const .struct_decl => |d| (table.type_decl_tids.get(@ptrCast(d)) orelse table.findByName(table.internString(name))), .enum_decl => |d| (table.type_decl_tids.get(@ptrCast(d)) orelse table.findByName(table.internString(name))), .union_decl => |d| (table.type_decl_tids.get(@ptrCast(d)) orelse table.findByName(table.internString(name))), - .error_set_decl, .protocol_decl, .foreign_class_decl => table.findByName(table.internString(name)), + .error_set_decl, .protocol_decl, .runtime_class_decl => table.findByName(table.internString(name)), .fn_decl, .const_decl, .var_decl, .namespace_decl => null, }; } @@ -2288,15 +2288,15 @@ pub fn lazyLowerFunction(self: *Lowering, name: []const u8) void { // Already lowered? if (self.lowered_functions.contains(name)) return; - // For sx-defined `#objc_class` methods, pin current_foreign_class + // For sx-defined `#objc_class` methods, pin current_runtime_class // so `*Self` substitutions in resolveTypeWithBindings find the // state-struct type (M1.2 A.2b). The inline body-lowering path // below re-resolves param types, so the context must be set // BEFORE any resolveReturnType / resolveParamType call. - const saved_fc_lazy = self.current_foreign_class; - defer self.current_foreign_class = saved_fc_lazy; + const saved_fc_lazy = self.current_runtime_class; + defer self.current_runtime_class = saved_fc_lazy; if (self.lookupObjcDefinedClassForMethod(name)) |fcd| { - self.current_foreign_class = fcd; + self.current_runtime_class = fcd; } // No AST? (builtins, foreign functions, or imported functions not in this file) const fd = self.program_index.fn_ast_map.get(name) orelse return; @@ -2381,10 +2381,10 @@ pub fn lazyLowerFunction(self: *Lowering, name: []const u8) void { pub fn lowerFunctionBodyInto(self: *Lowering, fd: *const ast.FnDecl, fid: FuncId, name: []const u8) void { // objc-defined-class method context for `*Self` substitution (M1.2 A.2b); // the resolveReturnType / resolveParamType calls below consult it. - const saved_fc = self.current_foreign_class; - defer self.current_foreign_class = saved_fc; + const saved_fc = self.current_runtime_class; + defer self.current_runtime_class = saved_fc; if (self.lookupObjcDefinedClassForMethod(name)) |fcd| { - self.current_foreign_class = fcd; + self.current_runtime_class = fcd; } var reentry = FnBodyReentry.enter(self); @@ -2477,13 +2477,13 @@ pub fn lowerFunctionBodyInto(self: *Lowering, fd: *const ast.FnDecl, fid: FuncId /// Lower a single function declaration. pub fn lowerFunction(self: *Lowering, fd: *const ast.FnDecl, name: []const u8, is_imported: bool) void { // For sx-defined `#objc_class` methods (qualified `.`), - // set `current_foreign_class` so `*Self` substitutions through + // set `current_runtime_class` so `*Self` substitutions through // `resolveTypeWithBindings` find the state-struct type (M1.2 A.2b). // Save+restore — function lowering can re-enter. - const saved_fc = self.current_foreign_class; - defer self.current_foreign_class = saved_fc; + const saved_fc = self.current_runtime_class; + defer self.current_runtime_class = saved_fc; if (self.lookupObjcDefinedClassForMethod(name)) |fcd| { - self.current_foreign_class = fcd; + self.current_runtime_class = fcd; } const name_id = self.module.types.internString(name); diff --git a/src/ir/lower/ffi.zig b/src/ir/lower/ffi.zig index 20d29c2..a70dee8 100644 --- a/src/ir/lower/ffi.zig +++ b/src/ir/lower/ffi.zig @@ -233,7 +233,7 @@ pub fn lowerJniCall(self: *Lowering, fic: *const ast.FfiIntrinsicCall) Ref { /// 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 /// Phase 3/4 and currently surface a clear diagnostic. -pub fn lowerForeignMethodCall( +pub fn lowerRuntimeMethodCall( self: *Lowering, fcd: *const ast.RuntimeClassDecl, method_name: []const u8, @@ -250,7 +250,7 @@ pub fn lowerForeignMethodCall( // still used for `*Self` substitution at the dispatch site // — the inherited method's *Self should resolve to the // child receiver, not the parent. - const found = self.findForeignMethodInChain(fcd, method_name) orelse { + 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 }); } @@ -270,7 +270,7 @@ pub fn lowerForeignMethodCall( if (fcd.runtime == .objc_class or fcd.runtime == .objc_protocol) { return self.lowerObjcMethodCall(fcd, method, target, method_args, span); } - if (!fcd.is_foreign) { + if (!fcd.is_reference) { if (self.diagnostics) |d| { d.addFmt(.err, span, "sx-defined classes on non-Obj-C runtimes can't yet be dispatched into (class '{s}', runtime '{s}')", .{ fcd.name, @tagName(fcd.runtime) }); } @@ -295,7 +295,7 @@ pub fn lowerForeignMethodCall( // resolve `*Foo` cross-class refs to their foreign paths. var registry = jni_descriptor.ClassRegistry.init(self.alloc); defer registry.deinit(); - var it = self.program_index.foreign_class_map.iterator(); + var it = self.program_index.runtime_class_map.iterator(); while (it.next()) |entry| { registry.put(entry.key_ptr.*, entry.value_ptr.*.foreign_path) catch {}; } @@ -357,33 +357,33 @@ pub fn lowerForeignMethodCall( /// with the foreign 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 resolveForeignClassMemberType( +pub fn resolveRuntimeClassMemberType( self: *Lowering, fcd: *const ast.RuntimeClassDecl, type_node: *const ast.Node, ) TypeId { if (type_node.data == .type_expr and std.mem.eql(u8, type_node.data.type_expr.name, "Self")) { - return self.foreignClassStructType(fcd); + return self.runtimeClassStructType(fcd); } if (type_node.data == .pointer_type_expr) { const pt = type_node.data.pointer_type_expr; if (pt.pointee_type.data == .type_expr and std.mem.eql(u8, pt.pointee_type.data.type_expr.name, "Self")) { - return self.module.types.ptrTo(self.foreignClassStructType(fcd)); + return self.module.types.ptrTo(self.runtimeClassStructType(fcd)); } } return self.resolveType(type_node); } -pub fn resolveForeignMethodReturnType( +pub fn resolveRuntimeMethodReturnType( self: *Lowering, fcd: *const ast.RuntimeClassDecl, method: ast.RuntimeMethodDecl, ) TypeId { const rt = method.return_type orelse return .void; - return self.resolveForeignClassMemberType(fcd, rt); + return self.resolveRuntimeClassMemberType(fcd, rt); } -pub fn foreignClassStructType(self: *Lowering, fcd: *const ast.RuntimeClassDecl) TypeId { +pub fn runtimeClassStructType(self: *Lowering, fcd: *const ast.RuntimeClassDecl) TypeId { const name_id = self.module.types.internString(fcd.name); if (self.module.types.findByName(name_id)) |existing| return existing; return self.module.types.intern(.{ .@"struct" = .{ .name = name_id, .fields = &.{} } }); @@ -434,7 +434,7 @@ pub fn lowerObjcMethodCall( } } - const ret_ty = self.resolveForeignMethodReturnType(fcd, method); + const ret_ty = self.resolveRuntimeMethodReturnType(fcd, method); // Cache the SEL slot per (selector-string, module) like // `#objc_call` does. The mangling produces the literal selector @@ -489,7 +489,7 @@ pub fn lowerObjcStaticCall( } } - const ret_ty = self.resolveForeignMethodReturnType(fcd, method); + const ret_ty = self.resolveRuntimeMethodReturnType(fcd, method); const vptr_ty = self.module.types.ptrTo(.void); @@ -505,7 +505,7 @@ pub fn lowerObjcStaticCall( // instead of going through `objc_msgSend` (which would land in the // +alloc IMP and use `__sx_default_context.allocator`). This honors // a surrounding `push Context.{ allocator = ... }`. - if (!fcd.is_foreign and + if (!fcd.is_reference and fcd.runtime == .objc_class and method_args.len == 0 and std.mem.eql(u8, method.name, "alloc")) @@ -568,7 +568,7 @@ pub fn lowerObjcStaticCall( /// user can use `#jni_static_call(T)(class, "name", sig, args...)` /// for those. Constructor is the common case for #jni_main bodies /// that need to instantiate Android classes (SurfaceView, etc.). -pub fn lowerForeignStaticCall( +pub fn lowerRuntimeStaticCall( self: *Lowering, fcd: *const ast.RuntimeClassDecl, method: ast.RuntimeMethodDecl, @@ -600,7 +600,7 @@ pub fn lowerForeignStaticCall( // Build class registry snapshot for `*Foo` cross-class refs. var registry = jni_descriptor.ClassRegistry.init(self.alloc); defer registry.deinit(); - var it = self.program_index.foreign_class_map.iterator(); + var it = self.program_index.runtime_class_map.iterator(); while (it.next()) |entry| { registry.put(entry.key_ptr.*, entry.value_ptr.*.foreign_path) catch {}; } @@ -679,7 +679,7 @@ pub fn lowerSuperCall( method_args: []const Ref, span: ast.Span, ) Ref { - const fcd = self.current_foreign_class orelse { + const fcd = self.current_runtime_class orelse { if (self.diagnostics) |d| d.addFmt(.err, span, "'super' is only valid inside a `#jni_class` method body", .{}); return Ref.none; }; @@ -689,7 +689,7 @@ pub fn lowerSuperCall( var parent_path: []const u8 = "android/app/Activity"; for (fcd.members) |m| switch (m) { .extends => |alias| { - if (self.program_index.foreign_class_map.get(alias)) |parent_fcd| { + if (self.program_index.runtime_class_map.get(alias)) |parent_fcd| { parent_path = parent_fcd.foreign_path; } else { parent_path = alias; @@ -704,14 +704,14 @@ pub fn lowerSuperCall( // the parent class to be declared via `#foreign #jni_class`. var descriptor: []const u8 = ""; var resolved_method: ?ast.RuntimeMethodDecl = null; - if (self.current_foreign_method) |em| { + if (self.current_runtime_method) |em| { if (std.mem.eql(u8, em.name, method_name)) { resolved_method = em; } } if (resolved_method == null) { const parent_fcd = blk: for (fcd.members) |m| switch (m) { - .extends => |alias| if (self.program_index.foreign_class_map.get(alias)) |pf| break :blk pf else continue, + .extends => |alias| if (self.program_index.runtime_class_map.get(alias)) |pf| break :blk pf else continue, else => {}, } else null; if (parent_fcd) |pf| { @@ -733,7 +733,7 @@ pub fn lowerSuperCall( // for `*Self` resolution). var registry = jni_descriptor.ClassRegistry.init(self.alloc); defer registry.deinit(); - var it = self.program_index.foreign_class_map.iterator(); + var it = self.program_index.runtime_class_map.iterator(); while (it.next()) |entry| { registry.put(entry.key_ptr.*, entry.value_ptr.*.foreign_path) catch {}; } @@ -781,7 +781,7 @@ pub fn lowerSuperCall( // ── Foreign-class registration ────────────────────────────────── /// Register a foreign-class declaration. The alias goes into -/// `foreign_class_map` for method-dispatch lookup. The underlying +/// `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). @@ -792,9 +792,9 @@ pub fn lowerSuperCall( /// under qualified names `.`. Lazy lowering /// then handles the body via the standard path; `*Self` is /// substituted to `*State` during body lowering (M1.2 A.2b). -pub fn registerForeignClassDecl(self: *Lowering, fcd: *const ast.RuntimeClassDecl) void { - self.program_index.foreign_class_map.put(fcd.name, fcd) catch {}; - if (!fcd.is_foreign and fcd.runtime == .objc_class) { +pub fn registerRuntimeClassDecl(self: *Lowering, fcd: *const ast.RuntimeClassDecl) void { + self.program_index.runtime_class_map.put(fcd.name, fcd) catch {}; + if (!fcd.is_reference and fcd.runtime == .objc_class) { if (self.module.lookupObjcDefinedClass(fcd.name) == null) { self.module.appendObjcDefinedClass(fcd.name, fcd); // M2.3 — resolve the `#extends` alias to the actual @@ -828,8 +828,8 @@ pub fn registerForeignClassDecl(self: *Lowering, fcd: *const ast.RuntimeClassDec pub fn resolveObjcParentName(self: *Lowering, fcd: *const ast.RuntimeClassDecl) []const u8 { for (fcd.members) |m| switch (m) { .extends => |alias| { - if (self.program_index.foreign_class_map.get(alias)) |parent_fcd| { - if (parent_fcd.is_foreign) return parent_fcd.foreign_path; + if (self.program_index.runtime_class_map.get(alias)) |parent_fcd| { + if (parent_fcd.is_reference) return parent_fcd.foreign_path; // Sx-defined parent — its alias IS its Obj-C name. return parent_fcd.name; } @@ -883,11 +883,11 @@ pub fn declareObjcDefinedClassGlobal(self: *Lowering, class_name: []const u8) vo /// (M1.2 A.4b.iii). Bodyless declarations are skipped — they /// reference inherited / external methods, not sx-side bodies. pub fn registerObjcDefinedClassMethods(self: *Lowering, fcd: *const ast.RuntimeClassDecl) void { - // Set current_foreign_class so `*Self` substitutions in + // Set current_runtime_class so `*Self` substitutions in // declareFunction's type resolution find the state struct. - const saved = self.current_foreign_class; - self.current_foreign_class = fcd; - defer self.current_foreign_class = saved; + const saved = self.current_runtime_class; + self.current_runtime_class = fcd; + defer self.current_runtime_class = saved; var method_infos = std.ArrayList(Module.ObjcDefinedMethodEntry).empty; @@ -969,7 +969,7 @@ pub fn synthesizeFnDeclFromObjcMethod(self: *Lowering, method: ast.RuntimeMethod /// If `name` matches an sx-defined `#objc_class`'s qualified-method /// pattern (`.`), return the class's /// RuntimeClassDecl. Used by `lowerFunction` to set -/// `current_foreign_class` so `*Self` resolves to the state struct +/// `current_runtime_class` so `*Self` resolves to the state struct /// during body lowering. pub fn lookupObjcDefinedClassForMethod(self: *Lowering, name: []const u8) ?*const ast.RuntimeClassDecl { const dot = std.mem.indexOf(u8, name, ".") orelse return null; @@ -1013,15 +1013,15 @@ pub fn getJniEnvTlFids(self: *Lowering) struct { get: FuncId, set: FuncId } { /// scan/lower already handles bare-name registration; this only adds the /// qualified-name entry, so cross-class refs in method signatures /// (`*View` → bare lookup) still work. -pub fn registerNamespacedForeignClasses(self: *Lowering, ns: ast.NamespaceDecl) void { +pub fn registerNamespacedRuntimeClasses(self: *Lowering, ns: ast.NamespaceDecl) void { for (ns.decls) |inner| { - if (inner.data == .foreign_class_decl) { - const fcd = &inner.data.foreign_class_decl; + if (inner.data == .runtime_class_decl) { + const fcd = &inner.data.runtime_class_decl; const qualified = std.fmt.allocPrint(self.alloc, "{s}.{s}", .{ ns.name, fcd.name }) catch fcd.name; - self.program_index.foreign_class_map.put(qualified, fcd) catch {}; + self.program_index.runtime_class_map.put(qualified, fcd) catch {}; } else if (inner.data == .namespace_decl) { // Nested namespaces — qualify with both prefixes. - self.registerNamespacedForeignClasses(inner.data.namespace_decl); + self.registerNamespacedRuntimeClasses(inner.data.namespace_decl); } } } @@ -1033,11 +1033,11 @@ pub fn synthesizeJniMainStubs(self: *Lowering) void { var seen = std.StringHashMap(void).init(self.alloc); defer seen.deinit(); - var it = self.program_index.foreign_class_map.iterator(); + var it = self.program_index.runtime_class_map.iterator(); while (it.next()) |entry| { const fcd = entry.value_ptr.*; if (!fcd.is_main) continue; - if (fcd.is_foreign) continue; + if (fcd.is_reference) continue; if (fcd.runtime != .jni_class) continue; if (seen.contains(fcd.foreign_path)) continue; seen.put(fcd.foreign_path, {}) catch continue; @@ -1121,13 +1121,13 @@ pub fn synthesizeJniMainStub(self: *Lowering, fcd: *const ast.RuntimeClassDecl, // Record method context so `super.method(args)` inside the body // can find the parent class (via `#extends`) and the method's // signature. - const saved_fcd = self.current_foreign_class; - const saved_method = self.current_foreign_method; - self.current_foreign_class = fcd; - self.current_foreign_method = md; + const saved_fcd = self.current_runtime_class; + const saved_method = self.current_runtime_method; + self.current_runtime_class = fcd; + self.current_runtime_method = md; defer { - self.current_foreign_class = saved_fcd; - self.current_foreign_method = saved_method; + self.current_runtime_class = saved_fcd; + self.current_runtime_method = saved_method; } // JNI native methods are C-callable entry points — install the diff --git a/src/ir/lower/nominal.zig b/src/ir/lower/nominal.zig index c7e60b4..77f4f51 100644 --- a/src/ir/lower/nominal.zig +++ b/src/ir/lower/nominal.zig @@ -296,7 +296,7 @@ pub fn rawNamedTypePtr(ref: resolver_mod.RawDeclRef) ?*const anyopaque { .union_decl => |d| @ptrCast(d), .error_set_decl => |d| @ptrCast(d), .protocol_decl => |d| @ptrCast(d), - .foreign_class_decl => |d| @ptrCast(d), + .runtime_class_decl => |d| @ptrCast(d), .fn_decl, .const_decl, .var_decl, .namespace_decl => null, }; } diff --git a/src/ir/lower/objc_class.zig b/src/ir/lower/objc_class.zig index 24856c7..bc45b80 100644 --- a/src/ir/lower/objc_class.zig +++ b/src/ir/lower/objc_class.zig @@ -30,7 +30,7 @@ const Lowering = lower.Lowering; /// `#objc_class`. The Obj-C runtime invokes these via the IMP /// pointers wired up in M1.2 A.4 — no sx-side call path triggers /// lazy lowering, so we walk the cache and force-lower here. -/// `lowerFunction` sets `current_foreign_class` automatically based +/// `lowerFunction` sets `current_runtime_class` automatically based /// on the qualified name, so `*Self` substitutions in the body /// resolve correctly (M1.2 A.2b). After the bodies are lowered, /// `emitObjcDefinedClassImps` wraps each with a C-ABI trampoline @@ -65,16 +65,16 @@ pub fn lookupObjcPropertyOnPointer(self: *Lowering, obj_expr: *const ast.Node, f const pointee_info = self.module.types.get(ptr_info.pointer.pointee); if (pointee_info != .@"struct") return null; const struct_name = self.module.types.getString(pointee_info.@"struct".name); - const fcd = self.program_index.foreign_class_map.get(struct_name) orelse return null; + const fcd = self.program_index.runtime_class_map.get(struct_name) orelse return null; if (fcd.runtime != .objc_class and fcd.runtime != .objc_protocol) return null; - return self.findForeignPropertyInChain(fcd, field_name); + return self.findRuntimePropertyInChain(fcd, field_name); } /// Walk the `#extends` chain looking for a method by name. M2.3. /// Returns the owning fcd + the method decl, or null if no ancestor /// declares it. Depth-capped at 16 to break accidental cycles /// (real Obj-C class chains rarely exceed 6 levels). -pub fn findForeignMethodInChain(self: *Lowering, fcd: *const ast.RuntimeClassDecl, method_name: []const u8) ?struct { fcd: *const ast.RuntimeClassDecl, method: ast.RuntimeMethodDecl } { +pub fn findRuntimeMethodInChain(self: *Lowering, fcd: *const ast.RuntimeClassDecl, method_name: []const u8) ?struct { fcd: *const ast.RuntimeClassDecl, method: ast.RuntimeMethodDecl } { var current: *const ast.RuntimeClassDecl = fcd; var depth: u32 = 0; while (depth < 16) : (depth += 1) { @@ -90,14 +90,14 @@ pub fn findForeignMethodInChain(self: *Lowering, fcd: *const ast.RuntimeClassDec }; break :blk null; } orelse return null; - current = self.program_index.foreign_class_map.get(parent) orelse return null; + current = self.program_index.runtime_class_map.get(parent) orelse return null; } return null; } /// Walk the `#extends` chain looking for a `#property` field by -/// name. M2.3 companion to findForeignMethodInChain. -pub fn findForeignPropertyInChain(self: *Lowering, fcd: *const ast.RuntimeClassDecl, field_name: []const u8) ?ast.RuntimeFieldDecl { +/// name. M2.3 companion to findRuntimeMethodInChain. +pub fn findRuntimePropertyInChain(self: *Lowering, fcd: *const ast.RuntimeClassDecl, field_name: []const u8) ?ast.RuntimeFieldDecl { var current: *const ast.RuntimeClassDecl = fcd; var depth: u32 = 0; while (depth < 16) : (depth += 1) { @@ -112,7 +112,7 @@ pub fn findForeignPropertyInChain(self: *Lowering, fcd: *const ast.RuntimeClassD }; break :blk null; } orelse return null; - current = self.program_index.foreign_class_map.get(parent) orelse return null; + current = self.program_index.runtime_class_map.get(parent) orelse return null; } return null; } @@ -136,10 +136,10 @@ pub fn lookupObjcDefinedStateFieldOnPointer(self: *Lowering, obj_expr: *const as const pointee_info = self.module.types.get(ptr_info.pointer.pointee); if (pointee_info != .@"struct") return null; const struct_name = self.module.types.getString(pointee_info.@"struct".name); - const fcd = self.program_index.foreign_class_map.get(struct_name) orelse return null; + const fcd = self.program_index.runtime_class_map.get(struct_name) orelse return null; // Only sx-defined Obj-C classes have a state struct. Foreign // classes' fields are purely declaration metadata (no state). - if (fcd.is_foreign or fcd.runtime != .objc_class) return null; + if (fcd.is_reference or fcd.runtime != .objc_class) return null; // Skip property fields — those dispatch via the M2.2 getter/setter // path. Plain instance fields take the ivar+gep path. for (fcd.members) |m| switch (m) { @@ -694,11 +694,11 @@ pub fn emitObjcDefinedClassImp(self: *Lowering, fcd: *const ast.RuntimeClassDecl params.append(self.alloc, .{ .name = self.module.types.internString("obj"), .ty = ptr_void }) catch return; params.append(self.alloc, .{ .name = self.module.types.internString("_cmd"), .ty = ptr_void }) catch return; - // Set current_foreign_class so *Self in user-param resolution + // Set current_runtime_class so *Self in user-param resolution // resolves to *State (M1.2 A.2b). Save+restore. - const saved_fc = self.current_foreign_class; - self.current_foreign_class = fcd; - defer self.current_foreign_class = saved_fc; + const saved_fc = self.current_runtime_class; + self.current_runtime_class = fcd; + defer self.current_runtime_class = saved_fc; const param_start: usize = 1; for (md.params[param_start..], 0..) |p_node, i| { @@ -971,12 +971,12 @@ pub fn emitObjcDefinedClassStaticImp(self: *Lowering, fcd: *const ast.RuntimeCla params.append(self.alloc, .{ .name = self.module.types.internString("cls"), .ty = ptr_void }) catch return; params.append(self.alloc, .{ .name = self.module.types.internString("_cmd"), .ty = ptr_void }) catch return; - // current_foreign_class lets `*Self` (if it appears in + // current_runtime_class lets `*Self` (if it appears in // user-arg types — rare for class methods) resolve to the // state-struct type. Save+restore. - const saved_fc = self.current_foreign_class; - self.current_foreign_class = fcd; - defer self.current_foreign_class = saved_fc; + const saved_fc = self.current_runtime_class; + self.current_runtime_class = fcd; + defer self.current_runtime_class = saved_fc; for (md.params, 0..) |p_node, i| { const pty = self.resolveType(p_node); diff --git a/src/ir/module.zig b/src/ir/module.zig index c8d3fb6..d2a6e67 100644 --- a/src/ir/module.zig +++ b/src/ir/module.zig @@ -79,7 +79,7 @@ pub const Module = struct { /// Pre-resolved Obj-C runtime name of the parent class, so /// emit_llvm can pass it to `objc_getClass(parent)` / /// `objc_allocateClassPair(super, ...)` without walking the - /// sx-side foreign_class_map (which lives in lower.zig). + /// sx-side runtime_class_map (which lives in lower.zig). /// Defaults to "NSObject" when no `#extends` member is present. parent_objc_name: []const u8 = "NSObject", }; diff --git a/src/ir/program_index.test.zig b/src/ir/program_index.test.zig index 3b3b197..b86d60e 100644 --- a/src/ir/program_index.test.zig +++ b/src/ir/program_index.test.zig @@ -67,17 +67,17 @@ test "ProgramIndex declaration maps round-trip (A1.1b)" { try idx.module_const_map.put("AF_INET", .{ .value = &blk, .ty = .i32 }); try std.testing.expect(idx.module_const_map.get("AF_INET").?.value == &blk); - // foreign_class_map: sx alias → RuntimeClassDecl. + // runtime_class_map: sx alias → RuntimeClassDecl. const fcd = ast.RuntimeClassDecl{ .name = "NSString", .foreign_path = "NSString", .runtime = .objc_class, .members = &.{}, - .is_foreign = true, + .is_reference = true, .is_main = false, }; - try idx.foreign_class_map.put("NSString", &fcd); - try std.testing.expect(idx.foreign_class_map.get("NSString").? == &fcd); + try idx.runtime_class_map.put("NSString", &fcd); + try std.testing.expect(idx.runtime_class_map.get("NSString").? == &fcd); // protocol_decl_map: protocol name → ProtocolDeclInfo. try idx.protocol_decl_map.put("Show", .{ .name = "Show", .is_inline = false, .methods = &.{} }); diff --git a/src/ir/program_index.zig b/src/ir/program_index.zig index 26c92a6..36e9674 100644 --- a/src/ir/program_index.zig +++ b/src/ir/program_index.zig @@ -665,7 +665,7 @@ pub const ProgramIndex = struct { /// resolve. Keyed/allocated with the lowering allocator. qualified_fn_source: std.StringHashMap([]const u8), /// sx alias → RuntimeClassDecl (jni_class / objc_class / swift_class / ... — registered in scan pass). - foreign_class_map: std.StringHashMap(*const ast.RuntimeClassDecl), + runtime_class_map: std.StringHashMap(*const ast.RuntimeClassDecl), /// `#run` global name → GlobalId. global_names: std.StringHashMap(GlobalInfo), /// Type alias name → target TypeId. The single-source alias table; passed @@ -708,7 +708,7 @@ pub const ProgramIndex = struct { .fn_ast_map = std.StringHashMap(*const ast.FnDecl).init(alloc), .qualified_fn_source = std.StringHashMap([]const u8).init(alloc), .global_names = std.StringHashMap(GlobalInfo).init(alloc), - .foreign_class_map = std.StringHashMap(*const ast.RuntimeClassDecl).init(alloc), + .runtime_class_map = std.StringHashMap(*const ast.RuntimeClassDecl).init(alloc), .type_alias_map = std.StringHashMap(TypeId).init(alloc), .struct_template_map = std.StringHashMap(StructTemplate).init(alloc), .struct_template_by_decl = std.AutoHashMap(imports.DeclId, StructTemplate).init(alloc), @@ -728,7 +728,7 @@ pub const ProgramIndex = struct { self.import_flags.deinit(); self.fn_ast_map.deinit(); self.qualified_fn_source.deinit(); - self.foreign_class_map.deinit(); + self.runtime_class_map.deinit(); self.global_names.deinit(); self.type_alias_map.deinit(); self.struct_template_map.deinit(); diff --git a/src/ir/resolver.zig b/src/ir/resolver.zig index f3f3a35..ae82231 100644 --- a/src/ir/resolver.zig +++ b/src/ir/resolver.zig @@ -121,7 +121,7 @@ pub const Domain = enum { generic_struct_head, type_fn_head, protocol_head, - foreign_class, + runtime_class, struct_const, namespace_member, ufcs, @@ -135,7 +135,7 @@ pub fn eligibleKind(domain: Domain, raw: RawDeclRef, field: ?[]const u8) bool { return switch (domain) { .bare_type => switch (raw) { .struct_decl, .enum_decl, .union_decl, .error_set_decl, - .protocol_decl, .foreign_class_decl => true, + .protocol_decl, .runtime_class_decl => true, else => false, }, .value_const => raw == .const_decl, @@ -143,7 +143,7 @@ pub fn eligibleKind(domain: Domain, raw: RawDeclRef, field: ?[]const u8) bool { .generic_struct_head => if (structDeclOf(raw)) |sd| sd.type_params.len > 0 else false, .type_fn_head => if (fnDeclOf(raw)) |fd| fd.type_params.len > 0 else false, .protocol_head => raw == .protocol_decl, - .foreign_class => raw == .foreign_class_decl, + .runtime_class => raw == .runtime_class_decl, .struct_const => structHasConstMember(raw, field orelse return false), .namespace_member => true, .ufcs => fnDeclOf(raw) != null, @@ -229,9 +229,9 @@ pub fn classifyHeadKind(raw: RawDeclRef, gs: *bool, tf: *bool, pr: *bool) void { /// True when the bare-type verdict selected a foreign-class author /// unambiguously. Used by lowering to route to the foreign-class path. -pub fn foreignClassWinsType(set: AuthorSet, verdict: Verdict) bool { +pub fn runtimeClassWinsType(set: AuthorSet, verdict: Verdict) bool { return switch (verdict) { - .own_wins => if (set.own) |a| std.meta.activeTag(a.raw) == .foreign_class_decl else false, + .own_wins => if (set.own) |a| std.meta.activeTag(a.raw) == .runtime_class_decl else false, .single => blk: { var selected: ?RawAuthor = null; for (set.flat) |a| { @@ -240,7 +240,7 @@ pub fn foreignClassWinsType(set: AuthorSet, verdict: Verdict) bool { selected = a; } const a = selected orelse break :blk false; - break :blk std.meta.activeTag(a.raw) == .foreign_class_decl; + break :blk std.meta.activeTag(a.raw) == .runtime_class_decl; }, .ambiguous, .not_visible, .domain_filtered => false, }; diff --git a/src/ir/semantic_diagnostics.zig b/src/ir/semantic_diagnostics.zig index 1c9d223..de425a8 100644 --- a/src/ir/semantic_diagnostics.zig +++ b/src/ir/semantic_diagnostics.zig @@ -211,7 +211,7 @@ pub const UnknownTypeChecker = struct { } } }, - .foreign_class_decl => |fcd| { + .runtime_class_decl => |fcd| { // The sx-side alias (left of `::`) is a user-chosen name, so a // reserved spelling is rejected like any other type decl (0089). self.checkDeclName(node, fcd.name, fcd.is_raw); @@ -394,7 +394,7 @@ pub const UnknownTypeChecker = struct { else => {}, } } - var it_fc = self.index.foreign_class_map.keyIterator(); + var it_fc = self.index.runtime_class_map.keyIterator(); while (it_fc.next()) |k| out.put(k.*, {}) catch {}; var it_tmpl = self.index.struct_template_map.keyIterator(); while (it_tmpl.next()) |k| out.put(k.*, {}) catch {}; diff --git a/src/parser.zig b/src/parser.zig index daf05b4..b9ae0af 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -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, } }); diff --git a/src/sema.zig b/src/sema.zig index d07e5d8..fa0d6da 100644 --- a/src/sema.zig +++ b/src/sema.zig @@ -1332,16 +1332,16 @@ pub const Analyzer = struct { } } }, - .foreign_class_decl => |fd| { + .runtime_class_decl => |fd| { try self.addSymbol(fd.name, .type_alias, null, node.span); - if (fd.is_foreign and fd.is_main) { + if (fd.is_reference and fd.is_main) { try self.diagnostics.append(self.allocator, .{ .level = .err, .message = "'#foreign' and '#jni_main' / '#objc_main' are mutually exclusive — a foreign-referenced class can't be the app's main entry", .span = node.span, }); } - if (fd.is_foreign) { + if (fd.is_reference) { for (fd.members) |m| switch (m) { .method => |md| if (md.body != null) { try self.diagnostics.append(self.allocator, .{ @@ -1784,7 +1784,7 @@ pub fn findNodeAtOffset(node: *Node, offset: u32) ?*Node { .tuple_type_expr, .ufcs_alias, .closure_type_expr, - .foreign_class_decl, + .runtime_class_decl, => {}, .jni_env_block => |eb| { if (findNodeAtOffset(eb.env, offset)) |found| return found;