From ecce8cdca35d7947e89d10ade5aa777b06653a5a Mon Sep 17 00:00:00 2001 From: agra Date: Wed, 20 May 2026 09:35:09 +0300 Subject: [PATCH] ffi 2.3 green: `static` body items in `#jni_class` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `JniMethodDecl` gains `is_static: bool = false`. parseJniClassDecl's body loop now recognises a `static` identifier prefix (context-sensitive — `static` stays a plain identifier elsewhere) and consumes it before the method name, setting `is_static` on the resulting decl. Dispatch to `GetStaticMethodID` / `CallStatic*Method` arrives in Phase 2.12. 122/122 examples green. --- src/ast.zig | 1 + src/parser.zig | 16 ++++++++++++++-- tests/expected/ffi-jni-class-03-static.exit | 2 +- tests/expected/ffi-jni-class-03-static.txt | 2 +- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/ast.zig b/src/ast.zig index e0ebec1..d13f38a 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -538,6 +538,7 @@ pub const JniMethodDecl = struct { 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 :: ...` }; pub const JniClassDecl = struct { diff --git a/src/parser.zig b/src/parser.zig index 93f9309..2034301 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -1043,8 +1043,19 @@ pub const Parser = struct { var methods = std.ArrayList(ast.JniMethodDecl).empty; while (self.current.tag != .r_brace and self.current.tag != .eof) { - // Instance method: name :: (self: *Self, args...) -> Ret; - // (`static`, fields, #extends, #implements land in later steps.) + // Optional `static` prefix → class method (no implicit `self`). + // Context-sensitive — `static` is a plain identifier elsewhere. + var is_static = false; + if (self.current.tag == .identifier and + std.mem.eql(u8, self.tokenSlice(self.current), "static") and + self.peekNext() == .identifier) + { + is_static = true; + self.advance(); // consume `static` + } + + // Method: name :: (args...) -> Ret; + // (Fields, #extends, #implements land in later steps.) if (self.current.tag != .identifier) { return self.fail("expected method name in '#jni_class' body"); } @@ -1085,6 +1096,7 @@ pub const Parser = struct { .params = try param_types.toOwnedSlice(self.allocator), .param_names = try param_names.toOwnedSlice(self.allocator), .return_type = return_type, + .is_static = is_static, }); } try self.expect(.r_brace); diff --git a/tests/expected/ffi-jni-class-03-static.exit b/tests/expected/ffi-jni-class-03-static.exit index d00491f..573541a 100644 --- a/tests/expected/ffi-jni-class-03-static.exit +++ b/tests/expected/ffi-jni-class-03-static.exit @@ -1 +1 @@ -1 +0 diff --git a/tests/expected/ffi-jni-class-03-static.txt b/tests/expected/ffi-jni-class-03-static.txt index 8c068a4..2ef3b99 100644 --- a/tests/expected/ffi-jni-class-03-static.txt +++ b/tests/expected/ffi-jni-class-03-static.txt @@ -1 +1 @@ -/Users/agra/projects/sx/examples/ffi-jni-class-03-static.sx:13:12: error: expected '::' +parse-only ok