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