| author | |
| committer | |
| log | d898945786b527b09ef056099e923e946425e146 |
| tree | 47db832a254a2278e393b7c10cc92dbd63fc008e |
| parent | 409ca8882939418b3d4cbd4be7a18daf1d4833aa |
4 files changed, 84 insertions(+), 64 deletions(-)
lib/std/zig/ast.zig+16-7| ... | ... | @@ -234,7 +234,9 @@ pub const Tree = struct { |
| 234 | 234 | .StringLiteral, |
| 235 | 235 | .GroupedExpression, |
| 236 | 236 | .BuiltinCallTwo, |
| 237 | .BuiltinCallTwoComma, | |
| 237 | 238 | .BuiltinCall, |
| 239 | .BuiltinCallComma, | |
| 238 | 240 | .ErrorSetDecl, |
| 239 | 241 | .AnyType, |
| 240 | 242 | .Comptime, |
| ... | ... | @@ -474,6 +476,7 @@ pub const Tree = struct { |
| 474 | 476 | .ErrorUnion, |
| 475 | 477 | .IfSimple, |
| 476 | 478 | .WhileSimple, |
| 479 | .FnDecl, | |
| 477 | 480 | => n = datas[n].rhs, |
| 478 | 481 | |
| 479 | 482 | .FieldAccess, |
| ... | ... | @@ -497,9 +500,7 @@ pub const Tree = struct { |
| 497 | 500 | .EnumLiteral, |
| 498 | 501 | => return main_tokens[n] + end_offset, |
| 499 | 502 | |
| 500 | .Call, | |
| 501 | .BuiltinCall, | |
| 502 | => { | |
| 503 | .Call => { | |
| 503 | 504 | end_offset += 1; // for the rparen |
| 504 | 505 | const params = tree.extraData(datas[n].rhs, Node.SubRange); |
| 505 | 506 | if (params.end - params.start == 0) { |
| ... | ... | @@ -526,6 +527,7 @@ pub const Tree = struct { |
| 526 | 527 | .Block, |
| 527 | 528 | .ContainerDecl, |
| 528 | 529 | .TaggedUnion, |
| 530 | .BuiltinCall, | |
| 529 | 531 | => { |
| 530 | 532 | end_offset += 1; // for the rbrace |
| 531 | 533 | if (datas[n].rhs - datas[n].lhs == 0) { |
| ... | ... | @@ -533,9 +535,12 @@ pub const Tree = struct { |
| 533 | 535 | } |
| 534 | 536 | n = tree.extra_data[datas[n].rhs - 1]; // last statement |
| 535 | 537 | }, |
| 536 | .ContainerDeclComma, .TaggedUnionComma => { | |
| 538 | .ContainerDeclComma, | |
| 539 | .TaggedUnionComma, | |
| 540 | .BuiltinCallComma, | |
| 541 | => { | |
| 537 | 542 | assert(datas[n].rhs - datas[n].lhs > 0); |
| 538 | end_offset += 2; // for the comma + rbrace | |
| 543 | end_offset += 2; // for the comma + rbrace/rparen | |
| 539 | 544 | n = tree.extra_data[datas[n].rhs - 1]; // last member |
| 540 | 545 | }, |
| 541 | 546 | .CallOne, |
| ... | ... | @@ -565,11 +570,12 @@ pub const Tree = struct { |
| 565 | 570 | } |
| 566 | 571 | }, |
| 567 | 572 | .ArrayInitDotTwoComma, |
| 573 | .BuiltinCallTwoComma, | |
| 568 | 574 | .StructInitDotTwoComma, |
| 569 | 575 | .ContainerDeclTwoComma, |
| 570 | 576 | .TaggedUnionTwoComma, |
| 571 | 577 | => { |
| 572 | end_offset += 2; // for the comma + rbrace | |
| 578 | end_offset += 2; // for the comma + rbrace/rparen | |
| 573 | 579 | if (datas[n].rhs != 0) { |
| 574 | 580 | n = datas[n].rhs; |
| 575 | 581 | } else if (datas[n].lhs != 0) { |
| ... | ... | @@ -690,7 +696,6 @@ pub const Tree = struct { |
| 690 | 696 | .Slice => unreachable, // TODO |
| 691 | 697 | .SwitchCaseOne => unreachable, // TODO |
| 692 | 698 | .SwitchRange => unreachable, // TODO |
| 693 | .FnDecl => unreachable, // TODO | |
| 694 | 699 | .ArrayType => unreachable, // TODO |
| 695 | 700 | .ArrayTypeSentinel => unreachable, // TODO |
| 696 | 701 | .PtrTypeAligned => unreachable, // TODO |
| ... | ... | @@ -1836,8 +1841,12 @@ pub const Node = struct { |
| 1836 | 1841 | GroupedExpression, |
| 1837 | 1842 | /// `@a(lhs, rhs)`. lhs and rhs may be omitted. |
| 1838 | 1843 | BuiltinCallTwo, |
| 1844 | /// Same as BuiltinCallTwo but there is known to be a trailing comma before the rparen. | |
| 1845 | BuiltinCallTwoComma, | |
| 1839 | 1846 | /// `@a(b, c)`. `sub_list[lhs..rhs]`. |
| 1840 | 1847 | BuiltinCall, |
| 1848 | /// Same as BuiltinCall but there is known to be a trailing comma before the rparen. | |
| 1849 | BuiltinCallComma, | |
| 1841 | 1850 | /// `error{a, b}`. |
| 1842 | 1851 | /// lhs and rhs both unused. |
| 1843 | 1852 | ErrorSetDecl, |
lib/std/zig/parse.zig+24-14| ... | ... | @@ -3676,7 +3676,6 @@ const Parser = struct { |
| 3676 | 3676 | |
| 3677 | 3677 | /// FnCallArguments <- LPAREN ExprList RPAREN |
| 3678 | 3678 | /// ExprList <- (Expr COMMA)* Expr? |
| 3679 | /// TODO detect when we can emit BuiltinCallTwo instead of BuiltinCall. | |
| 3680 | 3679 | fn parseBuiltinCall(p: *Parser) !Node.Index { |
| 3681 | 3680 | const builtin_token = p.assertToken(.Builtin); |
| 3682 | 3681 | _ = (try p.expectTokenRecoverable(.LParen)) orelse { |
| ... | ... | @@ -3708,7 +3707,7 @@ const Parser = struct { |
| 3708 | 3707 | .Comma => { |
| 3709 | 3708 | if (p.eatToken(.RParen)) |_| { |
| 3710 | 3709 | return p.addNode(.{ |
| 3711 | .tag = .BuiltinCallTwo, | |
| 3710 | .tag = .BuiltinCallTwoComma, | |
| 3712 | 3711 | .main_token = builtin_token, |
| 3713 | 3712 | .data = .{ |
| 3714 | 3713 | .lhs = param_one, |
| ... | ... | @@ -3739,7 +3738,7 @@ const Parser = struct { |
| 3739 | 3738 | .Comma => { |
| 3740 | 3739 | if (p.eatToken(.RParen)) |_| { |
| 3741 | 3740 | return p.addNode(.{ |
| 3742 | .tag = .BuiltinCallTwo, | |
| 3741 | .tag = .BuiltinCallTwoComma, | |
| 3743 | 3742 | .main_token = builtin_token, |
| 3744 | 3743 | .data = .{ |
| 3745 | 3744 | .lhs = param_one, |
| ... | ... | @@ -3776,10 +3775,30 @@ const Parser = struct { |
| 3776 | 3775 | try list.append(param); |
| 3777 | 3776 | switch (p.token_tags[p.nextToken()]) { |
| 3778 | 3777 | .Comma => { |
| 3779 | if (p.eatToken(.RParen)) |_| break; | |
| 3778 | if (p.eatToken(.RParen)) |_| { | |
| 3779 | const params = try p.listToSpan(list.items); | |
| 3780 | return p.addNode(.{ | |
| 3781 | .tag = .BuiltinCallComma, | |
| 3782 | .main_token = builtin_token, | |
| 3783 | .data = .{ | |
| 3784 | .lhs = params.start, | |
| 3785 | .rhs = params.end, | |
| 3786 | }, | |
| 3787 | }); | |
| 3788 | } | |
| 3780 | 3789 | continue; |
| 3781 | 3790 | }, |
| 3782 | .RParen => break, | |
| 3791 | .RParen => { | |
| 3792 | const params = try p.listToSpan(list.items); | |
| 3793 | return p.addNode(.{ | |
| 3794 | .tag = .BuiltinCall, | |
| 3795 | .main_token = builtin_token, | |
| 3796 | .data = .{ | |
| 3797 | .lhs = params.start, | |
| 3798 | .rhs = params.end, | |
| 3799 | }, | |
| 3800 | }); | |
| 3801 | }, | |
| 3783 | 3802 | else => { |
| 3784 | 3803 | // This is likely just a missing comma; |
| 3785 | 3804 | // give an error but continue parsing this list. |
| ... | ... | @@ -3790,15 +3809,6 @@ const Parser = struct { |
| 3790 | 3809 | }, |
| 3791 | 3810 | } |
| 3792 | 3811 | } |
| 3793 | const params = try p.listToSpan(list.items); | |
| 3794 | return p.addNode(.{ | |
| 3795 | .tag = .BuiltinCall, | |
| 3796 | .main_token = builtin_token, | |
| 3797 | .data = .{ | |
| 3798 | .lhs = params.start, | |
| 3799 | .rhs = params.end, | |
| 3800 | }, | |
| 3801 | }); | |
| 3802 | 3812 | } |
| 3803 | 3813 | |
| 3804 | 3814 | // string literal or multiline string literal |
lib/std/zig/parser_test.zig+29-34| ... | ... | @@ -263,38 +263,38 @@ test "zig fmt: trailing comma in fn parameter list" { |
| 263 | 263 | ); |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | //test "zig fmt: comptime struct field" { | |
| 267 | // try testCanonical( | |
| 268 | // \\const Foo = struct { | |
| 269 | // \\ a: i32, | |
| 270 | // \\ comptime b: i32 = 1234, | |
| 271 | // \\}; | |
| 272 | // \\ | |
| 273 | // ); | |
| 274 | //} | |
| 275 | // | |
| 266 | test "zig fmt: comptime struct field" { | |
| 267 | try testCanonical( | |
| 268 | \\const Foo = struct { | |
| 269 | \\ a: i32, | |
| 270 | \\ comptime b: i32 = 1234, | |
| 271 | \\}; | |
| 272 | \\ | |
| 273 | ); | |
| 274 | } | |
| 275 | ||
| 276 | 276 | //test "zig fmt: c pointer type" { |
| 277 | 277 | // try testCanonical( |
| 278 | 278 | // \\pub extern fn repro() [*c]const u8; |
| 279 | 279 | // \\ |
| 280 | 280 | // ); |
| 281 | 281 | //} |
| 282 | // | |
| 283 | //test "zig fmt: builtin call with trailing comma" { | |
| 284 | // try testCanonical( | |
| 285 | // \\pub fn main() void { | |
| 286 | // \\ @breakpoint(); | |
| 287 | // \\ _ = @boolToInt(a); | |
| 288 | // \\ _ = @call( | |
| 289 | // \\ a, | |
| 290 | // \\ b, | |
| 291 | // \\ c, | |
| 292 | // \\ ); | |
| 293 | // \\} | |
| 294 | // \\ | |
| 295 | // ); | |
| 296 | //} | |
| 297 | // | |
| 282 | ||
| 283 | test "zig fmt: builtin call with trailing comma" { | |
| 284 | try testCanonical( | |
| 285 | \\pub fn main() void { | |
| 286 | \\ @breakpoint(); | |
| 287 | \\ _ = @boolToInt(a); | |
| 288 | \\ _ = @call( | |
| 289 | \\ a, | |
| 290 | \\ b, | |
| 291 | \\ c, | |
| 292 | \\ ); | |
| 293 | \\} | |
| 294 | \\ | |
| 295 | ); | |
| 296 | } | |
| 297 | ||
| 298 | 298 | //test "zig fmt: asm expression with comptime content" { |
| 299 | 299 | // try testCanonical( |
| 300 | 300 | // \\comptime { |
| ... | ... | @@ -3988,14 +3988,9 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b |
| 3988 | 3988 | return error.ParseError; |
| 3989 | 3989 | } |
| 3990 | 3990 | |
| 3991 | var buffer = std.ArrayList(u8).init(allocator); | |
| 3992 | errdefer buffer.deinit(); | |
| 3993 | ||
| 3994 | const writer = buffer.writer(); | |
| 3995 | try std.zig.render(allocator, writer, tree); | |
| 3996 | const result = buffer.toOwnedSlice(); | |
| 3997 | anything_changed.* = !mem.eql(u8, result, source); | |
| 3998 | return result; | |
| 3991 | const formatted = try std.zig.render(allocator, tree); | |
| 3992 | anything_changed.* = !mem.eql(u8, formatted, source); | |
| 3993 | return formatted; | |
| 3999 | 3994 | } |
| 4000 | 3995 | fn testTransform(source: []const u8, expected_source: []const u8) !void { |
| 4001 | 3996 | const needed_alloc_count = x: { |
lib/std/zig/render.zig+15-9| ... | ... | @@ -22,13 +22,19 @@ pub const Error = error{ |
| 22 | 22 | const Writer = std.ArrayList(u8).Writer; |
| 23 | 23 | const Ais = std.io.AutoIndentingStream(Writer); |
| 24 | 24 | |
| 25 | /// Returns whether anything changed. | |
| 26 | /// `gpa` is used for allocating extra stack memory if needed, because | |
| 27 | /// this function utilizes recursion. | |
| 28 | pub fn render(gpa: *mem.Allocator, writer: Writer, tree: ast.Tree) Error!void { | |
| 29 | assert(tree.errors.len == 0); // cannot render an invalid tree | |
| 30 | var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, writer); | |
| 31 | return renderRoot(&auto_indenting_stream, tree); | |
| 25 | /// `gpa` is used both for allocating the resulting formatted source code, but also | |
| 26 | /// for allocating extra stack memory if needed, because this function utilizes recursion. | |
| 27 | /// Note: that's not actually true yet, see https://github.com/ziglang/zig/issues/1006. | |
| 28 | /// Caller owns the returned slice of bytes, allocated with `gpa`. | |
| 29 | pub fn render(gpa: *mem.Allocator, tree: ast.Tree) Error![]u8 { | |
| 30 | assert(tree.errors.len == 0); // Cannot render an invalid tree. | |
| 31 | ||
| 32 | var buffer = std.ArrayList(u8).init(gpa); | |
| 33 | defer buffer.deinit(); | |
| 34 | ||
| 35 | var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, buffer.writer()); | |
| 36 | try renderRoot(&auto_indenting_stream, tree); | |
| 37 | return buffer.toOwnedSlice(); | |
| 32 | 38 | } |
| 33 | 39 | |
| 34 | 40 | /// Assumes there are no tokens in between start and end. |
| ... | ... | @@ -770,7 +776,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 770 | 776 | // } |
| 771 | 777 | //}, |
| 772 | 778 | |
| 773 | .BuiltinCallTwo => { | |
| 779 | .BuiltinCallTwo, .BuiltinCallTwoComma => { | |
| 774 | 780 | if (datas[node].lhs == 0) { |
| 775 | 781 | const params = [_]ast.Node.Index{}; |
| 776 | 782 | return renderBuiltinCall(ais, tree, main_tokens[node], &params, space); |
| ... | ... | @@ -782,7 +788,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 782 | 788 | return renderBuiltinCall(ais, tree, main_tokens[node], &params, space); |
| 783 | 789 | } |
| 784 | 790 | }, |
| 785 | .BuiltinCall => { | |
| 791 | .BuiltinCall, .BuiltinCallComma => { | |
| 786 | 792 | const params = tree.extra_data[datas[node].lhs..datas[node].rhs]; |
| 787 | 793 | return renderBuiltinCall(ais, tree, main_tokens[node], params, space); |
| 788 | 794 | }, |