feature. See also
. The project being documented here (as the example) is the Zig library itself.
AstGen.blockExprStmts
fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Node.Index, block_kind: BlockKind) !void
File
Code
fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Node.Index, block_kind: BlockKind) !void {
const astgen = gz.astgen;
const tree = astgen.tree;
if (statements.len == 0) return;
var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa);
defer block_arena.deinit();
const block_arena_allocator = block_arena.allocator();
var noreturn_src_node: Ast.Node.OptionalIndex = .none;
var scope = parent_scope;
for (statements, 0..) |statement, stmt_idx| {
if (noreturn_src_node.unwrap()) |src_node| {
try astgen.appendErrorNodeNotes(
statement,
"unreachable code",
.{},
&[_]u32{
try astgen.errNoteNode(
src_node,
"control flow is diverted here",
.{},
),
},
);
}
const allow_branch_hint = switch (block_kind) {
.normal => false,
.allow_branch_hint => stmt_idx == 0,
};
var inner_node = statement;
while (true) {
switch (tree.nodeTag(inner_node)) {
.global_var_decl,
.local_var_decl,
.simple_var_decl,
.aligned_var_decl, => scope = try varDecl(gz, scope, statement, block_arena_allocator, tree.fullVarDecl(statement).?),
.assign_destructure => scope = try assignDestructureMaybeDecls(gz, scope, statement, block_arena_allocator),
.@"defer" => scope = try deferStmt(gz, scope, statement, block_arena_allocator, .defer_normal),
.@"errdefer" => scope = try deferStmt(gz, scope, statement, block_arena_allocator, .defer_error),
.assign => try assign(gz, scope, statement),
.assign_shl => try assignShift(gz, scope, statement, .shl),
.assign_shr => try assignShift(gz, scope, statement, .shr),
.assign_bit_and => try assignOp(gz, scope, statement, .bit_and),
.assign_bit_or => try assignOp(gz, scope, statement, .bit_or),
.assign_bit_xor => try assignOp(gz, scope, statement, .xor),
.assign_div => try assignOp(gz, scope, statement, .div),
.assign_sub => try assignOp(gz, scope, statement, .sub),
.assign_sub_wrap => try assignOp(gz, scope, statement, .subwrap),
.assign_mod => try assignOp(gz, scope, statement, .mod_rem),
.assign_add => try assignOp(gz, scope, statement, .add),
.assign_add_wrap => try assignOp(gz, scope, statement, .addwrap),
.assign_mul => try assignOp(gz, scope, statement, .mul),
.assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
.grouped_expression => {
inner_node = tree.nodeData(inner_node).node_and_token[0];
continue;
},
.while_simple,
.while_cont,
.@"while", => _ = try whileExpr(gz, scope, .{ .rl = .none }, inner_node, tree.fullWhile(inner_node).?, true),
.for_simple,
.@"for", => _ = try forExpr(gz, scope, .{ .rl = .none }, inner_node, tree.fullFor(inner_node).?, true),
// These cases are here to allow branch hints.
.builtin_call_two,
.builtin_call_two_comma,
.builtin_call,
.builtin_call_comma,
=> {
var buf: [2]Ast.Node.Index = undefined;
const params = tree.builtinCallParams(&buf, inner_node).?;
try emitDbgNode(gz, inner_node);
const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint, .anon);
noreturn_src_node = try addEnsureResult(gz, result, inner_node);
},
else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node),
}
break;
}
}
if (noreturn_src_node == .none) {
try genDefers(gz, parent_scope, scope, .normal_only);
}
try checkUsed(gz, parent_scope, scope);
}