diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2018-05-29 03:22:52 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2018-05-29 03:22:52 -0400 |
| commit | cb042c8343eb94a8d149fe1f5d69aa2746aa85d0 (patch) | |
| tree | 36b9711c480b61c372c86bc47dd20a635d624d3a | |
| parent | 7fa97b752e167de6df9a8a76999456d2c199b345 (diff) | |
| parent | eda6898c5b253367174172db909ee23013f32733 (diff) | |
| download | zig-cb042c8343eb94a8d149fe1f5d69aa2746aa85d0.tar.gz zig-cb042c8343eb94a8d149fe1f5d69aa2746aa85d0.zip | |
Merge remote-tracking branch 'origin/master' into llvm7
34 files changed, 2265 insertions, 1428 deletions
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("<pre><code class=\"shell\">$ 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("<pre><code class=\"shell\">$ 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{}{}</code></pre>\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("<pre><code class=\"shell\">$ 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("<pre><code class=\"shell\">$ 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("</code></pre>\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("</code></pre>\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), }; - 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/ast.zig b/std/zig/ast.zig index 6c848b4a54..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; @@ -2071,7 +2082,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; @@ -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/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 9d5e64a66f..8ed748ed30 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1,10 +1,427 @@ +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 + \\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 { + \\ // 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 { + \\ 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 { + \\ 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 {} + , + \\fn foo( + \\ a: i32, + \\ b: i32, + \\) void {} + \\ + ); +} + +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 { + \\ switch (a) { + \\ // hi + \\ 0 => {}, + \\ } + \\} + \\ + ); +} + +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{ + \\ 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, 8, // + \\}; + , + \\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, + \\ 8, + \\}; + \\ + ); +} + +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 { + \\ var module = try Module.create( + \\ allocator, + \\ zig_lib_dir, + \\ full_cache_dir, + \\ ); + \\} + \\ + ); +} + +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 { + \\ k: usize, s: u32, t: u32 + \\}; + , + \\const RoundParam = struct { + \\ k: usize, + \\ s: u32, + \\ t: u32, + \\}; + \\ + ); +} + +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{ + \\ .item = bar{ .a = b }, + \\}; + \\ + ); +} + test "zig fmt: switch cases trailing comma" { try testTransform( \\fn switch_cases(x: i32) void { \\ switch (x) { \\ 1,2,3 => {}, \\ 4,5, => {}, - \\ 6...8, => {}, + \\ 6... 8, => {}, \\ else => {}, \\ } \\} @@ -13,8 +430,9 @@ test "zig fmt: switch cases trailing comma" { \\ switch (x) { \\ 1, 2, 3 => {}, \\ 4, - \\ 5, => {}, - \\ 6 ... 8 => {}, + \\ 5, + \\ => {}, + \\ 6...8 => {}, \\ else => {}, \\ } \\} @@ -36,16 +454,20 @@ test "zig fmt: add trailing comma to array literal" { \\comptime { \\ return []u16{'m', 's', 'y', 's', '-' // hi \\ }; + \\ return []u16{'m', 's', 'y', 's', + \\ '-'}; + \\ return []u16{'m', 's', 'y', 's', '-'}; \\} , \\comptime { \\ return []u16{ - \\ 'm', - \\ 's', - \\ 'y', - \\ 's', - \\ '-', // hi + \\ 'm', 's', 'y', 's', '-', // hi \\ }; + \\ return []u16{ + \\ 'm', 's', 'y', 's', + \\ '-', + \\ }; + \\ return []u16{ 'm', 's', 'y', 's', '-' }; \\} \\ ); @@ -252,20 +674,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 "" { @@ -1026,7 +1434,7 @@ test "zig fmt: switch" { \\ 0 => {}, \\ 1 => unreachable, \\ 2, 3 => {}, - \\ 4 ... 7 => {}, + \\ 4...7 => {}, \\ 1 + 4 * 3 + 22 => {}, \\ else => { \\ const a = 1; @@ -1286,7 +1694,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 4691d836c3..16aed808fc 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) { @@ -28,41 +28,43 @@ 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 { - var first_token = node.firstToken(); - while (tree.tokens.at(first_token - 1).id == Token.Id.DocComment) { - first_token -= 1; +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) { + 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'); + 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); } }, @@ -70,148 +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.None); // type - try renderToken(tree, stream, tree.nextToken(field.lastToken()), indent, Space.Newline); // , + 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); - - 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 + try renderDocComments(tree, stream, tag, indent, start_col); - if (tag.type_expr) |type_expr| { - try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // : + if (tag.type_expr == null and tag.value_expr == null) { + return renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name, + } - 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.type_expr == null) { + try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name + } else { + try renderToken(tree, stream, tag.name_token, indent, start_col, Space.None); // name } - 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.type_expr) |type_expr| { + try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // : + + if (tag.value_expr == null) { + try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Comma); // type, + return; + } else { + try renderExpression(allocator, stream, tree, indent, start_col, 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, 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); - - 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 + try renderDocComments(tree, stream, tag, indent, start_col); if (tag.value) |value| { - try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // = - try renderExpression(allocator, stream, tree, indent, value, Space.None); - } + try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name - try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); // , + 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, 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); } }, @@ -219,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); } }, @@ -245,20 +253,31 @@ 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); - try renderToken(tree, stream, infix_op_node.op_token, indent, 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, + 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, 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 => { @@ -266,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, @@ -349,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 => { @@ -369,80 +388,152 @@ 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()); - try renderToken(tree, stream, lparen, indent, Space.None); + + if (call_info.params.len == 0) { + 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: { + 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, start_col, Space.Newline); + + var it = call_info.params.iterator(0); + while (true) { + const param_node = ??it.next(); + + 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, param_node_new_indent, start_col, param_node.*, Space.None); + const comma = tree.nextToken(param_node.*.lastToken()); + 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, start_col, param_node.*, Space.Comma); + try stream.writeByteNTimes(' ', indent); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); + } + } + } + + 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) { - const field_init = field_inits.at(0).*; + if (field_inits.len == 1) blk: { + const field_init = ??field_inits.at(0).*.cast(ast.Node.FieldInitializer); - 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 renderToken(tree, stream, suffix_op.rtoken, indent, space); - return; + 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, 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); } - try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None); - try renderToken(tree, stream, lbrace, indent, Space.Newline); + 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, 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, start_col, field_init.*, Space.None); + + const comma = tree.nextToken(field_init.*.lastToken()); + try renderToken(tree, stream, comma, indent, start_col, Space.Space); + } else { + try renderExpression(allocator, stream, tree, indent, start_col, field_init.*, Space.Space); + } + } + + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); + } + + 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; @@ -451,63 +542,116 @@ 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 renderTrailingComma(allocator, stream, tree, new_indent, field_init.*, Space.Newline); + 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); - - const new_indent = indent + indent_delta; - try renderToken(tree, stream, lbrace, new_indent, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + + // scan to find row size + const maybe_row_size: ?usize = blk: { + var count: usize = 1; + var it = exprs.iterator(0); + 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; + } + } + }; - var it = exprs.iterator(0); - while (it.next()) |expr| { + if (maybe_row_size) |row_size| { + const new_indent = indent + indent_delta; + try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline); try stream.writeByteNTimes(' ', new_indent); - if (it.peek()) |next_expr| { - try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None); + 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, start_col, expr.*, Space.None); - const comma = tree.nextToken(expr.*.lastToken()); - try renderToken(tree, stream, comma, new_indent, Space.Newline); // , + const comma = tree.nextToken(expr.*.lastToken()); - try renderExtraNewline(tree, stream, next_expr.*); - } else { - try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline); + if (i != row_size) { + try renderToken(tree, stream, comma, new_indent, start_col, Space.Space); // , + i += 1; + continue; + } + i = 1; + + try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // , + + try renderExtraNewline(tree, stream, start_col, next_expr.*); + try stream.writeByteNTimes(' ', new_indent); + } else { + try renderExpression(allocator, stream, tree, new_indent, start_col, expr.*, Space.Comma); // , + } + } + try stream.writeByteNTimes(' ', indent); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); + } else { + 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, start_col, expr.*, Space.None); + const comma = tree.nextToken(expr.*.lastToken()); + try renderToken(tree, stream, comma, indent, start_col, Space.Space); // , + } else { + try renderExpression(allocator, stream, tree, indent, start_col, expr.*, Space.Space); + } } - } - try stream.writeByteNTimes(' ', indent); - try renderToken(tree, stream, suffix_op.rtoken, indent, space); + return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); + } }, } }, @@ -517,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); // } } }, @@ -715,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: { @@ -732,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); @@ -748,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 renderTrailingComma(allocator, stream, tree, new_indent, node.*, Space.Newline); + 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 => { @@ -783,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 => { @@ -818,68 +969,94 @@ 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); } - 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); // ( + const lparen = if (fn_proto.name_token) |name_token| blk: { + 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, 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); // , - } - } + try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.None); // fn + 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()), }); - try renderToken(tree, stream, rparen, indent, Space.Space); // ) + + 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, 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, 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, start_col, Space.Space); // , + } + } + } else { + // one param per line + const new_indent = indent + indent_delta; + 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, start_col, param_decl_node.*, Space.Comma); + } + try stream.writeByteNTimes(' ', indent); + } + + 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); }, } }, @@ -888,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 } }, @@ -901,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 renderToken(tree, stream, rparen, indent, Space.Space); // ) - try renderToken(tree, stream, lbrace, indent, Space.Newline); // { + 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, 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.Newline); + 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 => { @@ -950,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 { @@ -964,84 +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 renderTrailingComma(allocator, stream, tree, indent, node.*, Space.Space); + 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 renderTrailingComma(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| { @@ -1049,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); } }, @@ -1087,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: { @@ -1121,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"| { @@ -1132,167 +1313,252 @@ 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); } }, 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, start_col, Space.Space); // if + try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( - if (if_node.payload) |payload| { - try renderExpression(allocator, stream, tree, indent, payload, Space.Space); - } - - 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); + try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition + + const body_is_block = nodeIsBlock(if_node.body); + + if (body_is_block) { + 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, start_col, payload, Space.BlockStart); // |x| + } + + if (if_node.@"else") |@"else"| { + 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, start_col, if_node.body, space); + } + } + + 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, start_col, after_rparen_space); // ) + + if (if_node.payload) |payload| { + 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 = 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, start_col, Space.Space); // else + + if (@"else".payload) |payload| { + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); } - try renderExpression(allocator, stream, tree, indent, &@"else".base, space); + return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, 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); + const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space; + 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.Space); + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Newline); } + try stream.writeByteNTimes(' ', new_indent); - try renderExpression(allocator, stream, tree, indent, @"else".body, space); - } else { - try renderExpression(allocator, stream, tree, indent, if_node.body, space); + return renderExpression(allocator, stream, tree, new_indent, start_col, @"else".body, space); } - }, + } else { + return renderExpression(allocator, stream, tree, new_indent, start_col, if_node.body, space); + } + } + + try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // ) + + if (if_node.payload) |payload| { + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); + } + + if (if_node.@"else") |@"else"| { + 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, start_col, payload, Space.Space); + } + + return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space); + } else { + 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, 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); - 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, start_col, Space.Newline); // : + try stream.writeByteNTimes(' ', indent_once); + + break :blk tree.nextToken(colon1); + } else blk: { + try renderToken(tree, stream, colon1, indent, start_col, 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, 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, start_col, node, Space.Newline); + try stream.writeByteNTimes(' ', indent); + return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); + } else { + 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) { + 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, start_col, Space.Newline); // : + try stream.writeByteNTimes(' ', indent_once); + + break :blk tree.nextToken(colon2); + } else blk: { + try renderToken(tree, stream, colon2, indent, start_col, 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, 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, start_col, node, Space.Newline); + try stream.writeByteNTimes(' ', indent); + return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); // ) + } else { + 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) { + 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, start_col, 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, start_col, Space.Newline); + try stream.writeByteNTimes(' ', indent); + return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); + } else { + 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, start_col, Space.Space); // , } } - - try renderToken(tree, stream, asm_node.rparen, indent, space); }, ast.Node.Id.AsmInput => { 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, @@ -1306,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) (@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.None); + try renderToken(tree, stream, var_args_token, indent, start_col, space); } else { - try renderExpression(allocator, stream, tree, indent, param_decl.type_node, Space.None); + 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); } }, } @@ -1400,32 +1666,95 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde const Space = enum { None, Newline, + Comma, Space, + SpaceOrOutdent, NoNewline, - NoIndent, 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(tree.tokenSlicePtr(token)); + try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " ")); - if (space == Space.NoComment) return; + if (space == Space.NoComment) + return; var next_token = tree.tokens.at(token_index + 1); - if (next_token.id != Token.Id.LineComment) { + + 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 => { + 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; + 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, Space.NoIndent => return, - Space.Newline => return stream.write("\n"), - Space.Space => return stream.writeByte(' '), - Space.NoComment => unreachable, + Space.None, Space.NoNewline => return, + Space.Newline => { + if (next_token.id == Token.Id.MultilineStringLiteralLine) { + return; + } else { + try stream.write("\n"); + start_col.* = 0; + return; + } + }, + 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 => { + try stream.writeByte('\n'); + start_col.* = 0; + return; + }, + else => {}, } } 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); @@ -1439,10 +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 { + try stream.write("\n"); + start_col.* = 0; + return; + } }, - Space.Newline, Space.NoIndent => try stream.write("\n"), Space.NoNewline => {}, - Space.NoComment => unreachable, + Space.NoComment, Space.Comma, Space.BlockStart => unreachable, } return; } @@ -1454,26 +1797,40 @@ 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; 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 => { + if (next_token.id == Token.Id.MultilineStringLiteralLine) { + return; + } else { + try stream.write("\n"); + start_col.* = 0; + return; + } + }, Space.None, Space.Space => { try stream.writeByte('\n'); 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); + start_col.* = next_line_indent; + }, + Space.SpaceOrOutdent => { + try stream.writeByte('\n'); + try stream.writeByteNTimes(' ', indent); + start_col.* = indent; }, Space.NoNewline => {}, - Space.NoComment => unreachable, + Space.NoComment, Space.Comma, Space.BlockStart => unreachable, } return; } @@ -1481,33 +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| { - 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, start_col, Space.Newline); + try stream.writeByteNTimes(' ', indent); + } else { + try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.NoComment); + try stream.write("\n"); + 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 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, + }; } 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, |
