ffi 2.7 green: parser accepts all seven type-introducer directive forms

Six new lexer tokens (`hash_jni_interface`, `hash_objc_class`,
`hash_objc_protocol`, `hash_swift_class`, `hash_swift_struct`,
`hash_swift_protocol`) join the existing `hash_jni_class`. All seven
share the body grammar from Phases 2.1–2.6.

AST refactored: `JniClassDecl` → `ForeignClassDecl` with a
`runtime: ForeignRuntime` enum discriminator; `JniMethodDecl` →
`ForeignMethodDecl` (with `jni_descriptor_override` renamed for
clarity since it's JNI-only); `JniFieldDecl` → `ForeignFieldDecl`;
`JniClassMember` → `ForeignClassMember`. AST variant renamed
`jni_class_decl` → `foreign_class_decl`.

`parseForeignClassDecl` takes the runtime as a parameter; the
`parseConstBinding` dispatch table now maps each of the seven
directive tokens to its `ForeignRuntime` variant via
`foreignRuntimeForCurrent`. No codegen yet — Phase 3 picks up Obj-C
runtime, Phase 4 picks up Swift. Runtime-specific body items (fields,
descriptor override) are validated at sema time in later steps.

126/126 examples green.
This commit is contained in:
agra
2026-05-20 10:15:10 +03:00
parent dc3821aeb0
commit 5fd8e0fbbe
8 changed files with 73 additions and 29 deletions

View File

@@ -81,7 +81,7 @@ pub const Node = struct {
protocol_decl: ProtocolDecl,
impl_block: ImplBlock,
ffi_intrinsic_call: FfiIntrinsicCall,
jni_class_decl: JniClassDecl,
foreign_class_decl: ForeignClassDecl,
pub fn declName(self: Data) ?[]const u8 {
return switch (self) {
@@ -95,7 +95,7 @@ pub const Node = struct {
.ufcs_alias => |d| d.name,
.c_import_decl => |d| d.name,
.protocol_decl => |d| d.name,
.jni_class_decl => |d| d.name,
.foreign_class_decl => |d| d.name,
else => null,
};
}
@@ -533,31 +533,42 @@ pub const ProtocolDecl = struct {
type_params: []const StructTypeParam = &.{}, // for `protocol(Target: Type) { ... }`
};
pub const JniMethodDecl = struct {
pub const ForeignRuntime = enum {
jni_class,
jni_interface,
objc_class,
objc_protocol,
swift_class,
swift_struct,
swift_protocol,
};
pub const ForeignMethodDecl = struct {
name: []const u8,
params: []const *Node, // type_expr nodes — first is `*Self` for instance methods
param_names: []const []const u8,
return_type: ?*Node, // null = void
is_static: bool = false, // true for `static name :: ...`
desc_override: ?[]const u8 = null, // `#desc("(Sig)Ret")` — skips auto-derivation in 2.8+
jni_descriptor_override: ?[]const u8 = null, // `#jni_method_descriptor("(Sig)Ret")` — JNI runtime only
};
pub const JniFieldDecl = struct {
pub const ForeignFieldDecl = struct {
name: []const u8,
field_type: *Node, // type_expr node
};
pub const JniClassMember = union(enum) {
method: JniMethodDecl,
field: JniFieldDecl,
pub const ForeignClassMember = union(enum) {
method: ForeignMethodDecl,
field: ForeignFieldDecl, // JNI runtime only (sema-checked in later step)
extends: []const u8, // sx-side alias name (right of `#extends`)
implements: []const u8, // sx-side alias name (right of `#implements`)
};
pub const JniClassDecl = struct {
pub const ForeignClassDecl = struct {
name: []const u8, // sx-side alias (left of `::`)
java_path: []const u8, // directive arg, e.g. "java/path/Foo"
members: []const JniClassMember = &.{}, // methods, #extends, #implements (fields/#desc land in 2.5+)
foreign_path: []const u8, // directive arg: "java/path/Foo" / "NSString" / "Foundation.URL"
runtime: ForeignRuntime,
members: []const ForeignClassMember = &.{},
};
pub const ImplBlock = struct {