ffi 2.6 green: #jni_method_descriptor("(Sig)Ret") override

New `hash_jni_method_descriptor` lexer token + LSP keyword
classification. `JniMethodDecl` gains `desc_override: ?[]const u8`.
parseJniClassDecl accepts an optional `#jni_method_descriptor("...")`
clause between the return type and the terminating `;`, stashing the
literal as the override. Auto-derivation in Phase 2.8 will treat
this as the precedence override when present.

The 2.6 xfail commit (0ed4799) used the working name `#desc` in its
test file; this commit renames to `#jni_method_descriptor` for
parallel naming with the rest of the FFI directive set (`#jni_call`,
`#jni_class`, `#jni_env`, ...). Test snapshot flips xfail → green.

125/125 examples green.
This commit is contained in:
agra
2026-05-20 10:10:23 +03:00
parent 0ed4799f5f
commit 11021d800d
8 changed files with 29 additions and 10 deletions

View File

@@ -1,17 +1,17 @@
// Phase 2 step 2.6 (PLAN-FFI.md): xfail then green for the
// `#desc("(Sig)Ret")` per-method JNI-descriptor override.
// `#jni_method_descriptor("(Sig)Ret")` per-method JNI-descriptor
// override.
//
// The default descriptor is derived from sx types (Phase 2.8); `#desc`
// is the escape hatch when the auto-derived signature doesn't match
// (e.g., synthetic methods, ambiguous overloads, accessing JNI
// internals). It appears trailing the method's return type, before
// the terminating `;`. Today the parser expects `;` immediately after
// the return type and errors at the `#desc` token.
// The default descriptor is derived from sx types (Phase 2.8); this
// directive is the escape hatch when the auto-derived signature
// doesn't match (e.g., synthetic methods, ambiguous overloads,
// accessing JNI internals). It appears trailing the method's return
// type, before the terminating `;`.
#import "modules/std.sx";
Foo :: #jni_class("com/example/Foo") {
weirdMethod :: (self: *Self) -> s32 #desc("()I");
weirdMethod :: (self: *Self) -> s32 #jni_method_descriptor("()I");
}
main :: () -> s32 {

View File

@@ -539,6 +539,7 @@ pub const JniMethodDecl = struct {
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+
};
pub const JniFieldDecl = struct {

View File

@@ -85,6 +85,7 @@ pub const Lexer = struct {
.{ "#jni_class", Tag.hash_jni_class },
.{ "#extends", Tag.hash_extends },
.{ "#implements", Tag.hash_implements },
.{ "#jni_method_descriptor", Tag.hash_jni_method_descriptor },
};
inline for (directives) |d| {
const keyword = d[0];

View File

@@ -1501,6 +1501,7 @@ pub const Server = struct {
.hash_jni_class,
.hash_extends,
.hash_implements,
.hash_jni_method_descriptor,
=> ST.keyword,
.kw_f32, .kw_f64, .kw_Type, .kw_Self => ST.type_,

View File

@@ -1121,6 +1121,20 @@ pub const Parser = struct {
return_type = try self.parseTypeExpr();
}
// Optional `#jni_method_descriptor("(Sig)Ret")` — explicit JNI descriptor override.
var desc_override: ?[]const u8 = null;
if (self.current.tag == .hash_jni_method_descriptor) {
self.advance(); // skip `#jni_method_descriptor`
try self.expect(.l_paren);
if (self.current.tag != .string_literal) {
return self.fail("expected string literal JNI descriptor after '#jni_method_descriptor('");
}
const raw_desc = self.tokenSlice(self.current);
desc_override = raw_desc[1 .. raw_desc.len - 1];
self.advance();
try self.expect(.r_paren);
}
try self.expect(.semicolon);
try members.append(self.allocator, .{ .method = .{
@@ -1129,6 +1143,7 @@ pub const Parser = struct {
.param_names = try param_names.toOwnedSlice(self.allocator),
.return_type = return_type,
.is_static = is_static,
.desc_override = desc_override,
} });
}
try self.expect(.r_brace);

View File

@@ -118,6 +118,7 @@ pub const Tag = enum {
hash_jni_class, // Foo :: #jni_class("java/path/Foo") { ...body... }
hash_extends, // `#extends Alias;` inside a #jni_class / #objc_class body
hash_implements, // `#implements Alias;` inside a #jni_class / #objc_class body
hash_jni_method_descriptor, // `#jni_method_descriptor("(Sig)Ret")` per-method JNI descriptor override
triple_minus, // ---
// Special

View File

@@ -1 +1 @@
1
0

View File

@@ -1 +1 @@
/Users/agra/projects/sx/examples/ffi-jni-class-06-desc.sx:14:41: error: expected ';'
parse-only ok