authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-14 15:27:48-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-14 22:50:00-04:00
log9a5a1013a833229e1d12588615c1a05644f76cc5
treec8a1cca2e5324891a4f748b3fd38c0f65ef78d03
parentc12a262503150d1b2251f7ba29e0f1ba4f649bf6

std.zig.ast: extract out Node.LabeledBlock from Node.Block

This is part of an ongoing effort to reduce size of in-memory AST. This enum flattening pattern is widespread throughout the self-hosted compiler. This is a API breaking change for consumers of the self-hosted parser.

6 files changed, 220 insertions(+), 109 deletions(-)

lib/std/zig/ast.zig+80-12
...@@ -526,6 +526,7 @@ pub const Node = struct {...@@ -526,6 +526,7 @@ pub const Node = struct {
526 Comptime,526 Comptime,
527 Nosuspend,527 Nosuspend,
528 Block,528 Block,
529 LabeledBlock,
529530
530 // Misc531 // Misc
531 DocComment,532 DocComment,
...@@ -654,6 +655,7 @@ pub const Node = struct {...@@ -654,6 +655,7 @@ pub const Node = struct {
654 .Comptime => Comptime,655 .Comptime => Comptime,
655 .Nosuspend => Nosuspend,656 .Nosuspend => Nosuspend,
656 .Block => Block,657 .Block => Block,
658 .LabeledBlock => LabeledBlock,
657 .DocComment => DocComment,659 .DocComment => DocComment,
658 .SwitchCase => SwitchCase,660 .SwitchCase => SwitchCase,
659 .SwitchElse => SwitchElse,661 .SwitchElse => SwitchElse,
...@@ -666,6 +668,13 @@ pub const Node = struct {...@@ -666,6 +668,13 @@ pub const Node = struct {
666 .FieldInitializer => FieldInitializer,668 .FieldInitializer => FieldInitializer,
667 };669 };
668 }670 }
671
672 pub fn isBlock(tag: Tag) bool {
673 return switch (tag) {
674 .Block, .LabeledBlock => true,
675 else => false,
676 };
677 }
669 };678 };
670679
671 /// Prefer `castTag` to this.680 /// Prefer `castTag` to this.
...@@ -729,6 +738,7 @@ pub const Node = struct {...@@ -729,6 +738,7 @@ pub const Node = struct {
729 .Root,738 .Root,
730 .ContainerField,739 .ContainerField,
731 .Block,740 .Block,
741 .LabeledBlock,
732 .Payload,742 .Payload,
733 .PointerPayload,743 .PointerPayload,
734 .PointerIndexPayload,744 .PointerIndexPayload,
...@@ -739,6 +749,7 @@ pub const Node = struct {...@@ -739,6 +749,7 @@ pub const Node = struct {
739 .DocComment,749 .DocComment,
740 .TestDecl,750 .TestDecl,
741 => return false,751 => return false,
752
742 .While => {753 .While => {
743 const while_node = @fieldParentPtr(While, "base", n);754 const while_node = @fieldParentPtr(While, "base", n);
744 if (while_node.@"else") |@"else"| {755 if (while_node.@"else") |@"else"| {
...@@ -746,7 +757,7 @@ pub const Node = struct {...@@ -746,7 +757,7 @@ pub const Node = struct {
746 continue;757 continue;
747 }758 }
748759
749 return while_node.body.tag != .Block;760 return !while_node.body.tag.isBlock();
750 },761 },
751 .For => {762 .For => {
752 const for_node = @fieldParentPtr(For, "base", n);763 const for_node = @fieldParentPtr(For, "base", n);
...@@ -755,7 +766,7 @@ pub const Node = struct {...@@ -755,7 +766,7 @@ pub const Node = struct {
755 continue;766 continue;
756 }767 }
757768
758 return for_node.body.tag != .Block;769 return !for_node.body.tag.isBlock();
759 },770 },
760 .If => {771 .If => {
761 const if_node = @fieldParentPtr(If, "base", n);772 const if_node = @fieldParentPtr(If, "base", n);
...@@ -764,7 +775,7 @@ pub const Node = struct {...@@ -764,7 +775,7 @@ pub const Node = struct {
764 continue;775 continue;
765 }776 }
766777
767 return if_node.body.tag != .Block;778 return !if_node.body.tag.isBlock();
768 },779 },
769 .Else => {780 .Else => {
770 const else_node = @fieldParentPtr(Else, "base", n);781 const else_node = @fieldParentPtr(Else, "base", n);
...@@ -773,29 +784,40 @@ pub const Node = struct {...@@ -773,29 +784,40 @@ pub const Node = struct {
773 },784 },
774 .Defer => {785 .Defer => {
775 const defer_node = @fieldParentPtr(Defer, "base", n);786 const defer_node = @fieldParentPtr(Defer, "base", n);
776 return defer_node.expr.tag != .Block;787 return !defer_node.expr.tag.isBlock();
777 },788 },
778 .Comptime => {789 .Comptime => {
779 const comptime_node = @fieldParentPtr(Comptime, "base", n);790 const comptime_node = @fieldParentPtr(Comptime, "base", n);
780 return comptime_node.expr.tag != .Block;791 return !comptime_node.expr.tag.isBlock();
781 },792 },
782 .Suspend => {793 .Suspend => {
783 const suspend_node = @fieldParentPtr(Suspend, "base", n);794 const suspend_node = @fieldParentPtr(Suspend, "base", n);
784 if (suspend_node.body) |body| {795 if (suspend_node.body) |body| {
785 return body.tag != .Block;796 return !body.tag.isBlock();
786 }797 }
787798
788 return true;799 return true;
789 },800 },
790 .Nosuspend => {801 .Nosuspend => {
791 const nosuspend_node = @fieldParentPtr(Nosuspend, "base", n);802 const nosuspend_node = @fieldParentPtr(Nosuspend, "base", n);
792 return nosuspend_node.expr.tag != .Block;803 return !nosuspend_node.expr.tag.isBlock();
793 },804 },
794 else => return true,805 else => return true,
795 }806 }
796 }807 }
797 }808 }
798809
810 /// Asserts the node is a Block or LabeledBlock and returns the statements slice.
811 pub fn blockStatements(base: *Node) []*Node {
812 if (base.castTag(.Block)) |block| {
813 return block.statements();
814 } else if (base.castTag(.LabeledBlock)) |labeled_block| {
815 return labeled_block.statements();
816 } else {
817 unreachable;
818 }
819 }
820
799 pub fn dump(self: *Node, indent: usize) void {821 pub fn dump(self: *Node, indent: usize) void {
800 {822 {
801 var i: usize = 0;823 var i: usize = 0;
...@@ -1460,7 +1482,6 @@ pub const Node = struct {...@@ -1460,7 +1482,6 @@ pub const Node = struct {
1460 statements_len: NodeIndex,1482 statements_len: NodeIndex,
1461 lbrace: TokenIndex,1483 lbrace: TokenIndex,
1462 rbrace: TokenIndex,1484 rbrace: TokenIndex,
1463 label: ?TokenIndex,
14641485
1465 /// After this the caller must initialize the statements list.1486 /// After this the caller must initialize the statements list.
1466 pub fn alloc(allocator: *mem.Allocator, statements_len: NodeIndex) !*Block {1487 pub fn alloc(allocator: *mem.Allocator, statements_len: NodeIndex) !*Block {
...@@ -1483,10 +1504,6 @@ pub const Node = struct {...@@ -1483,10 +1504,6 @@ pub const Node = struct {
1483 }1504 }
14841505
1485 pub fn firstToken(self: *const Block) TokenIndex {1506 pub fn firstToken(self: *const Block) TokenIndex {
1486 if (self.label) |label| {
1487 return label;
1488 }
1489
1490 return self.lbrace;1507 return self.lbrace;
1491 }1508 }
14921509
...@@ -1509,6 +1526,57 @@ pub const Node = struct {...@@ -1509,6 +1526,57 @@ pub const Node = struct {
1509 }1526 }
1510 };1527 };
15111528
1529 /// The statements of the block follow LabeledBlock directly in memory.
1530 pub const LabeledBlock = struct {
1531 base: Node = Node{ .tag = .LabeledBlock },
1532 statements_len: NodeIndex,
1533 lbrace: TokenIndex,
1534 rbrace: TokenIndex,
1535 label: TokenIndex,
1536
1537 /// After this the caller must initialize the statements list.
1538 pub fn alloc(allocator: *mem.Allocator, statements_len: NodeIndex) !*LabeledBlock {
1539 const bytes = try allocator.alignedAlloc(u8, @alignOf(LabeledBlock), sizeInBytes(statements_len));
1540 return @ptrCast(*LabeledBlock, bytes.ptr);
1541 }
1542
1543 pub fn free(self: *LabeledBlock, allocator: *mem.Allocator) void {
1544 const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.statements_len)];
1545 allocator.free(bytes);
1546 }
1547
1548 pub fn iterate(self: *const LabeledBlock, index: usize) ?*Node {
1549 var i = index;
1550
1551 if (i < self.statements_len) return self.statementsConst()[i];
1552 i -= self.statements_len;
1553
1554 return null;
1555 }
1556
1557 pub fn firstToken(self: *const LabeledBlock) TokenIndex {
1558 return self.label;
1559 }
1560
1561 pub fn lastToken(self: *const LabeledBlock) TokenIndex {
1562 return self.rbrace;
1563 }
1564
1565 pub fn statements(self: *LabeledBlock) []*Node {
1566 const decls_start = @ptrCast([*]u8, self) + @sizeOf(LabeledBlock);
1567 return @ptrCast([*]*Node, decls_start)[0..self.statements_len];
1568 }
1569
1570 pub fn statementsConst(self: *const LabeledBlock) []const *Node {
1571 const decls_start = @ptrCast([*]const u8, self) + @sizeOf(LabeledBlock);
1572 return @ptrCast([*]const *Node, decls_start)[0..self.statements_len];
1573 }
1574
1575 fn sizeInBytes(statements_len: NodeIndex) usize {
1576 return @sizeOf(LabeledBlock) + @sizeOf(*Node) * @as(usize, statements_len);
1577 }
1578 };
1579
1512 pub const Defer = struct {1580 pub const Defer = struct {
1513 base: Node = Node{ .tag = .Defer },1581 base: Node = Node{ .tag = .Defer },
1514 defer_token: TokenIndex,1582 defer_token: TokenIndex,
lib/std/zig/parse.zig+37-29
...@@ -364,9 +364,10 @@ const Parser = struct {...@@ -364,9 +364,10 @@ const Parser = struct {
364 const name_node = try p.expectNode(parseStringLiteralSingle, .{364 const name_node = try p.expectNode(parseStringLiteralSingle, .{
365 .ExpectedStringLiteral = .{ .token = p.tok_i },365 .ExpectedStringLiteral = .{ .token = p.tok_i },
366 });366 });
367 const block_node = try p.expectNode(parseBlock, .{367 const block_node = (try p.parseBlock(null)) orelse {
368 .ExpectedLBrace = .{ .token = p.tok_i },368 try p.errors.append(p.gpa, .{ .ExpectedLBrace = .{ .token = p.tok_i } });
369 });369 return error.ParseError;
370 };
370371
371 const test_node = try p.arena.allocator.create(Node.TestDecl);372 const test_node = try p.arena.allocator.create(Node.TestDecl);
372 test_node.* = .{373 test_node.* = .{
...@@ -540,12 +541,14 @@ const Parser = struct {...@@ -540,12 +541,14 @@ const Parser = struct {
540 if (p.eatToken(.Semicolon)) |_| {541 if (p.eatToken(.Semicolon)) |_| {
541 break :blk null;542 break :blk null;
542 }543 }
543 break :blk try p.expectNodeRecoverable(parseBlock, .{544 const body_block = (try p.parseBlock(null)) orelse {
544 // Since parseBlock only return error.ParseError on545 // Since parseBlock only return error.ParseError on
545 // a missing '}' we can assume this function was546 // a missing '}' we can assume this function was
546 // supposed to end here.547 // supposed to end here.
547 .ExpectedSemiOrLBrace = .{ .token = p.tok_i },548 try p.errors.append(p.gpa, .{ .ExpectedSemiOrLBrace = .{ .token = p.tok_i } });
548 });549 break :blk null;
550 };
551 break :blk body_block;
549 },552 },
550 .as_type => null,553 .as_type => null,
551 };554 };
...@@ -823,10 +826,7 @@ const Parser = struct {...@@ -823,10 +826,7 @@ const Parser = struct {
823 var colon: TokenIndex = undefined;826 var colon: TokenIndex = undefined;
824 const label_token = p.parseBlockLabel(&colon);827 const label_token = p.parseBlockLabel(&colon);
825828
826 if (try p.parseBlock()) |node| {829 if (try p.parseBlock(label_token)) |node| return node;
827 node.cast(Node.Block).?.label = label_token;
828 return node;
829 }
830830
831 if (try p.parseLoopStatement()) |node| {831 if (try p.parseLoopStatement()) |node| {
832 if (node.cast(Node.For)) |for_node| {832 if (node.cast(Node.For)) |for_node| {
...@@ -1003,14 +1003,13 @@ const Parser = struct {...@@ -1003,14 +1003,13 @@ const Parser = struct {
1003 fn parseBlockExpr(p: *Parser) Error!?*Node {1003 fn parseBlockExpr(p: *Parser) Error!?*Node {
1004 var colon: TokenIndex = undefined;1004 var colon: TokenIndex = undefined;
1005 const label_token = p.parseBlockLabel(&colon);1005 const label_token = p.parseBlockLabel(&colon);
1006 const block_node = (try p.parseBlock()) orelse {1006 const block_node = (try p.parseBlock(label_token)) orelse {
1007 if (label_token) |label| {1007 if (label_token) |label| {
1008 p.putBackToken(label + 1); // ":"1008 p.putBackToken(label + 1); // ":"
1009 p.putBackToken(label); // IDENTIFIER1009 p.putBackToken(label); // IDENTIFIER
1010 }1010 }
1011 return null;1011 return null;
1012 };1012 };
1013 block_node.cast(Node.Block).?.label = label_token;
1014 return block_node;1013 return block_node;
1015 }1014 }
10161015
...@@ -1177,7 +1176,7 @@ const Parser = struct {...@@ -1177,7 +1176,7 @@ const Parser = struct {
1177 p.putBackToken(token); // IDENTIFIER1176 p.putBackToken(token); // IDENTIFIER
1178 }1177 }
11791178
1180 if (try p.parseBlock()) |node| return node;1179 if (try p.parseBlock(null)) |node| return node;
1181 if (try p.parseCurlySuffixExpr()) |node| return node;1180 if (try p.parseCurlySuffixExpr()) |node| return node;
11821181
1183 return null;1182 return null;
...@@ -1189,7 +1188,7 @@ const Parser = struct {...@@ -1189,7 +1188,7 @@ const Parser = struct {
1189 }1188 }
11901189
1191 /// Block <- LBRACE Statement* RBRACE1190 /// Block <- LBRACE Statement* RBRACE
1192 fn parseBlock(p: *Parser) !?*Node {1191 fn parseBlock(p: *Parser, label_token: ?TokenIndex) !?*Node {
1193 const lbrace = p.eatToken(.LBrace) orelse return null;1192 const lbrace = p.eatToken(.LBrace) orelse return null;
11941193
1195 var statements = std.ArrayList(*Node).init(p.gpa);1194 var statements = std.ArrayList(*Node).init(p.gpa);
...@@ -1211,16 +1210,26 @@ const Parser = struct {...@@ -1211,16 +1210,26 @@ const Parser = struct {
12111210
1212 const statements_len = @intCast(NodeIndex, statements.items.len);1211 const statements_len = @intCast(NodeIndex, statements.items.len);
12131212
1214 const block_node = try Node.Block.alloc(&p.arena.allocator, statements_len);1213 if (label_token) |label| {
1215 block_node.* = .{1214 const block_node = try Node.LabeledBlock.alloc(&p.arena.allocator, statements_len);
1216 .label = null,1215 block_node.* = .{
1217 .lbrace = lbrace,1216 .label = label,
1218 .statements_len = statements_len,1217 .lbrace = lbrace,
1219 .rbrace = rbrace,1218 .statements_len = statements_len,
1220 };1219 .rbrace = rbrace,
1221 std.mem.copy(*Node, block_node.statements(), statements.items);1220 };
12221221 std.mem.copy(*Node, block_node.statements(), statements.items);
1223 return &block_node.base;1222 return &block_node.base;
1223 } else {
1224 const block_node = try Node.Block.alloc(&p.arena.allocator, statements_len);
1225 block_node.* = .{
1226 .lbrace = lbrace,
1227 .statements_len = statements_len,
1228 .rbrace = rbrace,
1229 };
1230 std.mem.copy(*Node, block_node.statements(), statements.items);
1231 return &block_node.base;
1232 }
1224 }1233 }
12251234
1226 /// LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)1235 /// LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)
...@@ -1658,11 +1667,8 @@ const Parser = struct {...@@ -1658,11 +1667,8 @@ const Parser = struct {
1658 var colon: TokenIndex = undefined;1667 var colon: TokenIndex = undefined;
1659 const label = p.parseBlockLabel(&colon);1668 const label = p.parseBlockLabel(&colon);
16601669
1661 if (label) |token| {1670 if (label) |label_token| {
1662 if (try p.parseBlock()) |node| {1671 if (try p.parseBlock(label_token)) |node| return node;
1663 node.cast(Node.Block).?.label = token;
1664 return node;
1665 }
1666 }1672 }
16671673
1668 if (try p.parseLoopTypeExpr()) |node| {1674 if (try p.parseLoopTypeExpr()) |node| {
...@@ -3440,6 +3446,7 @@ const Parser = struct {...@@ -3440,6 +3446,7 @@ const Parser = struct {
3440 }3446 }
3441 }3447 }
34423448
3449 /// TODO Delete this function. I don't like the inversion of control.
3443 fn expectNode(3450 fn expectNode(
3444 p: *Parser,3451 p: *Parser,
3445 parseFn: NodeParseFn,3452 parseFn: NodeParseFn,
...@@ -3449,6 +3456,7 @@ const Parser = struct {...@@ -3449,6 +3456,7 @@ const Parser = struct {
3449 return (try p.expectNodeRecoverable(parseFn, err)) orelse return error.ParseError;3456 return (try p.expectNodeRecoverable(parseFn, err)) orelse return error.ParseError;
3450 }3457 }
34513458
3459 /// TODO Delete this function. I don't like the inversion of control.
3452 fn expectNodeRecoverable(3460 fn expectNodeRecoverable(
3453 p: *Parser,3461 p: *Parser,
3454 parseFn: NodeParseFn,3462 parseFn: NodeParseFn,
lib/std/zig/render.zig+31-8
...@@ -392,28 +392,50 @@ fn renderExpression(...@@ -392,28 +392,50 @@ fn renderExpression(
392 return renderToken(tree, stream, any_type.token, indent, start_col, space);392 return renderToken(tree, stream, any_type.token, indent, start_col, space);
393 },393 },
394394
395 .Block => {395 .Block, .LabeledBlock => {
396 const block = @fieldParentPtr(ast.Node.Block, "base", base);396 const block: struct {
397 label: ?ast.TokenIndex,
398 statements: []*ast.Node,
399 lbrace: ast.TokenIndex,
400 rbrace: ast.TokenIndex,
401 } = b: {
402 if (base.castTag(.Block)) |block| {
403 break :b .{
404 .label = null,
405 .statements = block.statements(),
406 .lbrace = block.lbrace,
407 .rbrace = block.rbrace,
408 };
409 } else if (base.castTag(.LabeledBlock)) |block| {
410 break :b .{
411 .label = block.label,
412 .statements = block.statements(),
413 .lbrace = block.lbrace,
414 .rbrace = block.rbrace,
415 };
416 } else {
417 unreachable;
418 }
419 };
397420
398 if (block.label) |label| {421 if (block.label) |label| {
399 try renderToken(tree, stream, label, indent, start_col, Space.None);422 try renderToken(tree, stream, label, indent, start_col, Space.None);
400 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);423 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
401 }424 }
402425
403 if (block.statements_len == 0) {426 if (block.statements.len == 0) {
404 try renderToken(tree, stream, block.lbrace, indent + indent_delta, start_col, Space.None);427 try renderToken(tree, stream, block.lbrace, indent + indent_delta, start_col, Space.None);
405 return renderToken(tree, stream, block.rbrace, indent, start_col, space);428 return renderToken(tree, stream, block.rbrace, indent, start_col, space);
406 } else {429 } else {
407 const block_indent = indent + indent_delta;430 const block_indent = indent + indent_delta;
408 try renderToken(tree, stream, block.lbrace, block_indent, start_col, Space.Newline);431 try renderToken(tree, stream, block.lbrace, block_indent, start_col, Space.Newline);
409432
410 const block_statements = block.statements();433 for (block.statements) |statement, i| {
411 for (block_statements) |statement, i| {
412 try stream.writeByteNTimes(' ', block_indent);434 try stream.writeByteNTimes(' ', block_indent);
413 try renderStatement(allocator, stream, tree, block_indent, start_col, statement);435 try renderStatement(allocator, stream, tree, block_indent, start_col, statement);
414436
415 if (i + 1 < block_statements.len) {437 if (i + 1 < block.statements.len) {
416 try renderExtraNewline(tree, stream, start_col, block_statements[i + 1]);438 try renderExtraNewline(tree, stream, start_col, block.statements[i + 1]);
417 }439 }
418 }440 }
419441
...@@ -1841,7 +1863,7 @@ fn renderExpression(...@@ -1841,7 +1863,7 @@ fn renderExpression(
18411863
1842 const rparen = tree.nextToken(for_node.array_expr.lastToken());1864 const rparen = tree.nextToken(for_node.array_expr.lastToken());
18431865
1844 const body_is_block = for_node.body.tag == .Block;1866 const body_is_block = for_node.body.tag.isBlock();
1845 const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken());1867 const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken());
1846 const body_on_same_line = body_is_block or src_one_line_to_body;1868 const body_on_same_line = body_is_block or src_one_line_to_body;
18471869
...@@ -2578,6 +2600,7 @@ fn renderDocCommentsToken(...@@ -2578,6 +2600,7 @@ fn renderDocCommentsToken(
2578fn nodeIsBlock(base: *const ast.Node) bool {2600fn nodeIsBlock(base: *const ast.Node) bool {
2579 return switch (base.tag) {2601 return switch (base.tag) {
2580 .Block,2602 .Block,
2603 .LabeledBlock,
2581 .If,2604 .If,
2582 .For,2605 .For,
2583 .While,2606 .While,
src-self-hosted/Module.zig+1-1
...@@ -1343,7 +1343,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1343,7 +1343,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
13431343
1344 const body_block = body_node.cast(ast.Node.Block).?;1344 const body_block = body_node.cast(ast.Node.Block).?;
13451345
1346 _ = try astgen.blockExpr(self, params_scope, .none, body_block);1346 try astgen.blockExpr(self, params_scope, body_block);
13471347
1348 if (gen_scope.instructions.items.len == 0 or1348 if (gen_scope.instructions.items.len == 0 or
1349 !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())1349 !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())
src-self-hosted/astgen.zig+25-15
...@@ -107,31 +107,46 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -107,31 +107,46 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
107 .NullLiteral => return rlWrap(mod, scope, rl, try nullLiteral(mod, scope, node.castTag(.NullLiteral).?)),107 .NullLiteral => return rlWrap(mod, scope, rl, try nullLiteral(mod, scope, node.castTag(.NullLiteral).?)),
108 .OptionalType => return rlWrap(mod, scope, rl, try optionalType(mod, scope, node.castTag(.OptionalType).?)),108 .OptionalType => return rlWrap(mod, scope, rl, try optionalType(mod, scope, node.castTag(.OptionalType).?)),
109 .UnwrapOptional => return unwrapOptional(mod, scope, rl, node.castTag(.UnwrapOptional).?),109 .UnwrapOptional => return unwrapOptional(mod, scope, rl, node.castTag(.UnwrapOptional).?),
110 .Block => return blockExpr(mod, scope, rl, node.castTag(.Block).?),110 .Block => return rlWrapVoid(mod, scope, rl, node, try blockExpr(mod, scope, node.castTag(.Block).?)),
111 .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?),
111 else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}),112 else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}),
112 }113 }
113}114}
114115
115pub fn blockExpr(116pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block) InnerError!void {
117 const tracy = trace(@src());
118 defer tracy.end();
119
120 try blockExprStmts(mod, parent_scope, &block_node.base, block_node.statements());
121}
122
123fn labeledBlockExpr(
116 mod: *Module,124 mod: *Module,
117 parent_scope: *Scope,125 parent_scope: *Scope,
118 rl: ResultLoc,126 rl: ResultLoc,
119 block_node: *ast.Node.Block,127 block_node: *ast.Node.LabeledBlock,
120) InnerError!*zir.Inst {128) InnerError!*zir.Inst {
121 const tracy = trace(@src());129 const tracy = trace(@src());
122 defer tracy.end();130 defer tracy.end();
123131
124 if (block_node.label) |label| {132 const statements = block_node.statements();
125 return mod.failTok(parent_scope, label, "TODO implement labeled blocks", .{});133
134 if (statements.len == 0) {
135 // Hot path for `{}`.
136 return rlWrapVoid(mod, parent_scope, rl, &block_node.base, {});
126 }137 }
127138
128 var block_arena = std.heap.ArenaAllocator.init(mod.gpa);139 return mod.failNode(parent_scope, &block_node.base, "TODO implement labeled blocks", .{});
129 defer block_arena.deinit();140}
130141
142fn blockExprStmts(mod: *Module, parent_scope: *Scope, node: *ast.Node, statements: []*ast.Node) !void {
131 const tree = parent_scope.tree();143 const tree = parent_scope.tree();
132144
145 var block_arena = std.heap.ArenaAllocator.init(mod.gpa);
146 defer block_arena.deinit();
147
133 var scope = parent_scope;148 var scope = parent_scope;
134 for (block_node.statements()) |statement| {149 for (statements) |statement| {
135 const src = tree.token_locs[statement.firstToken()].start;150 const src = tree.token_locs[statement.firstToken()].start;
136 _ = try addZIRNoOp(mod, scope, src, .dbg_stmt);151 _ = try addZIRNoOp(mod, scope, src, .dbg_stmt);
137 switch (statement.tag) {152 switch (statement.tag) {
...@@ -162,12 +177,6 @@ pub fn blockExpr(...@@ -162,12 +177,6 @@ pub fn blockExpr(
162 },177 },
163 }178 }
164 }179 }
165
166 const src = tree.token_locs[block_node.firstToken()].start;
167 return addZIRInstConst(mod, parent_scope, src, .{
168 .ty = Type.initTag(.void),
169 .val = Value.initTag(.void_value),
170 });
171}180}
172181
173fn varDecl(182fn varDecl(
...@@ -1184,6 +1193,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {...@@ -1184,6 +1193,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {
1184 .Slice,1193 .Slice,
1185 .Deref,1194 .Deref,
1186 .ArrayAccess,1195 .ArrayAccess,
1196 .Block,
1187 => return false,1197 => return false,
11881198
1189 // Forward the question to a sub-expression.1199 // Forward the question to a sub-expression.
...@@ -1210,11 +1220,11 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {...@@ -1210,11 +1220,11 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {
1210 .Switch,1220 .Switch,
1211 .Call,1221 .Call,
1212 .BuiltinCall, // TODO some of these can return false1222 .BuiltinCall, // TODO some of these can return false
1223 .LabeledBlock,
1213 => return true,1224 => return true,
12141225
1215 // Depending on AST properties, they may need memory locations.1226 // Depending on AST properties, they may need memory locations.
1216 .If => return node.castTag(.If).?.@"else" != null,1227 .If => return node.castTag(.If).?.@"else" != null,
1217 .Block => return node.castTag(.Block).?.label != null,
1218 }1228 }
1219 }1229 }
1220}1230}
src-self-hosted/translate_c.zig+46-44
...@@ -118,19 +118,31 @@ const Scope = struct {...@@ -118,19 +118,31 @@ const Scope = struct {
118 self.* = undefined;118 self.* = undefined;
119 }119 }
120120
121 fn complete(self: *Block, c: *Context) !*ast.Node.Block {121 fn complete(self: *Block, c: *Context) !*ast.Node {
122 // We reserve 1 extra statement if the parent is a Loop. This is in case of122 // We reserve 1 extra statement if the parent is a Loop. This is in case of
123 // do while, we want to put `if (cond) break;` at the end.123 // do while, we want to put `if (cond) break;` at the end.
124 const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .Loop);124 const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .Loop);
125 const node = try ast.Node.Block.alloc(c.arena, alloc_len);125 const rbrace = try appendToken(c, .RBrace, "}");
126 node.* = .{126 if (self.label) |label| {
127 .statements_len = self.statements.items.len,127 const node = try ast.Node.LabeledBlock.alloc(c.arena, alloc_len);
128 .lbrace = self.lbrace,128 node.* = .{
129 .rbrace = try appendToken(c, .RBrace, "}"),129 .statements_len = self.statements.items.len,
130 .label = self.label,130 .lbrace = self.lbrace,
131 };131 .rbrace = rbrace,
132 mem.copy(*ast.Node, node.statements(), self.statements.items);132 .label = label,
133 return node;133 };
134 mem.copy(*ast.Node, node.statements(), self.statements.items);
135 return &node.base;
136 } else {
137 const node = try ast.Node.Block.alloc(c.arena, alloc_len);
138 node.* = .{
139 .statements_len = self.statements.items.len,
140 .lbrace = self.lbrace,
141 .rbrace = rbrace,
142 };
143 mem.copy(*ast.Node, node.statements(), self.statements.items);
144 return &node.base;
145 }
134 }146 }
135147
136 /// Given the desired name, return a name that does not shadow anything from outer scopes.148 /// Given the desired name, return a name that does not shadow anything from outer scopes.
...@@ -320,15 +332,9 @@ pub const Context = struct {...@@ -320,15 +332,9 @@ pub const Context = struct {
320 return node;332 return node;
321 }333 }
322334
323 fn createBlock(c: *Context, label: ?[]const u8, statements_len: ast.NodeIndex) !*ast.Node.Block {335 fn createBlock(c: *Context, statements_len: ast.NodeIndex) !*ast.Node.Block {
324 const label_node = if (label) |l| blk: {
325 const ll = try appendIdentifier(c, l);
326 _ = try appendToken(c, .Colon, ":");
327 break :blk ll;
328 } else null;
329 const block_node = try ast.Node.Block.alloc(c.arena, statements_len);336 const block_node = try ast.Node.Block.alloc(c.arena, statements_len);
330 block_node.* = .{337 block_node.* = .{
331 .label = label_node,
332 .lbrace = try appendToken(c, .LBrace, "{"),338 .lbrace = try appendToken(c, .LBrace, "{"),
333 .statements_len = statements_len,339 .statements_len = statements_len,
334 .rbrace = undefined,340 .rbrace = undefined,
...@@ -640,8 +646,8 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -640,8 +646,8 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
640 var last = block_scope.statements.items[block_scope.statements.items.len - 1];646 var last = block_scope.statements.items[block_scope.statements.items.len - 1];
641 while (true) {647 while (true) {
642 switch (last.tag) {648 switch (last.tag) {
643 .Block => {649 .Block, .LabeledBlock => {
644 const stmts = last.castTag(.Block).?.statements();650 const stmts = last.blockStatements();
645 if (stmts.len == 0) break;651 if (stmts.len == 0) break;
646652
647 last = stmts[stmts.len - 1];653 last = stmts[stmts.len - 1];
...@@ -669,7 +675,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -669,7 +675,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
669 }675 }
670676
671 const body_node = try block_scope.complete(rp.c);677 const body_node = try block_scope.complete(rp.c);
672 proto_node.setTrailer("body_node", &body_node.base);678 proto_node.setTrailer("body_node", body_node);
673 return addTopLevelDecl(c, fn_name, &proto_node.base);679 return addTopLevelDecl(c, fn_name, &proto_node.base);
674}680}
675681
...@@ -1275,7 +1281,7 @@ fn transStmt(...@@ -1275,7 +1281,7 @@ fn transStmt(
1275 .WhileStmtClass => return transWhileLoop(rp, scope, @ptrCast(*const ZigClangWhileStmt, stmt)),1281 .WhileStmtClass => return transWhileLoop(rp, scope, @ptrCast(*const ZigClangWhileStmt, stmt)),
1276 .DoStmtClass => return transDoWhileLoop(rp, scope, @ptrCast(*const ZigClangDoStmt, stmt)),1282 .DoStmtClass => return transDoWhileLoop(rp, scope, @ptrCast(*const ZigClangDoStmt, stmt)),
1277 .NullStmtClass => {1283 .NullStmtClass => {
1278 const block = try rp.c.createBlock(null, 0);1284 const block = try rp.c.createBlock(0);
1279 block.rbrace = try appendToken(rp.c, .RBrace, "}");1285 block.rbrace = try appendToken(rp.c, .RBrace, "}");
1280 return &block.base;1286 return &block.base;
1281 },1287 },
...@@ -1356,7 +1362,7 @@ fn transBinaryOperator(...@@ -1356,7 +1362,7 @@ fn transBinaryOperator(
1356 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);1362 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
1357 grouped_expr.* = .{1363 grouped_expr.* = .{
1358 .lparen = lparen,1364 .lparen = lparen,
1359 .expr = &block_node.base,1365 .expr = block_node,
1360 .rparen = rparen,1366 .rparen = rparen,
1361 };1367 };
1362 return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);1368 return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
...@@ -1521,8 +1527,7 @@ fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompo...@@ -1521,8 +1527,7 @@ fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompo
1521 var block_scope = try Scope.Block.init(rp.c, scope, false);1527 var block_scope = try Scope.Block.init(rp.c, scope, false);
1522 defer block_scope.deinit();1528 defer block_scope.deinit();
1523 try transCompoundStmtInline(rp, &block_scope.base, stmt, &block_scope);1529 try transCompoundStmtInline(rp, &block_scope.base, stmt, &block_scope);
1524 const node = try block_scope.complete(rp.c);1530 return try block_scope.complete(rp.c);
1525 return &node.base;
1526}1531}
15271532
1528fn transCStyleCastExprClass(1533fn transCStyleCastExprClass(
...@@ -2589,7 +2594,7 @@ fn transDoWhileLoop(...@@ -2589,7 +2594,7 @@ fn transDoWhileLoop(
2589 // zig: if (!cond) break;2594 // zig: if (!cond) break;
2590 // zig: }2595 // zig: }
2591 const node = try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value);2596 const node = try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value);
2592 break :blk node.cast(ast.Node.Block).?;2597 break :blk node.castTag(.Block).?;
2593 } else blk: {2598 } else blk: {
2594 // the C statement is without a block, so we need to create a block to contain it.2599 // the C statement is without a block, so we need to create a block to contain it.
2595 // c: do2600 // c: do
...@@ -2600,7 +2605,7 @@ fn transDoWhileLoop(...@@ -2600,7 +2605,7 @@ fn transDoWhileLoop(
2600 // zig: if (!cond) break;2605 // zig: if (!cond) break;
2601 // zig: }2606 // zig: }
2602 new = true;2607 new = true;
2603 const block = try rp.c.createBlock(null, 2);2608 const block = try rp.c.createBlock(2);
2604 block.statements_len = 1; // over-allocated so we can add another below2609 block.statements_len = 1; // over-allocated so we can add another below
2605 block.statements()[0] = try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value);2610 block.statements()[0] = try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value);
2606 break :blk block;2611 break :blk block;
...@@ -2659,8 +2664,7 @@ fn transForLoop(...@@ -2659,8 +2664,7 @@ fn transForLoop(
2659 while_node.body = try transStmt(rp, &loop_scope, ZigClangForStmt_getBody(stmt), .unused, .r_value);2664 while_node.body = try transStmt(rp, &loop_scope, ZigClangForStmt_getBody(stmt), .unused, .r_value);
2660 if (block_scope) |*bs| {2665 if (block_scope) |*bs| {
2661 try bs.statements.append(&while_node.base);2666 try bs.statements.append(&while_node.base);
2662 const node = try bs.complete(rp.c);2667 return try bs.complete(rp.c);
2663 return &node.base;
2664 } else {2668 } else {
2665 _ = try appendToken(rp.c, .Semicolon, ";");2669 _ = try appendToken(rp.c, .Semicolon, ";");
2666 return &while_node.base;2670 return &while_node.base;
...@@ -2768,7 +2772,7 @@ fn transSwitch(...@@ -2768,7 +2772,7 @@ fn transSwitch(
27682772
2769 const result_node = try switch_scope.pending_block.complete(rp.c);2773 const result_node = try switch_scope.pending_block.complete(rp.c);
2770 switch_scope.pending_block.deinit();2774 switch_scope.pending_block.deinit();
2771 return &result_node.base;2775 return result_node;
2772}2776}
27732777
2774fn transCase(2778fn transCase(
...@@ -2820,7 +2824,7 @@ fn transCase(...@@ -2820,7 +2824,7 @@ fn transCase(
2820 switch_scope.pending_block.deinit();2824 switch_scope.pending_block.deinit();
2821 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);2825 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
28222826
2823 try switch_scope.pending_block.statements.append(&pending_node.base);2827 try switch_scope.pending_block.statements.append(pending_node);
28242828
2825 return transStmt(rp, scope, ZigClangCaseStmt_getSubStmt(stmt), .unused, .r_value);2829 return transStmt(rp, scope, ZigClangCaseStmt_getSubStmt(stmt), .unused, .r_value);
2826}2830}
...@@ -2857,7 +2861,7 @@ fn transDefault(...@@ -2857,7 +2861,7 @@ fn transDefault(
2857 const pending_node = try switch_scope.pending_block.complete(rp.c);2861 const pending_node = try switch_scope.pending_block.complete(rp.c);
2858 switch_scope.pending_block.deinit();2862 switch_scope.pending_block.deinit();
2859 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);2863 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
2860 try switch_scope.pending_block.statements.append(&pending_node.base);2864 try switch_scope.pending_block.statements.append(pending_node);
28612865
2862 return transStmt(rp, scope, ZigClangDefaultStmt_getSubStmt(stmt), .unused, .r_value);2866 return transStmt(rp, scope, ZigClangDefaultStmt_getSubStmt(stmt), .unused, .r_value);
2863}2867}
...@@ -2972,7 +2976,7 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr,...@@ -2972,7 +2976,7 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr,
2972 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);2976 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
2973 grouped_expr.* = .{2977 grouped_expr.* = .{
2974 .lparen = lparen,2978 .lparen = lparen,
2975 .expr = &block_node.base,2979 .expr = block_node,
2976 .rparen = rparen,2980 .rparen = rparen,
2977 };2981 };
2978 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);2982 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
...@@ -3304,7 +3308,7 @@ fn transCreatePreCrement(...@@ -3304,7 +3308,7 @@ fn transCreatePreCrement(
3304 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);3308 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
3305 grouped_expr.* = .{3309 grouped_expr.* = .{
3306 .lparen = try appendToken(rp.c, .LParen, "("),3310 .lparen = try appendToken(rp.c, .LParen, "("),
3307 .expr = &block_node.base,3311 .expr = block_node,
3308 .rparen = try appendToken(rp.c, .RParen, ")"),3312 .rparen = try appendToken(rp.c, .RParen, ")"),
3309 };3313 };
3310 return &grouped_expr.base;3314 return &grouped_expr.base;
...@@ -3398,7 +3402,7 @@ fn transCreatePostCrement(...@@ -3398,7 +3402,7 @@ fn transCreatePostCrement(
3398 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);3402 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
3399 grouped_expr.* = .{3403 grouped_expr.* = .{
3400 .lparen = try appendToken(rp.c, .LParen, "("),3404 .lparen = try appendToken(rp.c, .LParen, "("),
3401 .expr = &block_node.base,3405 .expr = block_node,
3402 .rparen = try appendToken(rp.c, .RParen, ")"),3406 .rparen = try appendToken(rp.c, .RParen, ")"),
3403 };3407 };
3404 return &grouped_expr.base;3408 return &grouped_expr.base;
...@@ -3589,7 +3593,7 @@ fn transCreateCompoundAssign(...@@ -3589,7 +3593,7 @@ fn transCreateCompoundAssign(
3589 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);3593 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
3590 grouped_expr.* = .{3594 grouped_expr.* = .{
3591 .lparen = try appendToken(rp.c, .LParen, "("),3595 .lparen = try appendToken(rp.c, .LParen, "("),
3592 .expr = &block_node.base,3596 .expr = block_node,
3593 .rparen = try appendToken(rp.c, .RParen, ")"),3597 .rparen = try appendToken(rp.c, .RParen, ")"),
3594 };3598 };
3595 return &grouped_expr.base;3599 return &grouped_expr.base;
...@@ -3748,7 +3752,7 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const...@@ -3748,7 +3752,7 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const
3748 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);3752 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
3749 grouped_expr.* = .{3753 grouped_expr.* = .{
3750 .lparen = lparen,3754 .lparen = lparen,
3751 .expr = &block_node.base,3755 .expr = block_node,
3752 .rparen = try appendToken(rp.c, .RParen, ")"),3756 .rparen = try appendToken(rp.c, .RParen, ")"),
3753 };3757 };
3754 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);3758 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
...@@ -4191,7 +4195,7 @@ fn transCreateNodeAssign(...@@ -4191,7 +4195,7 @@ fn transCreateNodeAssign(
4191 const block_node = try block_scope.complete(rp.c);4195 const block_node = try block_scope.complete(rp.c);
4192 // semicolon must immediately follow rbrace because it is the last token in a block4196 // semicolon must immediately follow rbrace because it is the last token in a block
4193 _ = try appendToken(rp.c, .Semicolon, ";");4197 _ = try appendToken(rp.c, .Semicolon, ";");
4194 return &block_node.base;4198 return block_node;
4195}4199}
41964200
4197fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node {4201fn 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...@@ -4484,7 +4488,6 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a
44844488
4485 const block = try ast.Node.Block.alloc(c.arena, 1);4489 const block = try ast.Node.Block.alloc(c.arena, 1);
4486 block.* = .{4490 block.* = .{
4487 .label = null,
4488 .lbrace = block_lbrace,4491 .lbrace = block_lbrace,
4489 .statements_len = 1,4492 .statements_len = 1,
4490 .rbrace = try appendToken(c, .RBrace, "}"),4493 .rbrace = try appendToken(c, .RBrace, "}"),
...@@ -5475,9 +5478,9 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -5475,9 +5478,9 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
5475 if (last != .Eof and last != .Nl)5478 if (last != .Eof and last != .Nl)
5476 return m.fail(c, "unable to translate C expr: unexpected token .{}", .{@tagName(last)});5479 return m.fail(c, "unable to translate C expr: unexpected token .{}", .{@tagName(last)});
5477 _ = try appendToken(c, .Semicolon, ";");5480 _ = try appendToken(c, .Semicolon, ";");
5478 const type_of_arg = if (expr.tag != .Block) expr else blk: {5481 const type_of_arg = if (!expr.tag.isBlock()) expr else blk: {
5479 const blk = @fieldParentPtr(ast.Node.Block, "base", expr);5482 const stmts = expr.blockStatements();
5480 const blk_last = blk.statements()[blk.statements_len - 1];5483 const blk_last = stmts[stmts.len - 1];
5481 const br = blk_last.cast(ast.Node.ControlFlowExpression).?;5484 const br = blk_last.cast(ast.Node.ControlFlowExpression).?;
5482 break :blk br.getRHS().?;5485 break :blk br.getRHS().?;
5483 };5486 };
...@@ -5500,7 +5503,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -5500,7 +5503,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
5500 .visib_token = pub_tok,5503 .visib_token = pub_tok,
5501 .extern_export_inline_token = inline_tok,5504 .extern_export_inline_token = inline_tok,
5502 .name_token = name_tok,5505 .name_token = name_tok,
5503 .body_node = &block_node.base,5506 .body_node = block_node,
5504 });5507 });
5505 mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);5508 mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items);
55065509
...@@ -5555,8 +5558,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {...@@ -5555,8 +5558,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
55555558
5556 const break_node = try transCreateNodeBreak(c, block_scope.label, last);5559 const break_node = try transCreateNodeBreak(c, block_scope.label, last);
5557 try block_scope.statements.append(&break_node.base);5560 try block_scope.statements.append(&break_node.base);
5558 const block_node = try block_scope.complete(c);5561 return try block_scope.complete(c);
5559 return &block_node.base;
5560 },5562 },
5561 else => {5563 else => {
5562 m.i -= 1;5564 m.i -= 1;