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:
10
src/sema.zig
10
src/sema.zig
@@ -910,6 +910,12 @@ pub const Analyzer = struct {
|
||||
.foreign_class_decl => |fd| {
|
||||
try self.addSymbol(fd.name, .type_alias, null, node.span);
|
||||
},
|
||||
.jni_env_block => |eb| {
|
||||
try self.analyzeNode(eb.env);
|
||||
try self.pushScope();
|
||||
try self.analyzeNode(eb.body);
|
||||
self.popScope();
|
||||
},
|
||||
.impl_block => |ib| {
|
||||
// Each impl block gets its own scope so methods don't conflict across impls
|
||||
try self.pushScope();
|
||||
@@ -1311,6 +1317,10 @@ pub fn findNodeAtOffset(node: *Node, offset: u32) ?*Node {
|
||||
.closure_type_expr,
|
||||
.foreign_class_decl,
|
||||
=> {},
|
||||
.jni_env_block => |eb| {
|
||||
if (findNodeAtOffset(eb.env, offset)) |found| return found;
|
||||
if (findNodeAtOffset(eb.body, offset)) |found| return found;
|
||||
},
|
||||
.struct_decl => |sd| {
|
||||
for (sd.methods) |method_node| {
|
||||
if (findNodeAtOffset(method_node, offset)) |found| return found;
|
||||
|
||||
Reference in New Issue
Block a user