authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-29 03:22:52-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-29 03:22:52-04:00
logcb042c8343eb94a8d149fe1f5d69aa2746aa85d0
tree36b9711c480b61c372c86bc47dd20a635d624d3a
parent7fa97b752e167de6df9a8a76999456d2c199b345
parenteda6898c5b253367174172db909ee23013f32733

Merge remote-tracking branch 'origin/master' into llvm7


34 files changed, 2265 insertions(+), 1428 deletions(-)

doc/docgen.zig+117-65
......@@ -95,7 +95,7 @@ const Tokenizer = struct {
9595 };
9696
9797 fn init(source_file_name: []const u8, buffer: []const u8) Tokenizer {
98 return Tokenizer {
98 return Tokenizer{
9999 .buffer = buffer,
100100 .index = 0,
101101 .state = State.Start,
......@@ -105,7 +105,7 @@ const Tokenizer = struct {
105105 }
106106
107107 fn next(self: &Tokenizer) Token {
108 var result = Token {
108 var result = Token{
109109 .id = Token.Id.Eof,
110110 .start = self.index,
111111 .end = undefined,
......@@ -197,7 +197,7 @@ const Tokenizer = struct {
197197 };
198198
199199 fn getTokenLocation(self: &Tokenizer, token: &const Token) Location {
200 var loc = Location {
200 var loc = Location{
201201 .line = 0,
202202 .column = 0,
203203 .line_start = 0,
......@@ -346,7 +346,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
346346 break;
347347 },
348348 Token.Id.Content => {
349 try nodes.append(Node {.Content = tokenizer.buffer[token.start..token.end] });
349 try nodes.append(Node{ .Content = tokenizer.buffer[token.start..token.end] });
350350 },
351351 Token.Id.BracketOpen => {
352352 const tag_token = try eatToken(tokenizer, Token.Id.TagContent);
......@@ -365,11 +365,13 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
365365 header_stack_size += 1;
366366
367367 const urlized = try urlize(allocator, content);
368 try nodes.append(Node{.HeaderOpen = HeaderOpen {
369 .name = content,
370 .url = urlized,
371 .n = header_stack_size,
372 }});
368 try nodes.append(Node{
369 .HeaderOpen = HeaderOpen{
370 .name = content,
371 .url = urlized,
372 .n = header_stack_size,
373 },
374 });
373375 if (try urls.put(urlized, tag_token)) |other_tag_token| {
374376 parseError(tokenizer, tag_token, "duplicate header url: #{}", urlized) catch {};
375377 parseError(tokenizer, other_tag_token, "other tag here") catch {};
......@@ -407,14 +409,14 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
407409 switch (see_also_tok.id) {
408410 Token.Id.TagContent => {
409411 const content = tokenizer.buffer[see_also_tok.start..see_also_tok.end];
410 try list.append(SeeAlsoItem {
412 try list.append(SeeAlsoItem{
411413 .name = content,
412414 .token = see_also_tok,
413415 });
414416 },
415417 Token.Id.Separator => {},
416418 Token.Id.BracketClose => {
417 try nodes.append(Node {.SeeAlso = list.toOwnedSlice() } );
419 try nodes.append(Node{ .SeeAlso = list.toOwnedSlice() });
418420 break;
419421 },
420422 else => return parseError(tokenizer, see_also_tok, "invalid see_also token"),
......@@ -438,8 +440,8 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
438440 }
439441 };
440442
441 try nodes.append(Node {
442 .Link = Link {
443 try nodes.append(Node{
444 .Link = Link{
443445 .url = try urlize(allocator, url_name),
444446 .name = name,
445447 .token = name_tok,
......@@ -463,24 +465,24 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
463465 var code_kind_id: Code.Id = undefined;
464466 var is_inline = false;
465467 if (mem.eql(u8, code_kind_str, "exe")) {
466 code_kind_id = Code.Id { .Exe = ExpectedOutcome.Succeed };
468 code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Succeed };
467469 } else if (mem.eql(u8, code_kind_str, "exe_err")) {
468 code_kind_id = Code.Id { .Exe = ExpectedOutcome.Fail };
470 code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Fail };
469471 } else if (mem.eql(u8, code_kind_str, "test")) {
470472 code_kind_id = Code.Id.Test;
471473 } else if (mem.eql(u8, code_kind_str, "test_err")) {
472 code_kind_id = Code.Id { .TestError = name};
474 code_kind_id = Code.Id{ .TestError = name };
473475 name = "test";
474476 } else if (mem.eql(u8, code_kind_str, "test_safety")) {
475 code_kind_id = Code.Id { .TestSafety = name};
477 code_kind_id = Code.Id{ .TestSafety = name };
476478 name = "test";
477479 } else if (mem.eql(u8, code_kind_str, "obj")) {
478 code_kind_id = Code.Id { .Obj = null };
480 code_kind_id = Code.Id{ .Obj = null };
479481 } else if (mem.eql(u8, code_kind_str, "obj_err")) {
480 code_kind_id = Code.Id { .Obj = name };
482 code_kind_id = Code.Id{ .Obj = name };
481483 name = "test";
482484 } else if (mem.eql(u8, code_kind_str, "syntax")) {
483 code_kind_id = Code.Id { .Obj = null };
485 code_kind_id = Code.Id{ .Obj = null };
484486 is_inline = true;
485487 } else {
486488 return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {}", code_kind_str);
......@@ -514,17 +516,20 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
514516 return parseError(tokenizer, end_code_tag, "invalid token inside code_begin: {}", end_tag_name);
515517 }
516518 _ = try eatToken(tokenizer, Token.Id.BracketClose);
517 } else unreachable; // TODO issue #707
518 try nodes.append(Node {.Code = Code {
519 .id = code_kind_id,
520 .name = name,
521 .source_token = source_token,
522 .is_inline = is_inline,
523 .mode = mode,
524 .link_objects = link_objects.toOwnedSlice(),
525 .target_windows = target_windows,
526 .link_libc = link_libc,
527 }});
519 } else
520 unreachable; // TODO issue #707
521 try nodes.append(Node{
522 .Code = Code{
523 .id = code_kind_id,
524 .name = name,
525 .source_token = source_token,
526 .is_inline = is_inline,
527 .mode = mode,
528 .link_objects = link_objects.toOwnedSlice(),
529 .target_windows = target_windows,
530 .link_libc = link_libc,
531 },
532 });
528533 tokenizer.code_node_count += 1;
529534 } else {
530535 return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name);
......@@ -534,7 +539,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
534539 }
535540 }
536541
537 return Toc {
542 return Toc{
538543 .nodes = nodes.toOwnedSlice(),
539544 .toc = toc_buf.toOwnedSlice(),
540545 .urls = urls,
......@@ -727,16 +732,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
727732 const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
728733 const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);
729734 try io.writeFile(allocator, tmp_source_file_name, trimmed_raw_source);
730
735
731736 switch (code.id) {
732737 Code.Id.Exe => |expected_outcome| {
733738 const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
734739 const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext);
735740 var build_args = std.ArrayList([]const u8).init(allocator);
736741 defer build_args.deinit();
737 try build_args.appendSlice([][]const u8 {zig_exe,
738 "build-exe", tmp_source_file_name,
739 "--output", tmp_bin_file_name,
742 try build_args.appendSlice([][]const u8{
743 zig_exe,
744 "build-exe",
745 tmp_source_file_name,
746 "--output",
747 tmp_bin_file_name,
740748 });
741749 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);
742750 switch (code.mode) {
......@@ -766,10 +774,9 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
766774 try build_args.append("c");
767775 try out.print(" --library c");
768776 }
769 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(
770 tokenizer, code.source_token, "example failed to compile");
777 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
771778
772 const run_args = [][]const u8 {tmp_bin_file_name};
779 const run_args = [][]const u8{tmp_bin_file_name};
773780
774781 const result = if (expected_outcome == ExpectedOutcome.Fail) blk: {
775782 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
777784 os.ChildProcess.Term.Exited => |exit_code| {
778785 if (exit_code == 0) {
779786 warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
780 for (run_args) |arg| warn("{} ", arg) else warn("\n");
787 for (run_args) |arg|
788 warn("{} ", arg)
789 else
790 warn("\n");
781791 return parseError(tokenizer, code.source_token, "example incorrectly compiled");
782792 }
783793 },
......@@ -785,11 +795,9 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
785795 }
786796 break :blk result;
787797 } else blk: {
788 break :blk exec(allocator, run_args) catch return parseError(
789 tokenizer, code.source_token, "example crashed");
798 break :blk exec(allocator, run_args) catch return parseError(tokenizer, code.source_token, "example crashed");
790799 };
791800
792
793801 const escaped_stderr = try escapeHtml(allocator, result.stderr);
794802 const escaped_stdout = try escapeHtml(allocator, result.stdout);
795803
......@@ -802,7 +810,11 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
802810 var test_args = std.ArrayList([]const u8).init(allocator);
803811 defer test_args.deinit();
804812
805 try test_args.appendSlice([][]const u8 {zig_exe, "test", tmp_source_file_name});
813 try test_args.appendSlice([][]const u8{
814 zig_exe,
815 "test",
816 tmp_source_file_name,
817 });
806818 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
807819 switch (code.mode) {
808820 builtin.Mode.Debug => {},
......@@ -821,13 +833,15 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
821833 }
822834 if (code.target_windows) {
823835 try test_args.appendSlice([][]const u8{
824 "--target-os", "windows",
825 "--target-arch", "x86_64",
826 "--target-environ", "msvc",
836 "--target-os",
837 "windows",
838 "--target-arch",
839 "x86_64",
840 "--target-environ",
841 "msvc",
827842 });
828843 }
829 const result = exec(allocator, test_args.toSliceConst()) catch return parseError(
830 tokenizer, code.source_token, "test failed");
844 const result = exec(allocator, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
831845 const escaped_stderr = try escapeHtml(allocator, result.stderr);
832846 const escaped_stdout = try escapeHtml(allocator, result.stdout);
833847 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
836850 var test_args = std.ArrayList([]const u8).init(allocator);
837851 defer test_args.deinit();
838852
839 try test_args.appendSlice([][]const u8 {zig_exe, "test", "--color", "on", tmp_source_file_name});
853 try test_args.appendSlice([][]const u8{
854 zig_exe,
855 "test",
856 "--color",
857 "on",
858 tmp_source_file_name,
859 });
840860 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
841861 switch (code.mode) {
842862 builtin.Mode.Debug => {},
......@@ -858,13 +878,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
858878 os.ChildProcess.Term.Exited => |exit_code| {
859879 if (exit_code == 0) {
860880 warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
861 for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
881 for (test_args.toSliceConst()) |arg|
882 warn("{} ", arg)
883 else
884 warn("\n");
862885 return parseError(tokenizer, code.source_token, "example incorrectly compiled");
863886 }
864887 },
865888 else => {
866889 warn("{}\nThe following command crashed:\n", result.stderr);
867 for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
890 for (test_args.toSliceConst()) |arg|
891 warn("{} ", arg)
892 else
893 warn("\n");
868894 return parseError(tokenizer, code.source_token, "example compile crashed");
869895 },
870896 }
......@@ -881,7 +907,11 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
881907 var test_args = std.ArrayList([]const u8).init(allocator);
882908 defer test_args.deinit();
883909
884 try test_args.appendSlice([][]const u8 {zig_exe, "test", tmp_source_file_name});
910 try test_args.appendSlice([][]const u8{
911 zig_exe,
912 "test",
913 tmp_source_file_name,
914 });
885915 switch (code.mode) {
886916 builtin.Mode.Debug => {},
887917 builtin.Mode.ReleaseSafe => try test_args.append("--release-safe"),
......@@ -894,13 +924,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
894924 os.ChildProcess.Term.Exited => |exit_code| {
895925 if (exit_code == 0) {
896926 warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
897 for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
927 for (test_args.toSliceConst()) |arg|
928 warn("{} ", arg)
929 else
930 warn("\n");
898931 return parseError(tokenizer, code.source_token, "example test incorrectly succeeded");
899932 }
900933 },
901934 else => {
902935 warn("{}\nThe following command crashed:\n", result.stderr);
903 for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
936 for (test_args.toSliceConst()) |arg|
937 warn("{} ", arg)
938 else
939 warn("\n");
904940 return parseError(tokenizer, code.source_token, "example compile crashed");
905941 },
906942 }
......@@ -918,9 +954,15 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
918954 var build_args = std.ArrayList([]const u8).init(allocator);
919955 defer build_args.deinit();
920956
921 try build_args.appendSlice([][]const u8 {zig_exe, "build-obj", tmp_source_file_name,
922 "--color", "on",
923 "--output", tmp_obj_file_name});
957 try build_args.appendSlice([][]const u8{
958 zig_exe,
959 "build-obj",
960 tmp_source_file_name,
961 "--color",
962 "on",
963 "--output",
964 tmp_obj_file_name,
965 });
924966
925967 if (!code.is_inline) {
926968 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
954996 os.ChildProcess.Term.Exited => |exit_code| {
955997 if (exit_code == 0) {
956998 warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);
957 for (build_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
999 for (build_args.toSliceConst()) |arg|
1000 warn("{} ", arg)
1001 else
1002 warn("\n");
9581003 return parseError(tokenizer, code.source_token, "example build incorrectly succeeded");
9591004 }
9601005 },
9611006 else => {
9621007 warn("{}\nThe following command crashed:\n", result.stderr);
963 for (build_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n");
1008 for (build_args.toSliceConst()) |arg|
1009 warn("{} ", arg)
1010 else
1011 warn("\n");
9641012 return parseError(tokenizer, code.source_token, "example compile crashed");
9651013 },
9661014 }
......@@ -975,8 +1023,7 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
9751023 try out.print("</code></pre>\n");
9761024 }
9771025 } else {
978 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(
979 tokenizer, code.source_token, "example failed to compile");
1026 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
9801027 }
9811028 if (!code.is_inline) {
9821029 try out.print("</code></pre>\n");
......@@ -987,7 +1034,6 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
9871034 },
9881035 }
9891036 }
990
9911037}
9921038
9931039fn 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
9961042 os.ChildProcess.Term.Exited => |exit_code| {
9971043 if (exit_code != 0) {
9981044 warn("{}\nThe following command exited with code {}:\n", result.stderr, exit_code);
999 for (args) |arg| warn("{} ", arg) else warn("\n");
1045 for (args) |arg|
1046 warn("{} ", arg)
1047 else
1048 warn("\n");
10001049 return error.ChildExitError;
10011050 }
10021051 },
10031052 else => {
10041053 warn("{}\nThe following command crashed:\n", result.stderr);
1005 for (args) |arg| warn("{} ", arg) else warn("\n");
1054 for (args) |arg|
1055 warn("{} ", arg)
1056 else
1057 warn("\n");
10061058 return error.ChildCrashed;
10071059 },
10081060 }
example/guess_number/main.zig+1-1
......@@ -23,7 +23,7 @@ pub fn main() !void {
2323
2424 while (true) {
2525 try stdout.print("\nGuess a number between 1 and 100: ");
26 var line_buf : [20]u8 = undefined;
26 var line_buf: [20]u8 = undefined;
2727
2828 const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) {
2929 error.InputTooLong => {
example/hello_world/hello_libc.zig+1-2
......@@ -8,8 +8,7 @@ const c = @cImport({
88const msg = c"Hello, world!\n";
99
1010export fn main(argc: c_int, argv: &&u8) c_int {
11 if (c.printf(msg) != c_int(c.strlen(msg)))
12 return -1;
11 if (c.printf(msg) != c_int(c.strlen(msg))) return -1;
1312
1413 return 0;
1514}
example/mix_o_files/build.zig+1-3
......@@ -4,9 +4,7 @@ pub fn build(b: &Builder) void {
44 const obj = b.addObject("base64", "base64.zig");
55
66 const exe = b.addCExecutable("test");
7 exe.addCompileFlags([][]const u8 {
8 "-std=c99",
9 });
7 exe.addCompileFlags([][]const u8{"-std=c99"});
108 exe.addSourceFile("test.c");
119 exe.addObject(obj);
1210
example/shared_library/build.zig+1-3
......@@ -4,9 +4,7 @@ pub fn build(b: &Builder) void {
44 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
55
66 const exe = b.addCExecutable("test");
7 exe.addCompileFlags([][]const u8 {
8 "-std=c99",
9 });
7 exe.addCompileFlags([][]const u8{"-std=c99"});
108 exe.addSourceFile("test.c");
119 exe.linkLibrary(lib);
1210
src-self-hosted/introspect.zig+1-3
......@@ -48,9 +48,7 @@ pub fn resolveZigLibDir(allocator: &mem.Allocator) ![]u8 {
4848 \\Unable to find zig lib directory: {}.
4949 \\Reinstall Zig or use --zig-install-prefix.
5050 \\
51 ,
52 @errorName(err)
53 );
51 , @errorName(err));
5452
5553 return error.ZigLibDirNotFound;
5654 };
src-self-hosted/ir.zig-1
......@@ -108,5 +108,4 @@ pub const Instruction = struct {
108108 ArgType,
109109 Export,
110110 };
111
112111};
src-self-hosted/main.zig+102-67
......@@ -37,7 +37,7 @@ const usage =
3737 \\ zen Print zen of zig and exit
3838 \\
3939 \\
40 ;
40;
4141
4242const Command = struct {
4343 name: []const u8,
......@@ -63,22 +63,61 @@ pub fn main() !void {
6363 os.exit(1);
6464 }
6565
66 const commands = []Command {
67 Command { .name = "build", .exec = cmdBuild },
68 Command { .name = "build-exe", .exec = cmdBuildExe },
69 Command { .name = "build-lib", .exec = cmdBuildLib },
70 Command { .name = "build-obj", .exec = cmdBuildObj },
71 Command { .name = "fmt", .exec = cmdFmt },
72 Command { .name = "run", .exec = cmdRun },
73 Command { .name = "targets", .exec = cmdTargets },
74 Command { .name = "test", .exec = cmdTest },
75 Command { .name = "translate-c", .exec = cmdTranslateC },
76 Command { .name = "version", .exec = cmdVersion },
77 Command { .name = "zen", .exec = cmdZen },
66 const commands = []Command{
67 Command{
68 .name = "build",
69 .exec = cmdBuild,
70 },
71 Command{
72 .name = "build-exe",
73 .exec = cmdBuildExe,
74 },
75 Command{
76 .name = "build-lib",
77 .exec = cmdBuildLib,
78 },
79 Command{
80 .name = "build-obj",
81 .exec = cmdBuildObj,
82 },
83 Command{
84 .name = "fmt",
85 .exec = cmdFmt,
86 },
87 Command{
88 .name = "run",
89 .exec = cmdRun,
90 },
91 Command{
92 .name = "targets",
93 .exec = cmdTargets,
94 },
95 Command{
96 .name = "test",
97 .exec = cmdTest,
98 },
99 Command{
100 .name = "translate-c",
101 .exec = cmdTranslateC,
102 },
103 Command{
104 .name = "version",
105 .exec = cmdVersion,
106 },
107 Command{
108 .name = "zen",
109 .exec = cmdZen,
110 },
78111
79112 // undocumented commands
80 Command { .name = "help", .exec = cmdHelp },
81 Command { .name = "internal", .exec = cmdInternal },
113 Command{
114 .name = "help",
115 .exec = cmdHelp,
116 },
117 Command{
118 .name = "internal",
119 .exec = cmdInternal,
120 },
82121 };
83122
84123 for (commands) |command| {
......@@ -120,9 +159,9 @@ const usage_build =
120159 \\ --verbose-cimport Enable compiler debug output for C imports
121160 \\
122161 \\
123 ;
162;
124163
125const args_build_spec = []Flag {
164const args_build_spec = []Flag{
126165 Flag.Bool("--help"),
127166 Flag.Bool("--init"),
128167 Flag.Arg1("--build-file"),
......@@ -148,7 +187,7 @@ const missing_build_file =
148187 \\
149188 \\See: `zig build --help` or `zig help` for more options.
150189 \\
151 ;
190;
152191
153192fn cmdBuild(allocator: &Allocator, args: []const []const u8) !void {
154193 var flags = try Args.parse(allocator, args_build_spec, args);
......@@ -317,15 +356,23 @@ const usage_build_generic =
317356 \\ --ver-patch [ver] Dynamic library semver patch version
318357 \\
319358 \\
320 ;
359;
321360
322const args_build_generic = []Flag {
361const args_build_generic = []Flag{
323362 Flag.Bool("--help"),
324 Flag.Option("--color", []const []const u8 { "auto", "off", "on" }),
363 Flag.Option("--color", []const []const u8{
364 "auto",
365 "off",
366 "on",
367 }),
325368
326369 Flag.ArgMergeN("--assembly", 1),
327370 Flag.Arg1("--cache-dir"),
328 Flag.Option("--emit", []const []const u8 { "asm", "bin", "llvm-ir" }),
371 Flag.Option("--emit", []const []const u8{
372 "asm",
373 "bin",
374 "llvm-ir",
375 }),
329376 Flag.Bool("--enable-timing-info"),
330377 Flag.Arg1("--libc-include-dir"),
331378 Flag.Arg1("--name"),
......@@ -471,7 +518,7 @@ fn buildOutputType(allocator: &Allocator, args: []const []const u8, out_type: Mo
471518 os.exit(1);
472519 };
473520
474 const asm_a= flags.many("assembly");
521 const asm_a = flags.many("assembly");
475522 const obj_a = flags.many("object");
476523 if (in_file == null and (obj_a == null or (??obj_a).len == 0) and (asm_a == null or (??asm_a).len == 0)) {
477524 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
493540 const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch os.exit(1);
494541 defer allocator.free(zig_lib_dir);
495542
496 var module =
497 try Module.create(
498 allocator,
499 root_name,
500 zig_root_source_file,
501 Target.Native,
502 out_type,
503 build_mode,
504 zig_lib_dir,
505 full_cache_dir
506 );
543 var module = try Module.create(
544 allocator,
545 root_name,
546 zig_root_source_file,
547 Target.Native,
548 out_type,
549 build_mode,
550 zig_lib_dir,
551 full_cache_dir,
552 );
507553 defer module.destroy();
508554
509555 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
588634 }
589635
590636 if (flags.single("mmacosx-version-min")) |ver| {
591 module.darwin_version_min = Module.DarwinVersionMin { .MacOS = ver };
637 module.darwin_version_min = Module.DarwinVersionMin{ .MacOS = ver };
592638 }
593639 if (flags.single("mios-version-min")) |ver| {
594 module.darwin_version_min = Module.DarwinVersionMin { .Ios = ver };
640 module.darwin_version_min = Module.DarwinVersionMin{ .Ios = ver };
595641 }
596642
597643 module.emit_file_type = emit_type;
......@@ -639,11 +685,9 @@ const usage_fmt =
639685 \\ --help Print this help and exit
640686 \\
641687 \\
642 ;
688;
643689
644const args_fmt_spec = []Flag {
645 Flag.Bool("--help"),
646};
690const args_fmt_spec = []Flag{Flag.Bool("--help")};
647691
648692fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void {
649693 var flags = try Args.parse(allocator, args_fmt_spec, args);
......@@ -675,7 +719,6 @@ fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void {
675719 };
676720 defer tree.deinit();
677721
678
679722 var error_it = tree.errors.iterator(0);
680723 while (error_it.next()) |parse_error| {
681724 const token = tree.tokens.at(parse_error.loc());
......@@ -721,8 +764,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void {
721764 inline while (i < @memberCount(builtin.Arch)) : (i += 1) {
722765 comptime const arch_tag = @memberName(builtin.Arch, i);
723766 // NOTE: Cannot use empty string, see #918.
724 comptime const native_str =
725 if (comptime mem.eql(u8, arch_tag, @tagName(builtin.arch))) " (native)\n" else "\n";
767 comptime const native_str = if (comptime mem.eql(u8, arch_tag, @tagName(builtin.arch))) " (native)\n" else "\n";
726768
727769 try stdout.print(" {}{}", arch_tag, native_str);
728770 }
......@@ -735,8 +777,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void {
735777 inline while (i < @memberCount(builtin.Os)) : (i += 1) {
736778 comptime const os_tag = @memberName(builtin.Os, i);
737779 // NOTE: Cannot use empty string, see #918.
738 comptime const native_str =
739 if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n";
780 comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n";
740781
741782 try stdout.print(" {}{}", os_tag, native_str);
742783 }
......@@ -749,8 +790,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void {
749790 inline while (i < @memberCount(builtin.Environ)) : (i += 1) {
750791 comptime const environ_tag = @memberName(builtin.Environ, i);
751792 // NOTE: Cannot use empty string, see #918.
752 comptime const native_str =
753 if (comptime mem.eql(u8, environ_tag, @tagName(builtin.environ))) " (native)\n" else "\n";
793 comptime const native_str = if (comptime mem.eql(u8, environ_tag, @tagName(builtin.environ))) " (native)\n" else "\n";
754794
755795 try stdout.print(" {}{}", environ_tag, native_str);
756796 }
......@@ -772,12 +812,9 @@ const usage_test =
772812 \\ --help Print this help and exit
773813 \\
774814 \\
775 ;
776
777const args_test_spec = []Flag {
778 Flag.Bool("--help"),
779};
815;
780816
817const args_test_spec = []Flag{Flag.Bool("--help")};
781818
782819fn cmdTest(allocator: &Allocator, args: []const []const u8) !void {
783820 var flags = try Args.parse(allocator, args_build_spec, args);
......@@ -810,21 +847,18 @@ const usage_run =
810847 \\ --help Print this help and exit
811848 \\
812849 \\
813 ;
814
815const args_run_spec = []Flag {
816 Flag.Bool("--help"),
817};
850;
818851
852const args_run_spec = []Flag{Flag.Bool("--help")};
819853
820854fn cmdRun(allocator: &Allocator, args: []const []const u8) !void {
821855 var compile_args = args;
822 var runtime_args: []const []const u8 = []const []const u8 {};
856 var runtime_args: []const []const u8 = []const []const u8{};
823857
824858 for (args) |argv, i| {
825859 if (mem.eql(u8, argv, "--")) {
826860 compile_args = args[0..i];
827 runtime_args = args[i+1..];
861 runtime_args = args[i + 1..];
828862 break;
829863 }
830864 }
......@@ -858,9 +892,9 @@ const usage_translate_c =
858892 \\ --output [path] Output file to write generated zig file (default: stdout)
859893 \\
860894 \\
861 ;
895;
862896
863const args_translate_c_spec = []Flag {
897const args_translate_c_spec = []Flag{
864898 Flag.Bool("--help"),
865899 Flag.Bool("--enable-timing-info"),
866900 Flag.Arg1("--libc-include-dir"),
......@@ -934,7 +968,7 @@ const info_zen =
934968 \\ * Together we serve end users.
935969 \\
936970 \\
937 ;
971;
938972
939973fn cmdZen(allocator: &Allocator, args: []const []const u8) !void {
940974 try stdout.write(info_zen);
......@@ -949,7 +983,7 @@ const usage_internal =
949983 \\ build-info Print static compiler build-info
950984 \\
951985 \\
952 ;
986;
953987
954988fn cmdInternal(allocator: &Allocator, args: []const []const u8) !void {
955989 if (args.len == 0) {
......@@ -957,9 +991,10 @@ fn cmdInternal(allocator: &Allocator, args: []const []const u8) !void {
957991 os.exit(1);
958992 }
959993
960 const sub_commands = []Command {
961 Command { .name = "build-info", .exec = cmdInternalBuildInfo },
962 };
994 const sub_commands = []Command{Command{
995 .name = "build-info",
996 .exec = cmdInternalBuildInfo,
997 }};
963998
964999 for (sub_commands) |sub_command| {
9651000 if (mem.eql(u8, sub_command.name, args[0])) {
......@@ -983,7 +1018,7 @@ fn cmdInternalBuildInfo(allocator: &Allocator, args: []const []const u8) !void {
9831018 \\ZIG_C_HEADER_FILES {}
9841019 \\ZIG_DIA_GUIDS_LIB {}
9851020 \\
986 ,
1021 ,
9871022 std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
9881023 std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
9891024 std.cstr.toSliceConst(c.ZIG_LLVM_CONFIG_EXE),
src-self-hosted/target.zig+1-2
......@@ -38,8 +38,7 @@ pub const Target = union(enum) {
3838
3939 pub fn isDarwin(self: &const Target) bool {
4040 return switch (self.getOs()) {
41 builtin.Os.ios,
42 builtin.Os.macosx => true,
41 builtin.Os.ios, builtin.Os.macosx => true,
4342 else => false,
4443 };
4544 }
std/array_list.zig+6-3
......@@ -150,7 +150,10 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
150150 };
151151
152152 pub fn iterator(self: &const Self) Iterator {
153 return Iterator { .list = self, .count = 0 };
153 return Iterator{
154 .list = self,
155 .count = 0,
156 };
154157 }
155158 };
156159}
......@@ -207,7 +210,7 @@ test "iterator ArrayList test" {
207210 try list.append(2);
208211 try list.append(3);
209212
210 var count : i32 = 0;
213 var count: i32 = 0;
211214 var it = list.iterator();
212215 while (it.next()) |next| {
213216 assert(next == count + 1);
......@@ -225,7 +228,7 @@ test "iterator ArrayList test" {
225228 }
226229
227230 it.reset();
228 assert(?? it.next() == 1);
231 assert(??it.next() == 1);
229232}
230233
231234test "insert ArrayList test" {
std/base64.zig+46-71
......@@ -41,12 +41,10 @@ pub const Base64Encoder = struct {
4141 dest[out_index] = encoder.alphabet_chars[(source[i] >> 2) & 0x3f];
4242 out_index += 1;
4343
44 dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) |
45 ((source[i + 1] & 0xf0) >> 4)];
44 dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) | ((source[i + 1] & 0xf0) >> 4)];
4645 out_index += 1;
4746
48 dest[out_index] = encoder.alphabet_chars[((source[i + 1] & 0xf) << 2) |
49 ((source[i + 2] & 0xc0) >> 6)];
47 dest[out_index] = encoder.alphabet_chars[((source[i + 1] & 0xf) << 2) | ((source[i + 2] & 0xc0) >> 6)];
5048 out_index += 1;
5149
5250 dest[out_index] = encoder.alphabet_chars[source[i + 2] & 0x3f];
......@@ -64,8 +62,7 @@ pub const Base64Encoder = struct {
6462 dest[out_index] = encoder.pad_char;
6563 out_index += 1;
6664 } else {
67 dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) |
68 ((source[i + 1] & 0xf0) >> 4)];
65 dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) | ((source[i + 1] & 0xf0) >> 4)];
6966 out_index += 1;
7067
7168 dest[out_index] = encoder.alphabet_chars[(source[i + 1] & 0xf) << 2];
......@@ -131,26 +128,20 @@ pub const Base64Decoder = struct {
131128 // common case
132129 if (!decoder.char_in_alphabet[source[src_cursor + 2]]) return error.InvalidCharacter;
133130 if (!decoder.char_in_alphabet[source[src_cursor + 3]]) return error.InvalidCharacter;
134 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 |
135 decoder.char_to_index[source[src_cursor + 1]] >> 4;
136 dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 |
137 decoder.char_to_index[source[src_cursor + 2]] >> 2;
138 dest[dest_cursor + 2] = decoder.char_to_index[source[src_cursor + 2]] << 6 |
139 decoder.char_to_index[source[src_cursor + 3]];
131 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | decoder.char_to_index[source[src_cursor + 1]] >> 4;
132 dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 | decoder.char_to_index[source[src_cursor + 2]] >> 2;
133 dest[dest_cursor + 2] = decoder.char_to_index[source[src_cursor + 2]] << 6 | decoder.char_to_index[source[src_cursor + 3]];
140134 dest_cursor += 3;
141135 } else if (source[src_cursor + 2] != decoder.pad_char) {
142136 // one pad char
143137 if (!decoder.char_in_alphabet[source[src_cursor + 2]]) return error.InvalidCharacter;
144 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 |
145 decoder.char_to_index[source[src_cursor + 1]] >> 4;
146 dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 |
147 decoder.char_to_index[source[src_cursor + 2]] >> 2;
138 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | decoder.char_to_index[source[src_cursor + 1]] >> 4;
139 dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 | decoder.char_to_index[source[src_cursor + 2]] >> 2;
148140 if (decoder.char_to_index[source[src_cursor + 2]] << 6 != 0) return error.InvalidPadding;
149141 dest_cursor += 2;
150142 } else {
151143 // two pad chars
152 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 |
153 decoder.char_to_index[source[src_cursor + 1]] >> 4;
144 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | decoder.char_to_index[source[src_cursor + 1]] >> 4;
154145 if (decoder.char_to_index[source[src_cursor + 1]] << 4 != 0) return error.InvalidPadding;
155146 dest_cursor += 1;
156147 }
......@@ -165,7 +156,7 @@ pub const Base64DecoderWithIgnore = struct {
165156 decoder: Base64Decoder,
166157 char_is_ignored: [256]bool,
167158 pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) Base64DecoderWithIgnore {
168 var result = Base64DecoderWithIgnore {
159 var result = Base64DecoderWithIgnore{
169160 .decoder = Base64Decoder.init(alphabet_chars, pad_char),
170161 .char_is_ignored = []bool{false} ** 256,
171162 };
......@@ -223,10 +214,12 @@ pub const Base64DecoderWithIgnore = struct {
223214 } else if (decoder_with_ignore.char_is_ignored[c]) {
224215 // we can even ignore chars during the padding
225216 continue;
226 } else return error.InvalidCharacter;
217 } else
218 return error.InvalidCharacter;
227219 }
228220 break;
229 } else return error.InvalidCharacter;
221 } else
222 return error.InvalidCharacter;
230223 }
231224
232225 switch (available_chars) {
......@@ -234,22 +227,17 @@ pub const Base64DecoderWithIgnore = struct {
234227 // common case
235228 if (dest_cursor + 3 > dest.len) return error.OutputTooSmall;
236229 assert(pad_char_count == 0);
237 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 |
238 decoder.char_to_index[next_4_chars[1]] >> 4;
239 dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 |
240 decoder.char_to_index[next_4_chars[2]] >> 2;
241 dest[dest_cursor + 2] = decoder.char_to_index[next_4_chars[2]] << 6 |
242 decoder.char_to_index[next_4_chars[3]];
230 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | decoder.char_to_index[next_4_chars[1]] >> 4;
231 dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 | decoder.char_to_index[next_4_chars[2]] >> 2;
232 dest[dest_cursor + 2] = decoder.char_to_index[next_4_chars[2]] << 6 | decoder.char_to_index[next_4_chars[3]];
243233 dest_cursor += 3;
244234 continue;
245235 },
246236 3 => {
247237 if (dest_cursor + 2 > dest.len) return error.OutputTooSmall;
248238 if (pad_char_count != 1) return error.InvalidPadding;
249 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 |
250 decoder.char_to_index[next_4_chars[1]] >> 4;
251 dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 |
252 decoder.char_to_index[next_4_chars[2]] >> 2;
239 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | decoder.char_to_index[next_4_chars[1]] >> 4;
240 dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 | decoder.char_to_index[next_4_chars[2]] >> 2;
253241 if (decoder.char_to_index[next_4_chars[2]] << 6 != 0) return error.InvalidPadding;
254242 dest_cursor += 2;
255243 break;
......@@ -257,8 +245,7 @@ pub const Base64DecoderWithIgnore = struct {
257245 2 => {
258246 if (dest_cursor + 1 > dest.len) return error.OutputTooSmall;
259247 if (pad_char_count != 2) return error.InvalidPadding;
260 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 |
261 decoder.char_to_index[next_4_chars[1]] >> 4;
248 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | decoder.char_to_index[next_4_chars[1]] >> 4;
262249 if (decoder.char_to_index[next_4_chars[1]] << 4 != 0) return error.InvalidPadding;
263250 dest_cursor += 1;
264251 break;
......@@ -280,7 +267,6 @@ pub const Base64DecoderWithIgnore = struct {
280267 }
281268};
282269
283
284270pub const standard_decoder_unsafe = Base64DecoderUnsafe.init(standard_alphabet_chars, standard_pad_char);
285271
286272pub const Base64DecoderUnsafe = struct {
......@@ -291,7 +277,7 @@ pub const Base64DecoderUnsafe = struct {
291277
292278 pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64DecoderUnsafe {
293279 assert(alphabet_chars.len == 64);
294 var result = Base64DecoderUnsafe {
280 var result = Base64DecoderUnsafe{
295281 .char_to_index = undefined,
296282 .pad_char = pad_char,
297283 };
......@@ -321,16 +307,13 @@ pub const Base64DecoderUnsafe = struct {
321307 }
322308
323309 while (in_buf_len > 4) {
324 dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 |
325 decoder.char_to_index[source[src_index + 1]] >> 4;
310 dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | decoder.char_to_index[source[src_index + 1]] >> 4;
326311 dest_index += 1;
327312
328 dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 |
329 decoder.char_to_index[source[src_index + 2]] >> 2;
313 dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | decoder.char_to_index[source[src_index + 2]] >> 2;
330314 dest_index += 1;
331315
332 dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 |
333 decoder.char_to_index[source[src_index + 3]];
316 dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | decoder.char_to_index[source[src_index + 3]];
334317 dest_index += 1;
335318
336319 src_index += 4;
......@@ -338,18 +321,15 @@ pub const Base64DecoderUnsafe = struct {
338321 }
339322
340323 if (in_buf_len > 1) {
341 dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 |
342 decoder.char_to_index[source[src_index + 1]] >> 4;
324 dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | decoder.char_to_index[source[src_index + 1]] >> 4;
343325 dest_index += 1;
344326 }
345327 if (in_buf_len > 2) {
346 dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 |
347 decoder.char_to_index[source[src_index + 2]] >> 2;
328 dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | decoder.char_to_index[source[src_index + 2]] >> 2;
348329 dest_index += 1;
349330 }
350331 if (in_buf_len > 3) {
351 dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 |
352 decoder.char_to_index[source[src_index + 3]];
332 dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | decoder.char_to_index[source[src_index + 3]];
353333 dest_index += 1;
354334 }
355335 }
......@@ -367,7 +347,6 @@ fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) usize {
367347 return result;
368348}
369349
370
371350test "base64" {
372351 @setEvalBranchQuota(8000);
373352 testBase64() catch unreachable;
......@@ -375,26 +354,26 @@ test "base64" {
375354}
376355
377356fn testBase64() !void {
378 try testAllApis("", "");
379 try testAllApis("f", "Zg==");
380 try testAllApis("fo", "Zm8=");
381 try testAllApis("foo", "Zm9v");
382 try testAllApis("foob", "Zm9vYg==");
383 try testAllApis("fooba", "Zm9vYmE=");
357 try testAllApis("", "");
358 try testAllApis("f", "Zg==");
359 try testAllApis("fo", "Zm8=");
360 try testAllApis("foo", "Zm9v");
361 try testAllApis("foob", "Zm9vYg==");
362 try testAllApis("fooba", "Zm9vYmE=");
384363 try testAllApis("foobar", "Zm9vYmFy");
385364
386 try testDecodeIgnoreSpace("", " ");
387 try testDecodeIgnoreSpace("f", "Z g= =");
388 try testDecodeIgnoreSpace("fo", " Zm8=");
389 try testDecodeIgnoreSpace("foo", "Zm9v ");
390 try testDecodeIgnoreSpace("foob", "Zm9vYg = = ");
391 try testDecodeIgnoreSpace("fooba", "Zm9v YmE=");
365 try testDecodeIgnoreSpace("", " ");
366 try testDecodeIgnoreSpace("f", "Z g= =");
367 try testDecodeIgnoreSpace("fo", " Zm8=");
368 try testDecodeIgnoreSpace("foo", "Zm9v ");
369 try testDecodeIgnoreSpace("foob", "Zm9vYg = = ");
370 try testDecodeIgnoreSpace("fooba", "Zm9v YmE=");
392371 try testDecodeIgnoreSpace("foobar", " Z m 9 v Y m F y ");
393372
394373 // test getting some api errors
395 try testError("A", error.InvalidPadding);
396 try testError("AA", error.InvalidPadding);
397 try testError("AAA", error.InvalidPadding);
374 try testError("A", error.InvalidPadding);
375 try testError("AA", error.InvalidPadding);
376 try testError("AAA", error.InvalidPadding);
398377 try testError("A..A", error.InvalidCharacter);
399378 try testError("AA=A", error.InvalidCharacter);
400379 try testError("AA/=", error.InvalidPadding);
......@@ -427,8 +406,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
427406
428407 // Base64DecoderWithIgnore
429408 {
430 const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init(
431 standard_alphabet_chars, standard_pad_char, "");
409 const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, "");
432410 var buffer: [0x100]u8 = undefined;
433411 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)];
434412 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
446424}
447425
448426fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !void {
449 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
450 standard_alphabet_chars, standard_pad_char, " ");
427 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, " ");
451428 var buffer: [0x100]u8 = undefined;
452429 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)];
453430 var written = try standard_decoder_ignore_space.decode(decoded, encoded);
......@@ -455,8 +432,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi
455432}
456433
457434fn testError(encoded: []const u8, expected_err: error) !void {
458 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
459 standard_alphabet_chars, standard_pad_char, " ");
435 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, " ");
460436 var buffer: [0x100]u8 = undefined;
461437 if (standard_decoder.calcSize(encoded)) |decoded_size| {
462438 var decoded = buffer[0..decoded_size];
......@@ -471,8 +447,7 @@ fn testError(encoded: []const u8, expected_err: error) !void {
471447}
472448
473449fn testOutputTooSmallError(encoded: []const u8) !void {
474 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
475 standard_alphabet_chars, standard_pad_char, " ");
450 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, " ");
476451 var buffer: [0x100]u8 = undefined;
477452 var decoded = buffer[0..calcDecodedSizeExactUnsafe(encoded, standard_pad_char) - 1];
478453 if (standard_decoder_ignore_space.decode(decoded, encoded)) |_| {
std/buf_map.zig+1-3
......@@ -12,9 +12,7 @@ pub const BufMap = struct {
1212 const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8);
1313
1414 pub fn init(allocator: &Allocator) BufMap {
15 var self = BufMap {
16 .hash_map = BufMapHashMap.init(allocator),
17 };
15 var self = BufMap{ .hash_map = BufMapHashMap.init(allocator) };
1816 return self;
1917 }
2018
std/buf_set.zig+1-3
......@@ -10,9 +10,7 @@ pub const BufSet = struct {
1010 const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
1111
1212 pub fn init(a: &Allocator) BufSet {
13 var self = BufSet {
14 .hash_map = BufSetHashMap.init(a),
15 };
13 var self = BufSet{ .hash_map = BufSetHashMap.init(a) };
1614 return self;
1715 }
1816
std/build.zig+21-38
......@@ -420,15 +420,7 @@ pub const Builder = struct {
420420 const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") ?? false;
421421 const release_small = self.option(bool, "release-small", "size optimizations on and safety off") ?? false;
422422
423 const mode = if (release_safe and !release_fast and !release_small)
424 builtin.Mode.ReleaseSafe
425 else if (release_fast and !release_safe and !release_small)
426 builtin.Mode.ReleaseFast
427 else if (release_small and !release_fast and !release_safe)
428 builtin.Mode.ReleaseSmall
429 else if (!release_fast and !release_safe and !release_small)
430 builtin.Mode.Debug
431 else x: {
423 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: {
432424 warn("Multiple release modes (of -Drelease-safe, -Drelease-fast and -Drelease-small)");
433425 self.markInvalidUserInput();
434426 break :x builtin.Mode.Debug;
......@@ -649,11 +641,7 @@ pub const Builder = struct {
649641 if (builtin.environ == builtin.Environ.msvc) {
650642 return "cl.exe";
651643 } else {
652 return os.getEnvVarOwned(self.allocator, "CC") catch |err|
653 if (err == error.EnvironmentVariableNotFound)
654 ([]const u8)("cc")
655 else
656 debug.panic("Unable to get environment variable: {}", err);
644 return os.getEnvVarOwned(self.allocator, "CC") catch |err| if (err == error.EnvironmentVariableNotFound) ([]const u8)("cc") else debug.panic("Unable to get environment variable: {}", err);
657645 }
658646 }
659647
......@@ -782,8 +770,7 @@ pub const Target = union(enum) {
782770
783771 pub fn isDarwin(self: &const Target) bool {
784772 return switch (self.getOs()) {
785 builtin.Os.ios,
786 builtin.Os.macosx => true,
773 builtin.Os.ios, builtin.Os.macosx => true,
787774 else => false,
788775 };
789776 }
......@@ -990,8 +977,7 @@ pub const LibExeObjStep = struct {
990977 self.out_filename = self.builder.fmt("lib{}.a", self.name);
991978 } else {
992979 switch (self.target.getOs()) {
993 builtin.Os.ios,
994 builtin.Os.macosx => {
980 builtin.Os.ios, builtin.Os.macosx => {
995981 self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch);
996982 self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major);
997983 self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);
......@@ -1011,11 +997,13 @@ pub const LibExeObjStep = struct {
1011997 }
1012998
1013999 pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
1014 self.target = Target{ .Cross = CrossTarget{
1015 .arch = target_arch,
1016 .os = target_os,
1017 .environ = target_environ,
1018 } };
1000 self.target = Target{
1001 .Cross = CrossTarget{
1002 .arch = target_arch,
1003 .os = target_os,
1004 .environ = target_environ,
1005 },
1006 };
10191007 self.computeOutFileNames();
10201008 }
10211009
......@@ -1079,10 +1067,7 @@ pub const LibExeObjStep = struct {
10791067 }
10801068
10811069 pub fn getOutputPath(self: &LibExeObjStep) []const u8 {
1082 return if (self.output_path) |output_path|
1083 output_path
1084 else
1085 os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable;
1070 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;
10861071 }
10871072
10881073 pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) void {
......@@ -1095,10 +1080,7 @@ pub const LibExeObjStep = struct {
10951080 }
10961081
10971082 pub fn getOutputHPath(self: &LibExeObjStep) []const u8 {
1098 return if (self.output_h_path) |output_h_path|
1099 output_h_path
1100 else
1101 os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable;
1083 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;
11021084 }
11031085
11041086 pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) void {
......@@ -1352,8 +1334,7 @@ pub const LibExeObjStep = struct {
13521334 args.append("ssp-buffer-size=4") catch unreachable;
13531335 }
13541336 },
1355 builtin.Mode.ReleaseFast,
1356 builtin.Mode.ReleaseSmall => {
1337 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {
13571338 args.append("-O2") catch unreachable;
13581339 args.append("-fno-stack-protector") catch unreachable;
13591340 },
......@@ -1652,11 +1633,13 @@ pub const TestStep = struct {
16521633 }
16531634
16541635 pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
1655 self.target = Target{ .Cross = CrossTarget{
1656 .arch = target_arch,
1657 .os = target_os,
1658 .environ = target_environ,
1659 } };
1636 self.target = Target{
1637 .Cross = CrossTarget{
1638 .arch = target_arch,
1639 .os = target_os,
1640 .environ = target_environ,
1641 },
1642 };
16601643 }
16611644
16621645 pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void {
std/c/darwin.zig+1-1
......@@ -60,7 +60,7 @@ pub const sigset_t = u32;
6060
6161/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
6262pub const Sigaction = extern struct {
63 handler: extern fn(c_int)void,
63 handler: extern fn(c_int) void,
6464 sa_mask: sigset_t,
6565 sa_flags: c_int,
6666};
std/c/index.zig+4-8
......@@ -1,7 +1,7 @@
11const builtin = @import("builtin");
22const Os = builtin.Os;
33
4pub use switch(builtin.os) {
4pub use switch (builtin.os) {
55 Os.linux => @import("linux.zig"),
66 Os.windows => @import("windows.zig"),
77 Os.macosx, Os.ios => @import("darwin.zig"),
......@@ -21,8 +21,7 @@ pub extern "c" fn raise(sig: c_int) c_int;
2121pub extern "c" fn read(fd: c_int, buf: &c_void, nbyte: usize) isize;
2222pub extern "c" fn stat(noalias path: &const u8, noalias buf: &Stat) c_int;
2323pub extern "c" fn write(fd: c_int, buf: &const c_void, nbyte: usize) isize;
24pub extern "c" fn mmap(addr: ?&c_void, len: usize, prot: c_int, flags: c_int,
25 fd: c_int, offset: isize) ?&c_void;
24pub extern "c" fn mmap(addr: ?&c_void, len: usize, prot: c_int, flags: c_int, fd: c_int, offset: isize) ?&c_void;
2625pub extern "c" fn munmap(addr: &c_void, len: usize) c_int;
2726pub extern "c" fn unlink(path: &const u8) c_int;
2827pub 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;
3433pub extern "c" fn symlink(existing: &const u8, new: &const u8) c_int;
3534pub extern "c" fn rename(old: &const u8, new: &const u8) c_int;
3635pub extern "c" fn chdir(path: &const u8) c_int;
37pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8,
38 envp: &const ?&const u8) c_int;
36pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) c_int;
3937pub extern "c" fn dup(fd: c_int) c_int;
4038pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;
4139pub 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;
5452pub extern "c" fn free(&c_void) void;
5553pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) c_int;
5654
57pub extern "pthread" fn pthread_create(noalias newthread: &pthread_t,
58 noalias attr: ?&const pthread_attr_t, start_routine: extern fn(?&c_void) ?&c_void,
59 noalias arg: ?&c_void) c_int;
55pub 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;
6056pub extern "pthread" fn pthread_attr_init(attr: &pthread_attr_t) c_int;
6157pub extern "pthread" fn pthread_attr_setstack(attr: &pthread_attr_t, stackaddr: &c_void, stacksize: usize) c_int;
6258pub extern "pthread" fn pthread_attr_destroy(attr: &pthread_attr_t) c_int;
std/crypto/md5.zig+77-61
......@@ -6,12 +6,25 @@ const debug = @import("../debug/index.zig");
66const fmt = @import("../fmt/index.zig");
77
88const RoundParam = struct {
9 a: usize, b: usize, c: usize, d: usize,
10 k: usize, s: u32, t: u32
9 a: usize,
10 b: usize,
11 c: usize,
12 d: usize,
13 k: usize,
14 s: u32,
15 t: u32,
1116};
1217
1318fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundParam {
14 return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t };
19 return RoundParam{
20 .a = a,
21 .b = b,
22 .c = c,
23 .d = d,
24 .k = k,
25 .s = s,
26 .t = t,
27 };
1528}
1629
1730pub const Md5 = struct {
......@@ -99,7 +112,7 @@ pub const Md5 = struct {
99112 d.round(d.buf[0..]);
100113
101114 for (d.s) |s, j| {
102 mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Little);
115 mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Little);
103116 }
104117 }
105118
......@@ -112,30 +125,33 @@ pub const Md5 = struct {
112125 while (i < 16) : (i += 1) {
113126 // NOTE: Performing or's separately improves perf by ~10%
114127 s[i] = 0;
115 s[i] |= u32(b[i*4+0]);
116 s[i] |= u32(b[i*4+1]) << 8;
117 s[i] |= u32(b[i*4+2]) << 16;
118 s[i] |= u32(b[i*4+3]) << 24;
128 s[i] |= u32(b[i * 4 + 0]);
129 s[i] |= u32(b[i * 4 + 1]) << 8;
130 s[i] |= u32(b[i * 4 + 2]) << 16;
131 s[i] |= u32(b[i * 4 + 3]) << 24;
119132 }
120133
121 var v: [4]u32 = []u32 {
122 d.s[0], d.s[1], d.s[2], d.s[3],
134 var v: [4]u32 = []u32{
135 d.s[0],
136 d.s[1],
137 d.s[2],
138 d.s[3],
123139 };
124140
125 const round0 = comptime []RoundParam {
126 Rp(0, 1, 2, 3, 0, 7, 0xD76AA478),
127 Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756),
128 Rp(2, 3, 0, 1, 2, 17, 0x242070DB),
129 Rp(1, 2, 3, 0, 3, 22, 0xC1BDCEEE),
130 Rp(0, 1, 2, 3, 4, 7, 0xF57C0FAF),
131 Rp(3, 0, 1, 2, 5, 12, 0x4787C62A),
132 Rp(2, 3, 0, 1, 6, 17, 0xA8304613),
133 Rp(1, 2, 3, 0, 7, 22, 0xFD469501),
134 Rp(0, 1, 2, 3, 8, 7, 0x698098D8),
135 Rp(3, 0, 1, 2, 9, 12, 0x8B44F7AF),
141 const round0 = comptime []RoundParam{
142 Rp(0, 1, 2, 3, 0, 7, 0xD76AA478),
143 Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756),
144 Rp(2, 3, 0, 1, 2, 17, 0x242070DB),
145 Rp(1, 2, 3, 0, 3, 22, 0xC1BDCEEE),
146 Rp(0, 1, 2, 3, 4, 7, 0xF57C0FAF),
147 Rp(3, 0, 1, 2, 5, 12, 0x4787C62A),
148 Rp(2, 3, 0, 1, 6, 17, 0xA8304613),
149 Rp(1, 2, 3, 0, 7, 22, 0xFD469501),
150 Rp(0, 1, 2, 3, 8, 7, 0x698098D8),
151 Rp(3, 0, 1, 2, 9, 12, 0x8B44F7AF),
136152 Rp(2, 3, 0, 1, 10, 17, 0xFFFF5BB1),
137153 Rp(1, 2, 3, 0, 11, 22, 0x895CD7BE),
138 Rp(0, 1, 2, 3, 12, 7, 0x6B901122),
154 Rp(0, 1, 2, 3, 12, 7, 0x6B901122),
139155 Rp(3, 0, 1, 2, 13, 12, 0xFD987193),
140156 Rp(2, 3, 0, 1, 14, 17, 0xA679438E),
141157 Rp(1, 2, 3, 0, 15, 22, 0x49B40821),
......@@ -145,22 +161,22 @@ pub const Md5 = struct {
145161 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
146162 }
147163
148 const round1 = comptime []RoundParam {
149 Rp(0, 1, 2, 3, 1, 5, 0xF61E2562),
150 Rp(3, 0, 1, 2, 6, 9, 0xC040B340),
164 const round1 = comptime []RoundParam{
165 Rp(0, 1, 2, 3, 1, 5, 0xF61E2562),
166 Rp(3, 0, 1, 2, 6, 9, 0xC040B340),
151167 Rp(2, 3, 0, 1, 11, 14, 0x265E5A51),
152 Rp(1, 2, 3, 0, 0, 20, 0xE9B6C7AA),
153 Rp(0, 1, 2, 3, 5, 5, 0xD62F105D),
154 Rp(3, 0, 1, 2, 10, 9, 0x02441453),
168 Rp(1, 2, 3, 0, 0, 20, 0xE9B6C7AA),
169 Rp(0, 1, 2, 3, 5, 5, 0xD62F105D),
170 Rp(3, 0, 1, 2, 10, 9, 0x02441453),
155171 Rp(2, 3, 0, 1, 15, 14, 0xD8A1E681),
156 Rp(1, 2, 3, 0, 4, 20, 0xE7D3FBC8),
157 Rp(0, 1, 2, 3, 9, 5, 0x21E1CDE6),
158 Rp(3, 0, 1, 2, 14, 9, 0xC33707D6),
159 Rp(2, 3, 0, 1, 3, 14, 0xF4D50D87),
160 Rp(1, 2, 3, 0, 8, 20, 0x455A14ED),
161 Rp(0, 1, 2, 3, 13, 5, 0xA9E3E905),
162 Rp(3, 0, 1, 2, 2, 9, 0xFCEFA3F8),
163 Rp(2, 3, 0, 1, 7, 14, 0x676F02D9),
172 Rp(1, 2, 3, 0, 4, 20, 0xE7D3FBC8),
173 Rp(0, 1, 2, 3, 9, 5, 0x21E1CDE6),
174 Rp(3, 0, 1, 2, 14, 9, 0xC33707D6),
175 Rp(2, 3, 0, 1, 3, 14, 0xF4D50D87),
176 Rp(1, 2, 3, 0, 8, 20, 0x455A14ED),
177 Rp(0, 1, 2, 3, 13, 5, 0xA9E3E905),
178 Rp(3, 0, 1, 2, 2, 9, 0xFCEFA3F8),
179 Rp(2, 3, 0, 1, 7, 14, 0x676F02D9),
164180 Rp(1, 2, 3, 0, 12, 20, 0x8D2A4C8A),
165181 };
166182 inline for (round1) |r| {
......@@ -168,46 +184,46 @@ pub const Md5 = struct {
168184 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
169185 }
170186
171 const round2 = comptime []RoundParam {
172 Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942),
173 Rp(3, 0, 1, 2, 8, 11, 0x8771F681),
187 const round2 = comptime []RoundParam{
188 Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942),
189 Rp(3, 0, 1, 2, 8, 11, 0x8771F681),
174190 Rp(2, 3, 0, 1, 11, 16, 0x6D9D6122),
175191 Rp(1, 2, 3, 0, 14, 23, 0xFDE5380C),
176 Rp(0, 1, 2, 3, 1, 4, 0xA4BEEA44),
177 Rp(3, 0, 1, 2, 4, 11, 0x4BDECFA9),
178 Rp(2, 3, 0, 1, 7, 16, 0xF6BB4B60),
192 Rp(0, 1, 2, 3, 1, 4, 0xA4BEEA44),
193 Rp(3, 0, 1, 2, 4, 11, 0x4BDECFA9),
194 Rp(2, 3, 0, 1, 7, 16, 0xF6BB4B60),
179195 Rp(1, 2, 3, 0, 10, 23, 0xBEBFBC70),
180 Rp(0, 1, 2, 3, 13, 4, 0x289B7EC6),
181 Rp(3, 0, 1, 2, 0, 11, 0xEAA127FA),
182 Rp(2, 3, 0, 1, 3, 16, 0xD4EF3085),
183 Rp(1, 2, 3, 0, 6, 23, 0x04881D05),
184 Rp(0, 1, 2, 3, 9, 4, 0xD9D4D039),
196 Rp(0, 1, 2, 3, 13, 4, 0x289B7EC6),
197 Rp(3, 0, 1, 2, 0, 11, 0xEAA127FA),
198 Rp(2, 3, 0, 1, 3, 16, 0xD4EF3085),
199 Rp(1, 2, 3, 0, 6, 23, 0x04881D05),
200 Rp(0, 1, 2, 3, 9, 4, 0xD9D4D039),
185201 Rp(3, 0, 1, 2, 12, 11, 0xE6DB99E5),
186202 Rp(2, 3, 0, 1, 15, 16, 0x1FA27CF8),
187 Rp(1, 2, 3, 0, 2, 23, 0xC4AC5665),
203 Rp(1, 2, 3, 0, 2, 23, 0xC4AC5665),
188204 };
189205 inline for (round2) |r| {
190206 v[r.a] = v[r.a] +% (v[r.b] ^ v[r.c] ^ v[r.d]) +% r.t +% s[r.k];
191207 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
192208 }
193209
194 const round3 = comptime []RoundParam {
195 Rp(0, 1, 2, 3, 0, 6, 0xF4292244),
196 Rp(3, 0, 1, 2, 7, 10, 0x432AFF97),
210 const round3 = comptime []RoundParam{
211 Rp(0, 1, 2, 3, 0, 6, 0xF4292244),
212 Rp(3, 0, 1, 2, 7, 10, 0x432AFF97),
197213 Rp(2, 3, 0, 1, 14, 15, 0xAB9423A7),
198 Rp(1, 2, 3, 0, 5, 21, 0xFC93A039),
199 Rp(0, 1, 2, 3, 12, 6, 0x655B59C3),
200 Rp(3, 0, 1, 2, 3, 10, 0x8F0CCC92),
214 Rp(1, 2, 3, 0, 5, 21, 0xFC93A039),
215 Rp(0, 1, 2, 3, 12, 6, 0x655B59C3),
216 Rp(3, 0, 1, 2, 3, 10, 0x8F0CCC92),
201217 Rp(2, 3, 0, 1, 10, 15, 0xFFEFF47D),
202 Rp(1, 2, 3, 0, 1, 21, 0x85845DD1),
203 Rp(0, 1, 2, 3, 8, 6, 0x6FA87E4F),
218 Rp(1, 2, 3, 0, 1, 21, 0x85845DD1),
219 Rp(0, 1, 2, 3, 8, 6, 0x6FA87E4F),
204220 Rp(3, 0, 1, 2, 15, 10, 0xFE2CE6E0),
205 Rp(2, 3, 0, 1, 6, 15, 0xA3014314),
221 Rp(2, 3, 0, 1, 6, 15, 0xA3014314),
206222 Rp(1, 2, 3, 0, 13, 21, 0x4E0811A1),
207 Rp(0, 1, 2, 3, 4, 6, 0xF7537E82),
223 Rp(0, 1, 2, 3, 4, 6, 0xF7537E82),
208224 Rp(3, 0, 1, 2, 11, 10, 0xBD3AF235),
209 Rp(2, 3, 0, 1, 2, 15, 0x2AD7D2BB),
210 Rp(1, 2, 3, 0, 9, 21, 0xEB86D391),
225 Rp(2, 3, 0, 1, 2, 15, 0x2AD7D2BB),
226 Rp(1, 2, 3, 0, 9, 21, 0xEB86D391),
211227 };
212228 inline for (round3) |r| {
213229 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" {
255271}
256272
257273test "md5 aligned final" {
258 var block = []u8 {0} ** Md5.block_size;
274 var block = []u8{0} ** Md5.block_size;
259275 var out: [Md5.digest_size]u8 = undefined;
260276
261277 var h = Md5.init();
std/crypto/sha1.zig+47-39
......@@ -7,11 +7,23 @@ const builtin = @import("builtin");
77pub const u160 = @IntType(false, 160);
88
99const RoundParam = struct {
10 a: usize, b: usize, c: usize, d: usize, e: usize, i: u32,
10 a: usize,
11 b: usize,
12 c: usize,
13 d: usize,
14 e: usize,
15 i: u32,
1116};
1217
1318fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
14 return RoundParam { .a = a, .b = b, .c = c, .d = d, .e = e, .i = i };
19 return RoundParam{
20 .a = a,
21 .b = b,
22 .c = c,
23 .d = d,
24 .e = e,
25 .i = i,
26 };
1527}
1628
1729pub const Sha1 = struct {
......@@ -99,7 +111,7 @@ pub const Sha1 = struct {
99111 d.round(d.buf[0..]);
100112
101113 for (d.s) |s, j| {
102 mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Big);
114 mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Big);
103115 }
104116 }
105117
......@@ -108,21 +120,25 @@ pub const Sha1 = struct {
108120
109121 var s: [16]u32 = undefined;
110122
111 var v: [5]u32 = []u32 {
112 d.s[0], d.s[1], d.s[2], d.s[3], d.s[4],
123 var v: [5]u32 = []u32{
124 d.s[0],
125 d.s[1],
126 d.s[2],
127 d.s[3],
128 d.s[4],
113129 };
114130
115 const round0a = comptime []RoundParam {
116 Rp(0, 1, 2, 3, 4, 0),
117 Rp(4, 0, 1, 2, 3, 1),
118 Rp(3, 4, 0, 1, 2, 2),
119 Rp(2, 3, 4, 0, 1, 3),
120 Rp(1, 2, 3, 4, 0, 4),
121 Rp(0, 1, 2, 3, 4, 5),
122 Rp(4, 0, 1, 2, 3, 6),
123 Rp(3, 4, 0, 1, 2, 7),
124 Rp(2, 3, 4, 0, 1, 8),
125 Rp(1, 2, 3, 4, 0, 9),
131 const round0a = comptime []RoundParam{
132 Rp(0, 1, 2, 3, 4, 0),
133 Rp(4, 0, 1, 2, 3, 1),
134 Rp(3, 4, 0, 1, 2, 2),
135 Rp(2, 3, 4, 0, 1, 3),
136 Rp(1, 2, 3, 4, 0, 4),
137 Rp(0, 1, 2, 3, 4, 5),
138 Rp(4, 0, 1, 2, 3, 6),
139 Rp(3, 4, 0, 1, 2, 7),
140 Rp(2, 3, 4, 0, 1, 8),
141 Rp(1, 2, 3, 4, 0, 9),
126142 Rp(0, 1, 2, 3, 4, 10),
127143 Rp(4, 0, 1, 2, 3, 11),
128144 Rp(3, 4, 0, 1, 2, 12),
......@@ -131,32 +147,27 @@ pub const Sha1 = struct {
131147 Rp(0, 1, 2, 3, 4, 15),
132148 };
133149 inline for (round0a) |r| {
134 s[r.i] = (u32(b[r.i * 4 + 0]) << 24) |
135 (u32(b[r.i * 4 + 1]) << 16) |
136 (u32(b[r.i * 4 + 2]) << 8) |
137 (u32(b[r.i * 4 + 3]) << 0);
150 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);
138151
139 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf]
140 +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
152 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]));
141153 v[r.b] = math.rotl(u32, v[r.b], u32(30));
142154 }
143155
144 const round0b = comptime []RoundParam {
156 const round0b = comptime []RoundParam{
145157 Rp(4, 0, 1, 2, 3, 16),
146158 Rp(3, 4, 0, 1, 2, 17),
147159 Rp(2, 3, 4, 0, 1, 18),
148160 Rp(1, 2, 3, 4, 0, 19),
149161 };
150162 inline for (round0b) |r| {
151 const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf];
163 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
152164 s[r.i & 0xf] = math.rotl(u32, t, u32(1));
153165
154 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf]
155 +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
166 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]));
156167 v[r.b] = math.rotl(u32, v[r.b], u32(30));
157168 }
158169
159 const round1 = comptime []RoundParam {
170 const round1 = comptime []RoundParam{
160171 Rp(0, 1, 2, 3, 4, 20),
161172 Rp(4, 0, 1, 2, 3, 21),
162173 Rp(3, 4, 0, 1, 2, 22),
......@@ -179,15 +190,14 @@ pub const Sha1 = struct {
179190 Rp(1, 2, 3, 4, 0, 39),
180191 };
181192 inline for (round1) |r| {
182 const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf];
193 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
183194 s[r.i & 0xf] = math.rotl(u32, t, u32(1));
184195
185 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x6ED9EBA1 +% s[r.i & 0xf]
186 +% (v[r.b] ^ v[r.c] ^ v[r.d]);
196 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]);
187197 v[r.b] = math.rotl(u32, v[r.b], u32(30));
188198 }
189199
190 const round2 = comptime []RoundParam {
200 const round2 = comptime []RoundParam{
191201 Rp(0, 1, 2, 3, 4, 40),
192202 Rp(4, 0, 1, 2, 3, 41),
193203 Rp(3, 4, 0, 1, 2, 42),
......@@ -210,15 +220,14 @@ pub const Sha1 = struct {
210220 Rp(1, 2, 3, 4, 0, 59),
211221 };
212222 inline for (round2) |r| {
213 const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf];
223 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
214224 s[r.i & 0xf] = math.rotl(u32, t, u32(1));
215225
216 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x8F1BBCDC +% s[r.i & 0xf]
217 +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d]));
226 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]));
218227 v[r.b] = math.rotl(u32, v[r.b], u32(30));
219228 }
220229
221 const round3 = comptime []RoundParam {
230 const round3 = comptime []RoundParam{
222231 Rp(0, 1, 2, 3, 4, 60),
223232 Rp(4, 0, 1, 2, 3, 61),
224233 Rp(3, 4, 0, 1, 2, 62),
......@@ -241,11 +250,10 @@ pub const Sha1 = struct {
241250 Rp(1, 2, 3, 4, 0, 79),
242251 };
243252 inline for (round3) |r| {
244 const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf];
253 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
245254 s[r.i & 0xf] = math.rotl(u32, t, u32(1));
246255
247 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0xCA62C1D6 +% s[r.i & 0xf]
248 +% (v[r.b] ^ v[r.c] ^ v[r.d]);
256 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]);
249257 v[r.b] = math.rotl(u32, v[r.b], u32(30));
250258 }
251259
......@@ -286,7 +294,7 @@ test "sha1 streaming" {
286294}
287295
288296test "sha1 aligned final" {
289 var block = []u8 {0} ** Sha1.block_size;
297 var block = []u8{0} ** Sha1.block_size;
290298 var out: [Sha1.digest_size]u8 = undefined;
291299
292300 var h = Sha1.init();
std/crypto/sha2.zig+448-413
......@@ -9,12 +9,31 @@ const htest = @import("test.zig");
99// Sha224 + Sha256
1010
1111const RoundParam256 = struct {
12 a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize,
13 i: usize, k: u32,
12 a: usize,
13 b: usize,
14 c: usize,
15 d: usize,
16 e: usize,
17 f: usize,
18 g: usize,
19 h: usize,
20 i: usize,
21 k: u32,
1422};
1523
1624fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u32) RoundParam256 {
17 return RoundParam256 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k };
25 return RoundParam256{
26 .a = a,
27 .b = b,
28 .c = c,
29 .d = d,
30 .e = e,
31 .f = f,
32 .g = g,
33 .h = h,
34 .i = i,
35 .k = k,
36 };
1837}
1938
2039const Sha2Params32 = struct {
......@@ -29,7 +48,7 @@ const Sha2Params32 = struct {
2948 out_len: usize,
3049};
3150
32const Sha224Params = Sha2Params32 {
51const Sha224Params = Sha2Params32{
3352 .iv0 = 0xC1059ED8,
3453 .iv1 = 0x367CD507,
3554 .iv2 = 0x3070DD17,
......@@ -41,7 +60,7 @@ const Sha224Params = Sha2Params32 {
4160 .out_len = 224,
4261};
4362
44const Sha256Params = Sha2Params32 {
63const Sha256Params = Sha2Params32{
4564 .iv0 = 0x6A09E667,
4665 .iv1 = 0xBB67AE85,
4766 .iv2 = 0x3C6EF372,
......@@ -56,216 +75,215 @@ const Sha256Params = Sha2Params32 {
5675pub const Sha224 = Sha2_32(Sha224Params);
5776pub const Sha256 = Sha2_32(Sha256Params);
5877
59fn Sha2_32(comptime params: Sha2Params32) type { return struct {
60 const Self = this;
61 const block_size = 64;
62 const digest_size = params.out_len / 8;
63
64 s: [8]u32,
65 // Streaming Cache
66 buf: [64]u8,
67 buf_len: u8,
68 total_len: u64,
69
70 pub fn init() Self {
71 var d: Self = undefined;
72 d.reset();
73 return d;
74 }
75
76 pub fn reset(d: &Self) void {
77 d.s[0] = params.iv0;
78 d.s[1] = params.iv1;
79 d.s[2] = params.iv2;
80 d.s[3] = params.iv3;
81 d.s[4] = params.iv4;
82 d.s[5] = params.iv5;
83 d.s[6] = params.iv6;
84 d.s[7] = params.iv7;
85 d.buf_len = 0;
86 d.total_len = 0;
87 }
88
89 pub fn hash(b: []const u8, out: []u8) void {
90 var d = Self.init();
91 d.update(b);
92 d.final(out);
93 }
94
95 pub fn update(d: &Self, b: []const u8) void {
96 var off: usize = 0;
97
98 // Partial buffer exists from previous update. Copy into buffer then hash.
99 if (d.buf_len != 0 and d.buf_len + b.len > 64) {
100 off += 64 - d.buf_len;
101 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
78fn Sha2_32(comptime params: Sha2Params32) type {
79 return struct {
80 const Self = this;
81 const block_size = 64;
82 const digest_size = params.out_len / 8;
83
84 s: [8]u32,
85 // Streaming Cache
86 buf: [64]u8,
87 buf_len: u8,
88 total_len: u64,
89
90 pub fn init() Self {
91 var d: Self = undefined;
92 d.reset();
93 return d;
94 }
10295
103 d.round(d.buf[0..]);
96 pub fn reset(d: &Self) void {
97 d.s[0] = params.iv0;
98 d.s[1] = params.iv1;
99 d.s[2] = params.iv2;
100 d.s[3] = params.iv3;
101 d.s[4] = params.iv4;
102 d.s[5] = params.iv5;
103 d.s[6] = params.iv6;
104 d.s[7] = params.iv7;
104105 d.buf_len = 0;
106 d.total_len = 0;
105107 }
106108
107 // Full middle blocks.
108 while (off + 64 <= b.len) : (off += 64) {
109 d.round(b[off..off + 64]);
109 pub fn hash(b: []const u8, out: []u8) void {
110 var d = Self.init();
111 d.update(b);
112 d.final(out);
110113 }
111114
112 // Copy any remainder for next pass.
113 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
114 d.buf_len += u8(b[off..].len);
115 pub fn update(d: &Self, b: []const u8) void {
116 var off: usize = 0;
115117
116 d.total_len += b.len;
117 }
118 // Partial buffer exists from previous update. Copy into buffer then hash.
119 if (d.buf_len != 0 and d.buf_len + b.len > 64) {
120 off += 64 - d.buf_len;
121 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
118122
119 pub fn final(d: &Self, out: []u8) void {
120 debug.assert(out.len >= params.out_len / 8);
123 d.round(d.buf[0..]);
124 d.buf_len = 0;
125 }
121126
122 // The buffer here will never be completely full.
123 mem.set(u8, d.buf[d.buf_len..], 0);
127 // Full middle blocks.
128 while (off + 64 <= b.len) : (off += 64) {
129 d.round(b[off..off + 64]);
130 }
124131
125 // Append padding bits.
126 d.buf[d.buf_len] = 0x80;
127 d.buf_len += 1;
132 // Copy any remainder for next pass.
133 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
134 d.buf_len += u8(b[off..].len);
128135
129 // > 448 mod 512 so need to add an extra round to wrap around.
130 if (64 - d.buf_len < 8) {
131 d.round(d.buf[0..]);
132 mem.set(u8, d.buf[0..], 0);
136 d.total_len += b.len;
133137 }
134138
135 // Append message length.
136 var i: usize = 1;
137 var len = d.total_len >> 5;
138 d.buf[63] = u8(d.total_len & 0x1f) << 3;
139 while (i < 8) : (i += 1) {
140 d.buf[63 - i] = u8(len & 0xff);
141 len >>= 8;
142 }
139 pub fn final(d: &Self, out: []u8) void {
140 debug.assert(out.len >= params.out_len / 8);
143141
144 d.round(d.buf[0..]);
142 // The buffer here will never be completely full.
143 mem.set(u8, d.buf[d.buf_len..], 0);
145144
146 // May truncate for possible 224 output
147 const rr = d.s[0 .. params.out_len / 32];
145 // Append padding bits.
146 d.buf[d.buf_len] = 0x80;
147 d.buf_len += 1;
148148
149 for (rr) |s, j| {
150 mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Big);
151 }
152 }
149 // > 448 mod 512 so need to add an extra round to wrap around.
150 if (64 - d.buf_len < 8) {
151 d.round(d.buf[0..]);
152 mem.set(u8, d.buf[0..], 0);
153 }
154
155 // Append message length.
156 var i: usize = 1;
157 var len = d.total_len >> 5;
158 d.buf[63] = u8(d.total_len & 0x1f) << 3;
159 while (i < 8) : (i += 1) {
160 d.buf[63 - i] = u8(len & 0xff);
161 len >>= 8;
162 }
153163
154 fn round(d: &Self, b: []const u8) void {
155 debug.assert(b.len == 64);
164 d.round(d.buf[0..]);
156165
157 var s: [64]u32 = undefined;
166 // May truncate for possible 224 output
167 const rr = d.s[0..params.out_len / 32];
158168
159 var i: usize = 0;
160 while (i < 16) : (i += 1) {
161 s[i] = 0;
162 s[i] |= u32(b[i*4+0]) << 24;
163 s[i] |= u32(b[i*4+1]) << 16;
164 s[i] |= u32(b[i*4+2]) << 8;
165 s[i] |= u32(b[i*4+3]) << 0;
166 }
167 while (i < 64) : (i += 1) {
168 s[i] =
169 s[i-16] +% s[i-7] +%
170 (math.rotr(u32, s[i-15], u32(7)) ^ math.rotr(u32, s[i-15], u32(18)) ^ (s[i-15] >> 3)) +%
171 (math.rotr(u32, s[i-2], u32(17)) ^ math.rotr(u32, s[i-2], u32(19)) ^ (s[i-2] >> 10));
169 for (rr) |s, j| {
170 mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Big);
171 }
172172 }
173173
174 var v: [8]u32 = []u32 {
175 d.s[0], d.s[1], d.s[2], d.s[3], d.s[4], d.s[5], d.s[6], d.s[7],
176 };
177
178 const round0 = comptime []RoundParam256 {
179 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98),
180 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491),
181 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF),
182 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA5),
183 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25B),
184 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1),
185 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4),
186 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5),
187 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98),
188 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B01),
189 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE),
190 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3),
191 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74),
192 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE),
193 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A7),
194 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174),
195 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C1),
196 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786),
197 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC6),
198 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC),
199 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F),
200 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA),
201 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DC),
202 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA),
203 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152),
204 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D),
205 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C8),
206 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7),
207 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF3),
208 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147),
209 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351),
210 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x14292967),
211 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A85),
212 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B2138),
213 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC),
214 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D13),
215 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A7354),
216 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB),
217 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E),
218 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C85),
219 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A1),
220 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664B),
221 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70),
222 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A3),
223 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819),
224 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD6990624),
225 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E3585),
226 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA070),
227 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116),
228 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C08),
229 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774C),
230 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5),
231 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3),
232 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4A),
233 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F),
234 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3),
235 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE),
236 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F),
237 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814),
238 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC70208),
239 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA),
240 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEB),
241 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7),
242 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2),
243 };
244 inline for (round0) |r| {
245 v[r.h] =
246 v[r.h] +%
247 (math.rotr(u32, v[r.e], u32(6)) ^ math.rotr(u32, v[r.e], u32(11)) ^ math.rotr(u32, v[r.e], u32(25))) +%
248 (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +%
249 r.k +% s[r.i];
250
251 v[r.d] = v[r.d] +% v[r.h];
252
253 v[r.h] =
254 v[r.h] +%
255 (math.rotr(u32, v[r.a], u32(2)) ^ math.rotr(u32, v[r.a], u32(13)) ^ math.rotr(u32, v[r.a], u32(22))) +%
256 ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c]));
174 fn round(d: &Self, b: []const u8) void {
175 debug.assert(b.len == 64);
176
177 var s: [64]u32 = undefined;
178
179 var i: usize = 0;
180 while (i < 16) : (i += 1) {
181 s[i] = 0;
182 s[i] |= u32(b[i * 4 + 0]) << 24;
183 s[i] |= u32(b[i * 4 + 1]) << 16;
184 s[i] |= u32(b[i * 4 + 2]) << 8;
185 s[i] |= u32(b[i * 4 + 3]) << 0;
186 }
187 while (i < 64) : (i += 1) {
188 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));
189 }
190
191 var v: [8]u32 = []u32{
192 d.s[0],
193 d.s[1],
194 d.s[2],
195 d.s[3],
196 d.s[4],
197 d.s[5],
198 d.s[6],
199 d.s[7],
200 };
201
202 const round0 = comptime []RoundParam256{
203 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98),
204 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491),
205 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF),
206 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA5),
207 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25B),
208 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1),
209 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4),
210 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5),
211 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98),
212 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B01),
213 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE),
214 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3),
215 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74),
216 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE),
217 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A7),
218 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174),
219 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C1),
220 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786),
221 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC6),
222 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC),
223 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F),
224 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA),
225 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DC),
226 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA),
227 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152),
228 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D),
229 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C8),
230 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7),
231 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF3),
232 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147),
233 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351),
234 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x14292967),
235 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A85),
236 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B2138),
237 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC),
238 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D13),
239 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A7354),
240 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB),
241 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E),
242 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C85),
243 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A1),
244 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664B),
245 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70),
246 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A3),
247 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819),
248 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD6990624),
249 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E3585),
250 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA070),
251 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116),
252 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C08),
253 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774C),
254 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5),
255 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3),
256 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4A),
257 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F),
258 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3),
259 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE),
260 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F),
261 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814),
262 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC70208),
263 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA),
264 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEB),
265 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7),
266 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2),
267 };
268 inline for (round0) |r| {
269 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];
270
271 v[r.d] = v[r.d] +% v[r.h];
272
273 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]));
274 }
275
276 d.s[0] +%= v[0];
277 d.s[1] +%= v[1];
278 d.s[2] +%= v[2];
279 d.s[3] +%= v[3];
280 d.s[4] +%= v[4];
281 d.s[5] +%= v[5];
282 d.s[6] +%= v[6];
283 d.s[7] +%= v[7];
257284 }
258
259 d.s[0] +%= v[0];
260 d.s[1] +%= v[1];
261 d.s[2] +%= v[2];
262 d.s[3] +%= v[3];
263 d.s[4] +%= v[4];
264 d.s[5] +%= v[5];
265 d.s[6] +%= v[6];
266 d.s[7] +%= v[7];
267 }
268};}
285 };
286}
269287
270288test "sha224 single" {
271289 htest.assertEqualHash(Sha224, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", "");
......@@ -320,7 +338,7 @@ test "sha256 streaming" {
320338}
321339
322340test "sha256 aligned final" {
323 var block = []u8 {0} ** Sha256.block_size;
341 var block = []u8{0} ** Sha256.block_size;
324342 var out: [Sha256.digest_size]u8 = undefined;
325343
326344 var h = Sha256.init();
......@@ -328,17 +346,35 @@ test "sha256 aligned final" {
328346 h.final(out[0..]);
329347}
330348
331
332349/////////////////////
333350// Sha384 + Sha512
334351
335352const RoundParam512 = struct {
336 a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize,
337 i: usize, k: u64,
353 a: usize,
354 b: usize,
355 c: usize,
356 d: usize,
357 e: usize,
358 f: usize,
359 g: usize,
360 h: usize,
361 i: usize,
362 k: u64,
338363};
339364
340365fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) RoundParam512 {
341 return RoundParam512 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k };
366 return RoundParam512{
367 .a = a,
368 .b = b,
369 .c = c,
370 .d = d,
371 .e = e,
372 .f = f,
373 .g = g,
374 .h = h,
375 .i = i,
376 .k = k,
377 };
342378}
343379
344380const Sha2Params64 = struct {
......@@ -353,7 +389,7 @@ const Sha2Params64 = struct {
353389 out_len: usize,
354390};
355391
356const Sha384Params = Sha2Params64 {
392const Sha384Params = Sha2Params64{
357393 .iv0 = 0xCBBB9D5DC1059ED8,
358394 .iv1 = 0x629A292A367CD507,
359395 .iv2 = 0x9159015A3070DD17,
......@@ -365,7 +401,7 @@ const Sha384Params = Sha2Params64 {
365401 .out_len = 384,
366402};
367403
368const Sha512Params = Sha2Params64 {
404const Sha512Params = Sha2Params64{
369405 .iv0 = 0x6A09E667F3BCC908,
370406 .iv1 = 0xBB67AE8584CAA73B,
371407 .iv2 = 0x3C6EF372FE94F82B,
......@@ -374,242 +410,241 @@ const Sha512Params = Sha2Params64 {
374410 .iv5 = 0x9B05688C2B3E6C1F,
375411 .iv6 = 0x1F83D9ABFB41BD6B,
376412 .iv7 = 0x5BE0CD19137E2179,
377 .out_len = 512
413 .out_len = 512,
378414};
379415
380416pub const Sha384 = Sha2_64(Sha384Params);
381417pub const Sha512 = Sha2_64(Sha512Params);
382418
383fn Sha2_64(comptime params: Sha2Params64) type { return struct {
384 const Self = this;
385 const block_size = 128;
386 const digest_size = params.out_len / 8;
387
388 s: [8]u64,
389 // Streaming Cache
390 buf: [128]u8,
391 buf_len: u8,
392 total_len: u128,
393
394 pub fn init() Self {
395 var d: Self = undefined;
396 d.reset();
397 return d;
398 }
399
400 pub fn reset(d: &Self) void {
401 d.s[0] = params.iv0;
402 d.s[1] = params.iv1;
403 d.s[2] = params.iv2;
404 d.s[3] = params.iv3;
405 d.s[4] = params.iv4;
406 d.s[5] = params.iv5;
407 d.s[6] = params.iv6;
408 d.s[7] = params.iv7;
409 d.buf_len = 0;
410 d.total_len = 0;
411 }
412
413 pub fn hash(b: []const u8, out: []u8) void {
414 var d = Self.init();
415 d.update(b);
416 d.final(out);
417 }
418
419 pub fn update(d: &Self, b: []const u8) void {
420 var off: usize = 0;
421
422 // Partial buffer exists from previous update. Copy into buffer then hash.
423 if (d.buf_len != 0 and d.buf_len + b.len > 128) {
424 off += 128 - d.buf_len;
425 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
419fn Sha2_64(comptime params: Sha2Params64) type {
420 return struct {
421 const Self = this;
422 const block_size = 128;
423 const digest_size = params.out_len / 8;
424
425 s: [8]u64,
426 // Streaming Cache
427 buf: [128]u8,
428 buf_len: u8,
429 total_len: u128,
430
431 pub fn init() Self {
432 var d: Self = undefined;
433 d.reset();
434 return d;
435 }
426436
427 d.round(d.buf[0..]);
437 pub fn reset(d: &Self) void {
438 d.s[0] = params.iv0;
439 d.s[1] = params.iv1;
440 d.s[2] = params.iv2;
441 d.s[3] = params.iv3;
442 d.s[4] = params.iv4;
443 d.s[5] = params.iv5;
444 d.s[6] = params.iv6;
445 d.s[7] = params.iv7;
428446 d.buf_len = 0;
447 d.total_len = 0;
429448 }
430449
431 // Full middle blocks.
432 while (off + 128 <= b.len) : (off += 128) {
433 d.round(b[off..off + 128]);
450 pub fn hash(b: []const u8, out: []u8) void {
451 var d = Self.init();
452 d.update(b);
453 d.final(out);
434454 }
435455
436 // Copy any remainder for next pass.
437 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
438 d.buf_len += u8(b[off..].len);
456 pub fn update(d: &Self, b: []const u8) void {
457 var off: usize = 0;
439458
440 d.total_len += b.len;
441 }
459 // Partial buffer exists from previous update. Copy into buffer then hash.
460 if (d.buf_len != 0 and d.buf_len + b.len > 128) {
461 off += 128 - d.buf_len;
462 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
442463
443 pub fn final(d: &Self, out: []u8) void {
444 debug.assert(out.len >= params.out_len / 8);
464 d.round(d.buf[0..]);
465 d.buf_len = 0;
466 }
445467
446 // The buffer here will never be completely full.
447 mem.set(u8, d.buf[d.buf_len..], 0);
468 // Full middle blocks.
469 while (off + 128 <= b.len) : (off += 128) {
470 d.round(b[off..off + 128]);
471 }
448472
449 // Append padding bits.
450 d.buf[d.buf_len] = 0x80;
451 d.buf_len += 1;
473 // Copy any remainder for next pass.
474 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
475 d.buf_len += u8(b[off..].len);
452476
453 // > 896 mod 1024 so need to add an extra round to wrap around.
454 if (128 - d.buf_len < 16) {
455 d.round(d.buf[0..]);
456 mem.set(u8, d.buf[0..], 0);
477 d.total_len += b.len;
457478 }
458479
459 // Append message length.
460 var i: usize = 1;
461 var len = d.total_len >> 5;
462 d.buf[127] = u8(d.total_len & 0x1f) << 3;
463 while (i < 16) : (i += 1) {
464 d.buf[127 - i] = u8(len & 0xff);
465 len >>= 8;
466 }
480 pub fn final(d: &Self, out: []u8) void {
481 debug.assert(out.len >= params.out_len / 8);
467482
468 d.round(d.buf[0..]);
483 // The buffer here will never be completely full.
484 mem.set(u8, d.buf[d.buf_len..], 0);
469485
470 // May truncate for possible 384 output
471 const rr = d.s[0 .. params.out_len / 64];
486 // Append padding bits.
487 d.buf[d.buf_len] = 0x80;
488 d.buf_len += 1;
472489
473 for (rr) |s, j| {
474 mem.writeInt(out[8*j .. 8*j + 8], s, builtin.Endian.Big);
475 }
476 }
477
478 fn round(d: &Self, b: []const u8) void {
479 debug.assert(b.len == 128);
480
481 var s: [80]u64 = undefined;
482
483 var i: usize = 0;
484 while (i < 16) : (i += 1) {
485 s[i] = 0;
486 s[i] |= u64(b[i*8+0]) << 56;
487 s[i] |= u64(b[i*8+1]) << 48;
488 s[i] |= u64(b[i*8+2]) << 40;
489 s[i] |= u64(b[i*8+3]) << 32;
490 s[i] |= u64(b[i*8+4]) << 24;
491 s[i] |= u64(b[i*8+5]) << 16;
492 s[i] |= u64(b[i*8+6]) << 8;
493 s[i] |= u64(b[i*8+7]) << 0;
494 }
495 while (i < 80) : (i += 1) {
496 s[i] =
497 s[i-16] +% s[i-7] +%
498 (math.rotr(u64, s[i-15], u64(1)) ^ math.rotr(u64, s[i-15], u64(8)) ^ (s[i-15] >> 7)) +%
499 (math.rotr(u64, s[i-2], u64(19)) ^ math.rotr(u64, s[i-2], u64(61)) ^ (s[i-2] >> 6));
500 }
490 // > 896 mod 1024 so need to add an extra round to wrap around.
491 if (128 - d.buf_len < 16) {
492 d.round(d.buf[0..]);
493 mem.set(u8, d.buf[0..], 0);
494 }
501495
502 var v: [8]u64 = []u64 {
503 d.s[0], d.s[1], d.s[2], d.s[3], d.s[4], d.s[5], d.s[6], d.s[7],
504 };
505
506 const round0 = comptime []RoundParam512 {
507 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22),
508 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x7137449123EF65CD),
509 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCFEC4D3B2F),
510 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA58189DBBC),
511 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25BF348B538),
512 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1B605D019),
513 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4AF194F9B),
514 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5DA6D8118),
515 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98A3030242),
516 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B0145706FBE),
517 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE4EE4B28C),
518 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3D5FFB4E2),
519 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74F27B896F),
520 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE3B1696B1),
521 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A725C71235),
522 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174CF692694),
523 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C19EF14AD2),
524 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786384F25E3),
525 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC68B8CD5B5),
526 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC77AC9C65),
527 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F592B0275),
528 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA6EA6E483),
529 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DCBD41FBD4),
530 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA831153B5),
531 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152EE66DFAB),
532 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D2DB43210),
533 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C898FB213F),
534 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7BEEF0EE4),
535 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF33DA88FC2),
536 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147930AA725),
537 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351E003826F),
538 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x142929670A0E6E70),
539 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A8546D22FFC),
540 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B21385C26C926),
541 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC5AC42AED),
542 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D139D95B3DF),
543 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A73548BAF63DE),
544 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB3C77B2A8),
545 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E47EDAEE6),
546 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C851482353B),
547 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A14CF10364),
548 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664BBC423001),
549 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70D0F89791),
550 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A30654BE30),
551 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819D6EF5218),
552 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD69906245565A910),
553 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E35855771202A),
554 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA07032BBD1B8),
555 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116B8D2D0C8),
556 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C085141AB53),
557 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774CDF8EEB99),
558 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5E19B48A8),
559 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3C5C95A63),
560 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4AE3418ACB),
561 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F7763E373),
562 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3D6B2B8A3),
563 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE5DEFB2FC),
564 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F43172F60),
565 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814A1F0AB72),
566 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC702081A6439EC),
567 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA23631E28),
568 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEBDE82BDE9),
569 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7B2C67915),
570 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2E372532B),
571 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 64, 0xCA273ECEEA26619C),
572 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 65, 0xD186B8C721C0C207),
573 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 66, 0xEADA7DD6CDE0EB1E),
574 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 67, 0xF57D4F7FEE6ED178),
575 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 68, 0x06F067AA72176FBA),
576 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 69, 0x0A637DC5A2C898A6),
577 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 70, 0x113F9804BEF90DAE),
578 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 71, 0x1B710B35131C471B),
579 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 72, 0x28DB77F523047D84),
580 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 73, 0x32CAAB7B40C72493),
581 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 74, 0x3C9EBE0A15C9BEBC),
582 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 75, 0x431D67C49C100D4C),
583 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 76, 0x4CC5D4BECB3E42B6),
584 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 77, 0x597F299CFC657E2A),
585 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 78, 0x5FCB6FAB3AD6FAEC),
586 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 79, 0x6C44198C4A475817),
587 };
588 inline for (round0) |r| {
589 v[r.h] =
590 v[r.h] +%
591 (math.rotr(u64, v[r.e], u64(14)) ^ math.rotr(u64, v[r.e], u64(18)) ^ math.rotr(u64, v[r.e], u64(41))) +%
592 (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +%
593 r.k +% s[r.i];
594
595 v[r.d] = v[r.d] +% v[r.h];
596
597 v[r.h] =
598 v[r.h] +%
599 (math.rotr(u64, v[r.a], u64(28)) ^ math.rotr(u64, v[r.a], u64(34)) ^ math.rotr(u64, v[r.a], u64(39))) +%
600 ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c]));
496 // Append message length.
497 var i: usize = 1;
498 var len = d.total_len >> 5;
499 d.buf[127] = u8(d.total_len & 0x1f) << 3;
500 while (i < 16) : (i += 1) {
501 d.buf[127 - i] = u8(len & 0xff);
502 len >>= 8;
503 }
504
505 d.round(d.buf[0..]);
506
507 // May truncate for possible 384 output
508 const rr = d.s[0..params.out_len / 64];
509
510 for (rr) |s, j| {
511 mem.writeInt(out[8 * j..8 * j + 8], s, builtin.Endian.Big);
512 }
601513 }
602514
603 d.s[0] +%= v[0];
604 d.s[1] +%= v[1];
605 d.s[2] +%= v[2];
606 d.s[3] +%= v[3];
607 d.s[4] +%= v[4];
608 d.s[5] +%= v[5];
609 d.s[6] +%= v[6];
610 d.s[7] +%= v[7];
611 }
612};}
515 fn round(d: &Self, b: []const u8) void {
516 debug.assert(b.len == 128);
517
518 var s: [80]u64 = undefined;
519
520 var i: usize = 0;
521 while (i < 16) : (i += 1) {
522 s[i] = 0;
523 s[i] |= u64(b[i * 8 + 0]) << 56;
524 s[i] |= u64(b[i * 8 + 1]) << 48;
525 s[i] |= u64(b[i * 8 + 2]) << 40;
526 s[i] |= u64(b[i * 8 + 3]) << 32;
527 s[i] |= u64(b[i * 8 + 4]) << 24;
528 s[i] |= u64(b[i * 8 + 5]) << 16;
529 s[i] |= u64(b[i * 8 + 6]) << 8;
530 s[i] |= u64(b[i * 8 + 7]) << 0;
531 }
532 while (i < 80) : (i += 1) {
533 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));
534 }
535
536 var v: [8]u64 = []u64{
537 d.s[0],
538 d.s[1],
539 d.s[2],
540 d.s[3],
541 d.s[4],
542 d.s[5],
543 d.s[6],
544 d.s[7],
545 };
546
547 const round0 = comptime []RoundParam512{
548 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22),
549 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x7137449123EF65CD),
550 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCFEC4D3B2F),
551 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA58189DBBC),
552 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25BF348B538),
553 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1B605D019),
554 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4AF194F9B),
555 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5DA6D8118),
556 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98A3030242),
557 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B0145706FBE),
558 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE4EE4B28C),
559 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3D5FFB4E2),
560 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74F27B896F),
561 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE3B1696B1),
562 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A725C71235),
563 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174CF692694),
564 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C19EF14AD2),
565 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786384F25E3),
566 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC68B8CD5B5),
567 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC77AC9C65),
568 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F592B0275),
569 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA6EA6E483),
570 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DCBD41FBD4),
571 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA831153B5),
572 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152EE66DFAB),
573 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D2DB43210),
574 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C898FB213F),
575 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7BEEF0EE4),
576 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF33DA88FC2),
577 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147930AA725),
578 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351E003826F),
579 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x142929670A0E6E70),
580 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A8546D22FFC),
581 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B21385C26C926),
582 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC5AC42AED),
583 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D139D95B3DF),
584 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A73548BAF63DE),
585 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB3C77B2A8),
586 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E47EDAEE6),
587 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C851482353B),
588 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A14CF10364),
589 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664BBC423001),
590 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70D0F89791),
591 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A30654BE30),
592 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819D6EF5218),
593 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD69906245565A910),
594 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E35855771202A),
595 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA07032BBD1B8),
596 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116B8D2D0C8),
597 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C085141AB53),
598 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774CDF8EEB99),
599 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5E19B48A8),
600 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3C5C95A63),
601 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4AE3418ACB),
602 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F7763E373),
603 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3D6B2B8A3),
604 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE5DEFB2FC),
605 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F43172F60),
606 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814A1F0AB72),
607 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC702081A6439EC),
608 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA23631E28),
609 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEBDE82BDE9),
610 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7B2C67915),
611 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2E372532B),
612 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 64, 0xCA273ECEEA26619C),
613 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 65, 0xD186B8C721C0C207),
614 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 66, 0xEADA7DD6CDE0EB1E),
615 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 67, 0xF57D4F7FEE6ED178),
616 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 68, 0x06F067AA72176FBA),
617 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 69, 0x0A637DC5A2C898A6),
618 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 70, 0x113F9804BEF90DAE),
619 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 71, 0x1B710B35131C471B),
620 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 72, 0x28DB77F523047D84),
621 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 73, 0x32CAAB7B40C72493),
622 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 74, 0x3C9EBE0A15C9BEBC),
623 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 75, 0x431D67C49C100D4C),
624 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 76, 0x4CC5D4BECB3E42B6),
625 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 77, 0x597F299CFC657E2A),
626 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 78, 0x5FCB6FAB3AD6FAEC),
627 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 79, 0x6C44198C4A475817),
628 };
629 inline for (round0) |r| {
630 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];
631
632 v[r.d] = v[r.d] +% v[r.h];
633
634 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]));
635 }
636
637 d.s[0] +%= v[0];
638 d.s[1] +%= v[1];
639 d.s[2] +%= v[2];
640 d.s[3] +%= v[3];
641 d.s[4] +%= v[4];
642 d.s[5] +%= v[5];
643 d.s[6] +%= v[6];
644 d.s[7] +%= v[7];
645 }
646 };
647}
613648
614649test "sha384 single" {
615650 const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";
......@@ -680,7 +715,7 @@ test "sha512 streaming" {
680715}
681716
682717test "sha512 aligned final" {
683 var block = []u8 {0} ** Sha512.block_size;
718 var block = []u8{0} ** Sha512.block_size;
684719 var out: [Sha512.digest_size]u8 = undefined;
685720
686721 var h = Sha512.init();
std/crypto/test.zig+1-1
......@@ -14,7 +14,7 @@ pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, inpu
1414pub fn assertEqual(comptime expected: []const u8, input: []const u8) void {
1515 var expected_bytes: [expected.len / 2]u8 = undefined;
1616 for (expected_bytes) |*r, i| {
17 r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable;
17 r.* = fmt.parseInt(u8, expected[2 * i..2 * i + 2], 16) catch unreachable;
1818 }
1919
2020 debug.assert(mem.eql(u8, expected_bytes, input));
std/crypto/throughput_test.zig+1-1
......@@ -11,7 +11,7 @@ const Timer = time.Timer;
1111const HashFunction = @import("md5.zig").Md5;
1212
1313const MiB = 1024 * 1024;
14const BytesToHash = 1024 * MiB;
14const BytesToHash = 1024 * MiB;
1515
1616pub fn main() !void {
1717 var stdout_file = try std.io.getStdOut();
std/cstr.zig+1-3
......@@ -9,7 +9,6 @@ pub const line_sep = switch (builtin.os) {
99 else => "\n",
1010};
1111
12
1312pub fn len(ptr: &const u8) usize {
1413 var count: usize = 0;
1514 while (ptr[count] != 0) : (count += 1) {}
......@@ -95,7 +94,7 @@ pub const NullTerminated2DArray = struct {
9594 }
9695 index_buf[i] = null;
9796
98 return NullTerminated2DArray {
97 return NullTerminated2DArray{
9998 .allocator = allocator,
10099 .byte_count = byte_count,
101100 .ptr = @ptrCast(?&?&u8, buf.ptr),
......@@ -107,4 +106,3 @@ pub const NullTerminated2DArray = struct {
107106 self.allocator.free(buf[0..self.byte_count]);
108107 }
109108};
110
std/debug/failing_allocator.zig+2-2
......@@ -13,14 +13,14 @@ pub const FailingAllocator = struct {
1313 deallocations: usize,
1414
1515 pub fn init(allocator: &mem.Allocator, fail_index: usize) FailingAllocator {
16 return FailingAllocator {
16 return FailingAllocator{
1717 .internal_allocator = allocator,
1818 .fail_index = fail_index,
1919 .index = 0,
2020 .allocated_bytes = 0,
2121 .freed_bytes = 0,
2222 .deallocations = 0,
23 .allocator = mem.Allocator {
23 .allocator = mem.Allocator{
2424 .allocFn = alloc,
2525 .reallocFn = realloc,
2626 .freeFn = free,
std/debug/index.zig+9-9
......@@ -227,8 +227,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us
227227 else => return err,
228228 }
229229 } else |err| switch (err) {
230 error.MissingDebugInfo,
231 error.InvalidDebugInfo => {
230 error.MissingDebugInfo, error.InvalidDebugInfo => {
232231 try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name);
233232 },
234233 else => return err,
......@@ -597,10 +596,12 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !
597596}
598597
599598fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue {
600 return FormValue{ .Const = Constant{
601 .signed = signed,
602 .payload = try readAllocBytes(allocator, in_stream, size),
603 } };
599 return FormValue{
600 .Const = Constant{
601 .signed = signed,
602 .payload = try readAllocBytes(allocator, in_stream, size),
603 },
604 };
604605}
605606
606607fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
......@@ -621,7 +622,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: var, comptime T: type
621622 return parseFormValueRefLen(allocator, in_stream, block_len);
622623}
623624
624const ParseFormValueError = error {
625const ParseFormValueError = error{
625626 EndOfStream,
626627 Io,
627628 BadFd,
......@@ -645,8 +646,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64
645646 DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2),
646647 DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),
647648 DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),
648 DW.FORM_udata,
649 DW.FORM_sdata => {
649 DW.FORM_udata, DW.FORM_sdata => {
650650 const block_len = try readULeb128(in_stream);
651651 const signed = form_id == DW.FORM_sdata;
652652 return parseFormValueConstant(allocator, in_stream, signed, block_len);
std/dwarf.zig-2
......@@ -337,7 +337,6 @@ pub const AT_PGI_lbase = 0x3a00;
337337pub const AT_PGI_soffset = 0x3a01;
338338pub const AT_PGI_lstride = 0x3a02;
339339
340
341340pub const OP_addr = 0x03;
342341pub const OP_deref = 0x06;
343342pub const OP_const1u = 0x08;
......@@ -577,7 +576,6 @@ pub const ATE_HP_unsigned_fixed = 0x8e; // Cobol.
577576pub const ATE_HP_VAX_complex_float = 0x8f; // F or G floating complex.
578577pub const ATE_HP_VAX_complex_float_d = 0x90; // D floating complex.
579578
580
581579pub const CFA_advance_loc = 0x40;
582580pub const CFA_offset = 0x80;
583581pub const CFA_restore = 0xc0;
std/elf.zig+17-25
......@@ -123,13 +123,11 @@ pub const DT_SYMINFO = 0x6ffffeff;
123123pub const DT_ADDRRNGHI = 0x6ffffeff;
124124pub const DT_ADDRNUM = 11;
125125
126
127126pub const DT_VERSYM = 0x6ffffff0;
128127
129128pub const DT_RELACOUNT = 0x6ffffff9;
130129pub const DT_RELCOUNT = 0x6ffffffa;
131130
132
133131pub const DT_FLAGS_1 = 0x6ffffffb;
134132pub const DT_VERDEF = 0x6ffffffc;
135133
......@@ -139,13 +137,10 @@ pub const DT_VERNEED = 0x6ffffffe;
139137pub const DT_VERNEEDNUM = 0x6fffffff;
140138pub const DT_VERSIONTAGNUM = 16;
141139
142
143
144140pub const DT_AUXILIARY = 0x7ffffffd;
145141pub const DT_FILTER = 0x7fffffff;
146142pub const DT_EXTRANUM = 3;
147143
148
149144pub const DT_SPARC_REGISTER = 0x70000001;
150145pub const DT_SPARC_NUM = 2;
151146
......@@ -434,9 +429,7 @@ pub const Elf = struct {
434429 try elf.in_file.seekForward(4);
435430
436431 const header_size = try in.readInt(elf.endian, u16);
437 if ((elf.is_64 and header_size != 64) or
438 (!elf.is_64 and header_size != 52))
439 {
432 if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
440433 return error.InvalidFormat;
441434 }
442435
......@@ -467,16 +460,16 @@ pub const Elf = struct {
467460 if (sh_entry_size != 64) return error.InvalidFormat;
468461
469462 for (elf.section_headers) |*elf_section| {
470 elf_section.name = try in.readInt(elf.endian, u32);
471 elf_section.sh_type = try in.readInt(elf.endian, u32);
472 elf_section.flags = try in.readInt(elf.endian, u64);
473 elf_section.addr = try in.readInt(elf.endian, u64);
474 elf_section.offset = try in.readInt(elf.endian, u64);
475 elf_section.size = try in.readInt(elf.endian, u64);
476 elf_section.link = try in.readInt(elf.endian, u32);
477 elf_section.info = try in.readInt(elf.endian, u32);
478 elf_section.addr_align = try in.readInt(elf.endian, u64);
479 elf_section.ent_size = try in.readInt(elf.endian, u64);
463 elf_section.name = try in.readInt(elf.endian, u32);
464 elf_section.sh_type = try in.readInt(elf.endian, u32);
465 elf_section.flags = try in.readInt(elf.endian, u64);
466 elf_section.addr = try in.readInt(elf.endian, u64);
467 elf_section.offset = try in.readInt(elf.endian, u64);
468 elf_section.size = try in.readInt(elf.endian, u64);
469 elf_section.link = try in.readInt(elf.endian, u32);
470 elf_section.info = try in.readInt(elf.endian, u32);
471 elf_section.addr_align = try in.readInt(elf.endian, u64);
472 elf_section.ent_size = try in.readInt(elf.endian, u64);
480473 }
481474 } else {
482475 if (sh_entry_size != 40) return error.InvalidFormat;
......@@ -513,8 +506,7 @@ pub const Elf = struct {
513506 pub fn close(elf: &Elf) void {
514507 elf.allocator.free(elf.section_headers);
515508
516 if (elf.auto_close_stream)
517 elf.in_file.close();
509 if (elf.auto_close_stream) elf.in_file.close();
518510 }
519511
520512 pub fn findSection(elf: &Elf, name: []const u8) !?&SectionHeader {
......@@ -852,27 +844,27 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct {
852844 flags2: Elf32_Word,
853845};
854846
855pub const Ehdr = switch(@sizeOf(usize)) {
847pub const Ehdr = switch (@sizeOf(usize)) {
856848 4 => Elf32_Ehdr,
857849 8 => Elf64_Ehdr,
858850 else => @compileError("expected pointer size of 32 or 64"),
859851};
860pub const Phdr = switch(@sizeOf(usize)) {
852pub const Phdr = switch (@sizeOf(usize)) {
861853 4 => Elf32_Phdr,
862854 8 => Elf64_Phdr,
863855 else => @compileError("expected pointer size of 32 or 64"),
864856};
865pub const Sym = switch(@sizeOf(usize)) {
857pub const Sym = switch (@sizeOf(usize)) {
866858 4 => Elf32_Sym,
867859 8 => Elf64_Sym,
868860 else => @compileError("expected pointer size of 32 or 64"),
869861};
870pub const Verdef = switch(@sizeOf(usize)) {
862pub const Verdef = switch (@sizeOf(usize)) {
871863 4 => Elf32_Verdef,
872864 8 => Elf64_Verdef,
873865 else => @compileError("expected pointer size of 32 or 64"),
874866};
875pub const Verdaux = switch(@sizeOf(usize)) {
867pub const Verdaux = switch (@sizeOf(usize)) {
876868 4 => Elf32_Verdaux,
877869 8 => Elf64_Verdaux,
878870 else => @compileError("expected pointer size of 32 or 64"),
std/event.zig+2-11
......@@ -76,19 +76,14 @@ pub const TcpServer = struct {
7676 }
7777 continue;
7878 },
79 error.ConnectionAborted,
80 error.FileDescriptorClosed => continue,
79 error.ConnectionAborted, error.FileDescriptorClosed => continue,
8180
8281 error.PageFault => unreachable,
8382 error.InvalidSyscall => unreachable,
8483 error.FileDescriptorNotASocket => unreachable,
8584 error.OperationNotSupported => unreachable,
8685
87 error.SystemFdQuotaExceeded,
88 error.SystemResources,
89 error.ProtocolFailure,
90 error.BlockedByFirewall,
91 error.Unexpected => {
86 error.SystemFdQuotaExceeded, error.SystemResources, error.ProtocolFailure, error.BlockedByFirewall, error.Unexpected => {
9287 @panic("TODO handle this error");
9388 },
9489 }
......@@ -121,7 +116,6 @@ pub const Loop = struct {
121116 pub fn removeFd(self: &Loop, fd: i32) void {
122117 std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_DEL, fd, undefined) catch {};
123118 }
124
125119 async fn waitFd(self: &Loop, fd: i32) !void {
126120 defer self.removeFd(fd);
127121 suspend |p| {
......@@ -169,7 +163,6 @@ test "listen on a port, send bytes, receive bytes" {
169163 tcp_server: TcpServer,
170164
171165 const Self = this;
172
173166 async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, _socket: &const std.os.File) void {
174167 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
175168 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
......@@ -184,7 +177,6 @@ test "listen on a port, send bytes, receive bytes" {
184177 cancel p;
185178 }
186179 }
187
188180 async fn errorableHandler(self: &Self, _addr: &const std.net.Address, _socket: &const std.os.File) !void {
189181 const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/733
190182 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
......@@ -207,7 +199,6 @@ test "listen on a port, send bytes, receive bytes" {
207199 defer cancel p;
208200 loop.run();
209201}
210
211202async fn doAsyncTest(loop: &Loop, address: &const std.net.Address) void {
212203 errdefer @panic("test failure");
213204
std/fmt/errol/enum3.zig+3-4
......@@ -1,4 +1,4 @@
1pub const enum3 = []u64 {
1pub const enum3 = []u64{
22 0x4e2e2785c3a2a20b,
33 0x240a28877a09a4e1,
44 0x728fca36c06cf106,
......@@ -439,13 +439,13 @@ const Slab = struct {
439439};
440440
441441fn slab(str: []const u8, exp: i32) Slab {
442 return Slab {
442 return Slab{
443443 .str = str,
444444 .exp = exp,
445445 };
446446}
447447
448pub const enum3_data = []Slab {
448pub const enum3_data = []Slab{
449449 slab("40648030339495312", 69),
450450 slab("4498645355592131", -134),
451451 slab("678321594594593", 244),
......@@ -879,4 +879,3 @@ pub const enum3_data = []Slab {
879879 slab("32216657306260762", 218),
880880 slab("30423431424080128", 219),
881881};
882
std/mem.zig+8
......@@ -177,6 +177,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
177177 return true;
178178}
179179
180/// Returns true if all elements in a slice are equal to the scalar value provided
181pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool {
182 for (slice) |item| {
183 if (item != scalar) return false;
184 }
185 return true;
186}
187
180188/// Copies ::m to newly allocated memory. Caller is responsible to free it.
181189pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) ![]T {
182190 const new_buf = try allocator.alloc(T, m.len);
std/zig/ast.zig+17-9
......@@ -68,6 +68,14 @@ pub const Tree = struct {
6868 return self.tokenLocationPtr(start_index, self.tokens.at(token_index));
6969 }
7070
71 pub fn tokensOnSameLine(self: &Tree, token1_index: TokenIndex, token2_index: TokenIndex) bool {
72 return self.tokensOnSameLinePtr(self.tokens.at(token1_index), self.tokens.at(token2_index));
73 }
74
75 pub fn tokensOnSameLinePtr(self: &Tree, token1: &const Token, token2: &const Token) bool {
76 return mem.indexOfScalar(u8, self.source[token1.end..token2.start], '\n') == null;
77 }
78
7179 pub fn dump(self: &Tree) void {
7280 self.root_node.base.dump(0);
7381 }
......@@ -1529,14 +1537,14 @@ pub const Node = struct {
15291537
15301538 switch (self.op) {
15311539 Op.SliceType => |addr_of_info| {
1532 if (addr_of_info.align_expr) |align_expr| {
1533 if (i < 1) return align_expr;
1540 if (addr_of_info.align_info) |align_info| {
1541 if (i < 1) return align_info.node;
15341542 i -= 1;
15351543 }
15361544 },
15371545 Op.AddrOf => |addr_of_info| {
1538 if (addr_of_info.align_expr) |align_expr| {
1539 if (i < 1) return align_expr;
1546 if (addr_of_info.align_info) |align_info| {
1547 if (i < 1) return align_info.node;
15401548 i -= 1;
15411549 }
15421550 },
......@@ -1553,7 +1561,9 @@ pub const Node = struct {
15531561 Op.NegationWrap,
15541562 Op.Try,
15551563 Op.Resume,
1556 Op.UnwrapMaybe => {},
1564 Op.UnwrapMaybe,
1565 Op.PointerType,
1566 => {},
15571567 }
15581568
15591569 if (i < 1) return self.rhs;
......@@ -1656,6 +1666,7 @@ pub const Node = struct {
16561666 if (i < fields.len) return fields.at(i).*;
16571667 i -= fields.len;
16581668 },
1669 Op.Deref => {},
16591670 }
16601671
16611672 return null;
......@@ -2071,7 +2082,7 @@ pub const Node = struct {
20712082
20722083 const OutputList = SegmentedList(&AsmOutput, 2);
20732084 const InputList = SegmentedList(&AsmInput, 2);
2074 const ClobberList = SegmentedList(&Node, 2);
2085 const ClobberList = SegmentedList(TokenIndex, 2);
20752086
20762087 pub fn iterate(self: &Asm, index: usize) ?&Node {
20772088 var i = index;
......@@ -2082,9 +2093,6 @@ pub const Node = struct {
20822093 if (i < self.inputs.len) return &(self.inputs.at(index).*).base;
20832094 i -= self.inputs.len;
20842095
2085 if (i < self.clobbers.len) return self.clobbers.at(index).*;
2086 i -= self.clobbers.len;
2087
20882096 return null;
20892097 }
20902098
std/zig/parse.zig+5-3
......@@ -1153,9 +1153,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
11531153 continue;
11541154 },
11551155 State.AsmClobberItems => |items| {
1156 stack.append(State{ .AsmClobberItems = items }) catch unreachable;
1157 try stack.append(State{ .IfToken = Token.Id.Comma });
1158 try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = try items.addOne() } });
1156 while (eatToken(&tok_it, &tree, Token.Id.StringLiteral)) |strlit| {
1157 try items.push(strlit);
1158 if (eatToken(&tok_it, &tree, Token.Id.Comma) == null)
1159 break;
1160 }
11591161 continue;
11601162 },
11611163
std/zig/parser_test.zig+433-24
......@@ -1,10 +1,427 @@
1test "zig fmt: if condition wraps" {
2 try testTransform(
3 \\comptime {
4 \\ if (cond and
5 \\ cond) {
6 \\ return x;
7 \\ }
8 \\ while (cond and
9 \\ cond) {
10 \\ return x;
11 \\ }
12 \\ if (a == b and
13 \\ c) {
14 \\ a = b;
15 \\ }
16 \\ while (a == b and
17 \\ c) {
18 \\ a = b;
19 \\ }
20 \\ if ((cond and
21 \\ cond)) {
22 \\ return x;
23 \\ }
24 \\ while ((cond and
25 \\ cond)) {
26 \\ return x;
27 \\ }
28 \\ var a = if (a) |*f| x: {
29 \\ break :x &a.b;
30 \\ } else |err| err;
31 \\}
32 ,
33 \\comptime {
34 \\ if (cond and
35 \\ cond)
36 \\ {
37 \\ return x;
38 \\ }
39 \\ while (cond and
40 \\ cond)
41 \\ {
42 \\ return x;
43 \\ }
44 \\ if (a == b and
45 \\ c)
46 \\ {
47 \\ a = b;
48 \\ }
49 \\ while (a == b and
50 \\ c)
51 \\ {
52 \\ a = b;
53 \\ }
54 \\ if ((cond and
55 \\ cond))
56 \\ {
57 \\ return x;
58 \\ }
59 \\ while ((cond and
60 \\ cond))
61 \\ {
62 \\ return x;
63 \\ }
64 \\ var a = if (a) |*f| x: {
65 \\ break :x &a.b;
66 \\ } else |err| err;
67 \\}
68 \\
69 );
70}
71
72test "zig fmt: if condition has line break but must not wrap" {
73 try testCanonical(
74 \\comptime {
75 \\ if (self.user_input_options.put(name, UserInputOption{
76 \\ .name = name,
77 \\ .used = false,
78 \\ }) catch unreachable) |*prev_value| {
79 \\ foo();
80 \\ bar();
81 \\ }
82 \\ if (put(
83 \\ a,
84 \\ b,
85 \\ )) {
86 \\ foo();
87 \\ }
88 \\}
89 \\
90 );
91}
92
93test "zig fmt: same-line doc comment on variable declaration" {
94 try testTransform(
95 \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
96 \\pub const MAP_FILE = 0x0000; /// map from file (default)
97 \\
98 \\pub const EMEDIUMTYPE = 124; /// Wrong medium type
99 \\
100 \\// nameserver query return codes
101 \\pub const ENSROK = 0; /// DNS server returned answer with no data
102 ,
103 \\/// allocated from memory, swap space
104 \\pub const MAP_ANONYMOUS = 0x1000;
105 \\/// map from file (default)
106 \\pub const MAP_FILE = 0x0000;
107 \\
108 \\/// Wrong medium type
109 \\pub const EMEDIUMTYPE = 124;
110 \\
111 \\// nameserver query return codes
112 \\/// DNS server returned answer with no data
113 \\pub const ENSROK = 0;
114 \\
115 );
116}
117
118test "zig fmt: if-else with comment before else" {
119 try testCanonical(
120 \\comptime {
121 \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
122 \\ if ((hx & 0x7fffffff) != 0x7f800000) {
123 \\ return Complex(f32).new(y - y, y - y);
124 \\ } // cexp(-inf +- i inf|nan) = 0 + i0
125 \\ else if (hx & 0x80000000 != 0) {
126 \\ return Complex(f32).new(0, 0);
127 \\ } // cexp(+inf +- i inf|nan) = inf + i nan
128 \\ else {
129 \\ return Complex(f32).new(x, y - y);
130 \\ }
131 \\}
132 \\
133 );
134}
135
136test "zig fmt: respect line breaks in if-else" {
137 try testCanonical(
138 \\comptime {
139 \\ return if (cond) a else b;
140 \\ return if (cond)
141 \\ a
142 \\ else
143 \\ b;
144 \\ return if (cond)
145 \\ a
146 \\ else if (cond)
147 \\ b
148 \\ else
149 \\ c;
150 \\}
151 \\
152 );
153}
154
155test "zig fmt: respect line breaks after infix operators" {
156 try testCanonical(
157 \\comptime {
158 \\ self.crc =
159 \\ lookup_tables[0][p[7]] ^
160 \\ lookup_tables[1][p[6]] ^
161 \\ lookup_tables[2][p[5]] ^
162 \\ lookup_tables[3][p[4]] ^
163 \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
164 \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
165 \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
166 \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];
167 \\}
168 \\
169 );
170}
171
172test "zig fmt: fn decl with trailing comma" {
173 try testTransform(
174 \\fn foo(a: i32, b: i32,) void {}
175 ,
176 \\fn foo(
177 \\ a: i32,
178 \\ b: i32,
179 \\) void {}
180 \\
181 );
182}
183
184test "zig fmt: enum decl with no trailing comma" {
185 try testTransform(
186 \\const StrLitKind = enum {Normal, C};
187 ,
188 \\const StrLitKind = enum {
189 \\ Normal,
190 \\ C,
191 \\};
192 \\
193 );
194}
195
196test "zig fmt: switch comment before prong" {
197 try testCanonical(
198 \\comptime {
199 \\ switch (a) {
200 \\ // hi
201 \\ 0 => {},
202 \\ }
203 \\}
204 \\
205 );
206}
207
208test "zig fmt: struct literal no trailing comma" {
209 try testTransform(
210 \\const a = foo{ .x = 1, .y = 2 };
211 \\const a = foo{ .x = 1,
212 \\ .y = 2 };
213 ,
214 \\const a = foo{ .x = 1, .y = 2 };
215 \\const a = foo{
216 \\ .x = 1,
217 \\ .y = 2,
218 \\};
219 \\
220 );
221}
222
223test "zig fmt: array literal with hint" {
224 try testTransform(
225 \\const a = []u8{
226 \\ 1, 2, //
227 \\ 3,
228 \\ 4,
229 \\ 5,
230 \\ 6,
231 \\ 7 };
232 \\const a = []u8{
233 \\ 1, 2, //
234 \\ 3,
235 \\ 4,
236 \\ 5,
237 \\ 6,
238 \\ 7, 8 };
239 \\const a = []u8{
240 \\ 1, 2, //
241 \\ 3,
242 \\ 4,
243 \\ 5,
244 \\ 6, // blah
245 \\ 7, 8 };
246 \\const a = []u8{
247 \\ 1, 2, //
248 \\ 3, //
249 \\ 4,
250 \\ 5,
251 \\ 6,
252 \\ 7 };
253 \\const a = []u8{
254 \\ 1,
255 \\ 2,
256 \\ 3, 4, //
257 \\ 5, 6, //
258 \\ 7, 8, //
259 \\};
260 ,
261 \\const a = []u8{
262 \\ 1, 2,
263 \\ 3, 4,
264 \\ 5, 6,
265 \\ 7,
266 \\};
267 \\const a = []u8{
268 \\ 1, 2,
269 \\ 3, 4,
270 \\ 5, 6,
271 \\ 7, 8,
272 \\};
273 \\const a = []u8{
274 \\ 1, 2,
275 \\ 3, 4,
276 \\ 5, 6, // blah
277 \\ 7, 8,
278 \\};
279 \\const a = []u8{
280 \\ 1, 2,
281 \\ 3, //
282 \\ 4,
283 \\ 5, 6,
284 \\ 7,
285 \\};
286 \\const a = []u8{
287 \\ 1,
288 \\ 2,
289 \\ 3,
290 \\ 4,
291 \\ 5,
292 \\ 6,
293 \\ 7,
294 \\ 8,
295 \\};
296 \\
297 );
298}
299
300test "zig fmt: multiline string with backslash at end of line" {
301 try testCanonical(
302 \\comptime {
303 \\ err(
304 \\ \\\
305 \\ );
306 \\}
307 \\
308 );
309}
310
311test "zig fmt: multiline string parameter in fn call with trailing comma" {
312 try testCanonical(
313 \\fn foo() void {
314 \\ try stdout.print(
315 \\ \\ZIG_CMAKE_BINARY_DIR {}
316 \\ \\ZIG_C_HEADER_FILES {}
317 \\ \\ZIG_DIA_GUIDS_LIB {}
318 \\ \\
319 \\ ,
320 \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
321 \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
322 \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
323 \\ );
324 \\}
325 \\
326 );
327}
328
329test "zig fmt: trailing comma on fn call" {
330 try testCanonical(
331 \\comptime {
332 \\ var module = try Module.create(
333 \\ allocator,
334 \\ zig_lib_dir,
335 \\ full_cache_dir,
336 \\ );
337 \\}
338 \\
339 );
340}
341
342test "zig fmt: empty block with only comment" {
343 try testCanonical(
344 \\comptime {
345 \\ {
346 \\ // comment
347 \\ }
348 \\}
349 \\
350 );
351}
352
353test "zig fmt: no trailing comma on struct decl" {
354 try testTransform(
355 \\const RoundParam = struct {
356 \\ k: usize, s: u32, t: u32
357 \\};
358 ,
359 \\const RoundParam = struct {
360 \\ k: usize,
361 \\ s: u32,
362 \\ t: u32,
363 \\};
364 \\
365 );
366}
367
368test "zig fmt: simple asm" {
369 try testTransform(
370 \\comptime {
371 \\ asm volatile (
372 \\ \\.globl aoeu;
373 \\ \\.type aoeu, @function;
374 \\ \\.set aoeu, derp;
375 \\ );
376 \\
377 \\ asm ("not real assembly"
378 \\ :[a] "x" (x),);
379 \\ asm ("not real assembly"
380 \\ :[a] "x" (->i32),:[a] "x" (1),);
381 \\ asm ("still not real assembly"
382 \\ :::"a","b",);
383 \\}
384 ,
385 \\comptime {
386 \\ asm volatile (
387 \\ \\.globl aoeu;
388 \\ \\.type aoeu, @function;
389 \\ \\.set aoeu, derp;
390 \\ );
391 \\
392 \\ asm ("not real assembly"
393 \\ : [a] "x" (x)
394 \\ );
395 \\ asm ("not real assembly"
396 \\ : [a] "x" (-> i32)
397 \\ : [a] "x" (1)
398 \\ );
399 \\ asm ("still not real assembly"
400 \\ :
401 \\ :
402 \\ : "a", "b"
403 \\ );
404 \\}
405 \\
406 );
407}
408
409test "zig fmt: nested struct literal with one item" {
410 try testCanonical(
411 \\const a = foo{
412 \\ .item = bar{ .a = b },
413 \\};
414 \\
415 );
416}
417
1418test "zig fmt: switch cases trailing comma" {
2419 try testTransform(
3420 \\fn switch_cases(x: i32) void {
4421 \\ switch (x) {
5422 \\ 1,2,3 => {},
6423 \\ 4,5, => {},
7 \\ 6...8, => {},
424 \\ 6... 8, => {},
8425 \\ else => {},
9426 \\ }
10427 \\}
......@@ -13,8 +430,9 @@ test "zig fmt: switch cases trailing comma" {
13430 \\ switch (x) {
14431 \\ 1, 2, 3 => {},
15432 \\ 4,
16 \\ 5, => {},
17 \\ 6 ... 8 => {},
433 \\ 5,
434 \\ => {},
435 \\ 6...8 => {},
18436 \\ else => {},
19437 \\ }
20438 \\}
......@@ -36,16 +454,20 @@ test "zig fmt: add trailing comma to array literal" {
36454 \\comptime {
37455 \\ return []u16{'m', 's', 'y', 's', '-' // hi
38456 \\ };
457 \\ return []u16{'m', 's', 'y', 's',
458 \\ '-'};
459 \\ return []u16{'m', 's', 'y', 's', '-'};
39460 \\}
40461 ,
41462 \\comptime {
42463 \\ return []u16{
43 \\ 'm',
44 \\ 's',
45 \\ 'y',
46 \\ 's',
47 \\ '-', // hi
464 \\ 'm', 's', 'y', 's', '-', // hi
48465 \\ };
466 \\ return []u16{
467 \\ 'm', 's', 'y', 's',
468 \\ '-',
469 \\ };
470 \\ return []u16{ 'm', 's', 'y', 's', '-' };
49471 \\}
50472 \\
51473 );
......@@ -252,20 +674,6 @@ test "zig fmt: add comma on last switch prong" {
252674 );
253675}
254676
255test "zig fmt: same-line doc comment on variable declaration" {
256 try testTransform(
257 \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
258 \\pub const MAP_FILE = 0x0000; /// map from file (default)
259 \\
260 ,
261 \\/// allocated from memory, swap space
262 \\pub const MAP_ANONYMOUS = 0x1000;
263 \\/// map from file (default)
264 \\pub const MAP_FILE = 0x0000;
265 \\
266 );
267}
268
269677test "zig fmt: same-line comment after a statement" {
270678 try testCanonical(
271679 \\test "" {
......@@ -1026,7 +1434,7 @@ test "zig fmt: switch" {
10261434 \\ 0 => {},
10271435 \\ 1 => unreachable,
10281436 \\ 2, 3 => {},
1029 \\ 4 ... 7 => {},
1437 \\ 4...7 => {},
10301438 \\ 1 + 4 * 3 + 22 => {},
10311439 \\ else => {
10321440 \\ const a = 1;
......@@ -1286,7 +1694,8 @@ test "zig fmt: inline asm" {
12861694 \\ : [ret] "={rax}" (-> usize)
12871695 \\ : [number] "{rax}" (number),
12881696 \\ [arg1] "{rdi}" (arg1)
1289 \\ : "rcx", "r11");
1697 \\ : "rcx", "r11"
1698 \\ );
12901699 \\}
12911700 \\
12921701 );
std/zig/render.zig+889-535
......@@ -19,7 +19,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(
1919 var tok_it = tree.tokens.iterator(0);
2020 while (tok_it.next()) |token| {
2121 if (token.id != Token.Id.LineComment) break;
22 try stream.print("{}\n", tree.tokenSlicePtr(token));
22 try stream.print("{}\n", mem.trimRight(u8, tree.tokenSlicePtr(token), " "));
2323 if (tok_it.peek()) |next_token| {
2424 const loc = tree.tokenLocationPtr(token.end, next_token);
2525 if (loc.line >= 2) {
......@@ -28,41 +28,43 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(
2828 }
2929 }
3030
31
31 var start_col: usize = 0;
3232 var it = tree.root_node.decls.iterator(0);
3333 while (it.next()) |decl| {
34 try renderTopLevelDecl(allocator, stream, tree, 0, decl.*);
34 try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl.*);
3535 if (it.peek()) |next_decl| {
36 try renderExtraNewline(tree, stream, next_decl.*);
36 try renderExtraNewline(tree, stream, &start_col, next_decl.*);
3737 }
3838 }
3939}
4040
41fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void {
42 var first_token = node.firstToken();
43 while (tree.tokens.at(first_token - 1).id == Token.Id.DocComment) {
44 first_token -= 1;
41fn renderExtraNewline(tree: &ast.Tree, stream: var, start_col: &usize, node: &ast.Node) !void {
42 const first_token = node.firstToken();
43 var prev_token = first_token;
44 while (tree.tokens.at(prev_token - 1).id == Token.Id.DocComment) {
45 prev_token -= 1;
4546 }
46 const prev_token_end = tree.tokens.at(first_token - 1).end;
47 const prev_token_end = tree.tokens.at(prev_token - 1).end;
4748 const loc = tree.tokenLocation(prev_token_end, first_token);
4849 if (loc.line >= 2) {
4950 try stream.writeByte('\n');
51 start_col.* = 0;
5052 }
5153}
5254
53fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, decl: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {
55fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, decl: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {
5456 switch (decl.id) {
5557 ast.Node.Id.FnProto => {
5658 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
5759
58 try renderDocComments(tree, stream, fn_proto, indent);
60 try renderDocComments(tree, stream, fn_proto, indent, start_col);
5961
6062 if (fn_proto.body_node) |body_node| {
61 try renderExpression(allocator, stream, tree, indent, decl, Space.Space);
62 try renderExpression(allocator, stream, tree, indent, body_node, Space.Newline);
63 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Space);
64 try renderExpression(allocator, stream, tree, indent, start_col, body_node, Space.Newline);
6365 } else {
64 try renderExpression(allocator, stream, tree, indent, decl, Space.None);
65 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline);
66 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.None);
67 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, start_col, Space.Newline);
6668 }
6769 },
6870
......@@ -70,148 +72,154 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i
7072 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
7173
7274 if (use_decl.visib_token) |visib_token| {
73 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub
75 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
7476 }
75 try renderToken(tree, stream, use_decl.use_token, indent, Space.Space); // use
76 try renderExpression(allocator, stream, tree, indent, use_decl.expr, Space.None);
77 try renderToken(tree, stream, use_decl.semicolon_token, indent, Space.Newline); // ;
77 try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // use
78 try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, Space.None);
79 try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, Space.Newline); // ;
7880 },
7981
8082 ast.Node.Id.VarDecl => {
8183 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
8284
83 try renderDocComments(tree, stream, var_decl, indent);
84 try renderVarDecl(allocator, stream, tree, indent, var_decl);
85 try renderDocComments(tree, stream, var_decl, indent, start_col);
86 try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl);
8587 },
8688
8789 ast.Node.Id.TestDecl => {
8890 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
8991
90 try renderDocComments(tree, stream, test_decl, indent);
91 try renderToken(tree, stream, test_decl.test_token, indent, Space.Space);
92 try renderExpression(allocator, stream, tree, indent, test_decl.name, Space.Space);
93 try renderExpression(allocator, stream, tree, indent, test_decl.body_node, Space.Newline);
92 try renderDocComments(tree, stream, test_decl, indent, start_col);
93 try renderToken(tree, stream, test_decl.test_token, indent, start_col, Space.Space);
94 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, Space.Space);
95 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, Space.Newline);
9496 },
9597
9698 ast.Node.Id.StructField => {
9799 const field = @fieldParentPtr(ast.Node.StructField, "base", decl);
98100
99 try renderDocComments(tree, stream, field, indent);
101 try renderDocComments(tree, stream, field, indent, start_col);
100102 if (field.visib_token) |visib_token| {
101 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub
103 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
102104 }
103 try renderToken(tree, stream, field.name_token, indent, Space.None); // name
104 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // :
105 try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.None); // type
106 try renderToken(tree, stream, tree.nextToken(field.lastToken()), indent, Space.Newline); // ,
105 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
106 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :
107 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr, Space.Comma); // type,
107108 },
108109
109110 ast.Node.Id.UnionTag => {
110111 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);
111112
112 try renderDocComments(tree, stream, tag, indent);
113
114 const name_space = if (tag.type_expr == null and tag.value_expr != null) Space.Space else Space.None;
115 try renderToken(tree, stream, tag.name_token, indent, name_space); // name
113 try renderDocComments(tree, stream, tag, indent, start_col);
116114
117 if (tag.type_expr) |type_expr| {
118 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // :
115 if (tag.type_expr == null and tag.value_expr == null) {
116 return renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name,
117 }
119118
120 const after_type_space = if (tag.value_expr == null) Space.None else Space.Space;
121 try renderExpression(allocator, stream, tree, indent, type_expr, after_type_space);
119 if (tag.type_expr == null) {
120 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name
121 } else {
122 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.None); // name
122123 }
123124
124 if (tag.value_expr) |value_expr| {
125 try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // =
126 try renderExpression(allocator, stream, tree, indent, value_expr, Space.None);
125 if (tag.type_expr) |type_expr| {
126 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // :
127
128 if (tag.value_expr == null) {
129 try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Comma); // type,
130 return;
131 } else {
132 try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Space); // type
133 }
127134 }
128135
129 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); // ,
136 const value_expr = ??tag.value_expr;
137 try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, start_col, Space.Space); // =
138 try renderExpression(allocator, stream, tree, indent, start_col, value_expr, Space.Comma); // value,
130139 },
131140
132141 ast.Node.Id.EnumTag => {
133142 const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl);
134143
135 try renderDocComments(tree, stream, tag, indent);
136
137 const after_name_space = if (tag.value == null) Space.None else Space.Space;
138 try renderToken(tree, stream, tag.name_token, indent, after_name_space); // name
144 try renderDocComments(tree, stream, tag, indent, start_col);
139145
140146 if (tag.value) |value| {
141 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // =
142 try renderExpression(allocator, stream, tree, indent, value, Space.None);
143 }
147 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name
144148
145 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); // ,
149 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // =
150 try renderExpression(allocator, stream, tree, indent, start_col, value, Space.Comma);
151 } else {
152 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name
153 }
146154 },
147155
148156 ast.Node.Id.Comptime => {
149157 assert(!decl.requireSemiColon());
150 try renderExpression(allocator, stream, tree, indent, decl, Space.Newline);
158 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Newline);
151159 },
152160 else => unreachable,
153161 }
154162}
155163
156fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, space: Space) (@typeOf(stream).Child.Error || Error)!void {
164fn 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 {
157165 switch (base.id) {
158166 ast.Node.Id.Identifier => {
159167 const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base);
160 try renderToken(tree, stream, identifier.token, indent, space);
168 return renderToken(tree, stream, identifier.token, indent, start_col, space);
161169 },
162170 ast.Node.Id.Block => {
163171 const block = @fieldParentPtr(ast.Node.Block, "base", base);
164172
165173 if (block.label) |label| {
166 try renderToken(tree, stream, label, indent, Space.None);
167 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);
174 try renderToken(tree, stream, label, indent, start_col, Space.None);
175 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
168176 }
169177
170178 if (block.statements.len == 0) {
171 try renderToken(tree, stream, block.lbrace, indent + indent_delta, Space.None);
172 try renderToken(tree, stream, block.rbrace, indent, space);
179 try renderToken(tree, stream, block.lbrace, indent + indent_delta, start_col, Space.None);
180 return renderToken(tree, stream, block.rbrace, indent, start_col, space);
173181 } else {
174182 const block_indent = indent + indent_delta;
175 try renderToken(tree, stream, block.lbrace, block_indent, Space.Newline);
183 try renderToken(tree, stream, block.lbrace, block_indent, start_col, Space.Newline);
176184
177185 var it = block.statements.iterator(0);
178186 while (it.next()) |statement| {
179187 try stream.writeByteNTimes(' ', block_indent);
180 try renderStatement(allocator, stream, tree, block_indent, statement.*);
188 try renderStatement(allocator, stream, tree, block_indent, start_col, statement.*);
181189
182190 if (it.peek()) |next_statement| {
183 try renderExtraNewline(tree, stream, next_statement.*);
191 try renderExtraNewline(tree, stream, start_col, next_statement.*);
184192 }
185193 }
186194
187195 try stream.writeByteNTimes(' ', indent);
188 try renderToken(tree, stream, block.rbrace, indent, space);
196 return renderToken(tree, stream, block.rbrace, indent, start_col, space);
189197 }
190198 },
191199 ast.Node.Id.Defer => {
192200 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
193201
194 try renderToken(tree, stream, defer_node.defer_token, indent, Space.Space);
195 try renderExpression(allocator, stream, tree, indent, defer_node.expr, space);
202 try renderToken(tree, stream, defer_node.defer_token, indent, start_col, Space.Space);
203 return renderExpression(allocator, stream, tree, indent, start_col, defer_node.expr, space);
196204 },
197205 ast.Node.Id.Comptime => {
198206 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);
199207
200 try renderToken(tree, stream, comptime_node.comptime_token, indent, Space.Space);
201 try renderExpression(allocator, stream, tree, indent, comptime_node.expr, space);
208 try renderToken(tree, stream, comptime_node.comptime_token, indent, start_col, Space.Space);
209 return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space);
202210 },
203211
204212 ast.Node.Id.AsyncAttribute => {
205213 const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base);
206214
207215 if (async_attr.allocator_type) |allocator_type| {
208 try renderToken(tree, stream, async_attr.async_token, indent, Space.None);
216 try renderToken(tree, stream, async_attr.async_token, indent, start_col, Space.None);
209217
210 try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, Space.None);
211 try renderExpression(allocator, stream, tree, indent, allocator_type, Space.None);
212 try renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, space);
218 try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, start_col, Space.None);
219 try renderExpression(allocator, stream, tree, indent, start_col, allocator_type, Space.None);
220 return renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, start_col, space);
213221 } else {
214 try renderToken(tree, stream, async_attr.async_token, indent, space);
222 return renderToken(tree, stream, async_attr.async_token, indent, start_col, space);
215223 }
216224 },
217225
......@@ -219,24 +227,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
219227 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
220228
221229 if (suspend_node.label) |label| {
222 try renderToken(tree, stream, label, indent, Space.None);
223 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);
230 try renderToken(tree, stream, label, indent, start_col, Space.None);
231 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
224232 }
225233
226234 if (suspend_node.payload) |payload| {
227235 if (suspend_node.body) |body| {
228 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);
229 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
230 try renderExpression(allocator, stream, tree, indent, body, space);
236 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
237 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
238 return renderExpression(allocator, stream, tree, indent, start_col, body, space);
231239 } else {
232 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);
233 try renderExpression(allocator, stream, tree, indent, payload, space);
240 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
241 return renderExpression(allocator, stream, tree, indent, start_col, payload, space);
234242 }
235243 } else if (suspend_node.body) |body| {
236 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);
237 try renderExpression(allocator, stream, tree, indent, body, space);
244 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
245 return renderExpression(allocator, stream, tree, indent, start_col, body, space);
238246 } else {
239 try renderToken(tree, stream, suspend_node.suspend_token, indent, space);
247 return renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, space);
240248 }
241249 },
242250
......@@ -245,20 +253,31 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
245253
246254 const op_token = tree.tokens.at(infix_op_node.op_token);
247255 const op_space = switch (infix_op_node.op) {
248 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion => Space.None,
256 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None,
249257 else => Space.Space,
250258 };
251 try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs, op_space);
252 try renderToken(tree, stream, infix_op_node.op_token, indent, op_space);
259 try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space);
260
261 const after_op_space = blk: {
262 const loc = tree.tokenLocation(tree.tokens.at(infix_op_node.op_token).end,
263 tree.nextToken(infix_op_node.op_token));
264 break :blk if (loc.line == 0) op_space else Space.Newline;
265 };
266
267 try renderToken(tree, stream, infix_op_node.op_token, indent, start_col, after_op_space);
268 if (after_op_space == Space.Newline) {
269 try stream.writeByteNTimes(' ', indent + indent_delta);
270 start_col.* = indent + indent_delta;
271 }
253272
254273 switch (infix_op_node.op) {
255274 ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| {
256 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
275 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
257276 },
258277 else => {},
259278 }
260279
261 try renderExpression(allocator, stream, tree, indent, infix_op_node.rhs, space);
280 return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space);
262281 },
263282
264283 ast.Node.Id.PrefixOp => {
......@@ -266,81 +285,81 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
266285
267286 switch (prefix_op_node.op) {
268287 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {
269 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // &
288 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // &
270289 if (addr_of_info.align_info) |align_info| {
271290 const lparen_token = tree.prevToken(align_info.node.firstToken());
272291 const align_token = tree.prevToken(lparen_token);
273292
274 try renderToken(tree, stream, align_token, indent, Space.None); // align
275 try renderToken(tree, stream, lparen_token, indent, Space.None); // (
293 try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align
294 try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // (
276295
277 try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
296 try renderExpression(allocator, stream, tree, indent, start_col, align_info.node, Space.None);
278297
279298 if (align_info.bit_range) |bit_range| {
280299 const colon1 = tree.prevToken(bit_range.start.firstToken());
281300 const colon2 = tree.prevToken(bit_range.end.firstToken());
282301
283 try renderToken(tree, stream, colon1, indent, Space.None); // :
284 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
285 try renderToken(tree, stream, colon2, indent, Space.None); // :
286 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
302 try renderToken(tree, stream, colon1, indent, start_col, Space.None); // :
303 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None);
304 try renderToken(tree, stream, colon2, indent, start_col, Space.None); // :
305 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None);
287306
288307 const rparen_token = tree.nextToken(bit_range.end.lastToken());
289 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
308 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // )
290309 } else {
291310 const rparen_token = tree.nextToken(align_info.node.lastToken());
292 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
311 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // )
293312 }
294313 }
295314 if (addr_of_info.const_token) |const_token| {
296 try renderToken(tree, stream, const_token, indent, Space.Space); // const
315 try renderToken(tree, stream, const_token, indent, start_col, Space.Space); // const
297316 }
298317 if (addr_of_info.volatile_token) |volatile_token| {
299 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile
318 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile
300319 }
301320 },
302321
303322 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {
304 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
305 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]
323 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
324 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, start_col, Space.None); // ]
306325
307326 if (addr_of_info.align_info) |align_info| {
308327 const lparen_token = tree.prevToken(align_info.node.firstToken());
309328 const align_token = tree.prevToken(lparen_token);
310329
311 try renderToken(tree, stream, align_token, indent, Space.None); // align
312 try renderToken(tree, stream, lparen_token, indent, Space.None); // (
330 try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align
331 try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // (
313332
314 try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
333 try renderExpression(allocator, stream, tree, indent, start_col, align_info.node, Space.None);
315334
316335 if (align_info.bit_range) |bit_range| {
317336 const colon1 = tree.prevToken(bit_range.start.firstToken());
318337 const colon2 = tree.prevToken(bit_range.end.firstToken());
319338
320 try renderToken(tree, stream, colon1, indent, Space.None); // :
321 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
322 try renderToken(tree, stream, colon2, indent, Space.None); // :
323 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
339 try renderToken(tree, stream, colon1, indent, start_col, Space.None); // :
340 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None);
341 try renderToken(tree, stream, colon2, indent, start_col, Space.None); // :
342 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None);
324343
325344 const rparen_token = tree.nextToken(bit_range.end.lastToken());
326 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
345 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // )
327346 } else {
328347 const rparen_token = tree.nextToken(align_info.node.lastToken());
329 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
348 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // )
330349 }
331350 }
332351 if (addr_of_info.const_token) |const_token| {
333 try renderToken(tree, stream, const_token, indent, Space.Space);
352 try renderToken(tree, stream, const_token, indent, start_col, Space.Space);
334353 }
335354 if (addr_of_info.volatile_token) |volatile_token| {
336 try renderToken(tree, stream, volatile_token, indent, Space.Space);
355 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space);
337356 }
338357 },
339358
340359 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
341 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
342 try renderExpression(allocator, stream, tree, indent, array_index, Space.None);
343 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, Space.None); // ]
360 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
361 try renderExpression(allocator, stream, tree, indent, start_col, array_index, Space.None);
362 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, start_col, Space.None); // ]
344363 },
345364 ast.Node.PrefixOp.Op.BitNot,
346365 ast.Node.PrefixOp.Op.BoolNot,
......@@ -349,18 +368,18 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
349368 ast.Node.PrefixOp.Op.UnwrapMaybe,
350369 ast.Node.PrefixOp.Op.MaybeType,
351370 ast.Node.PrefixOp.Op.PointerType => {
352 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None);
371 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None);
353372 },
354373
355374 ast.Node.PrefixOp.Op.Try,
356375 ast.Node.PrefixOp.Op.Await,
357376 ast.Node.PrefixOp.Op.Cancel,
358377 ast.Node.PrefixOp.Op.Resume => {
359 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.Space);
378 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
360379 },
361380 }
362381
363 try renderExpression(allocator, stream, tree, indent, prefix_op_node.rhs, space);
382 return renderExpression(allocator, stream, tree, indent, start_col, prefix_op_node.rhs, space);
364383 },
365384
366385 ast.Node.Id.SuffixOp => {
......@@ -369,80 +388,152 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
369388 switch (suffix_op.op) {
370389 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {
371390 if (call_info.async_attr) |async_attr| {
372 try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space);
391 try renderExpression(allocator, stream, tree, indent, start_col, &async_attr.base, Space.Space);
373392 }
374393
375 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
394 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
376395
377396 const lparen = tree.nextToken(suffix_op.lhs.lastToken());
378 try renderToken(tree, stream, lparen, indent, Space.None);
397
398 if (call_info.params.len == 0) {
399 try renderToken(tree, stream, lparen, indent, start_col, Space.None);
400 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
401 }
402
403 const src_has_trailing_comma = blk: {
404 const maybe_comma = tree.prevToken(suffix_op.rtoken);
405 break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma;
406 };
407
408 if (src_has_trailing_comma) {
409 const new_indent = indent + indent_delta;
410 try renderToken(tree, stream, lparen, new_indent, start_col, Space.Newline);
411
412 var it = call_info.params.iterator(0);
413 while (true) {
414 const param_node = ??it.next();
415
416 const param_node_new_indent = if (param_node.*.id == ast.Node.Id.MultilineStringLiteral) blk: {
417 break :blk indent;
418 } else blk: {
419 try stream.writeByteNTimes(' ', new_indent);
420 break :blk new_indent;
421 };
422
423 if (it.peek()) |next_node| {
424 try renderExpression(allocator, stream, tree, param_node_new_indent, start_col, param_node.*, Space.None);
425 const comma = tree.nextToken(param_node.*.lastToken());
426 try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // ,
427 try renderExtraNewline(tree, stream, start_col, next_node.*);
428 } else {
429 try renderExpression(allocator, stream, tree, param_node_new_indent, start_col, param_node.*, Space.Comma);
430 try stream.writeByteNTimes(' ', indent);
431 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
432 }
433 }
434 }
435
436 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
379437
380438 var it = call_info.params.iterator(0);
381439 while (it.next()) |param_node| {
382 try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None);
440 try renderExpression(allocator, stream, tree, indent, start_col, param_node.*, Space.None);
383441
384442 if (it.peek() != null) {
385443 const comma = tree.nextToken(param_node.*.lastToken());
386 try renderToken(tree, stream, comma, indent, Space.Space);
444 try renderToken(tree, stream, comma, indent, start_col, Space.Space);
387445 }
388446 }
389
390 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
447 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
391448 },
392449
393450 ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| {
394451 const lbracket = tree.prevToken(index_expr.firstToken());
395452 const rbracket = tree.nextToken(index_expr.lastToken());
396453
397 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
398 try renderToken(tree, stream, lbracket, indent, Space.None); // [
399 try renderExpression(allocator, stream, tree, indent, index_expr, Space.None);
400 try renderToken(tree, stream, rbracket, indent, space); // ]
454 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
455 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
456 try renderExpression(allocator, stream, tree, indent, start_col, index_expr, Space.None);
457 return renderToken(tree, stream, rbracket, indent, start_col, space); // ]
401458 },
402459
403460 ast.Node.SuffixOp.Op.Deref => {
404 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
405 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, Space.None); // .
406 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // *
461 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
462 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
463 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // *
407464 },
408465
409466 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {
410 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
467 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
411468
412469 const lbracket = tree.prevToken(range.start.firstToken());
413470 const dotdot = tree.nextToken(range.start.lastToken());
414471
415 try renderToken(tree, stream, lbracket, indent, Space.None); // [
416 try renderExpression(allocator, stream, tree, indent, range.start, Space.None);
417 try renderToken(tree, stream, dotdot, indent, Space.None); // ..
472 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
473 try renderExpression(allocator, stream, tree, indent, start_col, range.start, Space.None);
474 try renderToken(tree, stream, dotdot, indent, start_col, Space.None); // ..
418475 if (range.end) |end| {
419 try renderExpression(allocator, stream, tree, indent, end, Space.None);
476 try renderExpression(allocator, stream, tree, indent, start_col, end, Space.None);
420477 }
421 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // ]
478 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ]
422479 },
423480
424481 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {
425482 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
426483
427484 if (field_inits.len == 0) {
428 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
429 try renderToken(tree, stream, lbrace, indent, Space.None);
430 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
431 return;
485 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
486 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
487 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
432488 }
433489
434 if (field_inits.len == 1) {
435 const field_init = field_inits.at(0).*;
490 if (field_inits.len == 1) blk: {
491 const field_init = ??field_inits.at(0).*.cast(ast.Node.FieldInitializer);
436492
437 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
438 try renderToken(tree, stream, lbrace, indent, Space.Space);
439 try renderExpression(allocator, stream, tree, indent, field_init, Space.Space);
440 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
441 return;
493 if (field_init.expr.cast(ast.Node.SuffixOp)) |nested_suffix_op| {
494 if (nested_suffix_op.op == ast.Node.SuffixOp.Op.StructInitializer) {
495 break :blk;
496 }
497 }
498
499 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
500 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
501 try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space);
502 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
442503 }
443504
444 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
445 try renderToken(tree, stream, lbrace, indent, Space.Newline);
505 const src_has_trailing_comma = blk: {
506 const maybe_comma = tree.prevToken(suffix_op.rtoken);
507 break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma;
508 };
509
510 const src_same_line = blk: {
511 const loc = tree.tokenLocation(tree.tokens.at(lbrace).end, suffix_op.rtoken);
512 break :blk loc.line == 0;
513 };
514
515 if (!src_has_trailing_comma and src_same_line) {
516 // render all on one line, no trailing comma
517 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
518 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
519
520 var it = field_inits.iterator(0);
521 while (it.next()) |field_init| {
522 if (it.peek() != null) {
523 try renderExpression(allocator, stream, tree, indent, start_col, field_init.*, Space.None);
524
525 const comma = tree.nextToken(field_init.*.lastToken());
526 try renderToken(tree, stream, comma, indent, start_col, Space.Space);
527 } else {
528 try renderExpression(allocator, stream, tree, indent, start_col, field_init.*, Space.Space);
529 }
530 }
531
532 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
533 }
534
535 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
536 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline);
446537
447538 const new_indent = indent + indent_delta;
448539
......@@ -451,63 +542,116 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
451542 try stream.writeByteNTimes(' ', new_indent);
452543
453544 if (it.peek()) |next_field_init| {
454 try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.None);
545 try renderExpression(allocator, stream, tree, new_indent, start_col, field_init.*, Space.None);
455546
456547 const comma = tree.nextToken(field_init.*.lastToken());
457 try renderToken(tree, stream, comma, new_indent, Space.Newline);
548 try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline);
458549
459 try renderExtraNewline(tree, stream, next_field_init.*);
550 try renderExtraNewline(tree, stream, start_col, next_field_init.*);
460551 } else {
461 try renderTrailingComma(allocator, stream, tree, new_indent, field_init.*, Space.Newline);
552 try renderExpression(allocator, stream, tree, new_indent, start_col, field_init.*, Space.Comma);
462553 }
463554 }
464555
465556 try stream.writeByteNTimes(' ', indent);
466 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
557 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
467558 },
468559
469560 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {
470561 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
471562
472563 if (exprs.len == 0) {
473 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
474 try renderToken(tree, stream, lbrace, indent, Space.None);
475 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
476 return;
564 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
565 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
566 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
477567 }
478568 if (exprs.len == 1) {
479569 const expr = exprs.at(0).*;
480570
481 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
482 try renderToken(tree, stream, lbrace, indent, Space.None);
483 try renderExpression(allocator, stream, tree, indent, expr, Space.None);
484 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
485 return;
571 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
572 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
573 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
574 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
486575 }
487576
488 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
489
490 const new_indent = indent + indent_delta;
491 try renderToken(tree, stream, lbrace, new_indent, Space.Newline);
577 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
578
579 // scan to find row size
580 const maybe_row_size: ?usize = blk: {
581 var count: usize = 1;
582 var it = exprs.iterator(0);
583 while (true) {
584 const expr = (??it.next()).*;
585 if (it.peek()) |next_expr| {
586 const expr_last_token = expr.*.lastToken() + 1;
587 const loc = tree.tokenLocation(tree.tokens.at(expr_last_token).end, next_expr.*.firstToken());
588 if (loc.line != 0) break :blk count;
589 count += 1;
590 } else {
591 const expr_last_token = expr.*.lastToken();
592 const loc = tree.tokenLocation(tree.tokens.at(expr_last_token).end, suffix_op.rtoken);
593 if (loc.line == 0) {
594 // all on one line
595 const src_has_trailing_comma = trailblk: {
596 const maybe_comma = tree.prevToken(suffix_op.rtoken);
597 break :trailblk tree.tokens.at(maybe_comma).id == Token.Id.Comma;
598 };
599 if (src_has_trailing_comma) {
600 break :blk 1; // force row size 1
601 } else {
602 break :blk null; // no newlines
603 }
604 }
605 break :blk count;
606 }
607 }
608 };
492609
493 var it = exprs.iterator(0);
494 while (it.next()) |expr| {
610 if (maybe_row_size) |row_size| {
611 const new_indent = indent + indent_delta;
612 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);
495613 try stream.writeByteNTimes(' ', new_indent);
496614
497 if (it.peek()) |next_expr| {
498 try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None);
615 var it = exprs.iterator(0);
616 var i: usize = 1;
617 while (it.next()) |expr| {
618 if (it.peek()) |next_expr| {
619 try renderExpression(allocator, stream, tree, new_indent, start_col, expr.*, Space.None);
499620
500 const comma = tree.nextToken(expr.*.lastToken());
501 try renderToken(tree, stream, comma, new_indent, Space.Newline); // ,
621 const comma = tree.nextToken(expr.*.lastToken());
502622
503 try renderExtraNewline(tree, stream, next_expr.*);
504 } else {
505 try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline);
623 if (i != row_size) {
624 try renderToken(tree, stream, comma, new_indent, start_col, Space.Space); // ,
625 i += 1;
626 continue;
627 }
628 i = 1;
629
630 try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // ,
631
632 try renderExtraNewline(tree, stream, start_col, next_expr.*);
633 try stream.writeByteNTimes(' ', new_indent);
634 } else {
635 try renderExpression(allocator, stream, tree, new_indent, start_col, expr.*, Space.Comma); // ,
636 }
637 }
638 try stream.writeByteNTimes(' ', indent);
639 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
640 } else {
641 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
642 var it = exprs.iterator(0);
643 while (it.next()) |expr| {
644 if (it.peek()) |next_expr| {
645 try renderExpression(allocator, stream, tree, indent, start_col, expr.*, Space.None);
646 const comma = tree.nextToken(expr.*.lastToken());
647 try renderToken(tree, stream, comma, indent, start_col, Space.Space); // ,
648 } else {
649 try renderExpression(allocator, stream, tree, indent, start_col, expr.*, Space.Space);
650 }
506651 }
507 }
508652
509 try stream.writeByteNTimes(' ', indent);
510 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
653 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
654 }
511655 },
512656 }
513657 },
......@@ -517,195 +661,204 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
517661
518662 switch (flow_expr.kind) {
519663 ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| {
520 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;
521 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);
664 if (maybe_label == null and flow_expr.rhs == null) {
665 return renderToken(tree, stream, flow_expr.ltoken, indent, start_col, space); // break
666 }
667
668 try renderToken(tree, stream, flow_expr.ltoken, indent, start_col, Space.Space); // break
522669 if (maybe_label) |label| {
523670 const colon = tree.nextToken(flow_expr.ltoken);
524 try renderToken(tree, stream, colon, indent, Space.None);
671 try renderToken(tree, stream, colon, indent, start_col, Space.None); // :
525672
526 const expr_space = if (flow_expr.rhs != null) Space.Space else space;
527 try renderExpression(allocator, stream, tree, indent, label, expr_space);
673 if (flow_expr.rhs == null) {
674 return renderExpression(allocator, stream, tree, indent, start_col, label, space); // label
675 }
676 try renderExpression(allocator, stream, tree, indent, start_col, label, Space.Space); // label
528677 }
529678 },
530679 ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| {
531 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;
532 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);
680 assert(flow_expr.rhs == null);
681
682 if (maybe_label == null and flow_expr.rhs == null) {
683 return renderToken(tree, stream, flow_expr.ltoken, indent, start_col, space); // continue
684 }
685
686 try renderToken(tree, stream, flow_expr.ltoken, indent, start_col, Space.Space); // continue
533687 if (maybe_label) |label| {
534688 const colon = tree.nextToken(flow_expr.ltoken);
535 try renderToken(tree, stream, colon, indent, Space.None);
689 try renderToken(tree, stream, colon, indent, start_col, Space.None); // :
536690
537 const expr_space = if (flow_expr.rhs != null) Space.Space else space;
538 try renderExpression(allocator, stream, tree, indent, label, space);
691 return renderExpression(allocator, stream, tree, indent, start_col, label, space);
539692 }
540693 },
541694 ast.Node.ControlFlowExpression.Kind.Return => {
542 const kw_space = if (flow_expr.rhs != null) Space.Space else space;
543 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);
695 if (flow_expr.rhs == null) {
696 return renderToken(tree, stream, flow_expr.ltoken, indent, start_col, space);
697 }
698 try renderToken(tree, stream, flow_expr.ltoken, indent, start_col, Space.Space);
544699 },
545700 }
546701
547 if (flow_expr.rhs) |rhs| {
548 try renderExpression(allocator, stream, tree, indent, rhs, space);
549 }
702 return renderExpression(allocator, stream, tree, indent, start_col, ??flow_expr.rhs, space);
550703 },
551704
552705 ast.Node.Id.Payload => {
553706 const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
554707
555 try renderToken(tree, stream, payload.lpipe, indent, Space.None);
556 try renderExpression(allocator, stream, tree, indent, payload.error_symbol, Space.None);
557 try renderToken(tree, stream, payload.rpipe, indent, space);
708 try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None);
709 try renderExpression(allocator, stream, tree, indent, start_col, payload.error_symbol, Space.None);
710 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
558711 },
559712
560713 ast.Node.Id.PointerPayload => {
561714 const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);
562715
563 try renderToken(tree, stream, payload.lpipe, indent, Space.None);
716 try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None);
564717 if (payload.ptr_token) |ptr_token| {
565 try renderToken(tree, stream, ptr_token, indent, Space.None);
718 try renderToken(tree, stream, ptr_token, indent, start_col, Space.None);
566719 }
567 try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None);
568 try renderToken(tree, stream, payload.rpipe, indent, space);
720 try renderExpression(allocator, stream, tree, indent, start_col, payload.value_symbol, Space.None);
721 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
569722 },
570723
571724 ast.Node.Id.PointerIndexPayload => {
572725 const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);
573726
574 try renderToken(tree, stream, payload.lpipe, indent, Space.None);
727 try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None);
575728 if (payload.ptr_token) |ptr_token| {
576 try renderToken(tree, stream, ptr_token, indent, Space.None);
729 try renderToken(tree, stream, ptr_token, indent, start_col, Space.None);
577730 }
578 try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None);
731 try renderExpression(allocator, stream, tree, indent, start_col, payload.value_symbol, Space.None);
579732
580733 if (payload.index_symbol) |index_symbol| {
581734 const comma = tree.nextToken(payload.value_symbol.lastToken());
582735
583 try renderToken(tree, stream, comma, indent, Space.Space);
584 try renderExpression(allocator, stream, tree, indent, index_symbol, Space.None);
736 try renderToken(tree, stream, comma, indent, start_col, Space.Space);
737 try renderExpression(allocator, stream, tree, indent, start_col, index_symbol, Space.None);
585738 }
586739
587 try renderToken(tree, stream, payload.rpipe, indent, space);
740 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
588741 },
589742
590743 ast.Node.Id.GroupedExpression => {
591744 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
592745
593 try renderToken(tree, stream, grouped_expr.lparen, indent, Space.None);
594 try renderExpression(allocator, stream, tree, indent, grouped_expr.expr, Space.None);
595 try renderToken(tree, stream, grouped_expr.rparen, indent, space);
746 try renderToken(tree, stream, grouped_expr.lparen, indent, start_col, Space.None);
747 try renderExpression(allocator, stream, tree, indent, start_col, grouped_expr.expr, Space.None);
748 return renderToken(tree, stream, grouped_expr.rparen, indent, start_col, space);
596749 },
597750
598751 ast.Node.Id.FieldInitializer => {
599752 const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
600753
601 try renderToken(tree, stream, field_init.period_token, indent, Space.None); // .
602 try renderToken(tree, stream, field_init.name_token, indent, Space.Space); // name
603 try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, Space.Space); // =
604 try renderExpression(allocator, stream, tree, indent, field_init.expr, space);
754 try renderToken(tree, stream, field_init.period_token, indent, start_col, Space.None); // .
755 try renderToken(tree, stream, field_init.name_token, indent, start_col, Space.Space); // name
756 try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, start_col, Space.Space); // =
757 return renderExpression(allocator, stream, tree, indent, start_col, field_init.expr, space);
605758 },
606759
607760 ast.Node.Id.IntegerLiteral => {
608761 const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base);
609 try renderToken(tree, stream, integer_literal.token, indent, space);
762 return renderToken(tree, stream, integer_literal.token, indent, start_col, space);
610763 },
611764 ast.Node.Id.FloatLiteral => {
612765 const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base);
613 try renderToken(tree, stream, float_literal.token, indent, space);
766 return renderToken(tree, stream, float_literal.token, indent, start_col, space);
614767 },
615768 ast.Node.Id.StringLiteral => {
616769 const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base);
617 try renderToken(tree, stream, string_literal.token, indent, space);
770 return renderToken(tree, stream, string_literal.token, indent, start_col, space);
618771 },
619772 ast.Node.Id.CharLiteral => {
620773 const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);
621 try renderToken(tree, stream, char_literal.token, indent, space);
774 return renderToken(tree, stream, char_literal.token, indent, start_col, space);
622775 },
623776 ast.Node.Id.BoolLiteral => {
624777 const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);
625 try renderToken(tree, stream, bool_literal.token, indent, space);
778 return renderToken(tree, stream, bool_literal.token, indent, start_col, space);
626779 },
627780 ast.Node.Id.NullLiteral => {
628781 const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base);
629 try renderToken(tree, stream, null_literal.token, indent, space);
782 return renderToken(tree, stream, null_literal.token, indent, start_col, space);
630783 },
631784 ast.Node.Id.ThisLiteral => {
632785 const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base);
633 try renderToken(tree, stream, this_literal.token, indent, space);
786 return renderToken(tree, stream, this_literal.token, indent, start_col, space);
634787 },
635788 ast.Node.Id.Unreachable => {
636789 const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base);
637 try renderToken(tree, stream, unreachable_node.token, indent, space);
790 return renderToken(tree, stream, unreachable_node.token, indent, start_col, space);
638791 },
639792 ast.Node.Id.ErrorType => {
640793 const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base);
641 try renderToken(tree, stream, error_type.token, indent, space);
794 return renderToken(tree, stream, error_type.token, indent, start_col, space);
642795 },
643796 ast.Node.Id.VarType => {
644797 const var_type = @fieldParentPtr(ast.Node.VarType, "base", base);
645 try renderToken(tree, stream, var_type.token, indent, space);
798 return renderToken(tree, stream, var_type.token, indent, start_col, space);
646799 },
647800 ast.Node.Id.ContainerDecl => {
648801 const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
649802
650803 if (container_decl.layout_token) |layout_token| {
651 try renderToken(tree, stream, layout_token, indent, Space.Space);
804 try renderToken(tree, stream, layout_token, indent, start_col, Space.Space);
652805 }
653806
654807 switch (container_decl.init_arg_expr) {
655808 ast.Node.ContainerDecl.InitArg.None => {
656 try renderToken(tree, stream, container_decl.kind_token, indent, Space.Space); // union
809 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.Space); // union
657810 },
658811 ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {
659 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union
812 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
660813
661814 const lparen = tree.nextToken(container_decl.kind_token);
662815 const enum_token = tree.nextToken(lparen);
663816
664 try renderToken(tree, stream, lparen, indent, Space.None); // (
665 try renderToken(tree, stream, enum_token, indent, Space.None); // enum
817 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
818 try renderToken(tree, stream, enum_token, indent, start_col, Space.None); // enum
666819
667820 if (enum_tag_type) |expr| {
668 try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.None); // (
669 try renderExpression(allocator, stream, tree, indent, expr, Space.None);
821 try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.None); // (
822 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
670823
671824 const rparen = tree.nextToken(expr.lastToken());
672 try renderToken(tree, stream, rparen, indent, Space.None); // )
673 try renderToken(tree, stream, tree.nextToken(rparen), indent, Space.Space); // )
825 try renderToken(tree, stream, rparen, indent, start_col, Space.None); // )
826 try renderToken(tree, stream, tree.nextToken(rparen), indent, start_col, Space.Space); // )
674827 } else {
675 try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.Space); // )
828 try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.Space); // )
676829 }
677830 },
678831 ast.Node.ContainerDecl.InitArg.Type => |type_expr| {
679 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union
832 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
680833
681834 const lparen = tree.nextToken(container_decl.kind_token);
682835 const rparen = tree.nextToken(type_expr.lastToken());
683836
684 try renderToken(tree, stream, lparen, indent, Space.None); // (
685 try renderExpression(allocator, stream, tree, indent, type_expr, Space.None);
686 try renderToken(tree, stream, rparen, indent, Space.Space); // )
837 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
838 try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.None);
839 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
687840 },
688841 }
689842
690843 if (container_decl.fields_and_decls.len == 0) {
691 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, Space.None); // {
692 try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // }
844 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, start_col, Space.None); // {
845 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }
693846 } else {
694847 const new_indent = indent + indent_delta;
695 try renderToken(tree, stream, container_decl.lbrace_token, new_indent, Space.Newline); // {
848 try renderToken(tree, stream, container_decl.lbrace_token, new_indent, start_col, Space.Newline); // {
696849
697850 var it = container_decl.fields_and_decls.iterator(0);
698851 while (it.next()) |decl| {
699852 try stream.writeByteNTimes(' ', new_indent);
700 try renderTopLevelDecl(allocator, stream, tree, new_indent, decl.*);
853 try renderTopLevelDecl(allocator, stream, tree, new_indent, start_col, decl.*);
701854
702855 if (it.peek()) |next_decl| {
703 try renderExtraNewline(tree, stream, next_decl.*);
856 try renderExtraNewline(tree, stream, start_col, next_decl.*);
704857 }
705858 }
706859
707860 try stream.writeByteNTimes(' ', indent);
708 try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // }
861 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }
709862 }
710863 },
711864
......@@ -715,10 +868,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
715868 const lbrace = tree.nextToken(err_set_decl.error_token);
716869
717870 if (err_set_decl.decls.len == 0) {
718 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None);
719 try renderToken(tree, stream, lbrace, indent, Space.None);
720 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space);
721 return;
871 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None);
872 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
873 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space);
722874 }
723875
724876 if (err_set_decl.decls.len == 1) blk: {
......@@ -732,15 +884,14 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
732884 break :blk;
733885 }
734886
735 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error
736 try renderToken(tree, stream, lbrace, indent, Space.None); // {
737 try renderExpression(allocator, stream, tree, indent, node, Space.None);
738 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // }
739 return;
887 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
888 try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // {
889 try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None);
890 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
740891 }
741892
742 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error
743 try renderToken(tree, stream, lbrace, indent, Space.Newline); // {
893 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
894 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // {
744895 const new_indent = indent + indent_delta;
745896
746897 var it = err_set_decl.decls.iterator(0);
......@@ -748,24 +899,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
748899 try stream.writeByteNTimes(' ', new_indent);
749900
750901 if (it.peek()) |next_node| {
751 try renderExpression(allocator, stream, tree, new_indent, node.*, Space.None);
752 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, Space.Newline); // ,
902 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None);
903 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, start_col, Space.Newline); // ,
753904
754 try renderExtraNewline(tree, stream, next_node.*);
905 try renderExtraNewline(tree, stream, start_col, next_node.*);
755906 } else {
756 try renderTrailingComma(allocator, stream, tree, new_indent, node.*, Space.Newline);
907 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma);
757908 }
758909 }
759910
760911 try stream.writeByteNTimes(' ', indent);
761 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // }
912 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
762913 },
763914
764915 ast.Node.Id.ErrorTag => {
765916 const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
766917
767 try renderDocComments(tree, stream, tag, indent);
768 try renderToken(tree, stream, tag.name_token, indent, space); // name
918 try renderDocComments(tree, stream, tag, indent, start_col);
919 return renderToken(tree, stream, tag.name_token, indent, start_col, space); // name
769920 },
770921
771922 ast.Node.Id.MultilineStringLiteral => {
......@@ -783,32 +934,32 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
783934 if (!skip_first_indent) {
784935 try stream.writeByteNTimes(' ', indent + indent_delta);
785936 }
786 try renderToken(tree, stream, t, indent, Space.None);
937 try renderToken(tree, stream, t, indent, start_col, Space.None);
787938 skip_first_indent = false;
788939 }
789940 try stream.writeByteNTimes(' ', indent);
790941 },
791942 ast.Node.Id.UndefinedLiteral => {
792943 const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base);
793 try renderToken(tree, stream, undefined_literal.token, indent, space);
944 return renderToken(tree, stream, undefined_literal.token, indent, start_col, space);
794945 },
795946
796947 ast.Node.Id.BuiltinCall => {
797948 const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
798949
799 try renderToken(tree, stream, builtin_call.builtin_token, indent, Space.None); // @name
800 try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, Space.None); // (
950 try renderToken(tree, stream, builtin_call.builtin_token, indent, start_col, Space.None); // @name
951 try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, start_col, Space.None); // (
801952
802953 var it = builtin_call.params.iterator(0);
803954 while (it.next()) |param_node| {
804 try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None);
955 try renderExpression(allocator, stream, tree, indent, start_col, param_node.*, Space.None);
805956
806957 if (it.peek() != null) {
807958 const comma_token = tree.nextToken(param_node.*.lastToken());
808 try renderToken(tree, stream, comma_token, indent, Space.Space); // ,
959 try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // ,
809960 }
810961 }
811 try renderToken(tree, stream, builtin_call.rparen_token, indent, space); // )
962 return renderToken(tree, stream, builtin_call.rparen_token, indent, start_col, space); // )
812963 },
813964
814965 ast.Node.Id.FnProto => {
......@@ -818,68 +969,94 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
818969 const visib_token = tree.tokens.at(visib_token_index);
819970 assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export);
820971
821 try renderToken(tree, stream, visib_token_index, indent, Space.Space); // pub
972 try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub
822973 }
823974
824975 if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {
825 try renderToken(tree, stream, extern_export_inline_token, indent, Space.Space); // extern/export
976 try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export
826977 }
827978
828979 if (fn_proto.lib_name) |lib_name| {
829 try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space);
980 try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space);
830981 }
831982
832983 if (fn_proto.cc_token) |cc_token| {
833 try renderToken(tree, stream, cc_token, indent, Space.Space); // stdcallcc
984 try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc
834985 }
835986
836987 if (fn_proto.async_attr) |async_attr| {
837 try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space);
988 try renderExpression(allocator, stream, tree, indent, start_col, &async_attr.base, Space.Space);
838989 }
839990
840 if (fn_proto.name_token) |name_token| blk: {
841 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.Space); // fn
842 try renderToken(tree, stream, name_token, indent, Space.None); // name
843 try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.None); // (
991 const lparen = if (fn_proto.name_token) |name_token| blk: {
992 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn
993 try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name
994 break :blk tree.nextToken(name_token);
844995 } else blk: {
845 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.None); // fn
846 try renderToken(tree, stream, tree.nextToken(fn_proto.fn_token), indent, Space.None); // (
847 }
848
849 var it = fn_proto.params.iterator(0);
850 while (it.next()) |param_decl_node| {
851 try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*);
852
853 if (it.peek() != null) {
854 const comma = tree.nextToken(param_decl_node.*.lastToken());
855 try renderToken(tree, stream, comma, indent, Space.Space); // ,
856 }
857 }
996 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.None); // fn
997 break :blk tree.nextToken(fn_proto.fn_token);
998 };
858999
8591000 const rparen = tree.prevToken(switch (fn_proto.return_type) {
8601001 ast.Node.FnProto.ReturnType.Explicit => |node| node.firstToken(),
8611002 ast.Node.FnProto.ReturnType.InferErrorSet => |node| tree.prevToken(node.firstToken()),
8621003 });
863 try renderToken(tree, stream, rparen, indent, Space.Space); // )
1004
1005 const src_params_trailing_comma = blk: {
1006 const maybe_comma = tree.prevToken(rparen);
1007 break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma;
1008 };
1009 const src_params_same_line = blk: {
1010 const loc = tree.tokenLocation(tree.tokens.at(lparen).end, rparen);
1011 break :blk loc.line == 0;
1012 };
1013
1014 if (!src_params_trailing_comma and src_params_same_line) {
1015 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
1016
1017 // render all on one line, no trailing comma
1018 var it = fn_proto.params.iterator(0);
1019 while (it.next()) |param_decl_node| {
1020 try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl_node.*, Space.None);
1021
1022 if (it.peek() != null) {
1023 const comma = tree.nextToken(param_decl_node.*.lastToken());
1024 try renderToken(tree, stream, comma, indent, start_col, Space.Space); // ,
1025 }
1026 }
1027 } else {
1028 // one param per line
1029 const new_indent = indent + indent_delta;
1030 try renderToken(tree, stream, lparen, new_indent, start_col, Space.Newline); // (
1031
1032 var it = fn_proto.params.iterator(0);
1033 while (it.next()) |param_decl_node| {
1034 try stream.writeByteNTimes(' ', new_indent);
1035 try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl_node.*, Space.Comma);
1036 }
1037 try stream.writeByteNTimes(' ', indent);
1038 }
1039
1040 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
8641041
8651042 if (fn_proto.align_expr) |align_expr| {
8661043 const align_rparen = tree.nextToken(align_expr.lastToken());
8671044 const align_lparen = tree.prevToken(align_expr.firstToken());
8681045 const align_kw = tree.prevToken(align_lparen);
8691046
870 try renderToken(tree, stream, align_kw, indent, Space.None); // align
871 try renderToken(tree, stream, align_lparen, indent, Space.None); // (
872 try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);
873 try renderToken(tree, stream, align_rparen, indent, Space.Space); // )
1047 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align
1048 try renderToken(tree, stream, align_lparen, indent, start_col, Space.None); // (
1049 try renderExpression(allocator, stream, tree, indent, start_col, align_expr, Space.None);
1050 try renderToken(tree, stream, align_rparen, indent, start_col, Space.Space); // )
8741051 }
8751052
8761053 switch (fn_proto.return_type) {
8771054 ast.Node.FnProto.ReturnType.Explicit => |node| {
878 try renderExpression(allocator, stream, tree, indent, node, space);
1055 return renderExpression(allocator, stream, tree, indent, start_col, node, space);
8791056 },
8801057 ast.Node.FnProto.ReturnType.InferErrorSet => |node| {
881 try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, Space.None); // !
882 try renderExpression(allocator, stream, tree, indent, node, space);
1058 try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, start_col, Space.None); // !
1059 return renderExpression(allocator, stream, tree, indent, start_col, node, space);
8831060 },
8841061 }
8851062 },
......@@ -888,11 +1065,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
8881065 const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base);
8891066
8901067 if (promise_type.result) |result| {
891 try renderToken(tree, stream, promise_type.promise_token, indent, Space.None); // promise
892 try renderToken(tree, stream, result.arrow_token, indent, Space.None); // ->
893 try renderExpression(allocator, stream, tree, indent, result.return_type, space);
1068 try renderToken(tree, stream, promise_type.promise_token, indent, start_col, Space.None); // promise
1069 try renderToken(tree, stream, result.arrow_token, indent, start_col, Space.None); // ->
1070 return renderExpression(allocator, stream, tree, indent, start_col, result.return_type, space);
8941071 } else {
895 try renderToken(tree, stream, promise_type.promise_token, indent, space); // promise
1072 return renderToken(tree, stream, promise_type.promise_token, indent, start_col, space); // promise
8961073 }
8971074 },
8981075
......@@ -901,39 +1078,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
9011078 ast.Node.Id.Switch => {
9021079 const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
9031080
904 try renderToken(tree, stream, switch_node.switch_token, indent, Space.Space); // switch
905 try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, Space.None); // (
1081 try renderToken(tree, stream, switch_node.switch_token, indent, start_col, Space.Space); // switch
1082 try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, start_col, Space.None); // (
9061083
9071084 const rparen = tree.nextToken(switch_node.expr.lastToken());
9081085 const lbrace = tree.nextToken(rparen);
9091086
9101087 if (switch_node.cases.len == 0) {
911 try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None);
912 try renderToken(tree, stream, rparen, indent, Space.Space); // )
913 try renderToken(tree, stream, lbrace, indent, Space.None); // {
914 try renderToken(tree, stream, switch_node.rbrace, indent, space); // }
915 return;
1088 try renderExpression(allocator, stream, tree, indent, start_col, switch_node.expr, Space.None);
1089 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
1090 try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // {
1091 return renderToken(tree, stream, switch_node.rbrace, indent, start_col, space); // }
9161092 }
9171093
918 try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None);
919
920 try renderToken(tree, stream, rparen, indent, Space.Space); // )
921 try renderToken(tree, stream, lbrace, indent, Space.Newline); // {
1094 try renderExpression(allocator, stream, tree, indent, start_col, switch_node.expr, Space.None);
9221095
9231096 const new_indent = indent + indent_delta;
9241097
1098 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
1099 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline); // {
1100
9251101 var it = switch_node.cases.iterator(0);
9261102 while (it.next()) |node| {
9271103 try stream.writeByteNTimes(' ', new_indent);
928 try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Newline);
1104 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma);
9291105
9301106 if (it.peek()) |next_node| {
931 try renderExtraNewline(tree, stream, next_node.*);
1107 try renderExtraNewline(tree, stream, start_col, next_node.*);
9321108 }
9331109 }
9341110
9351111 try stream.writeByteNTimes(' ', indent);
936 try renderToken(tree, stream, switch_node.rbrace, indent, space); // }
1112 return renderToken(tree, stream, switch_node.rbrace, indent, start_col, space); // }
9371113 },
9381114
9391115 ast.Node.Id.SwitchCase => {
......@@ -950,13 +1126,13 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
9501126 var it = switch_case.items.iterator(0);
9511127 while (it.next()) |node| {
9521128 if (it.peek()) |next_node| {
953 try renderExpression(allocator, stream, tree, indent, node.*, Space.None);
1129 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);
9541130
9551131 const comma_token = tree.nextToken(node.*.lastToken());
956 try renderToken(tree, stream, comma_token, indent, Space.Space); // ,
957 try renderExtraNewline(tree, stream, next_node.*);
1132 try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // ,
1133 try renderExtraNewline(tree, stream, start_col, next_node.*);
9581134 } else {
959 try renderExpression(allocator, stream, tree, indent, node.*, Space.Space);
1135 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Space);
9601136 }
9611137 }
9621138 } else {
......@@ -964,84 +1140,97 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
9641140 while (true) {
9651141 const node = ??it.next();
9661142 if (it.peek()) |next_node| {
967 try renderExpression(allocator, stream, tree, indent, node.*, Space.None);
1143 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);
9681144
9691145 const comma_token = tree.nextToken(node.*.lastToken());
970 try renderToken(tree, stream, comma_token, indent, Space.Newline); // ,
971 try renderExtraNewline(tree, stream, next_node.*);
1146 try renderToken(tree, stream, comma_token, indent, start_col, Space.Newline); // ,
1147 try renderExtraNewline(tree, stream, start_col, next_node.*);
9721148 try stream.writeByteNTimes(' ', indent);
9731149 } else {
974 try renderTrailingComma(allocator, stream, tree, indent, node.*, Space.Space);
1150 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Comma);
1151 try stream.writeByteNTimes(' ', indent);
9751152 break;
9761153 }
9771154 }
9781155 }
9791156
980 try renderToken(tree, stream, switch_case.arrow_token, indent, Space.Space); // =>
1157 try renderToken(tree, stream, switch_case.arrow_token, indent, start_col, Space.Space); // =>
9811158
9821159 if (switch_case.payload) |payload| {
983 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
1160 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
9841161 }
9851162
986 try renderTrailingComma(allocator, stream, tree, indent, switch_case.expr, space);
1163 return renderExpression(allocator, stream, tree, indent, start_col, switch_case.expr, space);
9871164 },
9881165 ast.Node.Id.SwitchElse => {
9891166 const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
990 try renderToken(tree, stream, switch_else.token, indent, space);
1167 return renderToken(tree, stream, switch_else.token, indent, start_col, space);
9911168 },
9921169 ast.Node.Id.Else => {
9931170 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
9941171
995 const block_body = switch (else_node.body.id) {
996 ast.Node.Id.Block,
997 ast.Node.Id.If,
998 ast.Node.Id.For,
999 ast.Node.Id.While,
1000 ast.Node.Id.Switch => true,
1001 else => false,
1002 };
1172 const body_is_block = nodeIsBlock(else_node.body);
1173 const same_line = body_is_block or tree.tokensOnSameLine(else_node.else_token, else_node.body.lastToken());
10031174
1004 const after_else_space = if (block_body or else_node.payload != null) Space.Space else Space.Newline;
1005 try renderToken(tree, stream, else_node.else_token, indent, after_else_space);
1175 const after_else_space = if (same_line or else_node.payload != null) Space.Space else Space.Newline;
1176 try renderToken(tree, stream, else_node.else_token, indent, start_col, after_else_space);
10061177
10071178 if (else_node.payload) |payload| {
1008 const payload_space = if (block_body) Space.Space else Space.Newline;
1009 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
1179 const payload_space = if (same_line) Space.Space else Space.Newline;
1180 try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space);
10101181 }
10111182
1012 if (block_body) {
1013 try renderExpression(allocator, stream, tree, indent, else_node.body, space);
1014 } else {
1015 try stream.writeByteNTimes(' ', indent + indent_delta);
1016 try renderExpression(allocator, stream, tree, indent, else_node.body, space);
1183 if (same_line) {
1184 return renderExpression(allocator, stream, tree, indent, start_col, else_node.body, space);
10171185 }
1186
1187 try stream.writeByteNTimes(' ', indent + indent_delta);
1188 start_col.* = indent + indent_delta;
1189 return renderExpression(allocator, stream, tree, indent, start_col, else_node.body, space);
10181190 },
10191191
10201192 ast.Node.Id.While => {
10211193 const while_node = @fieldParentPtr(ast.Node.While, "base", base);
10221194
10231195 if (while_node.label) |label| {
1024 try renderToken(tree, stream, label, indent, Space.None); // label
1025 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :
1196 try renderToken(tree, stream, label, indent, start_col, Space.None); // label
1197 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // :
10261198 }
10271199
10281200 if (while_node.inline_token) |inline_token| {
1029 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline
1201 try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline
10301202 }
10311203
1032 try renderToken(tree, stream, while_node.while_token, indent, Space.Space); // while
1033 try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, Space.None); // (
1034 try renderExpression(allocator, stream, tree, indent, while_node.condition, Space.None);
1204 try renderToken(tree, stream, while_node.while_token, indent, start_col, Space.Space); // while
1205 try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, start_col, Space.None); // (
1206 try renderExpression(allocator, stream, tree, indent, start_col, while_node.condition, Space.None);
1207
1208 const cond_rparen = tree.nextToken(while_node.condition.lastToken());
1209
1210 const body_is_block = nodeIsBlock(while_node.body);
1211
1212 var block_start_space: Space = undefined;
1213 var after_body_space: Space = undefined;
1214
1215 if (body_is_block) {
1216 block_start_space = Space.BlockStart;
1217 after_body_space = if (while_node.@"else" == null) space else Space.SpaceOrOutdent;
1218 } else if (tree.tokensOnSameLine(cond_rparen, while_node.body.lastToken())) {
1219 block_start_space = Space.Space;
1220 after_body_space = if (while_node.@"else" == null) space else Space.Space;
1221 } else {
1222 block_start_space = Space.Newline;
1223 after_body_space = if (while_node.@"else" == null) space else Space.Newline;
1224 }
10351225
10361226 {
1037 const rparen = tree.nextToken(while_node.condition.lastToken());
1038 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null or
1039 while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1040 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1227 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
1228 try renderToken(tree, stream, cond_rparen, indent, start_col, rparen_space); // )
10411229 }
10421230
10431231 if (while_node.payload) |payload| {
1044 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
1232 const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space;
1233 try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space);
10451234 }
10461235
10471236 if (while_node.continue_expr) |continue_expr| {
......@@ -1049,37 +1238,29 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
10491238 const lparen = tree.prevToken(continue_expr.firstToken());
10501239 const colon = tree.prevToken(lparen);
10511240
1052 try renderToken(tree, stream, colon, indent, Space.Space); // :
1053 try renderToken(tree, stream, lparen, indent, Space.None); // (
1241 try renderToken(tree, stream, colon, indent, start_col, Space.Space); // :
1242 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
10541243
1055 try renderExpression(allocator, stream, tree, indent, continue_expr, Space.None);
1244 try renderExpression(allocator, stream, tree, indent, start_col, continue_expr, Space.None);
10561245
1057 const rparen_space = if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1058 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1246 try renderToken(tree, stream, rparen, indent, start_col, block_start_space); // )
10591247 }
10601248
1061 const body_space = blk: {
1062 if (while_node.@"else" != null) {
1063 break :blk if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1064 } else {
1065 break :blk space;
1066 }
1067 };
1068
1069 if (while_node.body.id == ast.Node.Id.Block) {
1070 try renderExpression(allocator, stream, tree, indent, while_node.body, body_space);
1071 } else {
1072 try stream.writeByteNTimes(' ', indent + indent_delta);
1073 try renderExpression(allocator, stream, tree, indent, while_node.body, body_space);
1249 var new_indent = indent;
1250 if (block_start_space == Space.Newline) {
1251 new_indent += indent_delta;
1252 try stream.writeByteNTimes(' ', new_indent);
1253 start_col.* = new_indent;
10741254 }
10751255
1256 try renderExpression(allocator, stream, tree, indent, start_col, while_node.body, after_body_space);
1257
10761258 if (while_node.@"else") |@"else"| {
1077 if (while_node.body.id == ast.Node.Id.Block) {
1078 } else {
1259 if (after_body_space == Space.Newline) {
10791260 try stream.writeByteNTimes(' ', indent);
1261 start_col.* = indent;
10801262 }
1081
1082 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1263 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
10831264 }
10841265 },
10851266
......@@ -1087,26 +1268,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
10871268 const for_node = @fieldParentPtr(ast.Node.For, "base", base);
10881269
10891270 if (for_node.label) |label| {
1090 try renderToken(tree, stream, label, indent, Space.None); // label
1091 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :
1271 try renderToken(tree, stream, label, indent, start_col, Space.None); // label
1272 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // :
10921273 }
10931274
10941275 if (for_node.inline_token) |inline_token| {
1095 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline
1276 try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline
10961277 }
10971278
1098 try renderToken(tree, stream, for_node.for_token, indent, Space.Space); // for
1099 try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, Space.None); // (
1100 try renderExpression(allocator, stream, tree, indent, for_node.array_expr, Space.None);
1279 try renderToken(tree, stream, for_node.for_token, indent, start_col, Space.Space); // for
1280 try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, start_col, Space.None); // (
1281 try renderExpression(allocator, stream, tree, indent, start_col, for_node.array_expr, Space.None);
11011282
11021283 const rparen = tree.nextToken(for_node.array_expr.lastToken());
11031284 const rparen_space = if (for_node.payload != null or
11041285 for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1105 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1286 try renderToken(tree, stream, rparen, indent, start_col, rparen_space); // )
11061287
11071288 if (for_node.payload) |payload| {
11081289 const payload_space = if (for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1109 try renderExpression(allocator, stream, tree, indent, payload, payload_space);
1290 try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space);
11101291 }
11111292
11121293 const body_space = blk: {
......@@ -1121,10 +1302,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
11211302 }
11221303 };
11231304 if (for_node.body.id == ast.Node.Id.Block) {
1124 try renderExpression(allocator, stream, tree, indent, for_node.body, body_space);
1305 try renderExpression(allocator, stream, tree, indent, start_col, for_node.body, body_space);
11251306 } else {
11261307 try stream.writeByteNTimes(' ', indent + indent_delta);
1127 try renderExpression(allocator, stream, tree, indent, for_node.body, body_space);
1308 try renderExpression(allocator, stream, tree, indent, start_col, for_node.body, body_space);
11281309 }
11291310
11301311 if (for_node.@"else") |@"else"| {
......@@ -1132,167 +1313,252 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
11321313 try stream.writeByteNTimes(' ', indent);
11331314 }
11341315
1135 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1316 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
11361317 }
11371318 },
11381319
11391320 ast.Node.Id.If => {
11401321 const if_node = @fieldParentPtr(ast.Node.If, "base", base);
11411322
1142 try renderToken(tree, stream, if_node.if_token, indent, Space.Space);
1143 try renderToken(tree, stream, tree.prevToken(if_node.condition.firstToken()), indent, Space.None);
1323 const lparen = tree.prevToken(if_node.condition.firstToken());
1324 const rparen = tree.nextToken(if_node.condition.lastToken());
11441325
1145 try renderExpression(allocator, stream, tree, indent, if_node.condition, Space.None);
1146 try renderToken(tree, stream, tree.nextToken(if_node.condition.lastToken()), indent, Space.Space);
1326 try renderToken(tree, stream, if_node.if_token, indent, start_col, Space.Space); // if
1327 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
11471328
1148 if (if_node.payload) |payload| {
1149 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
1150 }
1151
1152 switch (if_node.body.id) {
1153 ast.Node.Id.Block,
1154 ast.Node.Id.If,
1155 ast.Node.Id.For,
1156 ast.Node.Id.While,
1157 ast.Node.Id.Switch => {
1158 if (if_node.@"else") |@"else"| {
1159 if (if_node.body.id == ast.Node.Id.Block) {
1160 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space);
1161 } else {
1162 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Newline);
1163 try stream.writeByteNTimes(' ', indent);
1329 try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition
1330
1331 const body_is_block = nodeIsBlock(if_node.body);
1332
1333 if (body_is_block) {
1334 const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space;
1335 try renderToken(tree, stream, rparen, indent, start_col, after_rparen_space); // )
1336
1337 if (if_node.payload) |payload| {
1338 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.BlockStart); // |x|
1339 }
1340
1341 if (if_node.@"else") |@"else"| {
1342 try renderExpression(allocator, stream, tree, indent, start_col, if_node.body, Space.SpaceOrOutdent);
1343 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
1344 } else {
1345 return renderExpression(allocator, stream, tree, indent, start_col, if_node.body, space);
1346 }
1347 }
1348
1349 const src_has_newline = !tree.tokensOnSameLine(rparen, if_node.body.lastToken());
1350
1351 if (src_has_newline) {
1352 const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space;
1353 try renderToken(tree, stream, rparen, indent, start_col, after_rparen_space); // )
1354
1355 if (if_node.payload) |payload| {
1356 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Newline);
1357 }
1358
1359 const new_indent = indent + indent_delta;
1360 try stream.writeByteNTimes(' ', new_indent);
1361
1362 if (if_node.@"else") |@"else"| {
1363 const else_is_block = nodeIsBlock(@"else".body);
1364 try renderExpression(allocator, stream, tree, new_indent, start_col, if_node.body, Space.Newline);
1365 try stream.writeByteNTimes(' ', indent);
1366
1367 if (else_is_block) {
1368 try renderToken(tree, stream, @"else".else_token, indent, start_col, Space.Space); // else
1369
1370 if (@"else".payload) |payload| {
1371 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
11641372 }
11651373
1166 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1374 return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space);
11671375 } else {
1168 try renderExpression(allocator, stream, tree, indent, if_node.body, space);
1169 }
1170 },
1171 else => {
1172 if (if_node.@"else") |@"else"| {
1173 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space);
1174 try renderToken(tree, stream, @"else".else_token, indent, Space.Space);
1376 const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space;
1377 try renderToken(tree, stream, @"else".else_token, indent, start_col, after_else_space); // else
11751378
11761379 if (@"else".payload) |payload| {
1177 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
1380 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Newline);
11781381 }
1382 try stream.writeByteNTimes(' ', new_indent);
11791383
1180 try renderExpression(allocator, stream, tree, indent, @"else".body, space);
1181 } else {
1182 try renderExpression(allocator, stream, tree, indent, if_node.body, space);
1384 return renderExpression(allocator, stream, tree, new_indent, start_col, @"else".body, space);
11831385 }
1184 },
1386 } else {
1387 return renderExpression(allocator, stream, tree, new_indent, start_col, if_node.body, space);
1388 }
1389 }
1390
1391 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
1392
1393 if (if_node.payload) |payload| {
1394 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
1395 }
1396
1397 if (if_node.@"else") |@"else"| {
1398 try renderExpression(allocator, stream, tree, indent, start_col, if_node.body, Space.Space);
1399 try renderToken(tree, stream, @"else".else_token, indent, start_col, Space.Space);
1400
1401 if (@"else".payload) |payload| {
1402 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
1403 }
1404
1405 return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space);
1406 } else {
1407 return renderExpression(allocator, stream, tree, indent, start_col, if_node.body, space);
11851408 }
11861409 },
11871410
11881411 ast.Node.Id.Asm => {
11891412 const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
11901413
1191 try renderToken(tree, stream, asm_node.asm_token, indent, Space.Space); // asm
1414 try renderToken(tree, stream, asm_node.asm_token, indent, start_col, Space.Space); // asm
11921415
11931416 if (asm_node.volatile_token) |volatile_token| {
1194 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile
1195 try renderToken(tree, stream, tree.nextToken(volatile_token), indent, Space.None); // (
1417 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile
1418 try renderToken(tree, stream, tree.nextToken(volatile_token), indent, start_col, Space.None); // (
11961419 } else {
1197 try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // (
1420 try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, start_col, Space.None); // (
1421 }
1422
1423 if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
1424 try renderExpression(allocator, stream, tree, indent, start_col, asm_node.template, Space.None);
1425 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
11981426 }
11991427
1200 try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline);
1428 try renderExpression(allocator, stream, tree, indent, start_col, asm_node.template, Space.Newline);
1429
12011430 const indent_once = indent + indent_delta;
12021431 try stream.writeByteNTimes(' ', indent_once);
1203 try stream.print(": ");
1432
1433 const colon1 = tree.nextToken(asm_node.template.lastToken());
12041434 const indent_extra = indent_once + 2;
12051435
1206 {
1436 const colon2 = if (asm_node.outputs.len == 0) blk: {
1437 try renderToken(tree, stream, colon1, indent, start_col, Space.Newline); // :
1438 try stream.writeByteNTimes(' ', indent_once);
1439
1440 break :blk tree.nextToken(colon1);
1441 } else blk: {
1442 try renderToken(tree, stream, colon1, indent, start_col, Space.Space); // :
1443
12071444 var it = asm_node.outputs.iterator(0);
1208 while (it.next()) |asm_output| {
1445 while (true) {
1446 const asm_output = ??it.next();
12091447 const node = &(asm_output.*).base;
1210 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
12111448
12121449 if (it.peek()) |next_asm_output| {
1450 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.None);
12131451 const next_node = &(next_asm_output.*).base;
12141452
12151453 const comma = tree.prevToken(next_asm_output.*.firstToken());
1216 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,
1217 try renderExtraNewline(tree, stream, next_node);
1454 try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // ,
1455 try renderExtraNewline(tree, stream, start_col, next_node);
12181456
12191457 try stream.writeByteNTimes(' ', indent_extra);
1458 } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
1459 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline);
1460 try stream.writeByteNTimes(' ', indent);
1461 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
1462 } else {
1463 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline);
1464 try stream.writeByteNTimes(' ', indent_once);
1465 const comma_or_colon = tree.nextToken(node.lastToken());
1466 break :blk switch (tree.tokens.at(comma_or_colon).id) {
1467 Token.Id.Comma => tree.nextToken(comma_or_colon),
1468 else => comma_or_colon,
1469 };
12201470 }
12211471 }
1222 }
1472 };
12231473
1224 try stream.write("\n");
1225 try stream.writeByteNTimes(' ', indent_once);
1226 try stream.write(": ");
1474 const colon3 = if (asm_node.inputs.len == 0) blk: {
1475 try renderToken(tree, stream, colon2, indent, start_col, Space.Newline); // :
1476 try stream.writeByteNTimes(' ', indent_once);
1477
1478 break :blk tree.nextToken(colon2);
1479 } else blk: {
1480 try renderToken(tree, stream, colon2, indent, start_col, Space.Space); // :
12271481
1228 {
12291482 var it = asm_node.inputs.iterator(0);
1230 while (it.next()) |asm_input| {
1483 while (true) {
1484 const asm_input = ??it.next();
12311485 const node = &(asm_input.*).base;
1232 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
12331486
12341487 if (it.peek()) |next_asm_input| {
1488 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.None);
12351489 const next_node = &(next_asm_input.*).base;
12361490
12371491 const comma = tree.prevToken(next_asm_input.*.firstToken());
1238 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,
1239 try renderExtraNewline(tree, stream, next_node);
1492 try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // ,
1493 try renderExtraNewline(tree, stream, start_col, next_node);
12401494
12411495 try stream.writeByteNTimes(' ', indent_extra);
1496 } else if (asm_node.clobbers.len == 0) {
1497 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline);
1498 try stream.writeByteNTimes(' ', indent);
1499 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); // )
1500 } else {
1501 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline);
1502 try stream.writeByteNTimes(' ', indent_once);
1503 const comma_or_colon = tree.nextToken(node.lastToken());
1504 break :blk switch (tree.tokens.at(comma_or_colon).id) {
1505 Token.Id.Comma => tree.nextToken(comma_or_colon),
1506 else => comma_or_colon,
1507 };
12421508 }
12431509 }
1244 }
1510 };
12451511
1246 try stream.write("\n");
1247 try stream.writeByteNTimes(' ', indent_once);
1248 try stream.write(": ");
1512 try renderToken(tree, stream, colon3, indent, start_col, Space.Space); // :
12491513
1250 {
1251 var it = asm_node.clobbers.iterator(0);
1252 while (it.next()) |node| {
1253 try renderExpression(allocator, stream, tree, indent_once, node.*, Space.None);
1514 var it = asm_node.clobbers.iterator(0);
1515 while (true) {
1516 const clobber_token = ??it.next();
12541517
1255 if (it.peek() != null) {
1256 try stream.write(", ");
1257 }
1518 if (it.peek() == null) {
1519 try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.Newline);
1520 try stream.writeByteNTimes(' ', indent);
1521 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
1522 } else {
1523 try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.None);
1524 const comma = tree.nextToken(clobber_token.*);
1525 try renderToken(tree, stream, comma, indent_once, start_col, Space.Space); // ,
12581526 }
12591527 }
1260
1261 try renderToken(tree, stream, asm_node.rparen, indent, space);
12621528 },
12631529
12641530 ast.Node.Id.AsmInput => {
12651531 const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base);
12661532
12671533 try stream.write("[");
1268 try renderExpression(allocator, stream, tree, indent, asm_input.symbolic_name, Space.None);
1534 try renderExpression(allocator, stream, tree, indent, start_col, asm_input.symbolic_name, Space.None);
12691535 try stream.write("] ");
1270 try renderExpression(allocator, stream, tree, indent, asm_input.constraint, Space.None);
1536 try renderExpression(allocator, stream, tree, indent, start_col, asm_input.constraint, Space.None);
12711537 try stream.write(" (");
1272 try renderExpression(allocator, stream, tree, indent, asm_input.expr, Space.None);
1273 try renderToken(tree, stream, asm_input.lastToken(), indent, space); // )
1538 try renderExpression(allocator, stream, tree, indent, start_col, asm_input.expr, Space.None);
1539 return renderToken(tree, stream, asm_input.lastToken(), indent, start_col, space); // )
12741540 },
12751541
12761542 ast.Node.Id.AsmOutput => {
12771543 const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base);
12781544
12791545 try stream.write("[");
1280 try renderExpression(allocator, stream, tree, indent, asm_output.symbolic_name, Space.None);
1546 try renderExpression(allocator, stream, tree, indent, start_col, asm_output.symbolic_name, Space.None);
12811547 try stream.write("] ");
1282 try renderExpression(allocator, stream, tree, indent, asm_output.constraint, Space.None);
1548 try renderExpression(allocator, stream, tree, indent, start_col, asm_output.constraint, Space.None);
12831549 try stream.write(" (");
12841550
12851551 switch (asm_output.kind) {
12861552 ast.Node.AsmOutput.Kind.Variable => |variable_name| {
1287 try renderExpression(allocator, stream, tree, indent, &variable_name.base, Space.None);
1553 try renderExpression(allocator, stream, tree, indent, start_col, &variable_name.base, Space.None);
12881554 },
12891555 ast.Node.AsmOutput.Kind.Return => |return_type| {
12901556 try stream.write("-> ");
1291 try renderExpression(allocator, stream, tree, indent, return_type, Space.None);
1557 try renderExpression(allocator, stream, tree, indent, start_col, return_type, Space.None);
12921558 },
12931559 }
12941560
1295 try renderToken(tree, stream, asm_output.lastToken(), indent, space); // )
1561 return renderToken(tree, stream, asm_output.lastToken(), indent, start_col, space); // )
12961562 },
12971563
12981564 ast.Node.Id.StructField,
......@@ -1306,92 +1572,92 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
13061572 }
13071573}
13081574
1309fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize,
1310 var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void
1575fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize,
1576 var_decl: &ast.Node.VarDecl,) (@typeOf(stream).Child.Error || Error)!void
13111577{
13121578 if (var_decl.visib_token) |visib_token| {
1313 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub
1579 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
13141580 }
13151581
13161582 if (var_decl.extern_export_token) |extern_export_token| {
1317 try renderToken(tree, stream, extern_export_token, indent, Space.Space); // extern
1583 try renderToken(tree, stream, extern_export_token, indent, start_col, Space.Space); // extern
13181584
13191585 if (var_decl.lib_name) |lib_name| {
1320 try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space); // "lib"
1586 try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); // "lib"
13211587 }
13221588 }
13231589
13241590 if (var_decl.comptime_token) |comptime_token| {
1325 try renderToken(tree, stream, comptime_token, indent, Space.Space); // comptime
1591 try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime
13261592 }
13271593
1328 try renderToken(tree, stream, var_decl.mut_token, indent, Space.Space); // var
1594 try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var
13291595
13301596 const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or
13311597 var_decl.init_node != null)) Space.Space else Space.None;
1332 try renderToken(tree, stream, var_decl.name_token, indent, name_space);
1598 try renderToken(tree, stream, var_decl.name_token, indent, start_col, name_space);
13331599
13341600 if (var_decl.type_node) |type_node| {
1335 try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, Space.Space);
1601 try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, start_col, Space.Space);
13361602 const s = if (var_decl.align_node != null or var_decl.init_node != null) Space.Space else Space.None;
1337 try renderExpression(allocator, stream, tree, indent, type_node, s);
1603 try renderExpression(allocator, stream, tree, indent, start_col, type_node, s);
13381604 }
13391605
13401606 if (var_decl.align_node) |align_node| {
13411607 const lparen = tree.prevToken(align_node.firstToken());
13421608 const align_kw = tree.prevToken(lparen);
13431609 const rparen = tree.nextToken(align_node.lastToken());
1344 try renderToken(tree, stream, align_kw, indent, Space.None); // align
1345 try renderToken(tree, stream, lparen, indent, Space.None); // (
1346 try renderExpression(allocator, stream, tree, indent, align_node, Space.None);
1610 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align
1611 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
1612 try renderExpression(allocator, stream, tree, indent, start_col, align_node, Space.None);
13471613 const s = if (var_decl.init_node != null) Space.Space else Space.None;
1348 try renderToken(tree, stream, rparen, indent, s); // )
1614 try renderToken(tree, stream, rparen, indent, start_col, s); // )
13491615 }
13501616
13511617 if (var_decl.init_node) |init_node| {
13521618 const s = if (init_node.id == ast.Node.Id.MultilineStringLiteral) Space.None else Space.Space;
1353 try renderToken(tree, stream, var_decl.eq_token, indent, s); // =
1354 try renderExpression(allocator, stream, tree, indent, init_node, Space.None);
1619 try renderToken(tree, stream, var_decl.eq_token, indent, start_col, s); // =
1620 try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None);
13551621 }
13561622
1357 try renderToken(tree, stream, var_decl.semicolon_token, indent, Space.Newline);
1623 try renderToken(tree, stream, var_decl.semicolon_token, indent, start_col, Space.Newline);
13581624}
13591625
1360fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {
1626fn 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 {
13611627 const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);
13621628
13631629 if (param_decl.comptime_token) |comptime_token| {
1364 try renderToken(tree, stream, comptime_token, indent, Space.Space);
1630 try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space);
13651631 }
13661632 if (param_decl.noalias_token) |noalias_token| {
1367 try renderToken(tree, stream, noalias_token, indent, Space.Space);
1633 try renderToken(tree, stream, noalias_token, indent, start_col, Space.Space);
13681634 }
13691635 if (param_decl.name_token) |name_token| {
1370 try renderToken(tree, stream, name_token, indent, Space.None);
1371 try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.Space); // :
1636 try renderToken(tree, stream, name_token, indent, start_col, Space.None);
1637 try renderToken(tree, stream, tree.nextToken(name_token), indent, start_col, Space.Space); // :
13721638 }
13731639 if (param_decl.var_args_token) |var_args_token| {
1374 try renderToken(tree, stream, var_args_token, indent, Space.None);
1640 try renderToken(tree, stream, var_args_token, indent, start_col, space);
13751641 } else {
1376 try renderExpression(allocator, stream, tree, indent, param_decl.type_node, Space.None);
1642 try renderExpression(allocator, stream, tree, indent, start_col, param_decl.type_node, space);
13771643 }
13781644}
13791645
1380fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {
1646fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, base: &ast.Node,) (@typeOf(stream).Child.Error || Error)!void {
13811647 switch (base.id) {
13821648 ast.Node.Id.VarDecl => {
13831649 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
1384 try renderVarDecl(allocator, stream, tree, indent, var_decl);
1650 try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl);
13851651 },
13861652 else => {
13871653 if (base.requireSemiColon()) {
1388 try renderExpression(allocator, stream, tree, indent, base, Space.None);
1654 try renderExpression(allocator, stream, tree, indent, start_col, base, Space.None);
13891655
13901656 const semicolon_index = tree.nextToken(base.lastToken());
13911657 assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon);
1392 try renderToken(tree, stream, semicolon_index, indent, Space.Newline);
1658 try renderToken(tree, stream, semicolon_index, indent, start_col, Space.Newline);
13931659 } else {
1394 try renderExpression(allocator, stream, tree, indent, base, Space.Newline);
1660 try renderExpression(allocator, stream, tree, indent, start_col, base, Space.Newline);
13951661 }
13961662 },
13971663 }
......@@ -1400,32 +1666,95 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde
14001666const Space = enum {
14011667 None,
14021668 Newline,
1669 Comma,
14031670 Space,
1671 SpaceOrOutdent,
14041672 NoNewline,
1405 NoIndent,
14061673 NoComment,
1674 BlockStart,
14071675};
14081676
1409fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void {
1677fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, start_col: &usize, space: Space) (@typeOf(stream).Child.Error || Error)!void {
1678 if (space == Space.BlockStart) {
1679 if (start_col.* < indent + indent_delta)
1680 return renderToken(tree, stream, token_index, indent, start_col, Space.Space);
1681 try renderToken(tree, stream, token_index, indent, start_col, Space.Newline);
1682 try stream.writeByteNTimes(' ', indent);
1683 start_col.* = indent;
1684 return;
1685 }
1686
14101687 var token = tree.tokens.at(token_index);
1411 try stream.write(tree.tokenSlicePtr(token));
1688 try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " "));
14121689
1413 if (space == Space.NoComment) return;
1690 if (space == Space.NoComment)
1691 return;
14141692
14151693 var next_token = tree.tokens.at(token_index + 1);
1416 if (next_token.id != Token.Id.LineComment) {
1694
1695 if (space == Space.Comma) switch (next_token.id) {
1696 Token.Id.Comma => return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline),
1697 Token.Id.LineComment => {
1698 try stream.write(", ");
1699 return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline);
1700 },
1701 else => {
1702 if (tree.tokens.at(token_index + 2).id == Token.Id.MultilineStringLiteralLine) {
1703 try stream.write(",");
1704 return;
1705 } else {
1706 try stream.write(",\n");
1707 start_col.* = 0;
1708 return;
1709 }
1710 },
1711 };
1712
1713 // Skip over same line doc comments
1714 var offset: usize = 1;
1715 if (next_token.id == Token.Id.DocComment) {
1716 const loc = tree.tokenLocationPtr(token.end, next_token);
1717 if (loc.line == 0) {
1718 offset += 1;
1719 next_token = tree.tokens.at(token_index + offset);
1720 }
1721 }
1722
1723 if (next_token.id != Token.Id.LineComment) blk: {
14171724 switch (space) {
1418 Space.None, Space.NoNewline, Space.NoIndent => return,
1419 Space.Newline => return stream.write("\n"),
1420 Space.Space => return stream.writeByte(' '),
1421 Space.NoComment => unreachable,
1725 Space.None, Space.NoNewline => return,
1726 Space.Newline => {
1727 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
1728 return;
1729 } else {
1730 try stream.write("\n");
1731 start_col.* = 0;
1732 return;
1733 }
1734 },
1735 Space.Space, Space.SpaceOrOutdent => {
1736 try stream.writeByte(' ');
1737 return;
1738 },
1739 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
1740 }
1741 }
1742
1743 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;
1744 if (comment_is_empty) {
1745 switch (space) {
1746 Space.Newline => {
1747 try stream.writeByte('\n');
1748 start_col.* = 0;
1749 return;
1750 },
1751 else => {},
14221752 }
14231753 }
14241754
14251755 var loc = tree.tokenLocationPtr(token.end, next_token);
1426 var offset: usize = 1;
14271756 if (loc.line == 0) {
1428 try stream.print(" {}", tree.tokenSlicePtr(next_token));
1757 try stream.print(" {}", mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));
14291758 offset = 2;
14301759 token = next_token;
14311760 next_token = tree.tokens.at(token_index + offset);
......@@ -1439,10 +1768,24 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
14391768 else => indent + indent_delta,
14401769 };
14411770 try stream.writeByteNTimes(' ', next_line_indent);
1771 start_col.* = next_line_indent;
1772 },
1773 Space.SpaceOrOutdent => {
1774 try stream.writeByte('\n');
1775 try stream.writeByteNTimes(' ', indent);
1776 start_col.* = indent;
1777 },
1778 Space.Newline => {
1779 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
1780 return;
1781 } else {
1782 try stream.write("\n");
1783 start_col.* = 0;
1784 return;
1785 }
14421786 },
1443 Space.Newline, Space.NoIndent => try stream.write("\n"),
14441787 Space.NoNewline => {},
1445 Space.NoComment => unreachable,
1788 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
14461789 }
14471790 return;
14481791 }
......@@ -1454,26 +1797,40 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
14541797 const newline_count = if (loc.line == 1) u8(1) else u8(2);
14551798 try stream.writeByteNTimes('\n', newline_count);
14561799 try stream.writeByteNTimes(' ', indent);
1457 try stream.write(tree.tokenSlicePtr(next_token));
1800 try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));
14581801
14591802 offset += 1;
14601803 token = next_token;
14611804 next_token = tree.tokens.at(token_index + offset);
14621805 if (next_token.id != Token.Id.LineComment) {
14631806 switch (space) {
1464 Space.Newline, Space.NoIndent => try stream.writeByte('\n'),
1807 Space.Newline => {
1808 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
1809 return;
1810 } else {
1811 try stream.write("\n");
1812 start_col.* = 0;
1813 return;
1814 }
1815 },
14651816 Space.None, Space.Space => {
14661817 try stream.writeByte('\n');
14671818
14681819 const after_comment_token = tree.tokens.at(token_index + offset);
14691820 const next_line_indent = switch (after_comment_token.id) {
1470 Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent,
1821 Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent - indent_delta,
14711822 else => indent,
14721823 };
14731824 try stream.writeByteNTimes(' ', next_line_indent);
1825 start_col.* = next_line_indent;
1826 },
1827 Space.SpaceOrOutdent => {
1828 try stream.writeByte('\n');
1829 try stream.writeByteNTimes(' ', indent);
1830 start_col.* = indent;
14741831 },
14751832 Space.NoNewline => {},
1476 Space.NoComment => unreachable,
1833 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
14771834 }
14781835 return;
14791836 }
......@@ -1481,33 +1838,30 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
14811838 }
14821839}
14831840
1484fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@typeOf(stream).Child.Error || Error)!void {
1841fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize, start_col: &usize,) (@typeOf(stream).Child.Error || Error)!void {
14851842 const comment = node.doc_comments ?? return;
14861843 var it = comment.lines.iterator(0);
1844 const first_token = node.firstToken();
14871845 while (it.next()) |line_token_index| {
1488 try renderToken(tree, stream, line_token_index.*, indent, Space.Newline);
1489 try stream.writeByteNTimes(' ', indent);
1846 if (line_token_index.* < first_token) {
1847 try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.Newline);
1848 try stream.writeByteNTimes(' ', indent);
1849 } else {
1850 try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.NoComment);
1851 try stream.write("\n");
1852 try stream.writeByteNTimes(' ', indent);
1853 }
14901854 }
14911855}
14921856
1493fn renderTrailingComma(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node,
1494 space: Space) (@typeOf(stream).Child.Error || Error)!void
1495{
1496 const end_token = base.lastToken() + 1;
1497 switch (tree.tokens.at(end_token).id) {
1498 Token.Id.Comma => {
1499 try renderExpression(allocator, stream, tree, indent, base, Space.None);
1500 try renderToken(tree, stream, end_token, indent, space); // ,
1501 },
1502 Token.Id.LineComment => {
1503 try renderExpression(allocator, stream, tree, indent, base, Space.NoComment);
1504 try stream.write(", ");
1505 try renderToken(tree, stream, end_token, indent, space);
1506 },
1507 else => {
1508 try renderExpression(allocator, stream, tree, indent, base, Space.None);
1509 try stream.write(",\n");
1510 assert(space == Space.Newline);
1511 },
1512 }
1857fn nodeIsBlock(base: &const ast.Node) bool {
1858 return switch (base.id) {
1859 ast.Node.Id.Block,
1860 ast.Node.Id.If,
1861 ast.Node.Id.For,
1862 ast.Node.Id.While,
1863 ast.Node.Id.Switch,
1864 => true,
1865 else => false,
1866 };
15131867}
std/zig/tokenizer.zig-12
......@@ -217,7 +217,6 @@ pub const Tokenizer = struct {
217217 StringLiteral,
218218 StringLiteralBackslash,
219219 MultilineStringLiteralLine,
220 MultilineStringLiteralLineBackslash,
221220 CharLiteral,
222221 CharLiteralBackslash,
223222 CharLiteralEscape1,
......@@ -655,9 +654,6 @@ pub const Tokenizer = struct {
655654 },
656655
657656 State.MultilineStringLiteralLine => switch (c) {
658 '\\' => {
659 state = State.MultilineStringLiteralLineBackslash;
660 },
661657 '\n' => {
662658 self.index += 1;
663659 break;
......@@ -665,13 +661,6 @@ pub const Tokenizer = struct {
665661 else => self.checkLiteralCharacter(),
666662 },
667663
668 State.MultilineStringLiteralLineBackslash => switch (c) {
669 '\n' => break, // Look for this error later.
670 else => {
671 state = State.MultilineStringLiteralLine;
672 },
673 },
674
675664 State.Bang => switch (c) {
676665 '=' => {
677666 result.id = Token.Id.BangEqual;
......@@ -1010,7 +999,6 @@ pub const Tokenizer = struct {
1010999 State.FloatExponentUnsignedHex,
10111000 State.SawAtSign,
10121001 State.Backslash,
1013 State.MultilineStringLiteralLineBackslash,
10141002 State.CharLiteral,
10151003 State.CharLiteralBackslash,
10161004 State.CharLiteralEscape1,