Commit 9a5a1013a8
Changed files (6)
lib
std
src-self-hosted
lib/std/zig/ast.zig
@@ -526,6 +526,7 @@ pub const Node = struct {
Comptime,
Nosuspend,
Block,
+ LabeledBlock,
// Misc
DocComment,
@@ -654,6 +655,7 @@ pub const Node = struct {
.Comptime => Comptime,
.Nosuspend => Nosuspend,
.Block => Block,
+ .LabeledBlock => LabeledBlock,
.DocComment => DocComment,
.SwitchCase => SwitchCase,
.SwitchElse => SwitchElse,
@@ -666,6 +668,13 @@ pub const Node = struct {
.FieldInitializer => FieldInitializer,
};
}
+
+ pub fn isBlock(tag: Tag) bool {
+ return switch (tag) {
+ .Block, .LabeledBlock => true,
+ else => false,
+ };
+ }
};
/// Prefer `castTag` to this.
@@ -729,6 +738,7 @@ pub const Node = struct {
.Root,
.ContainerField,
.Block,
+ .LabeledBlock,
.Payload,
.PointerPayload,
.PointerIndexPayload,
@@ -739,6 +749,7 @@ pub const Node = struct {
.DocComment,
.TestDecl,
=> return false,
+
.While => {
const while_node = @fieldParentPtr(While, "base", n);
if (while_node.@"else") |@"else"| {
@@ -746,7 +757,7 @@ pub const Node = struct {
continue;
}
- return while_node.body.tag != .Block;
+ return !while_node.body.tag.isBlock();
},
.For => {
const for_node = @fieldParentPtr(For, "base", n);
@@ -755,7 +766,7 @@ pub const Node = struct {
continue;
}
- return for_node.body.tag != .Block;
+ return !for_node.body.tag.isBlock();
},
.If => {
const if_node = @fieldParentPtr(If, "base", n);
@@ -764,7 +775,7 @@ pub const Node = struct {
continue;
}
- return if_node.body.tag != .Block;
+ return !if_node.body.tag.isBlock();
},
.Else => {
const else_node = @fieldParentPtr(Else, "base", n);
@@ -773,29 +784,40 @@ pub const Node = struct {
},
.Defer => {
const defer_node = @fieldParentPtr(Defer, "base", n);
- return defer_node.expr.tag != .Block;
+ return !defer_node.expr.tag.isBlock();
},
.Comptime => {
const comptime_node = @fieldParentPtr(Comptime, "base", n);
- return comptime_node.expr.tag != .Block;
+ return !comptime_node.expr.tag.isBlock();
},
.Suspend => {
const suspend_node = @fieldParentPtr(Suspend, "base", n);
if (suspend_node.body) |body| {
- return body.tag != .Block;
+ return !body.tag.isBlock();
}
return true;
},
.Nosuspend => {
const nosuspend_node = @fieldParentPtr(Nosuspend, "base", n);
- return nosuspend_node.expr.tag != .Block;
+ return !nosuspend_node.expr.tag.isBlock();
},
else => return true,
}
}
}
+ /// Asserts the node is a Block or LabeledBlock and returns the statements slice.
+ pub fn blockStatements(base: *Node) []*Node {
+ if (base.castTag(.Block)) |block| {
+ return block.statements();
+ } else if (base.castTag(.LabeledBlock)) |labeled_block| {
+ return labeled_block.statements();
+ } else {
+ unreachable;
+ }
+ }
+
pub fn dump(self: *Node, indent: usize) void {
{
var i: usize = 0;
@@ -1460,7 +1482,6 @@ pub const Node = struct {
statements_len: NodeIndex,
lbrace: TokenIndex,
rbrace: TokenIndex,
- label: ?TokenIndex,
/// After this the caller must initialize the statements list.
pub fn alloc(allocator: *mem.Allocator, statements_len: NodeIndex) !*Block {
@@ -1483,10 +1504,6 @@ pub const Node = struct {
}
pub fn firstToken(self: *const Block) TokenIndex {
- if (self.label) |label| {
- return label;
- }
-
return self.lbrace;
}
@@ -1509,6 +1526,57 @@ pub const Node = struct {
}
};
+ /// The statements of the block follow LabeledBlock directly in memory.
+ pub const LabeledBlock = struct {
+ base: Node = Node{ .tag = .LabeledBlock },
+ statements_len: NodeIndex,
+ lbrace: TokenIndex,
+ rbrace: TokenIndex,
+ label: TokenIndex,
+
+ /// After this the caller must initialize the statements list.
+ pub fn alloc(allocator: *mem.Allocator, statements_len: NodeIndex) !*LabeledBlock {
+ const bytes = try allocator.alignedAlloc(u8, @alignOf(LabeledBlock), sizeInBytes(statements_len));
+ return @ptrCast(*LabeledBlock, bytes.ptr);
+ }
+
+ pub fn free(self: *LabeledBlock, allocator: *mem.Allocator) void {
+ const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.statements_len)];
+ allocator.free(bytes);
+ }
+
+ pub fn iterate(self: *const LabeledBlock, index: usize) ?*Node {
+ var i = index;
+
+ if (i < self.statements_len) return self.statementsConst()[i];
+ i -= self.statements_len;
+
+ return null;
+ }
+
+ pub fn firstToken(self: *const LabeledBlock) TokenIndex {
+ return self.label;
+ }
+
+ pub fn lastToken(self: *const LabeledBlock) TokenIndex {
+ return self.rbrace;
+ }
+
+ pub fn statements(self: *LabeledBlock) []*Node {
+ const decls_start = @ptrCast([*]u8, self) + @sizeOf(LabeledBlock);
+ return @ptrCast([*]*Node, decls_start)[0..self.statements_len];
+ }
+
+ pub fn statementsConst(self: *const LabeledBlock) []const *Node {
+ const decls_start = @ptrCast([*]const u8, self) + @sizeOf(LabeledBlock);
+ return @ptrCast([*]const *Node, decls_start)[0..self.statements_len];
+ }
+
+ fn sizeInBytes(statements_len: NodeIndex) usize {
+ return @sizeOf(LabeledBlock) + @sizeOf(*Node) * @as(usize, statements_len);
+ }
+ };
+
pub const Defer = struct {
base: Node = Node{ .tag = .Defer },
defer_token: TokenIndex,
lib/std/zig/parse.zig
@@ -364,9 +364,10 @@ const Parser = struct {
const name_node = try p.expectNode(parseStringLiteralSingle, .{
.ExpectedStringLiteral = .{ .token = p.tok_i },
});
- const block_node = try p.expectNode(parseBlock, .{
- .ExpectedLBrace = .{ .token = p.tok_i },
- });
+ const block_node = (try p.parseBlock(null)) orelse {
+ try p.errors.append(p.gpa, .{ .ExpectedLBrace = .{ .token = p.tok_i } });
+ return error.ParseError;
+ };
const test_node = try p.arena.allocator.create(Node.TestDecl);
test_node.* = .{
@@ -540,12 +541,14 @@ const Parser = struct {
if (p.eatToken(.Semicolon)) |_| {
break :blk null;
}
- break :blk try p.expectNodeRecoverable(parseBlock, .{
+ const body_block = (try p.parseBlock(null)) orelse {
// Since parseBlock only return error.ParseError on
// a missing '}' we can assume this function was
// supposed to end here.
- .ExpectedSemiOrLBrace = .{ .token = p.tok_i },
- });
+ try p.errors.append(p.gpa, .{ .ExpectedSemiOrLBrace = .{ .token = p.tok_i } });
+ break :blk null;
+ };
+ break :blk body_block;
},
.as_type => null,
};
@@ -823,10 +826,7 @@ const Parser = struct {
var colon: TokenIndex = undefined;
const label_token = p.parseBlockLabel(&colon);
- if (try p.parseBlock()) |node| {
- node.cast(Node.Block).?.label = label_token;
- return node;
- }
+ if (try p.parseBlock(label_token)) |node| return node;
if (try p.parseLoopStatement()) |node| {
if (node.cast(Node.For)) |for_node| {
@@ -1003,14 +1003,13 @@ const Parser = struct {
fn parseBlockExpr(p: *Parser) Error!?*Node {
var colon: TokenIndex = undefined;
const label_token = p.parseBlockLabel(&colon);
- const block_node = (try p.parseBlock()) orelse {
+ const block_node = (try p.parseBlock(label_token)) orelse {
if (label_token) |label| {
p.putBackToken(label + 1); // ":"
p.putBackToken(label); // IDENTIFIER
}
return null;
};
- block_node.cast(Node.Block).?.label = label_token;
return block_node;
}
@@ -1177,7 +1176,7 @@ const Parser = struct {
p.putBackToken(token); // IDENTIFIER
}
- if (try p.parseBlock()) |node| return node;
+ if (try p.parseBlock(null)) |node| return node;
if (try p.parseCurlySuffixExpr()) |node| return node;
return null;
@@ -1189,7 +1188,7 @@ const Parser = struct {
}
/// Block <- LBRACE Statement* RBRACE
- fn parseBlock(p: *Parser) !?*Node {
+ fn parseBlock(p: *Parser, label_token: ?TokenIndex) !?*Node {
const lbrace = p.eatToken(.LBrace) orelse return null;
var statements = std.ArrayList(*Node).init(p.gpa);
@@ -1211,16 +1210,26 @@ const Parser = struct {
const statements_len = @intCast(NodeIndex, statements.items.len);
- const block_node = try Node.Block.alloc(&p.arena.allocator, statements_len);
- block_node.* = .{
- .label = null,
- .lbrace = lbrace,
- .statements_len = statements_len,
- .rbrace = rbrace,
- };
- std.mem.copy(*Node, block_node.statements(), statements.items);
-
- return &block_node.base;
+ if (label_token) |label| {
+ const block_node = try Node.LabeledBlock.alloc(&p.arena.allocator, statements_len);
+ block_node.* = .{
+ .label = label,
+ .lbrace = lbrace,
+ .statements_len = statements_len,
+ .rbrace = rbrace,
+ };
+ std.mem.copy(*Node, block_node.statements(), statements.items);
+ return &block_node.base;
+ } else {
+ const block_node = try Node.Block.alloc(&p.arena.allocator, statements_len);
+ block_node.* = .{
+ .lbrace = lbrace,
+ .statements_len = statements_len,
+ .rbrace = rbrace,
+ };
+ std.mem.copy(*Node, block_node.statements(), statements.items);
+ return &block_node.base;
+ }
}
/// LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)
@@ -1658,11 +1667,8 @@ const Parser = struct {
var colon: TokenIndex = undefined;
const label = p.parseBlockLabel(&colon);
- if (label) |token| {
- if (try p.parseBlock()) |node| {
- node.cast(Node.Block).?.label = token;
- return node;
- }
+ if (label) |label_token| {
+ if (try p.parseBlock(label_token)) |node| return node;
}
if (try p.parseLoopTypeExpr()) |node| {
@@ -3440,6 +3446,7 @@ const Parser = struct {
}
}
+ /// TODO Delete this function. I don't like the inversion of control.
fn expectNode(
p: *Parser,
parseFn: NodeParseFn,
@@ -3449,6 +3456,7 @@ const Parser = struct {
return (try p.expectNodeRecoverable(parseFn, err)) orelse return error.ParseError;
}
+ /// TODO Delete this function. I don't like the inversion of control.
fn expectNodeRecoverable(
p: *Parser,
parseFn: NodeParseFn,
lib/std/zig/render.zig
@@ -392,28 +392,50 @@ fn renderExpression(
return renderToken(tree, stream, any_type.token, indent, start_col, space);
},
- .Block => {
- const block = @fieldParentPtr(ast.Node.Block, "base", base);
+ .Block, .LabeledBlock => {
+ const block: struct {
+ label: ?ast.TokenIndex,
+ statements: []*ast.Node,
+ lbrace: ast.TokenIndex,
+ rbrace: ast.TokenIndex,
+ } = b: {
+ if (base.castTag(.Block)) |block| {
+ break :b .{
+ .label = null,
+ .statements = block.statements(),
+ .lbrace = block.lbrace,
+ .rbrace = block.rbrace,
+ };
+ } else if (base.castTag(.LabeledBlock)) |block| {
+ break :b .{
+ .label = block.label,
+ .statements = block.statements(),
+ .lbrace = block.lbrace,
+ .rbrace = block.rbrace,
+ };
+ } else {
+ unreachable;
+ }
+ };
if (block.label) |label| {
try renderToken(tree, stream, label, indent, start_col, Space.None);
try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
}
- if (block.statements_len == 0) {
+ if (block.statements.len == 0) {
try renderToken(tree, stream, block.lbrace, indent + indent_delta, start_col, Space.None);
return renderToken(tree, stream, block.rbrace, indent, start_col, space);
} else {
const block_indent = indent + indent_delta;
try renderToken(tree, stream, block.lbrace, block_indent, start_col, Space.Newline);
- const block_statements = block.statements();
- for (block_statements) |statement, i| {
+ for (block.statements) |statement, i| {
try stream.writeByteNTimes(' ', block_indent);
try renderStatement(allocator, stream, tree, block_indent, start_col, statement);
- if (i + 1 < block_statements.len) {
- try renderExtraNewline(tree, stream, start_col, block_statements[i + 1]);
+ if (i + 1 < block.statements.len) {
+ try renderExtraNewline(tree, stream, start_col, block.statements[i + 1]);
}
}
@@ -1841,7 +1863,7 @@ fn renderExpression(
const rparen = tree.nextToken(for_node.array_expr.lastToken());
- const body_is_block = for_node.body.tag == .Block;
+ const body_is_block = for_node.body.tag.isBlock();
const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken());
const body_on_same_line = body_is_block or src_one_line_to_body;
@@ -2578,6 +2600,7 @@ fn renderDocCommentsToken(
fn nodeIsBlock(base: *const ast.Node) bool {
return switch (base.tag) {
.Block,
+ .LabeledBlock,
.If,
.For,
.While,
src-self-hosted/astgen.zig
@@ -107,31 +107,46 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
.NullLiteral => return rlWrap(mod, scope, rl, try nullLiteral(mod, scope, node.castTag(.NullLiteral).?)),
.OptionalType => return rlWrap(mod, scope, rl, try optionalType(mod, scope, node.castTag(.OptionalType).?)),
.UnwrapOptional => return unwrapOptional(mod, scope, rl, node.castTag(.UnwrapOptional).?),
- .Block => return blockExpr(mod, scope, rl, node.castTag(.Block).?),
+ .Block => return rlWrapVoid(mod, scope, rl, node, try blockExpr(mod, scope, node.castTag(.Block).?)),
+ .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?),
else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}),
}
}
-pub fn blockExpr(
+pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block) InnerError!void {
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ try blockExprStmts(mod, parent_scope, &block_node.base, block_node.statements());
+}
+
+fn labeledBlockExpr(
mod: *Module,
parent_scope: *Scope,
rl: ResultLoc,
- block_node: *ast.Node.Block,
+ block_node: *ast.Node.LabeledBlock,
) InnerError!*zir.Inst {
const tracy = trace(@src());
defer tracy.end();
- if (block_node.label) |label| {
- return mod.failTok(parent_scope, label, "TODO implement labeled blocks", .{});
+ const statements = block_node.statements();
+
+ if (statements.len == 0) {
+ // Hot path for `{}`.
+ return rlWrapVoid(mod, parent_scope, rl, &block_node.base, {});
}
- var block_arena = std.heap.ArenaAllocator.init(mod.gpa);
- defer block_arena.deinit();
+ return mod.failNode(parent_scope, &block_node.base, "TODO implement labeled blocks", .{});
+}
+fn blockExprStmts(mod: *Module, parent_scope: *Scope, node: *ast.Node, statements: []*ast.Node) !void {
const tree = parent_scope.tree();
+ var block_arena = std.heap.ArenaAllocator.init(mod.gpa);
+ defer block_arena.deinit();
+
var scope = parent_scope;
- for (block_node.statements()) |statement| {
+ for (statements) |statement| {
const src = tree.token_locs[statement.firstToken()].start;
_ = try addZIRNoOp(mod, scope, src, .dbg_stmt);
switch (statement.tag) {
@@ -162,12 +177,6 @@ pub fn blockExpr(
},
}
}
-
- const src = tree.token_locs[block_node.firstToken()].start;
- return addZIRInstConst(mod, parent_scope, src, .{
- .ty = Type.initTag(.void),
- .val = Value.initTag(.void_value),
- });
}
fn varDecl(
@@ -1184,6 +1193,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {
.Slice,
.Deref,
.ArrayAccess,
+ .Block,
=> return false,
// Forward the question to a sub-expression.
@@ -1210,11 +1220,11 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {
.Switch,
.Call,
.BuiltinCall, // TODO some of these can return false
+ .LabeledBlock,
=> return true,
// Depending on AST properties, they may need memory locations.
.If => return node.castTag(.If).?.@"else" != null,
- .Block => return node.castTag(.Block).?.label != null,
}
}
}
src-self-hosted/Module.zig
@@ -1343,7 +1343,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
const body_block = body_node.cast(ast.Node.Block).?;
- _ = try astgen.blockExpr(self, params_scope, .none, body_block);
+ try astgen.blockExpr(self, params_scope, body_block);
if (gen_scope.instructions.items.len == 0 or
!gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())
src-self-hosted/translate_c.zig
@@ -118,19 +118,31 @@ const Scope = struct {
self.* = undefined;
}
- fn complete(self: *Block, c: *Context) !*ast.Node.Block {
+ fn complete(self: *Block, c: *Context) !*ast.Node {
// We reserve 1 extra statement if the parent is a Loop. This is in case of
// do while, we want to put `if (cond) break;` at the end.
const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .Loop);
- const node = try ast.Node.Block.alloc(c.arena, alloc_len);
- node.* = .{
- .statements_len = self.statements.items.len,
- .lbrace = self.lbrace,
- .rbrace = try appendToken(c, .RBrace, "}"),
- .label = self.label,
- };
- mem.copy(*ast.Node, node.statements(), self.statements.items);
- return node;
+ const rbrace = try appendToken(c, .RBrace, "}");
+ if (self.label) |label| {
+ const node = try ast.Node.LabeledBlock.alloc(c.arena, alloc_len);
+ node.* = .{
+ .statements_len = self.statements.items.len,
+ .lbrace = self.lbrace,
+ .rbrace = rbrace,
+ .label = label,
+ };
+ mem.copy(*ast.Node, node.statements(), self.statements.items);
+ return &node.base;
+ } else {
+ const node = try ast.Node.Block.alloc(c.arena, alloc_len);
+ node.* = .{
+ .statements_len = self.statements.items.len,
+ .lbrace = self.lbrace,
+ .rbrace = rbrace,
+ };
+ mem.copy(*ast.Node, node.statements(), self.statements.items);
+ return &node.base;
+ }
}
/// Given the desired name, return a name that does not shadow anything from outer scopes.
@@ -320,15 +332,9 @@ pub const Context = struct {
return node;
}
- fn createBlock(c: *Context, label: ?[]const u8, statements_len: ast.NodeIndex) !*ast.Node.Block {
- const label_node = if (label) |l| blk: {
- const ll = try appendIdentifier(c, l);
- _ = try appendToken(c, .Colon, ":");
- break :blk ll;
- } else null;
+ fn createBlock(c: *Context, statements_len: ast.NodeIndex) !*ast.Node.Block {
const block_node = try ast.Node.Block.alloc(c.arena, statements_len);
block_node.* = .{
- .label = label_node,
.lbrace = try appendToken(c, .LBrace, "{"),
.statements_len = statements_len,
.rbrace = undefined,
@@ -640,8 +646,8 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
var last = block_scope.statements.items[block_scope.statements.items.len - 1];
while (true) {
switch (last.tag) {
- .Block => {
- const stmts = last.castTag(.Block).?.statements();
+ .Block, .LabeledBlock => {
+ const stmts = last.blockStatements();
if (stmts.len == 0) break;
last = stmts[stmts.len - 1];
@@ -669,7 +675,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
}
const body_node = try block_scope.complete(rp.c);
- proto_node.setTrailer("body_node", &body_node.base);
+ proto_node.setTrailer("body_node", body_node);
return addTopLevelDecl(c, fn_name, &proto_node.base);
}
@@ -1275,7 +1281,7 @@ fn transStmt(
.WhileStmtClass => return transWhileLoop(rp, scope, @ptrCast(*const ZigClangWhileStmt, stmt)),
.DoStmtClass => return transDoWhileLoop(rp, scope, @ptrCast(*const ZigClangDoStmt, stmt)),
.NullStmtClass => {
- const block = try rp.c.createBlock(null, 0);
+ const block = try rp.c.createBlock(0);
block.rbrace = try appendToken(rp.c, .RBrace, "}");
return &block.base;
},
@@ -1356,7 +1362,7 @@ fn transBinaryOperator(
const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
grouped_expr.* = .{
.lparen = lparen,
- .expr = &block_node.base,
+ .expr = block_node,
.rparen = rparen,
};
return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
@@ -1521,8 +1527,7 @@ fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompo
var block_scope = try Scope.Block.init(rp.c, scope, false);
defer block_scope.deinit();
try transCompoundStmtInline(rp, &block_scope.base, stmt, &block_scope);
- const node = try block_scope.complete(rp.c);
- return &node.base;
+ return try block_scope.complete(rp.c);
}
fn transCStyleCastExprClass(
@@ -2589,7 +2594,7 @@ fn transDoWhileLoop(
// zig: if (!cond) break;
// zig: }
const node = try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value);
- break :blk node.cast(ast.Node.Block).?;
+ break :blk node.castTag(.Block).?;
} else blk: {
// the C statement is without a block, so we need to create a block to contain it.
// c: do
@@ -2600,7 +2605,7 @@ fn transDoWhileLoop(
// zig: if (!cond) break;
// zig: }
new = true;
- const block = try rp.c.createBlock(null, 2);
+ const block = try rp.c.createBlock(2);
block.statements_len = 1; // over-allocated so we can add another below
block.statements()[0] = try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value);
break :blk block;
@@ -2659,8 +2664,7 @@ fn transForLoop(
while_node.body = try transStmt(rp, &loop_scope, ZigClangForStmt_getBody(stmt), .unused, .r_value);
if (block_scope) |*bs| {
try bs.statements.append(&while_node.base);
- const node = try bs.complete(rp.c);
- return &node.base;
+ return try bs.complete(rp.c);
} else {
_ = try appendToken(rp.c, .Semicolon, ";");
return &while_node.base;
@@ -2768,7 +2772,7 @@ fn transSwitch(
const result_node = try switch_scope.pending_block.complete(rp.c);
switch_scope.pending_block.deinit();
- return &result_node.base;
+ return result_node;
}
fn transCase(
@@ -2820,7 +2824,7 @@ fn transCase(
switch_scope.pending_block.deinit();
switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
- try switch_scope.pending_block.statements.append(&pending_node.base);
+ try switch_scope.pending_block.statements.append(pending_node);
return transStmt(rp, scope, ZigClangCaseStmt_getSubStmt(stmt), .unused, .r_value);
}
@@ -2857,7 +2861,7 @@ fn transDefault(
const pending_node = try switch_scope.pending_block.complete(rp.c);
switch_scope.pending_block.deinit();
switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
- try switch_scope.pending_block.statements.append(&pending_node.base);
+ try switch_scope.pending_block.statements.append(pending_node);
return transStmt(rp, scope, ZigClangDefaultStmt_getSubStmt(stmt), .unused, .r_value);
}
@@ -2972,7 +2976,7 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr,
const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
grouped_expr.* = .{
.lparen = lparen,
- .expr = &block_node.base,
+ .expr = block_node,
.rparen = rparen,
};
return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
@@ -3304,7 +3308,7 @@ fn transCreatePreCrement(
const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
grouped_expr.* = .{
.lparen = try appendToken(rp.c, .LParen, "("),
- .expr = &block_node.base,
+ .expr = block_node,
.rparen = try appendToken(rp.c, .RParen, ")"),
};
return &grouped_expr.base;
@@ -3398,7 +3402,7 @@ fn transCreatePostCrement(
const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
grouped_expr.* = .{
.lparen = try appendToken(rp.c, .LParen, "("),
- .expr = &block_node.base,
+ .expr = block_node,
.rparen = try appendToken(rp.c, .RParen, ")"),
};
return &grouped_expr.base;
@@ -3589,7 +3593,7 @@ fn transCreateCompoundAssign(
const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
grouped_expr.* = .{
.lparen = try appendToken(rp.c, .LParen, "("),
- .expr = &block_node.base,
+ .expr = block_node,
.rparen = try appendToken(rp.c, .RParen, ")"),
};
return &grouped_expr.base;
@@ -3748,7 +3752,7 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const
const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
grouped_expr.* = .{
.lparen = lparen,
- .expr = &block_node.base,
+ .expr = block_node,
.rparen = try appendToken(rp.c, .RParen, ")"),
};
return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
@@ -4191,7 +4195,7 @@ fn transCreateNodeAssign(
const block_node = try block_scope.complete(rp.c);
// semicolon must immediately follow rbrace because it is the last token in a block
_ = try appendToken(rp.c, .Semicolon, ";");
- return &block_node.base;
+ return block_node;
}
fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node {
@@ -4484,7 +4488,6 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a
const block = try ast.Node.Block.alloc(c.arena, 1);
block.* = .{
- .label = null,
.lbrace = block_lbrace,
.statements_len = 1,
.rbrace = try appendToken(c, .RBrace, "}"),
@@ -5475,9 +5478,9 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
if (last != .Eof and last != .Nl)
return m.fail(c, "unable to translate C expr: unexpected token .{}", .{@tagName(last)});
_ = try appendToken(c, .Semicolon, ";");
- const type_of_arg = if (expr.tag != .Block) expr else blk: {
- const blk = @fieldParentPtr(ast.Node.Block, "base", expr);
- const blk_last = blk.statements()[blk.statements_len - 1];
+ const type_of_arg = if (!expr.tag.isBlock()) expr else blk: {
+ const stmts = expr.blockStatements();
+ const blk_last = stmts[stmts.len - 1];
const br = blk_last.cast(ast.Node.ControlFlowExpression).?;
break :blk br.getRHS().?;
};
@@ -5500,7 +5503,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
.visib_token = pub_tok,
.extern_export_inline_token = inline_tok,
.name_token = name_tok,
- .body_node = &block_node.base,
+ .body_node = block_node,
});
mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);
@@ -5555,8 +5558,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
const break_node = try transCreateNodeBreak(c, block_scope.label, last);
try block_scope.statements.append(&break_node.base);
- const block_node = try block_scope.complete(c);
- return &block_node.base;
+ return try block_scope.complete(c);
},
else => {
m.i -= 1;