From a9a6d53dc07938c24385459f295f14f5914bacbe Mon Sep 17 00:00:00 2001 From: agra Date: Sun, 14 Jun 2026 15:08:18 +0300 Subject: [PATCH] =?UTF-8?q?feat(ffi-linkage):=20postfix=20extern/export=20?= =?UTF-8?q?on=20#objc=5Fclass=20aggregate=20(Phase=203.1)=20=E2=80=94=2013?= =?UTF-8?q?48=20green?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parser.zig | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/parser.zig b/src/parser.zig index 0934dad..7a51ae4 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -1406,6 +1406,23 @@ pub const Parser = struct { self.advance(); try self.expect(.r_paren); + // Phase 3 (FFI-linkage): optional postfix `extern` / `export` after the + // `#objc_class("X")` directive — the new spelling that replaces the prefix + // `#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 + // 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; + if (self.current.tag == .kw_extern) { + is_foreign_eff = true; + self.advance(); + } else if (self.current.tag == .kw_export) { + is_foreign_eff = false; + self.advance(); + } + try self.expect(.l_brace); var members = std.ArrayList(ast.ForeignClassMember).empty; @@ -1633,7 +1650,7 @@ pub const Parser = struct { .foreign_path = foreign_path, .runtime = runtime, .members = try members.toOwnedSlice(self.allocator), - .is_foreign = is_foreign, + .is_foreign = is_foreign_eff, .is_main = is_main, .is_raw = name_is_raw, } });