From 85ca611af1d7401dd336f4655a0ab15640cc8424 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 15:37:47 -0400 Subject: zig fmt: put nested struct inits on newlines See #1003 --- std/zig/parser_test.zig | 9 +++++++++ std/zig/render.zig | 12 +++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 9d5e64a66f..d321f78668 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,12 @@ +test "zig fmt: nested struct literal with one item" { + try testCanonical( + \\const a = foo{ + \\ .item = bar{ .a = b }, + \\}; + \\ + ); +} + test "zig fmt: switch cases trailing comma" { try testTransform( \\fn switch_cases(x: i32) void { diff --git a/std/zig/render.zig b/std/zig/render.zig index 4691d836c3..04939324a8 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -431,12 +431,18 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind return; } - if (field_inits.len == 1) { - const field_init = field_inits.at(0).*; + if (field_inits.len == 1) blk: { + const field_init = ??field_inits.at(0).*.cast(ast.Node.FieldInitializer); + + if (field_init.expr.cast(ast.Node.SuffixOp)) |nested_suffix_op| { + if (nested_suffix_op.op == ast.Node.SuffixOp.Op.StructInitializer) { + break :blk; + } + } try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); try renderToken(tree, stream, lbrace, indent, Space.Space); - try renderExpression(allocator, stream, tree, indent, field_init, Space.Space); + try renderExpression(allocator, stream, tree, indent, &field_init.base, Space.Space); try renderToken(tree, stream, suffix_op.rtoken, indent, space); return; } -- cgit v1.2.3 From 0ab888c639dffcc48bc08a6ff186aa3da0ecbf74 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 16:37:55 -0400 Subject: zig fmt: parse extra comma in asm expressions --- std/zig/ast.zig | 2 +- std/zig/parse.zig | 8 +++-- std/zig/parser_test.zig | 44 ++++++++++++++++++++++- std/zig/render.zig | 95 ++++++++++++++++++++++++++++++++++++------------- 4 files changed, 120 insertions(+), 29 deletions(-) (limited to 'std') diff --git a/std/zig/ast.zig b/std/zig/ast.zig index 6c848b4a54..addd3a37e8 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -2071,7 +2071,7 @@ pub const Node = struct { const OutputList = SegmentedList(&AsmOutput, 2); const InputList = SegmentedList(&AsmInput, 2); - const ClobberList = SegmentedList(&Node, 2); + const ClobberList = SegmentedList(TokenIndex, 2); pub fn iterate(self: &Asm, index: usize) ?&Node { var i = index; diff --git a/std/zig/parse.zig b/std/zig/parse.zig index a6eb22a2d0..1bc64c3ddb 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -1153,9 +1153,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { continue; }, State.AsmClobberItems => |items| { - stack.append(State{ .AsmClobberItems = items }) catch unreachable; - try stack.append(State{ .IfToken = Token.Id.Comma }); - try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = try items.addOne() } }); + while (eatToken(&tok_it, &tree, Token.Id.StringLiteral)) |strlit| { + try items.push(strlit); + if (eatToken(&tok_it, &tree, Token.Id.Comma) == null) + break; + } continue; }, diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index d321f78668..ab15ca3a58 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,44 @@ +test "zig fmt: simple asm" { + try testTransform( + \\comptime { + \\ asm volatile ( + \\ \\.globl aoeu; + \\ \\.type aoeu, @function; + \\ \\.set aoeu, derp; + \\ ); + \\ + \\ asm ("not real assembly" + \\ :[a] "x" (x),); + \\ asm ("not real assembly" + \\ :[a] "x" (->i32),:[a] "x" (1),); + \\ asm ("still not real assembly" + \\ :::"a","b",); + \\} + , + \\comptime { + \\ asm volatile ( + \\ \\.globl aoeu; + \\ \\.type aoeu, @function; + \\ \\.set aoeu, derp; + \\ ); + \\ + \\ asm ("not real assembly" + \\ : [a] "x" (x) + \\ ); + \\ asm ("not real assembly" + \\ : [a] "x" (-> i32) + \\ : [a] "x" (1) + \\ ); + \\ asm ("still not real assembly" + \\ : + \\ : + \\ : "a", "b" + \\ ); + \\} + \\ + ); +} + test "zig fmt: nested struct literal with one item" { try testCanonical( \\const a = foo{ @@ -1295,7 +1336,8 @@ test "zig fmt: inline asm" { \\ : [ret] "={rax}" (-> usize) \\ : [number] "{rax}" (number), \\ [arg1] "{rdi}" (arg1) - \\ : "rcx", "r11"); + \\ : "rcx", "r11" + \\ ); \\} \\ ); diff --git a/std/zig/render.zig b/std/zig/render.zig index 04939324a8..c37f6e37c7 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -1203,19 +1203,35 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // ( } + if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) { + try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.None); + try renderToken(tree, stream, asm_node.rparen, indent, space); + return; + } + try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline); + const indent_once = indent + indent_delta; try stream.writeByteNTimes(' ', indent_once); - try stream.print(": "); + + const colon1 = tree.nextToken(asm_node.template.lastToken()); const indent_extra = indent_once + 2; - { + const colon2 = if (asm_node.outputs.len == 0) blk: { + try renderToken(tree, stream, colon1, indent, Space.Newline); // : + try stream.writeByteNTimes(' ', indent_once); + + break :blk tree.nextToken(colon1); + } else blk: { + try renderToken(tree, stream, colon1, indent, Space.Space); // : + var it = asm_node.outputs.iterator(0); - while (it.next()) |asm_output| { + while (true) { + const asm_output = ??it.next(); const node = &(asm_output.*).base; - try renderExpression(allocator, stream, tree, indent_extra, node, Space.None); if (it.peek()) |next_asm_output| { + try renderExpression(allocator, stream, tree, indent_extra, node, Space.None); const next_node = &(next_asm_output.*).base; const comma = tree.prevToken(next_asm_output.*.firstToken()); @@ -1223,21 +1239,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExtraNewline(tree, stream, next_node); try stream.writeByteNTimes(' ', indent_extra); + } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) { + try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline); + try stream.writeByteNTimes(' ', indent); + try renderToken(tree, stream, asm_node.rparen, indent, space); + return; + } else { + try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline); + try stream.writeByteNTimes(' ', indent_once); + const comma_or_colon = tree.nextToken(node.lastToken()); + break :blk switch (tree.tokens.at(comma_or_colon).id) { + Token.Id.Comma => tree.nextToken(comma_or_colon), + else => comma_or_colon, + }; } } - } + }; - try stream.write("\n"); - try stream.writeByteNTimes(' ', indent_once); - try stream.write(": "); + const colon3 = if (asm_node.inputs.len == 0) blk: { + try renderToken(tree, stream, colon2, indent, Space.Newline); // : + try stream.writeByteNTimes(' ', indent_once); + + break :blk tree.nextToken(colon2); + } else blk: { + try renderToken(tree, stream, colon2, indent, Space.Space); // : - { var it = asm_node.inputs.iterator(0); - while (it.next()) |asm_input| { + while (true) { + const asm_input = ??it.next(); const node = &(asm_input.*).base; - try renderExpression(allocator, stream, tree, indent_extra, node, Space.None); if (it.peek()) |next_asm_input| { + try renderExpression(allocator, stream, tree, indent_extra, node, Space.None); const next_node = &(next_asm_input.*).base; const comma = tree.prevToken(next_asm_input.*.firstToken()); @@ -1245,26 +1278,40 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExtraNewline(tree, stream, next_node); try stream.writeByteNTimes(' ', indent_extra); + } else if (asm_node.clobbers.len == 0) { + try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline); + try stream.writeByteNTimes(' ', indent); + try renderToken(tree, stream, asm_node.rparen, indent, space); // ) + return; + } else { + try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline); + try stream.writeByteNTimes(' ', indent_once); + const comma_or_colon = tree.nextToken(node.lastToken()); + break :blk switch (tree.tokens.at(comma_or_colon).id) { + Token.Id.Comma => tree.nextToken(comma_or_colon), + else => comma_or_colon, + }; } } - } + }; - try stream.write("\n"); - try stream.writeByteNTimes(' ', indent_once); - try stream.write(": "); + try renderToken(tree, stream, colon3, indent, Space.Space); // : - { - var it = asm_node.clobbers.iterator(0); - while (it.next()) |node| { - try renderExpression(allocator, stream, tree, indent_once, node.*, Space.None); + var it = asm_node.clobbers.iterator(0); + while (true) { + const clobber_token = ??it.next(); - if (it.peek() != null) { - try stream.write(", "); - } + if (it.peek() == null) { + try renderToken(tree, stream, clobber_token.*, indent_once, Space.Newline); + try stream.writeByteNTimes(' ', indent); + try renderToken(tree, stream, asm_node.rparen, indent, space); + return; + } else { + try renderToken(tree, stream, clobber_token.*, indent_once, Space.None); + const comma = tree.nextToken(clobber_token.*); + try renderToken(tree, stream, comma, indent_once, Space.Space); // , } } - - try renderToken(tree, stream, asm_node.rparen, indent, space); }, ast.Node.Id.AsmInput => { -- cgit v1.2.3 From 0bef1f98247160cbd5101c763404c76ae287b2bd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 16:43:33 -0400 Subject: zig fmt: fix rendering of struct with no trailing comma on last field --- std/zig/parser_test.zig | 15 +++++++++++++++ std/zig/render.zig | 3 +-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index ab15ca3a58..e76d588088 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,18 @@ +test "zig fmt: no trailing comma on struct decl" { + try testTransform( + \\const RoundParam = struct { + \\ k: usize, s: u32, t: u32 + \\}; + , + \\const RoundParam = struct { + \\ k: usize, + \\ s: u32, + \\ t: u32, + \\}; + \\ + ); +} + test "zig fmt: simple asm" { try testTransform( \\comptime { diff --git a/std/zig/render.zig b/std/zig/render.zig index c37f6e37c7..dea06e3a7d 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -102,8 +102,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i } try renderToken(tree, stream, field.name_token, indent, Space.None); // name try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // : - try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.None); // type - try renderToken(tree, stream, tree.nextToken(field.lastToken()), indent, Space.Newline); // , + try renderTrailingComma(allocator, stream, tree, indent, field.type_expr, Space.Newline); // type, }, ast.Node.Id.UnionTag => { -- cgit v1.2.3 From 7e900d28be00e03eee2ec3703c0c45247b4748b1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 18:10:06 -0400 Subject: zig fmt: no space on switch range operator --- std/zig/parser_test.zig | 6 +++--- std/zig/render.zig | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index e76d588088..dfef594df7 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -69,7 +69,7 @@ test "zig fmt: switch cases trailing comma" { \\ switch (x) { \\ 1,2,3 => {}, \\ 4,5, => {}, - \\ 6...8, => {}, + \\ 6... 8, => {}, \\ else => {}, \\ } \\} @@ -79,7 +79,7 @@ test "zig fmt: switch cases trailing comma" { \\ 1, 2, 3 => {}, \\ 4, \\ 5, => {}, - \\ 6 ... 8 => {}, + \\ 6...8 => {}, \\ else => {}, \\ } \\} @@ -1091,7 +1091,7 @@ test "zig fmt: switch" { \\ 0 => {}, \\ 1 => unreachable, \\ 2, 3 => {}, - \\ 4 ... 7 => {}, + \\ 4...7 => {}, \\ 1 + 4 * 3 + 22 => {}, \\ else => { \\ const a = 1; diff --git a/std/zig/render.zig b/std/zig/render.zig index dea06e3a7d..67ec8f7632 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -244,7 +244,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const op_token = tree.tokens.at(infix_op_node.op_token); const op_space = switch (infix_op_node.op) { - ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion => Space.None, + ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None, else => Space.Space, }; try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs, op_space); -- cgit v1.2.3 From b8d4e05361d6a01ae1c0bf931e27e2bfdb25551d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 18:29:14 -0400 Subject: zig fmt: handle empty block with comment inside --- std/zig/parser_test.zig | 11 +++++++++++ std/zig/render.zig | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index dfef594df7..c115c5848f 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,14 @@ +test "zig fmt: empty block with only comment" { + try testCanonical( + \\comptime { + \\ { + \\ // comment + \\ } + \\} + \\ + ); +} + test "zig fmt: no trailing comma on struct decl" { try testTransform( \\const RoundParam = struct { diff --git a/std/zig/render.zig b/std/zig/render.zig index 67ec8f7632..90acb0e412 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -1519,7 +1519,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent const after_comment_token = tree.tokens.at(token_index + offset); const next_line_indent = switch (after_comment_token.id) { - Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent, + Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent - indent_delta, else => indent, }; try stream.writeByteNTimes(' ', next_line_indent); -- cgit v1.2.3 From cabf7fa93b7250a69a3cfad417537c2a46414779 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 18:44:10 -0400 Subject: zig fmt: fn calls with trailing comma with params on new lines --- std/zig/parser_test.zig | 13 +++++++++++++ std/zig/render.zig | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index c115c5848f..4ce355dc87 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,16 @@ +test "zig fmt: trailing comma on fn call" { + try testCanonical( + \\comptime { + \\ var module = try Module.create( + \\ allocator, + \\ zig_lib_dir, + \\ full_cache_dir, + \\ ); + \\} + \\ + ); +} + test "zig fmt: empty block with only comment" { try testCanonical( \\comptime { diff --git a/std/zig/render.zig b/std/zig/render.zig index 90acb0e412..f068e652bb 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -374,7 +374,42 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); const lparen = tree.nextToken(suffix_op.lhs.lastToken()); - try renderToken(tree, stream, lparen, indent, Space.None); + + if (call_info.params.len == 0) { + try renderToken(tree, stream, lparen, indent, Space.None); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); + return; + } + + const src_has_trailing_comma = blk: { + const maybe_comma = tree.prevToken(suffix_op.rtoken); + break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma; + }; + + if (src_has_trailing_comma) { + const new_indent = indent + indent_delta; + try renderToken(tree, stream, lparen, new_indent, Space.Newline); + + var it = call_info.params.iterator(0); + while (true) { + const param_node = ??it.next(); + try stream.writeByteNTimes(' ', new_indent); + + if (it.peek()) |next_node| { + try renderExpression(allocator, stream, tree, new_indent, param_node.*, Space.None); + const comma = tree.nextToken(param_node.*.lastToken()); + try renderToken(tree, stream, comma, new_indent, Space.Newline); // , + try renderExtraNewline(tree, stream, next_node.*); + } else { + try renderTrailingComma(allocator, stream, tree, new_indent, param_node.*, Space.Newline); + try stream.writeByteNTimes(' ', indent); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); + return; + } + } + } + + try renderToken(tree, stream, lparen, indent, Space.None); // ( var it = call_info.params.iterator(0); while (it.next()) |param_node| { @@ -385,7 +420,6 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderToken(tree, stream, comma, indent, Space.Space); } } - try renderToken(tree, stream, suffix_op.rtoken, indent, space); }, -- cgit v1.2.3 From 349365d9a483bc6be8c1677149ec1a31a789e4b2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 19:32:28 -0400 Subject: zig fmt: better multiline string formatting --- std/zig/parser_test.zig | 29 +++++++++++++++++++++++++++++ std/zig/render.zig | 36 ++++++++++++++++++++++++++++++------ std/zig/tokenizer.zig | 12 ------------ 3 files changed, 59 insertions(+), 18 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 4ce355dc87..152056c6b4 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,32 @@ +test "zig fmt: multiline string with backslash at end of line" { + try testCanonical( + \\comptime { + \\ err( + \\ \\\ + \\ ); + \\} + \\ + ); +} + +test "zig fmt: multiline string parameter in fn call with trailing comma" { + try testCanonical( + \\fn foo() void { + \\ try stdout.print( + \\ \\ZIG_CMAKE_BINARY_DIR {} + \\ \\ZIG_C_HEADER_FILES {} + \\ \\ZIG_DIA_GUIDS_LIB {} + \\ \\ + \\ , + \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR), + \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER), + \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB), + \\ ); + \\} + \\ + ); +} + test "zig fmt: trailing comma on fn call" { try testCanonical( \\comptime { diff --git a/std/zig/render.zig b/std/zig/render.zig index f068e652bb..409828e070 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -393,15 +393,21 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = call_info.params.iterator(0); while (true) { const param_node = ??it.next(); - try stream.writeByteNTimes(' ', new_indent); + + const param_node_new_indent = if (param_node.*.id == ast.Node.Id.MultilineStringLiteral) blk: { + break :blk indent; + } else blk: { + try stream.writeByteNTimes(' ', new_indent); + break :blk new_indent; + }; if (it.peek()) |next_node| { - try renderExpression(allocator, stream, tree, new_indent, param_node.*, Space.None); + try renderExpression(allocator, stream, tree, param_node_new_indent, param_node.*, Space.None); const comma = tree.nextToken(param_node.*.lastToken()); try renderToken(tree, stream, comma, new_indent, Space.Newline); // , try renderExtraNewline(tree, stream, next_node.*); } else { - try renderTrailingComma(allocator, stream, tree, new_indent, param_node.*, Space.Newline); + try renderTrailingComma(allocator, stream, tree, param_node_new_indent, param_node.*, Space.Newline); try stream.writeByteNTimes(' ', indent); try renderToken(tree, stream, suffix_op.rtoken, indent, space); return; @@ -1502,7 +1508,13 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent if (next_token.id != Token.Id.LineComment) { switch (space) { Space.None, Space.NoNewline, Space.NoIndent => return, - Space.Newline => return stream.write("\n"), + Space.Newline => { + if (next_token.id == Token.Id.MultilineStringLiteralLine) { + return; + } else { + return stream.write("\n"); + } + }, Space.Space => return stream.writeByte(' '), Space.NoComment => unreachable, } @@ -1526,7 +1538,13 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent }; try stream.writeByteNTimes(' ', next_line_indent); }, - Space.Newline, Space.NoIndent => try stream.write("\n"), + Space.Newline, Space.NoIndent => { + if (next_token.id == Token.Id.MultilineStringLiteralLine) { + return; + } else { + return stream.write("\n"); + } + }, Space.NoNewline => {}, Space.NoComment => unreachable, } @@ -1547,7 +1565,13 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent next_token = tree.tokens.at(token_index + offset); if (next_token.id != Token.Id.LineComment) { switch (space) { - Space.Newline, Space.NoIndent => try stream.writeByte('\n'), + Space.Newline, Space.NoIndent => { + if (next_token.id == Token.Id.MultilineStringLiteralLine) { + return; + } else { + return stream.write("\n"); + } + }, Space.None, Space.Space => { try stream.writeByte('\n'); diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig index f4cd847dff..b90a40108f 100644 --- a/std/zig/tokenizer.zig +++ b/std/zig/tokenizer.zig @@ -217,7 +217,6 @@ pub const Tokenizer = struct { StringLiteral, StringLiteralBackslash, MultilineStringLiteralLine, - MultilineStringLiteralLineBackslash, CharLiteral, CharLiteralBackslash, CharLiteralEscape1, @@ -655,9 +654,6 @@ pub const Tokenizer = struct { }, State.MultilineStringLiteralLine => switch (c) { - '\\' => { - state = State.MultilineStringLiteralLineBackslash; - }, '\n' => { self.index += 1; break; @@ -665,13 +661,6 @@ pub const Tokenizer = struct { else => self.checkLiteralCharacter(), }, - State.MultilineStringLiteralLineBackslash => switch (c) { - '\n' => break, // Look for this error later. - else => { - state = State.MultilineStringLiteralLine; - }, - }, - State.Bang => switch (c) { '=' => { result.id = Token.Id.BangEqual; @@ -1010,7 +999,6 @@ pub const Tokenizer = struct { State.FloatExponentUnsignedHex, State.SawAtSign, State.Backslash, - State.MultilineStringLiteralLineBackslash, State.CharLiteral, State.CharLiteralBackslash, State.CharLiteralEscape1, -- cgit v1.2.3 From 118d41ef8325b4c1ca8be1fea66c2e8368b67e32 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 22:59:46 -0400 Subject: zig fmt: support array literal row size hint See #1003 --- std/mem.zig | 8 ++++ std/zig/parser_test.zig | 59 ++++++++++++++++++++++++++ std/zig/render.zig | 108 ++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 167 insertions(+), 8 deletions(-) (limited to 'std') diff --git a/std/mem.zig b/std/mem.zig index 617c1de2f5..70f2fe22ac 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -177,6 +177,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { return true; } +/// Returns true if all elements in a slice are equal to the scalar value provided +pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool { + for (slice) |item| { + if (item != scalar) return false; + } + return true; +} + /// Copies ::m to newly allocated memory. Caller is responsible to free it. pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) ![]T { const new_buf = try allocator.alloc(T, m.len); diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 152056c6b4..909220a6f6 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,62 @@ +test "zig fmt: array literal with hint" { + try testTransform( + \\const a = []u8{ + \\ 1, 2, // + \\ 3, + \\ 4, + \\ 5, + \\ 6, + \\ 7 }; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, + \\ 4, + \\ 5, + \\ 6, + \\ 7, 8 }; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, + \\ 4, + \\ 5, + \\ 6, // blah + \\ 7, 8 }; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, // + \\ 4, + \\ 5, + \\ 6, + \\ 7 }; + , + \\const a = []u8{ + \\ 1, 2, // + \\ 3, 4, // + \\ 5, 6, // + \\ 7, + \\}; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, 4, // + \\ 5, 6, // + \\ 7, 8, // + \\}; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, 4, // + \\ 5, 6, // blah + \\ 7, 8, // + \\}; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, 4, // + \\ 5, 6, // + \\ 7, + \\}; + \\ + ); +} + test "zig fmt: multiline string with backslash at end of line" { try testCanonical( \\comptime { diff --git a/std/zig/render.zig b/std/zig/render.zig index 409828e070..fa3755b719 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -19,7 +19,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf( var tok_it = tree.tokens.iterator(0); while (tok_it.next()) |token| { if (token.id != Token.Id.LineComment) break; - try stream.print("{}\n", tree.tokenSlicePtr(token)); + try stream.print("{}\n", mem.trimRight(u8, tree.tokenSlicePtr(token), " ")); if (tok_it.peek()) |next_token| { const loc = tree.tokenLocationPtr(token.end, next_token); if (loc.line >= 2) { @@ -532,12 +532,73 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + // scan to find row size + const maybe_row_size: ?usize = blk: { + var count: usize = 0; + var it = exprs.iterator(0); + var prev_token = (??it.peek()).*.lastToken() + 1; + while (it.next()) |expr| { + const expr_last_token = expr.*.lastToken() + 1; + const next_token = tree.tokens.at(expr_last_token + 1); + const loc = tree.tokenLocationPtr(tree.tokens.at(prev_token).end, next_token); + if (loc.line != 0) break :blk null; + if (next_token.id == Token.Id.LineComment) { + const trimmed = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "); + if (trimmed.len == 2) { + break :blk count; + } else { + break :blk null; + } + } + prev_token = expr_last_token; + count += 1; + } + break :blk null; + }; + + const new_indent = indent + indent_delta; try renderToken(tree, stream, lbrace, new_indent, Space.Newline); + try stream.writeByteNTimes(' ', new_indent); + + if (maybe_row_size) |row_size| { + var it = exprs.iterator(0); + var i: usize = 0; + while (it.next()) |expr| { + if (it.peek()) |next_expr| { + try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None); + + const comma = tree.nextToken(expr.*.lastToken()); + + if (i != row_size) { + try renderToken(tree, stream, comma, new_indent, Space.IgnoreEmptyComment); // , + i += 1; + continue; + } + i = 0; + + try renderToken(tree, stream, comma, new_indent, Space.NoIndent); // , + + const next_token = tree.tokens.at(comma + 1); + if (next_token.id != Token.Id.LineComment) { + try stream.print(" //\n"); + } + + try renderExtraNewline(tree, stream, next_expr.*); + try stream.writeByteNTimes(' ', new_indent); + } else if (i == row_size) { + try renderTrailingCommaAndEmptyComment(allocator, stream, tree, new_indent, expr.*); // , // + } else { + try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline); // , + } + } + try stream.writeByteNTimes(' ', indent); + try renderToken(tree, stream, suffix_op.rtoken, indent, space); + return; + } var it = exprs.iterator(0); while (it.next()) |expr| { - try stream.writeByteNTimes(' ', new_indent); if (it.peek()) |next_expr| { try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None); @@ -546,6 +607,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderToken(tree, stream, comma, new_indent, Space.Newline); // , try renderExtraNewline(tree, stream, next_expr.*); + try stream.writeByteNTimes(' ', new_indent); } else { try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline); } @@ -1496,11 +1558,12 @@ const Space = enum { NoNewline, NoIndent, NoComment, + IgnoreEmptyComment, }; fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void { var token = tree.tokens.at(token_index); - try stream.write(tree.tokenSlicePtr(token)); + try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " ")); if (space == Space.NoComment) return; @@ -1515,15 +1578,19 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent return stream.write("\n"); } }, - Space.Space => return stream.writeByte(' '), + Space.Space, Space.IgnoreEmptyComment => return stream.writeByte(' '), Space.NoComment => unreachable, } } + if (space == Space.IgnoreEmptyComment and mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2) { + return stream.writeByte(' '); + } + var loc = tree.tokenLocationPtr(token.end, next_token); var offset: usize = 1; if (loc.line == 0) { - try stream.print(" {}", tree.tokenSlicePtr(next_token)); + try stream.print(" {}", mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ")); offset = 2; token = next_token; next_token = tree.tokens.at(token_index + offset); @@ -1546,7 +1613,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent } }, Space.NoNewline => {}, - Space.NoComment => unreachable, + Space.NoComment, Space.IgnoreEmptyComment => unreachable, } return; } @@ -1558,7 +1625,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent const newline_count = if (loc.line == 1) u8(1) else u8(2); try stream.writeByteNTimes('\n', newline_count); try stream.writeByteNTimes(' ', indent); - try stream.write(tree.tokenSlicePtr(next_token)); + try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ")); offset += 1; token = next_token; @@ -1583,7 +1650,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent try stream.writeByteNTimes(' ', next_line_indent); }, Space.NoNewline => {}, - Space.NoComment => unreachable, + Space.NoComment, Space.IgnoreEmptyComment => unreachable, } return; } @@ -1621,3 +1688,28 @@ fn renderTrailingComma(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, }, } } + +fn renderTrailingCommaAndEmptyComment(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void +{ + const end_token = base.lastToken() + 1; + switch (tree.tokens.at(end_token).id) { + Token.Id.Comma => { + try renderExpression(allocator, stream, tree, indent, base, Space.None); + try renderToken(tree, stream, end_token, indent, Space.Space); // , + + const next_token = tree.tokens.at(end_token + 1); + if (next_token.id != Token.Id.LineComment) { + try stream.print("//\n"); + } + }, + Token.Id.LineComment => { + try renderExpression(allocator, stream, tree, indent, base, Space.NoComment); + try stream.write(", "); + try renderToken(tree, stream, end_token, indent, Space.Newline); + }, + else => { + try renderExpression(allocator, stream, tree, indent, base, Space.None); + try stream.write(", //\n"); + }, + } +} -- cgit v1.2.3 From b184ae5ca5d3d3c0a4b9de564a6e30555e596e65 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 18:16:39 -0400 Subject: run zig fmt on some of the codebase See #1003 --- doc/docgen.zig | 182 +++++--- example/guess_number/main.zig | 2 +- example/hello_world/hello_libc.zig | 3 +- example/mix_o_files/build.zig | 4 +- example/shared_library/build.zig | 4 +- src-self-hosted/introspect.zig | 4 +- src-self-hosted/ir.zig | 1 - src-self-hosted/main.zig | 169 +++++--- src-self-hosted/target.zig | 3 +- std/array_list.zig | 9 +- std/base64.zig | 117 ++--- std/buf_map.zig | 4 +- std/buf_set.zig | 4 +- std/build.zig | 59 +-- std/c/darwin.zig | 2 +- std/c/index.zig | 12 +- std/crypto/md5.zig | 138 +++--- std/crypto/sha1.zig | 86 ++-- std/crypto/sha2.zig | 861 +++++++++++++++++++------------------ std/crypto/test.zig | 2 +- std/crypto/throughput_test.zig | 2 +- std/cstr.zig | 4 +- std/debug/failing_allocator.zig | 4 +- std/debug/index.zig | 18 +- std/dwarf.zig | 2 - std/elf.zig | 42 +- std/event.zig | 13 +- std/fmt/errol/enum3.zig | 7 +- 28 files changed, 913 insertions(+), 845 deletions(-) (limited to 'std') diff --git a/doc/docgen.zig b/doc/docgen.zig index bd9dc6c147..7dc444f127 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -95,7 +95,7 @@ const Tokenizer = struct { }; fn init(source_file_name: []const u8, buffer: []const u8) Tokenizer { - return Tokenizer { + return Tokenizer{ .buffer = buffer, .index = 0, .state = State.Start, @@ -105,7 +105,7 @@ const Tokenizer = struct { } fn next(self: &Tokenizer) Token { - var result = Token { + var result = Token{ .id = Token.Id.Eof, .start = self.index, .end = undefined, @@ -197,7 +197,7 @@ const Tokenizer = struct { }; fn getTokenLocation(self: &Tokenizer, token: &const Token) Location { - var loc = Location { + var loc = Location{ .line = 0, .column = 0, .line_start = 0, @@ -346,7 +346,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc { break; }, Token.Id.Content => { - try nodes.append(Node {.Content = tokenizer.buffer[token.start..token.end] }); + try nodes.append(Node{ .Content = tokenizer.buffer[token.start..token.end] }); }, Token.Id.BracketOpen => { const tag_token = try eatToken(tokenizer, Token.Id.TagContent); @@ -365,11 +365,13 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc { header_stack_size += 1; const urlized = try urlize(allocator, content); - try nodes.append(Node{.HeaderOpen = HeaderOpen { - .name = content, - .url = urlized, - .n = header_stack_size, - }}); + try nodes.append(Node{ + .HeaderOpen = HeaderOpen{ + .name = content, + .url = urlized, + .n = header_stack_size, + }, + }); if (try urls.put(urlized, tag_token)) |other_tag_token| { parseError(tokenizer, tag_token, "duplicate header url: #{}", urlized) catch {}; parseError(tokenizer, other_tag_token, "other tag here") catch {}; @@ -407,14 +409,14 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc { switch (see_also_tok.id) { Token.Id.TagContent => { const content = tokenizer.buffer[see_also_tok.start..see_also_tok.end]; - try list.append(SeeAlsoItem { + try list.append(SeeAlsoItem{ .name = content, .token = see_also_tok, }); }, Token.Id.Separator => {}, Token.Id.BracketClose => { - try nodes.append(Node {.SeeAlso = list.toOwnedSlice() } ); + try nodes.append(Node{ .SeeAlso = list.toOwnedSlice() }); break; }, else => return parseError(tokenizer, see_also_tok, "invalid see_also token"), @@ -438,8 +440,8 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc { } }; - try nodes.append(Node { - .Link = Link { + try nodes.append(Node{ + .Link = Link{ .url = try urlize(allocator, url_name), .name = name, .token = name_tok, @@ -463,24 +465,24 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc { var code_kind_id: Code.Id = undefined; var is_inline = false; if (mem.eql(u8, code_kind_str, "exe")) { - code_kind_id = Code.Id { .Exe = ExpectedOutcome.Succeed }; + code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Succeed }; } else if (mem.eql(u8, code_kind_str, "exe_err")) { - code_kind_id = Code.Id { .Exe = ExpectedOutcome.Fail }; + code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Fail }; } else if (mem.eql(u8, code_kind_str, "test")) { code_kind_id = Code.Id.Test; } else if (mem.eql(u8, code_kind_str, "test_err")) { - code_kind_id = Code.Id { .TestError = name}; + code_kind_id = Code.Id{ .TestError = name }; name = "test"; } else if (mem.eql(u8, code_kind_str, "test_safety")) { - code_kind_id = Code.Id { .TestSafety = name}; + code_kind_id = Code.Id{ .TestSafety = name }; name = "test"; } else if (mem.eql(u8, code_kind_str, "obj")) { - code_kind_id = Code.Id { .Obj = null }; + code_kind_id = Code.Id{ .Obj = null }; } else if (mem.eql(u8, code_kind_str, "obj_err")) { - code_kind_id = Code.Id { .Obj = name }; + code_kind_id = Code.Id{ .Obj = name }; name = "test"; } else if (mem.eql(u8, code_kind_str, "syntax")) { - code_kind_id = Code.Id { .Obj = null }; + code_kind_id = Code.Id{ .Obj = null }; is_inline = true; } else { return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {}", code_kind_str); @@ -514,17 +516,20 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc { return parseError(tokenizer, end_code_tag, "invalid token inside code_begin: {}", end_tag_name); } _ = try eatToken(tokenizer, Token.Id.BracketClose); - } else unreachable; // TODO issue #707 - try nodes.append(Node {.Code = Code { - .id = code_kind_id, - .name = name, - .source_token = source_token, - .is_inline = is_inline, - .mode = mode, - .link_objects = link_objects.toOwnedSlice(), - .target_windows = target_windows, - .link_libc = link_libc, - }}); + } else + unreachable; // TODO issue #707 + try nodes.append(Node{ + .Code = Code{ + .id = code_kind_id, + .name = name, + .source_token = source_token, + .is_inline = is_inline, + .mode = mode, + .link_objects = link_objects.toOwnedSlice(), + .target_windows = target_windows, + .link_libc = link_libc, + }, + }); tokenizer.code_node_count += 1; } else { return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name); @@ -534,7 +539,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc { } } - return Toc { + return Toc{ .nodes = nodes.toOwnedSlice(), .toc = toc_buf.toOwnedSlice(), .urls = urls, @@ -727,16 +732,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name); const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext); try io.writeFile(allocator, tmp_source_file_name, trimmed_raw_source); - + switch (code.id) { Code.Id.Exe => |expected_outcome| { const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext); const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext); var build_args = std.ArrayList([]const u8).init(allocator); defer build_args.deinit(); - try build_args.appendSlice([][]const u8 {zig_exe, - "build-exe", tmp_source_file_name, - "--output", tmp_bin_file_name, + try build_args.appendSlice([][]const u8{ + zig_exe, + "build-exe", + tmp_source_file_name, + "--output", + tmp_bin_file_name, }); try out.print("
$ zig build-exe {}.zig", code.name);
                         switch (code.mode) {
@@ -766,10 +774,9 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                             try build_args.append("c");
                             try out.print(" --library c");
                         }
-                        _ = exec(allocator, build_args.toSliceConst()) catch return parseError(
-                            tokenizer, code.source_token, "example failed to compile");
+                        _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
 
-                        const run_args = [][]const u8 {tmp_bin_file_name};
+                        const run_args = [][]const u8{tmp_bin_file_name};
 
                         const result = if (expected_outcome == ExpectedOutcome.Fail) blk: {
                             const result = try os.ChildProcess.exec(allocator, run_args, null, null, max_doc_file_size);
@@ -777,7 +784,10 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                                 os.ChildProcess.Term.Exited => |exit_code| {
                                     if (exit_code == 0) {
                                         warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
-                                        for (run_args) |arg| warn("{} ", arg) else warn("\n");
+                                        for (run_args) |arg|
+                                            warn("{} ", arg)
+                                        else
+                                            warn("\n");
                                         return parseError(tokenizer, code.source_token, "example incorrectly compiled");
                                     }
                                 },
@@ -785,11 +795,9 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                             }
                             break :blk result;
                         } else blk: {
-                            break :blk exec(allocator, run_args) catch return parseError(
-                                tokenizer, code.source_token, "example crashed");
+                            break :blk exec(allocator, run_args) catch return parseError(tokenizer, code.source_token, "example crashed");
                         };
 
-                        
                         const escaped_stderr = try escapeHtml(allocator, result.stderr);
                         const escaped_stdout = try escapeHtml(allocator, result.stdout);
 
@@ -802,7 +810,11 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                         var test_args = std.ArrayList([]const u8).init(allocator);
                         defer test_args.deinit();
 
-                        try test_args.appendSlice([][]const u8 {zig_exe, "test", tmp_source_file_name});
+                        try test_args.appendSlice([][]const u8{
+                            zig_exe,
+                            "test",
+                            tmp_source_file_name,
+                        });
                         try out.print("
$ zig test {}.zig", code.name);
                         switch (code.mode) {
                             builtin.Mode.Debug => {},
@@ -821,13 +833,15 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                         }
                         if (code.target_windows) {
                             try test_args.appendSlice([][]const u8{
-                                "--target-os", "windows",
-                                "--target-arch", "x86_64",
-                                "--target-environ", "msvc",
+                                "--target-os",
+                                "windows",
+                                "--target-arch",
+                                "x86_64",
+                                "--target-environ",
+                                "msvc",
                             });
                         }
-                        const result = exec(allocator, test_args.toSliceConst()) catch return parseError(
-                            tokenizer, code.source_token, "test failed");
+                        const result = exec(allocator, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
                         const escaped_stderr = try escapeHtml(allocator, result.stderr);
                         const escaped_stdout = try escapeHtml(allocator, result.stdout);
                         try out.print("\n{}{}
\n", escaped_stderr, escaped_stdout); @@ -836,7 +850,13 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var var test_args = std.ArrayList([]const u8).init(allocator); defer test_args.deinit(); - try test_args.appendSlice([][]const u8 {zig_exe, "test", "--color", "on", tmp_source_file_name}); + try test_args.appendSlice([][]const u8{ + zig_exe, + "test", + "--color", + "on", + tmp_source_file_name, + }); try out.print("
$ zig test {}.zig", code.name);
                         switch (code.mode) {
                             builtin.Mode.Debug => {},
@@ -858,13 +878,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                             os.ChildProcess.Term.Exited => |exit_code| {
                                 if (exit_code == 0) {
                                     warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
-                                    for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+                                    for (test_args.toSliceConst()) |arg|
+                                        warn("{} ", arg)
+                                    else
+                                        warn("\n");
                                     return parseError(tokenizer, code.source_token, "example incorrectly compiled");
                                 }
                             },
                             else => {
                                 warn("{}\nThe following command crashed:\n", result.stderr);
-                                for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+                                for (test_args.toSliceConst()) |arg|
+                                    warn("{} ", arg)
+                                else
+                                    warn("\n");
                                 return parseError(tokenizer, code.source_token, "example compile crashed");
                             },
                         }
@@ -881,7 +907,11 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                         var test_args = std.ArrayList([]const u8).init(allocator);
                         defer test_args.deinit();
 
-                        try test_args.appendSlice([][]const u8 {zig_exe, "test", tmp_source_file_name});
+                        try test_args.appendSlice([][]const u8{
+                            zig_exe,
+                            "test",
+                            tmp_source_file_name,
+                        });
                         switch (code.mode) {
                             builtin.Mode.Debug => {},
                             builtin.Mode.ReleaseSafe => try test_args.append("--release-safe"),
@@ -894,13 +924,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                             os.ChildProcess.Term.Exited => |exit_code| {
                                 if (exit_code == 0) {
                                     warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
-                                    for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+                                    for (test_args.toSliceConst()) |arg|
+                                        warn("{} ", arg)
+                                    else
+                                        warn("\n");
                                     return parseError(tokenizer, code.source_token, "example test incorrectly succeeded");
                                 }
                             },
                             else => {
                                 warn("{}\nThe following command crashed:\n", result.stderr);
-                                for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+                                for (test_args.toSliceConst()) |arg|
+                                    warn("{} ", arg)
+                                else
+                                    warn("\n");
                                 return parseError(tokenizer, code.source_token, "example compile crashed");
                             },
                         }
@@ -918,9 +954,15 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                         var build_args = std.ArrayList([]const u8).init(allocator);
                         defer build_args.deinit();
 
-                        try build_args.appendSlice([][]const u8 {zig_exe, "build-obj", tmp_source_file_name,
-                            "--color", "on",
-                            "--output", tmp_obj_file_name});
+                        try build_args.appendSlice([][]const u8{
+                            zig_exe,
+                            "build-obj",
+                            tmp_source_file_name,
+                            "--color",
+                            "on",
+                            "--output",
+                            tmp_obj_file_name,
+                        });
 
                         if (!code.is_inline) {
                             try out.print("
$ zig build-obj {}.zig", code.name);
@@ -954,13 +996,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                                 os.ChildProcess.Term.Exited => |exit_code| {
                                     if (exit_code == 0) {
                                         warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
-                                        for (build_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+                                        for (build_args.toSliceConst()) |arg|
+                                            warn("{} ", arg)
+                                        else
+                                            warn("\n");
                                         return parseError(tokenizer, code.source_token, "example build incorrectly succeeded");
                                     }
                                 },
                                 else => {
                                     warn("{}\nThe following command crashed:\n", result.stderr);
-                                    for (build_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
+                                    for (build_args.toSliceConst()) |arg|
+                                        warn("{} ", arg)
+                                    else
+                                        warn("\n");
                                     return parseError(tokenizer, code.source_token, "example compile crashed");
                                 },
                             }
@@ -975,8 +1023,7 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
                                 try out.print("
\n"); } } else { - _ = exec(allocator, build_args.toSliceConst()) catch return parseError( - tokenizer, code.source_token, "example failed to compile"); + _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile"); } if (!code.is_inline) { try out.print("
\n"); @@ -987,7 +1034,6 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var }, } } - } fn exec(allocator: &mem.Allocator, args: []const []const u8) !os.ChildProcess.ExecResult { @@ -996,13 +1042,19 @@ fn exec(allocator: &mem.Allocator, args: []const []const u8) !os.ChildProcess.Ex os.ChildProcess.Term.Exited => |exit_code| { if (exit_code != 0) { warn("{}\nThe following command exited with code {}:\n", result.stderr, exit_code); - for (args) |arg| warn("{} ", arg) else warn("\n"); + for (args) |arg| + warn("{} ", arg) + else + warn("\n"); return error.ChildExitError; } }, else => { warn("{}\nThe following command crashed:\n", result.stderr); - for (args) |arg| warn("{} ", arg) else warn("\n"); + for (args) |arg| + warn("{} ", arg) + else + warn("\n"); return error.ChildCrashed; }, } diff --git a/example/guess_number/main.zig b/example/guess_number/main.zig index 7178c5274a..bed132b25c 100644 --- a/example/guess_number/main.zig +++ b/example/guess_number/main.zig @@ -23,7 +23,7 @@ pub fn main() !void { while (true) { try stdout.print("\nGuess a number between 1 and 100: "); - var line_buf : [20]u8 = undefined; + var line_buf: [20]u8 = undefined; const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) { error.InputTooLong => { diff --git a/example/hello_world/hello_libc.zig b/example/hello_world/hello_libc.zig index 4a35e47b15..1df8f04ce4 100644 --- a/example/hello_world/hello_libc.zig +++ b/example/hello_world/hello_libc.zig @@ -8,8 +8,7 @@ const c = @cImport({ const msg = c"Hello, world!\n"; export fn main(argc: c_int, argv: &&u8) c_int { - if (c.printf(msg) != c_int(c.strlen(msg))) - return -1; + if (c.printf(msg) != c_int(c.strlen(msg))) return -1; return 0; } diff --git a/example/mix_o_files/build.zig b/example/mix_o_files/build.zig index 4380486867..e5d2e6a446 100644 --- a/example/mix_o_files/build.zig +++ b/example/mix_o_files/build.zig @@ -4,9 +4,7 @@ pub fn build(b: &Builder) void { const obj = b.addObject("base64", "base64.zig"); const exe = b.addCExecutable("test"); - exe.addCompileFlags([][]const u8 { - "-std=c99", - }); + exe.addCompileFlags([][]const u8{"-std=c99"}); exe.addSourceFile("test.c"); exe.addObject(obj); diff --git a/example/shared_library/build.zig b/example/shared_library/build.zig index 2b5a178b35..30c714c6c6 100644 --- a/example/shared_library/build.zig +++ b/example/shared_library/build.zig @@ -4,9 +4,7 @@ pub fn build(b: &Builder) void { const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); const exe = b.addCExecutable("test"); - exe.addCompileFlags([][]const u8 { - "-std=c99", - }); + exe.addCompileFlags([][]const u8{"-std=c99"}); exe.addSourceFile("test.c"); exe.linkLibrary(lib); diff --git a/src-self-hosted/introspect.zig b/src-self-hosted/introspect.zig index 3f1fefdd5a..adab00286b 100644 --- a/src-self-hosted/introspect.zig +++ b/src-self-hosted/introspect.zig @@ -48,9 +48,7 @@ pub fn resolveZigLibDir(allocator: &mem.Allocator) ![]u8 { \\Unable to find zig lib directory: {}. \\Reinstall Zig or use --zig-install-prefix. \\ - , - @errorName(err) - ); + , @errorName(err)); return error.ZigLibDirNotFound; }; diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index b66a0abdee..c4550b5179 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -108,5 +108,4 @@ pub const Instruction = struct { ArgType, Export, }; - }; diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 22f49e80d9..f54bdbdaf0 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -37,7 +37,7 @@ const usage = \\ zen Print zen of zig and exit \\ \\ - ; +; const Command = struct { name: []const u8, @@ -63,22 +63,61 @@ pub fn main() !void { os.exit(1); } - const commands = []Command { - Command { .name = "build", .exec = cmdBuild }, - Command { .name = "build-exe", .exec = cmdBuildExe }, - Command { .name = "build-lib", .exec = cmdBuildLib }, - Command { .name = "build-obj", .exec = cmdBuildObj }, - Command { .name = "fmt", .exec = cmdFmt }, - Command { .name = "run", .exec = cmdRun }, - Command { .name = "targets", .exec = cmdTargets }, - Command { .name = "test", .exec = cmdTest }, - Command { .name = "translate-c", .exec = cmdTranslateC }, - Command { .name = "version", .exec = cmdVersion }, - Command { .name = "zen", .exec = cmdZen }, + const commands = []Command{ + Command{ + .name = "build", + .exec = cmdBuild, + }, + Command{ + .name = "build-exe", + .exec = cmdBuildExe, + }, + Command{ + .name = "build-lib", + .exec = cmdBuildLib, + }, + Command{ + .name = "build-obj", + .exec = cmdBuildObj, + }, + Command{ + .name = "fmt", + .exec = cmdFmt, + }, + Command{ + .name = "run", + .exec = cmdRun, + }, + Command{ + .name = "targets", + .exec = cmdTargets, + }, + Command{ + .name = "test", + .exec = cmdTest, + }, + Command{ + .name = "translate-c", + .exec = cmdTranslateC, + }, + Command{ + .name = "version", + .exec = cmdVersion, + }, + Command{ + .name = "zen", + .exec = cmdZen, + }, // undocumented commands - Command { .name = "help", .exec = cmdHelp }, - Command { .name = "internal", .exec = cmdInternal }, + Command{ + .name = "help", + .exec = cmdHelp, + }, + Command{ + .name = "internal", + .exec = cmdInternal, + }, }; for (commands) |command| { @@ -120,9 +159,9 @@ const usage_build = \\ --verbose-cimport Enable compiler debug output for C imports \\ \\ - ; +; -const args_build_spec = []Flag { +const args_build_spec = []Flag{ Flag.Bool("--help"), Flag.Bool("--init"), Flag.Arg1("--build-file"), @@ -148,7 +187,7 @@ const missing_build_file = \\ \\See: `zig build --help` or `zig help` for more options. \\ - ; +; fn cmdBuild(allocator: &Allocator, args: []const []const u8) !void { var flags = try Args.parse(allocator, args_build_spec, args); @@ -317,15 +356,23 @@ const usage_build_generic = \\ --ver-patch [ver] Dynamic library semver patch version \\ \\ - ; +; -const args_build_generic = []Flag { +const args_build_generic = []Flag{ Flag.Bool("--help"), - Flag.Option("--color", []const []const u8 { "auto", "off", "on" }), + Flag.Option("--color", []const []const u8{ + "auto", + "off", + "on", + }), Flag.ArgMergeN("--assembly", 1), Flag.Arg1("--cache-dir"), - Flag.Option("--emit", []const []const u8 { "asm", "bin", "llvm-ir" }), + Flag.Option("--emit", []const []const u8{ + "asm", + "bin", + "llvm-ir", + }), Flag.Bool("--enable-timing-info"), Flag.Arg1("--libc-include-dir"), Flag.Arg1("--name"), @@ -471,7 +518,7 @@ fn buildOutputType(allocator: &Allocator, args: []const []const u8, out_type: Mo os.exit(1); }; - const asm_a= flags.many("assembly"); + const asm_a = flags.many("assembly"); const obj_a = flags.many("object"); if (in_file == null and (obj_a == null or (??obj_a).len == 0) and (asm_a == null or (??asm_a).len == 0)) { try stderr.write("Expected source file argument or at least one --object or --assembly argument\n"); @@ -493,17 +540,16 @@ fn buildOutputType(allocator: &Allocator, args: []const []const u8, out_type: Mo const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch os.exit(1); defer allocator.free(zig_lib_dir); - var module = - try Module.create( - allocator, - root_name, - zig_root_source_file, - Target.Native, - out_type, - build_mode, - zig_lib_dir, - full_cache_dir - ); + var module = try Module.create( + allocator, + root_name, + zig_root_source_file, + Target.Native, + out_type, + build_mode, + zig_lib_dir, + full_cache_dir, + ); defer module.destroy(); module.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") ?? "0", 10); @@ -588,10 +634,10 @@ fn buildOutputType(allocator: &Allocator, args: []const []const u8, out_type: Mo } if (flags.single("mmacosx-version-min")) |ver| { - module.darwin_version_min = Module.DarwinVersionMin { .MacOS = ver }; + module.darwin_version_min = Module.DarwinVersionMin{ .MacOS = ver }; } if (flags.single("mios-version-min")) |ver| { - module.darwin_version_min = Module.DarwinVersionMin { .Ios = ver }; + module.darwin_version_min = Module.DarwinVersionMin{ .Ios = ver }; } module.emit_file_type = emit_type; @@ -639,11 +685,9 @@ const usage_fmt = \\ --help Print this help and exit \\ \\ - ; +; -const args_fmt_spec = []Flag { - Flag.Bool("--help"), -}; +const args_fmt_spec = []Flag{Flag.Bool("--help")}; fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void { var flags = try Args.parse(allocator, args_fmt_spec, args); @@ -675,7 +719,6 @@ fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void { }; defer tree.deinit(); - var error_it = tree.errors.iterator(0); while (error_it.next()) |parse_error| { const token = tree.tokens.at(parse_error.loc()); @@ -721,8 +764,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void { inline while (i < @memberCount(builtin.Arch)) : (i += 1) { comptime const arch_tag = @memberName(builtin.Arch, i); // NOTE: Cannot use empty string, see #918. - comptime const native_str = - if (comptime mem.eql(u8, arch_tag, @tagName(builtin.arch))) " (native)\n" else "\n"; + comptime const native_str = if (comptime mem.eql(u8, arch_tag, @tagName(builtin.arch))) " (native)\n" else "\n"; try stdout.print(" {}{}", arch_tag, native_str); } @@ -735,8 +777,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void { inline while (i < @memberCount(builtin.Os)) : (i += 1) { comptime const os_tag = @memberName(builtin.Os, i); // NOTE: Cannot use empty string, see #918. - comptime const native_str = - if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n"; + comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n"; try stdout.print(" {}{}", os_tag, native_str); } @@ -749,8 +790,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void { inline while (i < @memberCount(builtin.Environ)) : (i += 1) { comptime const environ_tag = @memberName(builtin.Environ, i); // NOTE: Cannot use empty string, see #918. - comptime const native_str = - if (comptime mem.eql(u8, environ_tag, @tagName(builtin.environ))) " (native)\n" else "\n"; + comptime const native_str = if (comptime mem.eql(u8, environ_tag, @tagName(builtin.environ))) " (native)\n" else "\n"; try stdout.print(" {}{}", environ_tag, native_str); } @@ -772,12 +812,9 @@ const usage_test = \\ --help Print this help and exit \\ \\ - ; - -const args_test_spec = []Flag { - Flag.Bool("--help"), -}; +; +const args_test_spec = []Flag{Flag.Bool("--help")}; fn cmdTest(allocator: &Allocator, args: []const []const u8) !void { var flags = try Args.parse(allocator, args_build_spec, args); @@ -810,21 +847,18 @@ const usage_run = \\ --help Print this help and exit \\ \\ - ; - -const args_run_spec = []Flag { - Flag.Bool("--help"), -}; +; +const args_run_spec = []Flag{Flag.Bool("--help")}; fn cmdRun(allocator: &Allocator, args: []const []const u8) !void { var compile_args = args; - var runtime_args: []const []const u8 = []const []const u8 {}; + var runtime_args: []const []const u8 = []const []const u8{}; for (args) |argv, i| { if (mem.eql(u8, argv, "--")) { compile_args = args[0..i]; - runtime_args = args[i+1..]; + runtime_args = args[i + 1..]; break; } } @@ -858,9 +892,9 @@ const usage_translate_c = \\ --output [path] Output file to write generated zig file (default: stdout) \\ \\ - ; +; -const args_translate_c_spec = []Flag { +const args_translate_c_spec = []Flag{ Flag.Bool("--help"), Flag.Bool("--enable-timing-info"), Flag.Arg1("--libc-include-dir"), @@ -934,7 +968,7 @@ const info_zen = \\ * Together we serve end users. \\ \\ - ; +; fn cmdZen(allocator: &Allocator, args: []const []const u8) !void { try stdout.write(info_zen); @@ -949,7 +983,7 @@ const usage_internal = \\ build-info Print static compiler build-info \\ \\ - ; +; fn cmdInternal(allocator: &Allocator, args: []const []const u8) !void { if (args.len == 0) { @@ -957,9 +991,10 @@ fn cmdInternal(allocator: &Allocator, args: []const []const u8) !void { os.exit(1); } - const sub_commands = []Command { - Command { .name = "build-info", .exec = cmdInternalBuildInfo }, - }; + const sub_commands = []Command{Command{ + .name = "build-info", + .exec = cmdInternalBuildInfo, + }}; for (sub_commands) |sub_command| { if (mem.eql(u8, sub_command.name, args[0])) { @@ -983,7 +1018,7 @@ fn cmdInternalBuildInfo(allocator: &Allocator, args: []const []const u8) !void { \\ZIG_C_HEADER_FILES {} \\ZIG_DIA_GUIDS_LIB {} \\ - , + , std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR), std.cstr.toSliceConst(c.ZIG_CXX_COMPILER), std.cstr.toSliceConst(c.ZIG_LLVM_CONFIG_EXE), diff --git a/src-self-hosted/target.zig b/src-self-hosted/target.zig index 27a90bd096..7983a3ddec 100644 --- a/src-self-hosted/target.zig +++ b/src-self-hosted/target.zig @@ -38,8 +38,7 @@ pub const Target = union(enum) { pub fn isDarwin(self: &const Target) bool { return switch (self.getOs()) { - builtin.Os.ios, - builtin.Os.macosx => true, + builtin.Os.ios, builtin.Os.macosx => true, else => false, }; } diff --git a/std/array_list.zig b/std/array_list.zig index d1165c626d..679f7d73b8 100644 --- a/std/array_list.zig +++ b/std/array_list.zig @@ -150,7 +150,10 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type { }; pub fn iterator(self: &const Self) Iterator { - return Iterator { .list = self, .count = 0 }; + return Iterator{ + .list = self, + .count = 0, + }; } }; } @@ -207,7 +210,7 @@ test "iterator ArrayList test" { try list.append(2); try list.append(3); - var count : i32 = 0; + var count: i32 = 0; var it = list.iterator(); while (it.next()) |next| { assert(next == count + 1); @@ -225,7 +228,7 @@ test "iterator ArrayList test" { } it.reset(); - assert(?? it.next() == 1); + assert(??it.next() == 1); } test "insert ArrayList test" { diff --git a/std/base64.zig b/std/base64.zig index 13f3ea5714..515738a99e 100644 --- a/std/base64.zig +++ b/std/base64.zig @@ -41,12 +41,10 @@ pub const Base64Encoder = struct { dest[out_index] = encoder.alphabet_chars[(source[i] >> 2) & 0x3f]; out_index += 1; - dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) | - ((source[i + 1] & 0xf0) >> 4)]; + dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) | ((source[i + 1] & 0xf0) >> 4)]; out_index += 1; - dest[out_index] = encoder.alphabet_chars[((source[i + 1] & 0xf) << 2) | - ((source[i + 2] & 0xc0) >> 6)]; + dest[out_index] = encoder.alphabet_chars[((source[i + 1] & 0xf) << 2) | ((source[i + 2] & 0xc0) >> 6)]; out_index += 1; dest[out_index] = encoder.alphabet_chars[source[i + 2] & 0x3f]; @@ -64,8 +62,7 @@ pub const Base64Encoder = struct { dest[out_index] = encoder.pad_char; out_index += 1; } else { - dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) | - ((source[i + 1] & 0xf0) >> 4)]; + dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) | ((source[i + 1] & 0xf0) >> 4)]; out_index += 1; dest[out_index] = encoder.alphabet_chars[(source[i + 1] & 0xf) << 2]; @@ -131,26 +128,20 @@ pub const Base64Decoder = struct { // common case if (!decoder.char_in_alphabet[source[src_cursor + 2]]) return error.InvalidCharacter; if (!decoder.char_in_alphabet[source[src_cursor + 3]]) return error.InvalidCharacter; - dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | - decoder.char_to_index[source[src_cursor + 1]] >> 4; - dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 | - decoder.char_to_index[source[src_cursor + 2]] >> 2; - dest[dest_cursor + 2] = decoder.char_to_index[source[src_cursor + 2]] << 6 | - decoder.char_to_index[source[src_cursor + 3]]; + dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | decoder.char_to_index[source[src_cursor + 1]] >> 4; + dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 | decoder.char_to_index[source[src_cursor + 2]] >> 2; + dest[dest_cursor + 2] = decoder.char_to_index[source[src_cursor + 2]] << 6 | decoder.char_to_index[source[src_cursor + 3]]; dest_cursor += 3; } else if (source[src_cursor + 2] != decoder.pad_char) { // one pad char if (!decoder.char_in_alphabet[source[src_cursor + 2]]) return error.InvalidCharacter; - dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | - decoder.char_to_index[source[src_cursor + 1]] >> 4; - dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 | - decoder.char_to_index[source[src_cursor + 2]] >> 2; + dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | decoder.char_to_index[source[src_cursor + 1]] >> 4; + dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 | decoder.char_to_index[source[src_cursor + 2]] >> 2; if (decoder.char_to_index[source[src_cursor + 2]] << 6 != 0) return error.InvalidPadding; dest_cursor += 2; } else { // two pad chars - dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | - decoder.char_to_index[source[src_cursor + 1]] >> 4; + dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | decoder.char_to_index[source[src_cursor + 1]] >> 4; if (decoder.char_to_index[source[src_cursor + 1]] << 4 != 0) return error.InvalidPadding; dest_cursor += 1; } @@ -165,7 +156,7 @@ pub const Base64DecoderWithIgnore = struct { decoder: Base64Decoder, char_is_ignored: [256]bool, pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) Base64DecoderWithIgnore { - var result = Base64DecoderWithIgnore { + var result = Base64DecoderWithIgnore{ .decoder = Base64Decoder.init(alphabet_chars, pad_char), .char_is_ignored = []bool{false} ** 256, }; @@ -223,10 +214,12 @@ pub const Base64DecoderWithIgnore = struct { } else if (decoder_with_ignore.char_is_ignored[c]) { // we can even ignore chars during the padding continue; - } else return error.InvalidCharacter; + } else + return error.InvalidCharacter; } break; - } else return error.InvalidCharacter; + } else + return error.InvalidCharacter; } switch (available_chars) { @@ -234,22 +227,17 @@ pub const Base64DecoderWithIgnore = struct { // common case if (dest_cursor + 3 > dest.len) return error.OutputTooSmall; assert(pad_char_count == 0); - dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | - decoder.char_to_index[next_4_chars[1]] >> 4; - dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 | - decoder.char_to_index[next_4_chars[2]] >> 2; - dest[dest_cursor + 2] = decoder.char_to_index[next_4_chars[2]] << 6 | - decoder.char_to_index[next_4_chars[3]]; + dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | decoder.char_to_index[next_4_chars[1]] >> 4; + dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 | decoder.char_to_index[next_4_chars[2]] >> 2; + dest[dest_cursor + 2] = decoder.char_to_index[next_4_chars[2]] << 6 | decoder.char_to_index[next_4_chars[3]]; dest_cursor += 3; continue; }, 3 => { if (dest_cursor + 2 > dest.len) return error.OutputTooSmall; if (pad_char_count != 1) return error.InvalidPadding; - dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | - decoder.char_to_index[next_4_chars[1]] >> 4; - dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 | - decoder.char_to_index[next_4_chars[2]] >> 2; + dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | decoder.char_to_index[next_4_chars[1]] >> 4; + dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 | decoder.char_to_index[next_4_chars[2]] >> 2; if (decoder.char_to_index[next_4_chars[2]] << 6 != 0) return error.InvalidPadding; dest_cursor += 2; break; @@ -257,8 +245,7 @@ pub const Base64DecoderWithIgnore = struct { 2 => { if (dest_cursor + 1 > dest.len) return error.OutputTooSmall; if (pad_char_count != 2) return error.InvalidPadding; - dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | - decoder.char_to_index[next_4_chars[1]] >> 4; + dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | decoder.char_to_index[next_4_chars[1]] >> 4; if (decoder.char_to_index[next_4_chars[1]] << 4 != 0) return error.InvalidPadding; dest_cursor += 1; break; @@ -280,7 +267,6 @@ pub const Base64DecoderWithIgnore = struct { } }; - pub const standard_decoder_unsafe = Base64DecoderUnsafe.init(standard_alphabet_chars, standard_pad_char); pub const Base64DecoderUnsafe = struct { @@ -291,7 +277,7 @@ pub const Base64DecoderUnsafe = struct { pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64DecoderUnsafe { assert(alphabet_chars.len == 64); - var result = Base64DecoderUnsafe { + var result = Base64DecoderUnsafe{ .char_to_index = undefined, .pad_char = pad_char, }; @@ -321,16 +307,13 @@ pub const Base64DecoderUnsafe = struct { } while (in_buf_len > 4) { - dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | - decoder.char_to_index[source[src_index + 1]] >> 4; + dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | decoder.char_to_index[source[src_index + 1]] >> 4; dest_index += 1; - dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | - decoder.char_to_index[source[src_index + 2]] >> 2; + dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | decoder.char_to_index[source[src_index + 2]] >> 2; dest_index += 1; - dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | - decoder.char_to_index[source[src_index + 3]]; + dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | decoder.char_to_index[source[src_index + 3]]; dest_index += 1; src_index += 4; @@ -338,18 +321,15 @@ pub const Base64DecoderUnsafe = struct { } if (in_buf_len > 1) { - dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | - decoder.char_to_index[source[src_index + 1]] >> 4; + dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | decoder.char_to_index[source[src_index + 1]] >> 4; dest_index += 1; } if (in_buf_len > 2) { - dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | - decoder.char_to_index[source[src_index + 2]] >> 2; + dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | decoder.char_to_index[source[src_index + 2]] >> 2; dest_index += 1; } if (in_buf_len > 3) { - dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | - decoder.char_to_index[source[src_index + 3]]; + dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | decoder.char_to_index[source[src_index + 3]]; dest_index += 1; } } @@ -367,7 +347,6 @@ fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) usize { return result; } - test "base64" { @setEvalBranchQuota(8000); testBase64() catch unreachable; @@ -375,26 +354,26 @@ test "base64" { } fn testBase64() !void { - try testAllApis("", ""); - try testAllApis("f", "Zg=="); - try testAllApis("fo", "Zm8="); - try testAllApis("foo", "Zm9v"); - try testAllApis("foob", "Zm9vYg=="); - try testAllApis("fooba", "Zm9vYmE="); + try testAllApis("", ""); + try testAllApis("f", "Zg=="); + try testAllApis("fo", "Zm8="); + try testAllApis("foo", "Zm9v"); + try testAllApis("foob", "Zm9vYg=="); + try testAllApis("fooba", "Zm9vYmE="); try testAllApis("foobar", "Zm9vYmFy"); - try testDecodeIgnoreSpace("", " "); - try testDecodeIgnoreSpace("f", "Z g= ="); - try testDecodeIgnoreSpace("fo", " Zm8="); - try testDecodeIgnoreSpace("foo", "Zm9v "); - try testDecodeIgnoreSpace("foob", "Zm9vYg = = "); - try testDecodeIgnoreSpace("fooba", "Zm9v YmE="); + try testDecodeIgnoreSpace("", " "); + try testDecodeIgnoreSpace("f", "Z g= ="); + try testDecodeIgnoreSpace("fo", " Zm8="); + try testDecodeIgnoreSpace("foo", "Zm9v "); + try testDecodeIgnoreSpace("foob", "Zm9vYg = = "); + try testDecodeIgnoreSpace("fooba", "Zm9v YmE="); try testDecodeIgnoreSpace("foobar", " Z m 9 v Y m F y "); // test getting some api errors - try testError("A", error.InvalidPadding); - try testError("AA", error.InvalidPadding); - try testError("AAA", error.InvalidPadding); + try testError("A", error.InvalidPadding); + try testError("AA", error.InvalidPadding); + try testError("AAA", error.InvalidPadding); try testError("A..A", error.InvalidCharacter); try testError("AA=A", error.InvalidCharacter); try testError("AA/=", error.InvalidPadding); @@ -427,8 +406,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void // Base64DecoderWithIgnore { - const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init( - standard_alphabet_chars, standard_pad_char, ""); + const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, ""); var buffer: [0x100]u8 = undefined; var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)]; var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded); @@ -446,8 +424,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void } fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !void { - const standard_decoder_ignore_space = Base64DecoderWithIgnore.init( - standard_alphabet_chars, standard_pad_char, " "); + const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, " "); var buffer: [0x100]u8 = undefined; var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)]; var written = try standard_decoder_ignore_space.decode(decoded, encoded); @@ -455,8 +432,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi } fn testError(encoded: []const u8, expected_err: error) !void { - const standard_decoder_ignore_space = Base64DecoderWithIgnore.init( - standard_alphabet_chars, standard_pad_char, " "); + const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, " "); var buffer: [0x100]u8 = undefined; if (standard_decoder.calcSize(encoded)) |decoded_size| { var decoded = buffer[0..decoded_size]; @@ -471,8 +447,7 @@ fn testError(encoded: []const u8, expected_err: error) !void { } fn testOutputTooSmallError(encoded: []const u8) !void { - const standard_decoder_ignore_space = Base64DecoderWithIgnore.init( - standard_alphabet_chars, standard_pad_char, " "); + const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, " "); var buffer: [0x100]u8 = undefined; var decoded = buffer[0..calcDecodedSizeExactUnsafe(encoded, standard_pad_char) - 1]; if (standard_decoder_ignore_space.decode(decoded, encoded)) |_| { diff --git a/std/buf_map.zig b/std/buf_map.zig index 57c5830bbe..930fc36a78 100644 --- a/std/buf_map.zig +++ b/std/buf_map.zig @@ -12,9 +12,7 @@ pub const BufMap = struct { const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8); pub fn init(allocator: &Allocator) BufMap { - var self = BufMap { - .hash_map = BufMapHashMap.init(allocator), - }; + var self = BufMap{ .hash_map = BufMapHashMap.init(allocator) }; return self; } diff --git a/std/buf_set.zig b/std/buf_set.zig index 1badb5bf18..c5a80e16fb 100644 --- a/std/buf_set.zig +++ b/std/buf_set.zig @@ -10,9 +10,7 @@ pub const BufSet = struct { const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); pub fn init(a: &Allocator) BufSet { - var self = BufSet { - .hash_map = BufSetHashMap.init(a), - }; + var self = BufSet{ .hash_map = BufSetHashMap.init(a) }; return self; } diff --git a/std/build.zig b/std/build.zig index 276176c63c..f86c3d394f 100644 --- a/std/build.zig +++ b/std/build.zig @@ -420,15 +420,7 @@ pub const Builder = struct { const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") ?? false; const release_small = self.option(bool, "release-small", "size optimizations on and safety off") ?? false; - const mode = if (release_safe and !release_fast and !release_small) - builtin.Mode.ReleaseSafe - else if (release_fast and !release_safe and !release_small) - builtin.Mode.ReleaseFast - else if (release_small and !release_fast and !release_safe) - builtin.Mode.ReleaseSmall - else if (!release_fast and !release_safe and !release_small) - builtin.Mode.Debug - else x: { + const mode = if (release_safe and !release_fast and !release_small) builtin.Mode.ReleaseSafe else if (release_fast and !release_safe and !release_small) builtin.Mode.ReleaseFast else if (release_small and !release_fast and !release_safe) builtin.Mode.ReleaseSmall else if (!release_fast and !release_safe and !release_small) builtin.Mode.Debug else x: { warn("Multiple release modes (of -Drelease-safe, -Drelease-fast and -Drelease-small)"); self.markInvalidUserInput(); break :x builtin.Mode.Debug; @@ -649,11 +641,7 @@ pub const Builder = struct { if (builtin.environ == builtin.Environ.msvc) { return "cl.exe"; } else { - return os.getEnvVarOwned(self.allocator, "CC") catch |err| - if (err == error.EnvironmentVariableNotFound) - ([]const u8)("cc") - else - debug.panic("Unable to get environment variable: {}", err); + return os.getEnvVarOwned(self.allocator, "CC") catch |err| if (err == error.EnvironmentVariableNotFound) ([]const u8)("cc") else debug.panic("Unable to get environment variable: {}", err); } } @@ -782,8 +770,7 @@ pub const Target = union(enum) { pub fn isDarwin(self: &const Target) bool { return switch (self.getOs()) { - builtin.Os.ios, - builtin.Os.macosx => true, + builtin.Os.ios, builtin.Os.macosx => true, else => false, }; } @@ -990,8 +977,7 @@ pub const LibExeObjStep = struct { self.out_filename = self.builder.fmt("lib{}.a", self.name); } else { switch (self.target.getOs()) { - builtin.Os.ios, - builtin.Os.macosx => { + builtin.Os.ios, builtin.Os.macosx => { self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch); self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major); self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name); @@ -1011,11 +997,13 @@ pub const LibExeObjStep = struct { } pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { - self.target = Target{ .Cross = CrossTarget{ - .arch = target_arch, - .os = target_os, - .environ = target_environ, - } }; + self.target = Target{ + .Cross = CrossTarget{ + .arch = target_arch, + .os = target_os, + .environ = target_environ, + }, + }; self.computeOutFileNames(); } @@ -1079,10 +1067,7 @@ pub const LibExeObjStep = struct { } pub fn getOutputPath(self: &LibExeObjStep) []const u8 { - return if (self.output_path) |output_path| - output_path - else - os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable; + return if (self.output_path) |output_path| output_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable; } pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) void { @@ -1095,10 +1080,7 @@ pub const LibExeObjStep = struct { } pub fn getOutputHPath(self: &LibExeObjStep) []const u8 { - return if (self.output_h_path) |output_h_path| - output_h_path - else - os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable; + return if (self.output_h_path) |output_h_path| output_h_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable; } pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) void { @@ -1352,8 +1334,7 @@ pub const LibExeObjStep = struct { args.append("ssp-buffer-size=4") catch unreachable; } }, - builtin.Mode.ReleaseFast, - builtin.Mode.ReleaseSmall => { + builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => { args.append("-O2") catch unreachable; args.append("-fno-stack-protector") catch unreachable; }, @@ -1652,11 +1633,13 @@ pub const TestStep = struct { } pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { - self.target = Target{ .Cross = CrossTarget{ - .arch = target_arch, - .os = target_os, - .environ = target_environ, - } }; + self.target = Target{ + .Cross = CrossTarget{ + .arch = target_arch, + .os = target_os, + .environ = target_environ, + }, + }; } pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void { diff --git a/std/c/darwin.zig b/std/c/darwin.zig index 7ac57514c9..24be832d01 100644 --- a/std/c/darwin.zig +++ b/std/c/darwin.zig @@ -60,7 +60,7 @@ pub const sigset_t = u32; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. pub const Sigaction = extern struct { - handler: extern fn(c_int)void, + handler: extern fn(c_int) void, sa_mask: sigset_t, sa_flags: c_int, }; diff --git a/std/c/index.zig b/std/c/index.zig index 34269d2aa2..b5e6b48751 100644 --- a/std/c/index.zig +++ b/std/c/index.zig @@ -1,7 +1,7 @@ const builtin = @import("builtin"); const Os = builtin.Os; -pub use switch(builtin.os) { +pub use switch (builtin.os) { Os.linux => @import("linux.zig"), Os.windows => @import("windows.zig"), Os.macosx, Os.ios => @import("darwin.zig"), @@ -21,8 +21,7 @@ pub extern "c" fn raise(sig: c_int) c_int; pub extern "c" fn read(fd: c_int, buf: &c_void, nbyte: usize) isize; pub extern "c" fn stat(noalias path: &const u8, noalias buf: &Stat) c_int; pub extern "c" fn write(fd: c_int, buf: &const c_void, nbyte: usize) isize; -pub extern "c" fn mmap(addr: ?&c_void, len: usize, prot: c_int, flags: c_int, - fd: c_int, offset: isize) ?&c_void; +pub extern "c" fn mmap(addr: ?&c_void, len: usize, prot: c_int, flags: c_int, fd: c_int, offset: isize) ?&c_void; pub extern "c" fn munmap(addr: &c_void, len: usize) c_int; pub extern "c" fn unlink(path: &const u8) c_int; pub extern "c" fn getcwd(buf: &u8, size: usize) ?&u8; @@ -34,8 +33,7 @@ pub extern "c" fn mkdir(path: &const u8, mode: c_uint) c_int; pub extern "c" fn symlink(existing: &const u8, new: &const u8) c_int; pub extern "c" fn rename(old: &const u8, new: &const u8) c_int; pub extern "c" fn chdir(path: &const u8) c_int; -pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8, - envp: &const ?&const u8) c_int; +pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) c_int; pub extern "c" fn dup(fd: c_int) c_int; pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int; pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) isize; @@ -54,9 +52,7 @@ pub extern "c" fn realloc(&c_void, usize) ?&c_void; pub extern "c" fn free(&c_void) void; pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) c_int; -pub extern "pthread" fn pthread_create(noalias newthread: &pthread_t, - noalias attr: ?&const pthread_attr_t, start_routine: extern fn(?&c_void) ?&c_void, - noalias arg: ?&c_void) c_int; +pub extern "pthread" fn pthread_create(noalias newthread: &pthread_t, noalias attr: ?&const pthread_attr_t, start_routine: extern fn(?&c_void) ?&c_void, noalias arg: ?&c_void) c_int; pub extern "pthread" fn pthread_attr_init(attr: &pthread_attr_t) c_int; pub extern "pthread" fn pthread_attr_setstack(attr: &pthread_attr_t, stackaddr: &c_void, stacksize: usize) c_int; pub extern "pthread" fn pthread_attr_destroy(attr: &pthread_attr_t) c_int; diff --git a/std/crypto/md5.zig b/std/crypto/md5.zig index 705b2428a7..e0473884cd 100644 --- a/std/crypto/md5.zig +++ b/std/crypto/md5.zig @@ -6,12 +6,25 @@ const debug = @import("../debug/index.zig"); const fmt = @import("../fmt/index.zig"); const RoundParam = struct { - a: usize, b: usize, c: usize, d: usize, - k: usize, s: u32, t: u32 + a: usize, + b: usize, + c: usize, + d: usize, + k: usize, + s: u32, + t: u32, }; fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundParam { - return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t }; + return RoundParam{ + .a = a, + .b = b, + .c = c, + .d = d, + .k = k, + .s = s, + .t = t, + }; } pub const Md5 = struct { @@ -99,7 +112,7 @@ pub const Md5 = struct { d.round(d.buf[0..]); for (d.s) |s, j| { - mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Little); + mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Little); } } @@ -112,30 +125,33 @@ pub const Md5 = struct { while (i < 16) : (i += 1) { // NOTE: Performing or's separately improves perf by ~10% s[i] = 0; - s[i] |= u32(b[i*4+0]); - s[i] |= u32(b[i*4+1]) << 8; - s[i] |= u32(b[i*4+2]) << 16; - s[i] |= u32(b[i*4+3]) << 24; + s[i] |= u32(b[i * 4 + 0]); + s[i] |= u32(b[i * 4 + 1]) << 8; + s[i] |= u32(b[i * 4 + 2]) << 16; + s[i] |= u32(b[i * 4 + 3]) << 24; } - var v: [4]u32 = []u32 { - d.s[0], d.s[1], d.s[2], d.s[3], + var v: [4]u32 = []u32{ + d.s[0], + d.s[1], + d.s[2], + d.s[3], }; - const round0 = comptime []RoundParam { - Rp(0, 1, 2, 3, 0, 7, 0xD76AA478), - Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756), - Rp(2, 3, 0, 1, 2, 17, 0x242070DB), - Rp(1, 2, 3, 0, 3, 22, 0xC1BDCEEE), - Rp(0, 1, 2, 3, 4, 7, 0xF57C0FAF), - Rp(3, 0, 1, 2, 5, 12, 0x4787C62A), - Rp(2, 3, 0, 1, 6, 17, 0xA8304613), - Rp(1, 2, 3, 0, 7, 22, 0xFD469501), - Rp(0, 1, 2, 3, 8, 7, 0x698098D8), - Rp(3, 0, 1, 2, 9, 12, 0x8B44F7AF), + const round0 = comptime []RoundParam{ + Rp(0, 1, 2, 3, 0, 7, 0xD76AA478), + Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756), + Rp(2, 3, 0, 1, 2, 17, 0x242070DB), + Rp(1, 2, 3, 0, 3, 22, 0xC1BDCEEE), + Rp(0, 1, 2, 3, 4, 7, 0xF57C0FAF), + Rp(3, 0, 1, 2, 5, 12, 0x4787C62A), + Rp(2, 3, 0, 1, 6, 17, 0xA8304613), + Rp(1, 2, 3, 0, 7, 22, 0xFD469501), + Rp(0, 1, 2, 3, 8, 7, 0x698098D8), + Rp(3, 0, 1, 2, 9, 12, 0x8B44F7AF), Rp(2, 3, 0, 1, 10, 17, 0xFFFF5BB1), Rp(1, 2, 3, 0, 11, 22, 0x895CD7BE), - Rp(0, 1, 2, 3, 12, 7, 0x6B901122), + Rp(0, 1, 2, 3, 12, 7, 0x6B901122), Rp(3, 0, 1, 2, 13, 12, 0xFD987193), Rp(2, 3, 0, 1, 14, 17, 0xA679438E), Rp(1, 2, 3, 0, 15, 22, 0x49B40821), @@ -145,22 +161,22 @@ pub const Md5 = struct { v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s); } - const round1 = comptime []RoundParam { - Rp(0, 1, 2, 3, 1, 5, 0xF61E2562), - Rp(3, 0, 1, 2, 6, 9, 0xC040B340), + const round1 = comptime []RoundParam{ + Rp(0, 1, 2, 3, 1, 5, 0xF61E2562), + Rp(3, 0, 1, 2, 6, 9, 0xC040B340), Rp(2, 3, 0, 1, 11, 14, 0x265E5A51), - Rp(1, 2, 3, 0, 0, 20, 0xE9B6C7AA), - Rp(0, 1, 2, 3, 5, 5, 0xD62F105D), - Rp(3, 0, 1, 2, 10, 9, 0x02441453), + Rp(1, 2, 3, 0, 0, 20, 0xE9B6C7AA), + Rp(0, 1, 2, 3, 5, 5, 0xD62F105D), + Rp(3, 0, 1, 2, 10, 9, 0x02441453), Rp(2, 3, 0, 1, 15, 14, 0xD8A1E681), - Rp(1, 2, 3, 0, 4, 20, 0xE7D3FBC8), - Rp(0, 1, 2, 3, 9, 5, 0x21E1CDE6), - Rp(3, 0, 1, 2, 14, 9, 0xC33707D6), - Rp(2, 3, 0, 1, 3, 14, 0xF4D50D87), - Rp(1, 2, 3, 0, 8, 20, 0x455A14ED), - Rp(0, 1, 2, 3, 13, 5, 0xA9E3E905), - Rp(3, 0, 1, 2, 2, 9, 0xFCEFA3F8), - Rp(2, 3, 0, 1, 7, 14, 0x676F02D9), + Rp(1, 2, 3, 0, 4, 20, 0xE7D3FBC8), + Rp(0, 1, 2, 3, 9, 5, 0x21E1CDE6), + Rp(3, 0, 1, 2, 14, 9, 0xC33707D6), + Rp(2, 3, 0, 1, 3, 14, 0xF4D50D87), + Rp(1, 2, 3, 0, 8, 20, 0x455A14ED), + Rp(0, 1, 2, 3, 13, 5, 0xA9E3E905), + Rp(3, 0, 1, 2, 2, 9, 0xFCEFA3F8), + Rp(2, 3, 0, 1, 7, 14, 0x676F02D9), Rp(1, 2, 3, 0, 12, 20, 0x8D2A4C8A), }; inline for (round1) |r| { @@ -168,46 +184,46 @@ pub const Md5 = struct { v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s); } - const round2 = comptime []RoundParam { - Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942), - Rp(3, 0, 1, 2, 8, 11, 0x8771F681), + const round2 = comptime []RoundParam{ + Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942), + Rp(3, 0, 1, 2, 8, 11, 0x8771F681), Rp(2, 3, 0, 1, 11, 16, 0x6D9D6122), Rp(1, 2, 3, 0, 14, 23, 0xFDE5380C), - Rp(0, 1, 2, 3, 1, 4, 0xA4BEEA44), - Rp(3, 0, 1, 2, 4, 11, 0x4BDECFA9), - Rp(2, 3, 0, 1, 7, 16, 0xF6BB4B60), + Rp(0, 1, 2, 3, 1, 4, 0xA4BEEA44), + Rp(3, 0, 1, 2, 4, 11, 0x4BDECFA9), + Rp(2, 3, 0, 1, 7, 16, 0xF6BB4B60), Rp(1, 2, 3, 0, 10, 23, 0xBEBFBC70), - Rp(0, 1, 2, 3, 13, 4, 0x289B7EC6), - Rp(3, 0, 1, 2, 0, 11, 0xEAA127FA), - Rp(2, 3, 0, 1, 3, 16, 0xD4EF3085), - Rp(1, 2, 3, 0, 6, 23, 0x04881D05), - Rp(0, 1, 2, 3, 9, 4, 0xD9D4D039), + Rp(0, 1, 2, 3, 13, 4, 0x289B7EC6), + Rp(3, 0, 1, 2, 0, 11, 0xEAA127FA), + Rp(2, 3, 0, 1, 3, 16, 0xD4EF3085), + Rp(1, 2, 3, 0, 6, 23, 0x04881D05), + Rp(0, 1, 2, 3, 9, 4, 0xD9D4D039), Rp(3, 0, 1, 2, 12, 11, 0xE6DB99E5), Rp(2, 3, 0, 1, 15, 16, 0x1FA27CF8), - Rp(1, 2, 3, 0, 2, 23, 0xC4AC5665), + Rp(1, 2, 3, 0, 2, 23, 0xC4AC5665), }; inline for (round2) |r| { v[r.a] = v[r.a] +% (v[r.b] ^ v[r.c] ^ v[r.d]) +% r.t +% s[r.k]; v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s); } - const round3 = comptime []RoundParam { - Rp(0, 1, 2, 3, 0, 6, 0xF4292244), - Rp(3, 0, 1, 2, 7, 10, 0x432AFF97), + const round3 = comptime []RoundParam{ + Rp(0, 1, 2, 3, 0, 6, 0xF4292244), + Rp(3, 0, 1, 2, 7, 10, 0x432AFF97), Rp(2, 3, 0, 1, 14, 15, 0xAB9423A7), - Rp(1, 2, 3, 0, 5, 21, 0xFC93A039), - Rp(0, 1, 2, 3, 12, 6, 0x655B59C3), - Rp(3, 0, 1, 2, 3, 10, 0x8F0CCC92), + Rp(1, 2, 3, 0, 5, 21, 0xFC93A039), + Rp(0, 1, 2, 3, 12, 6, 0x655B59C3), + Rp(3, 0, 1, 2, 3, 10, 0x8F0CCC92), Rp(2, 3, 0, 1, 10, 15, 0xFFEFF47D), - Rp(1, 2, 3, 0, 1, 21, 0x85845DD1), - Rp(0, 1, 2, 3, 8, 6, 0x6FA87E4F), + Rp(1, 2, 3, 0, 1, 21, 0x85845DD1), + Rp(0, 1, 2, 3, 8, 6, 0x6FA87E4F), Rp(3, 0, 1, 2, 15, 10, 0xFE2CE6E0), - Rp(2, 3, 0, 1, 6, 15, 0xA3014314), + Rp(2, 3, 0, 1, 6, 15, 0xA3014314), Rp(1, 2, 3, 0, 13, 21, 0x4E0811A1), - Rp(0, 1, 2, 3, 4, 6, 0xF7537E82), + Rp(0, 1, 2, 3, 4, 6, 0xF7537E82), Rp(3, 0, 1, 2, 11, 10, 0xBD3AF235), - Rp(2, 3, 0, 1, 2, 15, 0x2AD7D2BB), - Rp(1, 2, 3, 0, 9, 21, 0xEB86D391), + Rp(2, 3, 0, 1, 2, 15, 0x2AD7D2BB), + Rp(1, 2, 3, 0, 9, 21, 0xEB86D391), }; inline for (round3) |r| { v[r.a] = v[r.a] +% (v[r.c] ^ (v[r.b] | ~v[r.d])) +% r.t +% s[r.k]; @@ -255,7 +271,7 @@ test "md5 streaming" { } test "md5 aligned final" { - var block = []u8 {0} ** Md5.block_size; + var block = []u8{0} ** Md5.block_size; var out: [Md5.digest_size]u8 = undefined; var h = Md5.init(); diff --git a/std/crypto/sha1.zig b/std/crypto/sha1.zig index 333597b12d..77324b482f 100644 --- a/std/crypto/sha1.zig +++ b/std/crypto/sha1.zig @@ -7,11 +7,23 @@ const builtin = @import("builtin"); pub const u160 = @IntType(false, 160); const RoundParam = struct { - a: usize, b: usize, c: usize, d: usize, e: usize, i: u32, + a: usize, + b: usize, + c: usize, + d: usize, + e: usize, + i: u32, }; fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam { - return RoundParam { .a = a, .b = b, .c = c, .d = d, .e = e, .i = i }; + return RoundParam{ + .a = a, + .b = b, + .c = c, + .d = d, + .e = e, + .i = i, + }; } pub const Sha1 = struct { @@ -99,7 +111,7 @@ pub const Sha1 = struct { d.round(d.buf[0..]); for (d.s) |s, j| { - mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Big); + mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Big); } } @@ -108,21 +120,25 @@ pub const Sha1 = struct { var s: [16]u32 = undefined; - var v: [5]u32 = []u32 { - d.s[0], d.s[1], d.s[2], d.s[3], d.s[4], + var v: [5]u32 = []u32{ + d.s[0], + d.s[1], + d.s[2], + d.s[3], + d.s[4], }; - const round0a = comptime []RoundParam { - Rp(0, 1, 2, 3, 4, 0), - Rp(4, 0, 1, 2, 3, 1), - Rp(3, 4, 0, 1, 2, 2), - Rp(2, 3, 4, 0, 1, 3), - Rp(1, 2, 3, 4, 0, 4), - Rp(0, 1, 2, 3, 4, 5), - Rp(4, 0, 1, 2, 3, 6), - Rp(3, 4, 0, 1, 2, 7), - Rp(2, 3, 4, 0, 1, 8), - Rp(1, 2, 3, 4, 0, 9), + const round0a = comptime []RoundParam{ + Rp(0, 1, 2, 3, 4, 0), + Rp(4, 0, 1, 2, 3, 1), + Rp(3, 4, 0, 1, 2, 2), + Rp(2, 3, 4, 0, 1, 3), + Rp(1, 2, 3, 4, 0, 4), + Rp(0, 1, 2, 3, 4, 5), + Rp(4, 0, 1, 2, 3, 6), + Rp(3, 4, 0, 1, 2, 7), + Rp(2, 3, 4, 0, 1, 8), + Rp(1, 2, 3, 4, 0, 9), Rp(0, 1, 2, 3, 4, 10), Rp(4, 0, 1, 2, 3, 11), Rp(3, 4, 0, 1, 2, 12), @@ -131,32 +147,27 @@ pub const Sha1 = struct { Rp(0, 1, 2, 3, 4, 15), }; inline for (round0a) |r| { - s[r.i] = (u32(b[r.i * 4 + 0]) << 24) | - (u32(b[r.i * 4 + 1]) << 16) | - (u32(b[r.i * 4 + 2]) << 8) | - (u32(b[r.i * 4 + 3]) << 0); + s[r.i] = (u32(b[r.i * 4 + 0]) << 24) | (u32(b[r.i * 4 + 1]) << 16) | (u32(b[r.i * 4 + 2]) << 8) | (u32(b[r.i * 4 + 3]) << 0); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] - +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } - const round0b = comptime []RoundParam { + const round0b = comptime []RoundParam{ Rp(4, 0, 1, 2, 3, 16), Rp(3, 4, 0, 1, 2, 17), Rp(2, 3, 4, 0, 1, 18), Rp(1, 2, 3, 4, 0, 19), }; inline for (round0b) |r| { - const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf]; + const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; s[r.i & 0xf] = math.rotl(u32, t, u32(1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] - +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } - const round1 = comptime []RoundParam { + const round1 = comptime []RoundParam{ Rp(0, 1, 2, 3, 4, 20), Rp(4, 0, 1, 2, 3, 21), Rp(3, 4, 0, 1, 2, 22), @@ -179,15 +190,14 @@ pub const Sha1 = struct { Rp(1, 2, 3, 4, 0, 39), }; inline for (round1) |r| { - const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf]; + const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; s[r.i & 0xf] = math.rotl(u32, t, u32(1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x6ED9EBA1 +% s[r.i & 0xf] - +% (v[r.b] ^ v[r.c] ^ v[r.d]); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x6ED9EBA1 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } - const round2 = comptime []RoundParam { + const round2 = comptime []RoundParam{ Rp(0, 1, 2, 3, 4, 40), Rp(4, 0, 1, 2, 3, 41), Rp(3, 4, 0, 1, 2, 42), @@ -210,15 +220,14 @@ pub const Sha1 = struct { Rp(1, 2, 3, 4, 0, 59), }; inline for (round2) |r| { - const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf]; + const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; s[r.i & 0xf] = math.rotl(u32, t, u32(1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x8F1BBCDC +% s[r.i & 0xf] - +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d])); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x8F1BBCDC +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d])); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } - const round3 = comptime []RoundParam { + const round3 = comptime []RoundParam{ Rp(0, 1, 2, 3, 4, 60), Rp(4, 0, 1, 2, 3, 61), Rp(3, 4, 0, 1, 2, 62), @@ -241,11 +250,10 @@ pub const Sha1 = struct { Rp(1, 2, 3, 4, 0, 79), }; inline for (round3) |r| { - const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf]; + const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; s[r.i & 0xf] = math.rotl(u32, t, u32(1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0xCA62C1D6 +% s[r.i & 0xf] - +% (v[r.b] ^ v[r.c] ^ v[r.d]); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0xCA62C1D6 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } @@ -286,7 +294,7 @@ test "sha1 streaming" { } test "sha1 aligned final" { - var block = []u8 {0} ** Sha1.block_size; + var block = []u8{0} ** Sha1.block_size; var out: [Sha1.digest_size]u8 = undefined; var h = Sha1.init(); diff --git a/std/crypto/sha2.zig b/std/crypto/sha2.zig index b70450c0ad..a55182aacd 100644 --- a/std/crypto/sha2.zig +++ b/std/crypto/sha2.zig @@ -9,12 +9,31 @@ const htest = @import("test.zig"); // Sha224 + Sha256 const RoundParam256 = struct { - a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, - i: usize, k: u32, + a: usize, + b: usize, + c: usize, + d: usize, + e: usize, + f: usize, + g: usize, + h: usize, + i: usize, + k: u32, }; fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u32) RoundParam256 { - return RoundParam256 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k }; + return RoundParam256{ + .a = a, + .b = b, + .c = c, + .d = d, + .e = e, + .f = f, + .g = g, + .h = h, + .i = i, + .k = k, + }; } const Sha2Params32 = struct { @@ -29,7 +48,7 @@ const Sha2Params32 = struct { out_len: usize, }; -const Sha224Params = Sha2Params32 { +const Sha224Params = Sha2Params32{ .iv0 = 0xC1059ED8, .iv1 = 0x367CD507, .iv2 = 0x3070DD17, @@ -41,7 +60,7 @@ const Sha224Params = Sha2Params32 { .out_len = 224, }; -const Sha256Params = Sha2Params32 { +const Sha256Params = Sha2Params32{ .iv0 = 0x6A09E667, .iv1 = 0xBB67AE85, .iv2 = 0x3C6EF372, @@ -56,216 +75,215 @@ const Sha256Params = Sha2Params32 { pub const Sha224 = Sha2_32(Sha224Params); pub const Sha256 = Sha2_32(Sha256Params); -fn Sha2_32(comptime params: Sha2Params32) type { return struct { - const Self = this; - const block_size = 64; - const digest_size = params.out_len / 8; - - s: [8]u32, - // Streaming Cache - buf: [64]u8, - buf_len: u8, - total_len: u64, - - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; - } - - pub fn reset(d: &Self) void { - d.s[0] = params.iv0; - d.s[1] = params.iv1; - d.s[2] = params.iv2; - d.s[3] = params.iv3; - d.s[4] = params.iv4; - d.s[5] = params.iv5; - d.s[6] = params.iv6; - d.s[7] = params.iv7; - d.buf_len = 0; - d.total_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } - - pub fn update(d: &Self, b: []const u8) void { - var off: usize = 0; - - // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 64) { - off += 64 - d.buf_len; - mem.copy(u8, d.buf[d.buf_len..], b[0..off]); +fn Sha2_32(comptime params: Sha2Params32) type { + return struct { + const Self = this; + const block_size = 64; + const digest_size = params.out_len / 8; + + s: [8]u32, + // Streaming Cache + buf: [64]u8, + buf_len: u8, + total_len: u64, + + pub fn init() Self { + var d: Self = undefined; + d.reset(); + return d; + } - d.round(d.buf[0..]); + pub fn reset(d: &Self) void { + d.s[0] = params.iv0; + d.s[1] = params.iv1; + d.s[2] = params.iv2; + d.s[3] = params.iv3; + d.s[4] = params.iv4; + d.s[5] = params.iv5; + d.s[6] = params.iv6; + d.s[7] = params.iv7; d.buf_len = 0; + d.total_len = 0; } - // Full middle blocks. - while (off + 64 <= b.len) : (off += 64) { - d.round(b[off..off + 64]); + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); } - // Copy any remainder for next pass. - mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); + pub fn update(d: &Self, b: []const u8) void { + var off: usize = 0; - d.total_len += b.len; - } + // Partial buffer exists from previous update. Copy into buffer then hash. + if (d.buf_len != 0 and d.buf_len + b.len > 64) { + off += 64 - d.buf_len; + mem.copy(u8, d.buf[d.buf_len..], b[0..off]); - pub fn final(d: &Self, out: []u8) void { - debug.assert(out.len >= params.out_len / 8); + d.round(d.buf[0..]); + d.buf_len = 0; + } - // The buffer here will never be completely full. - mem.set(u8, d.buf[d.buf_len..], 0); + // Full middle blocks. + while (off + 64 <= b.len) : (off += 64) { + d.round(b[off..off + 64]); + } - // Append padding bits. - d.buf[d.buf_len] = 0x80; - d.buf_len += 1; + // Copy any remainder for next pass. + mem.copy(u8, d.buf[d.buf_len..], b[off..]); + d.buf_len += u8(b[off..].len); - // > 448 mod 512 so need to add an extra round to wrap around. - if (64 - d.buf_len < 8) { - d.round(d.buf[0..]); - mem.set(u8, d.buf[0..], 0); + d.total_len += b.len; } - // Append message length. - var i: usize = 1; - var len = d.total_len >> 5; - d.buf[63] = u8(d.total_len & 0x1f) << 3; - while (i < 8) : (i += 1) { - d.buf[63 - i] = u8(len & 0xff); - len >>= 8; - } + pub fn final(d: &Self, out: []u8) void { + debug.assert(out.len >= params.out_len / 8); - d.round(d.buf[0..]); + // The buffer here will never be completely full. + mem.set(u8, d.buf[d.buf_len..], 0); - // May truncate for possible 224 output - const rr = d.s[0 .. params.out_len / 32]; + // Append padding bits. + d.buf[d.buf_len] = 0x80; + d.buf_len += 1; - for (rr) |s, j| { - mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Big); - } - } + // > 448 mod 512 so need to add an extra round to wrap around. + if (64 - d.buf_len < 8) { + d.round(d.buf[0..]); + mem.set(u8, d.buf[0..], 0); + } + + // Append message length. + var i: usize = 1; + var len = d.total_len >> 5; + d.buf[63] = u8(d.total_len & 0x1f) << 3; + while (i < 8) : (i += 1) { + d.buf[63 - i] = u8(len & 0xff); + len >>= 8; + } - fn round(d: &Self, b: []const u8) void { - debug.assert(b.len == 64); + d.round(d.buf[0..]); - var s: [64]u32 = undefined; + // May truncate for possible 224 output + const rr = d.s[0..params.out_len / 32]; - var i: usize = 0; - while (i < 16) : (i += 1) { - s[i] = 0; - s[i] |= u32(b[i*4+0]) << 24; - s[i] |= u32(b[i*4+1]) << 16; - s[i] |= u32(b[i*4+2]) << 8; - s[i] |= u32(b[i*4+3]) << 0; - } - while (i < 64) : (i += 1) { - s[i] = - s[i-16] +% s[i-7] +% - (math.rotr(u32, s[i-15], u32(7)) ^ math.rotr(u32, s[i-15], u32(18)) ^ (s[i-15] >> 3)) +% - (math.rotr(u32, s[i-2], u32(17)) ^ math.rotr(u32, s[i-2], u32(19)) ^ (s[i-2] >> 10)); + for (rr) |s, j| { + mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Big); + } } - var v: [8]u32 = []u32 { - d.s[0], d.s[1], d.s[2], d.s[3], d.s[4], d.s[5], d.s[6], d.s[7], - }; - - const round0 = comptime []RoundParam256 { - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA5), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25B), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B01), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A7), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C1), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC6), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DC), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C8), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF3), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x14292967), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A85), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B2138), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D13), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A7354), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C85), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A1), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664B), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A3), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD6990624), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E3585), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA070), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C08), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774C), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4A), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC70208), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEB), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2), - }; - inline for (round0) |r| { - v[r.h] = - v[r.h] +% - (math.rotr(u32, v[r.e], u32(6)) ^ math.rotr(u32, v[r.e], u32(11)) ^ math.rotr(u32, v[r.e], u32(25))) +% - (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% - r.k +% s[r.i]; - - v[r.d] = v[r.d] +% v[r.h]; - - v[r.h] = - v[r.h] +% - (math.rotr(u32, v[r.a], u32(2)) ^ math.rotr(u32, v[r.a], u32(13)) ^ math.rotr(u32, v[r.a], u32(22))) +% - ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + fn round(d: &Self, b: []const u8) void { + debug.assert(b.len == 64); + + var s: [64]u32 = undefined; + + var i: usize = 0; + while (i < 16) : (i += 1) { + s[i] = 0; + s[i] |= u32(b[i * 4 + 0]) << 24; + s[i] |= u32(b[i * 4 + 1]) << 16; + s[i] |= u32(b[i * 4 + 2]) << 8; + s[i] |= u32(b[i * 4 + 3]) << 0; + } + while (i < 64) : (i += 1) { + s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u32, s[i - 15], u32(7)) ^ math.rotr(u32, s[i - 15], u32(18)) ^ (s[i - 15] >> 3)) +% (math.rotr(u32, s[i - 2], u32(17)) ^ math.rotr(u32, s[i - 2], u32(19)) ^ (s[i - 2] >> 10)); + } + + var v: [8]u32 = []u32{ + d.s[0], + d.s[1], + d.s[2], + d.s[3], + d.s[4], + d.s[5], + d.s[6], + d.s[7], + }; + + const round0 = comptime []RoundParam256{ + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA5), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25B), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B01), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A7), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C1), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC6), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DC), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C8), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF3), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x14292967), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A85), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B2138), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D13), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A7354), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C85), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A1), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664B), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A3), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD6990624), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E3585), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA070), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C08), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774C), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4A), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC70208), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEB), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2), + }; + inline for (round0) |r| { + v[r.h] = v[r.h] +% (math.rotr(u32, v[r.e], u32(6)) ^ math.rotr(u32, v[r.e], u32(11)) ^ math.rotr(u32, v[r.e], u32(25))) +% (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% r.k +% s[r.i]; + + v[r.d] = v[r.d] +% v[r.h]; + + v[r.h] = v[r.h] +% (math.rotr(u32, v[r.a], u32(2)) ^ math.rotr(u32, v[r.a], u32(13)) ^ math.rotr(u32, v[r.a], u32(22))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + } + + d.s[0] +%= v[0]; + d.s[1] +%= v[1]; + d.s[2] +%= v[2]; + d.s[3] +%= v[3]; + d.s[4] +%= v[4]; + d.s[5] +%= v[5]; + d.s[6] +%= v[6]; + d.s[7] +%= v[7]; } - - d.s[0] +%= v[0]; - d.s[1] +%= v[1]; - d.s[2] +%= v[2]; - d.s[3] +%= v[3]; - d.s[4] +%= v[4]; - d.s[5] +%= v[5]; - d.s[6] +%= v[6]; - d.s[7] +%= v[7]; - } -};} + }; +} test "sha224 single" { htest.assertEqualHash(Sha224, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", ""); @@ -320,7 +338,7 @@ test "sha256 streaming" { } test "sha256 aligned final" { - var block = []u8 {0} ** Sha256.block_size; + var block = []u8{0} ** Sha256.block_size; var out: [Sha256.digest_size]u8 = undefined; var h = Sha256.init(); @@ -328,17 +346,35 @@ test "sha256 aligned final" { h.final(out[0..]); } - ///////////////////// // Sha384 + Sha512 const RoundParam512 = struct { - a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, - i: usize, k: u64, + a: usize, + b: usize, + c: usize, + d: usize, + e: usize, + f: usize, + g: usize, + h: usize, + i: usize, + k: u64, }; fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) RoundParam512 { - return RoundParam512 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k }; + return RoundParam512{ + .a = a, + .b = b, + .c = c, + .d = d, + .e = e, + .f = f, + .g = g, + .h = h, + .i = i, + .k = k, + }; } const Sha2Params64 = struct { @@ -353,7 +389,7 @@ const Sha2Params64 = struct { out_len: usize, }; -const Sha384Params = Sha2Params64 { +const Sha384Params = Sha2Params64{ .iv0 = 0xCBBB9D5DC1059ED8, .iv1 = 0x629A292A367CD507, .iv2 = 0x9159015A3070DD17, @@ -365,7 +401,7 @@ const Sha384Params = Sha2Params64 { .out_len = 384, }; -const Sha512Params = Sha2Params64 { +const Sha512Params = Sha2Params64{ .iv0 = 0x6A09E667F3BCC908, .iv1 = 0xBB67AE8584CAA73B, .iv2 = 0x3C6EF372FE94F82B, @@ -374,242 +410,241 @@ const Sha512Params = Sha2Params64 { .iv5 = 0x9B05688C2B3E6C1F, .iv6 = 0x1F83D9ABFB41BD6B, .iv7 = 0x5BE0CD19137E2179, - .out_len = 512 + .out_len = 512, }; pub const Sha384 = Sha2_64(Sha384Params); pub const Sha512 = Sha2_64(Sha512Params); -fn Sha2_64(comptime params: Sha2Params64) type { return struct { - const Self = this; - const block_size = 128; - const digest_size = params.out_len / 8; - - s: [8]u64, - // Streaming Cache - buf: [128]u8, - buf_len: u8, - total_len: u128, - - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; - } - - pub fn reset(d: &Self) void { - d.s[0] = params.iv0; - d.s[1] = params.iv1; - d.s[2] = params.iv2; - d.s[3] = params.iv3; - d.s[4] = params.iv4; - d.s[5] = params.iv5; - d.s[6] = params.iv6; - d.s[7] = params.iv7; - d.buf_len = 0; - d.total_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } - - pub fn update(d: &Self, b: []const u8) void { - var off: usize = 0; - - // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 128) { - off += 128 - d.buf_len; - mem.copy(u8, d.buf[d.buf_len..], b[0..off]); +fn Sha2_64(comptime params: Sha2Params64) type { + return struct { + const Self = this; + const block_size = 128; + const digest_size = params.out_len / 8; + + s: [8]u64, + // Streaming Cache + buf: [128]u8, + buf_len: u8, + total_len: u128, + + pub fn init() Self { + var d: Self = undefined; + d.reset(); + return d; + } - d.round(d.buf[0..]); + pub fn reset(d: &Self) void { + d.s[0] = params.iv0; + d.s[1] = params.iv1; + d.s[2] = params.iv2; + d.s[3] = params.iv3; + d.s[4] = params.iv4; + d.s[5] = params.iv5; + d.s[6] = params.iv6; + d.s[7] = params.iv7; d.buf_len = 0; + d.total_len = 0; } - // Full middle blocks. - while (off + 128 <= b.len) : (off += 128) { - d.round(b[off..off + 128]); + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); } - // Copy any remainder for next pass. - mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); + pub fn update(d: &Self, b: []const u8) void { + var off: usize = 0; - d.total_len += b.len; - } + // Partial buffer exists from previous update. Copy into buffer then hash. + if (d.buf_len != 0 and d.buf_len + b.len > 128) { + off += 128 - d.buf_len; + mem.copy(u8, d.buf[d.buf_len..], b[0..off]); - pub fn final(d: &Self, out: []u8) void { - debug.assert(out.len >= params.out_len / 8); + d.round(d.buf[0..]); + d.buf_len = 0; + } - // The buffer here will never be completely full. - mem.set(u8, d.buf[d.buf_len..], 0); + // Full middle blocks. + while (off + 128 <= b.len) : (off += 128) { + d.round(b[off..off + 128]); + } - // Append padding bits. - d.buf[d.buf_len] = 0x80; - d.buf_len += 1; + // Copy any remainder for next pass. + mem.copy(u8, d.buf[d.buf_len..], b[off..]); + d.buf_len += u8(b[off..].len); - // > 896 mod 1024 so need to add an extra round to wrap around. - if (128 - d.buf_len < 16) { - d.round(d.buf[0..]); - mem.set(u8, d.buf[0..], 0); + d.total_len += b.len; } - // Append message length. - var i: usize = 1; - var len = d.total_len >> 5; - d.buf[127] = u8(d.total_len & 0x1f) << 3; - while (i < 16) : (i += 1) { - d.buf[127 - i] = u8(len & 0xff); - len >>= 8; - } + pub fn final(d: &Self, out: []u8) void { + debug.assert(out.len >= params.out_len / 8); - d.round(d.buf[0..]); + // The buffer here will never be completely full. + mem.set(u8, d.buf[d.buf_len..], 0); - // May truncate for possible 384 output - const rr = d.s[0 .. params.out_len / 64]; + // Append padding bits. + d.buf[d.buf_len] = 0x80; + d.buf_len += 1; - for (rr) |s, j| { - mem.writeInt(out[8*j .. 8*j + 8], s, builtin.Endian.Big); - } - } - - fn round(d: &Self, b: []const u8) void { - debug.assert(b.len == 128); - - var s: [80]u64 = undefined; - - var i: usize = 0; - while (i < 16) : (i += 1) { - s[i] = 0; - s[i] |= u64(b[i*8+0]) << 56; - s[i] |= u64(b[i*8+1]) << 48; - s[i] |= u64(b[i*8+2]) << 40; - s[i] |= u64(b[i*8+3]) << 32; - s[i] |= u64(b[i*8+4]) << 24; - s[i] |= u64(b[i*8+5]) << 16; - s[i] |= u64(b[i*8+6]) << 8; - s[i] |= u64(b[i*8+7]) << 0; - } - while (i < 80) : (i += 1) { - s[i] = - s[i-16] +% s[i-7] +% - (math.rotr(u64, s[i-15], u64(1)) ^ math.rotr(u64, s[i-15], u64(8)) ^ (s[i-15] >> 7)) +% - (math.rotr(u64, s[i-2], u64(19)) ^ math.rotr(u64, s[i-2], u64(61)) ^ (s[i-2] >> 6)); - } + // > 896 mod 1024 so need to add an extra round to wrap around. + if (128 - d.buf_len < 16) { + d.round(d.buf[0..]); + mem.set(u8, d.buf[0..], 0); + } - var v: [8]u64 = []u64 { - d.s[0], d.s[1], d.s[2], d.s[3], d.s[4], d.s[5], d.s[6], d.s[7], - }; - - const round0 = comptime []RoundParam512 { - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x7137449123EF65CD), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCFEC4D3B2F), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA58189DBBC), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25BF348B538), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1B605D019), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4AF194F9B), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5DA6D8118), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98A3030242), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B0145706FBE), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE4EE4B28C), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3D5FFB4E2), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74F27B896F), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE3B1696B1), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A725C71235), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174CF692694), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C19EF14AD2), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786384F25E3), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC68B8CD5B5), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC77AC9C65), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F592B0275), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA6EA6E483), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DCBD41FBD4), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA831153B5), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152EE66DFAB), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D2DB43210), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C898FB213F), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7BEEF0EE4), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF33DA88FC2), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147930AA725), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351E003826F), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x142929670A0E6E70), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A8546D22FFC), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B21385C26C926), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC5AC42AED), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D139D95B3DF), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A73548BAF63DE), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB3C77B2A8), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E47EDAEE6), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C851482353B), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A14CF10364), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664BBC423001), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70D0F89791), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A30654BE30), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819D6EF5218), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD69906245565A910), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E35855771202A), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA07032BBD1B8), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116B8D2D0C8), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C085141AB53), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774CDF8EEB99), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5E19B48A8), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3C5C95A63), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4AE3418ACB), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F7763E373), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3D6B2B8A3), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE5DEFB2FC), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F43172F60), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814A1F0AB72), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC702081A6439EC), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA23631E28), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEBDE82BDE9), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7B2C67915), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2E372532B), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 64, 0xCA273ECEEA26619C), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 65, 0xD186B8C721C0C207), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 66, 0xEADA7DD6CDE0EB1E), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 67, 0xF57D4F7FEE6ED178), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 68, 0x06F067AA72176FBA), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 69, 0x0A637DC5A2C898A6), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 70, 0x113F9804BEF90DAE), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 71, 0x1B710B35131C471B), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 72, 0x28DB77F523047D84), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 73, 0x32CAAB7B40C72493), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 74, 0x3C9EBE0A15C9BEBC), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 75, 0x431D67C49C100D4C), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 76, 0x4CC5D4BECB3E42B6), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 77, 0x597F299CFC657E2A), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 78, 0x5FCB6FAB3AD6FAEC), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 79, 0x6C44198C4A475817), - }; - inline for (round0) |r| { - v[r.h] = - v[r.h] +% - (math.rotr(u64, v[r.e], u64(14)) ^ math.rotr(u64, v[r.e], u64(18)) ^ math.rotr(u64, v[r.e], u64(41))) +% - (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% - r.k +% s[r.i]; - - v[r.d] = v[r.d] +% v[r.h]; - - v[r.h] = - v[r.h] +% - (math.rotr(u64, v[r.a], u64(28)) ^ math.rotr(u64, v[r.a], u64(34)) ^ math.rotr(u64, v[r.a], u64(39))) +% - ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + // Append message length. + var i: usize = 1; + var len = d.total_len >> 5; + d.buf[127] = u8(d.total_len & 0x1f) << 3; + while (i < 16) : (i += 1) { + d.buf[127 - i] = u8(len & 0xff); + len >>= 8; + } + + d.round(d.buf[0..]); + + // May truncate for possible 384 output + const rr = d.s[0..params.out_len / 64]; + + for (rr) |s, j| { + mem.writeInt(out[8 * j..8 * j + 8], s, builtin.Endian.Big); + } } - d.s[0] +%= v[0]; - d.s[1] +%= v[1]; - d.s[2] +%= v[2]; - d.s[3] +%= v[3]; - d.s[4] +%= v[4]; - d.s[5] +%= v[5]; - d.s[6] +%= v[6]; - d.s[7] +%= v[7]; - } -};} + fn round(d: &Self, b: []const u8) void { + debug.assert(b.len == 128); + + var s: [80]u64 = undefined; + + var i: usize = 0; + while (i < 16) : (i += 1) { + s[i] = 0; + s[i] |= u64(b[i * 8 + 0]) << 56; + s[i] |= u64(b[i * 8 + 1]) << 48; + s[i] |= u64(b[i * 8 + 2]) << 40; + s[i] |= u64(b[i * 8 + 3]) << 32; + s[i] |= u64(b[i * 8 + 4]) << 24; + s[i] |= u64(b[i * 8 + 5]) << 16; + s[i] |= u64(b[i * 8 + 6]) << 8; + s[i] |= u64(b[i * 8 + 7]) << 0; + } + while (i < 80) : (i += 1) { + s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u64, s[i - 15], u64(1)) ^ math.rotr(u64, s[i - 15], u64(8)) ^ (s[i - 15] >> 7)) +% (math.rotr(u64, s[i - 2], u64(19)) ^ math.rotr(u64, s[i - 2], u64(61)) ^ (s[i - 2] >> 6)); + } + + var v: [8]u64 = []u64{ + d.s[0], + d.s[1], + d.s[2], + d.s[3], + d.s[4], + d.s[5], + d.s[6], + d.s[7], + }; + + const round0 = comptime []RoundParam512{ + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x7137449123EF65CD), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCFEC4D3B2F), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA58189DBBC), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25BF348B538), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1B605D019), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4AF194F9B), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5DA6D8118), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98A3030242), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B0145706FBE), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE4EE4B28C), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3D5FFB4E2), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74F27B896F), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE3B1696B1), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A725C71235), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174CF692694), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C19EF14AD2), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786384F25E3), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC68B8CD5B5), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC77AC9C65), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F592B0275), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA6EA6E483), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DCBD41FBD4), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA831153B5), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152EE66DFAB), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D2DB43210), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C898FB213F), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7BEEF0EE4), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF33DA88FC2), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147930AA725), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351E003826F), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x142929670A0E6E70), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A8546D22FFC), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B21385C26C926), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC5AC42AED), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D139D95B3DF), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A73548BAF63DE), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB3C77B2A8), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E47EDAEE6), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C851482353B), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A14CF10364), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664BBC423001), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70D0F89791), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A30654BE30), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819D6EF5218), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD69906245565A910), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E35855771202A), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA07032BBD1B8), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116B8D2D0C8), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C085141AB53), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774CDF8EEB99), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5E19B48A8), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3C5C95A63), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4AE3418ACB), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F7763E373), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3D6B2B8A3), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE5DEFB2FC), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F43172F60), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814A1F0AB72), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC702081A6439EC), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA23631E28), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEBDE82BDE9), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7B2C67915), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2E372532B), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 64, 0xCA273ECEEA26619C), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 65, 0xD186B8C721C0C207), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 66, 0xEADA7DD6CDE0EB1E), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 67, 0xF57D4F7FEE6ED178), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 68, 0x06F067AA72176FBA), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 69, 0x0A637DC5A2C898A6), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 70, 0x113F9804BEF90DAE), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 71, 0x1B710B35131C471B), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 72, 0x28DB77F523047D84), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 73, 0x32CAAB7B40C72493), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 74, 0x3C9EBE0A15C9BEBC), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 75, 0x431D67C49C100D4C), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 76, 0x4CC5D4BECB3E42B6), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 77, 0x597F299CFC657E2A), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 78, 0x5FCB6FAB3AD6FAEC), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 79, 0x6C44198C4A475817), + }; + inline for (round0) |r| { + v[r.h] = v[r.h] +% (math.rotr(u64, v[r.e], u64(14)) ^ math.rotr(u64, v[r.e], u64(18)) ^ math.rotr(u64, v[r.e], u64(41))) +% (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% r.k +% s[r.i]; + + v[r.d] = v[r.d] +% v[r.h]; + + v[r.h] = v[r.h] +% (math.rotr(u64, v[r.a], u64(28)) ^ math.rotr(u64, v[r.a], u64(34)) ^ math.rotr(u64, v[r.a], u64(39))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + } + + d.s[0] +%= v[0]; + d.s[1] +%= v[1]; + d.s[2] +%= v[2]; + d.s[3] +%= v[3]; + d.s[4] +%= v[4]; + d.s[5] +%= v[5]; + d.s[6] +%= v[6]; + d.s[7] +%= v[7]; + } + }; +} test "sha384 single" { const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; @@ -680,7 +715,7 @@ test "sha512 streaming" { } test "sha512 aligned final" { - var block = []u8 {0} ** Sha512.block_size; + var block = []u8{0} ** Sha512.block_size; var out: [Sha512.digest_size]u8 = undefined; var h = Sha512.init(); diff --git a/std/crypto/test.zig b/std/crypto/test.zig index 3fa24272e5..c0a96a98de 100644 --- a/std/crypto/test.zig +++ b/std/crypto/test.zig @@ -14,7 +14,7 @@ pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, inpu pub fn assertEqual(comptime expected: []const u8, input: []const u8) void { var expected_bytes: [expected.len / 2]u8 = undefined; for (expected_bytes) |*r, i| { - r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable; + r.* = fmt.parseInt(u8, expected[2 * i..2 * i + 2], 16) catch unreachable; } debug.assert(mem.eql(u8, expected_bytes, input)); diff --git a/std/crypto/throughput_test.zig b/std/crypto/throughput_test.zig index 0756f9a4eb..c5c4f9fe10 100644 --- a/std/crypto/throughput_test.zig +++ b/std/crypto/throughput_test.zig @@ -11,7 +11,7 @@ const Timer = time.Timer; const HashFunction = @import("md5.zig").Md5; const MiB = 1024 * 1024; -const BytesToHash = 1024 * MiB; +const BytesToHash = 1024 * MiB; pub fn main() !void { var stdout_file = try std.io.getStdOut(); diff --git a/std/cstr.zig b/std/cstr.zig index d396dcbce3..c9f3026064 100644 --- a/std/cstr.zig +++ b/std/cstr.zig @@ -9,7 +9,6 @@ pub const line_sep = switch (builtin.os) { else => "\n", }; - pub fn len(ptr: &const u8) usize { var count: usize = 0; while (ptr[count] != 0) : (count += 1) {} @@ -95,7 +94,7 @@ pub const NullTerminated2DArray = struct { } index_buf[i] = null; - return NullTerminated2DArray { + return NullTerminated2DArray{ .allocator = allocator, .byte_count = byte_count, .ptr = @ptrCast(?&?&u8, buf.ptr), @@ -107,4 +106,3 @@ pub const NullTerminated2DArray = struct { self.allocator.free(buf[0..self.byte_count]); } }; - diff --git a/std/debug/failing_allocator.zig b/std/debug/failing_allocator.zig index f876b7902d..6b5edff5bf 100644 --- a/std/debug/failing_allocator.zig +++ b/std/debug/failing_allocator.zig @@ -13,14 +13,14 @@ pub const FailingAllocator = struct { deallocations: usize, pub fn init(allocator: &mem.Allocator, fail_index: usize) FailingAllocator { - return FailingAllocator { + return FailingAllocator{ .internal_allocator = allocator, .fail_index = fail_index, .index = 0, .allocated_bytes = 0, .freed_bytes = 0, .deallocations = 0, - .allocator = mem.Allocator { + .allocator = mem.Allocator{ .allocFn = alloc, .reallocFn = realloc, .freeFn = free, diff --git a/std/debug/index.zig b/std/debug/index.zig index 36ac2e8a3f..92e565b391 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -227,8 +227,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us else => return err, } } else |err| switch (err) { - error.MissingDebugInfo, - error.InvalidDebugInfo => { + error.MissingDebugInfo, error.InvalidDebugInfo => { try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name); }, else => return err, @@ -597,10 +596,12 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) ! } fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue { - return FormValue{ .Const = Constant{ - .signed = signed, - .payload = try readAllocBytes(allocator, in_stream, size), - } }; + return FormValue{ + .Const = Constant{ + .signed = signed, + .payload = try readAllocBytes(allocator, in_stream, size), + }, + }; } fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 { @@ -621,7 +622,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: var, comptime T: type return parseFormValueRefLen(allocator, in_stream, block_len); } -const ParseFormValueError = error { +const ParseFormValueError = error{ EndOfStream, Io, BadFd, @@ -645,8 +646,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64 DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2), DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4), DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8), - DW.FORM_udata, - DW.FORM_sdata => { + DW.FORM_udata, DW.FORM_sdata => { const block_len = try readULeb128(in_stream); const signed = form_id == DW.FORM_sdata; return parseFormValueConstant(allocator, in_stream, signed, block_len); diff --git a/std/dwarf.zig b/std/dwarf.zig index 04456d9e5c..76ed122447 100644 --- a/std/dwarf.zig +++ b/std/dwarf.zig @@ -337,7 +337,6 @@ pub const AT_PGI_lbase = 0x3a00; pub const AT_PGI_soffset = 0x3a01; pub const AT_PGI_lstride = 0x3a02; - pub const OP_addr = 0x03; pub const OP_deref = 0x06; pub const OP_const1u = 0x08; @@ -577,7 +576,6 @@ pub const ATE_HP_unsigned_fixed = 0x8e; // Cobol. pub const ATE_HP_VAX_complex_float = 0x8f; // F or G floating complex. pub const ATE_HP_VAX_complex_float_d = 0x90; // D floating complex. - pub const CFA_advance_loc = 0x40; pub const CFA_offset = 0x80; pub const CFA_restore = 0xc0; diff --git a/std/elf.zig b/std/elf.zig index 1764829bc8..29b9473f98 100644 --- a/std/elf.zig +++ b/std/elf.zig @@ -123,13 +123,11 @@ pub const DT_SYMINFO = 0x6ffffeff; pub const DT_ADDRRNGHI = 0x6ffffeff; pub const DT_ADDRNUM = 11; - pub const DT_VERSYM = 0x6ffffff0; pub const DT_RELACOUNT = 0x6ffffff9; pub const DT_RELCOUNT = 0x6ffffffa; - pub const DT_FLAGS_1 = 0x6ffffffb; pub const DT_VERDEF = 0x6ffffffc; @@ -139,13 +137,10 @@ pub const DT_VERNEED = 0x6ffffffe; pub const DT_VERNEEDNUM = 0x6fffffff; pub const DT_VERSIONTAGNUM = 16; - - pub const DT_AUXILIARY = 0x7ffffffd; pub const DT_FILTER = 0x7fffffff; pub const DT_EXTRANUM = 3; - pub const DT_SPARC_REGISTER = 0x70000001; pub const DT_SPARC_NUM = 2; @@ -434,9 +429,7 @@ pub const Elf = struct { try elf.in_file.seekForward(4); const header_size = try in.readInt(elf.endian, u16); - if ((elf.is_64 and header_size != 64) or - (!elf.is_64 and header_size != 52)) - { + if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) { return error.InvalidFormat; } @@ -467,16 +460,16 @@ pub const Elf = struct { if (sh_entry_size != 64) return error.InvalidFormat; for (elf.section_headers) |*elf_section| { - elf_section.name = try in.readInt(elf.endian, u32); - elf_section.sh_type = try in.readInt(elf.endian, u32); - elf_section.flags = try in.readInt(elf.endian, u64); - elf_section.addr = try in.readInt(elf.endian, u64); - elf_section.offset = try in.readInt(elf.endian, u64); - elf_section.size = try in.readInt(elf.endian, u64); - elf_section.link = try in.readInt(elf.endian, u32); - elf_section.info = try in.readInt(elf.endian, u32); - elf_section.addr_align = try in.readInt(elf.endian, u64); - elf_section.ent_size = try in.readInt(elf.endian, u64); + elf_section.name = try in.readInt(elf.endian, u32); + elf_section.sh_type = try in.readInt(elf.endian, u32); + elf_section.flags = try in.readInt(elf.endian, u64); + elf_section.addr = try in.readInt(elf.endian, u64); + elf_section.offset = try in.readInt(elf.endian, u64); + elf_section.size = try in.readInt(elf.endian, u64); + elf_section.link = try in.readInt(elf.endian, u32); + elf_section.info = try in.readInt(elf.endian, u32); + elf_section.addr_align = try in.readInt(elf.endian, u64); + elf_section.ent_size = try in.readInt(elf.endian, u64); } } else { if (sh_entry_size != 40) return error.InvalidFormat; @@ -513,8 +506,7 @@ pub const Elf = struct { pub fn close(elf: &Elf) void { elf.allocator.free(elf.section_headers); - if (elf.auto_close_stream) - elf.in_file.close(); + if (elf.auto_close_stream) elf.in_file.close(); } pub fn findSection(elf: &Elf, name: []const u8) !?&SectionHeader { @@ -852,27 +844,27 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct { flags2: Elf32_Word, }; -pub const Ehdr = switch(@sizeOf(usize)) { +pub const Ehdr = switch (@sizeOf(usize)) { 4 => Elf32_Ehdr, 8 => Elf64_Ehdr, else => @compileError("expected pointer size of 32 or 64"), }; -pub const Phdr = switch(@sizeOf(usize)) { +pub const Phdr = switch (@sizeOf(usize)) { 4 => Elf32_Phdr, 8 => Elf64_Phdr, else => @compileError("expected pointer size of 32 or 64"), }; -pub const Sym = switch(@sizeOf(usize)) { +pub const Sym = switch (@sizeOf(usize)) { 4 => Elf32_Sym, 8 => Elf64_Sym, else => @compileError("expected pointer size of 32 or 64"), }; -pub const Verdef = switch(@sizeOf(usize)) { +pub const Verdef = switch (@sizeOf(usize)) { 4 => Elf32_Verdef, 8 => Elf64_Verdef, else => @compileError("expected pointer size of 32 or 64"), }; -pub const Verdaux = switch(@sizeOf(usize)) { +pub const Verdaux = switch (@sizeOf(usize)) { 4 => Elf32_Verdaux, 8 => Elf64_Verdaux, else => @compileError("expected pointer size of 32 or 64"), diff --git a/std/event.zig b/std/event.zig index 558bd2a188..6ee8ab35f1 100644 --- a/std/event.zig +++ b/std/event.zig @@ -76,19 +76,14 @@ pub const TcpServer = struct { } continue; }, - error.ConnectionAborted, - error.FileDescriptorClosed => continue, + error.ConnectionAborted, error.FileDescriptorClosed => continue, error.PageFault => unreachable, error.InvalidSyscall => unreachable, error.FileDescriptorNotASocket => unreachable, error.OperationNotSupported => unreachable, - error.SystemFdQuotaExceeded, - error.SystemResources, - error.ProtocolFailure, - error.BlockedByFirewall, - error.Unexpected => { + error.SystemFdQuotaExceeded, error.SystemResources, error.ProtocolFailure, error.BlockedByFirewall, error.Unexpected => { @panic("TODO handle this error"); }, } @@ -121,7 +116,6 @@ pub const Loop = struct { pub fn removeFd(self: &Loop, fd: i32) void { std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_DEL, fd, undefined) catch {}; } - async fn waitFd(self: &Loop, fd: i32) !void { defer self.removeFd(fd); suspend |p| { @@ -169,7 +163,6 @@ test "listen on a port, send bytes, receive bytes" { tcp_server: TcpServer, const Self = this; - async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, _socket: &const std.os.File) void { const self = @fieldParentPtr(Self, "tcp_server", tcp_server); var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733 @@ -184,7 +177,6 @@ test "listen on a port, send bytes, receive bytes" { cancel p; } } - async fn errorableHandler(self: &Self, _addr: &const std.net.Address, _socket: &const std.os.File) !void { const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/733 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733 @@ -207,7 +199,6 @@ test "listen on a port, send bytes, receive bytes" { defer cancel p; loop.run(); } - async fn doAsyncTest(loop: &Loop, address: &const std.net.Address) void { errdefer @panic("test failure"); diff --git a/std/fmt/errol/enum3.zig b/std/fmt/errol/enum3.zig index f8299d3c6f..7663f9b5d9 100644 --- a/std/fmt/errol/enum3.zig +++ b/std/fmt/errol/enum3.zig @@ -1,4 +1,4 @@ -pub const enum3 = []u64 { +pub const enum3 = []u64{ 0x4e2e2785c3a2a20b, 0x240a28877a09a4e1, 0x728fca36c06cf106, @@ -439,13 +439,13 @@ const Slab = struct { }; fn slab(str: []const u8, exp: i32) Slab { - return Slab { + return Slab{ .str = str, .exp = exp, }; } -pub const enum3_data = []Slab { +pub const enum3_data = []Slab{ slab("40648030339495312", 69), slab("4498645355592131", -134), slab("678321594594593", 244), @@ -879,4 +879,3 @@ pub const enum3_data = []Slab { slab("32216657306260762", 218), slab("30423431424080128", 219), }; - -- cgit v1.2.3 From afdfbc0367b261ea43d5618027e23022c01e2c93 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 23:17:24 -0400 Subject: zig fmt: delete empty comments that do nothing --- std/zig/parser_test.zig | 16 ++++++++++++++++ std/zig/render.zig | 9 +++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 909220a6f6..a2ee77796b 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -28,6 +28,12 @@ test "zig fmt: array literal with hint" { \\ 5, \\ 6, \\ 7 }; + \\const a = []u8{ + \\ 1, 2, + \\ 3, 4, // + \\ 5, 6, // + \\ 7, 8, // + \\}; , \\const a = []u8{ \\ 1, 2, // @@ -53,6 +59,16 @@ test "zig fmt: array literal with hint" { \\ 5, 6, // \\ 7, \\}; + \\const a = []u8{ + \\ 1, + \\ 2, + \\ 3, + \\ 4, + \\ 5, + \\ 6, + \\ 7, + \\ 8, + \\}; \\ ); } diff --git a/std/zig/render.zig b/std/zig/render.zig index fa3755b719..49138e0e78 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -1583,8 +1583,13 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent } } - if (space == Space.IgnoreEmptyComment and mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2) { - return stream.writeByte(' '); + const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2; + if (comment_is_empty) { + switch (space) { + Space.IgnoreEmptyComment => return stream.writeByte(' '), + Space.Newline => return stream.writeByte('\n'), + else => {}, + } } var loc = tree.tokenLocationPtr(token.end, next_token); -- cgit v1.2.3 From 3fed10883bd6916147cce8060949040770532daf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 26 May 2018 23:24:43 -0400 Subject: zig fmt: array literals with no trailing comma all on one line --- std/zig/parser_test.zig | 10 ++++------ std/zig/render.zig | 32 ++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 10 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index a2ee77796b..e83f99c972 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -229,16 +229,14 @@ test "zig fmt: add trailing comma to array literal" { \\comptime { \\ return []u16{'m', 's', 'y', 's', '-' // hi \\ }; + \\ return []u16{'m', 's', 'y', 's', + \\ '-'}; \\} , \\comptime { - \\ return []u16{ - \\ 'm', - \\ 's', - \\ 'y', - \\ 's', - \\ '-', // hi + \\ return []u16{ 'm', 's', 'y', 's', '-' // hi \\ }; + \\ return []u16{ 'm', 's', 'y', 's', '-'}; \\} \\ ); diff --git a/std/zig/render.zig b/std/zig/render.zig index 49138e0e78..9805b7cf75 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -557,11 +557,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind }; - const new_indent = indent + indent_delta; - try renderToken(tree, stream, lbrace, new_indent, Space.Newline); - try stream.writeByteNTimes(' ', new_indent); - if (maybe_row_size) |row_size| { + const new_indent = indent + indent_delta; + try renderToken(tree, stream, lbrace, new_indent, Space.Newline); + try stream.writeByteNTimes(' ', new_indent); + var it = exprs.iterator(0); var i: usize = 0; while (it.next()) |expr| { @@ -597,6 +597,30 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind return; } + const src_has_trailing_comma = blk: { + const maybe_comma = tree.prevToken(suffix_op.rtoken); + break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma; + }; + if (!src_has_trailing_comma) { + try renderToken(tree, stream, lbrace, indent, Space.Space); + var it = exprs.iterator(0); + while (it.next()) |expr| { + try renderExpression(allocator, stream, tree, indent, expr.*, Space.None); + + if (it.peek()) |next_expr| { + const comma = tree.nextToken(expr.*.lastToken()); + try renderToken(tree, stream, comma, indent, Space.Space); // , + } + } + + try renderToken(tree, stream, suffix_op.rtoken, indent, space); + return; + } + + const new_indent = indent + indent_delta; + try renderToken(tree, stream, lbrace, new_indent, Space.Newline); + try stream.writeByteNTimes(' ', new_indent); + var it = exprs.iterator(0); while (it.next()) |expr| { -- cgit v1.2.3 From 122a74724cb527ae6e1997c2c77118047fb50a2c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 28 May 2018 16:23:33 -0400 Subject: zig fmt: use simple newlines rather than empty comments to hint now the first row of an array literal is the hint to zig fmt for how long each row should be. See #1003 --- std/zig/parser_test.zig | 40 +++++++++++++--------- std/zig/render.zig | 91 +++++++++++++++++-------------------------------- 2 files changed, 55 insertions(+), 76 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index e83f99c972..550d8fa111 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -29,34 +29,36 @@ test "zig fmt: array literal with hint" { \\ 6, \\ 7 }; \\const a = []u8{ - \\ 1, 2, + \\ 1, + \\ 2, \\ 3, 4, // \\ 5, 6, // \\ 7, 8, // \\}; , \\const a = []u8{ - \\ 1, 2, // - \\ 3, 4, // - \\ 5, 6, // + \\ 1, 2, + \\ 3, 4, + \\ 5, 6, \\ 7, \\}; \\const a = []u8{ - \\ 1, 2, // - \\ 3, 4, // - \\ 5, 6, // - \\ 7, 8, // + \\ 1, 2, + \\ 3, 4, + \\ 5, 6, + \\ 7, 8, \\}; \\const a = []u8{ - \\ 1, 2, // - \\ 3, 4, // + \\ 1, 2, + \\ 3, 4, \\ 5, 6, // blah - \\ 7, 8, // + \\ 7, 8, \\}; \\const a = []u8{ - \\ 1, 2, // - \\ 3, 4, // - \\ 5, 6, // + \\ 1, 2, + \\ 3, // + \\ 4, + \\ 5, 6, \\ 7, \\}; \\const a = []u8{ @@ -231,12 +233,18 @@ test "zig fmt: add trailing comma to array literal" { \\ }; \\ return []u16{'m', 's', 'y', 's', \\ '-'}; + \\ return []u16{'m', 's', 'y', 's', '-'}; \\} , \\comptime { - \\ return []u16{ 'm', 's', 'y', 's', '-' // hi + \\ return []u16{ + \\ 'm', 's', 'y', 's', '-', // hi + \\ }; + \\ return []u16{ + \\ 'm', 's', 'y', 's', + \\ '-', \\ }; - \\ return []u16{ 'm', 's', 'y', 's', '-'}; + \\ return []u16{ 'm', 's', 'y', 's', '-' }; \\} \\ ); diff --git a/std/zig/render.zig b/std/zig/render.zig index 9805b7cf75..1528ae31aa 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -534,36 +534,42 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind // scan to find row size const maybe_row_size: ?usize = blk: { - var count: usize = 0; + var count: usize = 1; var it = exprs.iterator(0); - var prev_token = (??it.peek()).*.lastToken() + 1; - while (it.next()) |expr| { - const expr_last_token = expr.*.lastToken() + 1; - const next_token = tree.tokens.at(expr_last_token + 1); - const loc = tree.tokenLocationPtr(tree.tokens.at(prev_token).end, next_token); - if (loc.line != 0) break :blk null; - if (next_token.id == Token.Id.LineComment) { - const trimmed = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "); - if (trimmed.len == 2) { - break :blk count; - } else { - break :blk null; + while (true) { + const expr = (??it.next()).*; + if (it.peek()) |next_expr| { + const expr_last_token = expr.*.lastToken() + 1; + const loc = tree.tokenLocation(tree.tokens.at(expr_last_token).end, next_expr.*.firstToken()); + if (loc.line != 0) break :blk count; + count += 1; + } else { + const expr_last_token = expr.*.lastToken(); + const loc = tree.tokenLocation(tree.tokens.at(expr_last_token).end, suffix_op.rtoken); + if (loc.line == 0) { + // all on one line + const src_has_trailing_comma = trailblk: { + const maybe_comma = tree.prevToken(suffix_op.rtoken); + break :trailblk tree.tokens.at(maybe_comma).id == Token.Id.Comma; + }; + if (src_has_trailing_comma) { + break :blk 1; // force row size 1 + } else { + break :blk null; // no newlines + } } + break :blk count; } - prev_token = expr_last_token; - count += 1; } - break :blk null; }; - if (maybe_row_size) |row_size| { const new_indent = indent + indent_delta; try renderToken(tree, stream, lbrace, new_indent, Space.Newline); try stream.writeByteNTimes(' ', new_indent); var it = exprs.iterator(0); - var i: usize = 0; + var i: usize = 1; while (it.next()) |expr| { if (it.peek()) |next_expr| { try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None); @@ -571,23 +577,16 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const comma = tree.nextToken(expr.*.lastToken()); if (i != row_size) { - try renderToken(tree, stream, comma, new_indent, Space.IgnoreEmptyComment); // , + try renderToken(tree, stream, comma, new_indent, Space.Space); // , i += 1; continue; } - i = 0; - - try renderToken(tree, stream, comma, new_indent, Space.NoIndent); // , + i = 1; - const next_token = tree.tokens.at(comma + 1); - if (next_token.id != Token.Id.LineComment) { - try stream.print(" //\n"); - } + try renderToken(tree, stream, comma, new_indent, Space.Newline); // , try renderExtraNewline(tree, stream, next_expr.*); try stream.writeByteNTimes(' ', new_indent); - } else if (i == row_size) { - try renderTrailingCommaAndEmptyComment(allocator, stream, tree, new_indent, expr.*); // , // } else { try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline); // , } @@ -595,50 +594,22 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try stream.writeByteNTimes(' ', indent); try renderToken(tree, stream, suffix_op.rtoken, indent, space); return; - } - - const src_has_trailing_comma = blk: { - const maybe_comma = tree.prevToken(suffix_op.rtoken); - break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma; - }; - if (!src_has_trailing_comma) { + } else { try renderToken(tree, stream, lbrace, indent, Space.Space); var it = exprs.iterator(0); while (it.next()) |expr| { - try renderExpression(allocator, stream, tree, indent, expr.*, Space.None); - if (it.peek()) |next_expr| { + try renderExpression(allocator, stream, tree, indent, expr.*, Space.None); const comma = tree.nextToken(expr.*.lastToken()); try renderToken(tree, stream, comma, indent, Space.Space); // , + } else { + try renderExpression(allocator, stream, tree, indent, expr.*, Space.Space); } } try renderToken(tree, stream, suffix_op.rtoken, indent, space); return; } - - const new_indent = indent + indent_delta; - try renderToken(tree, stream, lbrace, new_indent, Space.Newline); - try stream.writeByteNTimes(' ', new_indent); - - var it = exprs.iterator(0); - while (it.next()) |expr| { - - if (it.peek()) |next_expr| { - try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None); - - const comma = tree.nextToken(expr.*.lastToken()); - try renderToken(tree, stream, comma, new_indent, Space.Newline); // , - - try renderExtraNewline(tree, stream, next_expr.*); - try stream.writeByteNTimes(' ', new_indent); - } else { - try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline); - } - } - - try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); }, } }, -- cgit v1.2.3 From fd13a757855e185b4250c65fe89bbd72c9479a52 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 28 May 2018 16:59:42 -0400 Subject: zig fmt: allow same line struct literal with no trailing comma See #1003 --- std/zig/parser_test.zig | 15 +++++++++++++++ std/zig/render.zig | 31 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 550d8fa111..72818bc074 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,18 @@ +test "zig fmt: struct literal no trailing comma" { + try testTransform( + \\const a = foo{ .x = 1, .y = 2 }; + \\const a = foo{ .x = 1, + \\ .y = 2 }; + , + \\const a = foo{ .x = 1, .y = 2 }; + \\const a = foo{ + \\ .x = 1, + \\ .y = 2, + \\}; + \\ + ); +} + test "zig fmt: array literal with hint" { try testTransform( \\const a = []u8{ diff --git a/std/zig/render.zig b/std/zig/render.zig index 1528ae31aa..86e972c173 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -486,6 +486,37 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind return; } + const src_has_trailing_comma = blk: { + const maybe_comma = tree.prevToken(suffix_op.rtoken); + break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma; + }; + + const src_same_line = blk: { + const loc = tree.tokenLocation(tree.tokens.at(lbrace).end, suffix_op.rtoken); + break :blk loc.line == 0; + }; + + if (!src_has_trailing_comma and src_same_line) { + // render all on one line, no trailing comma + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, Space.Space); + + var it = field_inits.iterator(0); + while (it.next()) |field_init| { + if (it.peek() != null) { + try renderExpression(allocator, stream, tree, indent, field_init.*, Space.None); + + const comma = tree.nextToken(field_init.*.lastToken()); + try renderToken(tree, stream, comma, indent, Space.Space); + } else { + try renderExpression(allocator, stream, tree, indent, field_init.*, Space.Space); + } + } + + try renderToken(tree, stream, suffix_op.rtoken, indent, space); + return; + } + try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); try renderToken(tree, stream, lbrace, indent, Space.Newline); -- cgit v1.2.3 From 6c1fda3f99ebef60f4cb45b6bd66e76c85483c36 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 28 May 2018 17:09:55 -0400 Subject: zig fmt: fix switch body indent --- std/zig/parser_test.zig | 12 ++++++++++++ std/zig/render.zig | 6 +++--- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 72818bc074..dc522b3ef4 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,15 @@ +test "zig fmt: switch comment before prong" { + try testCanonical( + \\comptime { + \\ switch (a) { + \\ // hi + \\ 0 => {}, + \\ } + \\} + \\ + ); +} + test "zig fmt: struct literal no trailing comma" { try testTransform( \\const a = foo{ .x = 1, .y = 2 }; diff --git a/std/zig/render.zig b/std/zig/render.zig index 86e972c173..2f94d1cf8a 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -1050,11 +1050,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None); - try renderToken(tree, stream, rparen, indent, Space.Space); // ) - try renderToken(tree, stream, lbrace, indent, Space.Newline); // { - const new_indent = indent + indent_delta; + try renderToken(tree, stream, rparen, indent, Space.Space); // ) + try renderToken(tree, stream, lbrace, new_indent, Space.Newline); // { + var it = switch_node.cases.iterator(0); while (it.next()) |node| { try stream.writeByteNTimes(' ', new_indent); -- cgit v1.2.3 From 530da363521ca7c3b22e6451874cef24d49683cc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 28 May 2018 17:43:17 -0400 Subject: zig fmt: fix enum decl with no trailing comma See #1003 --- std/zig/parser_test.zig | 12 +++++++++ std/zig/render.zig | 69 ++++++++++++++++++++++++------------------------- 2 files changed, 46 insertions(+), 35 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index dc522b3ef4..dc586e53b4 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,15 @@ +test "zig fmt: enum decl with no trailing comma" { + try testTransform( + \\const StrLitKind = enum {Normal, C}; + , + \\const StrLitKind = enum { + \\ Normal, + \\ C, + \\}; + \\ + ); +} + test "zig fmt: switch comment before prong" { try testCanonical( \\comptime { diff --git a/std/zig/render.zig b/std/zig/render.zig index 2f94d1cf8a..ed760a4b22 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -110,22 +110,29 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i try renderDocComments(tree, stream, tag, indent); - const name_space = if (tag.type_expr == null and tag.value_expr != null) Space.Space else Space.None; - try renderToken(tree, stream, tag.name_token, indent, name_space); // name + if (tag.type_expr == null and tag.value_expr == null) { + return renderTokenAndTrailingComma(tree, stream, tag.name_token, indent, Space.Newline); // name, + } + + if (tag.type_expr == null) { + try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name + } else { + try renderToken(tree, stream, tag.name_token, indent, Space.None); // name + } if (tag.type_expr) |type_expr| { try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // : - const after_type_space = if (tag.value_expr == null) Space.None else Space.Space; - try renderExpression(allocator, stream, tree, indent, type_expr, after_type_space); - } - - if (tag.value_expr) |value_expr| { - try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // = - try renderExpression(allocator, stream, tree, indent, value_expr, Space.None); + if (tag.value_expr == null) { + return renderTrailingComma(allocator, stream, tree, indent, type_expr, Space.Newline); // type, + } else { + try renderExpression(allocator, stream, tree, indent, type_expr, Space.Space); // type + } } - try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); // , + const value_expr = ??tag.value_expr; + try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // = + try renderTrailingComma(allocator, stream, tree, indent, value_expr, Space.Newline); // value, }, ast.Node.Id.EnumTag => { @@ -133,15 +140,14 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i try renderDocComments(tree, stream, tag, indent); - const after_name_space = if (tag.value == null) Space.None else Space.Space; - try renderToken(tree, stream, tag.name_token, indent, after_name_space); // name - if (tag.value) |value| { + try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name + try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // = - try renderExpression(allocator, stream, tree, indent, value, Space.None); + try renderTrailingComma(allocator, stream, tree, indent, value, Space.Newline); + } else { + try renderTokenAndTrailingComma(tree, stream, tag.name_token, indent, Space.Newline); // name } - - try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); // , }, ast.Node.Id.Comptime => { @@ -1584,7 +1590,6 @@ const Space = enum { NoNewline, NoIndent, NoComment, - IgnoreEmptyComment, }; fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void { @@ -1604,7 +1609,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent return stream.write("\n"); } }, - Space.Space, Space.IgnoreEmptyComment => return stream.writeByte(' '), + Space.Space => return stream.writeByte(' '), Space.NoComment => unreachable, } } @@ -1612,7 +1617,6 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2; if (comment_is_empty) { switch (space) { - Space.IgnoreEmptyComment => return stream.writeByte(' '), Space.Newline => return stream.writeByte('\n'), else => {}, } @@ -1644,7 +1648,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent } }, Space.NoNewline => {}, - Space.NoComment, Space.IgnoreEmptyComment => unreachable, + Space.NoComment => unreachable, } return; } @@ -1681,7 +1685,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent try stream.writeByteNTimes(' ', next_line_indent); }, Space.NoNewline => {}, - Space.NoComment, Space.IgnoreEmptyComment => unreachable, + Space.NoComment => unreachable, } return; } @@ -1720,27 +1724,22 @@ fn renderTrailingComma(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, } } -fn renderTrailingCommaAndEmptyComment(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void -{ - const end_token = base.lastToken() + 1; +fn renderTokenAndTrailingComma(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void { + const end_token = token_index + 1; switch (tree.tokens.at(end_token).id) { Token.Id.Comma => { - try renderExpression(allocator, stream, tree, indent, base, Space.None); - try renderToken(tree, stream, end_token, indent, Space.Space); // , - - const next_token = tree.tokens.at(end_token + 1); - if (next_token.id != Token.Id.LineComment) { - try stream.print("//\n"); - } + try renderToken(tree, stream, token_index, indent, Space.None); + try renderToken(tree, stream, end_token, indent, space); // , }, Token.Id.LineComment => { - try renderExpression(allocator, stream, tree, indent, base, Space.NoComment); + try renderToken(tree, stream, token_index, indent, Space.NoComment); try stream.write(", "); - try renderToken(tree, stream, end_token, indent, Space.Newline); + try renderToken(tree, stream, end_token, indent, space); }, else => { - try renderExpression(allocator, stream, tree, indent, base, Space.None); - try stream.write(", //\n"); + try renderToken(tree, stream, token_index, indent, Space.None); + try stream.write(",\n"); + assert(space == Space.Newline); }, } } -- cgit v1.2.3 From 354ab1c5c8ec62c485fbc297817a0e70ab625a71 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 28 May 2018 21:18:41 -0400 Subject: zig fmt: render fn decl with trailing comma 1 line per param --- std/zig/parser_test.zig | 15 ++++- std/zig/render.zig | 158 +++++++++++++++++++++++++----------------------- 2 files changed, 95 insertions(+), 78 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index dc586e53b4..edf1b002b0 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,15 @@ +test "zig fmt: fn decl with trailing comma" { + try testTransform( + \\fn foo(a: i32, b: i32,) void {} + , + \\fn foo( + \\ a: i32, + \\ b: i32, + \\) void {} + \\ + ); +} + test "zig fmt: enum decl with no trailing comma" { try testTransform( \\const StrLitKind = enum {Normal, C}; @@ -247,7 +259,8 @@ test "zig fmt: switch cases trailing comma" { \\ switch (x) { \\ 1, 2, 3 => {}, \\ 4, - \\ 5, => {}, + \\ 5, + \\ => {}, \\ 6...8 => {}, \\ else => {}, \\ } diff --git a/std/zig/render.zig b/std/zig/render.zig index ed760a4b22..b8481b1348 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -102,7 +102,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i } try renderToken(tree, stream, field.name_token, indent, Space.None); // name try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // : - try renderTrailingComma(allocator, stream, tree, indent, field.type_expr, Space.Newline); // type, + try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.Comma); // type, }, ast.Node.Id.UnionTag => { @@ -111,7 +111,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i try renderDocComments(tree, stream, tag, indent); if (tag.type_expr == null and tag.value_expr == null) { - return renderTokenAndTrailingComma(tree, stream, tag.name_token, indent, Space.Newline); // name, + return renderToken(tree, stream, tag.name_token, indent, Space.Comma); // name, } if (tag.type_expr == null) { @@ -124,7 +124,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // : if (tag.value_expr == null) { - return renderTrailingComma(allocator, stream, tree, indent, type_expr, Space.Newline); // type, + return renderExpression(allocator, stream, tree, indent, type_expr, Space.Comma); // type, } else { try renderExpression(allocator, stream, tree, indent, type_expr, Space.Space); // type } @@ -132,7 +132,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i const value_expr = ??tag.value_expr; try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // = - try renderTrailingComma(allocator, stream, tree, indent, value_expr, Space.Newline); // value, + try renderExpression(allocator, stream, tree, indent, value_expr, Space.Comma); // value, }, ast.Node.Id.EnumTag => { @@ -144,9 +144,9 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // = - try renderTrailingComma(allocator, stream, tree, indent, value, Space.Newline); + try renderExpression(allocator, stream, tree, indent, value, Space.Comma); } else { - try renderTokenAndTrailingComma(tree, stream, tag.name_token, indent, Space.Newline); // name + try renderToken(tree, stream, tag.name_token, indent, Space.Comma); // name } }, @@ -413,7 +413,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderToken(tree, stream, comma, new_indent, Space.Newline); // , try renderExtraNewline(tree, stream, next_node.*); } else { - try renderTrailingComma(allocator, stream, tree, param_node_new_indent, param_node.*, Space.Newline); + try renderExpression(allocator, stream, tree, param_node_new_indent, param_node.*, Space.Comma); try stream.writeByteNTimes(' ', indent); try renderToken(tree, stream, suffix_op.rtoken, indent, space); return; @@ -540,7 +540,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExtraNewline(tree, stream, next_field_init.*); } else { - try renderTrailingComma(allocator, stream, tree, new_indent, field_init.*, Space.Newline); + try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.Comma); } } @@ -625,7 +625,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExtraNewline(tree, stream, next_expr.*); try stream.writeByteNTimes(' ', new_indent); } else { - try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline); // , + try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.Comma); // , } } try stream.writeByteNTimes(' ', indent); @@ -892,7 +892,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExtraNewline(tree, stream, next_node.*); } else { - try renderTrailingComma(allocator, stream, tree, new_indent, node.*, Space.Newline); + try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Comma); } } @@ -976,29 +976,55 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space); } - if (fn_proto.name_token) |name_token| blk: { + const lparen = if (fn_proto.name_token) |name_token| blk: { try renderToken(tree, stream, fn_proto.fn_token, indent, Space.Space); // fn try renderToken(tree, stream, name_token, indent, Space.None); // name - try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.None); // ( + break :blk tree.nextToken(name_token); } else blk: { try renderToken(tree, stream, fn_proto.fn_token, indent, Space.None); // fn - try renderToken(tree, stream, tree.nextToken(fn_proto.fn_token), indent, Space.None); // ( - } - - var it = fn_proto.params.iterator(0); - while (it.next()) |param_decl_node| { - try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*); - - if (it.peek() != null) { - const comma = tree.nextToken(param_decl_node.*.lastToken()); - try renderToken(tree, stream, comma, indent, Space.Space); // , - } - } + break :blk tree.nextToken(fn_proto.fn_token); + }; const rparen = tree.prevToken(switch (fn_proto.return_type) { ast.Node.FnProto.ReturnType.Explicit => |node| node.firstToken(), ast.Node.FnProto.ReturnType.InferErrorSet => |node| tree.prevToken(node.firstToken()), }); + + const src_params_trailing_comma = blk: { + const maybe_comma = tree.prevToken(rparen); + break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma; + }; + const src_params_same_line = blk: { + const loc = tree.tokenLocation(tree.tokens.at(lparen).end, rparen); + break :blk loc.line == 0; + }; + + if (!src_params_trailing_comma and src_params_same_line) { + try renderToken(tree, stream, lparen, indent, Space.None); // ( + + // render all on one line, no trailing comma + var it = fn_proto.params.iterator(0); + while (it.next()) |param_decl_node| { + try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*, Space.None); + + if (it.peek() != null) { + const comma = tree.nextToken(param_decl_node.*.lastToken()); + try renderToken(tree, stream, comma, indent, Space.Space); // , + } + } + } else { + // one param per line + const new_indent = indent + indent_delta; + try renderToken(tree, stream, lparen, new_indent, Space.Newline); // ( + + var it = fn_proto.params.iterator(0); + while (it.next()) |param_decl_node| { + try stream.writeByteNTimes(' ', new_indent); + try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*, Space.Comma); + } + try stream.writeByteNTimes(' ', indent); + } + try renderToken(tree, stream, rparen, indent, Space.Space); // ) if (fn_proto.align_expr) |align_expr| { @@ -1064,7 +1090,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = switch_node.cases.iterator(0); while (it.next()) |node| { try stream.writeByteNTimes(' ', new_indent); - try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Newline); + try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Comma); if (it.peek()) |next_node| { try renderExtraNewline(tree, stream, next_node.*); @@ -1110,7 +1136,8 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExtraNewline(tree, stream, next_node.*); try stream.writeByteNTimes(' ', indent); } else { - try renderTrailingComma(allocator, stream, tree, indent, node.*, Space.Space); + try renderExpression(allocator, stream, tree, indent, node.*, Space.Comma); + try stream.writeByteNTimes(' ', indent); break; } } @@ -1122,7 +1149,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try renderExpression(allocator, stream, tree, indent, payload, Space.Space); } - try renderTrailingComma(allocator, stream, tree, indent, switch_case.expr, space); + try renderExpression(allocator, stream, tree, indent, switch_case.expr, space); }, ast.Node.Id.SwitchElse => { const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base); @@ -1543,7 +1570,7 @@ fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent try renderToken(tree, stream, var_decl.semicolon_token, indent, Space.Newline); } -fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { +fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, space: Space) (@typeOf(stream).Child.Error || Error)!void { const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base); if (param_decl.comptime_token) |comptime_token| { @@ -1557,9 +1584,9 @@ fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.Space); // : } if (param_decl.var_args_token) |var_args_token| { - try renderToken(tree, stream, var_args_token, indent, Space.None); + try renderToken(tree, stream, var_args_token, indent, space); } else { - try renderExpression(allocator, stream, tree, indent, param_decl.type_node, Space.None); + try renderExpression(allocator, stream, tree, indent, param_decl.type_node, space); } } @@ -1586,6 +1613,7 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde const Space = enum { None, Newline, + Comma, Space, NoNewline, NoIndent, @@ -1596,9 +1624,27 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent var token = tree.tokens.at(token_index); try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " ")); - if (space == Space.NoComment) return; - var next_token = tree.tokens.at(token_index + 1); + + switch (space) { + Space.NoComment => return, + Space.Comma => switch (next_token.id) { + Token.Id.Comma => return renderToken(tree, stream, token_index + 1, indent, Space.Newline), + Token.Id.LineComment => { + try stream.write(", "); + return renderToken(tree, stream, token_index + 1, indent, Space.Newline); + }, + else => { + if (tree.tokens.at(token_index + 2).id == Token.Id.MultilineStringLiteralLine) { + return stream.write(","); + } else { + return stream.write(",\n"); + } + }, + }, + else => {}, + } + if (next_token.id != Token.Id.LineComment) { switch (space) { Space.None, Space.NoNewline, Space.NoIndent => return, @@ -1610,7 +1656,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent } }, Space.Space => return stream.writeByte(' '), - Space.NoComment => unreachable, + Space.NoComment, Space.Comma => unreachable, } } @@ -1648,7 +1694,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent } }, Space.NoNewline => {}, - Space.NoComment => unreachable, + Space.NoComment, Space.Comma => unreachable, } return; } @@ -1685,7 +1731,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent try stream.writeByteNTimes(' ', next_line_indent); }, Space.NoNewline => {}, - Space.NoComment => unreachable, + Space.NoComment, Space.Comma => unreachable, } return; } @@ -1701,45 +1747,3 @@ fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@t try stream.writeByteNTimes(' ', indent); } } - -fn renderTrailingComma(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, - space: Space) (@typeOf(stream).Child.Error || Error)!void -{ - const end_token = base.lastToken() + 1; - switch (tree.tokens.at(end_token).id) { - Token.Id.Comma => { - try renderExpression(allocator, stream, tree, indent, base, Space.None); - try renderToken(tree, stream, end_token, indent, space); // , - }, - Token.Id.LineComment => { - try renderExpression(allocator, stream, tree, indent, base, Space.NoComment); - try stream.write(", "); - try renderToken(tree, stream, end_token, indent, space); - }, - else => { - try renderExpression(allocator, stream, tree, indent, base, Space.None); - try stream.write(",\n"); - assert(space == Space.Newline); - }, - } -} - -fn renderTokenAndTrailingComma(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void { - const end_token = token_index + 1; - switch (tree.tokens.at(end_token).id) { - Token.Id.Comma => { - try renderToken(tree, stream, token_index, indent, Space.None); - try renderToken(tree, stream, end_token, indent, space); // , - }, - Token.Id.LineComment => { - try renderToken(tree, stream, token_index, indent, Space.NoComment); - try stream.write(", "); - try renderToken(tree, stream, end_token, indent, space); - }, - else => { - try renderToken(tree, stream, token_index, indent, Space.None); - try stream.write(",\n"); - assert(space == Space.Newline); - }, - } -} -- cgit v1.2.3 From 71badebd08a1e5da9326fc7126c4de0fba4ae3d0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 28 May 2018 21:28:32 -0400 Subject: zig fmt: respect line breaks after infix operators --- std/zig/parser_test.zig | 17 +++++++++++++++++ std/zig/render.zig | 12 +++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index edf1b002b0..f722c7f08f 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,20 @@ +test "zig fmt: respect line breaks after infix operators" { + try testCanonical( + \\comptime { + \\ self.crc = + \\ lookup_tables[0][p[7]] ^ + \\ lookup_tables[1][p[6]] ^ + \\ lookup_tables[2][p[5]] ^ + \\ lookup_tables[3][p[4]] ^ + \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^ + \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^ + \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^ + \\ lookup_tables[7][@truncate(u8, self.crc >> 0)]; + \\} + \\ + ); +} + test "zig fmt: fn decl with trailing comma" { try testTransform( \\fn foo(a: i32, b: i32,) void {} diff --git a/std/zig/render.zig b/std/zig/render.zig index b8481b1348..56f3d24b8e 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -254,7 +254,17 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind else => Space.Space, }; try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs, op_space); - try renderToken(tree, stream, infix_op_node.op_token, indent, op_space); + + const after_op_space = blk: { + const loc = tree.tokenLocation(tree.tokens.at(infix_op_node.op_token).end, + tree.nextToken(infix_op_node.op_token)); + break :blk if (loc.line == 0) op_space else Space.Newline; + }; + + try renderToken(tree, stream, infix_op_node.op_token, indent, after_op_space); + if (after_op_space == Space.Newline) { + try stream.writeByteNTimes(' ', indent + indent_delta); + } switch (infix_op_node.op) { ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| { -- cgit v1.2.3 From 77ec81b0353eac45a66b4ed79821c8c954032345 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 28 May 2018 22:22:01 -0400 Subject: zig fmt: respect line breaks in if-else --- std/zig/parser_test.zig | 19 ++++++++ std/zig/render.zig | 116 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 107 insertions(+), 28 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index f722c7f08f..30e7eb3e7c 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,22 @@ +test "zig fmt: respect line breaks in if-else" { + try testCanonical( + \\comptime { + \\ return if (cond) a else b; + \\ return if (cond) + \\ a + \\ else + \\ b; + \\ return if (cond) + \\ a + \\ else if (cond) + \\ b + \\ else + \\ c; + \\} + \\ + ); +} + test "zig fmt: respect line breaks after infix operators" { try testCanonical( \\comptime { diff --git a/std/zig/render.zig b/std/zig/render.zig index 56f3d24b8e..90bc74fd63 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -1315,49 +1315,109 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.Id.If => { const if_node = @fieldParentPtr(ast.Node.If, "base", base); - try renderToken(tree, stream, if_node.if_token, indent, Space.Space); - try renderToken(tree, stream, tree.prevToken(if_node.condition.firstToken()), indent, Space.None); + const lparen = tree.prevToken(if_node.condition.firstToken()); + const rparen = tree.nextToken(if_node.condition.lastToken()); - try renderExpression(allocator, stream, tree, indent, if_node.condition, Space.None); - try renderToken(tree, stream, tree.nextToken(if_node.condition.lastToken()), indent, Space.Space); + try renderToken(tree, stream, if_node.if_token, indent, Space.Space); // if + try renderToken(tree, stream, lparen, indent, Space.None); // ( - if (if_node.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); - } + try renderExpression(allocator, stream, tree, indent, if_node.condition, Space.None); // condition - switch (if_node.body.id) { + const body_is_block = switch (if_node.body.id) { ast.Node.Id.Block, ast.Node.Id.If, ast.Node.Id.For, ast.Node.Id.While, - ast.Node.Id.Switch => { - if (if_node.@"else") |@"else"| { - if (if_node.body.id == ast.Node.Id.Block) { - try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space); - } else { - try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Newline); - try stream.writeByteNTimes(' ', indent); - } + ast.Node.Id.Switch, + => true, + else => false, + }; - try renderExpression(allocator, stream, tree, indent, &@"else".base, space); - } else { - try renderExpression(allocator, stream, tree, indent, if_node.body, space); - } - }, - else => { - if (if_node.@"else") |@"else"| { - try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space); - try renderToken(tree, stream, @"else".else_token, indent, Space.Space); + if (body_is_block) { + try renderToken(tree, stream, rparen, indent, Space.Space); // ) + + if (if_node.payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); // |x| + } + + if (if_node.@"else") |@"else"| { + try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space); + return renderExpression(allocator, stream, tree, indent, &@"else".base, space); + } else { + return renderExpression(allocator, stream, tree, indent, if_node.body, space); + } + } + + const src_has_newline = blk: { + const loc = tree.tokenLocation(tree.tokens.at(rparen).end, if_node.body.lastToken()); + break :blk loc.line != 0; + }; + + if (src_has_newline) { + const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space; + try renderToken(tree, stream, rparen, indent, after_rparen_space); // ) + + if (if_node.payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload, Space.Newline); + } + + const new_indent = indent + indent_delta; + try stream.writeByteNTimes(' ', new_indent); + + if (if_node.@"else") |@"else"| { + const else_is_block = switch (@"else".body.id) { + ast.Node.Id.Block, + ast.Node.Id.If, + ast.Node.Id.For, + ast.Node.Id.While, + ast.Node.Id.Switch, + => true, + else => false, + }; + try renderExpression(allocator, stream, tree, new_indent, if_node.body, Space.Newline); + try stream.writeByteNTimes(' ', indent); + + if (else_is_block) { + try renderToken(tree, stream, @"else".else_token, indent, Space.Space); // else if (@"else".payload) |payload| { try renderExpression(allocator, stream, tree, indent, payload, Space.Space); } - try renderExpression(allocator, stream, tree, indent, @"else".body, space); + return renderExpression(allocator, stream, tree, indent, @"else".body, space); } else { - try renderExpression(allocator, stream, tree, indent, if_node.body, space); + const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space; + try renderToken(tree, stream, @"else".else_token, indent, after_else_space); // else + + if (@"else".payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload, Space.Newline); + } + try stream.writeByteNTimes(' ', new_indent); + + return renderExpression(allocator, stream, tree, new_indent, @"else".body, space); } - }, + } else { + return renderExpression(allocator, stream, tree, new_indent, if_node.body, space); + } + } + + try renderToken(tree, stream, rparen, indent, Space.Space); // ) + + if (if_node.payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + } + + if (if_node.@"else") |@"else"| { + try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space); + try renderToken(tree, stream, @"else".else_token, indent, Space.Space); + + if (@"else".payload) |payload| { + try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + } + + return renderExpression(allocator, stream, tree, indent, @"else".body, space); + } else { + return renderExpression(allocator, stream, tree, indent, if_node.body, space); } }, -- cgit v1.2.3 From 0d1b47362c7623ba923a6831dab0989133caf9ab Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 28 May 2018 22:41:05 -0400 Subject: zig fmt: if-else with comment before else --- std/zig/parser_test.zig | 18 ++++++++++++++++++ std/zig/render.zig | 20 ++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 30e7eb3e7c..0f8b2d798a 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,21 @@ +test "zig fmt: if-else with comment before else" { + try testCanonical( + \\comptime { + \\ // cexp(finite|nan +- i inf|nan) = nan + i nan + \\ if ((hx & 0x7fffffff) != 0x7f800000) { + \\ return Complex(f32).new(y - y, y - y); + \\ } // cexp(-inf +- i inf|nan) = 0 + i0 + \\ else if (hx & 0x80000000 != 0) { + \\ return Complex(f32).new(0, 0); + \\ } // cexp(+inf +- i inf|nan) = inf + i nan + \\ else { + \\ return Complex(f32).new(x, y - y); + \\ } + \\} + \\ + ); +} + test "zig fmt: respect line breaks in if-else" { try testCanonical( \\comptime { diff --git a/std/zig/render.zig b/std/zig/render.zig index 90bc74fd63..af8f3f385c 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -1341,7 +1341,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } if (if_node.@"else") |@"else"| { - try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space); + try renderExpression(allocator, stream, tree, indent, if_node.body, Space.SpaceOrOutdent); return renderExpression(allocator, stream, tree, indent, &@"else".base, space); } else { return renderExpression(allocator, stream, tree, indent, if_node.body, space); @@ -1685,8 +1685,8 @@ const Space = enum { Newline, Comma, Space, + SpaceOrOutdent, NoNewline, - NoIndent, NoComment, }; @@ -1717,7 +1717,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent if (next_token.id != Token.Id.LineComment) { switch (space) { - Space.None, Space.NoNewline, Space.NoIndent => return, + Space.None, Space.NoNewline => return, Space.Newline => { if (next_token.id == Token.Id.MultilineStringLiteralLine) { return; @@ -1725,7 +1725,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent return stream.write("\n"); } }, - Space.Space => return stream.writeByte(' '), + Space.Space, Space.SpaceOrOutdent => return stream.writeByte(' '), Space.NoComment, Space.Comma => unreachable, } } @@ -1756,7 +1756,11 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent }; try stream.writeByteNTimes(' ', next_line_indent); }, - Space.Newline, Space.NoIndent => { + Space.SpaceOrOutdent => { + try stream.writeByte('\n'); + try stream.writeByteNTimes(' ', indent); + }, + Space.Newline => { if (next_token.id == Token.Id.MultilineStringLiteralLine) { return; } else { @@ -1783,7 +1787,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent next_token = tree.tokens.at(token_index + offset); if (next_token.id != Token.Id.LineComment) { switch (space) { - Space.Newline, Space.NoIndent => { + Space.Newline => { if (next_token.id == Token.Id.MultilineStringLiteralLine) { return; } else { @@ -1800,6 +1804,10 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent }; try stream.writeByteNTimes(' ', next_line_indent); }, + Space.SpaceOrOutdent => { + try stream.writeByte('\n'); + try stream.writeByteNTimes(' ', indent); + }, Space.NoNewline => {}, Space.NoComment, Space.Comma => unreachable, } -- cgit v1.2.3 From 530d17542207151f768a14a0cc8311181599b9b9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 28 May 2018 23:41:09 -0400 Subject: zig fmt: fix spacing when moving doc comment on var decls --- std/zig/parser_test.zig | 39 +++++++++++++++++++++++++-------------- std/zig/render.zig | 33 +++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 22 deletions(-) (limited to 'std') diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 0f8b2d798a..0106b990bc 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,28 @@ +test "zig fmt: same-line doc comment on variable declaration" { + try testTransform( + \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space + \\pub const MAP_FILE = 0x0000; /// map from file (default) + \\ + \\pub const EMEDIUMTYPE = 124; /// Wrong medium type + \\ + \\// nameserver query return codes + \\pub const ENSROK = 0; /// DNS server returned answer with no data + , + \\/// allocated from memory, swap space + \\pub const MAP_ANONYMOUS = 0x1000; + \\/// map from file (default) + \\pub const MAP_FILE = 0x0000; + \\ + \\/// Wrong medium type + \\pub const EMEDIUMTYPE = 124; + \\ + \\// nameserver query return codes + \\/// DNS server returned answer with no data + \\pub const ENSROK = 0; + \\ + ); +} + test "zig fmt: if-else with comment before else" { try testCanonical( \\comptime { @@ -557,20 +582,6 @@ test "zig fmt: add comma on last switch prong" { ); } -test "zig fmt: same-line doc comment on variable declaration" { - try testTransform( - \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space - \\pub const MAP_FILE = 0x0000; /// map from file (default) - \\ - , - \\/// allocated from memory, swap space - \\pub const MAP_ANONYMOUS = 0x1000; - \\/// map from file (default) - \\pub const MAP_FILE = 0x0000; - \\ - ); -} - test "zig fmt: same-line comment after a statement" { try testCanonical( \\test "" { diff --git a/std/zig/render.zig b/std/zig/render.zig index af8f3f385c..3248b33aa7 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -39,11 +39,12 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf( } fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void { - var first_token = node.firstToken(); - while (tree.tokens.at(first_token - 1).id == Token.Id.DocComment) { - first_token -= 1; + const first_token = node.firstToken(); + var prev_token = first_token; + while (tree.tokens.at(prev_token - 1).id == Token.Id.DocComment) { + prev_token -= 1; } - const prev_token_end = tree.tokens.at(first_token - 1).end; + const prev_token_end = tree.tokens.at(prev_token - 1).end; const loc = tree.tokenLocation(prev_token_end, first_token); if (loc.line >= 2) { try stream.writeByte('\n'); @@ -1715,7 +1716,17 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent else => {}, } - if (next_token.id != Token.Id.LineComment) { + // Skip over same line doc comments + var offset: usize = 1; + if (next_token.id == Token.Id.DocComment) { + const loc = tree.tokenLocationPtr(token.end, next_token); + if (loc.line == 0) { + offset += 1; + next_token = tree.tokens.at(token_index + offset); + } + } + + if (next_token.id != Token.Id.LineComment) blk: { switch (space) { Space.None, Space.NoNewline => return, Space.Newline => { @@ -1739,7 +1750,6 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent } var loc = tree.tokenLocationPtr(token.end, next_token); - var offset: usize = 1; if (loc.line == 0) { try stream.print(" {}", mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ")); offset = 2; @@ -1820,8 +1830,15 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@typeOf(stream).Child.Error || Error)!void { const comment = node.doc_comments ?? return; var it = comment.lines.iterator(0); + const first_token = node.firstToken(); while (it.next()) |line_token_index| { - try renderToken(tree, stream, line_token_index.*, indent, Space.Newline); - try stream.writeByteNTimes(' ', indent); + if (line_token_index.* < first_token) { + try renderToken(tree, stream, line_token_index.*, indent, Space.Newline); + try stream.writeByteNTimes(' ', indent); + } else { + try renderToken(tree, stream, line_token_index.*, indent, Space.NoComment); + try stream.write("\n"); + try stream.writeByteNTimes(' ', indent); + } } } -- cgit v1.2.3 From eda6898c5b253367174172db909ee23013f32733 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 29 May 2018 03:15:12 -0400 Subject: zig fmt: handle if and while indentation better --- std/zig/ast.zig | 24 +- std/zig/parser_test.zig | 92 ++++ std/zig/render.zig | 1077 ++++++++++++++++++++++++----------------------- 3 files changed, 658 insertions(+), 535 deletions(-) (limited to 'std') diff --git a/std/zig/ast.zig b/std/zig/ast.zig index addd3a37e8..3b705e2ee6 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -68,6 +68,14 @@ pub const Tree = struct { return self.tokenLocationPtr(start_index, self.tokens.at(token_index)); } + pub fn tokensOnSameLine(self: &Tree, token1_index: TokenIndex, token2_index: TokenIndex) bool { + return self.tokensOnSameLinePtr(self.tokens.at(token1_index), self.tokens.at(token2_index)); + } + + pub fn tokensOnSameLinePtr(self: &Tree, token1: &const Token, token2: &const Token) bool { + return mem.indexOfScalar(u8, self.source[token1.end..token2.start], '\n') == null; + } + pub fn dump(self: &Tree) void { self.root_node.base.dump(0); } @@ -1529,14 +1537,14 @@ pub const Node = struct { switch (self.op) { Op.SliceType => |addr_of_info| { - if (addr_of_info.align_expr) |align_expr| { - if (i < 1) return align_expr; + if (addr_of_info.align_info) |align_info| { + if (i < 1) return align_info.node; i -= 1; } }, Op.AddrOf => |addr_of_info| { - if (addr_of_info.align_expr) |align_expr| { - if (i < 1) return align_expr; + if (addr_of_info.align_info) |align_info| { + if (i < 1) return align_info.node; i -= 1; } }, @@ -1553,7 +1561,9 @@ pub const Node = struct { Op.NegationWrap, Op.Try, Op.Resume, - Op.UnwrapMaybe => {}, + Op.UnwrapMaybe, + Op.PointerType, + => {}, } if (i < 1) return self.rhs; @@ -1656,6 +1666,7 @@ pub const Node = struct { if (i < fields.len) return fields.at(i).*; i -= fields.len; }, + Op.Deref => {}, } return null; @@ -2082,9 +2093,6 @@ pub const Node = struct { if (i < self.inputs.len) return &(self.inputs.at(index).*).base; i -= self.inputs.len; - if (i < self.clobbers.len) return self.clobbers.at(index).*; - i -= self.clobbers.len; - return null; } diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 0106b990bc..8ed748ed30 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,3 +1,95 @@ +test "zig fmt: if condition wraps" { + try testTransform( + \\comptime { + \\ if (cond and + \\ cond) { + \\ return x; + \\ } + \\ while (cond and + \\ cond) { + \\ return x; + \\ } + \\ if (a == b and + \\ c) { + \\ a = b; + \\ } + \\ while (a == b and + \\ c) { + \\ a = b; + \\ } + \\ if ((cond and + \\ cond)) { + \\ return x; + \\ } + \\ while ((cond and + \\ cond)) { + \\ return x; + \\ } + \\ var a = if (a) |*f| x: { + \\ break :x &a.b; + \\ } else |err| err; + \\} + , + \\comptime { + \\ if (cond and + \\ cond) + \\ { + \\ return x; + \\ } + \\ while (cond and + \\ cond) + \\ { + \\ return x; + \\ } + \\ if (a == b and + \\ c) + \\ { + \\ a = b; + \\ } + \\ while (a == b and + \\ c) + \\ { + \\ a = b; + \\ } + \\ if ((cond and + \\ cond)) + \\ { + \\ return x; + \\ } + \\ while ((cond and + \\ cond)) + \\ { + \\ return x; + \\ } + \\ var a = if (a) |*f| x: { + \\ break :x &a.b; + \\ } else |err| err; + \\} + \\ + ); +} + +test "zig fmt: if condition has line break but must not wrap" { + try testCanonical( + \\comptime { + \\ if (self.user_input_options.put(name, UserInputOption{ + \\ .name = name, + \\ .used = false, + \\ }) catch unreachable) |*prev_value| { + \\ foo(); + \\ bar(); + \\ } + \\ if (put( + \\ a, + \\ b, + \\ )) { + \\ foo(); + \\ } + \\} + \\ + ); +} + test "zig fmt: same-line doc comment on variable declaration" { try testTransform( \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space diff --git a/std/zig/render.zig b/std/zig/render.zig index 3248b33aa7..16aed808fc 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -28,17 +28,17 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf( } } - + var start_col: usize = 0; var it = tree.root_node.decls.iterator(0); while (it.next()) |decl| { - try renderTopLevelDecl(allocator, stream, tree, 0, decl.*); + try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl.*); if (it.peek()) |next_decl| { - try renderExtraNewline(tree, stream, next_decl.*); + try renderExtraNewline(tree, stream, &start_col, next_decl.*); } } } -fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void { +fn renderExtraNewline(tree: &ast.Tree, stream: var, start_col: &usize, node: &ast.Node) !void { const first_token = node.firstToken(); var prev_token = first_token; while (tree.tokens.at(prev_token - 1).id == Token.Id.DocComment) { @@ -48,22 +48,23 @@ fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void { const loc = tree.tokenLocation(prev_token_end, first_token); if (loc.line >= 2) { try stream.writeByte('\n'); + start_col.* = 0; } } -fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, decl: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { +fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, decl: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { switch (decl.id) { ast.Node.Id.FnProto => { const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); - try renderDocComments(tree, stream, fn_proto, indent); + try renderDocComments(tree, stream, fn_proto, indent, start_col); if (fn_proto.body_node) |body_node| { - try renderExpression(allocator, stream, tree, indent, decl, Space.Space); - try renderExpression(allocator, stream, tree, indent, body_node, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, body_node, Space.Newline); } else { - try renderExpression(allocator, stream, tree, indent, decl, Space.None); - try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.None); + try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, start_col, Space.Newline); } }, @@ -71,153 +72,154 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl); if (use_decl.visib_token) |visib_token| { - try renderToken(tree, stream, visib_token, indent, Space.Space); // pub + try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub } - try renderToken(tree, stream, use_decl.use_token, indent, Space.Space); // use - try renderExpression(allocator, stream, tree, indent, use_decl.expr, Space.None); - try renderToken(tree, stream, use_decl.semicolon_token, indent, Space.Newline); // ; + try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // use + try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, Space.None); + try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, Space.Newline); // ; }, ast.Node.Id.VarDecl => { const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl); - try renderDocComments(tree, stream, var_decl, indent); - try renderVarDecl(allocator, stream, tree, indent, var_decl); + try renderDocComments(tree, stream, var_decl, indent, start_col); + try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl); }, ast.Node.Id.TestDecl => { const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl); - try renderDocComments(tree, stream, test_decl, indent); - try renderToken(tree, stream, test_decl.test_token, indent, Space.Space); - try renderExpression(allocator, stream, tree, indent, test_decl.name, Space.Space); - try renderExpression(allocator, stream, tree, indent, test_decl.body_node, Space.Newline); + try renderDocComments(tree, stream, test_decl, indent, start_col); + try renderToken(tree, stream, test_decl.test_token, indent, start_col, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, Space.Newline); }, ast.Node.Id.StructField => { const field = @fieldParentPtr(ast.Node.StructField, "base", decl); - try renderDocComments(tree, stream, field, indent); + try renderDocComments(tree, stream, field, indent, start_col); if (field.visib_token) |visib_token| { - try renderToken(tree, stream, visib_token, indent, Space.Space); // pub + try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub } - try renderToken(tree, stream, field.name_token, indent, Space.None); // name - try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // : - try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.Comma); // type, + try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name + try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // : + try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr, Space.Comma); // type, }, ast.Node.Id.UnionTag => { const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl); - try renderDocComments(tree, stream, tag, indent); + try renderDocComments(tree, stream, tag, indent, start_col); if (tag.type_expr == null and tag.value_expr == null) { - return renderToken(tree, stream, tag.name_token, indent, Space.Comma); // name, + return renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name, } if (tag.type_expr == null) { - try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name + try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name } else { - try renderToken(tree, stream, tag.name_token, indent, Space.None); // name + try renderToken(tree, stream, tag.name_token, indent, start_col, Space.None); // name } if (tag.type_expr) |type_expr| { - try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // : + try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // : if (tag.value_expr == null) { - return renderExpression(allocator, stream, tree, indent, type_expr, Space.Comma); // type, + try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Comma); // type, + return; } else { - try renderExpression(allocator, stream, tree, indent, type_expr, Space.Space); // type + try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Space); // type } } const value_expr = ??tag.value_expr; - try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // = - try renderExpression(allocator, stream, tree, indent, value_expr, Space.Comma); // value, + try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, start_col, Space.Space); // = + try renderExpression(allocator, stream, tree, indent, start_col, value_expr, Space.Comma); // value, }, ast.Node.Id.EnumTag => { const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl); - try renderDocComments(tree, stream, tag, indent); + try renderDocComments(tree, stream, tag, indent, start_col); if (tag.value) |value| { - try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name + try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name - try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // = - try renderExpression(allocator, stream, tree, indent, value, Space.Comma); + try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // = + try renderExpression(allocator, stream, tree, indent, start_col, value, Space.Comma); } else { - try renderToken(tree, stream, tag.name_token, indent, Space.Comma); // name + try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name } }, ast.Node.Id.Comptime => { assert(!decl.requireSemiColon()); - try renderExpression(allocator, stream, tree, indent, decl, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Newline); }, else => unreachable, } } -fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, space: Space) (@typeOf(stream).Child.Error || Error)!void { +fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, base: &ast.Node, space: Space,) (@typeOf(stream).Child.Error || Error)!void { switch (base.id) { ast.Node.Id.Identifier => { const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base); - try renderToken(tree, stream, identifier.token, indent, space); + return renderToken(tree, stream, identifier.token, indent, start_col, space); }, ast.Node.Id.Block => { const block = @fieldParentPtr(ast.Node.Block, "base", base); if (block.label) |label| { - try renderToken(tree, stream, label, indent, Space.None); - try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); + 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) { - try renderToken(tree, stream, block.lbrace, indent + indent_delta, Space.None); - try renderToken(tree, stream, block.rbrace, indent, space); + 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, Space.Newline); + try renderToken(tree, stream, block.lbrace, block_indent, start_col, Space.Newline); var it = block.statements.iterator(0); while (it.next()) |statement| { try stream.writeByteNTimes(' ', block_indent); - try renderStatement(allocator, stream, tree, block_indent, statement.*); + try renderStatement(allocator, stream, tree, block_indent, start_col, statement.*); if (it.peek()) |next_statement| { - try renderExtraNewline(tree, stream, next_statement.*); + try renderExtraNewline(tree, stream, start_col, next_statement.*); } } try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, block.rbrace, indent, space); + return renderToken(tree, stream, block.rbrace, indent, start_col, space); } }, ast.Node.Id.Defer => { const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base); - try renderToken(tree, stream, defer_node.defer_token, indent, Space.Space); - try renderExpression(allocator, stream, tree, indent, defer_node.expr, space); + try renderToken(tree, stream, defer_node.defer_token, indent, start_col, Space.Space); + return renderExpression(allocator, stream, tree, indent, start_col, defer_node.expr, space); }, ast.Node.Id.Comptime => { const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base); - try renderToken(tree, stream, comptime_node.comptime_token, indent, Space.Space); - try renderExpression(allocator, stream, tree, indent, comptime_node.expr, space); + try renderToken(tree, stream, comptime_node.comptime_token, indent, start_col, Space.Space); + return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space); }, ast.Node.Id.AsyncAttribute => { const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base); if (async_attr.allocator_type) |allocator_type| { - try renderToken(tree, stream, async_attr.async_token, indent, Space.None); + try renderToken(tree, stream, async_attr.async_token, indent, start_col, Space.None); - try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, Space.None); - try renderExpression(allocator, stream, tree, indent, allocator_type, Space.None); - try renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, space); + try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, start_col, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, allocator_type, Space.None); + return renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, start_col, space); } else { - try renderToken(tree, stream, async_attr.async_token, indent, space); + return renderToken(tree, stream, async_attr.async_token, indent, start_col, space); } }, @@ -225,24 +227,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base); if (suspend_node.label) |label| { - try renderToken(tree, stream, label, indent, Space.None); - try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); + try renderToken(tree, stream, label, indent, start_col, Space.None); + try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); } if (suspend_node.payload) |payload| { if (suspend_node.body) |body| { - try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space); - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); - try renderExpression(allocator, stream, tree, indent, body, space); + try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); + return renderExpression(allocator, stream, tree, indent, start_col, body, space); } else { - try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space); - try renderExpression(allocator, stream, tree, indent, payload, space); + try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space); + return renderExpression(allocator, stream, tree, indent, start_col, payload, space); } } else if (suspend_node.body) |body| { - try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space); - try renderExpression(allocator, stream, tree, indent, body, space); + try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space); + return renderExpression(allocator, stream, tree, indent, start_col, body, space); } else { - try renderToken(tree, stream, suspend_node.suspend_token, indent, space); + return renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, space); } }, @@ -254,7 +256,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None, else => Space.Space, }; - try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs, op_space); + try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space); const after_op_space = blk: { const loc = tree.tokenLocation(tree.tokens.at(infix_op_node.op_token).end, @@ -262,19 +264,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind break :blk if (loc.line == 0) op_space else Space.Newline; }; - try renderToken(tree, stream, infix_op_node.op_token, indent, after_op_space); + try renderToken(tree, stream, infix_op_node.op_token, indent, start_col, after_op_space); if (after_op_space == Space.Newline) { try stream.writeByteNTimes(' ', indent + indent_delta); + start_col.* = indent + indent_delta; } switch (infix_op_node.op) { ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); }, else => {}, } - try renderExpression(allocator, stream, tree, indent, infix_op_node.rhs, space); + return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space); }, ast.Node.Id.PrefixOp => { @@ -282,81 +285,81 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind switch (prefix_op_node.op) { ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| { - try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // & + try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // & if (addr_of_info.align_info) |align_info| { const lparen_token = tree.prevToken(align_info.node.firstToken()); const align_token = tree.prevToken(lparen_token); - try renderToken(tree, stream, align_token, indent, Space.None); // align - try renderToken(tree, stream, lparen_token, indent, Space.None); // ( + try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align + try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, align_info.node, Space.None); if (align_info.bit_range) |bit_range| { const colon1 = tree.prevToken(bit_range.start.firstToken()); const colon2 = tree.prevToken(bit_range.end.firstToken()); - try renderToken(tree, stream, colon1, indent, Space.None); // : - try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None); - try renderToken(tree, stream, colon2, indent, Space.None); // : - try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None); + try renderToken(tree, stream, colon1, indent, start_col, Space.None); // : + try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None); + try renderToken(tree, stream, colon2, indent, start_col, Space.None); // : + try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None); const rparen_token = tree.nextToken(bit_range.end.lastToken()); - try renderToken(tree, stream, rparen_token, indent, Space.Space); // ) + try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // ) } else { const rparen_token = tree.nextToken(align_info.node.lastToken()); - try renderToken(tree, stream, rparen_token, indent, Space.Space); // ) + try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // ) } } if (addr_of_info.const_token) |const_token| { - try renderToken(tree, stream, const_token, indent, Space.Space); // const + try renderToken(tree, stream, const_token, indent, start_col, Space.Space); // const } if (addr_of_info.volatile_token) |volatile_token| { - try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile + try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile } }, ast.Node.PrefixOp.Op.SliceType => |addr_of_info| { - try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [ - try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ] + try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [ + try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, start_col, Space.None); // ] if (addr_of_info.align_info) |align_info| { const lparen_token = tree.prevToken(align_info.node.firstToken()); const align_token = tree.prevToken(lparen_token); - try renderToken(tree, stream, align_token, indent, Space.None); // align - try renderToken(tree, stream, lparen_token, indent, Space.None); // ( + try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align + try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, align_info.node, Space.None); if (align_info.bit_range) |bit_range| { const colon1 = tree.prevToken(bit_range.start.firstToken()); const colon2 = tree.prevToken(bit_range.end.firstToken()); - try renderToken(tree, stream, colon1, indent, Space.None); // : - try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None); - try renderToken(tree, stream, colon2, indent, Space.None); // : - try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None); + try renderToken(tree, stream, colon1, indent, start_col, Space.None); // : + try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None); + try renderToken(tree, stream, colon2, indent, start_col, Space.None); // : + try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None); const rparen_token = tree.nextToken(bit_range.end.lastToken()); - try renderToken(tree, stream, rparen_token, indent, Space.Space); // ) + try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // ) } else { const rparen_token = tree.nextToken(align_info.node.lastToken()); - try renderToken(tree, stream, rparen_token, indent, Space.Space); // ) + try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // ) } } if (addr_of_info.const_token) |const_token| { - try renderToken(tree, stream, const_token, indent, Space.Space); + try renderToken(tree, stream, const_token, indent, start_col, Space.Space); } if (addr_of_info.volatile_token) |volatile_token| { - try renderToken(tree, stream, volatile_token, indent, Space.Space); + try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); } }, ast.Node.PrefixOp.Op.ArrayType => |array_index| { - try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [ - try renderExpression(allocator, stream, tree, indent, array_index, Space.None); - try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, Space.None); // ] + try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [ + try renderExpression(allocator, stream, tree, indent, start_col, array_index, Space.None); + try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, start_col, Space.None); // ] }, ast.Node.PrefixOp.Op.BitNot, ast.Node.PrefixOp.Op.BoolNot, @@ -365,18 +368,18 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.PrefixOp.Op.UnwrapMaybe, ast.Node.PrefixOp.Op.MaybeType, ast.Node.PrefixOp.Op.PointerType => { - try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); + try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); }, ast.Node.PrefixOp.Op.Try, ast.Node.PrefixOp.Op.Await, ast.Node.PrefixOp.Op.Cancel, ast.Node.PrefixOp.Op.Resume => { - try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.Space); + try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space); }, } - try renderExpression(allocator, stream, tree, indent, prefix_op_node.rhs, space); + return renderExpression(allocator, stream, tree, indent, start_col, prefix_op_node.rhs, space); }, ast.Node.Id.SuffixOp => { @@ -385,17 +388,16 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind switch (suffix_op.op) { @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| { if (call_info.async_attr) |async_attr| { - try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, &async_attr.base, Space.Space); } - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); const lparen = tree.nextToken(suffix_op.lhs.lastToken()); if (call_info.params.len == 0) { - try renderToken(tree, stream, lparen, indent, Space.None); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + try renderToken(tree, stream, lparen, indent, start_col, Space.None); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } const src_has_trailing_comma = blk: { @@ -405,7 +407,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind if (src_has_trailing_comma) { const new_indent = indent + indent_delta; - try renderToken(tree, stream, lparen, new_indent, Space.Newline); + try renderToken(tree, stream, lparen, new_indent, start_col, Space.Newline); var it = call_info.params.iterator(0); while (true) { @@ -419,72 +421,70 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind }; if (it.peek()) |next_node| { - try renderExpression(allocator, stream, tree, param_node_new_indent, param_node.*, Space.None); + try renderExpression(allocator, stream, tree, param_node_new_indent, start_col, param_node.*, Space.None); const comma = tree.nextToken(param_node.*.lastToken()); - try renderToken(tree, stream, comma, new_indent, Space.Newline); // , - try renderExtraNewline(tree, stream, next_node.*); + try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // , + try renderExtraNewline(tree, stream, start_col, next_node.*); } else { - try renderExpression(allocator, stream, tree, param_node_new_indent, param_node.*, Space.Comma); + try renderExpression(allocator, stream, tree, param_node_new_indent, start_col, param_node.*, Space.Comma); try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } } } - try renderToken(tree, stream, lparen, indent, Space.None); // ( + try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( var it = call_info.params.iterator(0); while (it.next()) |param_node| { - try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, param_node.*, Space.None); if (it.peek() != null) { const comma = tree.nextToken(param_node.*.lastToken()); - try renderToken(tree, stream, comma, indent, Space.Space); + try renderToken(tree, stream, comma, indent, start_col, Space.Space); } } - try renderToken(tree, stream, suffix_op.rtoken, indent, space); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); }, ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| { const lbracket = tree.prevToken(index_expr.firstToken()); const rbracket = tree.nextToken(index_expr.lastToken()); - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); - try renderToken(tree, stream, lbracket, indent, Space.None); // [ - try renderExpression(allocator, stream, tree, indent, index_expr, Space.None); - try renderToken(tree, stream, rbracket, indent, space); // ] + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ + try renderExpression(allocator, stream, tree, indent, start_col, index_expr, Space.None); + return renderToken(tree, stream, rbracket, indent, start_col, space); // ] }, ast.Node.SuffixOp.Op.Deref => { - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); - try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, Space.None); // . - try renderToken(tree, stream, suffix_op.rtoken, indent, space); // * + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // . + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // * }, @TagType(ast.Node.SuffixOp.Op).Slice => |range| { - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); const lbracket = tree.prevToken(range.start.firstToken()); const dotdot = tree.nextToken(range.start.lastToken()); - try renderToken(tree, stream, lbracket, indent, Space.None); // [ - try renderExpression(allocator, stream, tree, indent, range.start, Space.None); - try renderToken(tree, stream, dotdot, indent, Space.None); // .. + try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ + try renderExpression(allocator, stream, tree, indent, start_col, range.start, Space.None); + try renderToken(tree, stream, dotdot, indent, start_col, Space.None); // .. if (range.end) |end| { - try renderExpression(allocator, stream, tree, indent, end, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, end, Space.None); } - try renderToken(tree, stream, suffix_op.rtoken, indent, space); // ] + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ] }, ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| { const lbrace = tree.nextToken(suffix_op.lhs.lastToken()); if (field_inits.len == 0) { - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); - try renderToken(tree, stream, lbrace, indent, Space.None); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, start_col, Space.None); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } if (field_inits.len == 1) blk: { @@ -496,11 +496,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } } - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); - try renderToken(tree, stream, lbrace, indent, Space.Space); - try renderExpression(allocator, stream, tree, indent, &field_init.base, Space.Space); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } const src_has_trailing_comma = blk: { @@ -515,27 +514,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind if (!src_has_trailing_comma and src_same_line) { // render all on one line, no trailing comma - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); - try renderToken(tree, stream, lbrace, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); var it = field_inits.iterator(0); while (it.next()) |field_init| { if (it.peek() != null) { - try renderExpression(allocator, stream, tree, indent, field_init.*, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, field_init.*, Space.None); const comma = tree.nextToken(field_init.*.lastToken()); - try renderToken(tree, stream, comma, indent, Space.Space); + try renderToken(tree, stream, comma, indent, start_col, Space.Space); } else { - try renderExpression(allocator, stream, tree, indent, field_init.*, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, field_init.*, Space.Space); } } - try renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); - try renderToken(tree, stream, lbrace, indent, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); const new_indent = indent + indent_delta; @@ -544,41 +542,39 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try stream.writeByteNTimes(' ', new_indent); if (it.peek()) |next_field_init| { - try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.None); + try renderExpression(allocator, stream, tree, new_indent, start_col, field_init.*, Space.None); const comma = tree.nextToken(field_init.*.lastToken()); - try renderToken(tree, stream, comma, new_indent, Space.Newline); + try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); - try renderExtraNewline(tree, stream, next_field_init.*); + try renderExtraNewline(tree, stream, start_col, next_field_init.*); } else { - try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.Comma); + try renderExpression(allocator, stream, tree, new_indent, start_col, field_init.*, Space.Comma); } } try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); }, ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| { const lbrace = tree.nextToken(suffix_op.lhs.lastToken()); if (exprs.len == 0) { - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); - try renderToken(tree, stream, lbrace, indent, Space.None); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, start_col, Space.None); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } if (exprs.len == 1) { const expr = exprs.at(0).*; - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); - try renderToken(tree, stream, lbrace, indent, Space.None); - try renderExpression(allocator, stream, tree, indent, expr, Space.None); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderToken(tree, stream, lbrace, indent, start_col, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); // scan to find row size const maybe_row_size: ?usize = blk: { @@ -613,50 +609,48 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind if (maybe_row_size) |row_size| { const new_indent = indent + indent_delta; - try renderToken(tree, stream, lbrace, new_indent, Space.Newline); + try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline); try stream.writeByteNTimes(' ', new_indent); var it = exprs.iterator(0); var i: usize = 1; while (it.next()) |expr| { if (it.peek()) |next_expr| { - try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None); + try renderExpression(allocator, stream, tree, new_indent, start_col, expr.*, Space.None); const comma = tree.nextToken(expr.*.lastToken()); if (i != row_size) { - try renderToken(tree, stream, comma, new_indent, Space.Space); // , + try renderToken(tree, stream, comma, new_indent, start_col, Space.Space); // , i += 1; continue; } i = 1; - try renderToken(tree, stream, comma, new_indent, Space.Newline); // , + try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // , - try renderExtraNewline(tree, stream, next_expr.*); + try renderExtraNewline(tree, stream, start_col, next_expr.*); try stream.writeByteNTimes(' ', new_indent); } else { - try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.Comma); // , + try renderExpression(allocator, stream, tree, new_indent, start_col, expr.*, Space.Comma); // , } } try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } else { - try renderToken(tree, stream, lbrace, indent, Space.Space); + try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); var it = exprs.iterator(0); while (it.next()) |expr| { if (it.peek()) |next_expr| { - try renderExpression(allocator, stream, tree, indent, expr.*, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, expr.*, Space.None); const comma = tree.nextToken(expr.*.lastToken()); - try renderToken(tree, stream, comma, indent, Space.Space); // , + try renderToken(tree, stream, comma, indent, start_col, Space.Space); // , } else { - try renderExpression(allocator, stream, tree, indent, expr.*, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, expr.*, Space.Space); } } - try renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } }, } @@ -667,195 +661,204 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind switch (flow_expr.kind) { ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| { - const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space; - try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space); + if (maybe_label == null and flow_expr.rhs == null) { + return renderToken(tree, stream, flow_expr.ltoken, indent, start_col, space); // break + } + + try renderToken(tree, stream, flow_expr.ltoken, indent, start_col, Space.Space); // break if (maybe_label) |label| { const colon = tree.nextToken(flow_expr.ltoken); - try renderToken(tree, stream, colon, indent, Space.None); + try renderToken(tree, stream, colon, indent, start_col, Space.None); // : - const expr_space = if (flow_expr.rhs != null) Space.Space else space; - try renderExpression(allocator, stream, tree, indent, label, expr_space); + if (flow_expr.rhs == null) { + return renderExpression(allocator, stream, tree, indent, start_col, label, space); // label + } + try renderExpression(allocator, stream, tree, indent, start_col, label, Space.Space); // label } }, ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| { - const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space; - try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space); + assert(flow_expr.rhs == null); + + if (maybe_label == null and flow_expr.rhs == null) { + return renderToken(tree, stream, flow_expr.ltoken, indent, start_col, space); // continue + } + + try renderToken(tree, stream, flow_expr.ltoken, indent, start_col, Space.Space); // continue if (maybe_label) |label| { const colon = tree.nextToken(flow_expr.ltoken); - try renderToken(tree, stream, colon, indent, Space.None); + try renderToken(tree, stream, colon, indent, start_col, Space.None); // : - const expr_space = if (flow_expr.rhs != null) Space.Space else space; - try renderExpression(allocator, stream, tree, indent, label, space); + return renderExpression(allocator, stream, tree, indent, start_col, label, space); } }, ast.Node.ControlFlowExpression.Kind.Return => { - const kw_space = if (flow_expr.rhs != null) Space.Space else space; - try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space); + if (flow_expr.rhs == null) { + return renderToken(tree, stream, flow_expr.ltoken, indent, start_col, space); + } + try renderToken(tree, stream, flow_expr.ltoken, indent, start_col, Space.Space); }, } - if (flow_expr.rhs) |rhs| { - try renderExpression(allocator, stream, tree, indent, rhs, space); - } + return renderExpression(allocator, stream, tree, indent, start_col, ??flow_expr.rhs, space); }, ast.Node.Id.Payload => { const payload = @fieldParentPtr(ast.Node.Payload, "base", base); - try renderToken(tree, stream, payload.lpipe, indent, Space.None); - try renderExpression(allocator, stream, tree, indent, payload.error_symbol, Space.None); - try renderToken(tree, stream, payload.rpipe, indent, space); + try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, payload.error_symbol, Space.None); + return renderToken(tree, stream, payload.rpipe, indent, start_col, space); }, ast.Node.Id.PointerPayload => { const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base); - try renderToken(tree, stream, payload.lpipe, indent, Space.None); + try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None); if (payload.ptr_token) |ptr_token| { - try renderToken(tree, stream, ptr_token, indent, Space.None); + try renderToken(tree, stream, ptr_token, indent, start_col, Space.None); } - try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None); - try renderToken(tree, stream, payload.rpipe, indent, space); + try renderExpression(allocator, stream, tree, indent, start_col, payload.value_symbol, Space.None); + return renderToken(tree, stream, payload.rpipe, indent, start_col, space); }, ast.Node.Id.PointerIndexPayload => { const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base); - try renderToken(tree, stream, payload.lpipe, indent, Space.None); + try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None); if (payload.ptr_token) |ptr_token| { - try renderToken(tree, stream, ptr_token, indent, Space.None); + try renderToken(tree, stream, ptr_token, indent, start_col, Space.None); } - try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, payload.value_symbol, Space.None); if (payload.index_symbol) |index_symbol| { const comma = tree.nextToken(payload.value_symbol.lastToken()); - try renderToken(tree, stream, comma, indent, Space.Space); - try renderExpression(allocator, stream, tree, indent, index_symbol, Space.None); + try renderToken(tree, stream, comma, indent, start_col, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, index_symbol, Space.None); } - try renderToken(tree, stream, payload.rpipe, indent, space); + return renderToken(tree, stream, payload.rpipe, indent, start_col, space); }, ast.Node.Id.GroupedExpression => { const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base); - try renderToken(tree, stream, grouped_expr.lparen, indent, Space.None); - try renderExpression(allocator, stream, tree, indent, grouped_expr.expr, Space.None); - try renderToken(tree, stream, grouped_expr.rparen, indent, space); + try renderToken(tree, stream, grouped_expr.lparen, indent, start_col, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, grouped_expr.expr, Space.None); + return renderToken(tree, stream, grouped_expr.rparen, indent, start_col, space); }, ast.Node.Id.FieldInitializer => { const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base); - try renderToken(tree, stream, field_init.period_token, indent, Space.None); // . - try renderToken(tree, stream, field_init.name_token, indent, Space.Space); // name - try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, Space.Space); // = - try renderExpression(allocator, stream, tree, indent, field_init.expr, space); + try renderToken(tree, stream, field_init.period_token, indent, start_col, Space.None); // . + try renderToken(tree, stream, field_init.name_token, indent, start_col, Space.Space); // name + try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, start_col, Space.Space); // = + return renderExpression(allocator, stream, tree, indent, start_col, field_init.expr, space); }, ast.Node.Id.IntegerLiteral => { const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base); - try renderToken(tree, stream, integer_literal.token, indent, space); + return renderToken(tree, stream, integer_literal.token, indent, start_col, space); }, ast.Node.Id.FloatLiteral => { const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base); - try renderToken(tree, stream, float_literal.token, indent, space); + return renderToken(tree, stream, float_literal.token, indent, start_col, space); }, ast.Node.Id.StringLiteral => { const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base); - try renderToken(tree, stream, string_literal.token, indent, space); + return renderToken(tree, stream, string_literal.token, indent, start_col, space); }, ast.Node.Id.CharLiteral => { const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); - try renderToken(tree, stream, char_literal.token, indent, space); + return renderToken(tree, stream, char_literal.token, indent, start_col, space); }, ast.Node.Id.BoolLiteral => { const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); - try renderToken(tree, stream, bool_literal.token, indent, space); + return renderToken(tree, stream, bool_literal.token, indent, start_col, space); }, ast.Node.Id.NullLiteral => { const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base); - try renderToken(tree, stream, null_literal.token, indent, space); + return renderToken(tree, stream, null_literal.token, indent, start_col, space); }, ast.Node.Id.ThisLiteral => { const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base); - try renderToken(tree, stream, this_literal.token, indent, space); + return renderToken(tree, stream, this_literal.token, indent, start_col, space); }, ast.Node.Id.Unreachable => { const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base); - try renderToken(tree, stream, unreachable_node.token, indent, space); + return renderToken(tree, stream, unreachable_node.token, indent, start_col, space); }, ast.Node.Id.ErrorType => { const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base); - try renderToken(tree, stream, error_type.token, indent, space); + return renderToken(tree, stream, error_type.token, indent, start_col, space); }, ast.Node.Id.VarType => { const var_type = @fieldParentPtr(ast.Node.VarType, "base", base); - try renderToken(tree, stream, var_type.token, indent, space); + return renderToken(tree, stream, var_type.token, indent, start_col, space); }, ast.Node.Id.ContainerDecl => { const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base); if (container_decl.layout_token) |layout_token| { - try renderToken(tree, stream, layout_token, indent, Space.Space); + try renderToken(tree, stream, layout_token, indent, start_col, Space.Space); } switch (container_decl.init_arg_expr) { ast.Node.ContainerDecl.InitArg.None => { - try renderToken(tree, stream, container_decl.kind_token, indent, Space.Space); // union + try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.Space); // union }, ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| { - try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union + try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union const lparen = tree.nextToken(container_decl.kind_token); const enum_token = tree.nextToken(lparen); - try renderToken(tree, stream, lparen, indent, Space.None); // ( - try renderToken(tree, stream, enum_token, indent, Space.None); // enum + try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( + try renderToken(tree, stream, enum_token, indent, start_col, Space.None); // enum if (enum_tag_type) |expr| { - try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, expr, Space.None); + try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None); const rparen = tree.nextToken(expr.lastToken()); - try renderToken(tree, stream, rparen, indent, Space.None); // ) - try renderToken(tree, stream, tree.nextToken(rparen), indent, Space.Space); // ) + try renderToken(tree, stream, rparen, indent, start_col, Space.None); // ) + try renderToken(tree, stream, tree.nextToken(rparen), indent, start_col, Space.Space); // ) } else { - try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.Space); // ) + try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.Space); // ) } }, ast.Node.ContainerDecl.InitArg.Type => |type_expr| { - try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union + try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union const lparen = tree.nextToken(container_decl.kind_token); const rparen = tree.nextToken(type_expr.lastToken()); - try renderToken(tree, stream, lparen, indent, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, type_expr, Space.None); - try renderToken(tree, stream, rparen, indent, Space.Space); // ) + try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.None); + try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // ) }, } if (container_decl.fields_and_decls.len == 0) { - try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, Space.None); // { - try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // } + try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, start_col, Space.None); // { + return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // } } else { const new_indent = indent + indent_delta; - try renderToken(tree, stream, container_decl.lbrace_token, new_indent, Space.Newline); // { + try renderToken(tree, stream, container_decl.lbrace_token, new_indent, start_col, Space.Newline); // { var it = container_decl.fields_and_decls.iterator(0); while (it.next()) |decl| { try stream.writeByteNTimes(' ', new_indent); - try renderTopLevelDecl(allocator, stream, tree, new_indent, decl.*); + try renderTopLevelDecl(allocator, stream, tree, new_indent, start_col, decl.*); if (it.peek()) |next_decl| { - try renderExtraNewline(tree, stream, next_decl.*); + try renderExtraNewline(tree, stream, start_col, next_decl.*); } } try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // } + return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // } } }, @@ -865,10 +868,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const lbrace = tree.nextToken(err_set_decl.error_token); if (err_set_decl.decls.len == 0) { - try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); - try renderToken(tree, stream, lbrace, indent, Space.None); - try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); - return; + try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); + try renderToken(tree, stream, lbrace, indent, start_col, Space.None); + return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); } if (err_set_decl.decls.len == 1) blk: { @@ -882,15 +884,14 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind break :blk; } - try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error - try renderToken(tree, stream, lbrace, indent, Space.None); // { - try renderExpression(allocator, stream, tree, indent, node, Space.None); - try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // } - return; + try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error + try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // { + try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None); + return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // } } - try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error - try renderToken(tree, stream, lbrace, indent, Space.Newline); // { + try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error + try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // { const new_indent = indent + indent_delta; var it = err_set_decl.decls.iterator(0); @@ -898,24 +899,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try stream.writeByteNTimes(' ', new_indent); if (it.peek()) |next_node| { - try renderExpression(allocator, stream, tree, new_indent, node.*, Space.None); - try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, Space.Newline); // , + try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None); + try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, start_col, Space.Newline); // , - try renderExtraNewline(tree, stream, next_node.*); + try renderExtraNewline(tree, stream, start_col, next_node.*); } else { - try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Comma); + try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma); } } try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // } + return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // } }, ast.Node.Id.ErrorTag => { const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base); - try renderDocComments(tree, stream, tag, indent); - try renderToken(tree, stream, tag.name_token, indent, space); // name + try renderDocComments(tree, stream, tag, indent, start_col); + return renderToken(tree, stream, tag.name_token, indent, start_col, space); // name }, ast.Node.Id.MultilineStringLiteral => { @@ -933,32 +934,32 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind if (!skip_first_indent) { try stream.writeByteNTimes(' ', indent + indent_delta); } - try renderToken(tree, stream, t, indent, Space.None); + try renderToken(tree, stream, t, indent, start_col, Space.None); skip_first_indent = false; } try stream.writeByteNTimes(' ', indent); }, ast.Node.Id.UndefinedLiteral => { const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base); - try renderToken(tree, stream, undefined_literal.token, indent, space); + return renderToken(tree, stream, undefined_literal.token, indent, start_col, space); }, ast.Node.Id.BuiltinCall => { const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base); - try renderToken(tree, stream, builtin_call.builtin_token, indent, Space.None); // @name - try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, Space.None); // ( + try renderToken(tree, stream, builtin_call.builtin_token, indent, start_col, Space.None); // @name + try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, start_col, Space.None); // ( var it = builtin_call.params.iterator(0); while (it.next()) |param_node| { - try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, param_node.*, Space.None); if (it.peek() != null) { const comma_token = tree.nextToken(param_node.*.lastToken()); - try renderToken(tree, stream, comma_token, indent, Space.Space); // , + try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // , } } - try renderToken(tree, stream, builtin_call.rparen_token, indent, space); // ) + return renderToken(tree, stream, builtin_call.rparen_token, indent, start_col, space); // ) }, ast.Node.Id.FnProto => { @@ -968,31 +969,31 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const visib_token = tree.tokens.at(visib_token_index); assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export); - try renderToken(tree, stream, visib_token_index, indent, Space.Space); // pub + try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub } if (fn_proto.extern_export_inline_token) |extern_export_inline_token| { - try renderToken(tree, stream, extern_export_inline_token, indent, Space.Space); // extern/export + try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export } if (fn_proto.lib_name) |lib_name| { - try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); } if (fn_proto.cc_token) |cc_token| { - try renderToken(tree, stream, cc_token, indent, Space.Space); // stdcallcc + try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc } if (fn_proto.async_attr) |async_attr| { - try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, &async_attr.base, Space.Space); } const lparen = if (fn_proto.name_token) |name_token| blk: { - try renderToken(tree, stream, fn_proto.fn_token, indent, Space.Space); // fn - try renderToken(tree, stream, name_token, indent, Space.None); // name + try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn + try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name break :blk tree.nextToken(name_token); } else blk: { - try renderToken(tree, stream, fn_proto.fn_token, indent, Space.None); // fn + try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.None); // fn break :blk tree.nextToken(fn_proto.fn_token); }; @@ -1011,51 +1012,51 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind }; if (!src_params_trailing_comma and src_params_same_line) { - try renderToken(tree, stream, lparen, indent, Space.None); // ( + try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( // render all on one line, no trailing comma var it = fn_proto.params.iterator(0); while (it.next()) |param_decl_node| { - try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*, Space.None); + try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl_node.*, Space.None); if (it.peek() != null) { const comma = tree.nextToken(param_decl_node.*.lastToken()); - try renderToken(tree, stream, comma, indent, Space.Space); // , + try renderToken(tree, stream, comma, indent, start_col, Space.Space); // , } } } else { // one param per line const new_indent = indent + indent_delta; - try renderToken(tree, stream, lparen, new_indent, Space.Newline); // ( + try renderToken(tree, stream, lparen, new_indent, start_col, Space.Newline); // ( var it = fn_proto.params.iterator(0); while (it.next()) |param_decl_node| { try stream.writeByteNTimes(' ', new_indent); - try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*, Space.Comma); + try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl_node.*, Space.Comma); } try stream.writeByteNTimes(' ', indent); } - try renderToken(tree, stream, rparen, indent, Space.Space); // ) + try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // ) if (fn_proto.align_expr) |align_expr| { const align_rparen = tree.nextToken(align_expr.lastToken()); const align_lparen = tree.prevToken(align_expr.firstToken()); const align_kw = tree.prevToken(align_lparen); - try renderToken(tree, stream, align_kw, indent, Space.None); // align - try renderToken(tree, stream, align_lparen, indent, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, align_expr, Space.None); - try renderToken(tree, stream, align_rparen, indent, Space.Space); // ) + try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align + try renderToken(tree, stream, align_lparen, indent, start_col, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, align_expr, Space.None); + try renderToken(tree, stream, align_rparen, indent, start_col, Space.Space); // ) } switch (fn_proto.return_type) { ast.Node.FnProto.ReturnType.Explicit => |node| { - try renderExpression(allocator, stream, tree, indent, node, space); + return renderExpression(allocator, stream, tree, indent, start_col, node, space); }, ast.Node.FnProto.ReturnType.InferErrorSet => |node| { - try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, Space.None); // ! - try renderExpression(allocator, stream, tree, indent, node, space); + try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, start_col, Space.None); // ! + return renderExpression(allocator, stream, tree, indent, start_col, node, space); }, } }, @@ -1064,11 +1065,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base); if (promise_type.result) |result| { - try renderToken(tree, stream, promise_type.promise_token, indent, Space.None); // promise - try renderToken(tree, stream, result.arrow_token, indent, Space.None); // -> - try renderExpression(allocator, stream, tree, indent, result.return_type, space); + try renderToken(tree, stream, promise_type.promise_token, indent, start_col, Space.None); // promise + try renderToken(tree, stream, result.arrow_token, indent, start_col, Space.None); // -> + return renderExpression(allocator, stream, tree, indent, start_col, result.return_type, space); } else { - try renderToken(tree, stream, promise_type.promise_token, indent, space); // promise + return renderToken(tree, stream, promise_type.promise_token, indent, start_col, space); // promise } }, @@ -1077,39 +1078,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind ast.Node.Id.Switch => { const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base); - try renderToken(tree, stream, switch_node.switch_token, indent, Space.Space); // switch - try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, Space.None); // ( + try renderToken(tree, stream, switch_node.switch_token, indent, start_col, Space.Space); // switch + try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, start_col, Space.None); // ( const rparen = tree.nextToken(switch_node.expr.lastToken()); const lbrace = tree.nextToken(rparen); if (switch_node.cases.len == 0) { - try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None); - try renderToken(tree, stream, rparen, indent, Space.Space); // ) - try renderToken(tree, stream, lbrace, indent, Space.None); // { - try renderToken(tree, stream, switch_node.rbrace, indent, space); // } - return; + try renderExpression(allocator, stream, tree, indent, start_col, switch_node.expr, Space.None); + try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // ) + try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // { + return renderToken(tree, stream, switch_node.rbrace, indent, start_col, space); // } } - try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, switch_node.expr, Space.None); const new_indent = indent + indent_delta; - try renderToken(tree, stream, rparen, indent, Space.Space); // ) - try renderToken(tree, stream, lbrace, new_indent, Space.Newline); // { + try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // ) + try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline); // { var it = switch_node.cases.iterator(0); while (it.next()) |node| { try stream.writeByteNTimes(' ', new_indent); - try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Comma); + try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma); if (it.peek()) |next_node| { - try renderExtraNewline(tree, stream, next_node.*); + try renderExtraNewline(tree, stream, start_col, next_node.*); } } try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, switch_node.rbrace, indent, space); // } + return renderToken(tree, stream, switch_node.rbrace, indent, start_col, space); // } }, ast.Node.Id.SwitchCase => { @@ -1126,13 +1126,13 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind var it = switch_case.items.iterator(0); while (it.next()) |node| { if (it.peek()) |next_node| { - try renderExpression(allocator, stream, tree, indent, node.*, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None); const comma_token = tree.nextToken(node.*.lastToken()); - try renderToken(tree, stream, comma_token, indent, Space.Space); // , - try renderExtraNewline(tree, stream, next_node.*); + try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // , + try renderExtraNewline(tree, stream, start_col, next_node.*); } else { - try renderExpression(allocator, stream, tree, indent, node.*, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Space); } } } else { @@ -1140,85 +1140,97 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind while (true) { const node = ??it.next(); if (it.peek()) |next_node| { - try renderExpression(allocator, stream, tree, indent, node.*, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None); const comma_token = tree.nextToken(node.*.lastToken()); - try renderToken(tree, stream, comma_token, indent, Space.Newline); // , - try renderExtraNewline(tree, stream, next_node.*); + try renderToken(tree, stream, comma_token, indent, start_col, Space.Newline); // , + try renderExtraNewline(tree, stream, start_col, next_node.*); try stream.writeByteNTimes(' ', indent); } else { - try renderExpression(allocator, stream, tree, indent, node.*, Space.Comma); + try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Comma); try stream.writeByteNTimes(' ', indent); break; } } } - try renderToken(tree, stream, switch_case.arrow_token, indent, Space.Space); // => + try renderToken(tree, stream, switch_case.arrow_token, indent, start_col, Space.Space); // => if (switch_case.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); } - try renderExpression(allocator, stream, tree, indent, switch_case.expr, space); + return renderExpression(allocator, stream, tree, indent, start_col, switch_case.expr, space); }, ast.Node.Id.SwitchElse => { const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base); - try renderToken(tree, stream, switch_else.token, indent, space); + return renderToken(tree, stream, switch_else.token, indent, start_col, space); }, ast.Node.Id.Else => { const else_node = @fieldParentPtr(ast.Node.Else, "base", base); - const block_body = switch (else_node.body.id) { - ast.Node.Id.Block, - ast.Node.Id.If, - ast.Node.Id.For, - ast.Node.Id.While, - ast.Node.Id.Switch => true, - else => false, - }; + const body_is_block = nodeIsBlock(else_node.body); + const same_line = body_is_block or tree.tokensOnSameLine(else_node.else_token, else_node.body.lastToken()); - const after_else_space = if (block_body or else_node.payload != null) Space.Space else Space.Newline; - try renderToken(tree, stream, else_node.else_token, indent, after_else_space); + const after_else_space = if (same_line or else_node.payload != null) Space.Space else Space.Newline; + try renderToken(tree, stream, else_node.else_token, indent, start_col, after_else_space); if (else_node.payload) |payload| { - const payload_space = if (block_body) Space.Space else Space.Newline; - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + const payload_space = if (same_line) Space.Space else Space.Newline; + try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space); } - if (block_body) { - try renderExpression(allocator, stream, tree, indent, else_node.body, space); - } else { - try stream.writeByteNTimes(' ', indent + indent_delta); - try renderExpression(allocator, stream, tree, indent, else_node.body, space); + if (same_line) { + return renderExpression(allocator, stream, tree, indent, start_col, else_node.body, space); } + + try stream.writeByteNTimes(' ', indent + indent_delta); + start_col.* = indent + indent_delta; + return renderExpression(allocator, stream, tree, indent, start_col, else_node.body, space); }, ast.Node.Id.While => { const while_node = @fieldParentPtr(ast.Node.While, "base", base); if (while_node.label) |label| { - try renderToken(tree, stream, label, indent, Space.None); // label - try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // : + try renderToken(tree, stream, label, indent, start_col, Space.None); // label + try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // : } if (while_node.inline_token) |inline_token| { - try renderToken(tree, stream, inline_token, indent, Space.Space); // inline + try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline } - try renderToken(tree, stream, while_node.while_token, indent, Space.Space); // while - try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, while_node.condition, Space.None); + try renderToken(tree, stream, while_node.while_token, indent, start_col, Space.Space); // while + try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, start_col, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, while_node.condition, Space.None); + + const cond_rparen = tree.nextToken(while_node.condition.lastToken()); + + const body_is_block = nodeIsBlock(while_node.body); + + var block_start_space: Space = undefined; + var after_body_space: Space = undefined; + + if (body_is_block) { + block_start_space = Space.BlockStart; + after_body_space = if (while_node.@"else" == null) space else Space.SpaceOrOutdent; + } else if (tree.tokensOnSameLine(cond_rparen, while_node.body.lastToken())) { + block_start_space = Space.Space; + after_body_space = if (while_node.@"else" == null) space else Space.Space; + } else { + block_start_space = Space.Newline; + after_body_space = if (while_node.@"else" == null) space else Space.Newline; + } { - const rparen = tree.nextToken(while_node.condition.lastToken()); - const rparen_space = if (while_node.payload != null or while_node.continue_expr != null or - while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; - try renderToken(tree, stream, rparen, indent, rparen_space); // ) + const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space; + try renderToken(tree, stream, cond_rparen, indent, start_col, rparen_space); // ) } if (while_node.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space; + try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space); } if (while_node.continue_expr) |continue_expr| { @@ -1226,37 +1238,29 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const lparen = tree.prevToken(continue_expr.firstToken()); const colon = tree.prevToken(lparen); - try renderToken(tree, stream, colon, indent, Space.Space); // : - try renderToken(tree, stream, lparen, indent, Space.None); // ( + try renderToken(tree, stream, colon, indent, start_col, Space.Space); // : + try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, continue_expr, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, continue_expr, Space.None); - const rparen_space = if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; - try renderToken(tree, stream, rparen, indent, rparen_space); // ) + try renderToken(tree, stream, rparen, indent, start_col, block_start_space); // ) } - const body_space = blk: { - if (while_node.@"else" != null) { - break :blk if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; - } else { - break :blk space; - } - }; - - if (while_node.body.id == ast.Node.Id.Block) { - try renderExpression(allocator, stream, tree, indent, while_node.body, body_space); - } else { - try stream.writeByteNTimes(' ', indent + indent_delta); - try renderExpression(allocator, stream, tree, indent, while_node.body, body_space); + var new_indent = indent; + if (block_start_space == Space.Newline) { + new_indent += indent_delta; + try stream.writeByteNTimes(' ', new_indent); + start_col.* = new_indent; } + try renderExpression(allocator, stream, tree, indent, start_col, while_node.body, after_body_space); + if (while_node.@"else") |@"else"| { - if (while_node.body.id == ast.Node.Id.Block) { - } else { + if (after_body_space == Space.Newline) { try stream.writeByteNTimes(' ', indent); + start_col.* = indent; } - - try renderExpression(allocator, stream, tree, indent, &@"else".base, space); + return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space); } }, @@ -1264,26 +1268,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const for_node = @fieldParentPtr(ast.Node.For, "base", base); if (for_node.label) |label| { - try renderToken(tree, stream, label, indent, Space.None); // label - try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // : + try renderToken(tree, stream, label, indent, start_col, Space.None); // label + try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // : } if (for_node.inline_token) |inline_token| { - try renderToken(tree, stream, inline_token, indent, Space.Space); // inline + try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline } - try renderToken(tree, stream, for_node.for_token, indent, Space.Space); // for - try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, for_node.array_expr, Space.None); + try renderToken(tree, stream, for_node.for_token, indent, start_col, Space.Space); // for + try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, start_col, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, for_node.array_expr, Space.None); const rparen = tree.nextToken(for_node.array_expr.lastToken()); const rparen_space = if (for_node.payload != null or for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; - try renderToken(tree, stream, rparen, indent, rparen_space); // ) + try renderToken(tree, stream, rparen, indent, start_col, rparen_space); // ) if (for_node.payload) |payload| { const payload_space = if (for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline; - try renderExpression(allocator, stream, tree, indent, payload, payload_space); + try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space); } const body_space = blk: { @@ -1298,10 +1302,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } }; if (for_node.body.id == ast.Node.Id.Block) { - try renderExpression(allocator, stream, tree, indent, for_node.body, body_space); + try renderExpression(allocator, stream, tree, indent, start_col, for_node.body, body_space); } else { try stream.writeByteNTimes(' ', indent + indent_delta); - try renderExpression(allocator, stream, tree, indent, for_node.body, body_space); + try renderExpression(allocator, stream, tree, indent, start_col, for_node.body, body_space); } if (for_node.@"else") |@"else"| { @@ -1309,7 +1313,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind try stream.writeByteNTimes(' ', indent); } - try renderExpression(allocator, stream, tree, indent, &@"else".base, space); + return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space); } }, @@ -1319,128 +1323,109 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const lparen = tree.prevToken(if_node.condition.firstToken()); const rparen = tree.nextToken(if_node.condition.lastToken()); - try renderToken(tree, stream, if_node.if_token, indent, Space.Space); // if - try renderToken(tree, stream, lparen, indent, Space.None); // ( + try renderToken(tree, stream, if_node.if_token, indent, start_col, Space.Space); // if + try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, if_node.condition, Space.None); // condition + try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition - const body_is_block = switch (if_node.body.id) { - ast.Node.Id.Block, - ast.Node.Id.If, - ast.Node.Id.For, - ast.Node.Id.While, - ast.Node.Id.Switch, - => true, - else => false, - }; + const body_is_block = nodeIsBlock(if_node.body); if (body_is_block) { - try renderToken(tree, stream, rparen, indent, Space.Space); // ) + const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space; + try renderToken(tree, stream, rparen, indent, start_col, after_rparen_space); // ) if (if_node.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); // |x| + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.BlockStart); // |x| } if (if_node.@"else") |@"else"| { - try renderExpression(allocator, stream, tree, indent, if_node.body, Space.SpaceOrOutdent); - return renderExpression(allocator, stream, tree, indent, &@"else".base, space); + try renderExpression(allocator, stream, tree, indent, start_col, if_node.body, Space.SpaceOrOutdent); + return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space); } else { - return renderExpression(allocator, stream, tree, indent, if_node.body, space); + return renderExpression(allocator, stream, tree, indent, start_col, if_node.body, space); } } - const src_has_newline = blk: { - const loc = tree.tokenLocation(tree.tokens.at(rparen).end, if_node.body.lastToken()); - break :blk loc.line != 0; - }; + const src_has_newline = !tree.tokensOnSameLine(rparen, if_node.body.lastToken()); if (src_has_newline) { const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space; - try renderToken(tree, stream, rparen, indent, after_rparen_space); // ) + try renderToken(tree, stream, rparen, indent, start_col, after_rparen_space); // ) if (if_node.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Newline); } const new_indent = indent + indent_delta; try stream.writeByteNTimes(' ', new_indent); if (if_node.@"else") |@"else"| { - const else_is_block = switch (@"else".body.id) { - ast.Node.Id.Block, - ast.Node.Id.If, - ast.Node.Id.For, - ast.Node.Id.While, - ast.Node.Id.Switch, - => true, - else => false, - }; - try renderExpression(allocator, stream, tree, new_indent, if_node.body, Space.Newline); + const else_is_block = nodeIsBlock(@"else".body); + try renderExpression(allocator, stream, tree, new_indent, start_col, if_node.body, Space.Newline); try stream.writeByteNTimes(' ', indent); if (else_is_block) { - try renderToken(tree, stream, @"else".else_token, indent, Space.Space); // else + try renderToken(tree, stream, @"else".else_token, indent, start_col, Space.Space); // else if (@"else".payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); } - return renderExpression(allocator, stream, tree, indent, @"else".body, space); + return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space); } else { const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space; - try renderToken(tree, stream, @"else".else_token, indent, after_else_space); // else + try renderToken(tree, stream, @"else".else_token, indent, start_col, after_else_space); // else if (@"else".payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Newline); } try stream.writeByteNTimes(' ', new_indent); - return renderExpression(allocator, stream, tree, new_indent, @"else".body, space); + return renderExpression(allocator, stream, tree, new_indent, start_col, @"else".body, space); } } else { - return renderExpression(allocator, stream, tree, new_indent, if_node.body, space); + return renderExpression(allocator, stream, tree, new_indent, start_col, if_node.body, space); } } - try renderToken(tree, stream, rparen, indent, Space.Space); // ) + try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // ) if (if_node.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); } if (if_node.@"else") |@"else"| { - try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space); - try renderToken(tree, stream, @"else".else_token, indent, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, if_node.body, Space.Space); + try renderToken(tree, stream, @"else".else_token, indent, start_col, Space.Space); if (@"else".payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); } - return renderExpression(allocator, stream, tree, indent, @"else".body, space); + return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space); } else { - return renderExpression(allocator, stream, tree, indent, if_node.body, space); + return renderExpression(allocator, stream, tree, indent, start_col, if_node.body, space); } }, ast.Node.Id.Asm => { const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base); - try renderToken(tree, stream, asm_node.asm_token, indent, Space.Space); // asm + try renderToken(tree, stream, asm_node.asm_token, indent, start_col, Space.Space); // asm if (asm_node.volatile_token) |volatile_token| { - try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile - try renderToken(tree, stream, tree.nextToken(volatile_token), indent, Space.None); // ( + try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile + try renderToken(tree, stream, tree.nextToken(volatile_token), indent, start_col, Space.None); // ( } else { - try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // ( + try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, start_col, Space.None); // ( } if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) { - try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.None); - try renderToken(tree, stream, asm_node.rparen, indent, space); - return; + try renderExpression(allocator, stream, tree, indent, start_col, asm_node.template, Space.None); + return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); } - try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, asm_node.template, Space.Newline); const indent_once = indent + indent_delta; try stream.writeByteNTimes(' ', indent_once); @@ -1449,12 +1434,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const indent_extra = indent_once + 2; const colon2 = if (asm_node.outputs.len == 0) blk: { - try renderToken(tree, stream, colon1, indent, Space.Newline); // : + try renderToken(tree, stream, colon1, indent, start_col, Space.Newline); // : try stream.writeByteNTimes(' ', indent_once); break :blk tree.nextToken(colon1); } else blk: { - try renderToken(tree, stream, colon1, indent, Space.Space); // : + try renderToken(tree, stream, colon1, indent, start_col, Space.Space); // : var it = asm_node.outputs.iterator(0); while (true) { @@ -1462,21 +1447,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const node = &(asm_output.*).base; if (it.peek()) |next_asm_output| { - try renderExpression(allocator, stream, tree, indent_extra, node, Space.None); + try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.None); const next_node = &(next_asm_output.*).base; const comma = tree.prevToken(next_asm_output.*.firstToken()); - try renderToken(tree, stream, comma, indent_extra, Space.Newline); // , - try renderExtraNewline(tree, stream, next_node); + try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // , + try renderExtraNewline(tree, stream, start_col, next_node); try stream.writeByteNTimes(' ', indent_extra); } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) { - try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline); + try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline); try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, asm_node.rparen, indent, space); - return; + return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); } else { - try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline); + try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline); try stream.writeByteNTimes(' ', indent_once); const comma_or_colon = tree.nextToken(node.lastToken()); break :blk switch (tree.tokens.at(comma_or_colon).id) { @@ -1488,12 +1472,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind }; const colon3 = if (asm_node.inputs.len == 0) blk: { - try renderToken(tree, stream, colon2, indent, Space.Newline); // : + try renderToken(tree, stream, colon2, indent, start_col, Space.Newline); // : try stream.writeByteNTimes(' ', indent_once); break :blk tree.nextToken(colon2); } else blk: { - try renderToken(tree, stream, colon2, indent, Space.Space); // : + try renderToken(tree, stream, colon2, indent, start_col, Space.Space); // : var it = asm_node.inputs.iterator(0); while (true) { @@ -1501,21 +1485,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const node = &(asm_input.*).base; if (it.peek()) |next_asm_input| { - try renderExpression(allocator, stream, tree, indent_extra, node, Space.None); + try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.None); const next_node = &(next_asm_input.*).base; const comma = tree.prevToken(next_asm_input.*.firstToken()); - try renderToken(tree, stream, comma, indent_extra, Space.Newline); // , - try renderExtraNewline(tree, stream, next_node); + try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // , + try renderExtraNewline(tree, stream, start_col, next_node); try stream.writeByteNTimes(' ', indent_extra); } else if (asm_node.clobbers.len == 0) { - try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline); + try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline); try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, asm_node.rparen, indent, space); // ) - return; + return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); // ) } else { - try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline); + try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline); try stream.writeByteNTimes(' ', indent_once); const comma_or_colon = tree.nextToken(node.lastToken()); break :blk switch (tree.tokens.at(comma_or_colon).id) { @@ -1526,21 +1509,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } }; - try renderToken(tree, stream, colon3, indent, Space.Space); // : + try renderToken(tree, stream, colon3, indent, start_col, Space.Space); // : var it = asm_node.clobbers.iterator(0); while (true) { const clobber_token = ??it.next(); if (it.peek() == null) { - try renderToken(tree, stream, clobber_token.*, indent_once, Space.Newline); + try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.Newline); try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, asm_node.rparen, indent, space); - return; + return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); } else { - try renderToken(tree, stream, clobber_token.*, indent_once, Space.None); + try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.None); const comma = tree.nextToken(clobber_token.*); - try renderToken(tree, stream, comma, indent_once, Space.Space); // , + try renderToken(tree, stream, comma, indent_once, start_col, Space.Space); // , } } }, @@ -1549,34 +1531,34 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base); try stream.write("["); - try renderExpression(allocator, stream, tree, indent, asm_input.symbolic_name, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, asm_input.symbolic_name, Space.None); try stream.write("] "); - try renderExpression(allocator, stream, tree, indent, asm_input.constraint, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, asm_input.constraint, Space.None); try stream.write(" ("); - try renderExpression(allocator, stream, tree, indent, asm_input.expr, Space.None); - try renderToken(tree, stream, asm_input.lastToken(), indent, space); // ) + try renderExpression(allocator, stream, tree, indent, start_col, asm_input.expr, Space.None); + return renderToken(tree, stream, asm_input.lastToken(), indent, start_col, space); // ) }, ast.Node.Id.AsmOutput => { const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base); try stream.write("["); - try renderExpression(allocator, stream, tree, indent, asm_output.symbolic_name, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, asm_output.symbolic_name, Space.None); try stream.write("] "); - try renderExpression(allocator, stream, tree, indent, asm_output.constraint, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, asm_output.constraint, Space.None); try stream.write(" ("); switch (asm_output.kind) { ast.Node.AsmOutput.Kind.Variable => |variable_name| { - try renderExpression(allocator, stream, tree, indent, &variable_name.base, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, &variable_name.base, Space.None); }, ast.Node.AsmOutput.Kind.Return => |return_type| { try stream.write("-> "); - try renderExpression(allocator, stream, tree, indent, return_type, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, return_type, Space.None); }, } - try renderToken(tree, stream, asm_output.lastToken(), indent, space); // ) + return renderToken(tree, stream, asm_output.lastToken(), indent, start_col, space); // ) }, ast.Node.Id.StructField, @@ -1590,92 +1572,92 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind } } -fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, - var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void +fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, + var_decl: &ast.Node.VarDecl,) (@typeOf(stream).Child.Error || Error)!void { if (var_decl.visib_token) |visib_token| { - try renderToken(tree, stream, visib_token, indent, Space.Space); // pub + try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub } if (var_decl.extern_export_token) |extern_export_token| { - try renderToken(tree, stream, extern_export_token, indent, Space.Space); // extern + try renderToken(tree, stream, extern_export_token, indent, start_col, Space.Space); // extern if (var_decl.lib_name) |lib_name| { - try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space); // "lib" + try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); // "lib" } } if (var_decl.comptime_token) |comptime_token| { - try renderToken(tree, stream, comptime_token, indent, Space.Space); // comptime + try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime } - try renderToken(tree, stream, var_decl.mut_token, indent, Space.Space); // var + try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or var_decl.init_node != null)) Space.Space else Space.None; - try renderToken(tree, stream, var_decl.name_token, indent, name_space); + try renderToken(tree, stream, var_decl.name_token, indent, start_col, name_space); if (var_decl.type_node) |type_node| { - try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, Space.Space); + try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, start_col, Space.Space); const s = if (var_decl.align_node != null or var_decl.init_node != null) Space.Space else Space.None; - try renderExpression(allocator, stream, tree, indent, type_node, s); + try renderExpression(allocator, stream, tree, indent, start_col, type_node, s); } if (var_decl.align_node) |align_node| { const lparen = tree.prevToken(align_node.firstToken()); const align_kw = tree.prevToken(lparen); const rparen = tree.nextToken(align_node.lastToken()); - try renderToken(tree, stream, align_kw, indent, Space.None); // align - try renderToken(tree, stream, lparen, indent, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, align_node, Space.None); + try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align + try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, align_node, Space.None); const s = if (var_decl.init_node != null) Space.Space else Space.None; - try renderToken(tree, stream, rparen, indent, s); // ) + try renderToken(tree, stream, rparen, indent, start_col, s); // ) } if (var_decl.init_node) |init_node| { const s = if (init_node.id == ast.Node.Id.MultilineStringLiteral) Space.None else Space.Space; - try renderToken(tree, stream, var_decl.eq_token, indent, s); // = - try renderExpression(allocator, stream, tree, indent, init_node, Space.None); + try renderToken(tree, stream, var_decl.eq_token, indent, start_col, s); // = + try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None); } - try renderToken(tree, stream, var_decl.semicolon_token, indent, Space.Newline); + try renderToken(tree, stream, var_decl.semicolon_token, indent, start_col, Space.Newline); } -fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, space: Space) (@typeOf(stream).Child.Error || Error)!void { +fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, base: &ast.Node, space: Space,) (@typeOf(stream).Child.Error || Error)!void { const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base); if (param_decl.comptime_token) |comptime_token| { - try renderToken(tree, stream, comptime_token, indent, Space.Space); + try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); } if (param_decl.noalias_token) |noalias_token| { - try renderToken(tree, stream, noalias_token, indent, Space.Space); + try renderToken(tree, stream, noalias_token, indent, start_col, Space.Space); } if (param_decl.name_token) |name_token| { - try renderToken(tree, stream, name_token, indent, Space.None); - try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.Space); // : + try renderToken(tree, stream, name_token, indent, start_col, Space.None); + try renderToken(tree, stream, tree.nextToken(name_token), indent, start_col, Space.Space); // : } if (param_decl.var_args_token) |var_args_token| { - try renderToken(tree, stream, var_args_token, indent, space); + try renderToken(tree, stream, var_args_token, indent, start_col, space); } else { - try renderExpression(allocator, stream, tree, indent, param_decl.type_node, space); + try renderExpression(allocator, stream, tree, indent, start_col, param_decl.type_node, space); } } -fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { +fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, base: &ast.Node,) (@typeOf(stream).Child.Error || Error)!void { switch (base.id) { ast.Node.Id.VarDecl => { const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base); - try renderVarDecl(allocator, stream, tree, indent, var_decl); + try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl); }, else => { if (base.requireSemiColon()) { - try renderExpression(allocator, stream, tree, indent, base, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, base, Space.None); const semicolon_index = tree.nextToken(base.lastToken()); assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon); - try renderToken(tree, stream, semicolon_index, indent, Space.Newline); + try renderToken(tree, stream, semicolon_index, indent, start_col, Space.Newline); } else { - try renderExpression(allocator, stream, tree, indent, base, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, base, Space.Newline); } }, } @@ -1689,32 +1671,44 @@ const Space = enum { SpaceOrOutdent, NoNewline, NoComment, + BlockStart, }; -fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void { +fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, start_col: &usize, space: Space) (@typeOf(stream).Child.Error || Error)!void { + if (space == Space.BlockStart) { + if (start_col.* < indent + indent_delta) + return renderToken(tree, stream, token_index, indent, start_col, Space.Space); + try renderToken(tree, stream, token_index, indent, start_col, Space.Newline); + try stream.writeByteNTimes(' ', indent); + start_col.* = indent; + return; + } + var token = tree.tokens.at(token_index); try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " ")); + if (space == Space.NoComment) + return; + var next_token = tree.tokens.at(token_index + 1); - switch (space) { - Space.NoComment => return, - Space.Comma => switch (next_token.id) { - Token.Id.Comma => return renderToken(tree, stream, token_index + 1, indent, Space.Newline), - Token.Id.LineComment => { - try stream.write(", "); - return renderToken(tree, stream, token_index + 1, indent, Space.Newline); - }, - else => { - if (tree.tokens.at(token_index + 2).id == Token.Id.MultilineStringLiteralLine) { - return stream.write(","); - } else { - return stream.write(",\n"); - } - }, + if (space == Space.Comma) switch (next_token.id) { + Token.Id.Comma => return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline), + Token.Id.LineComment => { + try stream.write(", "); + return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline); }, - else => {}, - } + else => { + if (tree.tokens.at(token_index + 2).id == Token.Id.MultilineStringLiteralLine) { + try stream.write(","); + return; + } else { + try stream.write(",\n"); + start_col.* = 0; + return; + } + }, + }; // Skip over same line doc comments var offset: usize = 1; @@ -1733,18 +1727,27 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent if (next_token.id == Token.Id.MultilineStringLiteralLine) { return; } else { - return stream.write("\n"); + try stream.write("\n"); + start_col.* = 0; + return; } }, - Space.Space, Space.SpaceOrOutdent => return stream.writeByte(' '), - Space.NoComment, Space.Comma => unreachable, + Space.Space, Space.SpaceOrOutdent => { + try stream.writeByte(' '); + return; + }, + Space.NoComment, Space.Comma, Space.BlockStart => unreachable, } } const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2; if (comment_is_empty) { switch (space) { - Space.Newline => return stream.writeByte('\n'), + Space.Newline => { + try stream.writeByte('\n'); + start_col.* = 0; + return; + }, else => {}, } } @@ -1765,20 +1768,24 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent else => indent + indent_delta, }; try stream.writeByteNTimes(' ', next_line_indent); + start_col.* = next_line_indent; }, Space.SpaceOrOutdent => { try stream.writeByte('\n'); try stream.writeByteNTimes(' ', indent); + start_col.* = indent; }, Space.Newline => { if (next_token.id == Token.Id.MultilineStringLiteralLine) { return; } else { - return stream.write("\n"); + try stream.write("\n"); + start_col.* = 0; + return; } }, Space.NoNewline => {}, - Space.NoComment, Space.Comma => unreachable, + Space.NoComment, Space.Comma, Space.BlockStart => unreachable, } return; } @@ -1801,7 +1808,9 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent if (next_token.id == Token.Id.MultilineStringLiteralLine) { return; } else { - return stream.write("\n"); + try stream.write("\n"); + start_col.* = 0; + return; } }, Space.None, Space.Space => { @@ -1813,13 +1822,15 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent else => indent, }; try stream.writeByteNTimes(' ', next_line_indent); + start_col.* = next_line_indent; }, Space.SpaceOrOutdent => { try stream.writeByte('\n'); try stream.writeByteNTimes(' ', indent); + start_col.* = indent; }, Space.NoNewline => {}, - Space.NoComment, Space.Comma => unreachable, + Space.NoComment, Space.Comma, Space.BlockStart => unreachable, } return; } @@ -1827,18 +1838,30 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent } } -fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@typeOf(stream).Child.Error || Error)!void { +fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize, start_col: &usize,) (@typeOf(stream).Child.Error || Error)!void { const comment = node.doc_comments ?? return; var it = comment.lines.iterator(0); const first_token = node.firstToken(); while (it.next()) |line_token_index| { if (line_token_index.* < first_token) { - try renderToken(tree, stream, line_token_index.*, indent, Space.Newline); + try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.Newline); try stream.writeByteNTimes(' ', indent); } else { - try renderToken(tree, stream, line_token_index.*, indent, Space.NoComment); + try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.NoComment); try stream.write("\n"); try stream.writeByteNTimes(' ', indent); } } } + +fn nodeIsBlock(base: &const ast.Node) bool { + return switch (base.id) { + ast.Node.Id.Block, + ast.Node.Id.If, + ast.Node.Id.For, + ast.Node.Id.While, + ast.Node.Id.Switch, + => true, + else => false, + }; +} -- cgit v1.2.3