ffi 2.2 green: parser collects #jni_class instance method body items
New `JniMethodDecl` AST struct (name, params, param_names, return_type — no body, foreign declaration). `JniClassDecl.body` becomes `methods: []const JniMethodDecl`. parseJniClassDecl loops over body items, parsing each `name :: (self: *Self, args...) -> Ret;` similarly to parseProtocolDecl but requiring `;` (no body brace). `static`, fields, `#extends`, `#implements`, and the other six directive forms land in 2.3–2.7. Sema/lower still treat the decl as an opaque type alias — descriptor derivation arrives in 2.8+. 121/121 examples green.
This commit is contained in:
@@ -533,10 +533,17 @@ pub const ProtocolDecl = struct {
|
||||
type_params: []const StructTypeParam = &.{}, // for `protocol(Target: Type) { ... }`
|
||||
};
|
||||
|
||||
pub const JniMethodDecl = 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
|
||||
};
|
||||
|
||||
pub const JniClassDecl = struct {
|
||||
name: []const u8, // sx-side alias (left of `::`)
|
||||
java_path: []const u8, // directive arg, e.g. "java/path/Foo"
|
||||
body: []const *Node = &.{}, // body items (methods, fields, #extends, ...) — empty in 2.1
|
||||
methods: []const JniMethodDecl = &.{}, // instance methods (static/fields/extends land in later steps)
|
||||
};
|
||||
|
||||
pub const ImplBlock = struct {
|
||||
|
||||
@@ -1040,16 +1040,59 @@ pub const Parser = struct {
|
||||
try self.expect(.r_paren);
|
||||
|
||||
try self.expect(.l_brace);
|
||||
// Body items (methods, fields, #extends, #implements, ...) land in steps
|
||||
// 2.2 onward. Step 2.1 accepts only the empty body (opaque forward decl).
|
||||
if (self.current.tag != .r_brace) {
|
||||
return self.fail("non-empty `#jni_class` body not yet supported (Phase 2.1 accepts only the empty/opaque form)");
|
||||
|
||||
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.)
|
||||
if (self.current.tag != .identifier) {
|
||||
return self.fail("expected method name in '#jni_class' body");
|
||||
}
|
||||
const method_name = self.tokenSlice(self.current);
|
||||
self.advance();
|
||||
try self.expect(.colon_colon);
|
||||
try self.expect(.l_paren);
|
||||
|
||||
var param_types = std.ArrayList(*Node).empty;
|
||||
var param_names = std.ArrayList([]const u8).empty;
|
||||
while (self.current.tag != .r_paren and self.current.tag != .eof) {
|
||||
if (param_types.items.len > 0) {
|
||||
try self.expect(.comma);
|
||||
if (self.current.tag == .r_paren) break;
|
||||
}
|
||||
if (self.current.tag != .identifier and self.current.tag != .kw_Self) {
|
||||
return self.fail("expected parameter name in '#jni_class' method");
|
||||
}
|
||||
const pname = self.tokenSlice(self.current);
|
||||
self.advance();
|
||||
try self.expect(.colon);
|
||||
const ptype = try self.parseTypeExpr();
|
||||
try param_names.append(self.allocator, pname);
|
||||
try param_types.append(self.allocator, ptype);
|
||||
}
|
||||
try self.expect(.r_paren);
|
||||
|
||||
var return_type: ?*Node = null;
|
||||
if (self.current.tag == .arrow) {
|
||||
self.advance();
|
||||
return_type = try self.parseTypeExpr();
|
||||
}
|
||||
|
||||
try self.expect(.semicolon);
|
||||
|
||||
try methods.append(self.allocator, .{
|
||||
.name = method_name,
|
||||
.params = try param_types.toOwnedSlice(self.allocator),
|
||||
.param_names = try param_names.toOwnedSlice(self.allocator),
|
||||
.return_type = return_type,
|
||||
});
|
||||
}
|
||||
try self.expect(.r_brace);
|
||||
|
||||
return try self.createNode(start_pos, .{ .jni_class_decl = .{
|
||||
.name = name,
|
||||
.java_path = java_path,
|
||||
.methods = try methods.toOwnedSlice(self.allocator),
|
||||
} });
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
1
|
||||
0
|
||||
|
||||
@@ -1 +1 @@
|
||||
/Users/agra/projects/sx/examples/ffi-jni-class-02-method.sx:14:5: error: non-empty `#jni_class` body not yet supported (Phase 2.1 accepts only the empty/opaque form)
|
||||
parse-only ok
|
||||
|
||||
Reference in New Issue
Block a user