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:
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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_,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
1
|
||||
0
|
||||
|
||||
@@ -1 +1 @@
|
||||
/Users/agra/projects/sx/examples/ffi-jni-class-06-desc.sx:14:41: error: expected ';'
|
||||
parse-only ok
|
||||
|
||||
Reference in New Issue
Block a user