ffi 2.16a green: parser + AST + sema for #jni_env(env) { body }
New `hash_jni_env` lexer token; `parsePrimary` dispatches to a small
`parseJniEnvBlock` that consumes `(env) { body }` and returns a new
`JniEnvBlock` AST node (env_expr + body block).
Sema's analyzeNode arm recurses into env + body inside a pushed
scope; findNodeAtOffset descends through both children for go-to-
definition.
Lowering treats it as a syntactic wrapper around the block: env is
evaluated for side effects, body lowers as a normal block. The TL
push/pop semantics (synthesizing the env stack so `#jni_call`'s env
arg can become optional) land in 2.16b.
`expectSemicolonAfter` recognises `jni_env_block` as block-form so
statement-position uses don't need a trailing `;` — matches `if` /
`while` / `for` / bare blocks.
Test runs through the block body and prints expected output; xfail
snapshot flips to green. 127/127 examples green.
This commit is contained in:
@@ -1558,6 +1558,7 @@ pub const Parser = struct {
|
||||
.while_expr => false,
|
||||
.for_expr => false,
|
||||
.block => false,
|
||||
.jni_env_block => false,
|
||||
else => true,
|
||||
};
|
||||
if (needs_semi) {
|
||||
@@ -2187,6 +2188,9 @@ pub const Parser = struct {
|
||||
.hash_objc_call, .hash_jni_call, .hash_jni_static_call => {
|
||||
return try self.parseFfiIntrinsicCall();
|
||||
},
|
||||
.hash_jni_env => {
|
||||
return try self.parseJniEnvBlock();
|
||||
},
|
||||
else => {
|
||||
return self.fail("unexpected token in expression");
|
||||
},
|
||||
@@ -2198,6 +2202,27 @@ pub const Parser = struct {
|
||||
/// `#jni_static_call(T)(class, "name", "(Sig)R", args...)`. The
|
||||
/// return type sits in the first parens; the actual call args
|
||||
/// follow in the second.
|
||||
fn parseJniEnvBlock(self: *Parser) anyerror!*Node {
|
||||
const start = self.current.loc.start;
|
||||
self.advance(); // skip `#jni_env`
|
||||
|
||||
try self.expect(.l_paren);
|
||||
const env_expr = try self.parseExpr();
|
||||
try self.expect(.r_paren);
|
||||
|
||||
// Body is a brace-delimited block. The `-> ?T` annotation for
|
||||
// exception bubbling lands with step 2.15 / 2.16 follow-ups.
|
||||
if (self.current.tag != .l_brace) {
|
||||
return self.fail("expected '{' after '#jni_env(env)'");
|
||||
}
|
||||
const body = try self.parseBlock();
|
||||
|
||||
return try self.createNode(start, .{ .jni_env_block = .{
|
||||
.env = env_expr,
|
||||
.body = body,
|
||||
} });
|
||||
}
|
||||
|
||||
fn parseFfiIntrinsicCall(self: *Parser) anyerror!*Node {
|
||||
const start = self.current.loc.start;
|
||||
const kind: ast.FfiIntrinsicKind = switch (self.current.tag) {
|
||||
|
||||
Reference in New Issue
Block a user